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 * $Id: clparse.c,v 1.62.2.4 2003/02/10 00:39:57 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.
44 * $FreeBSD: src/contrib/isc-dhcp/client/clparse.c,v 1.11 2003/09/02 11:13:20 mbr Exp $
45 * $DragonFly: src/contrib/isc-dhcp/client/Attic/clparse.c,v 1.3 2003/10/11 21:14:12 dillon Exp $
50 static TIME parsed_time;
52 struct client_config top_level_config;
54 char client_script_name [] = _PATH_DHCLIENT_SCRIPT;
56 u_int32_t default_requested_options [] = {
58 DHO_BROADCAST_ADDRESS,
62 DHO_DOMAIN_NAME_SERVERS,
67 /* client-conf-file :== client-declarations END_OF_FILE
68 client-declarations :== <nil>
70 | client-declarations client-declaration */
72 isc_result_t read_client_conf ()
74 struct client_config *config;
75 struct client_state *state;
76 struct interface_info *ip;
79 /* Set up the initial dhcp option universe. */
80 initialize_common_option_spaces ();
82 /* Initialize the top level client configuration. */
83 memset (&top_level_config, 0, sizeof top_level_config);
85 /* Set some defaults... */
86 top_level_config.timeout = 60;
87 top_level_config.select_interval = 0;
88 top_level_config.reboot_timeout = 10;
89 top_level_config.retry_interval = 300;
90 top_level_config.backoff_cutoff = 15;
91 top_level_config.initial_interval = 3;
92 top_level_config.bootp_policy = P_ACCEPT;
93 top_level_config.script_name = path_dhclient_script;
94 top_level_config.requested_options = default_requested_options;
95 top_level_config.omapi_port = -1;
96 top_level_config.do_forward_update = 1;
98 group_allocate (&top_level_config.on_receipt, MDL);
99 if (!top_level_config.on_receipt)
100 log_fatal ("no memory for top-level on_receipt group");
102 group_allocate (&top_level_config.on_transmission, MDL);
103 if (!top_level_config.on_transmission)
104 log_fatal ("no memory for top-level on_transmission group");
106 status = read_client_conf_file (path_dhclient_conf,
107 (struct interface_info *)0,
109 if (status != ISC_R_SUCCESS) {
112 /* Set up the standard name service updater routine. */
113 parse = (struct parse *)0;
114 status = new_parse (&parse, -1, default_client_config,
115 (sizeof default_client_config) - 1,
116 "default client configuration", 0);
117 if (status != ISC_R_SUCCESS)
118 log_fatal ("can't begin default client config!");
121 token = peek_token (&val, (unsigned *)0, cfile);
122 if (token == END_OF_FILE)
124 parse_client_statement (cfile,
125 (struct interface_info *)0,
132 /* Set up state and config structures for clients that don't
133 have per-interface configuration statements. */
134 config = (struct client_config *)0;
135 for (ip = interfaces; ip; ip = ip -> next) {
137 ip -> client = (struct client_state *)
138 dmalloc (sizeof (struct client_state), MDL);
140 log_fatal ("no memory for client state.");
141 memset (ip -> client, 0, sizeof *(ip -> client));
142 ip -> client -> interface = ip;
145 if (!ip -> client -> config) {
147 config = (struct client_config *)
148 dmalloc (sizeof (struct client_config),
151 log_fatal ("no memory for client config.");
152 memcpy (config, &top_level_config,
153 sizeof top_level_config);
155 ip -> client -> config = config;
161 int read_client_conf_file (const char *name, struct interface_info *ip,
162 struct client_config *client)
170 if ((file = open (name, O_RDONLY)) < 0)
171 return uerr2isc (errno);
173 cfile = (struct parse *)0;
174 new_parse (&cfile, file, (char *)0, 0, path_dhclient_conf, 0);
177 token = peek_token (&val, (unsigned *)0, cfile);
178 if (token == END_OF_FILE)
180 parse_client_statement (cfile, ip, client);
182 token = next_token (&val, (unsigned *)0, cfile);
183 status = (cfile -> warnings_occurred
192 /* lease-file :== client-lease-statements END_OF_FILE
193 client-lease-statements :== <nil>
194 | client-lease-statements LEASE client-lease-statement */
196 void read_client_leases ()
203 /* Open the lease file. If we can't open it, just return -
204 we can safely trust the server to remember our state. */
205 if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
207 cfile = (struct parse *)0;
208 new_parse (&cfile, file, (char *)0, 0, path_dhclient_db, 0);
211 token = next_token (&val, (unsigned *)0, cfile);
212 if (token == END_OF_FILE)
214 if (token != LEASE) {
215 log_error ("Corrupt lease file - possible data loss!");
216 skip_to_semi (cfile);
219 parse_client_lease_statement (cfile, 0);
227 /* client-declaration :==
229 DEFAULT option-decl |
230 SUPERSEDE option-decl |
231 PREPEND option-decl |
233 hardware-declaration |
234 REQUEST option-list |
235 REQUIRE option-list |
239 SELECT_TIMEOUT number |
241 VENDOR_SPACE string |
242 interface-declaration |
243 LEASE client-lease-statement |
244 ALIAS client-lease-statement |
245 KEY key-definition */
247 void parse_client_statement (cfile, ip, config)
249 struct interface_info *ip;
250 struct client_config *config;
254 struct option *option;
255 struct executable_statement *stmt, **p;
256 enum statement_op op;
259 struct data_string key_id;
265 switch (peek_token (&val, (unsigned *)0, cfile)) {
267 next_token (&val, (unsigned *)0, cfile);
268 token = next_token (&val, (unsigned *)0, cfile);
269 if (token != STRING) {
270 parse_warn (cfile, "filename string expected.");
271 skip_to_semi (cfile);
273 status = read_client_conf_file (val, ip, config);
274 if (status != ISC_R_SUCCESS)
275 parse_warn (cfile, "%s: bad parse.", val);
281 next_token (&val, (unsigned *)0, cfile);
283 /* This may seem arbitrary, but there's a reason for
284 doing it: the authentication key database is not
285 scoped. If we allow the user to declare a key other
286 than in the outer scope, the user is very likely to
287 believe that the key will only be used in that
288 scope. If the user only wants the key to be used on
289 one interface, because it's known that the other
290 interface may be connected to an insecure net and
291 the secret key is considered sensitive, we don't
292 want to lull them into believing they've gotten
293 their way. This is a bit contrived, but people
294 tend not to be entirely rational about security. */
295 parse_warn (cfile, "key definition not allowed here.");
296 skip_to_semi (cfile);
302 /* REQUIRE can either start a policy statement or a
303 comma-seperated list of names of required options. */
305 next_token (&val, (unsigned *)0, cfile);
306 token = peek_token (&val, (unsigned *)0, cfile);
307 if (token == AUTHENTICATION) {
311 parse_option_list (cfile, &config -> required_options);
315 next_token (&val, (unsigned *)0, cfile);
320 next_token (&val, (unsigned *)0, cfile);
325 next_token (&val, (unsigned *)0, cfile);
330 next_token (&val, (unsigned *)0, cfile);
335 token = next_token (&val, (unsigned *)0, cfile);
336 if (token == AUTHENTICATION) {
337 if (policy != P_PREFER &&
338 policy != P_REQUIRE &&
341 "invalid authentication policy.");
342 skip_to_semi (cfile);
345 config -> auth_policy = policy;
346 } else if (token != TOKEN_BOOTP) {
347 if (policy != P_PREFER &&
348 policy != P_IGNORE &&
349 policy != P_ACCEPT) {
350 parse_warn (cfile, "invalid bootp policy.");
351 skip_to_semi (cfile);
354 config -> bootp_policy = policy;
356 parse_warn (cfile, "expecting a policy type.");
357 skip_to_semi (cfile);
363 token = next_token (&val, (unsigned *)0, cfile);
365 token = peek_token (&val, (unsigned *)0, cfile);
366 if (token == SPACE) {
369 "option space definitions %s",
370 " may not be scoped.");
371 skip_to_semi (cfile);
374 parse_option_space_decl (cfile);
378 option = parse_option_name (cfile, 1, &known);
382 token = next_token (&val, (unsigned *)0, cfile);
384 parse_warn (cfile, "expecting \"code\" keyword.");
385 skip_to_semi (cfile);
386 free_option (option, MDL);
391 "option definitions may only appear in %s",
392 "the outermost scope.");
393 skip_to_semi (cfile);
394 free_option (option, MDL);
397 if (!parse_option_code_definition (cfile, option))
398 free_option (option, MDL);
402 token = next_token (&val, (unsigned *)0, cfile);
403 parse_string_list (cfile, &config -> media, 1);
407 token = next_token (&val, (unsigned *)0, cfile);
409 parse_hardware_param (cfile, &ip -> hw_address);
411 parse_warn (cfile, "hardware address parameter %s",
412 "not allowed here.");
413 skip_to_semi (cfile);
418 token = next_token (&val, (unsigned *)0, cfile);
419 if (config -> requested_options == default_requested_options)
420 config -> requested_options = (u_int32_t *)0;
421 parse_option_list (cfile, &config -> requested_options);
425 token = next_token (&val, (unsigned *)0, cfile);
426 parse_lease_time (cfile, &config -> timeout);
430 token = next_token (&val, (unsigned *)0, cfile);
431 parse_lease_time (cfile, &config -> retry_interval);
435 token = next_token (&val, (unsigned *)0, cfile);
436 parse_lease_time (cfile, &config -> select_interval);
440 token = next_token (&val, (unsigned *)0, cfile);
441 token = next_token (&val, (unsigned *)0, cfile);
444 "unexpected omapi subtype: %s", val);
445 skip_to_semi (cfile);
448 token = next_token (&val, (unsigned *)0, cfile);
449 if (token != NUMBER) {
450 parse_warn (cfile, "invalid port number: `%s'", val);
451 skip_to_semi (cfile);
455 if (tmp < 0 || tmp > 65535)
456 parse_warn (cfile, "invalid omapi port %d.", tmp);
457 else if (config != &top_level_config)
459 "omapi port only works at top level.");
461 config -> omapi_port = tmp;
465 case DO_FORWARD_UPDATE:
466 token = next_token (&val, (unsigned *)0, cfile);
467 token = next_token (&val, (unsigned *)0, cfile);
468 if (!strcasecmp (val, "on") ||
469 !strcasecmp (val, "true"))
470 config -> do_forward_update = 1;
471 else if (!strcasecmp (val, "off") ||
472 !strcasecmp (val, "false"))
473 config -> do_forward_update = 0;
475 parse_warn (cfile, "expecting boolean value.");
476 skip_to_semi (cfile);
483 token = next_token (&val, (unsigned *)0, cfile);
484 parse_lease_time (cfile, &config -> reboot_timeout);
488 token = next_token (&val, (unsigned *)0, cfile);
489 parse_lease_time (cfile, &config -> backoff_cutoff);
492 case INITIAL_INTERVAL:
493 token = next_token (&val, (unsigned *)0, cfile);
494 parse_lease_time (cfile, &config -> initial_interval);
498 token = next_token (&val, (unsigned *)0, cfile);
499 parse_string (cfile, &config -> script_name, (unsigned *)0);
503 token = next_token (&val, (unsigned *)0, cfile);
504 token = next_token (&val, (unsigned *)0, cfile);
505 if (token != OPTION) {
506 parse_warn (cfile, "expecting 'vendor option space'");
507 skip_to_semi (cfile);
510 token = next_token (&val, (unsigned *)0, cfile);
511 if (token != SPACE) {
512 parse_warn (cfile, "expecting 'vendor option space'");
513 skip_to_semi (cfile);
516 token = next_token (&val, (unsigned *)0, cfile);
517 if (!is_identifier (token)) {
518 parse_warn (cfile, "expecting an identifier.");
519 skip_to_semi (cfile);
522 config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
523 if (!config -> vendor_space_name)
524 log_fatal ("no memory for vendor option space name.");
525 strcpy (config -> vendor_space_name, val);
526 for (i = 0; i < universe_count; i++)
527 if (!strcmp (universes [i] -> name,
528 config -> vendor_space_name))
530 if (i == universe_count) {
531 log_error ("vendor option space %s not found.",
532 config -> vendor_space_name);
538 token = next_token (&val, (unsigned *)0, cfile);
540 parse_warn (cfile, "nested interface declaration.");
541 parse_interface_declaration (cfile, config, (char *)0);
545 token = next_token (&val, (unsigned *)0, cfile);
546 token = next_token (&val, (unsigned *)0, cfile);
547 name = dmalloc (strlen (val) + 1, MDL);
549 log_fatal ("no memory for pseudo interface name");
551 parse_interface_declaration (cfile, config, name);
555 token = next_token (&val, (unsigned *)0, cfile);
556 parse_client_lease_statement (cfile, 1);
560 token = next_token (&val, (unsigned *)0, cfile);
561 parse_client_lease_statement (cfile, 2);
565 token = next_token (&val, (unsigned *)0, cfile);
566 parse_reject_statement (cfile, config);
571 stmt = (struct executable_statement *)0;
572 if (!parse_executable_statement (&stmt,
573 cfile, &lose, context_any)) {
575 parse_warn (cfile, "expecting a statement.");
576 skip_to_semi (cfile);
579 struct executable_statement **eptr, *sptr;
581 (stmt -> op == send_option_statement ||
582 (stmt -> op == on_statement &&
583 (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
584 eptr = &config -> on_transmission -> statements;
585 if (stmt -> op == on_statement) {
586 sptr = (struct executable_statement *)0;
587 executable_statement_reference
589 stmt -> data.on.statements, MDL);
590 executable_statement_dereference (&stmt,
592 executable_statement_reference (&stmt,
595 executable_statement_dereference (&sptr,
599 eptr = &config -> on_receipt -> statements;
602 for (; *eptr; eptr = &(*eptr) -> next)
604 executable_statement_reference (eptr,
614 /* option-list :== option_name |
615 option_list COMMA option_name */
617 void parse_option_list (cfile, list)
624 pair p = (pair)0, q, r;
625 struct option *option;
629 token = peek_token (&val, (unsigned *)0, cfile);
631 token = next_token (&val, (unsigned *)0, cfile);
634 if (!is_identifier (token)) {
635 parse_warn (cfile, "%s: expected option name.", val);
636 token = next_token (&val, (unsigned *)0, cfile);
637 skip_to_semi (cfile);
640 option = parse_option_name (cfile, 0, NULL);
642 parse_warn (cfile, "%s: expected option name.", val);
645 if (option -> universe != &dhcp_universe) {
647 "%s.%s: Only global options allowed.",
648 option -> universe -> name, option->name );
649 skip_to_semi (cfile);
654 log_fatal ("can't allocate pair for option code.");
655 r -> car = (caddr_t)(long)option -> code;
663 token = next_token (&val, (unsigned *)0, cfile);
664 } while (token == COMMA);
666 parse_warn (cfile, "expecting semicolon.");
667 skip_to_semi (cfile);
670 /* XXX we can't free the list here, because we may have copied
671 XXX it from an outer config state. */
672 *list = (u_int32_t *)0;
674 *list = dmalloc ((ix + 1) * sizeof **list, MDL);
676 log_error ("no memory for option list.");
679 for (q = p; q; q = q -> cdr)
680 (*list) [ix++] = (u_int32_t)(long)q -> car;
691 /* interface-declaration :==
692 INTERFACE string LBRACE client-declarations RBRACE */
694 void parse_interface_declaration (cfile, outer_config, name)
696 struct client_config *outer_config;
701 struct client_state *client, **cp;
702 struct interface_info *ip = (struct interface_info *)0;
704 token = next_token (&val, (unsigned *)0, cfile);
705 if (token != STRING) {
706 parse_warn (cfile, "expecting interface name (in quotes).");
707 skip_to_semi (cfile);
711 if (!interface_or_dummy (&ip, val))
712 log_fatal ("Can't allocate interface %s.", val);
714 /* If we were given a name, this is a pseudo-interface. */
716 make_client_state (&client);
717 client -> name = name;
718 client -> interface = ip;
719 for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
724 make_client_state (&ip -> client);
725 ip -> client -> interface = ip;
727 client = ip -> client;
730 if (!client -> config)
731 make_client_config (client, outer_config);
733 ip -> flags &= ~INTERFACE_AUTOMATIC;
734 interfaces_requested = 1;
736 token = next_token (&val, (unsigned *)0, cfile);
737 if (token != LBRACE) {
738 parse_warn (cfile, "expecting left brace.");
739 skip_to_semi (cfile);
744 token = peek_token (&val, (unsigned *)0, cfile);
745 if (token == END_OF_FILE) {
747 "unterminated interface declaration.");
752 parse_client_statement (cfile, ip, client -> config);
754 token = next_token (&val, (unsigned *)0, cfile);
757 int interface_or_dummy (struct interface_info **pi, const char *name)
759 struct interface_info *i;
760 struct interface_info *ip = (struct interface_info *)0;
763 /* Find the interface (if any) that matches the name. */
764 for (i = interfaces; i; i = i -> next) {
765 if (!strcmp (i -> name, name)) {
766 interface_reference (&ip, i, MDL);
771 /* If it's not a real interface, see if it's on the dummy list. */
773 for (ip = dummy_interfaces; ip; ip = ip -> next) {
774 if (!strcmp (ip -> name, name)) {
775 interface_reference (&ip, i, MDL);
781 /* If we didn't find an interface, make a dummy interface as
785 status = interface_allocate (&ip, MDL);
786 if (status != ISC_R_SUCCESS)
787 log_fatal ("Can't record interface %s: %s",
788 name, isc_result_totext (status));
789 strlcpy (ip -> name, name, IFNAMSIZ);
790 if (dummy_interfaces) {
791 interface_reference (&ip -> next,
792 dummy_interfaces, MDL);
793 interface_dereference (&dummy_interfaces, MDL);
795 interface_reference (&dummy_interfaces, ip, MDL);
798 status = interface_reference (pi, ip, MDL);
799 interface_dereference (&ip, MDL);
800 if (status != ISC_R_SUCCESS)
805 void make_client_state (state)
806 struct client_state **state;
808 *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
810 log_fatal ("no memory for client state\n");
811 memset (*state, 0, sizeof **state);
814 void make_client_config (client, config)
815 struct client_state *client;
816 struct client_config *config;
818 client -> config = (((struct client_config *)
819 dmalloc (sizeof (struct client_config), MDL)));
820 if (!client -> config)
821 log_fatal ("no memory for client config\n");
822 memcpy (client -> config, config, sizeof *config);
823 if (!clone_group (&client -> config -> on_receipt,
824 config -> on_receipt, MDL) ||
825 !clone_group (&client -> config -> on_transmission,
826 config -> on_transmission, MDL))
827 log_fatal ("no memory for client state groups.");
830 /* client-lease-statement :==
831 RBRACE client-lease-declarations LBRACE
833 client-lease-declarations :==
835 client-lease-declaration |
836 client-lease-declarations client-lease-declaration */
839 void parse_client_lease_statement (cfile, is_static)
843 struct client_lease *lease, *lp, *pl;
844 struct interface_info *ip = (struct interface_info *)0;
847 struct client_state *client = (struct client_state *)0;
849 token = next_token (&val, (unsigned *)0, cfile);
850 if (token != LBRACE) {
851 parse_warn (cfile, "expecting left brace.");
852 skip_to_semi (cfile);
856 lease = ((struct client_lease *)
857 dmalloc (sizeof (struct client_lease), MDL));
859 log_fatal ("no memory for lease.\n");
860 memset (lease, 0, sizeof *lease);
861 lease -> is_static = is_static;
862 if (!option_state_allocate (&lease -> options, MDL))
863 log_fatal ("no memory for lease options.\n");
866 token = peek_token (&val, (unsigned *)0, cfile);
867 if (token == END_OF_FILE) {
868 parse_warn (cfile, "unterminated lease declaration.");
873 parse_client_lease_declaration (cfile, lease, &ip, &client);
875 token = next_token (&val, (unsigned *)0, cfile);
877 /* If the lease declaration didn't include an interface
878 declaration that we recognized, it's of no use to us. */
880 destroy_client_lease (lease);
884 /* Make sure there's a client state structure... */
886 make_client_state (&ip -> client);
887 ip -> client -> interface = ip;
890 client = ip -> client;
892 /* If this is an alias lease, it doesn't need to be sorted in. */
893 if (is_static == 2) {
894 ip -> client -> alias = lease;
898 /* The new lease may supersede a lease that's not the
899 active lease but is still on the lease list, so scan the
900 lease list looking for a lease with the same address, and
901 if we find it, toss it. */
902 pl = (struct client_lease *)0;
903 for (lp = client -> leases; lp; lp = lp -> next) {
904 if (lp -> address.len == lease -> address.len &&
905 !memcmp (lp -> address.iabuf, lease -> address.iabuf,
906 lease -> address.len)) {
908 pl -> next = lp -> next;
910 client -> leases = lp -> next;
911 destroy_client_lease (lp);
916 /* If this is a preloaded lease, just put it on the list of recorded
917 leases - don't make it the active lease. */
919 lease -> next = client -> leases;
920 client -> leases = lease;
924 /* The last lease in the lease file on a particular interface is
925 the active lease for that interface. Of course, we don't know
926 what the last lease in the file is until we've parsed the whole
927 file, so at this point, we assume that the lease we just parsed
928 is the active lease for its interface. If there's already
929 an active lease for the interface, and this lease is for the same
930 ip address, then we just toss the old active lease and replace
931 it with this one. If this lease is for a different address,
932 then if the old active lease has expired, we dump it; if not,
933 we put it on the list of leases for this interface which are
934 still valid but no longer active. */
935 if (client -> active) {
936 if (client -> active -> expiry < cur_time)
937 destroy_client_lease (client -> active);
938 else if (client -> active -> address.len ==
939 lease -> address.len &&
940 !memcmp (client -> active -> address.iabuf,
941 lease -> address.iabuf,
942 lease -> address.len))
943 destroy_client_lease (client -> active);
945 client -> active -> next = client -> leases;
946 client -> leases = client -> active;
949 client -> active = lease;
954 /* client-lease-declaration :==
957 FIXED_ADDR ip_address |
966 void parse_client_lease_declaration (cfile, lease, ipp, clientp)
968 struct client_lease *lease;
969 struct interface_info **ipp;
970 struct client_state **clientp;
975 struct interface_info *ip;
976 struct option_cache *oc;
977 struct client_state *client = (struct client_state *)0;
978 struct data_string key_id;
980 switch (next_token (&val, (unsigned *)0, cfile)) {
982 token = next_token (&val, (unsigned *)0, cfile);
983 if (token != STRING && !is_identifier (token)) {
984 parse_warn (cfile, "expecting key name.");
985 skip_to_semi (cfile);
988 if (omapi_auth_key_lookup_name (&lease -> key, val) !=
990 parse_warn (cfile, "unknown key %s", val);
994 lease -> is_bootp = 1;
998 token = next_token (&val, (unsigned *)0, cfile);
999 if (token != STRING) {
1001 "expecting interface name (in quotes).");
1002 skip_to_semi (cfile);
1005 interface_or_dummy (ipp, val);
1009 token = next_token (&val, (unsigned *)0, cfile);
1012 parse_warn (cfile, "state name precedes interface.");
1015 for (client = ip -> client; client; client = client -> next)
1016 if (client -> name && !strcmp (client -> name, val))
1020 "lease specified for unknown pseudo.");
1025 if (!parse_ip_addr (cfile, &lease -> address))
1030 parse_string_list (cfile, &lease -> medium, 0);
1034 parse_string (cfile, &lease -> filename, (unsigned *)0);
1038 parse_string (cfile, &lease -> server_name, (unsigned *)0);
1042 lease -> renewal = parse_date (cfile);
1046 lease -> rebind = parse_date (cfile);
1050 lease -> expiry = parse_date (cfile);
1054 oc = (struct option_cache *)0;
1055 if (parse_option_decl (&oc, cfile)) {
1056 save_option (oc -> option -> universe,
1057 lease -> options, oc);
1058 option_cache_dereference (&oc, MDL);
1063 parse_warn (cfile, "expecting lease declaration.");
1064 skip_to_semi (cfile);
1067 token = next_token (&val, (unsigned *)0, cfile);
1068 if (token != SEMI) {
1069 parse_warn (cfile, "expecting semicolon.");
1070 skip_to_semi (cfile);
1074 void parse_string_list (cfile, lp, multiple)
1075 struct parse *cfile;
1076 struct string_list **lp;
1081 struct string_list *cur, *tmp;
1083 /* Find the last medium in the media list. */
1085 for (cur = *lp; cur -> next; cur = cur -> next)
1088 cur = (struct string_list *)0;
1092 token = next_token (&val, (unsigned *)0, cfile);
1093 if (token != STRING) {
1094 parse_warn (cfile, "Expecting media options.");
1095 skip_to_semi (cfile);
1099 tmp = ((struct string_list *)
1100 dmalloc (strlen (val) + sizeof (struct string_list),
1103 log_fatal ("no memory for string list entry.");
1105 strcpy (tmp -> string, val);
1106 tmp -> next = (struct string_list *)0;
1108 /* Store this medium at the end of the media list. */
1115 token = next_token (&val, (unsigned *)0, cfile);
1116 } while (multiple && token == COMMA);
1118 if (token != SEMI) {
1119 parse_warn (cfile, "expecting semicolon.");
1120 skip_to_semi (cfile);
1124 void parse_reject_statement (cfile, config)
1125 struct parse *cfile;
1126 struct client_config *config;
1131 struct iaddrlist *list;
1134 if (!parse_ip_addr (cfile, &addr)) {
1135 parse_warn (cfile, "expecting IP address.");
1136 skip_to_semi (cfile);
1140 list = (struct iaddrlist *)dmalloc (sizeof (struct iaddrlist),
1143 log_fatal ("no memory for reject list!");
1145 list -> addr = addr;
1146 list -> next = config -> reject_list;
1147 config -> reject_list = list;
1149 token = next_token (&val, (unsigned *)0, cfile);
1150 } while (token == COMMA);
1152 if (token != SEMI) {
1153 parse_warn (cfile, "expecting semicolon.");
1154 skip_to_semi (cfile);
1158 /* allow-deny-keyword :== BOOTP
1161 | UNKNOWN_CLIENTS */
1163 int parse_allow_deny (oc, cfile, flag)
1164 struct option_cache **oc;
1165 struct parse *cfile;
1168 enum dhcp_token token;
1170 unsigned char rf = flag;
1171 struct expression *data = (struct expression *)0;
1174 parse_warn (cfile, "allow/deny/ignore not permitted here.");
1175 skip_to_semi (cfile);