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

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

/trunk

Merge bugfixes and enhancements from /branches/stable r360 through r369

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