3 Parser for dhclient config and lease files... */
6 * Copyright (c) 1996-2002 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
43 * @(#) Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.
44 * $Id: clparse.c,v 1.62.2.3 2002/11/17 02:25:43 dhankins Exp $
45 * $FreeBSD: src/contrib/isc-dhcp/client/clparse.c,v 1.4.2.4 2003/03/02 16:42:37 murray Exp $
46 * $DragonFly: src/contrib/isc-dhcp/client/Attic/clparse.c,v 1.2 2003/06/17 04:24:02 dillon Exp $
49 static char copyright[] =
50 "$Id: clparse.c,v 1.62.2.3 2002/11/17 02:25:43 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n";
54 static TIME parsed_time;
56 struct client_config top_level_config;
58 char client_script_name [] = "/sbin/dhclient-script";
60 u_int32_t default_requested_options [] = {
62 DHO_BROADCAST_ADDRESS,
66 DHO_DOMAIN_NAME_SERVERS,
71 /* client-conf-file :== client-declarations END_OF_FILE
72 client-declarations :== <nil>
74 | client-declarations client-declaration */
76 isc_result_t read_client_conf ()
78 struct client_config *config;
79 struct client_state *state;
80 struct interface_info *ip;
83 /* Set up the initial dhcp option universe. */
84 initialize_common_option_spaces ();
86 /* Initialize the top level client configuration. */
87 memset (&top_level_config, 0, sizeof top_level_config);
89 /* Set some defaults... */
90 top_level_config.timeout = 60;
91 top_level_config.select_interval = 0;
92 top_level_config.reboot_timeout = 10;
93 top_level_config.retry_interval = 300;
94 top_level_config.backoff_cutoff = 15;
95 top_level_config.initial_interval = 3;
96 top_level_config.bootp_policy = P_ACCEPT;
97 top_level_config.script_name = path_dhclient_script;
98 top_level_config.requested_options = default_requested_options;
99 top_level_config.omapi_port = -1;
100 top_level_config.do_forward_update = 1;
102 group_allocate (&top_level_config.on_receipt, MDL);
103 if (!top_level_config.on_receipt)
104 log_fatal ("no memory for top-level on_receipt group");
106 group_allocate (&top_level_config.on_transmission, MDL);
107 if (!top_level_config.on_transmission)
108 log_fatal ("no memory for top-level on_transmission group");
110 status = read_client_conf_file (path_dhclient_conf,
111 (struct interface_info *)0,
113 if (status != ISC_R_SUCCESS) {
116 /* Set up the standard name service updater routine. */
117 parse = (struct parse *)0;
118 status = new_parse (&parse, -1, default_client_config,
119 (sizeof default_client_config) - 1,
120 "default client configuration", 0);
121 if (status != ISC_R_SUCCESS)
122 log_fatal ("can't begin default client config!");
125 token = peek_token (&val, (unsigned *)0, cfile);
126 if (token == END_OF_FILE)
128 parse_client_statement (cfile,
129 (struct interface_info *)0,
136 /* Set up state and config structures for clients that don't
137 have per-interface configuration statements. */
138 config = (struct client_config *)0;
139 for (ip = interfaces; ip; ip = ip -> next) {
141 ip -> client = (struct client_state *)
142 dmalloc (sizeof (struct client_state), MDL);
144 log_fatal ("no memory for client state.");
145 memset (ip -> client, 0, sizeof *(ip -> client));
146 ip -> client -> interface = ip;
149 if (!ip -> client -> config) {
151 config = (struct client_config *)
152 dmalloc (sizeof (struct client_config),
155 log_fatal ("no memory for client config.");
156 memcpy (config, &top_level_config,
157 sizeof top_level_config);
159 ip -> client -> config = config;
165 int read_client_conf_file (const char *name, struct interface_info *ip,
166 struct client_config *client)
174 if ((file = open (name, O_RDONLY)) < 0)
175 return uerr2isc (errno);
177 cfile = (struct parse *)0;
178 new_parse (&cfile, file, (char *)0, 0, path_dhclient_conf, 0);
181 token = peek_token (&val, (unsigned *)0, cfile);
182 if (token == END_OF_FILE)
184 parse_client_statement (cfile, ip, client);
186 token = next_token (&val, (unsigned *)0, cfile);
187 status = (cfile -> warnings_occurred
196 /* lease-file :== client-lease-statements END_OF_FILE
197 client-lease-statements :== <nil>
198 | client-lease-statements LEASE client-lease-statement */
200 void read_client_leases ()
207 /* Open the lease file. If we can't open it, just return -
208 we can safely trust the server to remember our state. */
209 if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
211 cfile = (struct parse *)0;
212 new_parse (&cfile, file, (char *)0, 0, path_dhclient_db, 0);
215 token = next_token (&val, (unsigned *)0, cfile);
216 if (token == END_OF_FILE)
218 if (token != LEASE) {
219 log_error ("Corrupt lease file - possible data loss!");
220 skip_to_semi (cfile);
223 parse_client_lease_statement (cfile, 0);
231 /* client-declaration :==
233 DEFAULT option-decl |
234 SUPERSEDE option-decl |
235 PREPEND option-decl |
237 hardware-declaration |
238 REQUEST option-list |
239 REQUIRE option-list |
243 SELECT_TIMEOUT number |
245 VENDOR_SPACE string |
246 interface-declaration |
247 LEASE client-lease-statement |
248 ALIAS client-lease-statement |
249 KEY key-definition */
251 void parse_client_statement (cfile, ip, config)
253 struct interface_info *ip;
254 struct client_config *config;
258 struct option *option;
259 struct executable_statement *stmt, **p;
260 enum statement_op op;
263 struct data_string key_id;
269 switch (peek_token (&val, (unsigned *)0, cfile)) {
271 next_token (&val, (unsigned *)0, cfile);
272 token = next_token (&val, (unsigned *)0, cfile);
273 if (token != STRING) {
274 parse_warn (cfile, "filename string expected.");
275 skip_to_semi (cfile);
277 status = read_client_conf_file (val, ip, config);
278 if (status != ISC_R_SUCCESS)
279 parse_warn (cfile, "%s: bad parse.", val);
285 next_token (&val, (unsigned *)0, cfile);
287 /* This may seem arbitrary, but there's a reason for
288 doing it: the authentication key database is not
289 scoped. If we allow the user to declare a key other
290 than in the outer scope, the user is very likely to
291 believe that the key will only be used in that
292 scope. If the user only wants the key to be used on
293 one interface, because it's known that the other
294 interface may be connected to an insecure net and
295 the secret key is considered sensitive, we don't
296 want to lull them into believing they've gotten
297 their way. This is a bit contrived, but people
298 tend not to be entirely rational about security. */
299 parse_warn (cfile, "key definition not allowed here.");
300 skip_to_semi (cfile);
306 /* REQUIRE can either start a policy statement or a
307 comma-seperated list of names of required options. */
309 next_token (&val, (unsigned *)0, cfile);
310 token = peek_token (&val, (unsigned *)0, cfile);
311 if (token == AUTHENTICATION) {
315 parse_option_list (cfile, &config -> required_options);
319 next_token (&val, (unsigned *)0, cfile);
324 next_token (&val, (unsigned *)0, cfile);
329 next_token (&val, (unsigned *)0, cfile);
334 next_token (&val, (unsigned *)0, cfile);
339 token = next_token (&val, (unsigned *)0, cfile);
340 if (token == AUTHENTICATION) {
341 if (policy != P_PREFER &&
342 policy != P_REQUIRE &&
345 "invalid authentication policy.");
346 skip_to_semi (cfile);
349 config -> auth_policy = policy;
350 } else if (token != TOKEN_BOOTP) {
351 if (policy != P_PREFER &&
352 policy != P_IGNORE &&
353 policy != P_ACCEPT) {
354 parse_warn (cfile, "invalid bootp policy.");
355 skip_to_semi (cfile);
358 config -> bootp_policy = policy;
360 parse_warn (cfile, "expecting a policy type.");
361 skip_to_semi (cfile);
367 token = next_token (&val, (unsigned *)0, cfile);
369 token = peek_token (&val, (unsigned *)0, cfile);
370 if (token == SPACE) {
373 "option space definitions %s",
374 " may not be scoped.");
375 skip_to_semi (cfile);
378 parse_option_space_decl (cfile);
382 option = parse_option_name (cfile, 1, &known);
386 token = next_token (&val, (unsigned *)0, cfile);
388 parse_warn (cfile, "expecting \"code\" keyword.");
389 skip_to_semi (cfile);
390 free_option (option, MDL);
395 "option definitions may only appear in %s",
396 "the outermost scope.");
397 skip_to_semi (cfile);
398 free_option (option, MDL);
401 if (!parse_option_code_definition (cfile, option))
402 free_option (option, MDL);
406 token = next_token (&val, (unsigned *)0, cfile);
407 parse_string_list (cfile, &config -> media, 1);
411 token = next_token (&val, (unsigned *)0, cfile);
413 parse_hardware_param (cfile, &ip -> hw_address);
415 parse_warn (cfile, "hardware address parameter %s",
416 "not allowed here.");
417 skip_to_semi (cfile);
422 token = next_token (&val, (unsigned *)0, cfile);
423 if (config -> requested_options == default_requested_options)
424 config -> requested_options = (u_int32_t *)0;
425 parse_option_list (cfile, &config -> requested_options);
429 token = next_token (&val, (unsigned *)0, cfile);
430 parse_lease_time (cfile, &config -> timeout);
434 token = next_token (&val, (unsigned *)0, cfile);
435 parse_lease_time (cfile, &config -> retry_interval);
439 token = next_token (&val, (unsigned *)0, cfile);
440 parse_lease_time (cfile, &config -> select_interval);
444 token = next_token (&val, (unsigned *)0, cfile);
445 token = next_token (&val, (unsigned *)0, cfile);
448 "unexpected omapi subtype: %s", val);
449 skip_to_semi (cfile);
452 token = next_token (&val, (unsigned *)0, cfile);
453 if (token != NUMBER) {
454 parse_warn (cfile, "invalid port number: `%s'", val);
455 skip_to_semi (cfile);
459 if (tmp < 0 || tmp > 65535)
460 parse_warn (cfile, "invalid omapi port %d.", tmp);
461 else if (config != &top_level_config)
463 "omapi port only works at top level.");
465 config -> omapi_port = tmp;
469 case DO_FORWARD_UPDATE:
470 token = next_token (&val, (unsigned *)0, cfile);
471 token = next_token (&val, (unsigned *)0, cfile);
472 if (!strcasecmp (val, "on") ||
473 !strcasecmp (val, "true"))
474 config -> do_forward_update = 1;
475 else if (!strcasecmp (val, "off") ||
476 !strcasecmp (val, "false"))
477 config -> do_forward_update = 0;
479 parse_warn (cfile, "expecting boolean value.");
480 skip_to_semi (cfile);
487 token = next_token (&val, (unsigned *)0, cfile);
488 parse_lease_time (cfile, &config -> reboot_timeout);
492 token = next_token (&val, (unsigned *)0, cfile);
493 parse_lease_time (cfile, &config -> backoff_cutoff);
496 case INITIAL_INTERVAL:
497 token = next_token (&val, (unsigned *)0, cfile);
498 parse_lease_time (cfile, &config -> initial_interval);
502 token = next_token (&val, (unsigned *)0, cfile);
503 parse_string (cfile, &config -> script_name, (unsigned *)0);
507 token = next_token (&val, (unsigned *)0, cfile);
508 token = next_token (&val, (unsigned *)0, cfile);
509 if (token != OPTION) {
510 parse_warn (cfile, "expecting 'vendor option space'");
511 skip_to_semi (cfile);
514 token = next_token (&val, (unsigned *)0, cfile);
515 if (token != SPACE) {
516 parse_warn (cfile, "expecting 'vendor option space'");
517 skip_to_semi (cfile);
520 token = next_token (&val, (unsigned *)0, cfile);
521 if (!is_identifier (token)) {
522 parse_warn (cfile, "expecting an identifier.");
523 skip_to_semi (cfile);
526 config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
527 if (!config -> vendor_space_name)
528 log_fatal ("no memory for vendor option space name.");
529 strcpy (config -> vendor_space_name, val);
530 for (i = 0; i < universe_count; i++)
531 if (!strcmp (universes [i] -> name,
532 config -> vendor_space_name))
534 if (i == universe_count) {
535 log_error ("vendor option space %s not found.",
536 config -> vendor_space_name);
542 token = next_token (&val, (unsigned *)0, cfile);
544 parse_warn (cfile, "nested interface declaration.");
545 parse_interface_declaration (cfile, config, (char *)0);
549 token = next_token (&val, (unsigned *)0, cfile);
550 token = next_token (&val, (unsigned *)0, cfile);
551 name = dmalloc (strlen (val) + 1, MDL);
553 log_fatal ("no memory for pseudo interface name");
555 parse_interface_declaration (cfile, config, name);
559 token = next_token (&val, (unsigned *)0, cfile);
560 parse_client_lease_statement (cfile, 1);
564 token = next_token (&val, (unsigned *)0, cfile);
565 parse_client_lease_statement (cfile, 2);
569 token = next_token (&val, (unsigned *)0, cfile);
570 parse_reject_statement (cfile, config);
575 stmt = (struct executable_statement *)0;
576 if (!parse_executable_statement (&stmt,
577 cfile, &lose, context_any)) {
579 parse_warn (cfile, "expecting a statement.");
580 skip_to_semi (cfile);
583 struct executable_statement **eptr, *sptr;
585 (stmt -> op == send_option_statement ||
586 (stmt -> op == on_statement &&
587 (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
588 eptr = &config -> on_transmission -> statements;
589 if (stmt -> op == on_statement) {
590 sptr = (struct executable_statement *)0;
591 executable_statement_reference
593 stmt -> data.on.statements, MDL);
594 executable_statement_dereference (&stmt,
596 executable_statement_reference (&stmt,
599 executable_statement_dereference (&sptr,
603 eptr = &config -> on_receipt -> statements;
606 for (; *eptr; eptr = &(*eptr) -> next)
608 executable_statement_reference (eptr,
618 /* option-list :== option_name |
619 option_list COMMA option_name */
621 void parse_option_list (cfile, list)
628 pair p = (pair)0, q, r;
632 token = next_token (&val, (unsigned *)0, cfile);
635 if (!is_identifier (token)) {
636 parse_warn (cfile, "%s: expected option name.", val);
637 skip_to_semi (cfile);
640 for (i = 0; i < 256; i++) {
641 if (!strcasecmp (dhcp_options [i].name, val))
645 parse_warn (cfile, "%s: expected option name.", val);
646 skip_to_semi (cfile);
651 log_fatal ("can't allocate pair for option code.");
652 r -> car = (caddr_t)(long)i;
660 token = next_token (&val, (unsigned *)0, cfile);
661 } while (token == COMMA);
663 parse_warn (cfile, "expecting semicolon.");
664 skip_to_semi (cfile);
667 /* XXX we can't free the list here, because we may have copied
668 XXX it from an outer config state. */
669 *list = (u_int32_t *)0;
671 *list = dmalloc ((ix + 1) * sizeof **list, MDL);
673 log_error ("no memory for option list.");
676 for (q = p; q; q = q -> cdr)
677 (*list) [ix++] = (u_int32_t)(long)q -> car;
688 /* interface-declaration :==
689 INTERFACE string LBRACE client-declarations RBRACE */
691 void parse_interface_declaration (cfile, outer_config, name)
693 struct client_config *outer_config;
698 struct client_state *client, **cp;
699 struct interface_info *ip = (struct interface_info *)0;
701 token = next_token (&val, (unsigned *)0, cfile);
702 if (token != STRING) {
703 parse_warn (cfile, "expecting interface name (in quotes).");
704 skip_to_semi (cfile);
708 if (!interface_or_dummy (&ip, val))
709 log_fatal ("Can't allocate interface %s.", val);
711 /* If we were given a name, this is a pseudo-interface. */
713 make_client_state (&client);
714 client -> name = name;
715 client -> interface = ip;
716 for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
721 make_client_state (&ip -> client);
722 ip -> client -> interface = ip;
724 client = ip -> client;
727 if (!client -> config)
728 make_client_config (client, outer_config);
730 ip -> flags &= ~INTERFACE_AUTOMATIC;
731 interfaces_requested = 1;
733 token = next_token (&val, (unsigned *)0, cfile);
734 if (token != LBRACE) {
735 parse_warn (cfile, "expecting left brace.");
736 skip_to_semi (cfile);
741 token = peek_token (&val, (unsigned *)0, cfile);
742 if (token == END_OF_FILE) {
744 "unterminated interface declaration.");
749 parse_client_statement (cfile, ip, client -> config);
751 token = next_token (&val, (unsigned *)0, cfile);
754 int interface_or_dummy (struct interface_info **pi, const char *name)
756 struct interface_info *i;
757 struct interface_info *ip = (struct interface_info *)0;
760 /* Find the interface (if any) that matches the name. */
761 for (i = interfaces; i; i = i -> next) {
762 if (!strcmp (i -> name, name)) {
763 interface_reference (&ip, i, MDL);
768 /* If it's not a real interface, see if it's on the dummy list. */
770 for (ip = dummy_interfaces; ip; ip = ip -> next) {
771 if (!strcmp (ip -> name, name)) {
772 interface_reference (&ip, i, MDL);
778 /* If we didn't find an interface, make a dummy interface as
782 status = interface_allocate (&ip, MDL);
783 if (status != ISC_R_SUCCESS)
784 log_fatal ("Can't record interface %s: %s",
785 name, isc_result_totext (status));
786 strlcpy (ip -> name, name, IFNAMSIZ);
787 if (dummy_interfaces) {
788 interface_reference (&ip -> next,
789 dummy_interfaces, MDL);
790 interface_dereference (&dummy_interfaces, MDL);
792 interface_reference (&dummy_interfaces, ip, MDL);
795 status = interface_reference (pi, ip, MDL);
796 interface_dereference (&ip, MDL);
797 if (status != ISC_R_SUCCESS)
802 void make_client_state (state)
803 struct client_state **state;
805 *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
807 log_fatal ("no memory for client state\n");
808 memset (*state, 0, sizeof **state);
811 void make_client_config (client, config)
812 struct client_state *client;
813 struct client_config *config;
815 client -> config = (((struct client_config *)
816 dmalloc (sizeof (struct client_config), MDL)));
817 if (!client -> config)
818 log_fatal ("no memory for client config\n");
819 memcpy (client -> config, config, sizeof *config);
820 if (!clone_group (&client -> config -> on_receipt,
821 config -> on_receipt, MDL) ||
822 !clone_group (&client -> config -> on_transmission,
823 config -> on_transmission, MDL))
824 log_fatal ("no memory for client state groups.");
827 /* client-lease-statement :==
828 RBRACE client-lease-declarations LBRACE
830 client-lease-declarations :==
832 client-lease-declaration |
833 client-lease-declarations client-lease-declaration */
836 void parse_client_lease_statement (cfile, is_static)
840 struct client_lease *lease, *lp, *pl;
841 struct interface_info *ip = (struct interface_info *)0;
844 struct client_state *client = (struct client_state *)0;
846 token = next_token (&val, (unsigned *)0, cfile);
847 if (token != LBRACE) {
848 parse_warn (cfile, "expecting left brace.");
849 skip_to_semi (cfile);
853 lease = ((struct client_lease *)
854 dmalloc (sizeof (struct client_lease), MDL));
856 log_fatal ("no memory for lease.\n");
857 memset (lease, 0, sizeof *lease);
858 lease -> is_static = is_static;
859 if (!option_state_allocate (&lease -> options, MDL))
860 log_fatal ("no memory for lease options.\n");
863 token = peek_token (&val, (unsigned *)0, cfile);
864 if (token == END_OF_FILE) {
865 parse_warn (cfile, "unterminated lease declaration.");
870 parse_client_lease_declaration (cfile, lease, &ip, &client);
872 token = next_token (&val, (unsigned *)0, cfile);
874 /* If the lease declaration didn't include an interface
875 declaration that we recognized, it's of no use to us. */
877 destroy_client_lease (lease);
881 /* Make sure there's a client state structure... */
883 make_client_state (&ip -> client);
884 ip -> client -> interface = ip;
887 client = ip -> client;
889 /* If this is an alias lease, it doesn't need to be sorted in. */
890 if (is_static == 2) {
891 ip -> client -> alias = lease;
895 /* The new lease may supersede a lease that's not the
896 active lease but is still on the lease list, so scan the
897 lease list looking for a lease with the same address, and
898 if we find it, toss it. */
899 pl = (struct client_lease *)0;
900 for (lp = client -> leases; lp; lp = lp -> next) {
901 if (lp -> address.len == lease -> address.len &&
902 !memcmp (lp -> address.iabuf, lease -> address.iabuf,
903 lease -> address.len)) {
905 pl -> next = lp -> next;
907 client -> leases = lp -> next;
908 destroy_client_lease (lp);
913 /* If this is a preloaded lease, just put it on the list of recorded
914 leases - don't make it the active lease. */
916 lease -> next = client -> leases;
917 client -> leases = lease;
921 /* The last lease in the lease file on a particular interface is
922 the active lease for that interface. Of course, we don't know
923 what the last lease in the file is until we've parsed the whole
924 file, so at this point, we assume that the lease we just parsed
925 is the active lease for its interface. If there's already
926 an active lease for the interface, and this lease is for the same
927 ip address, then we just toss the old active lease and replace
928 it with this one. If this lease is for a different address,
929 then if the old active lease has expired, we dump it; if not,
930 we put it on the list of leases for this interface which are
931 still valid but no longer active. */
932 if (client -> active) {
933 if (client -> active -> expiry < cur_time)
934 destroy_client_lease (client -> active);
935 else if (client -> active -> address.len ==
936 lease -> address.len &&
937 !memcmp (client -> active -> address.iabuf,
938 lease -> address.iabuf,
939 lease -> address.len))
940 destroy_client_lease (client -> active);
942 client -> active -> next = client -> leases;
943 client -> leases = client -> active;
946 client -> active = lease;
951 /* client-lease-declaration :==
954 FIXED_ADDR ip_address |
963 void parse_client_lease_declaration (cfile, lease, ipp, clientp)
965 struct client_lease *lease;
966 struct interface_info **ipp;
967 struct client_state **clientp;
972 struct interface_info *ip;
973 struct option_cache *oc;
974 struct client_state *client = (struct client_state *)0;
975 struct data_string key_id;
977 switch (next_token (&val, (unsigned *)0, cfile)) {
979 token = next_token (&val, (unsigned *)0, cfile);
980 if (token != STRING && !is_identifier (token)) {
981 parse_warn (cfile, "expecting key name.");
982 skip_to_semi (cfile);
985 if (omapi_auth_key_lookup_name (&lease -> key, val) !=
987 parse_warn (cfile, "unknown key %s", val);
991 lease -> is_bootp = 1;
995 token = next_token (&val, (unsigned *)0, cfile);
996 if (token != STRING) {
998 "expecting interface name (in quotes).");
999 skip_to_semi (cfile);
1002 interface_or_dummy (ipp, val);
1006 token = next_token (&val, (unsigned *)0, cfile);
1009 parse_warn (cfile, "state name precedes interface.");
1012 for (client = ip -> client; client; client = client -> next)
1013 if (client -> name && !strcmp (client -> name, val))
1017 "lease specified for unknown pseudo.");
1022 if (!parse_ip_addr (cfile, &lease -> address))
1027 parse_string_list (cfile, &lease -> medium, 0);
1031 parse_string (cfile, &lease -> filename, (unsigned *)0);
1035 parse_string (cfile, &lease -> server_name, (unsigned *)0);
1039 lease -> renewal = parse_date (cfile);
1043 lease -> rebind = parse_date (cfile);
1047 lease -> expiry = parse_date (cfile);
1051 oc = (struct option_cache *)0;
1052 if (parse_option_decl (&oc, cfile)) {
1053 save_option (oc -> option -> universe,
1054 lease -> options, oc);
1055 option_cache_dereference (&oc, MDL);
1060 parse_warn (cfile, "expecting lease declaration.");
1061 skip_to_semi (cfile);
1064 token = next_token (&val, (unsigned *)0, cfile);
1065 if (token != SEMI) {
1066 parse_warn (cfile, "expecting semicolon.");
1067 skip_to_semi (cfile);
1071 void parse_string_list (cfile, lp, multiple)
1072 struct parse *cfile;
1073 struct string_list **lp;
1078 struct string_list *cur, *tmp;
1080 /* Find the last medium in the media list. */
1082 for (cur = *lp; cur -> next; cur = cur -> next)
1085 cur = (struct string_list *)0;
1089 token = next_token (&val, (unsigned *)0, cfile);
1090 if (token != STRING) {
1091 parse_warn (cfile, "Expecting media options.");
1092 skip_to_semi (cfile);
1096 tmp = ((struct string_list *)
1097 dmalloc (strlen (val) + sizeof (struct string_list),
1100 log_fatal ("no memory for string list entry.");
1102 strcpy (tmp -> string, val);
1103 tmp -> next = (struct string_list *)0;
1105 /* Store this medium at the end of the media list. */
1112 token = next_token (&val, (unsigned *)0, cfile);
1113 } while (multiple && token == COMMA);
1115 if (token != SEMI) {
1116 parse_warn (cfile, "expecting semicolon.");
1117 skip_to_semi (cfile);
1121 void parse_reject_statement (cfile, config)
1122 struct parse *cfile;
1123 struct client_config *config;
1128 struct iaddrlist *list;
1131 if (!parse_ip_addr (cfile, &addr)) {
1132 parse_warn (cfile, "expecting IP address.");
1133 skip_to_semi (cfile);
1137 list = (struct iaddrlist *)dmalloc (sizeof (struct iaddrlist),
1140 log_fatal ("no memory for reject list!");
1142 list -> addr = addr;
1143 list -> next = config -> reject_list;
1144 config -> reject_list = list;
1146 token = next_token (&val, (unsigned *)0, cfile);
1147 } while (token == COMMA);
1149 if (token != SEMI) {
1150 parse_warn (cfile, "expecting semicolon.");
1151 skip_to_semi (cfile);
1155 /* allow-deny-keyword :== BOOTP
1158 | UNKNOWN_CLIENTS */
1160 int parse_allow_deny (oc, cfile, flag)
1161 struct option_cache **oc;
1162 struct parse *cfile;
1165 enum dhcp_token token;
1167 unsigned char rf = flag;
1168 struct expression *data = (struct expression *)0;
1171 parse_warn (cfile, "allow/deny/ignore not permitted here.");
1172 skip_to_semi (cfile);