source: trunk/cgi-bin/extras/db2rwhois.pl@ 447

Last change on this file since 447 was 437, checked in by Kris Deugau, 14 years ago

/trunk

More tidyups:

  • Add $IPDB::hostmaster for rWHOIS
  • Fix typo in MyIPDB.pm for orgname -> org_name
  • Use $IPDB::domain and $IPDB::hostmaster in db2rwhois.pl creating the SOA file
  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 11.3 KB
Line 
1#!/usr/bin/perl
2# -T
3# ipdb/cgi-bin/extras/db2rwhois.pl
4# Pull data from ipdb and mangle it into RWHOIS
5# Initial version 03/26/2004 kdeugau against IPDB v1
6###
7# Revision info
8# $Date: 2010-07-20 15:29:32 +0000 (Tue, 20 Jul 2010) $
9# SVN revision $Rev: 437 $
10# Last update by $Author: kdeugau $
11###
12# Copyright (C) 2004-2010 - Kris Deugau
13
14use strict;
15use warnings;
16use DBI;
17use NetAddr::IP;
18use File::Path 'rmtree';
19use POSIX qw(strftime);
20
21# don't remove! required for GNU/FHS-ish install from tarball
22##uselib##
23
24use MyIPDB;
25
26#$ENV{"PATH"} = "/bin;/usr/bin";
27
28my @autharea;
29my $authrw;
30# Use the template file to allow us to keep persistent nodes aside from netblock data
31open AUTHTEMPLATE, "<$IPDB::rwhoisDataPath/rwhoisd.auth_template";
32my $template_persist;
33while (<AUTHTEMPLATE>) {
34 next if /^##/;
35 $template_persist = 1 if /^[a-z]/i;
36 $autharea[0] .= $_;
37}
38
39my ($dbh,$msg) = connectDB_My;
40
41# For WHOIS purposes this may not be very useful. YMMV, we'll see.
42#initIPDBGlobals($dbh);
43
44my @masterblocks;
45my %netnameprefix;
46
47# Get the list of live directories for potential deletion
48opendir RWHOISROOT, $IPDB::rwhoisDataPath;
49my %rwhoisdirs;
50foreach (readdir RWHOISROOT) {
51 $rwhoisdirs{$_} = 1 if /^net-/;
52}
53closedir RWHOISROOT;
54
55# prefetch alloctype data
56my $sth = $dbh->prepare("select type,def_custid,arin_netname from alloctypes");
57$sth->execute;
58while (my @data = $sth->fetchrow_array) {
59 $netnameprefix{$data[0]} = $data[2];
60}
61
62# Get the list of masters to export
63my $msth = $dbh->prepare("select cidr,ctime,mtime from masterblocks where rwhois='y'");
64$msth->execute;
65
66# Prepare to select subblocks for each master
67# Make sure to remove the private netblocks from this,
68# no use or point in broadcasting our use of them.
69# Also remove the details of our "reserved CORE/WAN" blocks; they're not critical.
70my $ssth = $dbh->prepare("select cidr,custid,type,city,description,createstamp,modifystamp,swip ".
71 "from allocations where ".
72 "not (cidr <<= '192.168.0.0/16') and ".
73 "not (cidr <<= '172.16.0.0/12') and ".
74 "not (cidr <<= '10.0.0.0/8') and ".
75 "not (type = 'wr') and ".
76 "masklen(cidr) <=30 and ".
77 "cidr <<= ?");
78
79# Customer data, for those rare blocks we really need to delegate.
80my $custsth = $dbh->prepare("select name,street,city,province,country,pocode,phone,tech_handle,special ".
81 "from customers where custid=?");
82
83# Fill in data about our master blocks as allocated from ARIN
84# We open separate files for each of these as appropriate.
85# Changes in master blocks are treated as complete new masters - since we're exporting
86# all data every time, this isn't so terrible as it might seem.
87my $i=0;
88while (my @data = $msth->fetchrow_array()) {
89
90 $masterblocks[$i] = new NetAddr::IP $data[0];
91 my ($ctime,undef) = split /\s/, $data[1];
92 my ($mtime,undef) = split /\s/, $data[2];
93
94 print "$masterblocks[$i] $ctime $mtime\n";
95
96 my $date = strftime("%Y-%m-%d", localtime);
97
98 my $rwnet = "net-".$masterblocks[$i]->addr."-".$masterblocks[$i]->masklen;
99
100 # unflag the directory for deletion. Whee! Roundabout!
101 delete $rwhoisdirs{$rwnet};
102
103# Hokay. Gonna do checks *here* to see if we need to create new master trees
104 my $netdatadir = "$IPDB::rwhoisDataPath/$rwnet";
105 if (! -e $netdatadir) {
106 print " New master $masterblocks[$i]!\n";
107 print " Creating directories...\n";
108 mkdir $netdatadir;
109 mkdir "$netdatadir/attribute_defs";
110 mkdir "$netdatadir/data";
111 mkdir "$netdatadir/data/network";
112 mkdir "$netdatadir/data/org";
113 mkdir "$netdatadir/data/referral";
114
115 my $serial = strftime("%Y%m%d%H%M%S000", localtime);
116
117##fixme: SOA should be different every time data changes, therefore need to rewrite this ~~ every export :(
118 print " Creating SOA...\n";
119 open SOAFILE, ">$netdatadir/soa";
120 print SOAFILE qq(Serial-Number: $serial
121Refresh-Interval: 3600
122Increment-Interval: 1800
123Retry-Interval: 1800
124Time-To-Live: 86400
125Primary-Server: rwhois.$IPDB::domain:4321
126Hostmaster: $IPDB::hostmaster
127);
128 close SOAFILE;
129
130 print " Creating Schema...\n";
131 open SCHEMAFILE, ">$netdatadir/schema";
132 print SCHEMAFILE qq(name: network
133attributedef: $rwnet/attribute_defs/network.tmpl
134dbdir: $rwnet/data/network
135Schema-Version: $serial
136---
137name: organization
138attributedef: $rwnet/attribute_defs/org.tmpl
139dbdir: $rwnet/data/org
140description: Organization object
141Schema-Version: $serial
142---
143name: referral
144attributedef:$rwnet/attribute_defs/referral.tmpl
145dbdir:$rwnet/data/referral
146Schema-Version: $serial
147);
148 close SCHEMAFILE;
149
150 print " Copying template files...\n";
151##fixme: find a way to do this without a shell (or functional equivalent)
152 qx { /bin/cp $IPDB::rwhoisDataPath/skel/attribute_defs/* $netdatadir/attribute_defs/ };
153
154##fixme: not sure if this is even necessary, since it's not referenced anywhere I can recall...
155 print " Creating org data...\n";
156 open ORGDATAFILE, ">$netdatadir/data/org/ourorg.txt";
157 print ORGDATAFILE qq(ID: NETBLK-ISP.$masterblocks[$i]
158Auth-Area: $masterblocks[$i]
159Org-Name: $IPDB::org_name
160Street-Address: $IPDB::org_street
161City: $IPDB::org_city
162State: $IPDB::org_prov_state
163Postal-Code: $IPDB::org_pocode
164Country-Code: $IPDB::org_country
165Phone: $IPDB::org_phone
166Created: 20040308
167Updated: 20040308
168);
169 close ORGDATAFILE;
170
171 # Generate auth_area record, and add it to the array.
172 $authrw = 1; # Flag for rewrite and daemon reload/restart
173
174 } # new master
175
176 # do this for all masters, so that we can use this array to export the data
177 # to rwhoisd.auth_area later if we need to
178 push @autharea, qq(type:master
179name:$masterblocks[$i]
180data-dir: $rwnet/data
181schema-file: $rwnet/schema
182soa-file: $rwnet/soa
183);
184
185 # Recreate the net-nnn.nnn.nnn.nnn-nn.txt data file
186 my $masterfilename = "$rwnet/data/network/".$masterblocks[$i]->addr."-".$masterblocks[$i]->masklen.".txt";
187
188 open MASTERFILE,">$IPDB::rwhoisDataPath/$masterfilename";
189
190 print MASTERFILE "ID: NETBLK-ISP.$masterblocks[$i]\n".
191 "Auth-Area: $masterblocks[$i]\n".
192 "Network-Name: ISP-".$masterblocks[$i]->network."\n".
193 "IP-Network: $masterblocks[$i]\n".
194 "IP-Network-Block: ".$masterblocks[$i]->range."\n".
195 "Org-Name: $IPDB::org_name\n".
196 "Street-Address: $IPDB::org_street\n".
197 "City: $IPDB::org_city\n".
198 "StateProv: $IPDB::org_prov_state\n".
199 "Postal-Code: $IPDB::org_pocode\n".
200 "Country-Code: $IPDB::org_country\n".
201 "Tech-Contact: $IPDB::org_techhandle\n".
202 "Created: $ctime\n".
203 "Updated: $mtime\n".
204 "Updated-By: $IPDB::org_email\n";
205
206 # And now the subblocks
207 $ssth->execute("$masterblocks[$i]");
208 while (my ($cidr, $custid, $type, $city, $desc, $ctime, $mtime, $swip) = $ssth->fetchrow_array) {
209
210# We get master block info from @masterblocks.
211 # ID: NETBLK-ISP.10.0.0.0/8
212 # Auth-Area: 10.0.0.0/8
213 # Network-Name: ISP-10.0.2.144
214 # IP-Network: 10.0.2.144.144/29
215 # IP-Network-Block: 10.0.2.144 - 10.0.2.151
216 # Organization: WidgetCorp
217 # Tech-Contact: bob@widgetcorp.com
218 # Admin-Contact: ISP-ARIN-HANDLE
219 # Created: 20040314
220 # Updated: 20040314
221 # Updated-By: noc@example.com
222
223 # Get the "full" network number
224 my $net = new NetAddr::IP $cidr;
225
226# Assumptions: All data in ipdb is public
227# If not, we need another field to indicate "public/private".
228
229# cidr custid type city description notes maskbits
230
231# Fill in a generic entry for nameless allocations
232if ($desc =~ /^\s*$/) { $desc = $IPDB::org_name; }
233
234 # Fix up datestamps. We don't *really* need sub-microsecond resolution on our exports...
235 ($ctime) = ($ctime =~ /^(\d+-\d+-\d+)\s+/);
236 ($mtime) = ($mtime =~ /^(\d+-\d+-\d+)\s+/);
237
238# Notes:
239# Network-name should contain some component of "description"
240# Cust address/contact data should be included; NB, no phone for ARIN!
241# network:ID: NET-WIDGET
242# network:Network-Name: WIDGET [IPDB description, sort of]
243# network:IP-Network: 10.1.1.0/24
244# network:Org-Name: Widget Corp [Cust name; from billing?]
245# network:Street-Address: 211 Oak Drive [May need more than one line, OR...]
246# network:City: Pineville [...this line...]
247# network:StateProv: WI [...and this line...]
248# network:Postal-Code: 48888 [...and this line]
249# network:Country-Code: US
250# network:Tech-Contact: BZ142-MYRWHOIS [ARIN handle?]
251# network:Updated: 19991221 [timestamp from db]
252# network:Updated-By: jo@myrwhois.net [noc@example, since that's our POC for IP netspace issues]
253# network:Class-Name:network [Provided by rWHOIS protocol]
254
255 my $netname = $netnameprefix{$type};
256
257 if ($swip eq 'n') {
258 print MASTERFILE "---\nID: NETBLK-ISP.$masterblocks[$i]\n".
259 "Auth-Area: $masterblocks[$i]\n".
260 "Network-Name: $netname-".$net->network."\n".
261 "IP-Network: $net\n".
262 "IP-Network-Block: ".$net->range."\n".
263 "Org-Name: $IPDB::org_name\n".
264 "Street-Address: $IPDB::org_street\n".
265 "City: $IPDB::org_city\n".
266 "StateProv: $IPDB::org_prov_state\n".
267 "Postal-Code: $IPDB::org_pocode\n".
268 "Country-Code: $IPDB::org_country\n".
269 "Tech-Contact: $IPDB::org_techhandle\n".
270 "Created: $ctime\n".
271 "Updated: $mtime\n".
272 "Updated-By: $IPDB::org_email\n";
273 } else {
274 $custsth->execute($custid);
275 my ($name, $street, $city, $prov, $country, $pocode, $phone, $tech, $special) = $custsth->fetchrow_array;
276 $custsth->finish;
277 if ($special && $special =~ /NetName/ && $special =~ /$cidr/) {
278 ($netname) = ($special =~ /NetName$cidr: ([A-Z0-9_-]+)/);
279 } else {
280 $netname .= "-".$net->network;
281 }
282 print MASTERFILE "---\nID: NETBLK-ISP.$masterblocks[$i]\n".
283 "Auth-Area: $masterblocks[$i]\n".
284 "Network-Name: $netname\n".
285 "IP-Network: $net\n".
286 "IP-Network-Block: ".$net->range."\n".
287 "Org-Name: ".($name ? $name : $IPDB::org_name)."\n".
288 "Street-Address: ".($street ? $street : $IPDB::org_street)."\n".
289 "City: ".($city ? $city : $IPDB::org_city)."\n".
290 "StateProv: ".($prov ? $prov : $IPDB::org_prov_state)."\n".
291 "Postal-Code: ".($pocode ? $pocode : $IPDB::org_pocode)."\n".
292 "Country-Code: ".($country ? $country : $IPDB::org_country)."\n".
293 "Tech-Contact: ".($tech ? $tech : $IPDB::org_techhandle)."\n".
294 "Created: $ctime\n".
295 "Updated: $mtime\n".
296 "Updated-By: $IPDB::org_email\n";
297 } # swip
298
299 } # while $ssth->fetchrow_array()
300
301 close MASTERFILE;
302
303 $i++;
304} # while $msth->fetchrow_array()
305
306# Now we see if there's obsolete netdata directories to be deleted,
307# and therefore an auth-area file to regenerate
308foreach my $netdir (keys %rwhoisdirs) {
309 print "deleting obsolete directory $netdir...\n";
310 rmtree ( "$IPDB::rwhoisDataPath/$netdir", { verbose => 1, error => \my $errlist } );
311 for my $diag (@$errlist) {
312 my ($file, $message) = each %$diag;
313 if ($file eq '') {
314 print "general error: $message\n";
315 }
316 }
317 $authrw = 1; # there's probably a more efficient place to put this. Feh.
318}
319
320# Regenerate rwhoisd.auth_area if needed
321if ($authrw) {
322 print "Regenerating auth_area\n";
323 open RWHOISDAUTH, ">$IPDB::rwhoisDataPath/rwhoisd.auth_area";
324 print RWHOISDAUTH "# WARNING: This file is autogenerated! Any static nodes should\n".
325 "# be entered in /etc/rwhoisd/rwhoisd.auth_template\n";
326 if ($template_persist) {
327 print RWHOISDAUTH shift @autharea;
328 print RWHOISDAUTH "---\n";
329 }
330 # feh. we need to know when we're at the end of the loop, because then
331 # we DON'T want to write the separator...
332 for (;@autharea;) { # my head hurts.
333 print RWHOISDAUTH shift @autharea;
334 print RWHOISDAUTH "---\n" if @autharea;
335 }
336 close RWHOISDAUTH;
337
338 # restart/reload rwhoisd
339 if (-e "$IPDB::rwhoisDataPath/rwhoisd.pid") { # no pidfile, no restart.
340 print "Restarting rwhoisd\n";
341 open PIDFILE, "<$IPDB::rwhoisDataPath/rwhoisd.pid";
342 my ($rwpid) = (<PIDFILE> =~ /^(\d+)/);
343 close PIDFILE;
344 kill 'HUP', $rwpid;
345 }
346}
347
348# and finally
349$dbh->disconnect;
Note: See TracBrowser for help on using the repository browser.