#!/usr/bin/php -q // http://peen.net/ // Written & released 2006/03/08. Output unverified. // 2006/08/23 - Use less memory // The CSV file downloaded from // http://software77.net/cgi-bin/ip-country/geo-ip.pl $database = "IpToCountry.csv"; // A seperate file will be created for every acl. If you like, you can // specify a prefix and/or postfix. $prefix = "acl-"; $postfix = ".inc"; // Method of splitting used. You can split on either 'countrycode' or // 'registry'. $method = "countrycode"; // Define the zones you wish to split into. You can specify any number // of zones as long as they all have unique names. // Example for registry split: // $zone["ripe"] = array("RIPE"); // $zone["arin"] = array("ARIN"); // $zone["other"] = array("APNIC","LACNIC","AFRINIC", "IANA"); // Example for country split: $zone["europe_east"] = array("BY","BG","CZ","HU","MD","PL","RO","RU","SK", "UA"); $zone["europe_nort"] = array("AX","DK","EE","FO","FI","IS","IE","LV","LT", "NO","SJ","SE","GB"); $zone["europe_sout"] = array("AL","AD","BA","HR","GI","GR","VA","IT","MK", "MT","PT","SM","CS","SI","ES"); $zone["europe_west"] = array("AT","BE","FR","DE","LI","LU","MC","NL","CH", "EU", "CS", "YU", "FX"); $zone["australia"] = array("AU","CX","CC","NZ","NF"); $zone["melanesia"] = array("FJ","NC","PG","SB","VU"); $zone["micronesia"] = array("GU","KI","MH","FM","NR","MP","PW"); $zone["polynesia"] = array("AS","CK","PF","NU","PN","WS","TK","TO","TV", "WF"); $zone["asia_east"] = array("AP","CN","HK","MO","JP","KP","KR","MN","TW"); $zone["asia_cent"] = array("AF","BD","BT","IN","IR","KZ","KG","MV","NP", "PK","LK","TJ","TM","UZ"); $zone["asia_seas"] = array("BN","KH","ID","LA","MY","MM","PH","SG","TH", "TL","VN"); $zone["asia_west"] = array("AM","AZ","BH","CY","GE","IQ","IL","JO","KW", "LB","PS","OM","QA","SA","SY","TR","AE","YE"); $zone["america_nort"] = array("ZZ","US","BM","CA","GL","PM"); $zone["america_cari"] = array("AI","AG","AW","BS","BB","VG","KY","CU","DM", "DO","GD","GP","HT","JM","MQ","MS","AN","PR", "KN","LC","VC","TT","TC","VI"); $zone["america_cent"] = array("BZ","CR","SV","GT","HN","MX","NI","PA"); $zone["america_sout"] = array("AR","BO","BR","CL","CO","EC","FK","GF","GY", "PY","PE","SR","UY","VE"); $zone["africa_east"] = array("BI","KM","DJ","ER","ET","KE","MG","MW","MU", "YT","MZ","RE","RW","SC","SO","TZ","UW","ZM", "ZW"); $zone["africa_midd"] = array("AO","CM","CF","TD","CG","CD","GQ","GA","ST"); $zone["africa_nort"] = array("DZ","EG","LY","MA","SD","TN","EH"); $zone["africa_sout"] = array("BW","LS","NA","ZA","SZ"); $zone["africa_west"] = array("BJ","BF","CV","CI","GM","GH","GN","GW","LR", "ML","MR","NE","NG","SH","SN","SL","TG"); $zone["other"] = array("PS","AQ","BV","IO","TF","HM","GS","UM"); //////// No need to change anything else. Go and run this thing! ////////// /////////////////////////////////////////////////////////////////////////// function mask($t) { return base_convert( (pow(2,32) - pow(2, (32-$t)) ) , 10, 16); } function imaxblock($ibase, $tbit) { // function by trevor-hemsley at nospam dot dial dot pipex dot com while ($tbit > 0) { $im = hexdec(mask($tbit-1)); $imand = $ibase & $im; if ($imand != $ibase) { break; } $tbit--; } return $tbit; } function range2cidrlist($istart, $iend, $fp) { // function by trevor-hemsley at nospam dot dial dot pipex dot com $s = explode(".", $istart); $start = ""; $dot = ""; while (list($key,$val) = each($s)) { $start = sprintf("%s%s%d",$start,$dot,$val); $dot = "."; } $end = ""; $dot = ""; $e = explode(".",$iend); while (list($key,$val) = each($e)) { $end = sprintf("%s%s%d",$end,$dot,$val); $dot = "."; } $start = ip2long($start); $end = ip2long($end); $result = array(); while ($end >= $start) { $maxsize = imaxblock($start,32); $x = log($end - $start + 1)/log(2); $maxdiff = floor(32 - floor($x)); $ip = long2ip($start); if ($maxsize < $maxdiff) { $maxsize = $maxdiff; } set_time_limit(30); fputs($fp, "\t$ip/$maxsize;\n"); $start += pow(2, (32-$maxsize)); } return $result; } // fix input errors $method = strtolower(trim($method)); // open output files reset($zone); while($view = each($zone)) { $fps[$view[0]] = @fopen($prefix.$view[0].$postfix, "w") or die("Could not open ".$prefix.$view[0].$postfix." for writing!\n"); fputs($fps[$view[0]], "acl ".$view[0]." {\n"); } // start processing! $fp = @fopen($database, "r") or die("Could not open ".$database." for reading!\n"); reset($zone); $i=0; while(!feof($fp)) { $line = fgetcsv($fp, 4096, ",", "\""); if( (substr(trim($line[0]),0,1)!="#") && (count($line)==7)) { $ip_beg = $line[0]; $ip_end = $line[1]; $ip_reg = $line[2]; $ip_cnt = $line[4]; if($method=="countrycode") $ip_key = $ip_cnt; else $ip_key = $ip_reg; reset($zone); while($view = each($zone)) { if(in_array($ip_key, $view[1])) $ip_view = $view[0]; } $cidrlist = range2cidrlist($ip_beg, $ip_end, $fps[$ip_view]); } if(($i/100)==round($i/100))echo "\rProcessed ".$i." lines.."; $i++; } fclose($fp); reset($fps); while(list($dummy,$fpi) = each($fps)) { fputs($fpi, "};\n"); fclose($fpi); } echo "Done.\n"; ?>