Import initial version of 1:1 pthread library.
[dragonfly.git] / contrib / dhcp-3.0 / server / confpars.c
1 /* confpars.c
2
3    Parser for dhcpd config file... */
4
5 /*
6  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  *   Internet Systems Consortium, Inc.
22  *   950 Charter Street
23  *   Redwood City, CA 94063
24  *   <info@isc.org>
25  *   http://www.isc.org/
26  *
27  * This software has been written for Internet Systems Consortium
28  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29  * To learn more about Internet Systems Consortium, see
30  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
31  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
32  * ``http://www.nominum.com''.
33  */
34
35 #ifndef lint
36 static char copyright[] =
37 "$Id: confpars.c,v 1.143.2.24 2004/11/24 17:39:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41
42 static TIME parsed_time;
43
44 #if defined (TRACING)
45 trace_type_t *trace_readconf_type;
46 trace_type_t *trace_readleases_type;
47
48 void parse_trace_setup ()
49 {
50         trace_readconf_type = trace_type_register ("readconf", (void *)0,
51                                                    trace_conf_input,
52                                                    trace_conf_stop, MDL);
53         trace_readleases_type = trace_type_register ("readleases", (void *)0,
54                                                      trace_conf_input,
55                                                      trace_conf_stop, MDL);
56 }
57 #endif
58
59 /* conf-file :== parameters declarations END_OF_FILE
60    parameters :== <nil> | parameter | parameters parameter
61    declarations :== <nil> | declaration | declarations declaration */
62
63 isc_result_t readconf ()
64 {
65         return read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
66 }
67
68 isc_result_t read_conf_file (const char *filename, struct group *group,
69                              int group_type, int leasep)
70 {
71         int file;
72         struct parse *cfile;
73         isc_result_t status;
74 #if defined (TRACING)
75         char *fbuf, *dbuf;
76         off_t flen;
77         int result;
78         unsigned tflen, ulen;
79         trace_type_t *ttype;
80
81         if (leasep)
82                 ttype = trace_readleases_type;
83         else
84                 ttype = trace_readconf_type;
85
86         /* If we're in playback, we need to snarf the contents of the
87            named file out of the playback file rather than trying to
88            open and read it. */
89         if (trace_playback ()) {
90                 dbuf = (char *)0;
91                 tflen = 0;
92                 status = trace_get_file (ttype, filename, &tflen, &dbuf);
93                 if (status != ISC_R_SUCCESS)
94                         return status;
95                 ulen = tflen;
96
97                 /* What we get back is filename\0contents, where contents is
98                    terminated just by the length.  So we figure out the length
99                    of the filename, and subtract that and the NUL from the
100                    total length to get the length of the contents of the file.
101                    We make fbuf a pointer to the contents of the file, and
102                    leave dbuf as it is so we can free it later. */
103                 tflen = strlen (dbuf);
104                 ulen = ulen - tflen - 1;
105                 fbuf = dbuf + tflen + 1;
106                 goto memfile;
107         }
108 #endif
109
110         if ((file = open (filename, O_RDONLY)) < 0) {
111                 if (leasep) {
112                         log_error ("Can't open lease database %s: %m --",
113                                    path_dhcpd_db);
114                         log_error ("  check for failed database %s!",
115                                    "rewrite attempt");
116                         log_error ("Please read the dhcpd.leases manual%s",
117                                    " page if you");
118                         log_fatal ("don't know what to do about this.");
119                 } else {
120                         log_fatal ("Can't open %s: %m", filename);
121                 }
122         }
123
124         cfile = (struct parse *)0;
125 #if defined (TRACING)
126         flen = lseek (file, (off_t)0, SEEK_END);
127         if (flen < 0) {
128               boom:
129                 log_fatal ("Can't lseek on %s: %m", filename);
130         }
131         if (lseek (file, (off_t)0, SEEK_SET) < 0)
132                 goto boom;
133         /* Can't handle files greater than 2^31-1. */
134         if (flen > 0x7FFFFFFFUL)
135                 log_fatal ("%s: file is too long to buffer.", filename);
136         ulen = flen;
137
138         /* Allocate a buffer that will be what's written to the tracefile,
139            and also will be what we parse from. */
140         tflen = strlen (filename);
141         dbuf = dmalloc (ulen + tflen + 1, MDL);
142         if (!dbuf)
143                 log_fatal ("No memory for %s (%d bytes)",
144                            filename, ulen);
145
146         /* Copy the name into the beginning, nul-terminated. */
147         strcpy (dbuf, filename);
148
149         /* Load the file in after the NUL. */
150         fbuf = dbuf + tflen + 1;
151         result = read (file, fbuf, ulen);
152         if (result < 0)
153                 log_fatal ("Can't read in %s: %m", filename);
154         if (result != ulen)
155                 log_fatal ("%s: short read of %d bytes instead of %d.",
156                            filename, ulen, result);
157         close (file);
158       memfile:
159         /* If we're recording, write out the filename and file contents. */
160         if (trace_record ())
161                 trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL);
162         new_parse (&cfile, -1, fbuf, ulen, filename, 0); /* XXX */
163 #else
164         new_parse (&cfile, file, (char *)0, 0, filename, 0);
165         close (file);
166 #endif
167         if (leasep)
168                 status = lease_file_subparse (cfile);
169         else
170                 status = conf_file_subparse (cfile, group, group_type);
171         end_parse (&cfile);
172 #if defined (TRACING)
173         dfree (dbuf, MDL);
174 #endif
175         return status;
176 }
177
178 #if defined (TRACING)
179 void trace_conf_input (trace_type_t *ttype, unsigned len, char *data)
180 {
181         char *fbuf;
182         unsigned flen;
183         unsigned tflen;
184         struct parse *cfile = (struct parse *)0;
185         static int postconf_initialized;
186         static int leaseconf_initialized;
187         
188         /* Do what's done above, except that we don't have to read in the
189            data, because it's already been read for us. */
190         tflen = strlen (data);
191         flen = len - tflen - 1;
192         fbuf = data + tflen + 1;
193
194         /* If we're recording, write out the filename and file contents. */
195         if (trace_record ())
196                 trace_write_packet (ttype, len, data, MDL);
197         new_parse (&cfile, -1, fbuf, flen, data, 0);
198         if (ttype == trace_readleases_type)
199                 lease_file_subparse (cfile);
200         else
201                 conf_file_subparse (cfile, root_group, ROOT_GROUP);
202         end_parse (&cfile);
203
204         /* Postconfiguration needs to be done after the config file
205            has been loaded. */
206         if (!postconf_initialized && ttype == trace_readconf_type) {
207                 postconf_initialization (0);
208                 postconf_initialized = 1;
209         }
210
211         if (!leaseconf_initialized && ttype == trace_readleases_type) {
212                 db_startup (0);
213                 leaseconf_initialized = 1;
214                 postdb_startup ();
215         }
216 }
217
218 void trace_conf_stop (trace_type_t *ttype) { }
219 #endif
220
221 /* conf-file :== parameters declarations END_OF_FILE
222    parameters :== <nil> | parameter | parameters parameter
223    declarations :== <nil> | declaration | declarations declaration */
224
225 isc_result_t conf_file_subparse (struct parse *cfile, struct group *group,
226                                  int group_type)
227 {
228         const char *val;
229         enum dhcp_token token;
230         int declaration = 0;
231         int status;
232
233         do {
234                 token = peek_token (&val, (unsigned *)0, cfile);
235                 if (token == END_OF_FILE)
236                         break;
237                 declaration = parse_statement (cfile, group, group_type,
238                                                (struct host_decl *)0,
239                                                declaration);
240         } while (1);
241         token = next_token (&val, (unsigned *)0, cfile);
242
243         status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS;
244         return status;
245 }
246
247 /* lease-file :== lease-declarations END_OF_FILE
248    lease-statments :== <nil>
249                      | lease-declaration
250                      | lease-declarations lease-declaration */
251
252 isc_result_t lease_file_subparse (struct parse *cfile)
253 {
254         const char *val;
255         enum dhcp_token token;
256         isc_result_t status;
257
258         do {
259                 token = next_token (&val, (unsigned *)0, cfile);
260                 if (token == END_OF_FILE)
261                         break;
262                 if (token == LEASE) {
263                         struct lease *lease = (struct lease *)0;
264                         if (parse_lease_declaration (&lease, cfile)) {
265                                 enter_lease (lease);
266                                 lease_dereference (&lease, MDL);
267                         } else
268                                 parse_warn (cfile,
269                                             "possibly corrupt lease file");
270                 } else if (token == HOST) {
271                         parse_host_declaration (cfile, root_group);
272                 } else if (token == GROUP) {
273                         parse_group_declaration (cfile, root_group);
274 #if defined (FAILOVER_PROTOCOL)
275                 } else if (token == FAILOVER) {
276                         parse_failover_state_declaration
277                                 (cfile, (dhcp_failover_state_t *)0);
278 #endif
279                 } else {
280                         log_error ("Corrupt lease file - possible data loss!");
281                         skip_to_semi (cfile);
282                 }
283
284         } while (1);
285
286         status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS;
287         return status;
288 }
289
290 /* statement :== parameter | declaration
291
292    parameter :== timestamp
293                | DEFAULT_LEASE_TIME lease_time
294                | MAX_LEASE_TIME lease_time
295                | DYNAMIC_BOOTP_LEASE_CUTOFF date
296                | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
297                | BOOT_UNKNOWN_CLIENTS boolean
298                | ONE_LEASE_PER_CLIENT boolean
299                | GET_LEASE_HOSTNAMES boolean
300                | USE_HOST_DECL_NAME boolean
301                | NEXT_SERVER ip-addr-or-hostname SEMI
302                | option_parameter
303                | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
304                | FILENAME string-parameter
305                | SERVER_NAME string-parameter
306                | hardware-parameter
307                | fixed-address-parameter
308                | ALLOW allow-deny-keyword
309                | DENY allow-deny-keyword
310                | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
311                | AUTHORITATIVE
312                | NOT AUTHORITATIVE
313
314    declaration :== host-declaration
315                  | group-declaration
316                  | shared-network-declaration
317                  | subnet-declaration
318                  | VENDOR_CLASS class-declaration
319                  | USER_CLASS class-declaration
320                  | RANGE address-range-declaration */
321
322 int parse_statement (cfile, group, type, host_decl, declaration)
323         struct parse *cfile;
324         struct group *group;
325         int type;
326         struct host_decl *host_decl;
327         int declaration;
328 {
329         enum dhcp_token token;
330         const char *val;
331         struct shared_network *share;
332         char *t, *n;
333         struct expression *expr;
334         struct data_string data;
335         struct hardware hardware;
336         struct executable_statement *et, *ep;
337         struct option *option;
338         struct option_cache *cache;
339         int lose;
340         struct data_string key_id;
341         int known;
342         isc_result_t status;
343
344         token = peek_token (&val, (unsigned *)0, cfile);
345
346         switch (token) {
347               case INCLUDE:
348                 next_token (&val, (unsigned *)0, cfile);
349                 token = next_token (&val, (unsigned *)0, cfile);
350                 if (token != STRING) {
351                         parse_warn (cfile, "filename string expected.");
352                         skip_to_semi (cfile);
353                 } else {
354                         status = read_conf_file (val, group, type, 0);
355                         if (status != ISC_R_SUCCESS)
356                                 parse_warn (cfile, "%s: bad parse.", val);
357                         parse_semi (cfile);
358                 }
359                 return 1;
360                 
361               case HOST:
362                 next_token (&val, (unsigned *)0, cfile);
363                 if (type != HOST_DECL && type != CLASS_DECL)
364                         parse_host_declaration (cfile, group);
365                 else {
366                         parse_warn (cfile,
367                                     "host declarations not allowed here.");
368                         skip_to_semi (cfile);
369                 }
370                 return 1;
371
372               case GROUP:
373                 next_token (&val, (unsigned *)0, cfile);
374                 if (type != HOST_DECL && type != CLASS_DECL)
375                         parse_group_declaration (cfile, group);
376                 else {
377                         parse_warn (cfile,
378                                     "group declarations not allowed here.");
379                         skip_to_semi (cfile);
380                 }
381                 return 1;
382
383               case TIMESTAMP:
384                 next_token (&val, (unsigned *)0, cfile);
385                 parsed_time = parse_timestamp (cfile);
386                 break;
387
388               case SHARED_NETWORK:
389                 next_token (&val, (unsigned *)0, cfile);
390                 if (type == SHARED_NET_DECL ||
391                     type == HOST_DECL ||
392                     type == SUBNET_DECL ||
393                     type == CLASS_DECL) {
394                         parse_warn (cfile, "shared-network parameters not %s.",
395                                     "allowed here");
396                         skip_to_semi (cfile);
397                         break;
398                 }
399
400                 parse_shared_net_declaration (cfile, group);
401                 return 1;
402
403               case SUBNET:
404                 next_token (&val, (unsigned *)0, cfile);
405                 if (type == HOST_DECL || type == SUBNET_DECL ||
406                     type == CLASS_DECL) {
407                         parse_warn (cfile,
408                                     "subnet declarations not allowed here.");
409                         skip_to_semi (cfile);
410                         return 1;
411                 }
412
413                 /* If we're in a subnet declaration, just do the parse. */
414                 if (group -> shared_network) {
415                         parse_subnet_declaration (cfile,
416                                                   group -> shared_network);
417                         break;
418                 }
419
420                 /* Otherwise, cons up a fake shared network structure
421                    and populate it with the lone subnet... */
422
423                 share = (struct shared_network *)0;
424                 status = shared_network_allocate (&share, MDL);
425                 if (status != ISC_R_SUCCESS)
426                         log_fatal ("Can't allocate shared subnet: %s",
427                                    isc_result_totext (status));
428                 if (!clone_group (&share -> group, group, MDL))
429                         log_fatal ("Can't allocate group for shared net");
430                 shared_network_reference (&share -> group -> shared_network,
431                                           share, MDL);
432
433                 parse_subnet_declaration (cfile, share);
434
435                 /* share -> subnets is the subnet we just parsed. */
436                 if (share -> subnets) {
437                         interface_reference (&share -> interface,
438                                              share -> subnets -> interface,
439                                              MDL);
440
441                         /* Make the shared network name from network number. */
442                         n = piaddrmask (share -> subnets -> net,
443                                         share -> subnets -> netmask, MDL);
444                         share -> name = n;
445
446                         /* Copy the authoritative parameter from the subnet,
447                            since there is no opportunity to declare it here. */
448                         share -> group -> authoritative =
449                                 share -> subnets -> group -> authoritative;
450                         enter_shared_network (share);
451                 }
452                 shared_network_dereference (&share, MDL);
453                 return 1;
454
455               case VENDOR_CLASS:
456                 next_token (&val, (unsigned *)0, cfile);
457                 if (type == CLASS_DECL) {
458                         parse_warn (cfile,
459                                     "class declarations not allowed here.");
460                         skip_to_semi (cfile);
461                         break;
462                 }
463                 parse_class_declaration ((struct class **)0, cfile, group, 0);
464                 return 1;
465
466               case USER_CLASS:
467                 next_token (&val, (unsigned *)0, cfile);
468                 if (type == CLASS_DECL) {
469                         parse_warn (cfile,
470                                     "class declarations not allowed here.");
471                         skip_to_semi (cfile);
472                         break;
473                 }
474                 parse_class_declaration ((struct class **)0, cfile, group, 1);
475                 return 1;
476
477               case CLASS:
478                 next_token (&val, (unsigned *)0, cfile);
479                 if (type == CLASS_DECL) {
480                         parse_warn (cfile,
481                                     "class declarations not allowed here.");
482                         skip_to_semi (cfile);
483                         break;
484                 }
485                 parse_class_declaration ((struct class **)0, cfile, group, 2);
486                 return 1;
487
488               case SUBCLASS:
489                 next_token (&val, (unsigned *)0, cfile);
490                 if (type == CLASS_DECL) {
491                         parse_warn (cfile,
492                                     "class declarations not allowed here.");
493                         skip_to_semi (cfile);
494                         break;
495                 }
496                 parse_class_declaration ((struct class **)0, cfile, group, 3);
497                 return 1;
498
499               case HARDWARE:
500                 next_token (&val, (unsigned *)0, cfile);
501                 memset (&hardware, 0, sizeof hardware);
502                 parse_hardware_param (cfile, &hardware);
503                 if (host_decl)
504                         host_decl -> interface = hardware;
505                 else
506                         parse_warn (cfile, "hardware address parameter %s",
507                                     "not allowed here.");
508                 break;
509
510               case FIXED_ADDR:
511                 next_token (&val, (unsigned *)0, cfile);
512                 cache = (struct option_cache *)0;
513                 if (parse_fixed_addr_param (&cache, cfile)) {
514                         if (host_decl) {
515                                 if (host_decl -> fixed_addr) {
516                                         option_cache_dereference (&cache, MDL);
517                                         parse_warn (cfile,
518                                                     "Only one fixed address%s",
519                                                     " declaration per host.");
520                                 } else {
521                                         host_decl -> fixed_addr = cache;
522                                 }
523                         } else {
524                                 parse_warn (cfile,
525                                             "fixed-address parameter not %s",
526                                             "allowed here.");
527                                 option_cache_dereference (&cache, MDL);
528                         }
529                 }
530                 break;
531
532               case POOL:
533                 next_token (&val, (unsigned *)0, cfile);
534                 if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
535                         parse_warn (cfile, "pool declared outside of network");
536                 }
537                 if (type == POOL_DECL) {
538                         parse_warn (cfile, "pool declared within pool.");
539                 }
540                 parse_pool_statement (cfile, group, type);
541                 return declaration;
542
543               case RANGE:
544                 next_token (&val, (unsigned *)0, cfile);
545                 if (type != SUBNET_DECL || !group -> subnet) {
546                         parse_warn (cfile,
547                                     "range declaration not allowed here.");
548                         skip_to_semi (cfile);
549                         return declaration;
550                 }
551                 parse_address_range (cfile, group, type, (struct pool *)0,
552                                      (struct lease **)0);
553                 return declaration;
554
555               case TOKEN_NOT:
556                 token = next_token (&val, (unsigned *)0, cfile);
557                 token = next_token (&val, (unsigned *)0, cfile);
558                 switch (token) {
559                       case AUTHORITATIVE:
560                         group -> authoritative = 0;
561                         goto authoritative;
562                       default:
563                         parse_warn (cfile, "expecting assertion");
564                         skip_to_semi (cfile);
565                         break;
566                 }
567                 break;
568               case AUTHORITATIVE:
569                 token = next_token (&val, (unsigned *)0, cfile);
570                 group -> authoritative = 1;
571               authoritative:
572                 if (type == HOST_DECL)
573                         parse_warn (cfile, "authority makes no sense here."); 
574                 parse_semi (cfile);
575                 break;
576
577                 /* "server-identifier" is a special hack, equivalent to
578                    "option dhcp-server-identifier". */
579               case SERVER_IDENTIFIER:
580                 option = dhcp_universe.options [DHO_DHCP_SERVER_IDENTIFIER];
581                 token = next_token (&val, (unsigned *)0, cfile);
582                 goto finish_option;
583
584               case OPTION:
585                 token = next_token (&val, (unsigned *)0, cfile);
586                 token = peek_token (&val, (unsigned *)0, cfile);
587                 if (token == SPACE) {
588                         if (type != ROOT_GROUP) {
589                                 parse_warn (cfile,
590                                             "option space definitions %s",
591                                             "may not be scoped.");
592                                 skip_to_semi (cfile);
593                                 break;
594                         }
595                         parse_option_space_decl (cfile);
596                         return declaration;
597                 }
598
599                 known = 0;
600                 option = parse_option_name (cfile, 1, &known);
601                 if (option) {
602                         token = peek_token (&val, (unsigned *)0, cfile);
603                         if (token == CODE) {
604                                 if (type != ROOT_GROUP) {
605                                         parse_warn (cfile,
606                                                     "option definitions%s",
607                                                     " may not be scoped.");
608                                         skip_to_semi (cfile);
609                                         free_option (option, MDL);
610                                         break;
611                                 }
612                                 next_token (&val, (unsigned *)0, cfile);
613                                 if (!parse_option_code_definition (cfile,
614                                                                    option))
615                                         free_option (option, MDL);
616                                 return declaration;
617                         }
618
619                         /* If this wasn't an option code definition, don't
620                            allow an unknown option. */
621                         if (!known) {
622                                 parse_warn (cfile, "unknown option %s.%s",
623                                             option -> universe -> name,
624                                             option -> name);
625                                 skip_to_semi (cfile);
626                                 free_option (option, MDL);
627                                 return declaration;
628                         }
629
630                       finish_option:
631                         et = (struct executable_statement *)0;
632                         if (!parse_option_statement
633                                 (&et, cfile, 1, option,
634                                  supersede_option_statement))
635                                 return declaration;
636                         goto insert_statement;
637                 } else
638                         return declaration;
639
640                 break;
641
642               case FAILOVER:
643                 if (type != ROOT_GROUP && type != SHARED_NET_DECL) {
644                         parse_warn (cfile, "failover peers may only be %s",
645                                     "defined in shared-network");
646                         log_error ("declarations and the outer scope.");
647                         skip_to_semi (cfile);
648                         break;
649                 }
650                 token = next_token (&val, (unsigned *)0, cfile);
651 #if defined (FAILOVER_PROTOCOL)
652                 parse_failover_peer (cfile, group, type);
653 #else
654                 parse_warn (cfile, "No failover support.");
655                 skip_to_semi (cfile);
656 #endif
657                 break;
658
659               default:
660                 et = (struct executable_statement *)0;
661                 lose = 0;
662                 if (!parse_executable_statement (&et, cfile, &lose,
663                                                  context_any)) {
664                         if (!lose) {
665                                 if (declaration)
666                                         parse_warn (cfile,
667                                                     "expecting a declaration");
668                                 else
669                                         parse_warn (cfile,
670                                                     "expecting a parameter %s",
671                                                     "or declaration");
672                                 skip_to_semi (cfile);
673                         }
674                         return declaration;
675                 }
676                 if (!et)
677                         return declaration;
678               insert_statement:
679                 if (group -> statements) {
680                         int multi = 0;
681
682                         /* If this set of statements is only referenced
683                            by this group, just add the current statement
684                            to the end of the chain. */
685                         for (ep = group -> statements; ep -> next;
686                              ep = ep -> next)
687                                 if (ep -> refcnt > 1) /* XXX */
688                                         multi = 1;
689                         if (!multi) {
690                                 executable_statement_reference (&ep -> next,
691                                                                 et, MDL);
692                                 executable_statement_dereference (&et, MDL);
693                                 return declaration;
694                         }
695
696                         /* Otherwise, make a parent chain, and put the
697                            current group statements first and the new
698                            statement in the next pointer. */
699                         ep = (struct executable_statement *)0;
700                         if (!executable_statement_allocate (&ep, MDL))
701                                 log_fatal ("No memory for statements.");
702                         ep -> op = statements_statement;
703                         executable_statement_reference (&ep -> data.statements,
704                                                         group -> statements,
705                                                         MDL);
706                         executable_statement_reference (&ep -> next, et, MDL);
707                         executable_statement_dereference (&group -> statements,
708                                                           MDL);
709                         executable_statement_reference (&group -> statements,
710                                                         ep, MDL);
711                         executable_statement_dereference (&ep, MDL);
712                 } else {
713                         executable_statement_reference (&group -> statements,
714                                                         et, MDL);
715                 }
716                 executable_statement_dereference (&et, MDL);
717                 return declaration;
718         }
719
720         return 0;
721 }
722
723 #if defined (FAILOVER_PROTOCOL)
724 void parse_failover_peer (cfile, group, type)
725         struct parse *cfile;
726         struct group *group;
727         int type;
728 {
729         enum dhcp_token token;
730         const char *val;
731         dhcp_failover_state_t *peer;
732         u_int32_t *tp;
733         char *name;
734         u_int32_t split;
735         u_int8_t hba [32];
736         unsigned hba_len = sizeof hba;
737         int i;
738         struct expression *expr;
739         isc_result_t status;
740         dhcp_failover_config_t *cp;
741
742         token = next_token (&val, (unsigned *)0, cfile);
743         if (token != PEER) {
744                 parse_warn (cfile, "expecting \"peer\"");
745                 skip_to_semi (cfile);
746                 return;
747         }
748
749         token = next_token (&val, (unsigned *)0, cfile);
750         if (is_identifier (token) || token == STRING) {
751                 name = dmalloc (strlen (val) + 1, MDL);
752                 if (!name)
753                         log_fatal ("no memory for peer name %s", name);
754                 strcpy (name, val);
755         } else {
756                 parse_warn (cfile, "expecting failover peer name.");
757                 skip_to_semi (cfile);
758                 return;
759         }
760
761         /* See if there's a peer declaration by this name. */
762         peer = (dhcp_failover_state_t *)0;
763         find_failover_peer (&peer, name, MDL);
764
765         token = next_token (&val, (unsigned *)0, cfile);
766         if (token == SEMI) {
767                 dfree (name, MDL);
768                 if (type != SHARED_NET_DECL)
769                         parse_warn (cfile, "failover peer reference not %s",
770                                     "in shared-network declaration");
771                 else {
772                         if (!peer) {
773                                 parse_warn (cfile, "reference to unknown%s%s",
774                                             " failover peer ", name);
775                                 return;
776                         }
777                         dhcp_failover_state_reference
778                                 (&group -> shared_network -> failover_peer,
779                                  peer, MDL);
780                 }
781                 dhcp_failover_state_dereference (&peer, MDL);
782                 return;
783         } else if (token == STATE) {
784                 if (!peer) {
785                         parse_warn (cfile, "state declaration for unknown%s%s",
786                                     " failover peer ", name);
787                         return;
788                 }
789                 parse_failover_state_declaration (cfile, peer);
790                 dhcp_failover_state_dereference (&peer, MDL);
791                 return;
792         } else if (token != LBRACE) {
793                 parse_warn (cfile, "expecting left brace");
794                 skip_to_semi (cfile);
795         }
796
797         /* Make sure this isn't a redeclaration. */
798         if (peer) {
799                 parse_warn (cfile, "redeclaration of failover peer %s", name);
800                 skip_to_rbrace (cfile, 1);
801                 dhcp_failover_state_dereference (&peer, MDL);
802                 return;
803         }
804
805         status = dhcp_failover_state_allocate (&peer, MDL);
806         if (status != ISC_R_SUCCESS)
807                 log_fatal ("Can't allocate failover peer %s: %s",
808                            name, isc_result_totext (status));
809
810         /* Save the name. */
811         peer -> name = name;
812
813         do {
814                 cp = &peer -> me;
815               peer:
816                 token = next_token (&val, (unsigned *)0, cfile);
817                 switch (token) {
818                       case RBRACE:
819                         break;
820
821                       case PRIMARY:
822                         peer -> i_am = primary;
823                         break;
824
825                       case SECONDARY:
826                         peer -> i_am = secondary;
827                         if (peer -> hba)
828                                 parse_warn (cfile,
829                                             "secondary may not define %s",
830                                             "load balance settings.");
831                         break;
832
833                       case PEER:
834                         cp = &peer -> partner;
835                         goto peer;
836
837                       case ADDRESS:
838                         expr = (struct expression *)0;
839                         if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
840                                 skip_to_rbrace (cfile, 1);
841                                 dhcp_failover_state_dereference (&peer, MDL);
842                                 return;
843                         }
844                         option_cache (&cp -> address,
845                                       (struct data_string *)0, expr,
846                                       (struct option *)0, MDL);
847                         expression_dereference (&expr, MDL);
848                         break;
849
850                       case PORT:
851                         token = next_token (&val, (unsigned *)0, cfile);
852                         if (token != NUMBER) {
853                                 parse_warn (cfile, "expecting number");
854                                 skip_to_rbrace (cfile, 1);
855                         }
856                         cp -> port = atoi (val);
857                         break;
858
859                       case MAX_RESPONSE_DELAY:
860                         tp = &cp -> max_response_delay;
861                       parse_idle:
862                         token = next_token (&val, (unsigned *)0, cfile);
863                         if (token != NUMBER) {
864                                 parse_warn (cfile, "expecting number.");
865                                 skip_to_rbrace (cfile, 1);
866                                 dhcp_failover_state_dereference (&peer, MDL);
867                                 return;
868                         }
869                         *tp = atoi (val);
870                         break;
871
872                       case MAX_UNACKED_UPDATES:
873                         tp = &cp -> max_flying_updates;
874                         goto parse_idle;
875
876                       case MCLT:
877                         tp = &peer -> mclt;
878                         goto parse_idle;
879
880                       case HBA:
881                         hba_len = 32;
882                         if (peer -> i_am == secondary)
883                                 parse_warn (cfile,
884                                             "secondary may not define %s",
885                                             "load balance settings.");
886                         if (!parse_numeric_aggregate (cfile, hba, &hba_len,
887                                                       COLON, 16, 8)) {
888                                 skip_to_rbrace (cfile, 1);
889                                 dhcp_failover_state_dereference (&peer, MDL);
890                                 return;
891                         }
892                         if (hba_len != 32) {
893                                 parse_warn (cfile,
894                                             "HBA must be exactly 32 bytes.");
895                                 dfree (hba, MDL);
896                                 break;
897                         }
898                       make_hba:
899                         peer -> hba = dmalloc (32, MDL);
900                         if (!peer -> hba) {
901                                 dfree (peer -> name, MDL);
902                                 dfree (peer, MDL);
903                         }
904                         memcpy (peer -> hba, hba, 32);
905                         break;
906
907                       case SPLIT:
908                         token = next_token (&val, (unsigned *)0, cfile);
909                         if (peer -> i_am == secondary)
910                                 parse_warn (cfile,
911                                             "secondary may not define %s",
912                                             "load balance settings.");
913                         if (token != NUMBER) {
914                                 parse_warn (cfile, "expecting number");
915                               badsplit:
916                                 skip_to_rbrace (cfile, 1);
917                                 dhcp_failover_state_dereference (&peer, MDL);
918                                 return;
919                         }
920                         split = atoi (val);
921                         if (split > 255) {
922                                 parse_warn (cfile, "split must be < 256");
923                         } else {
924                                 memset (hba, 0, sizeof hba);
925                                 for (i = 0; i < split; i++) {
926                                         if (i < split)
927                                                 hba [i / 8] |= (1 << (i & 7));
928                                 }
929                                 goto make_hba;
930                         }
931                         break;
932                         
933                       case LOAD:
934                         token = next_token (&val, (unsigned *)0, cfile);
935                         if (token != BALANCE) {
936                                 parse_warn (cfile, "expecting 'balance'");
937                               badload:
938                                 skip_to_rbrace (cfile, 1);
939                                 break;
940                         }
941                         token = next_token (&val, (unsigned *)0, cfile);
942                         if (token != TOKEN_MAX) {
943                                 parse_warn (cfile, "expecting 'max'");
944                                 goto badload;
945                         }
946                         token = next_token (&val, (unsigned *)0, cfile);
947                         if (token != SECONDS) {
948                                 parse_warn (cfile, "expecting 'secs'");
949                                 goto badload;
950                         }
951                         token = next_token (&val, (unsigned *)0, cfile);
952                         if (token != NUMBER) {
953                                 parse_warn (cfile, "expecting number");
954                                 goto badload;
955                         }
956                         peer -> load_balance_max_secs = atoi (val);
957                         break;
958                         
959                       default:
960                         parse_warn (cfile,
961                                     "invalid statement in peer declaration");
962                         skip_to_rbrace (cfile, 1);
963                         dhcp_failover_state_dereference (&peer, MDL);
964                         return;
965                 }
966                 if (token != RBRACE && !parse_semi (cfile)) {
967                         skip_to_rbrace (cfile, 1);
968                         dhcp_failover_state_dereference (&peer, MDL);
969                         return;
970                 }
971         } while (token != RBRACE);
972
973         /* me.address can be null; the failover link initiate code tries to
974          * derive a reasonable address to use.
975          */
976         if (!peer -> partner.address)
977                 parse_warn (cfile, "peer address may not be omitted");
978
979         /* XXX - when/if we get a port number assigned, just set as default */
980         if (!peer -> me.port)
981                 parse_warn (cfile, "local port may not be omitted");
982         if (!peer -> partner.port)
983                 parse_warn (cfile, "peer port may not be omitted");
984
985         if (peer -> i_am == primary) {
986             if (!peer -> hba) {
987                 parse_warn (cfile,
988                             "primary failover server must have hba or split.");
989             } else if (!peer -> mclt) {
990                 parse_warn (cfile,
991                             "primary failover server must have mclt.");
992             }
993         }
994         if (!peer -> me.max_flying_updates) {
995                 peer -> me.max_flying_updates = 100;
996         }
997         if (!peer -> me.max_response_delay) {
998                 peer -> me.max_response_delay = 60;
999         }
1000
1001         if (type == SHARED_NET_DECL) {
1002                 group -> shared_network -> failover_peer = peer;
1003         }
1004
1005         /* Set the initial state. */
1006         if (peer -> i_am == primary) {
1007                 peer -> me.state = recover;
1008                 peer -> me.stos = cur_time;
1009                 peer -> partner.state = unknown_state;
1010                 peer -> partner.stos = cur_time;
1011         } else {
1012                 peer -> me.state = recover;
1013                 peer -> me.stos = cur_time;
1014                 peer -> partner.state = unknown_state;
1015                 peer -> partner.stos = cur_time;
1016         }
1017
1018         status = enter_failover_peer (peer);
1019         if (status != ISC_R_SUCCESS)
1020                 parse_warn (cfile, "failover peer %s: %s",
1021                             peer -> name, isc_result_totext (status));
1022         dhcp_failover_state_dereference (&peer, MDL);
1023 }
1024
1025 void parse_failover_state_declaration (struct parse *cfile,
1026                                        dhcp_failover_state_t *peer)
1027 {
1028         enum dhcp_token token;
1029         const char *val;
1030         char *name;
1031         dhcp_failover_state_t *state;
1032         dhcp_failover_config_t *cp;
1033
1034         if (!peer) {
1035                 token = next_token (&val, (unsigned *)0, cfile);
1036                 if (token != PEER) {
1037                         parse_warn (cfile, "expecting \"peer\"");
1038                         skip_to_semi (cfile);
1039                         return;
1040                 }
1041
1042                 token = next_token (&val, (unsigned *)0, cfile);
1043                 if (is_identifier (token) || token == STRING) {
1044                         name = dmalloc (strlen (val) + 1, MDL);
1045                         if (!name)
1046                                 log_fatal ("failover peer name %s: no memory",
1047                                            name);
1048                         strcpy (name, val);
1049                 } else {
1050                         parse_warn (cfile, "expecting failover peer name.");
1051                         skip_to_semi (cfile);
1052                         return;
1053                 }
1054
1055                 /* See if there's a peer declaration by this name. */
1056                 state = (dhcp_failover_state_t *)0;
1057                 find_failover_peer (&state, name, MDL);
1058                 if (!state) {
1059                         parse_warn (cfile, "unknown failover peer: %s", name);
1060                         skip_to_semi (cfile);
1061                         return;
1062                 }
1063
1064                 token = next_token (&val, (unsigned *)0, cfile);
1065                 if (token != STATE) {
1066                         parse_warn (cfile, "expecting 'state'");
1067                         if (token != SEMI)
1068                                 skip_to_semi (cfile);
1069                         return;
1070                 }
1071         } else {
1072                 state = (dhcp_failover_state_t *)0;
1073                 dhcp_failover_state_reference (&state, peer, MDL);
1074         }
1075         token = next_token (&val, (unsigned *)0, cfile);
1076         if (token != LBRACE) {
1077                 parse_warn (cfile, "expecting left brace");
1078                 if (token != SEMI)
1079                         skip_to_semi (cfile);
1080                 dhcp_failover_state_dereference (&state, MDL);
1081                 return;
1082         }
1083         do {
1084                 token = next_token (&val, (unsigned *)0, cfile);
1085                 switch (token) {
1086                       case RBRACE:
1087                         break;
1088                       case MY:
1089                         cp = &state -> me;
1090                       do_state:
1091                         token = next_token (&val, (unsigned *)0, cfile);
1092                         if (token != STATE) {
1093                                 parse_warn (cfile, "expecting 'state'");
1094                                 goto bogus;
1095                         }
1096                         parse_failover_state (cfile,
1097                                               &cp -> state, &cp -> stos);
1098                         break;
1099
1100                       case PARTNER:
1101                         cp = &state -> partner;
1102                         goto do_state;
1103
1104                       case MCLT:
1105                         if (state -> i_am == primary) {
1106                                 parse_warn (cfile,
1107                                             "mclt not valid for primary");
1108                                 goto bogus;
1109                         }
1110                         token = next_token (&val, (unsigned *)0, cfile);
1111                         if (token != NUMBER) {
1112                                 parse_warn (cfile, "expecting a number.");
1113                                 goto bogus;
1114                         }
1115                         state -> mclt = atoi (val);
1116                         parse_semi (cfile);
1117                         break;
1118                         
1119                       default:
1120                         parse_warn (cfile, "expecting state setting.");
1121                       bogus:
1122                         skip_to_rbrace (cfile, 1);      
1123                         dhcp_failover_state_dereference (&state, MDL);
1124                         return;
1125                 }
1126         } while (token != RBRACE);
1127         dhcp_failover_state_dereference (&state, MDL);
1128 }
1129
1130 void parse_failover_state (cfile, state, stos)
1131         struct parse *cfile;
1132         enum failover_state *state;
1133         TIME *stos;
1134 {
1135         enum dhcp_token token;
1136         const char *val;
1137         enum failover_state state_in;
1138         TIME stos_in;
1139
1140         token = next_token (&val, (unsigned *)0, cfile);
1141         switch (token) {
1142               case UNKNOWN_STATE:
1143                 state_in = unknown_state;
1144                 break;
1145
1146               case PARTNER_DOWN:
1147                 state_in = partner_down;
1148                 break;
1149
1150               case NORMAL:
1151                 state_in = normal;
1152                 break;
1153
1154               case COMMUNICATIONS_INTERRUPTED:
1155                 state_in = communications_interrupted;
1156                 break;
1157
1158               case RESOLUTION_INTERRUPTED:
1159                 state_in = resolution_interrupted;
1160                 break;
1161
1162               case POTENTIAL_CONFLICT:
1163                 state_in = potential_conflict;
1164                 break;
1165
1166               case RECOVER:
1167                 state_in = recover;
1168                 break;
1169                 
1170               case RECOVER_WAIT:
1171                 state_in = recover_wait;
1172                 break;
1173                 
1174               case RECOVER_DONE:
1175                 state_in = recover_done;
1176                 break;
1177                 
1178               case SHUTDOWN:
1179                 state_in = shut_down;
1180                 break;
1181                 
1182               case PAUSED:
1183                 state_in = paused;
1184                 break;
1185                 
1186               case STARTUP:
1187                 state_in = startup;
1188                 break;
1189
1190               default:
1191                 parse_warn (cfile, "unknown failover state");
1192                 skip_to_semi (cfile);
1193                 return;
1194         }
1195
1196         token = next_token (&val, (unsigned *)0, cfile);
1197         if (token == SEMI) {
1198                 stos_in = cur_time;
1199         } else {
1200                 if (token != AT) {
1201                         parse_warn (cfile, "expecting \"at\"");
1202                         skip_to_semi (cfile);
1203                         return;
1204                 }
1205                 
1206                 stos_in = parse_date (cfile);
1207                 if (!stos_in)
1208                         return;
1209         }
1210
1211         /* Now that we've apparently gotten a clean parse, we
1212            can trust that this is a state that was fully committed to
1213            disk, so we can install it. */
1214         *stos = stos_in;
1215         *state = state_in;
1216 }
1217 #endif /* defined (FAILOVER_PROTOCOL) */
1218
1219 /* Permit_list_match returns 1 if every element of the permit list in lhs
1220    also appears in rhs.   Note that this doesn't by itself mean that the
1221    two lists are equal - to check for equality, permit_list_match has to
1222    return 1 with (list1, list2) and with (list2, list1). */
1223
1224 int permit_list_match (struct permit *lhs, struct permit *rhs)
1225 {
1226         struct permit *plp, *prp;
1227         int matched;
1228
1229         if (!lhs)
1230                 return 1;
1231         if (!rhs)
1232                 return 0;
1233         for (plp = lhs; plp; plp = plp -> next) {
1234                 matched = 0;
1235                 for (prp = rhs; prp; prp = prp -> next) {
1236                         if (prp -> type == plp -> type &&
1237                             (prp -> type != permit_class ||
1238                              prp -> class == plp -> class)) {
1239                                 matched = 1;
1240                                 break;
1241                         }
1242                 }
1243                 if (!matched)
1244                         return 0;
1245         }
1246         return 1;
1247 }
1248
1249 void parse_pool_statement (cfile, group, type)
1250         struct parse *cfile;
1251         struct group *group;
1252         int type;
1253 {
1254         enum dhcp_token token;
1255         const char *val;
1256         int done = 0;
1257         struct pool *pool, **p, *pp;
1258         struct permit *permit;
1259         struct permit **permit_head;
1260         int declaration = 0;
1261         isc_result_t status;
1262         struct lease *lpchain = (struct lease *)0, *lp;
1263
1264         pool = (struct pool *)0;
1265         status = pool_allocate (&pool, MDL);
1266         if (status != ISC_R_SUCCESS)
1267                 log_fatal ("no memory for pool: %s",
1268                            isc_result_totext (status));
1269
1270         if (type == SUBNET_DECL)
1271                 shared_network_reference (&pool -> shared_network,
1272                                           group -> subnet -> shared_network,
1273                                           MDL);
1274         else
1275                 shared_network_reference (&pool -> shared_network,
1276                                           group -> shared_network, MDL);
1277
1278         if (!clone_group (&pool -> group, pool -> shared_network -> group, MDL))
1279                 log_fatal ("can't clone pool group.");
1280
1281 #if defined (FAILOVER_PROTOCOL)
1282         /* Inherit the failover peer from the shared network. */
1283         if (pool -> shared_network -> failover_peer)
1284             dhcp_failover_state_reference
1285                     (&pool -> failover_peer, 
1286                      pool -> shared_network -> failover_peer, MDL);
1287 #endif
1288
1289         if (!parse_lbrace (cfile)) {
1290                 pool_dereference (&pool, MDL);
1291                 return;
1292         }
1293
1294         do {
1295                 token = peek_token (&val, (unsigned *)0, cfile);
1296                 switch (token) {
1297                       case NO:
1298                         next_token (&val, (unsigned *)0, cfile);
1299                         token = next_token (&val, (unsigned *)0, cfile);
1300                         if (token != FAILOVER ||
1301                             (token = next_token (&val, (unsigned *)0,
1302                                                  cfile)) != PEER) {
1303                                 parse_warn (cfile,
1304                                             "expecting \"failover peer\".");
1305                                 skip_to_semi (cfile);
1306                                 continue;
1307                         }
1308 #if defined (FAILOVER_PROTOCOL)
1309                         if (pool -> failover_peer)
1310                                 dhcp_failover_state_dereference
1311                                         (&pool -> failover_peer, MDL);
1312 #endif
1313                         break;
1314                                 
1315 #if defined (FAILOVER_PROTOCOL)
1316                       case FAILOVER:
1317                         next_token (&val, (unsigned *)0, cfile);
1318                         token = next_token (&val, (unsigned *)0, cfile);
1319                         if (token != PEER) {
1320                                 parse_warn (cfile, "expecting 'peer'.");
1321                                 skip_to_semi (cfile);
1322                                 break;
1323                         }
1324                         token = next_token (&val, (unsigned *)0, cfile);
1325                         if (token != STRING) {
1326                                 parse_warn (cfile, "expecting string.");
1327                                 skip_to_semi (cfile);
1328                                 break;
1329                         }
1330                         if (pool -> failover_peer)
1331                                 dhcp_failover_state_dereference
1332                                         (&pool -> failover_peer, MDL);
1333                         status = find_failover_peer (&pool -> failover_peer,
1334                                                      val, MDL);
1335                         if (status != ISC_R_SUCCESS)
1336                                 parse_warn (cfile,
1337                                             "failover peer %s: %s", val,
1338                                             isc_result_totext (status));
1339                         else
1340                                 pool -> failover_peer -> pool_count++;
1341                         parse_semi (cfile);
1342                         break;
1343 #endif
1344
1345                       case RANGE:
1346                         next_token (&val, (unsigned *)0, cfile);
1347                         parse_address_range (cfile, group, type,
1348                                              pool, &lpchain);
1349                         break;
1350                       case ALLOW:
1351                         permit_head = &pool -> permit_list;
1352                       get_permit:
1353                         permit = new_permit (MDL);
1354                         if (!permit)
1355                                 log_fatal ("no memory for permit");
1356                         next_token (&val, (unsigned *)0, cfile);
1357                         token = next_token (&val, (unsigned *)0, cfile);
1358                         switch (token) {
1359                               case UNKNOWN:
1360                                 permit -> type = permit_unknown_clients;
1361                               get_clients:
1362                                 if (next_token (&val, (unsigned *)0,
1363                                                 cfile) != CLIENTS) {
1364                                         parse_warn (cfile,
1365                                                     "expecting \"clients\"");
1366                                         skip_to_semi (cfile);
1367                                         free_permit (permit, MDL);
1368                                         continue;
1369                                 }
1370                                 break;
1371                                 
1372                               case KNOWN_CLIENTS:
1373                                 permit -> type = permit_known_clients;
1374                                 break;
1375
1376                               case UNKNOWN_CLIENTS:
1377                                 permit -> type = permit_unknown_clients;
1378                                 break;
1379
1380                               case KNOWN:
1381                                 permit -> type = permit_known_clients;
1382                                 goto get_clients;
1383                                 
1384                               case AUTHENTICATED:
1385                                 permit -> type = permit_authenticated_clients;
1386                                 goto get_clients;
1387                                 
1388                               case UNAUTHENTICATED:
1389                                 permit -> type =
1390                                         permit_unauthenticated_clients;
1391                                 goto get_clients;
1392
1393                               case ALL:
1394                                 permit -> type = permit_all_clients;
1395                                 goto get_clients;
1396                                 break;
1397                                 
1398                               case DYNAMIC:
1399                                 permit -> type = permit_dynamic_bootp_clients;
1400                                 if (next_token (&val, (unsigned *)0,
1401                                                 cfile) != TOKEN_BOOTP) {
1402                                         parse_warn (cfile,
1403                                                     "expecting \"bootp\"");
1404                                         skip_to_semi (cfile);
1405                                         free_permit (permit, MDL);
1406                                         continue;
1407                                 }
1408                                 goto get_clients;
1409                                 
1410                               case MEMBERS:
1411                                 if (next_token (&val, (unsigned *)0,
1412                                                 cfile) != OF) {
1413                                         parse_warn (cfile, "expecting \"of\"");
1414                                         skip_to_semi (cfile);
1415                                         free_permit (permit, MDL);
1416                                         continue;
1417                                 }
1418                                 if (next_token (&val, (unsigned *)0,
1419                                                 cfile) != STRING) {
1420                                         parse_warn (cfile,
1421                                                     "expecting class name.");
1422                                         skip_to_semi (cfile);
1423                                         free_permit (permit, MDL);
1424                                         continue;
1425                                 }
1426                                 permit -> type = permit_class;
1427                                 permit -> class = (struct class *)0;
1428                                 find_class (&permit -> class, val, MDL);
1429                                 if (!permit -> class)
1430                                         parse_warn (cfile,
1431                                                     "no such class: %s", val);
1432                                 break;
1433
1434                               default:
1435                                 parse_warn (cfile, "expecting permit type.");
1436                                 skip_to_semi (cfile);
1437                                 break;
1438                         }
1439                         while (*permit_head)
1440                                 permit_head = &((*permit_head) -> next);
1441                         *permit_head = permit;
1442                         parse_semi (cfile);
1443                         break;
1444
1445                       case DENY:
1446                         permit_head = &pool -> prohibit_list;
1447                         goto get_permit;
1448                         
1449                       case RBRACE:
1450                         next_token (&val, (unsigned *)0, cfile);
1451                         done = 1;
1452                         break;
1453
1454                       default:
1455                         declaration = parse_statement (cfile, pool -> group,
1456                                                        POOL_DECL,
1457                                                        (struct host_decl *)0,
1458                                                        declaration);
1459                         break;
1460                 }
1461         } while (!done);
1462
1463 #if defined (FAILOVER_PROTOCOL)
1464         /* We can't do failover on a pool that supports dynamic bootp,
1465            because BOOTP doesn't support leases, and failover absolutely
1466            depends on lease timing. */
1467         if (pool -> failover_peer) {
1468                 /* This search order matches the search orders later in
1469                  * execution - deny first, if not denied, check permit
1470                  * list.  A dynamic bootp client may be known or unknown,
1471                  * it may belong to a member of a class, but it definitely
1472                  * will not be authenticated since that requires DHCP
1473                  * to work.  So a dynamic bootp client is definitely not
1474                  * an authenticated client, and we can't say for sure about
1475                  * anything else.
1476                  *
1477                  * So we nag the user.
1478                  */
1479                 for (permit = pool -> prohibit_list; permit;
1480                      permit = permit -> next) {
1481                         if (permit -> type == permit_dynamic_bootp_clients ||
1482                             permit -> type == permit_unauthenticated_clients ||
1483                             permit -> type == permit_all_clients)
1484                                 break;
1485                 }
1486                 if (!permit) {
1487                         permit = pool -> permit_list;
1488                         do {
1489                                 if (!permit ||
1490                                     permit -> type !=
1491                                         permit_authenticated_clients) {
1492                                         parse_warn (cfile,
1493                                           "pools with failover peers %s",
1494                                           "may not permit dynamic bootp.");
1495                                         log_error ("Either write a \"%s\" %s",
1496                                           "no failover",
1497                                           "statement and use disjoint");
1498                                         log_error ("pools, or%s (%s) %s",
1499                                           " don't permit dynamic bootp",
1500                                           "\"deny dynamic bootp clients;\"",
1501                                           "in this pool.");
1502                                         log_error ("This is a protocol,%s %s",
1503                                            " limitation, not an ISC DHCP",
1504                                            "limitation, so");
1505                                         log_error ("please don't request an %s",
1506                                            "enhancement or ask why this is.");
1507
1508                                         break;
1509                                 }
1510
1511                                 permit = permit -> next;
1512                         } while (permit);
1513                 }
1514         }
1515 #endif /* FAILOVER_PROTOCOL */
1516
1517         /* See if there's already a pool into which we can merge this one. */
1518         for (pp = pool -> shared_network -> pools; pp; pp = pp -> next) {
1519                 struct lease *l;
1520
1521                 if (pp -> group -> statements != pool -> group -> statements)
1522                         continue;
1523 #if defined (FAILOVER_PROTOCOL)
1524                 if (pool -> failover_peer != pp -> failover_peer)
1525                         continue;
1526 #endif
1527                 if (!permit_list_match (pp -> permit_list,
1528                                         pool -> permit_list) ||
1529                     !permit_list_match (pool -> permit_list,
1530                                         pp -> permit_list) ||
1531                     !permit_list_match (pp -> prohibit_list,
1532                                         pool -> prohibit_list) ||
1533                     !permit_list_match (pool -> prohibit_list,
1534                                         pp -> prohibit_list))
1535                         continue;
1536
1537                 /* Okay, we can merge these two pools.    All we have to
1538                    do is fix up the leases, which all point to their pool. */
1539                 for (lp = lpchain; lp; lp = lp -> next) {
1540                         pool_dereference (&lp -> pool, MDL);
1541                         pool_reference (&lp -> pool, pp, MDL);
1542                 }
1543                 break;
1544         }
1545
1546         /* If we didn't succeed in merging this pool into another, put
1547            it on the list. */
1548         if (!pp) {
1549                 p = &pool -> shared_network -> pools;
1550                 for (; *p; p = &((*p) -> next))
1551                         ;
1552                 pool_reference (p, pool, MDL);
1553         }
1554
1555         /* Don't allow a pool declaration with no addresses, since it is
1556            probably a configuration error. */
1557         if (!lpchain) {
1558                 parse_warn (cfile, "Pool declaration with no address range.");
1559                 log_error ("Pool declarations must always contain at least");
1560                 log_error ("one range statement.");
1561         }
1562
1563         /* Dereference the lease chain. */
1564         lp = (struct lease *)0;
1565         while (lpchain) {
1566                 lease_reference (&lp, lpchain, MDL);
1567                 lease_dereference (&lpchain, MDL);
1568                 if (lp -> next) {
1569                         lease_reference (&lpchain, lp -> next, MDL);
1570                         lease_dereference (&lp -> next, MDL);
1571                         lease_dereference (&lp, MDL);
1572                 }
1573         }
1574         pool_dereference (&pool, MDL);
1575 }
1576
1577 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
1578
1579 int parse_boolean (cfile)
1580         struct parse *cfile;
1581 {
1582         enum dhcp_token token;
1583         const char *val;
1584         int rv;
1585
1586         token = next_token (&val, (unsigned *)0, cfile);
1587         if (!strcasecmp (val, "true")
1588             || !strcasecmp (val, "on"))
1589                 rv = 1;
1590         else if (!strcasecmp (val, "false")
1591                  || !strcasecmp (val, "off"))
1592                 rv = 0;
1593         else {
1594                 parse_warn (cfile,
1595                             "boolean value (true/false/on/off) expected");
1596                 skip_to_semi (cfile);
1597                 return 0;
1598         }
1599         parse_semi (cfile);
1600         return rv;
1601 }
1602
1603 /* Expect a left brace; if there isn't one, skip over the rest of the
1604    statement and return zero; otherwise, return 1. */
1605
1606 int parse_lbrace (cfile)
1607         struct parse *cfile;
1608 {
1609         enum dhcp_token token;
1610         const char *val;
1611
1612         token = next_token (&val, (unsigned *)0, cfile);
1613         if (token != LBRACE) {
1614                 parse_warn (cfile, "expecting left brace.");
1615                 skip_to_semi (cfile);
1616                 return 0;
1617         }
1618         return 1;
1619 }
1620
1621
1622 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1623
1624 void parse_host_declaration (cfile, group)
1625         struct parse *cfile;
1626         struct group *group;
1627 {
1628         const char *val;
1629         enum dhcp_token token;
1630         struct host_decl *host;
1631         char *name;
1632         int declaration = 0;
1633         int dynamicp = 0;
1634         int deleted = 0;
1635         isc_result_t status;
1636
1637         name = parse_host_name (cfile);
1638         if (!name) {
1639                 parse_warn (cfile, "expecting a name for host declaration.");
1640                 skip_to_semi (cfile);
1641                 return;
1642         }
1643
1644         host = (struct host_decl *)0;
1645         status = host_allocate (&host, MDL);
1646         if (status != ISC_R_SUCCESS)
1647                 log_fatal ("can't allocate host decl struct %s: %s",
1648                            name, isc_result_totext (status));
1649         host -> name = name;
1650         if (!clone_group (&host -> group, group, MDL)) {
1651                 log_fatal ("can't clone group for host %s", name);
1652               boom:
1653                 host_dereference (&host, MDL);
1654                 return;
1655         }
1656
1657         if (!parse_lbrace (cfile))
1658                 goto boom;
1659
1660         do {
1661                 token = peek_token (&val, (unsigned *)0, cfile);
1662                 if (token == RBRACE) {
1663                         token = next_token (&val, (unsigned *)0, cfile);
1664                         break;
1665                 }
1666                 if (token == END_OF_FILE) {
1667                         token = next_token (&val, (unsigned *)0, cfile);
1668                         parse_warn (cfile, "unexpected end of file");
1669                         break;
1670                 }
1671                 /* If the host declaration was created by the server,
1672                    remember to save it. */
1673                 if (token == DYNAMIC) {
1674                         dynamicp = 1;
1675                         token = next_token (&val, (unsigned *)0, cfile);
1676                         if (!parse_semi (cfile))
1677                                 break;
1678                         continue;
1679                 }
1680                 /* If the host declaration was created by the server,
1681                    remember to save it. */
1682                 if (token == TOKEN_DELETED) {
1683                         deleted = 1;
1684                         token = next_token (&val, (unsigned *)0, cfile);
1685                         if (!parse_semi (cfile))
1686                                 break;
1687                         continue;
1688                 }
1689
1690                 if (token == GROUP) {
1691                         struct group_object *go;
1692                         token = next_token (&val, (unsigned *)0, cfile);
1693                         token = next_token (&val, (unsigned *)0, cfile);
1694                         if (token != STRING && !is_identifier (token)) {
1695                                 parse_warn (cfile,
1696                                             "expecting string or identifier.");
1697                                 skip_to_rbrace (cfile, 1);
1698                                 break;
1699                         }
1700                         go = (struct group_object *)0;
1701                         if (!group_hash_lookup (&go, group_name_hash,
1702                                                 val, strlen (val), MDL)) {
1703                             parse_warn (cfile, "unknown group %s in host %s",
1704                                         val, host -> name);
1705                         } else {
1706                                 if (host -> named_group)
1707                                         group_object_dereference
1708                                                 (&host -> named_group, MDL);
1709                                 group_object_reference (&host -> named_group,
1710                                                         go, MDL);
1711                                 group_object_dereference (&go, MDL);
1712                         }
1713                         if (!parse_semi (cfile))
1714                                 break;
1715                         continue;
1716                 }
1717
1718                 if (token == UID) {
1719                         const char *s;
1720                         unsigned char *t = 0;
1721                         unsigned len;
1722
1723                         token = next_token (&val, (unsigned *)0, cfile);
1724                         data_string_forget (&host -> client_identifier, MDL);
1725
1726                         /* See if it's a string or a cshl. */
1727                         token = peek_token (&val, (unsigned *)0, cfile);
1728                         if (token == STRING) {
1729                                 token = next_token (&val, &len, cfile);
1730                                 s = val;
1731                                 host -> client_identifier.terminated = 1;
1732                         } else {
1733                                 len = 0;
1734                                 t = parse_numeric_aggregate
1735                                         (cfile,
1736                                          (unsigned char *)0, &len, ':', 16, 8);
1737                                 if (!t) {
1738                                         parse_warn (cfile,
1739                                                     "expecting hex list.");
1740                                         skip_to_semi (cfile);
1741                                 }
1742                                 s = (const char *)t;
1743                         }
1744                         if (!buffer_allocate
1745                             (&host -> client_identifier.buffer,
1746                              len + host -> client_identifier.terminated, MDL))
1747                                 log_fatal ("no memory for uid for host %s.",
1748                                            host -> name);
1749                         host -> client_identifier.data =
1750                                 host -> client_identifier.buffer -> data;
1751                         host -> client_identifier.len = len;
1752                         memcpy (host -> client_identifier.buffer -> data, s,
1753                                 len + host -> client_identifier.terminated);
1754                         if (t)
1755                                 dfree (t, MDL);
1756
1757                         if (!parse_semi (cfile))
1758                                 break;
1759                         continue;
1760                 }
1761                 declaration = parse_statement (cfile, host -> group,
1762                                                HOST_DECL, host,
1763                                                declaration);
1764         } while (1);
1765
1766         if (deleted) {
1767                 struct host_decl *hp = (struct host_decl *)0;
1768                 if (host_hash_lookup (&hp, host_name_hash,
1769                                       (unsigned char *)host -> name,
1770                                       strlen (host -> name), MDL)) {
1771                         delete_host (hp, 0);
1772                         host_dereference (&hp, MDL);
1773                 }
1774         } else {
1775                 if (host -> named_group && host -> named_group -> group) {
1776                         if (host -> group -> statements ||
1777                             (host -> group -> authoritative !=
1778                              host -> named_group -> group -> authoritative)) {
1779                                 if (host -> group -> next)
1780                                     group_dereference (&host -> group -> next,
1781                                                        MDL);
1782                                 group_reference (&host -> group -> next,
1783                                                  host -> named_group -> group,
1784                                                  MDL);
1785                         } else {
1786                                 group_dereference (&host -> group, MDL);
1787                                 group_reference (&host -> group,
1788                                                  host -> named_group -> group,
1789                                                  MDL);
1790                         }
1791                 }
1792                                 
1793                 if (dynamicp)
1794                         host -> flags |= HOST_DECL_DYNAMIC;
1795                 else
1796                         host -> flags |= HOST_DECL_STATIC;
1797
1798                 status = enter_host (host, dynamicp, 0);
1799                 if (status != ISC_R_SUCCESS)
1800                         parse_warn (cfile, "host %s: %s", host -> name,
1801                                     isc_result_totext (status));
1802         }
1803         host_dereference (&host, MDL);
1804 }
1805
1806 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
1807 */
1808
1809 int parse_class_declaration (cp, cfile, group, type)
1810         struct class **cp;
1811         struct parse *cfile;
1812         struct group *group;
1813         int type;
1814 {
1815         const char *val;
1816         enum dhcp_token token;
1817         struct class *class = (struct class *)0, *pc = (struct class *)0;
1818         int declaration = 0;
1819         int lose = 0;
1820         struct data_string data;
1821         char *name;
1822         const char *tname;
1823         struct executable_statement *stmt = (struct executable_statement *)0;
1824         struct expression *expr;
1825         int new = 1;
1826         isc_result_t status = ISC_R_FAILURE;
1827
1828         token = next_token (&val, (unsigned *)0, cfile);
1829         if (token != STRING) {
1830                 parse_warn (cfile, "Expecting class name");
1831                 skip_to_semi (cfile);
1832                 return 0;
1833         }
1834
1835         /* See if there's already a class with the specified name. */
1836         find_class (&pc, val, MDL);
1837
1838         /* If this isn't a subclass, we're updating an existing class. */
1839         if (pc && type != 0 && type != 1 && type != 3) {
1840                 class_reference (&class, pc, MDL);
1841                 new = 0;
1842                 class_dereference (&pc, MDL);
1843         }
1844
1845         /* If this _is_ a subclass, there _must_ be a class with the
1846            same name. */
1847         if (!pc && (type == 0 || type == 1 || type == 3)) {
1848                 parse_warn (cfile, "no class named %s", val);
1849                 skip_to_semi (cfile);
1850                 return 0;
1851         }
1852
1853         /* The old vendor-class and user-class declarations had an implicit
1854            match.   We don't do the implicit match anymore.   Instead, for
1855            backward compatibility, we have an implicit-vendor-class and an
1856            implicit-user-class.   vendor-class and user-class declarations
1857            are turned into subclasses of the implicit classes, and the
1858            submatch expression of the implicit classes extracts the contents of
1859            the vendor class or user class. */
1860         if (type == 0 || type == 1) {
1861                 data.len = strlen (val);
1862                 data.buffer = (struct buffer *)0;
1863                 if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
1864                         log_fatal ("no memory for class name.");
1865                 data.data = &data.buffer -> data [0];
1866                 data.terminated = 1;
1867
1868                 tname = type ? "implicit-vendor-class" : "implicit-user-class";
1869         } else if (type == 2) {
1870                 tname = val;
1871         } else {
1872                 tname = (const char *)0;
1873         }
1874
1875         if (tname) {
1876                 name = dmalloc (strlen (tname) + 1, MDL);
1877                 if (!name)
1878                         log_fatal ("No memory for class name %s.", tname);
1879                 strcpy (name, val);
1880         } else
1881                 name = (char *)0;
1882
1883         /* If this is a straight subclass, parse the hash string. */
1884         if (type == 3) {
1885                 token = peek_token (&val, (unsigned *)0, cfile);
1886                 if (token == STRING) {
1887                         token = next_token (&val, &data.len, cfile);
1888                         data.buffer = (struct buffer *)0;
1889                         if (!buffer_allocate (&data.buffer,
1890                                               data.len + 1, MDL)) {
1891                                 if (pc)
1892                                         class_dereference (&pc, MDL);
1893                                 
1894                                 return 0;
1895                         }
1896                         data.terminated = 1;
1897                         data.data = &data.buffer -> data [0];
1898                         memcpy ((char *)data.buffer -> data, val,
1899                                 data.len + 1);
1900                 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
1901                         memset (&data, 0, sizeof data);
1902                         if (!parse_cshl (&data, cfile)) {
1903                                 class_dereference (&pc, MDL);
1904                                 return 0;
1905                         }
1906                 } else {
1907                         parse_warn (cfile, "Expecting string or hex list.");
1908                         if (pc)
1909                                 class_dereference (&pc, MDL);
1910                         return 0;
1911                 }
1912         }
1913
1914         /* See if there's already a class in the hash table matching the
1915            hash data. */
1916         if (type == 0 || type == 1 || type == 3)
1917                 class_hash_lookup (&class, pc -> hash,
1918                                    (const char *)data.data, data.len, MDL);
1919
1920         /* If we didn't find an existing class, allocate a new one. */
1921         if (!class) {
1922                 /* Allocate the class structure... */
1923                 status = class_allocate (&class, MDL);
1924                 if (pc) {
1925                         group_reference (&class -> group, pc -> group, MDL);
1926                         class_reference (&class -> superclass, pc, MDL);
1927                         class -> lease_limit = pc -> lease_limit;
1928                         if (class -> lease_limit) {
1929                                 class -> billed_leases =
1930                                         dmalloc (class -> lease_limit *
1931                                                  sizeof (struct lease *), MDL);
1932                                 if (!class -> billed_leases)
1933                                         log_fatal ("no memory for billing");
1934                                 memset (class -> billed_leases, 0,
1935                                         (class -> lease_limit *
1936                                          sizeof class -> billed_leases));
1937                         }
1938                         data_string_copy (&class -> hash_string, &data, MDL);
1939                         if (!pc -> hash &&
1940                             !class_new_hash (&pc -> hash, 0, MDL))
1941                                 log_fatal ("No memory for subclass hash.");
1942                         class_hash_add (pc -> hash,
1943                                         (const char *)class -> hash_string.data,
1944                                         class -> hash_string.len,
1945                                         (void *)class, MDL);
1946                 } else {
1947                         if (!clone_group (&class -> group, group, MDL))
1948                                 log_fatal ("no memory to clone class group.");
1949                 }
1950
1951                 /* If this is an implicit vendor or user class, add a
1952                    statement that causes the vendor or user class ID to
1953                    be sent back in the reply. */
1954                 if (type == 0 || type == 1) {
1955                         stmt = (struct executable_statement *)0;
1956                         if (!executable_statement_allocate (&stmt, MDL))
1957                                 log_fatal ("no memory for class statement.");
1958                         stmt -> op = supersede_option_statement;
1959                         if (option_cache_allocate (&stmt -> data.option,
1960                                                    MDL)) {
1961                                 stmt -> data.option -> data = data;
1962                                 stmt -> data.option -> option =
1963                                         dhcp_universe.options
1964                                         [type
1965                                         ? DHO_VENDOR_CLASS_IDENTIFIER
1966                                         : DHO_USER_CLASS];
1967                         }
1968                         class -> statements = stmt;
1969                 }
1970
1971                 /* Save the name, if there is one. */
1972                 class -> name = name;
1973         }
1974
1975         if (type == 0 || type == 1 || type == 3)
1976                 data_string_forget (&data, MDL);
1977
1978         /* Spawned classes don't have to have their own settings. */
1979         if (class -> superclass) {
1980                 token = peek_token (&val, (unsigned *)0, cfile);
1981                 if (token == SEMI) {
1982                         next_token (&val, (unsigned *)0, cfile);
1983                         if (cp)
1984                                 status = class_reference (cp, class, MDL);
1985                         class_dereference (&class, MDL);
1986                         if (pc)
1987                                 class_dereference (&pc, MDL);
1988                         return cp ? (status == ISC_R_SUCCESS) : 1;
1989                 }
1990                 /* Give the subclass its own group. */
1991                 if (!clone_group (&class -> group, class -> group, MDL))
1992                         log_fatal ("can't clone class group.");
1993
1994         }
1995
1996         if (!parse_lbrace (cfile)) {
1997                 class_dereference (&class, MDL);
1998                 if (pc)
1999                         class_dereference (&pc, MDL);
2000                 return 0;
2001         }
2002
2003         do {
2004                 token = peek_token (&val, (unsigned *)0, cfile);
2005                 if (token == RBRACE) {
2006                         token = next_token (&val, (unsigned *)0, cfile);
2007                         break;
2008                 } else if (token == END_OF_FILE) {
2009                         token = next_token (&val, (unsigned *)0, cfile);
2010                         parse_warn (cfile, "unexpected end of file");
2011                         break;
2012                 } else if (token == MATCH) {
2013                         if (pc) {
2014                                 parse_warn (cfile,
2015                                             "invalid match in subclass.");
2016                                 skip_to_semi (cfile);
2017                                 break;
2018                         }
2019                         token = next_token (&val, (unsigned *)0, cfile);
2020                         token = peek_token (&val, (unsigned *)0, cfile);
2021                         if (token != IF)
2022                                 goto submatch;
2023                         if (class -> expr) {
2024                                 parse_warn (cfile, "can't override match.");
2025                                 skip_to_semi (cfile);
2026                                 break;
2027                         }
2028                         token = next_token (&val, (unsigned *)0, cfile);
2029                         if (!parse_boolean_expression (&class -> expr, cfile,
2030                                                        &lose)) {
2031                                 if (!lose) {
2032                                         parse_warn (cfile,
2033                                                     "expecting boolean expr.");
2034                                         skip_to_semi (cfile);
2035                                 }
2036                         } else {
2037 #if defined (DEBUG_EXPRESSION_PARSE)
2038                                 print_expression ("class match",
2039                                                   class -> expr);
2040 #endif
2041                                 parse_semi (cfile);
2042                         }
2043                 } else if (token == SPAWN) {
2044                         if (pc) {
2045                                 parse_warn (cfile,
2046                                             "invalid spawn in subclass.");
2047                                 skip_to_semi (cfile);
2048                                 break;
2049                         }
2050                         token = next_token (&val, (unsigned *)0, cfile);
2051                         class -> spawning = 1;
2052                         token = next_token (&val, (unsigned *)0, cfile);
2053                         if (token != WITH) {
2054                                 parse_warn (cfile,
2055                                             "expecting with after spawn");
2056                                 skip_to_semi (cfile);
2057                                 break;
2058                         }
2059                       submatch:
2060                         if (class -> submatch) {
2061                                 parse_warn (cfile,
2062                                             "can't override existing %s.",
2063                                             "submatch/spawn");
2064                                 skip_to_semi (cfile);
2065                                 break;
2066                         }
2067                         if (!parse_data_expression (&class -> submatch,
2068                                                     cfile, &lose)) {
2069                                 if (!lose) {
2070                                         parse_warn (cfile,
2071                                                     "expecting data expr.");
2072                                         skip_to_semi (cfile);
2073                                 }
2074                         } else {
2075 #if defined (DEBUG_EXPRESSION_PARSE)
2076                                 print_expression ("class submatch",
2077                                                   class -> submatch);
2078 #endif
2079                                 parse_semi (cfile);
2080                         }
2081                 } else if (token == LEASE) {
2082                         next_token (&val, (unsigned *)0, cfile);
2083                         token = next_token (&val, (unsigned *)0, cfile);
2084                         if (token != LIMIT) {
2085                                 parse_warn (cfile, "expecting \"limit\"");
2086                                 if (token != SEMI)
2087                                         skip_to_semi (cfile);
2088                                 break;
2089                         }
2090                         token = next_token (&val, (unsigned *)0, cfile);
2091                         if (token != NUMBER) {
2092                                 parse_warn (cfile, "expecting a number");
2093                                 if (token != SEMI)
2094                                         skip_to_semi (cfile);
2095                                 break;
2096                         }
2097                         class -> lease_limit = atoi (val);
2098                         class -> billed_leases =
2099                                 dmalloc (class -> lease_limit *
2100                                          sizeof (struct lease *), MDL);
2101                         if (!class -> billed_leases)
2102                                 log_fatal ("no memory for billed leases.");
2103                         memset (class -> billed_leases, 0,
2104                                 (class -> lease_limit *
2105                                  sizeof class -> billed_leases));
2106                         have_billing_classes = 1;
2107                         parse_semi (cfile);
2108                 } else {
2109                         declaration = parse_statement (cfile, class -> group,
2110                                                        CLASS_DECL,
2111                                                        (struct host_decl *)0,
2112                                                        declaration);
2113                 }
2114         } while (1);
2115         if (type == 2 && new) {
2116                 if (!collections -> classes)
2117                         class_reference (&collections -> classes, class, MDL);
2118                 else {
2119                         struct class *c;
2120                         for (c = collections -> classes;
2121                              c -> nic; c = c -> nic)
2122                                 ;
2123                         class_reference (&c -> nic, class, MDL);
2124                 }
2125         }
2126         if (cp)
2127                 status = class_reference (cp, class, MDL);
2128         class_dereference (&class, MDL);
2129         if (pc)
2130                 class_dereference (&pc, MDL);
2131         return cp ? (status == ISC_R_SUCCESS) : 1;
2132 }
2133
2134 /* shared-network-declaration :==
2135                         hostname LBRACE declarations parameters RBRACE */
2136
2137 void parse_shared_net_declaration (cfile, group)
2138         struct parse *cfile;
2139         struct group *group;
2140 {
2141         const char *val;
2142         enum dhcp_token token;
2143         struct shared_network *share;
2144         char *name;
2145         int declaration = 0;
2146         isc_result_t status;
2147
2148         share = (struct shared_network *)0;
2149         status = shared_network_allocate (&share, MDL);
2150         if (status != ISC_R_SUCCESS)
2151                 log_fatal ("Can't allocate shared subnet: %s",
2152                            isc_result_totext (status));
2153         clone_group (&share -> group, group, MDL);
2154         shared_network_reference (&share -> group -> shared_network,
2155                                   share, MDL);
2156
2157         /* Get the name of the shared network... */
2158         token = peek_token (&val, (unsigned *)0, cfile);
2159         if (token == STRING) {
2160                 token = next_token (&val, (unsigned *)0, cfile);
2161
2162                 if (val [0] == 0) {
2163                         parse_warn (cfile, "zero-length shared network name");
2164                         val = "<no-name-given>";
2165                 }
2166                 name = dmalloc (strlen (val) + 1, MDL);
2167                 if (!name)
2168                         log_fatal ("no memory for shared network name");
2169                 strcpy (name, val);
2170         } else {
2171                 name = parse_host_name (cfile);
2172                 if (!name) {
2173                         parse_warn (cfile,
2174                                      "expecting a name for shared-network");
2175                         skip_to_semi (cfile);
2176                         shared_network_dereference (&share, MDL);
2177                         return;
2178                 }
2179         }
2180         share -> name = name;
2181
2182         if (!parse_lbrace (cfile)) {
2183                 shared_network_dereference (&share, MDL);
2184                 return;
2185         }
2186
2187         do {
2188                 token = peek_token (&val, (unsigned *)0, cfile);
2189                 if (token == RBRACE) {
2190                         token = next_token (&val, (unsigned *)0, cfile);
2191                         if (!share -> subnets)
2192                                 parse_warn (cfile,
2193                                             "empty shared-network decl");
2194                         else
2195                                 enter_shared_network (share);
2196                         shared_network_dereference (&share, MDL);
2197                         return;
2198                 } else if (token == END_OF_FILE) {
2199                         token = next_token (&val, (unsigned *)0, cfile);
2200                         parse_warn (cfile, "unexpected end of file");
2201                         break;
2202                 } else if (token == INTERFACE) {
2203                         token = next_token (&val, (unsigned *)0, cfile);
2204                         token = next_token (&val, (unsigned *)0, cfile);
2205                         new_shared_network_interface (cfile, share, val);
2206                         if (!parse_semi (cfile))
2207                                 break;
2208                         continue;
2209                 }
2210
2211                 declaration = parse_statement (cfile, share -> group,
2212                                                SHARED_NET_DECL,
2213                                                (struct host_decl *)0,
2214                                                declaration);
2215         } while (1);
2216         shared_network_dereference (&share, MDL);
2217 }
2218
2219 /* subnet-declaration :==
2220         net NETMASK netmask RBRACE parameters declarations LBRACE */
2221
2222 void parse_subnet_declaration (cfile, share)
2223         struct parse *cfile;
2224         struct shared_network *share;
2225 {
2226         const char *val;
2227         enum dhcp_token token;
2228         struct subnet *subnet, *t, *u;
2229         struct iaddr iaddr;
2230         unsigned char addr [4];
2231         unsigned len = sizeof addr;
2232         int declaration = 0;
2233         struct interface_info *ip;
2234         isc_result_t status;
2235
2236         subnet = (struct subnet *)0;
2237         status = subnet_allocate (&subnet, MDL);
2238         if (status != ISC_R_SUCCESS)
2239                 log_fatal ("Allocation of new subnet failed: %s",
2240                            isc_result_totext (status));
2241         shared_network_reference (&subnet -> shared_network, share, MDL);
2242         if (!clone_group (&subnet -> group, share -> group, MDL))
2243                 log_fatal ("allocation of group for new subnet failed.");
2244         subnet_reference (&subnet -> group -> subnet, subnet, MDL);
2245
2246         /* Get the network number... */
2247         if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2248                 subnet_dereference (&subnet, MDL);
2249                 return;
2250         }
2251         memcpy (iaddr.iabuf, addr, len);
2252         iaddr.len = len;
2253         subnet -> net = iaddr;
2254
2255         token = next_token (&val, (unsigned *)0, cfile);
2256         if (token != NETMASK) {
2257                 parse_warn (cfile, "Expecting netmask");
2258                 skip_to_semi (cfile);
2259                 return;
2260         }
2261
2262         /* Get the netmask... */
2263         if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2264                 subnet_dereference (&subnet, MDL);
2265                 return;
2266         }
2267         memcpy (iaddr.iabuf, addr, len);
2268         iaddr.len = len;
2269         subnet -> netmask = iaddr;
2270
2271         /* Validate the network number/netmask pair. */
2272         if (host_addr (subnet -> net, subnet -> netmask)) {
2273                 char *maskstr;
2274
2275                 maskstr = strdup (piaddr (subnet -> netmask));
2276                 parse_warn (cfile,
2277                    "subnet %s netmask %s: bad subnet number/mask combination.",
2278                             piaddr (subnet -> net), maskstr);
2279                 free(maskstr);
2280                 subnet_dereference (&subnet, MDL);
2281                 skip_to_semi (cfile);
2282                 return;
2283         }
2284
2285         enter_subnet (subnet);
2286
2287         if (!parse_lbrace (cfile)) {
2288                 subnet_dereference (&subnet, MDL);
2289                 return;
2290         }
2291
2292         do {
2293                 token = peek_token (&val, (unsigned *)0, cfile);
2294                 if (token == RBRACE) {
2295                         token = next_token (&val, (unsigned *)0, cfile);
2296                         break;
2297                 } else if (token == END_OF_FILE) {
2298                         token = next_token (&val, (unsigned *)0, cfile);
2299                         parse_warn (cfile, "unexpected end of file");
2300                         break;
2301                 } else if (token == INTERFACE) {
2302                         token = next_token (&val, (unsigned *)0, cfile);
2303                         token = next_token (&val, (unsigned *)0, cfile);
2304                         new_shared_network_interface (cfile, share, val);
2305                         if (!parse_semi (cfile))
2306                                 break;
2307                         continue;
2308                 }
2309                 declaration = parse_statement (cfile, subnet -> group,
2310                                                SUBNET_DECL,
2311                                                (struct host_decl *)0,
2312                                                declaration);
2313         } while (1);
2314
2315         /* Add the subnet to the list of subnets in this shared net. */
2316         if (!share -> subnets)
2317                 subnet_reference (&share -> subnets, subnet, MDL);
2318         else {
2319                 u = (struct subnet *)0;
2320                 for (t = share -> subnets;
2321                      t -> next_sibling; t = t -> next_sibling) {
2322                         if (subnet_inner_than (subnet, t, 0)) {
2323                                 subnet_reference (&subnet -> next_sibling,
2324                                                   t, MDL);
2325                                 if (u) {
2326                                         subnet_dereference (&u -> next_sibling,
2327                                                             MDL);
2328                                         subnet_reference (&u -> next_sibling,
2329                                                           subnet, MDL);
2330                                 } else {
2331                                         subnet_dereference (&share -> subnets,
2332                                                             MDL);
2333                                         subnet_reference (&share -> subnets,
2334                                                           subnet, MDL);
2335                                 }
2336                                 subnet_dereference (&subnet, MDL);
2337                                 return;
2338                         }
2339                         u = t;
2340                 }
2341                 subnet_reference (&t -> next_sibling, subnet, MDL);
2342         }
2343         subnet_dereference (&subnet, MDL);
2344 }
2345
2346 /* group-declaration :== RBRACE parameters declarations LBRACE */
2347
2348 void parse_group_declaration (cfile, group)
2349         struct parse *cfile;
2350         struct group *group;
2351 {
2352         const char *val;
2353         enum dhcp_token token;
2354         struct group *g;
2355         int declaration = 0;
2356         struct group_object *t;
2357         isc_result_t status;
2358         char *name = NULL;
2359         int deletedp = 0;
2360         int dynamicp = 0;
2361         int staticp = 0;
2362
2363         g = (struct group *)0;
2364         if (!clone_group (&g, group, MDL))
2365                 log_fatal ("no memory for explicit group.");
2366
2367         token = peek_token (&val, (unsigned *)0, cfile);
2368         if (is_identifier (token) || token == STRING) {
2369                 next_token (&val, (unsigned *)0, cfile);
2370                 
2371                 name = dmalloc (strlen (val) + 1, MDL);
2372                 if (!name)
2373                         log_fatal ("no memory for group decl name %s", val);
2374                 strcpy (name, val);
2375         }               
2376
2377         if (!parse_lbrace (cfile)) {
2378                 group_dereference (&g, MDL);
2379                 return;
2380         }
2381
2382         do {
2383                 token = peek_token (&val, (unsigned *)0, cfile);
2384                 if (token == RBRACE) {
2385                         token = next_token (&val, (unsigned *)0, cfile);
2386                         break;
2387                 } else if (token == END_OF_FILE) {
2388                         token = next_token (&val, (unsigned *)0, cfile);
2389                         parse_warn (cfile, "unexpected end of file");
2390                         break;
2391                 } else if (token == TOKEN_DELETED) {
2392                         token = next_token (&val, (unsigned *)0, cfile);
2393                         parse_semi (cfile);
2394                         deletedp = 1;
2395                 } else if (token == DYNAMIC) {
2396                         token = next_token (&val, (unsigned *)0, cfile);
2397                         parse_semi (cfile);
2398                         dynamicp = 1;
2399                 } else if (token == STATIC) {
2400                         token = next_token (&val, (unsigned *)0, cfile);
2401                         parse_semi (cfile);
2402                         staticp = 1;
2403                 }
2404                 declaration = parse_statement (cfile, g, GROUP_DECL,
2405                                                (struct host_decl *)0,
2406                                                declaration);
2407         } while (1);
2408
2409         if (name) {
2410                 if (deletedp) {
2411                         if (group_name_hash) {
2412                                 t = (struct group_object *)0;
2413                                 if (group_hash_lookup (&t, group_name_hash,
2414                                                        name,
2415                                                        strlen (name), MDL)) {
2416                                         delete_group (t, 0);
2417                                 }
2418                         }
2419                 } else {
2420                         t = (struct group_object *)0;
2421                         status = group_object_allocate (&t, MDL);
2422                         if (status != ISC_R_SUCCESS)
2423                                 log_fatal ("no memory for group decl %s: %s",
2424                                            val, isc_result_totext (status));
2425                         group_reference (&t -> group, g, MDL);
2426                         t -> name = name;
2427                         t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
2428                                       (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
2429                                       (deletedp ? GROUP_OBJECT_DELETED : 0));
2430                         supersede_group (t, 0);
2431                 }
2432                 if (t)
2433                         group_object_dereference (&t, MDL);
2434         }
2435 }
2436
2437 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2438    ip-addrs-or-hostnames :== ip-addr-or-hostname
2439                            | ip-addrs-or-hostnames ip-addr-or-hostname */
2440
2441 int parse_fixed_addr_param (oc, cfile)
2442         struct option_cache **oc;
2443         struct parse *cfile;
2444 {
2445         const char *val;
2446         enum dhcp_token token;
2447         struct expression *expr = (struct expression *)0;
2448         struct expression *tmp, *new;
2449         int status;
2450
2451         do {
2452                 tmp = (struct expression *)0;
2453                 if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
2454                         if (expr) {
2455                                 new = (struct expression *)0;
2456                                 status = make_concat (&new, expr, tmp);
2457                                 expression_dereference (&expr, MDL);
2458                                 expression_dereference (&tmp, MDL);
2459                                 if (!status)
2460                                         return 0;
2461                                 expr = new;
2462                         } else
2463                                 expr = tmp;
2464                 } else {
2465                         if (expr)
2466                                 expression_dereference (&expr, MDL);
2467                         return 0;
2468                 }
2469                 token = peek_token (&val, (unsigned *)0, cfile);
2470                 if (token == COMMA)
2471                         token = next_token (&val, (unsigned *)0, cfile);
2472         } while (token == COMMA);
2473
2474         if (!parse_semi (cfile)) {
2475                 if (expr)
2476                         expression_dereference (&expr, MDL);
2477                 return 0;
2478         }
2479         status = option_cache (oc, (struct data_string *)0, expr,
2480                                (struct option *)0, MDL);
2481         expression_dereference (&expr, MDL);
2482         return status;
2483 }
2484
2485 /* timestamp :== date
2486
2487    Timestamps are actually not used in dhcpd.conf, which is a static file,
2488    but rather in the database file and the journal file.  (Okay, actually
2489    they're not even used there yet). */
2490
2491 TIME parse_timestamp (cfile)
2492         struct parse *cfile;
2493 {
2494         TIME rv;
2495
2496         rv = parse_date (cfile);
2497         return rv;
2498 }
2499                 
2500 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2501
2502    lease_parameters :== <nil>
2503                       | lease_parameter
2504                       | lease_parameters lease_parameter
2505
2506    lease_parameter :== STARTS date
2507                      | ENDS date
2508                      | TIMESTAMP date
2509                      | HARDWARE hardware-parameter
2510                      | UID hex_numbers SEMI
2511                      | HOSTNAME hostname SEMI
2512                      | CLIENT_HOSTNAME hostname SEMI
2513                      | CLASS identifier SEMI
2514                      | DYNAMIC_BOOTP SEMI */
2515
2516 int parse_lease_declaration (struct lease **lp, struct parse *cfile)
2517 {
2518         const char *val;
2519         enum dhcp_token token;
2520         unsigned char addr [4];
2521         unsigned len = sizeof addr;
2522         int seenmask = 0;
2523         int seenbit;
2524         char tbuf [32];
2525         struct lease *lease;
2526         struct executable_statement *on;
2527         struct expression *exp;
2528         struct data_string ds;
2529         int lose;
2530         TIME t;
2531         char *s;
2532         int noequal, newbinding;
2533         struct binding *binding;
2534         isc_result_t status;
2535         struct option_cache *oc;
2536         pair *p;
2537         binding_state_t new_state;
2538         unsigned buflen = 0;
2539         struct class *class;
2540
2541         lease = (struct lease *)0;
2542         status = lease_allocate (&lease, MDL);
2543         if (status != ISC_R_SUCCESS)
2544                 return 0;
2545
2546         /* Get the address for which the lease has been issued. */
2547         if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2548                 lease_dereference (&lease, MDL);
2549                 return 0;
2550         }
2551         memcpy (lease -> ip_addr.iabuf, addr, len);
2552         lease -> ip_addr.len = len;
2553
2554         if (!parse_lbrace (cfile)) {
2555                 lease_dereference (&lease, MDL);
2556                 return 0;
2557         }
2558
2559         do {
2560                 token = next_token (&val, (unsigned *)0, cfile);
2561                 if (token == RBRACE)
2562                         break;
2563                 else if (token == END_OF_FILE) {
2564                         parse_warn (cfile, "unexpected end of file");
2565                         break;
2566                 }
2567                 strncpy (tbuf, val, sizeof tbuf);
2568                 tbuf [(sizeof tbuf) - 1] = 0;
2569
2570                 /* Parse any of the times associated with the lease. */
2571                 switch (token) {
2572                       case STARTS:
2573                       case ENDS:
2574                       case TIMESTAMP:
2575                       case TSTP:
2576                       case TSFP:
2577                       case CLTT:
2578                         t = parse_date (cfile);
2579                         switch (token) {
2580                               case STARTS:
2581                                 seenbit = 1;
2582                                 lease -> starts = t;
2583                                 break;
2584                         
2585                               case ENDS:
2586                                 seenbit = 2;
2587                                 lease -> ends = t;
2588                                 break;
2589                                 
2590                               case TIMESTAMP:
2591                                 seenbit = 4;
2592                                 lease -> timestamp = t;
2593                                 break;
2594
2595                               case TSTP:
2596                                 seenbit = 65536;
2597                                 lease -> tstp = t;
2598                                 break;
2599                                 
2600                               case TSFP:
2601                                 seenbit = 131072;
2602                                 lease -> tsfp = t;
2603                                 break;
2604                                 
2605                               case CLTT:
2606                                 seenbit = 524288;
2607                                 lease -> cltt = t;
2608                                 break;
2609                                 
2610                               default: /* for gcc, we'll never get here. */
2611                                 log_fatal ("Impossible error at %s:%d.", MDL);
2612                                 return 0;
2613                         }
2614                         break;
2615
2616                         /* Colon-seperated hexadecimal octets... */
2617                       case UID:
2618                         seenbit = 8;
2619                         token = peek_token (&val, (unsigned *)0, cfile);
2620                         if (token == STRING) {
2621                                 unsigned char *tuid;
2622                                 token = next_token (&val, &buflen, cfile);
2623                                 if (buflen < sizeof lease -> uid_buf) {
2624                                         tuid = lease -> uid_buf;
2625                                         lease -> uid_max =
2626                                                 sizeof lease -> uid_buf;
2627                                 } else {
2628                                         tuid = ((unsigned char *)
2629                                                 dmalloc (buflen, MDL));
2630                                         if (!tuid) {
2631                                                 log_error ("no space for uid");
2632                                                 lease_dereference (&lease,
2633                                                                    MDL);
2634                                                 return 0;
2635                                         }
2636                                         lease -> uid_max = buflen;
2637                                 }
2638                                 lease -> uid_len = buflen;
2639                                 memcpy (tuid, val, lease -> uid_len);
2640                                 lease -> uid = tuid;
2641                         } else {
2642                                 buflen = 0;
2643                                 lease -> uid = (parse_numeric_aggregate
2644                                                 (cfile, (unsigned char *)0,
2645                                                  &buflen, ':', 16, 8));
2646                                 if (!lease -> uid) {
2647                                         lease_dereference (&lease, MDL);
2648                                         return 0;
2649                                 }
2650                                 lease -> uid_len = buflen;
2651                                 lease -> uid_max = buflen;
2652                                 if (lease -> uid_len == 0) {
2653                                         lease -> uid = (unsigned char *)0;
2654                                         parse_warn (cfile, "zero-length uid");
2655                                         seenbit = 0;
2656                                         parse_semi (cfile);
2657                                         break;
2658                                 }
2659                         }
2660                         parse_semi (cfile);
2661                         if (!lease -> uid) {
2662                                 log_fatal ("No memory for lease uid");
2663                         }
2664                         break;
2665                         
2666                       case CLASS:
2667                         seenbit = 32;
2668                         token = next_token (&val, (unsigned *)0, cfile);
2669                         if (!is_identifier (token)) {
2670                                 if (token != SEMI)
2671                                         skip_to_rbrace (cfile, 1);
2672                                 lease_dereference (&lease, MDL);
2673                                 return 0;
2674                         }
2675                         parse_semi (cfile);
2676                         /* for now, we aren't using this. */
2677                         break;
2678
2679                       case HARDWARE:
2680                         seenbit = 64;
2681                         parse_hardware_param (cfile,
2682                                               &lease -> hardware_addr);
2683                         break;
2684
2685                       case DYNAMIC_BOOTP:
2686                         seenbit = 256;
2687                         lease -> flags |= BOOTP_LEASE;
2688                         parse_semi (cfile);
2689                         break;
2690                         
2691                       case TOKEN_ABANDONED:
2692                         seenbit = 256;
2693                         lease -> binding_state = FTS_ABANDONED;
2694                         lease -> next_binding_state = FTS_ABANDONED;
2695                         parse_semi (cfile);
2696                         break;
2697
2698                       case TOKEN_NEXT:
2699                         seenbit = 128;
2700                         token = next_token (&val, (unsigned *)0, cfile);
2701                         if (token != BINDING) {
2702                                 parse_warn (cfile, "expecting 'binding'");
2703                                 skip_to_semi (cfile);
2704                                 break;
2705                         }
2706                         goto do_binding_state;
2707
2708                       case BINDING:
2709                         seenbit = 256;
2710
2711                       do_binding_state:
2712                         token = next_token (&val, (unsigned *)0, cfile);
2713                         if (token != STATE) {
2714                                 parse_warn (cfile, "expecting 'state'");
2715                                 skip_to_semi (cfile);
2716                                 break;
2717                         }
2718                         token = next_token (&val, (unsigned *)0, cfile);
2719                         switch (token) {
2720                               case TOKEN_ABANDONED:
2721                                 new_state = FTS_ABANDONED;
2722                                 break;
2723                               case TOKEN_FREE:
2724                                 new_state = FTS_FREE;
2725                                 break;
2726                               case TOKEN_ACTIVE:
2727                                 new_state = FTS_ACTIVE;
2728                                 break;
2729                               case TOKEN_EXPIRED:
2730                                 new_state = FTS_EXPIRED;
2731                                 break;
2732                               case TOKEN_RELEASED:
2733                                 new_state = FTS_RELEASED;
2734                                 break;
2735                               case TOKEN_RESET:
2736                                 new_state = FTS_RESET;
2737                                 break;
2738                               case TOKEN_BACKUP:
2739                                 new_state = FTS_BACKUP;
2740                                 break;
2741                               case TOKEN_RESERVED:
2742                                 new_state = FTS_ACTIVE;
2743                                 break;
2744                               case TOKEN_BOOTP:
2745                                 new_state = FTS_ACTIVE;
2746                                 lease -> flags |= BOOTP_LEASE;
2747                                 break;
2748                               default:
2749                                 parse_warn (cfile,
2750                                             "%s: expecting a binding state.",
2751                                             val);
2752                                 skip_to_semi (cfile);
2753                                 return 0;
2754                         }
2755
2756                         if (seenbit == 256) {
2757                                 lease -> binding_state = new_state;
2758
2759                                 /* If no next binding state is specified, it's
2760                                    the same as the current state. */
2761                                 if (!(seenmask & 128))
2762                                     lease -> next_binding_state = new_state;
2763                         } else
2764                                 lease -> next_binding_state = new_state;
2765                                 
2766                         parse_semi (cfile);
2767                         break;
2768
2769                       case CLIENT_HOSTNAME:
2770                         seenbit = 1024;
2771                         token = peek_token (&val, (unsigned *)0, cfile);
2772                         if (token == STRING) {
2773                                 if (!parse_string (cfile,
2774                                                    &lease -> client_hostname,
2775                                                    (unsigned *)0)) {
2776                                         lease_dereference (&lease, MDL);
2777                                         return 0;
2778                                 }
2779                         } else {
2780                                 lease -> client_hostname =
2781                                         parse_host_name (cfile);
2782                                 if (lease -> client_hostname)
2783                                         parse_semi (cfile);
2784                                 else {
2785                                         parse_warn (cfile,
2786                                                     "expecting a hostname.");
2787                                         skip_to_semi (cfile);
2788                                         lease_dereference (&lease, MDL);
2789                                         return 0;
2790                                 }
2791                         }
2792                         break;
2793                         
2794                       case BILLING:
2795                         seenbit = 2048;
2796                         class = (struct class *)0;
2797                         token = next_token (&val, (unsigned *)0, cfile);
2798                         if (token == CLASS) {
2799                                 token = next_token (&val,
2800                                                     (unsigned *)0, cfile);
2801                                 if (token != STRING) {
2802                                         parse_warn (cfile, "expecting string");
2803                                         if (token != SEMI)
2804                                                 skip_to_semi (cfile);
2805                                         token = BILLING;
2806                                         break;
2807                                 }
2808                                 if (lease -> billing_class)
2809                                     class_dereference (&lease -> billing_class,
2810                                                        MDL);
2811                                 find_class (&class, val, MDL);
2812                                 if (!class)
2813                                         parse_warn (cfile,
2814                                                     "unknown class %s", val);
2815                                 parse_semi (cfile);
2816                         } else if (token == SUBCLASS) {
2817                                 if (lease -> billing_class)
2818                                     class_dereference (&lease -> billing_class,
2819                                                        MDL);
2820                                 parse_class_declaration
2821                                         (&class,
2822                                          cfile, (struct group *)0, 3);
2823                         } else {
2824                                 parse_warn (cfile, "expecting \"class\"");
2825                                 if (token != SEMI)
2826                                         skip_to_semi (cfile);
2827                         }
2828                         if (class) {
2829                                 class_reference (&lease -> billing_class,
2830                                                  class, MDL);
2831                                 class_dereference (&class, MDL);
2832                         }
2833                         break;
2834
2835                       case ON:
2836                         on = (struct executable_statement *)0;
2837                         lose = 0;
2838                         if (!parse_on_statement (&on, cfile, &lose)) {
2839                                 skip_to_rbrace (cfile, 1);
2840                                 lease_dereference (&lease, MDL);
2841                                 return 0;
2842                         }
2843                         seenbit = 0;
2844                         if ((on -> data.on.evtypes & ON_EXPIRY) &&
2845                             on -> data.on.statements) {
2846                                 seenbit |= 16384;
2847                                 executable_statement_reference
2848                                         (&lease -> on_expiry,
2849                                          on -> data.on.statements, MDL);
2850                         }
2851                         if ((on -> data.on.evtypes & ON_RELEASE) &&
2852                             on -> data.on.statements) {
2853                                 seenbit |= 32768;
2854                                 executable_statement_reference
2855                                         (&lease -> on_release,
2856                                          on -> data.on.statements, MDL);
2857                         }
2858                         executable_statement_dereference (&on, MDL);
2859                         break;
2860                         
2861                       case OPTION:
2862                       case SUPERSEDE:
2863                         noequal = 0;
2864                         seenbit = 0;
2865                         oc = (struct option_cache *)0;
2866                         if (parse_option_decl (&oc, cfile)) {
2867                             if (oc -> option -> universe !=
2868                                 &agent_universe) {
2869                                     parse_warn (cfile,
2870                                                 "agent option expected.");
2871                                     option_cache_dereference (&oc, MDL);
2872                                     break;
2873                             }
2874                             if (!lease -> agent_options &&
2875                                 !(option_chain_head_allocate
2876                                   (&lease -> agent_options, MDL))) {
2877                                 log_error ("no memory to stash agent option");
2878                                 break;
2879                             }
2880                             for (p = &lease -> agent_options -> first;
2881                                  *p; p = &((*p) -> cdr))
2882                                     ;
2883                             *p = cons (0, 0);
2884                             option_cache_reference (((struct option_cache **)
2885                                                      &((*p) -> car)), oc, MDL);
2886                             option_cache_dereference (&oc, MDL);
2887                         }
2888                         break;
2889
2890                       case TOKEN_SET:
2891                         noequal = 0;
2892                         
2893                         token = next_token (&val, (unsigned *)0, cfile);
2894                         if (token != NAME && token != NUMBER_OR_NAME) {
2895                                 parse_warn (cfile,
2896                                             "%s can't be a variable name",
2897                                             val);
2898                               badset:
2899                                 skip_to_semi (cfile);
2900                                 lease_dereference (&lease, MDL);
2901                                 return 0;
2902                         }
2903                         
2904                         seenbit = 0;
2905                       special_set:
2906                         if (lease -> scope)
2907                                 binding = find_binding (lease -> scope, val);
2908                         else
2909                                 binding = (struct binding *)0;
2910                         if (!binding) {
2911                             if (!lease -> scope)
2912                                 if (!(binding_scope_allocate
2913                                       (&lease -> scope, MDL)))
2914                                         log_fatal ("no memory for scope");
2915                             binding = dmalloc (sizeof *binding, MDL);
2916                             if (!binding)
2917                                     log_fatal ("No memory for lease %s.",
2918                                                "binding");
2919                             memset (binding, 0, sizeof *binding);
2920                             binding -> name =
2921                                     dmalloc (strlen (val) + 1, MDL);
2922                             if (!binding -> name)
2923                                     log_fatal ("No memory for binding %s.",
2924                                                "name");
2925                             strcpy (binding -> name, val);
2926                             newbinding = 1;
2927                         } else  {
2928                                 if (binding -> value)
2929                                   binding_value_dereference (&binding -> value,
2930                                                            MDL);
2931                                 newbinding = 0;
2932                         }
2933
2934                         if (!binding_value_allocate (&binding -> value, MDL))
2935                                 log_fatal ("no memory for binding value.");
2936
2937                         if (!noequal) {
2938                             token = next_token (&val, (unsigned *)0, cfile);
2939                             if (token != EQUAL) {
2940                                 parse_warn (cfile,
2941                                             "expecting '=' in set statement.");
2942                                 goto badset;
2943                             }
2944                         }
2945
2946                         token = peek_token (&val, (unsigned *)0, cfile);
2947                         if (token == STRING) {
2948                             unsigned char *tuid;
2949                             token = next_token (&val, &buflen, cfile);
2950                             binding -> value -> type = binding_data;
2951                             binding -> value -> value.data.len = buflen;
2952                             if (!(buffer_allocate
2953                                   (&binding -> value -> value.data.buffer,
2954                                    buflen + 1, MDL)))
2955                                 log_fatal ("No memory for binding.");
2956                             memcpy ((char *)
2957                                     (binding -> value ->
2958                                      value.data.buffer -> data),
2959                                     val, buflen + 1);
2960                             binding -> value -> value.data.data =
2961                                 binding -> value -> value.data.buffer -> data;
2962                             binding -> value -> value.data.terminated = 1;
2963                         } else if (token == NUMBER_OR_NAME) {
2964                             binding -> value -> type = binding_data;
2965                             s = ((char *)
2966                                  (parse_numeric_aggregate
2967                                   (cfile, (unsigned char *)0,
2968                                    &binding -> value -> value.data.len,
2969                                    ':', 16, 8)));
2970                             if (!s) {
2971                                     binding_value_dereference
2972                                             (&binding -> value, MDL);
2973                                     lease_dereference (&lease, MDL);
2974                                     return 0;
2975                             }
2976                             if (binding -> value -> value.data.len) {
2977                                 if (!(buffer_allocate
2978                                       (&binding -> value -> value.data.buffer,
2979                                        binding -> value -> value.data.len + 1,
2980                                        MDL)))
2981                                         log_fatal ("No memory for binding.");
2982                                 memcpy ((binding -> value ->
2983                                          value.data.buffer -> data), s,
2984                                         binding -> value -> value.data.len);
2985                                 dfree (s, MDL);
2986                                 binding -> value -> value.data.data =
2987                                  binding -> value -> value.data.buffer -> data;
2988                             }
2989                         } else if (token == PERCENT) {
2990                             token = next_token (&val, (unsigned *)0, cfile);
2991                             token = next_token (&val, (unsigned *)0, cfile);
2992                             if (token != NUMBER) {
2993                                     parse_warn (cfile,
2994                                                 "expecting decimal number.");
2995                                     if (token != SEMI)
2996                                             skip_to_semi (cfile);
2997                                     binding_value_dereference
2998                                             (&binding -> value, MDL);
2999                                     lease_dereference (&lease, MDL);
3000                                     return 0;
3001                             }
3002                             binding -> value -> type = binding_numeric;
3003                             binding -> value -> value.intval = atol (val);
3004                         } else if (token == NAME) {
3005                                 token = next_token (&val,
3006                                                     (unsigned *)0, cfile);
3007                                 binding -> value -> type = binding_boolean;
3008                                 if (!strcasecmp (val, "true"))
3009                                         binding -> value -> value.boolean = 1;
3010                                 else if (!strcasecmp (val, "false"))
3011                                         binding -> value -> value.boolean = 0;
3012                                 else
3013                                         goto badbool;
3014                         } else {
3015                               badbool:
3016                                 parse_warn (cfile,
3017                                             "expecting a constant value.");
3018                                 skip_to_semi (cfile);
3019                                 binding_value_dereference (&binding -> value,
3020                                                            MDL);
3021                                 lease_dereference (&lease, MDL);
3022                                 return 0;
3023                         }
3024                                 
3025                         if (newbinding) {
3026                                 binding -> next = lease -> scope -> bindings;
3027                                 lease -> scope -> bindings = binding;
3028                         }
3029                         parse_semi (cfile);
3030                         break;
3031
3032                       default:
3033                         if (!strcasecmp (val, "ddns-fwd-name")) {
3034                                 seenbit = 4096;
3035                                 noequal = 1;
3036                                 goto special_set;
3037                         } else if (!strcasecmp (val, "ddns-rev-name")) {
3038                                 seenbit = 8192;
3039                                 noequal = 1;
3040                                 goto special_set;
3041                         }
3042                         skip_to_semi (cfile);
3043                         seenbit = 0;
3044                         lease_dereference (&lease, MDL);
3045                         return 0;
3046                 }
3047
3048                 if (seenmask & seenbit) {
3049                         parse_warn (cfile,
3050                                     "Too many %s parameters in lease %s\n",
3051                                     tbuf, piaddr (lease -> ip_addr));
3052                 } else
3053                         seenmask |= seenbit;
3054
3055         } while (1);
3056
3057         /* If no binding state is specified, make one up. */
3058         if (!(seenmask & 256)) {
3059                 if (lease -> ends > cur_time ||
3060                     lease -> on_expiry || lease -> on_release)
3061                         lease -> binding_state = FTS_ACTIVE;
3062 #if defined (FAILOVER_PROTOCOL)
3063                 else if (lease -> pool && lease -> pool -> failover_peer)
3064                         lease -> binding_state = FTS_EXPIRED;
3065 #endif
3066                 else
3067                         lease -> binding_state = FTS_FREE;
3068                 if (lease -> binding_state == FTS_ACTIVE) {
3069 #if defined (FAILOVER_PROTOCOL)
3070                         if (lease -> pool && lease -> pool -> failover_peer)
3071                                 lease -> next_binding_state = FTS_EXPIRED;
3072                         else
3073 #endif
3074                                 lease -> next_binding_state = FTS_FREE;
3075                 } else
3076                         lease -> next_binding_state = lease -> binding_state;
3077         }
3078
3079         if (!(seenmask & 65536))
3080                 lease -> tstp = lease -> ends;
3081
3082         lease_reference (lp, lease, MDL);
3083         lease_dereference (&lease, MDL);
3084         return 1;
3085 }
3086
3087 /* address-range-declaration :== ip-address ip-address SEMI
3088                                | DYNAMIC_BOOTP ip-address ip-address SEMI */
3089
3090 void parse_address_range (cfile, group, type, inpool, lpchain)
3091         struct parse *cfile;
3092         struct group *group;
3093         int type;
3094         struct pool *inpool;
3095         struct lease **lpchain;
3096 {
3097         struct iaddr low, high, net;
3098         unsigned char addr [4];
3099         unsigned len = sizeof addr;
3100         enum dhcp_token token;
3101         const char *val;
3102         int dynamic = 0;
3103         struct subnet *subnet;
3104         struct shared_network *share;
3105         struct pool *p;
3106         struct pool *pool;
3107         isc_result_t status;
3108
3109         if ((token = peek_token (&val,
3110                                  (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3111                 token = next_token (&val, (unsigned *)0, cfile);
3112                 dynamic = 1;
3113         }
3114
3115         /* Get the bottom address in the range... */
3116         if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3117                 return;
3118         memcpy (low.iabuf, addr, len);
3119         low.len = len;
3120
3121         /* Only one address? */
3122         token = peek_token (&val, (unsigned *)0, cfile);
3123         if (token == SEMI)
3124                 high = low;
3125         else {
3126         /* Get the top address in the range... */
3127                 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3128                         return;
3129                 memcpy (high.iabuf, addr, len);
3130                 high.len = len;
3131         }
3132
3133         token = next_token (&val, (unsigned *)0, cfile);
3134         if (token != SEMI) {
3135                 parse_warn (cfile, "semicolon expected.");
3136                 skip_to_semi (cfile);
3137                 return;
3138         }
3139
3140         if (type == SUBNET_DECL) {
3141                 subnet = group -> subnet;
3142                 share = subnet -> shared_network;
3143         } else {
3144                 share = group -> shared_network;
3145                 for (subnet = share -> subnets;
3146                      subnet; subnet = subnet -> next_sibling) {
3147                         net = subnet_number (low, subnet -> netmask);
3148                         if (addr_eq (net, subnet -> net))
3149                                 break;
3150                 }
3151                 if (!subnet) {
3152                         parse_warn (cfile, "address range not on network %s",
3153                                     group -> shared_network -> name);
3154                         log_error ("Be sure to place pool statement after %s",
3155                                    "related subnet declarations.");
3156                         return;
3157                 }
3158         }
3159
3160         if (!inpool) {
3161                 struct pool *last = (struct pool *)0;
3162
3163                 /* If we're permitting dynamic bootp for this range,
3164                    then look for a pool with an empty prohibit list and
3165                    a permit list with one entry that permits all clients. */
3166                 for (pool = share -> pools; pool; pool = pool -> next) {
3167                         if ((!dynamic && !pool -> permit_list && 
3168                              pool -> prohibit_list &&
3169                              !pool -> prohibit_list -> next &&
3170                              (pool -> prohibit_list -> type ==
3171                               permit_dynamic_bootp_clients)) ||
3172                             (dynamic && !pool -> prohibit_list &&
3173                              pool -> permit_list &&
3174                              !pool -> permit_list -> next &&
3175                              (pool -> permit_list -> type ==
3176                               permit_all_clients))) {
3177                                 break;
3178                         }
3179                         last = pool;
3180                 }
3181
3182                 /* If we didn't get a pool, make one. */
3183                 if (!pool) {
3184                         struct permit *p;
3185                         status = pool_allocate (&pool, MDL);
3186                         if (status != ISC_R_SUCCESS)
3187                                 log_fatal ("no memory for ad-hoc pool: %s",
3188                                            isc_result_totext (status));
3189                         p = new_permit (MDL);
3190                         if (!p)
3191                                 log_fatal ("no memory for ad-hoc permit.");
3192
3193                         /* Dynamic pools permit all clients.   Otherwise
3194                            we prohibit BOOTP clients. */
3195                         if (dynamic) {
3196                                 p -> type = permit_all_clients;
3197                                 pool -> permit_list = p;
3198                         } else {
3199                                 p -> type = permit_dynamic_bootp_clients;
3200                                 pool -> prohibit_list = p;
3201                         }
3202
3203                         if (share -> pools)
3204                                 pool_reference (&last -> next, pool, MDL);
3205                         else
3206                                 pool_reference (&share -> pools, pool, MDL);
3207                         shared_network_reference (&pool -> shared_network,
3208                                                   share, MDL);
3209                         if (!clone_group (&pool -> group, share -> group, MDL))
3210                                 log_fatal ("no memory for anon pool group.");
3211                 } else {
3212                         pool = (struct pool *)0;
3213                         if (last)
3214                                 pool_reference (&pool, last, MDL);
3215                         else
3216                                 pool_reference (&pool, share -> pools, MDL);
3217                 }
3218         } else {
3219                 pool = (struct pool *)0;
3220                 pool_reference (&pool, inpool, MDL);
3221         }
3222
3223 #if defined (FAILOVER_PROTOCOL)
3224         if (pool -> failover_peer && dynamic) {
3225                 /* Doctor, do you think I'm overly sensitive
3226                    about getting bug reports I can't fix? */
3227                 parse_warn (cfile, "dynamic-bootp flag is %s",
3228                             "not permitted for address");
3229                 log_error ("range declarations where there is a failover");
3230                 log_error ("peer in scope.   If you wish to declare an");
3231                 log_error ("address range from which dynamic bootp leases");
3232                 log_error ("can be allocated, please declare it within a");
3233                 log_error ("pool declaration that also contains the \"no");
3234                 log_error ("failover\" statement.   The failover protocol");
3235                 log_error ("itself does not permit dynamic bootp - this");
3236                 log_error ("is not a limitation specific to the ISC DHCP");
3237                 log_error ("server.   Please don't ask me to defend this");
3238                 log_error ("until you have read and really tried %s",
3239                            "to understand");
3240                 log_error ("the failover protocol specification.");
3241
3242                 /* We don't actually bomb at this point - instead,
3243                    we let parse_lease_file notice the error and
3244                    bomb at that point - it's easier. */
3245         }
3246 #endif /* FAILOVER_PROTOCOL */
3247
3248         /* Create the new address range... */
3249         new_address_range (cfile, low, high, subnet, pool, lpchain);
3250         pool_dereference (&pool, MDL);
3251 }
3252
3253 /* allow-deny-keyword :== BOOTP
3254                         | BOOTING
3255                         | DYNAMIC_BOOTP
3256                         | UNKNOWN_CLIENTS */
3257
3258 int parse_allow_deny (oc, cfile, flag)
3259         struct option_cache **oc;
3260         struct parse *cfile;
3261         int flag;
3262 {
3263         enum dhcp_token token;
3264         const char *val;
3265         unsigned char rf = flag;
3266         struct expression *data = (struct expression *)0;
3267         int status;
3268
3269         if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
3270                 return 0;
3271
3272         token = next_token (&val, (unsigned *)0, cfile);
3273         switch (token) {
3274               case TOKEN_BOOTP:
3275                 status = option_cache (oc, (struct data_string *)0, data,
3276                                        &server_options [SV_ALLOW_BOOTP], MDL);
3277                 break;
3278
3279               case BOOTING:
3280                 status = option_cache (oc, (struct data_string *)0, data,
3281                                        &server_options [SV_ALLOW_BOOTING],
3282                                        MDL);
3283                 break;
3284
3285               case DYNAMIC_BOOTP:
3286                 status = option_cache (oc, (struct data_string *)0, data,
3287                                        &server_options [SV_DYNAMIC_BOOTP],
3288                                        MDL);
3289                 break;
3290
3291               case UNKNOWN_CLIENTS:
3292                 status = (option_cache
3293                           (oc, (struct data_string *)0, data,
3294                            &server_options [SV_BOOT_UNKNOWN_CLIENTS], MDL));
3295                 break;
3296
3297               case DUPLICATES:
3298                 status = option_cache (oc, (struct data_string *)0, data,
3299                                        &server_options [SV_DUPLICATES], MDL);
3300                 break;
3301
3302               case DECLINES:
3303                 status = option_cache (oc, (struct data_string *)0, data,
3304                                        &server_options [SV_DECLINES], MDL);
3305                 break;
3306
3307               case CLIENT_UPDATES:
3308                 status = option_cache (oc, (struct data_string *)0, data,
3309                                        &server_options [SV_CLIENT_UPDATES],
3310                                        MDL);
3311                 break;
3312
3313               default:
3314                 parse_warn (cfile, "expecting allow/deny key");
3315                 skip_to_semi (cfile);
3316                 return 0;
3317         }
3318         expression_dereference (&data, MDL);
3319         parse_semi (cfile);
3320         return status;
3321 }
3322