#!/usr/bin/php
<?php

	// to add extra ip:
	// add an [oldip] group to ini file (like in nodeip)

#	$extra['dns']='ns1.xxx';
#	$extra['mx']='mail.xxx';

	$dns_recursors=array('192.168.222.1','8.8.8.8','8.8.4.4','1.1.1.1');

	$old_subnet='79.172.192.';
	$new_subnet='77.111.114.';

#####################################################

	$extra['extra']=1;

	$tldnslist=array();

	$teststring=array(
				'ns' => array( 0 =>'--', 1=>'NS', 2=>'ns', 3=>'??', 4=>'!!' ),
				'a' => array( 0 =>'-', 1=>'A', 2=>'a', 3=>'?', 4=>'!' ),
				'mx' => array( 0 =>'--', 1=>'MX', 2=>'mx', 3=>'??', 4=>'!!' ),
			);

	global $DNS_ERR;

	global $MYCONN;

	function DBconnect($maxretry=3)
	{
		global $MYCONN;

		$myini=parse_ini_file("/chroot/admin/etc/mysql/debian.cnf",TRUE);

#		$MYCONN=new mysqli('127.0.0.1', $myini['client']['user'], $myini['client']['password'], 'sys_admin', '3307' );
		$MYCONN=new mysqli('localhost', $myini['client']['user'], $myini['client']['password'], 'sys_admin', NULL, '/chroot/admin/run/mysqld/mysqld.sock');
		$MYCONN->set_charset('utf8');
	}

	function DBquery($query, $resultmode = MYSQLI_STORE_RESULT)
	{
		global $MYCONN;
		$res=$MYCONN->query($query, $resultmode);
		if ($MYCONN->errno)
		{
			echo("DB error:".$MYCONN->error);
		}
		return $res;
	}

	function get_local_data($extra)
	{
		global $old_subnet;
		global $new_subnet;

#		$ini=parse_ini_file(dirname(__FILE__)."/../config/sys-admin.conf",true);
		$ini=parse_ini_file("/etc/sys-admin/config/sys-admin.conf",true);
		$local=array();

		if (array_key_exists('dns', $extra))
		{
			$local['dns']=$extra['dns'];
		}
		else
		{
			$local['dns']="ns1.".$ini['global']['domain'];
		}

		if (array_key_exists('mx', $extra))
		{
			$local['mx']=$extra['mx'];
		}
		else
		{
			$local['mx']="mail.".$ini['global']['domain'];
		}

		$local['ips']=$ini['nodeip'];

		$local['oldips']=array();
		foreach($local['ips'] as $ip_addr)
		{
			$local['oldips'][]=str_replace($new_subnet, $old_subnet, $ip_addr);
		}

		if (array_key_exists('oldip', $ini))
		{
			foreach($ini['oldip'] as $extra_ip)
			{
				$local['ips'][]=$extra_ip;
			}
		}
		return $local;
	}

	function in_array_array($whats=array(), $where=array())
	{
		foreach ($whats as $what)
		{
			if(in_array($what, $where))
			{
				return true;
			}
		}
		return false;
	}

	function dnsbq($what, $type, $resolver)
	{
		try {
			$result = $resolver->query($what, $type);
		} catch(Net_DNS2_Exception $e) {
			echo "DNS2::query($what/$type) failed: ", $e->getMessage(), "\n";
			die(3);
		}
		return $result;
	}

	function dnsq($what, $type, $ans, $val, $resolver)
	{
		global $DNS_ERR;
		$DNS_ERR=0;

		$ret=array();
		try {
			$result = $resolver->query($what, $type);
		} catch(Net_DNS2_Exception $e) {
			//echo "DNS2::query($what/$type) failed: ", $e->getMessage(), "\n";
			$result = $e->getCode();
			fwrite(STDERR, "[$result][$type][$what]");
			fwrite(STDERR, ' @'.implode('|',$resolver->nameservers). PHP_EOL);
			$DNS_ERR=$result;
			return false;
		}

		if (is_object($result) && property_exists($result, $ans))
		{
			foreach ($result->$ans as $obj)
			{
				if(is_object($obj) && property_exists($obj, $val))
				{
					$ret[]=$obj->$val;
				}
			}
		}
		return $ret;
	}

	function get_ips($hosts, $resolver)
	{
		$ret=array();
		foreach($hosts as $host)
		{
			$ipa=dnsq($host, 'A', 'answer', 'address', $resolver);
			if ($ipa)
			{
				$ret[]=$ipa[0];
			}
		}
		return $ret;
	}

#######################################################################################

	$local=get_local_data($extra);

	set_include_path(ini_get('include_path').':/etc/sys-admin/include/netdns2');
	require('Net/DNS2.php');

	// check local dns A record
	shuffle($dns_recursors);
	$r=new Net_DNS2_Resolver(array('nameservers' => $dns_recursors));

	$my_dns_ips=dnsq($local['dns'], 'A', 'answer', 'address', $r);

	if ($my_dns_ips)
	{
		if (count($my_dns_ips)>0)
		{
			if (!in_array_array($local['ips'], $my_dns_ips))
			{
				echo "ERROR: Local DNS is not yet in the new subnet: ";
				echo implode("|",$my_dns_ips)."\n\n";
			}
			else
			{
				echo "OK Local DNS IP: ";
				echo implode("|",$my_dns_ips)."\n\n";
			}
		}
	}

	echo "*** domains ***\n";

	DBconnect();

	$dres=DBquery("SELECT	`domain`.`name` AS `name`,
				`domain`.`id` AS `id`,
				`domain`.`dns` AS `dns`,
				`client`.`name` AS `clientname`,
				`client`.`node` AS `clientnode`,
				IF((`client`.`active`=1), `domain`.`ip`, NULL) AS `ip`,
				IF((`client`.`active`=1), `domain`.`mx`, NULL) AS `mx`
				FROM `domain`
				LEFT JOIN `client` ON `domain`.`clientid`=`client`.`id`
				WHERE `domain`.`active`=1
				AND `domain`.`name` NOT LIKE '%.null'
				AND `domain`.`name` NOT LIKE '%.vacation'
				ORDER BY `client`.`node`,`client`.`name`,`domain`.`name`
				;");
//	$dres=DBquery("SELECT `name`,`id` FROM `domain` WHERE `active`=0 AND `name`!='null.null';");
//	$dres=DBquery("SELECT `name`,`id` FROM `domain` WHERE `name`!='null.null';");

	while($drow=$dres->fetch_assoc())
	{

		shuffle($dns_recursors);
		$r=new Net_DNS2_Resolver(array('nameservers' => $dns_recursors));

		$test['exist']=1;
		$test['error']=1;
		$test['ns']=1;
		$test['a']=1;
		$test['mx']=1;
		$test['summary']=0;

		$clientname=$drow['clientname'];
		$clientnode=$drow['clientnode'];

		$domainid=$drow['id'];
		$domain=$drow['name'];
		$dom_parts=explode('.',$domain,2);
		$tld=end($dom_parts);

		$d_dns=$drow['dns'];
		$d_ip=$drow['ip'];
		$d_mx=$drow['mx'];

		//get NIC dns servers
//		$dns_nic=dns_get_targets(dns_get_record($tld, DNS_NS, $dns_recursors));

		if (array_key_exists($tld,$tldnslist))
		{
			$dns_nic_ips=$tldnslist[$tld];
		}
		else
		{
			$dns_nic=dnsq($tld, 'NS', 'answer', 'nsdname', $r);
			if ($dns_nic)
			{
				$dns_nic_ips=get_ips($dns_nic, $r);
				if ($dns_nic_ips)
				{
					$tldnslist[$tld]=$dns_nic_ips;
				}
			}
		}

		shuffle($dns_nic_ips);
		$a_r=new Net_DNS2_Resolver(array('nameservers' => $dns_nic_ips));

		// get domain auth NS servers
		$dns_auth=dnsq($domain, 'NS', 'authority', 'nsdname', $a_r);
		//$dns_auth_ips=get_ips($dns_auth, $r);

		if ($dns_auth && count($dns_auth)>0)
		{
			//domain ok

			// NS match
			if (!in_array($local['dns'], $dns_auth))
			{
				foreach ($dns_auth as $dom_ns)
				{
					$ns_ips=dnsq($dom_ns, 'A', 'answer', 'address', $r);

					if ($ns_ips)
					{
						if (count($ns_ips)>0)
						{
							if (!in_array_array($local['ips'], $ns_ips))
							{
								$test['ns']=0;
								if (in_array_array($local['oldips'], $ns_ips))
								{
									$test['ns']=4;
								}
							}
							else
							{
								$test['ns']=1;
								break;
							}
						}
						else
						{
							$test['ns']=3; // this must be an ns error
						}
					}
					else
					{
						$test['error']=0; //ns error
						$test['ns']=3; // ns error
					}
				}
			}


			// A match
			$a_ips=dnsq($domain, 'A', 'answer', 'address', $r);

			if ($a_ips)
			{
				if (count($a_ips)>0)
				{
					// has A record
					if (!in_array_array($local['ips'], $a_ips))
					{
						$test['a']=0;
						if (in_array_array($local['oldips'], $a_ips))
						{
							$test['a']=4;
						}
					}
				}
				else
				{
					$test['a']=3; // this must be an ns error
				}
			}
			else
			{
				$test['a']=3; // ns error
			}

			// WWW A match (only if A doesn't)
			if ($test['a']==0 || $test['a']==3)
			{
				$www_ips=dnsq('www.'.$domain, 'A', 'answer', 'address', $r);
				if ($www_ips && count($www_ips)>0)
				{
					// WWW has A record
					if (in_array_array($local['ips'], $www_ips))
					{
						$test['a']=1;
					}
					elseif (in_array_array($local['oldips'], $www_ips))
					{
						$test['a']=4;
					}

				}
			}

			// MX match
			$mxs=dnsq($domain, 'MX', 'answer', 'exchange', $r);
			if ($mxs)
			{
				if (count($mxs)>0)
				{
					if (!in_array($local['mx'], $mxs))
					{
						foreach ($mxs as $dom_mx)
						{
							$mx_ips=dnsq($dom_mx, 'A', 'answer', 'address', $r);

							if ($mx_ips)
							{
								if (count($mx_ips)>0)
								{
									if (!in_array_array($local['ips'], $mx_ips))
									{
										$test['mx']=0;
										if (in_array_array($local['oldips'], $mx_ips))
										{
											$test['a']=4;
										}
									}
									else
									{
										$test['mx']=1;
										break;
									}
								}
								else
								{
									$test['mx']=3; // this must be an ns error
								}
							}
							else
							{
								$test['mx']=3; // ns error
							}
						}
					}
				}
				else
				{
					$test['mx']=3; // this must be an ns error
				}
			}
			else
			{
					$test['mx']=3; // ns error
			}
		}
		else
		{
			// authoritetive NS not found
			switch($DNS_ERR)
			{
				case 3:
					//NXDOMAIN
					$test['exist']=0;
					$test['ns']=0;
					$test['a']=0;
					$test['mx']=0;
					break;
				case 2:
					//SERVFAIL
					$test['ns']=3;
					$test['error']=0;
					break;
				case 5:
					$test['ns']=3;
					//REFUSED (=rate limit)
//					die('DNS query refused'.PHP_EOL);
					$test['ns']=3;
					$test['error']=0;
					break;
				default:
					$test['ns']=3;
					//display the whole DNS answer
					$nsraw_arr=array();
					shuffle($dns_nic_ips);
					exec("dig NS $domain @".$dns_nic_ips[0], $nsraw_arr);
					$nsraw=implode("\n",$nsraw_arr);
					echo "$nsraw\n";
					break;
			}
		}

		if ($test['ns']==1 && $d_dns==0)
		{
			$test['ns']=2;
		}
		if ($test['a']==1 && $d_ip && !in_array($d_ip, $local['ips']))
		{
			$test['a']=2;
		}
		if ($test['mx']==1 && $d_mx)
		{
			$test['mx']=2;
		}

#######################################

		$test['summary']=0;

		if (!$test['exist'])
		{
			echo "NXDOM   ";
#			$rdres=DBquery("UPDATE `domain` SET `active`=0 WHERE `id`='$domainid' AND `active`=1 AND `name`!='null.null';");
		}
		elseif (!$test['error'])
		{
			echo "NSFAIL  ";
			$test['summary']=999;
		}
		else
		{
			echo $teststring['ns'][$test['ns']].' ';
			echo $teststring['a'][$test['a']].' ';
			echo $teststring['mx'][$test['mx']].' ';
			$test['summary']=$test['summary']+$test['ns']+$test['a']+$test['mx'];
		}

		echo "#$clientnode [$clientname] ".$domain;

		if ($test['summary']==0)
		{
			echo " *DELETE*";
#			$rdres=DBquery("UPDATE `domain` SET `active`=0 WHERE `id`='$domainid' AND `name`!='null.null';");
		}
		else
		{
			if ($test['ns']==0)
			{
				echo " *NSOFF*";
//				$rdres=DBquery("UPDATE `domain` SET `dns`=0 WHERE `id`='$domainid' AND `name`!='null.null';");
			}
			if ($test['ns']==2)
			{
//				echo " *NS_SHOULD_BE_ON* ";
			}
			if ($test['a']==2)
			{
//				echo " *A_SHOULD_BE_ON* ";
			}
			if ($test['mx']==2)
			{
//				echo " *MX_SHOULD_BE_ON* ";
			}
			if ($test['ns']==4)
			{
				echo " ***OLD_NS*** ";
			}
			if ($test['a']==4)
			{
				echo " ***OLD_A*** ";
			}
			if ($test['mx']==4)
			{
				echo " ***OLD_MX*** ";
			}
		}

		echo "\n";

#		if ($test['exist']==1 && $test['error']==1 && $test['summary']<3)
#		{
#			system("dig ANY $domain @$dns_recursor");
#		}
#		exit(0);
	}

	echo "\n*** vhosts ***\n";

	$dres=DBquery("SELECT	`vhosts`.`ext_alias` AS `name`,
				`client`.`name` AS `clientname`,
				`client`.`node` AS `clientnode`
				FROM `vhosts`
				LEFT JOIN `domain` ON `vhosts`.`domainid`=`domain`.`id`
				LEFT JOIN `client` ON `domain`.`clientid`=`client`.`id`
				WHERE `vhosts`.`active`=1
				AND `vhosts`.`ext_alias` IS NOT NULL
				ORDER BY `client`.`node`, `client`.`name`,`vhosts`.`ext_alias`
				;");
//	$dres=DBquery("SELECT `name`,`id` FROM `domain` WHERE `active`=0 AND `name`!='null.null';");
//	$dres=DBquery("SELECT `name`,`id` FROM `domain` WHERE `name`!='null.null';");

	while($drow=$dres->fetch_assoc())
	{

		$clientname=$drow['clientname'];
		$clientnode=$drow['clientnode'];

		$hns_arr=explode(PHP_EOL, $drow['name']);
		foreach($hns_arr as $hn)
		{

			$domain=trim($hn);

			shuffle($dns_recursors);
			$r=new Net_DNS2_Resolver(array('nameservers' => $dns_recursors));

			$test['exist']=1;
			$test['error']=1;
			$test['a']=1;
			$test['summary']=0;

			// A match
			$a_ips=dnsq($domain, 'A', 'answer', 'address', $r);

			if ($a_ips)
			{
				if (count($a_ips)>0)
				{
					// has A record
					if (!in_array_array($local['ips'], $a_ips))
					{
						$test['a']=0;
						if (in_array_array($local['oldips'], $a_ips))
						{
							$test['a']=4;
						}
					}
				}
				else
				{
					$test['a']=3; // this must be an ns error
				}
			}
			else
			{
				$test['a']=3; // ns error
			}

			// WWW A match (only if A doesn't)
			if ($test['a']==0 || $test['a']==3)
			{
				$www_ips=dnsq('www.'.$domain, 'A', 'answer', 'address', $r);
				if ($www_ips && count($www_ips)>0)
				{
					// WWW has A record
					if (in_array_array($local['ips'], $www_ips))
					{
						$test['a']=1;
					}
					elseif (in_array_array($local['oldips'], $www_ips))
					{
						$test['a']=4;
					}

				}
			}

#######################################

			$test['summary']=0;

			echo $teststring['a'][$test['a']].' ';
			$test['summary']=$test['a'];

			echo "#$clientnode [$clientname] ".$domain;

			if ($test['summary']==0)
			{
				echo " *DELETE*";
			}
			else
			{
				if ($test['a']==2)
				{
					echo " +++";
				}
				if ($test['a']==4)
				{
					echo " ***OLD_A*** ";
				}
			}

			echo "\n";
		}
	}


exit (0);
