source: branches/stable/cgi-bin/extras/db2rwhois.pl@ 367

Last change on this file since 367 was 367, checked in by Kris Deugau, 17 years ago

/branches/stable

Major update to db2rwhois.pl so that it can

a) take advantage of updates to the masterblocks table to determine

which masters get exported to rwhois

b) create and delete rwhois directory trees as needed for

new/changed/removed master blocks

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