dhcpd-conf-to-ldap revision 1.1.1.1 1 1.1 christos #!/usr/bin/perl -w
2 1.1 christos
3 1.1 christos # Brian Masney <masneyb (at] gftp.org>
4 1.1 christos # To use this script, set your base DN below. Then run
5 1.1 christos # ./dhcpd-conf-to-ldap.pl < /path-to-dhcpd-conf/dhcpd.conf > output-file
6 1.1 christos # The output of this script will generate entries in LDIF format. You can use
7 1.1 christos # the slapadd command to add these entries into your LDAP server. You will
8 1.1 christos # definately want to double check that your LDAP entries are correct before
9 1.1 christos # you load them into LDAP.
10 1.1 christos
11 1.1 christos # This script does not do much error checking. Make sure before you run this
12 1.1 christos # that the DHCP server doesn't give any errors about your config file
13 1.1 christos
14 1.1 christos # FailOver notes:
15 1.1 christos # Failover is disabled by default, since it may need manually intervention.
16 1.1 christos # You can try the '--use=failover' option to see what happens :-)
17 1.1 christos #
18 1.1 christos # If enabled, the failover pool references will be written to LDIF output.
19 1.1 christos # The failover configs itself will be added to the dhcpServer statements
20 1.1 christos # and not to the dhcpService object (since this script uses only one and
21 1.1 christos # it may be usefull to have multiple service containers in failover mode).
22 1.1 christos # Further, this script does not check if primary or secondary makes sense,
23 1.1 christos # it simply converts what it gets...
24 1.1 christos
25 1.1 christos use Net::Domain qw(hostname hostfqdn hostdomain);
26 1.1 christos use Getopt::Long;
27 1.1 christos
28 1.1 christos my $domain = hostdomain(); # your.domain
29 1.1 christos my $basedn = "dc=".$domain;
30 1.1 christos $basedn =~ s/\./,dc=/g; # dc=your,dc=domain
31 1.1 christos my $server = hostname(); # hostname (nodename)
32 1.1 christos my $dhcpcn = 'DHCP Config'; # CN of DHCP config tree
33 1.1 christos my $dhcpdn = "cn=$dhcpcn, $basedn"; # DHCP config tree DN
34 1.1 christos my $second = ''; # secondary server DN / hostname
35 1.1 christos my $i_conf = ''; # dhcp.conf file to read or stdin
36 1.1 christos my $o_ldif = ''; # output ldif file name or stdout
37 1.1 christos my @use = (); # extended flags (failover)
38 1.1 christos
39 1.1 christos sub usage($;$)
40 1.1 christos {
41 1.1 christos my $rc = shift;
42 1.1 christos my $err= shift;
43 1.1 christos
44 1.1 christos print STDERR "Error: $err\n\n" if(defined $err);
45 1.1 christos print STDERR <<__EOF_USAGE__;
46 1.1 christos usage:
47 1.1 christos $0 [options] < dhcpd.conf > dhcpd.ldif
48 1.1 christos
49 1.1 christos options:
50 1.1 christos
51 1.1 christos --basedn "dc=your,dc=domain" ("$basedn")
52 1.1 christos
53 1.1 christos --dhcpdn "dhcp config DN" ("$dhcpdn")
54 1.1 christos
55 1.1 christos --server "dhcp server name" ("$server")
56 1.1 christos
57 1.1 christos --second "secondary server or DN" ("$second")
58 1.1 christos
59 1.1 christos --conf "/path/to/dhcpd.conf" (default is stdin)
60 1.1 christos --ldif "/path/to/output.ldif" (default is stdout)
61 1.1 christos
62 1.1 christos --use "extended features" (see source comments)
63 1.1 christos __EOF_USAGE__
64 1.1 christos exit($rc);
65 1.1 christos }
66 1.1 christos
67 1.1 christos
68 1.1 christos sub next_token
69 1.1 christos {
70 1.1 christos local ($lowercase) = @_;
71 1.1 christos local ($token, $newline);
72 1.1 christos
73 1.1 christos do
74 1.1 christos {
75 1.1 christos if (!defined ($line) || length ($line) == 0)
76 1.1 christos {
77 1.1 christos $line = <>;
78 1.1 christos return undef if !defined ($line);
79 1.1 christos chop $line;
80 1.1 christos $line_number++;
81 1.1 christos $token_number = 0;
82 1.1 christos }
83 1.1 christos
84 1.1 christos $line =~ s/#.*//;
85 1.1 christos $line =~ s/^\s+//;
86 1.1 christos $line =~ s/\s+$//;
87 1.1 christos }
88 1.1 christos while (length ($line) == 0);
89 1.1 christos
90 1.1 christos if (($token, $newline) = $line =~ /^(.*?)\s+(.*)/)
91 1.1 christos {
92 1.1 christos if ($token =~ /^"/) {
93 1.1 christos #handle quoted token
94 1.1 christos if ($token !~ /"\s*$/)
95 1.1 christos {
96 1.1 christos ($tok, $newline) = $newline =~ /([^"]+")(.*)/;
97 1.1 christos $token .= " $tok";
98 1.1 christos }
99 1.1 christos }
100 1.1 christos $line = $newline;
101 1.1 christos }
102 1.1 christos else
103 1.1 christos {
104 1.1 christos $token = $line;
105 1.1 christos $line = '';
106 1.1 christos }
107 1.1 christos $token_number++;
108 1.1 christos
109 1.1 christos $token =~ y/[A-Z]/[a-z]/ if $lowercase;
110 1.1 christos
111 1.1 christos return ($token);
112 1.1 christos }
113 1.1 christos
114 1.1 christos
115 1.1 christos sub remaining_line
116 1.1 christos {
117 1.1 christos local ($block) = shift || 0;
118 1.1 christos local ($tmp, $str);
119 1.1 christos
120 1.1 christos $str = "";
121 1.1 christos while (defined($tmp = next_token (0)))
122 1.1 christos {
123 1.1 christos $str .= ' ' if !($str eq "");
124 1.1 christos $str .= $tmp;
125 1.1 christos last if $tmp =~ /;\s*$/;
126 1.1 christos last if($block and $tmp =~ /\s*[}{]\s*$/);
127 1.1 christos }
128 1.1 christos
129 1.1 christos $str =~ s/;$//;
130 1.1 christos return ($str);
131 1.1 christos }
132 1.1 christos
133 1.1 christos
134 1.1 christos sub
135 1.1 christos add_dn_to_stack
136 1.1 christos {
137 1.1 christos local ($dn) = @_;
138 1.1 christos
139 1.1 christos $current_dn = "$dn, $current_dn";
140 1.1 christos $curentry{'current_dn'} = $current_dn;
141 1.1 christos }
142 1.1 christos
143 1.1 christos
144 1.1 christos sub
145 1.1 christos remove_dn_from_stack
146 1.1 christos {
147 1.1 christos $current_dn =~ s/^.*?,\s*//;
148 1.1 christos }
149 1.1 christos
150 1.1 christos
151 1.1 christos sub
152 1.1 christos parse_error
153 1.1 christos {
154 1.1 christos print "Parse error on line number $line_number at token number $token_number\n";
155 1.1 christos exit (1);
156 1.1 christos }
157 1.1 christos
158 1.1 christos sub
159 1.1 christos new_entry
160 1.1 christos {
161 1.1 christos if (%curentry) {
162 1.1 christos $curentry{'current_dn'} = $current_dn;
163 1.1 christos push(@entrystack, {%curentry});
164 1.1 christos undef(%curentry);
165 1.1 christos }
166 1.1 christos }
167 1.1 christos
168 1.1 christos sub
169 1.1 christos pop_entry
170 1.1 christos {
171 1.1 christos if (%curentry) {
172 1.1 christos push(@outputlist, {%curentry});
173 1.1 christos }
174 1.1 christos $rentry = pop(@entrystack);
175 1.1 christos %curentry = %$rentry if $rentry;
176 1.1 christos }
177 1.1 christos
178 1.1 christos
179 1.1 christos sub
180 1.1 christos print_entry
181 1.1 christos {
182 1.1 christos return if (scalar keys %curentry == 0);
183 1.1 christos
184 1.1 christos if (!defined ($curentry{'type'}))
185 1.1 christos {
186 1.1 christos $hostdn = "cn=$server, $basedn";
187 1.1 christos print "dn: $hostdn\n";
188 1.1 christos print "cn: $server\n";
189 1.1 christos print "objectClass: top\n";
190 1.1 christos print "objectClass: dhcpServer\n";
191 1.1 christos print "dhcpServiceDN: $curentry{'current_dn'}\n";
192 1.1 christos if(grep(/FaIlOvEr/i, @use))
193 1.1 christos {
194 1.1 christos foreach my $fo_peer (keys %failover)
195 1.1 christos {
196 1.1 christos next if(scalar(@{$failover{$fo_peer}}) <= 1);
197 1.1 christos print "dhcpStatements: failover peer $fo_peer { ",
198 1.1 christos join('; ', @{$failover{$fo_peer}}), "; }\n";
199 1.1 christos }
200 1.1 christos }
201 1.1 christos print "\n";
202 1.1 christos
203 1.1 christos print "dn: $curentry{'current_dn'}\n";
204 1.1 christos print "cn: $dhcpcn\n";
205 1.1 christos print "objectClass: top\n";
206 1.1 christos print "objectClass: dhcpService\n";
207 1.1 christos if (defined ($curentry{'options'}))
208 1.1 christos {
209 1.1 christos print "objectClass: dhcpOptions\n";
210 1.1 christos }
211 1.1 christos print "dhcpPrimaryDN: $hostdn\n";
212 1.1 christos if(grep(/FaIlOvEr/i, @use) and ($second ne ''))
213 1.1 christos {
214 1.1 christos print "dhcpSecondaryDN: $second\n";
215 1.1 christos }
216 1.1 christos }
217 1.1 christos elsif ($curentry{'type'} eq 'subnet')
218 1.1 christos {
219 1.1 christos print "dn: $curentry{'current_dn'}\n";
220 1.1 christos print "cn: " . $curentry{'ip'} . "\n";
221 1.1 christos print "objectClass: top\n";
222 1.1 christos print "objectClass: dhcpSubnet\n";
223 1.1 christos if (defined ($curentry{'options'}))
224 1.1 christos {
225 1.1 christos print "objectClass: dhcpOptions\n";
226 1.1 christos }
227 1.1 christos
228 1.1 christos print "dhcpNetMask: " . $curentry{'netmask'} . "\n";
229 1.1 christos if (defined ($curentry{'ranges'}))
230 1.1 christos {
231 1.1 christos foreach $statement (@{$curentry{'ranges'}})
232 1.1 christos {
233 1.1 christos print "dhcpRange: $statement\n";
234 1.1 christos }
235 1.1 christos }
236 1.1 christos }
237 1.1 christos elsif ($curentry{'type'} eq 'shared-network')
238 1.1 christos {
239 1.1 christos print "dn: $curentry{'current_dn'}\n";
240 1.1 christos print "cn: " . $curentry{'descr'} . "\n";
241 1.1 christos print "objectClass: top\n";
242 1.1 christos print "objectClass: dhcpSharedNetwork\n";
243 1.1 christos if (defined ($curentry{'options'}))
244 1.1 christos {
245 1.1 christos print "objectClass: dhcpOptions\n";
246 1.1 christos }
247 1.1 christos }
248 1.1 christos elsif ($curentry{'type'} eq 'group')
249 1.1 christos {
250 1.1 christos print "dn: $curentry{'current_dn'}\n";
251 1.1 christos print "cn: group", $curentry{'idx'}, "\n";
252 1.1 christos print "objectClass: top\n";
253 1.1 christos print "objectClass: dhcpGroup\n";
254 1.1 christos if (defined ($curentry{'options'}))
255 1.1 christos {
256 1.1 christos print "objectClass: dhcpOptions\n";
257 1.1 christos }
258 1.1 christos }
259 1.1 christos elsif ($curentry{'type'} eq 'host')
260 1.1 christos {
261 1.1 christos print "dn: $curentry{'current_dn'}\n";
262 1.1 christos print "cn: " . $curentry{'host'} . "\n";
263 1.1 christos print "objectClass: top\n";
264 1.1 christos print "objectClass: dhcpHost\n";
265 1.1 christos if (defined ($curentry{'options'}))
266 1.1 christos {
267 1.1 christos print "objectClass: dhcpOptions\n";
268 1.1 christos }
269 1.1 christos
270 1.1 christos if (defined ($curentry{'hwaddress'}))
271 1.1 christos {
272 1.1 christos $curentry{'hwaddress'} =~ y/[A-Z]/[a-z]/;
273 1.1 christos print "dhcpHWAddress: " . $curentry{'hwaddress'} . "\n";
274 1.1 christos }
275 1.1 christos }
276 1.1 christos elsif ($curentry{'type'} eq 'pool')
277 1.1 christos {
278 1.1 christos print "dn: $curentry{'current_dn'}\n";
279 1.1 christos print "cn: pool", $curentry{'idx'}, "\n";
280 1.1 christos print "objectClass: top\n";
281 1.1 christos print "objectClass: dhcpPool\n";
282 1.1 christos if (defined ($curentry{'options'}))
283 1.1 christos {
284 1.1 christos print "objectClass: dhcpOptions\n";
285 1.1 christos }
286 1.1 christos
287 1.1 christos if (defined ($curentry{'ranges'}))
288 1.1 christos {
289 1.1 christos foreach $statement (@{$curentry{'ranges'}})
290 1.1 christos {
291 1.1 christos print "dhcpRange: $statement\n";
292 1.1 christos }
293 1.1 christos }
294 1.1 christos }
295 1.1 christos elsif ($curentry{'type'} eq 'class')
296 1.1 christos {
297 1.1 christos print "dn: $curentry{'current_dn'}\n";
298 1.1 christos print "cn: " . $curentry{'class'} . "\n";
299 1.1 christos print "objectClass: top\n";
300 1.1 christos print "objectClass: dhcpClass\n";
301 1.1 christos if (defined ($curentry{'options'}))
302 1.1 christos {
303 1.1 christos print "objectClass: dhcpOptions\n";
304 1.1 christos }
305 1.1 christos }
306 1.1 christos elsif ($curentry{'type'} eq 'subclass')
307 1.1 christos {
308 1.1 christos print "dn: $curentry{'current_dn'}\n";
309 1.1 christos print "cn: " . $curentry{'subclass'} . "\n";
310 1.1 christos print "objectClass: top\n";
311 1.1 christos print "objectClass: dhcpSubClass\n";
312 1.1 christos if (defined ($curentry{'options'}))
313 1.1 christos {
314 1.1 christos print "objectClass: dhcpOptions\n";
315 1.1 christos }
316 1.1 christos print "dhcpClassData: " . $curentry{'class'} . "\n";
317 1.1 christos }
318 1.1 christos
319 1.1 christos if (defined ($curentry{'statements'}))
320 1.1 christos {
321 1.1 christos foreach $statement (@{$curentry{'statements'}})
322 1.1 christos {
323 1.1 christos print "dhcpStatements: $statement\n";
324 1.1 christos }
325 1.1 christos }
326 1.1 christos
327 1.1 christos if (defined ($curentry{'options'}))
328 1.1 christos {
329 1.1 christos foreach $statement (@{$curentry{'options'}})
330 1.1 christos {
331 1.1 christos print "dhcpOption: $statement\n";
332 1.1 christos }
333 1.1 christos }
334 1.1 christos
335 1.1 christos print "\n";
336 1.1 christos undef (%curentry);
337 1.1 christos }
338 1.1 christos
339 1.1 christos
340 1.1 christos sub parse_netmask
341 1.1 christos {
342 1.1 christos local ($netmask) = @_;
343 1.1 christos local ($i);
344 1.1 christos
345 1.1 christos if ((($a, $b, $c, $d) = $netmask =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) != 4)
346 1.1 christos {
347 1.1 christos parse_error ();
348 1.1 christos }
349 1.1 christos
350 1.1 christos $num = (($a & 0xff) << 24) |
351 1.1 christos (($b & 0xff) << 16) |
352 1.1 christos (($c & 0xff) << 8) |
353 1.1 christos ($d & 0xff);
354 1.1 christos
355 1.1 christos for ($i=1; $i<=32 && $num & (1 << (32 - $i)); $i++)
356 1.1 christos {
357 1.1 christos }
358 1.1 christos $i--;
359 1.1 christos
360 1.1 christos return ($i);
361 1.1 christos }
362 1.1 christos
363 1.1 christos
364 1.1 christos sub parse_subnet
365 1.1 christos {
366 1.1 christos local ($ip, $tmp, $netmask);
367 1.1 christos
368 1.1 christos new_entry ();
369 1.1 christos
370 1.1 christos $ip = next_token (0);
371 1.1 christos parse_error () if !defined ($ip);
372 1.1 christos
373 1.1 christos $tmp = next_token (1);
374 1.1 christos parse_error () if !defined ($tmp);
375 1.1 christos parse_error () if !($tmp eq 'netmask');
376 1.1 christos
377 1.1 christos $tmp = next_token (0);
378 1.1 christos parse_error () if !defined ($tmp);
379 1.1 christos $netmask = parse_netmask ($tmp);
380 1.1 christos
381 1.1 christos $tmp = next_token (0);
382 1.1 christos parse_error () if !defined ($tmp);
383 1.1 christos parse_error () if !($tmp eq '{');
384 1.1 christos
385 1.1 christos add_dn_to_stack ("cn=$ip");
386 1.1 christos $curentry{'type'} = 'subnet';
387 1.1 christos $curentry{'ip'} = $ip;
388 1.1 christos $curentry{'netmask'} = $netmask;
389 1.1 christos $cursubnet = $ip;
390 1.1 christos $curcounter{$ip} = { pool => 0, group => 0 };
391 1.1 christos }
392 1.1 christos
393 1.1 christos
394 1.1 christos sub parse_shared_network
395 1.1 christos {
396 1.1 christos local ($descr, $tmp);
397 1.1 christos
398 1.1 christos new_entry ();
399 1.1 christos
400 1.1 christos $descr = next_token (0);
401 1.1 christos parse_error () if !defined ($descr);
402 1.1 christos
403 1.1 christos $tmp = next_token (0);
404 1.1 christos parse_error () if !defined ($tmp);
405 1.1 christos parse_error () if !($tmp eq '{');
406 1.1 christos
407 1.1 christos add_dn_to_stack ("cn=$descr");
408 1.1 christos $curentry{'type'} = 'shared-network';
409 1.1 christos $curentry{'descr'} = $descr;
410 1.1 christos }
411 1.1 christos
412 1.1 christos
413 1.1 christos sub parse_host
414 1.1 christos {
415 1.1 christos local ($descr, $tmp);
416 1.1 christos
417 1.1 christos new_entry ();
418 1.1 christos
419 1.1 christos $host = next_token (0);
420 1.1 christos parse_error () if !defined ($host);
421 1.1 christos
422 1.1 christos $tmp = next_token (0);
423 1.1 christos parse_error () if !defined ($tmp);
424 1.1 christos parse_error () if !($tmp eq '{');
425 1.1 christos
426 1.1 christos add_dn_to_stack ("cn=$host");
427 1.1 christos $curentry{'type'} = 'host';
428 1.1 christos $curentry{'host'} = $host;
429 1.1 christos }
430 1.1 christos
431 1.1 christos
432 1.1 christos sub parse_group
433 1.1 christos {
434 1.1 christos local ($descr, $tmp);
435 1.1 christos
436 1.1 christos new_entry ();
437 1.1 christos
438 1.1 christos $tmp = next_token (0);
439 1.1 christos parse_error () if !defined ($tmp);
440 1.1 christos parse_error () if !($tmp eq '{');
441 1.1 christos
442 1.1 christos my $idx;
443 1.1 christos if(exists($curcounter{$cursubnet})) {
444 1.1 christos $idx = ++$curcounter{$cursubnet}->{'group'};
445 1.1 christos } else {
446 1.1 christos $idx = ++$curcounter{''}->{'group'};
447 1.1 christos }
448 1.1 christos
449 1.1 christos add_dn_to_stack ("cn=group".$idx);
450 1.1 christos $curentry{'type'} = 'group';
451 1.1 christos $curentry{'idx'} = $idx;
452 1.1 christos }
453 1.1 christos
454 1.1 christos
455 1.1 christos sub parse_pool
456 1.1 christos {
457 1.1 christos local ($descr, $tmp);
458 1.1 christos
459 1.1 christos new_entry ();
460 1.1 christos
461 1.1 christos $tmp = next_token (0);
462 1.1 christos parse_error () if !defined ($tmp);
463 1.1 christos parse_error () if !($tmp eq '{');
464 1.1 christos
465 1.1 christos my $idx;
466 1.1 christos if(exists($curcounter{$cursubnet})) {
467 1.1 christos $idx = ++$curcounter{$cursubnet}->{'pool'};
468 1.1 christos } else {
469 1.1 christos $idx = ++$curcounter{''}->{'pool'};
470 1.1 christos }
471 1.1 christos
472 1.1 christos add_dn_to_stack ("cn=pool".$idx);
473 1.1 christos $curentry{'type'} = 'pool';
474 1.1 christos $curentry{'idx'} = $idx;
475 1.1 christos }
476 1.1 christos
477 1.1 christos
478 1.1 christos sub parse_class
479 1.1 christos {
480 1.1 christos local ($descr, $tmp);
481 1.1 christos
482 1.1 christos new_entry ();
483 1.1 christos
484 1.1 christos $class = next_token (0);
485 1.1 christos parse_error () if !defined ($class);
486 1.1 christos
487 1.1 christos $tmp = next_token (0);
488 1.1 christos parse_error () if !defined ($tmp);
489 1.1 christos parse_error () if !($tmp eq '{');
490 1.1 christos
491 1.1 christos $class =~ s/\"//g;
492 1.1 christos add_dn_to_stack ("cn=$class");
493 1.1 christos $curentry{'type'} = 'class';
494 1.1 christos $curentry{'class'} = $class;
495 1.1 christos }
496 1.1 christos
497 1.1 christos
498 1.1 christos sub parse_subclass
499 1.1 christos {
500 1.1 christos local ($descr, $tmp);
501 1.1 christos
502 1.1 christos new_entry ();
503 1.1 christos
504 1.1 christos $class = next_token (0);
505 1.1 christos parse_error () if !defined ($class);
506 1.1 christos
507 1.1 christos $subclass = next_token (0);
508 1.1 christos parse_error () if !defined ($subclass);
509 1.1 christos
510 1.1 christos if (substr($subclass,-1) eq ';') {
511 1.1 christos $tmp = ";";
512 1.1 christos $subclass = substr($subclass,0,-1);
513 1.1 christos } else {
514 1.1 christos $tmp = next_token (0);
515 1.1 christos parse_error () if !defined ($tmp);
516 1.1 christos }
517 1.1 christos parse_error () if !($tmp eq '{' or $tmp eq ';');
518 1.1 christos add_dn_to_stack ("cn=$subclass");
519 1.1 christos $curentry{'type'} = 'subclass';
520 1.1 christos $curentry{'class'} = $class;
521 1.1 christos $curentry{'subclass'} = $subclass;
522 1.1 christos
523 1.1 christos if ($tmp eq ';') {
524 1.1 christos pop_entry ();
525 1.1 christos remove_dn_from_stack ();
526 1.1 christos }
527 1.1 christos }
528 1.1 christos
529 1.1 christos
530 1.1 christos sub parse_hwaddress
531 1.1 christos {
532 1.1 christos local ($type, $hw, $tmp);
533 1.1 christos
534 1.1 christos $type = next_token (1);
535 1.1 christos parse_error () if !defined ($type);
536 1.1 christos
537 1.1 christos $hw = next_token (1);
538 1.1 christos parse_error () if !defined ($hw);
539 1.1 christos $hw =~ s/;$//;
540 1.1 christos
541 1.1 christos $curentry{'hwaddress'} = "$type $hw";
542 1.1 christos }
543 1.1 christos
544 1.1 christos
545 1.1 christos sub parse_range
546 1.1 christos {
547 1.1 christos local ($tmp, $str);
548 1.1 christos
549 1.1 christos $str = remaining_line ();
550 1.1 christos
551 1.1 christos if (!($str eq ''))
552 1.1 christos {
553 1.1 christos $str =~ s/;$//;
554 1.1 christos push (@{$curentry{'ranges'}}, $str);
555 1.1 christos }
556 1.1 christos }
557 1.1 christos
558 1.1 christos
559 1.1 christos sub parse_statement
560 1.1 christos {
561 1.1 christos local ($token) = shift;
562 1.1 christos local ($str);
563 1.1 christos
564 1.1 christos if ($token eq 'option')
565 1.1 christos {
566 1.1 christos $str = remaining_line ();
567 1.1 christos push (@{$curentry{'options'}}, $str);
568 1.1 christos }
569 1.1 christos elsif($token eq 'failover')
570 1.1 christos {
571 1.1 christos $str = remaining_line (1); # take care on block
572 1.1 christos if($str =~ /[{]/)
573 1.1 christos {
574 1.1 christos my ($peername, @statements);
575 1.1 christos
576 1.1 christos parse_error() if($str !~ /^\s*peer\s+(.+?)\s+[{]\s*$/);
577 1.1 christos parse_error() if(($peername = $1) !~ /^\"?[^\"]+\"?$/);
578 1.1 christos
579 1.1 christos #
580 1.1 christos # failover config block found:
581 1.1 christos # e.g. 'failover peer "some-name" {'
582 1.1 christos #
583 1.1 christos if(not grep(/FaIlOvEr/i, @use))
584 1.1 christos {
585 1.1 christos print STDERR "Warning: Failover config 'peer $peername' found!\n";
586 1.1 christos print STDERR " Skipping it, since failover disabled!\n";
587 1.1 christos print STDERR " You may try out --use=failover option.\n";
588 1.1 christos }
589 1.1 christos
590 1.1 christos until($str =~ /[}]/ or $str eq "")
591 1.1 christos {
592 1.1 christos $str = remaining_line (1);
593 1.1 christos # collect all statements, except ending '}'
594 1.1 christos push(@statements, $str) if($str !~ /[}]/);
595 1.1 christos }
596 1.1 christos $failover{$peername} = [@statements];
597 1.1 christos }
598 1.1 christos else
599 1.1 christos {
600 1.1 christos #
601 1.1 christos # pool reference to failover config is fine
602 1.1 christos # e.g. 'failover peer "some-name";'
603 1.1 christos #
604 1.1 christos if(not grep(/FaIlOvEr/i, @use))
605 1.1 christos {
606 1.1 christos print STDERR "Warning: Failover reference '$str' found!\n";
607 1.1 christos print STDERR " Skipping it, since failover disabled!\n";
608 1.1 christos print STDERR " You may try out --use=failover option.\n";
609 1.1 christos }
610 1.1 christos else
611 1.1 christos {
612 1.1 christos push (@{$curentry{'statements'}}, $token. " " . $str);
613 1.1 christos }
614 1.1 christos }
615 1.1 christos }
616 1.1 christos elsif($token eq 'zone')
617 1.1 christos {
618 1.1 christos $str = $token;
619 1.1 christos while($str !~ /}$/) {
620 1.1 christos $str .= ' ' . next_token (0);
621 1.1 christos }
622 1.1 christos push (@{$curentry{'statements'}}, $str);
623 1.1 christos }
624 1.1 christos elsif($token =~ /^(authoritative)[;]*$/)
625 1.1 christos {
626 1.1 christos push (@{$curentry{'statements'}}, $1);
627 1.1 christos }
628 1.1 christos else
629 1.1 christos {
630 1.1 christos $str = $token . " " . remaining_line ();
631 1.1 christos push (@{$curentry{'statements'}}, $str);
632 1.1 christos }
633 1.1 christos }
634 1.1 christos
635 1.1 christos
636 1.1 christos my $ok = GetOptions(
637 1.1 christos 'basedn=s' => \$basedn,
638 1.1 christos 'dhcpdn=s' => \$dhcpdn,
639 1.1 christos 'server=s' => \$server,
640 1.1 christos 'second=s' => \$second,
641 1.1 christos 'conf=s' => \$i_conf,
642 1.1 christos 'ldif=s' => \$o_ldif,
643 1.1 christos 'use=s' => \@use,
644 1.1 christos 'h|help|usage' => sub { usage(0); },
645 1.1 christos );
646 1.1 christos
647 1.1 christos unless($server =~ /^\w+/)
648 1.1 christos {
649 1.1 christos usage(1, "invalid server name '$server'");
650 1.1 christos }
651 1.1 christos unless($basedn =~ /^\w+=[^,]+/)
652 1.1 christos {
653 1.1 christos usage(1, "invalid base dn '$basedn'");
654 1.1 christos }
655 1.1 christos
656 1.1 christos if($dhcpdn =~ /^cn=([^,]+)/i)
657 1.1 christos {
658 1.1 christos $dhcpcn = "$1";
659 1.1 christos }
660 1.1 christos $second = '' if not defined $second;
661 1.1 christos unless($second eq '' or $second =~ /^cn=[^,]+\s*,\s*\w+=[^,]+/i)
662 1.1 christos {
663 1.1 christos if($second =~ /^cn=[^,]+$/i)
664 1.1 christos {
665 1.1 christos # relative DN 'cn=name'
666 1.1 christos $second = "$second, $basedn";
667 1.1 christos }
668 1.1 christos elsif($second =~ /^\w+/)
669 1.1 christos {
670 1.1 christos # assume hostname only
671 1.1 christos $second = "cn=$second, $basedn";
672 1.1 christos }
673 1.1 christos else
674 1.1 christos {
675 1.1 christos usage(1, "invalid secondary '$second'")
676 1.1 christos }
677 1.1 christos }
678 1.1 christos
679 1.1 christos usage(1) unless($ok);
680 1.1 christos
681 1.1 christos if($i_conf ne "" and -f $i_conf)
682 1.1 christos {
683 1.1 christos if(not open(STDIN, '<', $i_conf))
684 1.1 christos {
685 1.1 christos print STDERR "Error: can't open conf file '$i_conf': $!\n";
686 1.1 christos exit(1);
687 1.1 christos }
688 1.1 christos }
689 1.1 christos if($o_ldif ne "")
690 1.1 christos {
691 1.1 christos if(-e $o_ldif)
692 1.1 christos {
693 1.1 christos print STDERR "Error: output ldif name '$o_ldif' already exists!\n";
694 1.1 christos exit(1);
695 1.1 christos }
696 1.1 christos if(not open(STDOUT, '>', $o_ldif))
697 1.1 christos {
698 1.1 christos print STDERR "Error: can't open ldif file '$o_ldif': $!\n";
699 1.1 christos exit(1);
700 1.1 christos }
701 1.1 christos }
702 1.1 christos
703 1.1 christos
704 1.1 christos print STDERR "Creating LDAP Configuration with the following options:\n";
705 1.1 christos print STDERR "\tBase DN: $basedn\n";
706 1.1 christos print STDERR "\tDHCP DN: $dhcpdn\n";
707 1.1 christos print STDERR "\tServer DN: cn=$server, $basedn\n";
708 1.1 christos print STDERR "\tSecondary DN: $second\n"
709 1.1 christos if(grep(/FaIlOvEr/i, @use) and $second ne '');
710 1.1 christos print STDERR "\n";
711 1.1 christos
712 1.1 christos my $token;
713 1.1 christos my $token_number = 0;
714 1.1 christos my $line_number = 0;
715 1.1 christos my $cursubnet = '';
716 1.1 christos my %curcounter = ( '' => { pool => 0, group => 0 } );
717 1.1 christos
718 1.1 christos $current_dn = "$dhcpdn";
719 1.1 christos $curentry{'current_dn'} = $current_dn;
720 1.1 christos $curentry{'descr'} = $dhcpcn;
721 1.1 christos $line = '';
722 1.1 christos %failover = ();
723 1.1 christos
724 1.1 christos while (($token = next_token (1)))
725 1.1 christos {
726 1.1 christos if ($token eq '}')
727 1.1 christos {
728 1.1 christos pop_entry ();
729 1.1 christos if($current_dn =~ /.+?,\s*${dhcpdn}$/) {
730 1.1 christos # don't go below dhcpdn ...
731 1.1 christos remove_dn_from_stack ();
732 1.1 christos }
733 1.1 christos }
734 1.1 christos elsif ($token eq 'subnet')
735 1.1 christos {
736 1.1 christos parse_subnet ();
737 1.1 christos next;
738 1.1 christos }
739 1.1 christos elsif ($token eq 'shared-network')
740 1.1 christos {
741 1.1 christos parse_shared_network ();
742 1.1 christos next;
743 1.1 christos }
744 1.1 christos elsif ($token eq 'class')
745 1.1 christos {
746 1.1 christos parse_class ();
747 1.1 christos next;
748 1.1 christos }
749 1.1 christos elsif ($token eq 'subclass')
750 1.1 christos {
751 1.1 christos parse_subclass ();
752 1.1 christos next;
753 1.1 christos }
754 1.1 christos elsif ($token eq 'pool')
755 1.1 christos {
756 1.1 christos parse_pool ();
757 1.1 christos next;
758 1.1 christos }
759 1.1 christos elsif ($token eq 'group')
760 1.1 christos {
761 1.1 christos parse_group ();
762 1.1 christos next;
763 1.1 christos }
764 1.1 christos elsif ($token eq 'host')
765 1.1 christos {
766 1.1 christos parse_host ();
767 1.1 christos next;
768 1.1 christos }
769 1.1 christos elsif ($token eq 'hardware')
770 1.1 christos {
771 1.1 christos parse_hwaddress ();
772 1.1 christos next;
773 1.1 christos }
774 1.1 christos elsif ($token eq 'range')
775 1.1 christos {
776 1.1 christos parse_range ();
777 1.1 christos next;
778 1.1 christos }
779 1.1 christos else
780 1.1 christos {
781 1.1 christos parse_statement ($token);
782 1.1 christos next;
783 1.1 christos }
784 1.1 christos }
785 1.1 christos
786 1.1 christos pop_entry ();
787 1.1 christos
788 1.1 christos while ($#outputlist >= 0) {
789 1.1 christos $rentry = pop(@outputlist);
790 1.1 christos if ($rentry) {
791 1.1 christos %curentry = %$rentry;
792 1.1 christos print_entry ();
793 1.1 christos }
794 1.1 christos }
795 1.1 christos
796 1.1 christos close(STDIN) if($i_conf);
797 1.1 christos close(STDOUT) if($o_ldif);
798 1.1 christos
799 1.1 christos print STDERR "Done.\n";
800 1.1 christos
801