1*83ee113eSDavid van Moolenbroek /* $NetBSD: clparse.c,v 1.1.1.3 2014/07/12 11:57:35 spz Exp $ */
2*83ee113eSDavid van Moolenbroek /* clparse.c
3*83ee113eSDavid van Moolenbroek
4*83ee113eSDavid van Moolenbroek Parser for dhclient config and lease files... */
5*83ee113eSDavid van Moolenbroek
6*83ee113eSDavid van Moolenbroek /*
7*83ee113eSDavid van Moolenbroek * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
8*83ee113eSDavid van Moolenbroek * Copyright (c) 1996-2003 by Internet Software Consortium
9*83ee113eSDavid van Moolenbroek *
10*83ee113eSDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
11*83ee113eSDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
12*83ee113eSDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
13*83ee113eSDavid van Moolenbroek *
14*83ee113eSDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15*83ee113eSDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16*83ee113eSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17*83ee113eSDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18*83ee113eSDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19*83ee113eSDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20*83ee113eSDavid van Moolenbroek * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21*83ee113eSDavid van Moolenbroek *
22*83ee113eSDavid van Moolenbroek * Internet Systems Consortium, Inc.
23*83ee113eSDavid van Moolenbroek * 950 Charter Street
24*83ee113eSDavid van Moolenbroek * Redwood City, CA 94063
25*83ee113eSDavid van Moolenbroek * <info@isc.org>
26*83ee113eSDavid van Moolenbroek * https://www.isc.org/
27*83ee113eSDavid van Moolenbroek *
28*83ee113eSDavid van Moolenbroek */
29*83ee113eSDavid van Moolenbroek
30*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
31*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: clparse.c,v 1.1.1.3 2014/07/12 11:57:35 spz Exp $");
32*83ee113eSDavid van Moolenbroek
33*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
34*83ee113eSDavid van Moolenbroek #include <errno.h>
35*83ee113eSDavid van Moolenbroek
36*83ee113eSDavid van Moolenbroek struct client_config top_level_config;
37*83ee113eSDavid van Moolenbroek
38*83ee113eSDavid van Moolenbroek #define NUM_DEFAULT_REQUESTED_OPTS 9
39*83ee113eSDavid van Moolenbroek struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
40*83ee113eSDavid van Moolenbroek
41*83ee113eSDavid van Moolenbroek static void parse_client_default_duid(struct parse *cfile);
42*83ee113eSDavid van Moolenbroek static void parse_client6_lease_statement(struct parse *cfile);
43*83ee113eSDavid van Moolenbroek #ifdef DHCPv6
44*83ee113eSDavid van Moolenbroek static struct dhc6_ia *parse_client6_ia_na_statement(struct parse *cfile);
45*83ee113eSDavid van Moolenbroek static struct dhc6_ia *parse_client6_ia_ta_statement(struct parse *cfile);
46*83ee113eSDavid van Moolenbroek static struct dhc6_ia *parse_client6_ia_pd_statement(struct parse *cfile);
47*83ee113eSDavid van Moolenbroek static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
48*83ee113eSDavid van Moolenbroek static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
49*83ee113eSDavid van Moolenbroek #endif /* DHCPv6 */
50*83ee113eSDavid van Moolenbroek
51*83ee113eSDavid van Moolenbroek /* client-conf-file :== client-declarations END_OF_FILE
52*83ee113eSDavid van Moolenbroek client-declarations :== <nil>
53*83ee113eSDavid van Moolenbroek | client-declaration
54*83ee113eSDavid van Moolenbroek | client-declarations client-declaration */
55*83ee113eSDavid van Moolenbroek
read_client_conf()56*83ee113eSDavid van Moolenbroek isc_result_t read_client_conf ()
57*83ee113eSDavid van Moolenbroek {
58*83ee113eSDavid van Moolenbroek struct client_config *config;
59*83ee113eSDavid van Moolenbroek struct interface_info *ip;
60*83ee113eSDavid van Moolenbroek isc_result_t status;
61*83ee113eSDavid van Moolenbroek unsigned code;
62*83ee113eSDavid van Moolenbroek
63*83ee113eSDavid van Moolenbroek /*
64*83ee113eSDavid van Moolenbroek * TODO: LATER constant is very undescriptive. We should review it and
65*83ee113eSDavid van Moolenbroek * change it to something more descriptive or even better remove it
66*83ee113eSDavid van Moolenbroek * completely as it is currently not used.
67*83ee113eSDavid van Moolenbroek */
68*83ee113eSDavid van Moolenbroek #ifdef LATER
69*83ee113eSDavid van Moolenbroek struct parse *parse = NULL;
70*83ee113eSDavid van Moolenbroek #endif
71*83ee113eSDavid van Moolenbroek
72*83ee113eSDavid van Moolenbroek /* Initialize the default request list. */
73*83ee113eSDavid van Moolenbroek memset(default_requested_options, 0, sizeof(default_requested_options));
74*83ee113eSDavid van Moolenbroek
75*83ee113eSDavid van Moolenbroek /* 1 */
76*83ee113eSDavid van Moolenbroek code = DHO_SUBNET_MASK;
77*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[0],
78*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
79*83ee113eSDavid van Moolenbroek
80*83ee113eSDavid van Moolenbroek /* 2 */
81*83ee113eSDavid van Moolenbroek code = DHO_BROADCAST_ADDRESS;
82*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[1],
83*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
84*83ee113eSDavid van Moolenbroek
85*83ee113eSDavid van Moolenbroek /* 3 */
86*83ee113eSDavid van Moolenbroek code = DHO_TIME_OFFSET;
87*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[2],
88*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
89*83ee113eSDavid van Moolenbroek
90*83ee113eSDavid van Moolenbroek /* 4 */
91*83ee113eSDavid van Moolenbroek code = DHO_ROUTERS;
92*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[3],
93*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
94*83ee113eSDavid van Moolenbroek
95*83ee113eSDavid van Moolenbroek /* 5 */
96*83ee113eSDavid van Moolenbroek code = DHO_DOMAIN_NAME;
97*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[4],
98*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
99*83ee113eSDavid van Moolenbroek
100*83ee113eSDavid van Moolenbroek /* 6 */
101*83ee113eSDavid van Moolenbroek code = DHO_DOMAIN_NAME_SERVERS;
102*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[5],
103*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
104*83ee113eSDavid van Moolenbroek
105*83ee113eSDavid van Moolenbroek /* 7 */
106*83ee113eSDavid van Moolenbroek code = DHO_HOST_NAME;
107*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[6],
108*83ee113eSDavid van Moolenbroek dhcp_universe.code_hash, &code, 0, MDL);
109*83ee113eSDavid van Moolenbroek
110*83ee113eSDavid van Moolenbroek /* 8 */
111*83ee113eSDavid van Moolenbroek code = D6O_NAME_SERVERS;
112*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[7],
113*83ee113eSDavid van Moolenbroek dhcpv6_universe.code_hash, &code, 0, MDL);
114*83ee113eSDavid van Moolenbroek
115*83ee113eSDavid van Moolenbroek /* 9 */
116*83ee113eSDavid van Moolenbroek code = D6O_DOMAIN_SEARCH;
117*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&default_requested_options[8],
118*83ee113eSDavid van Moolenbroek dhcpv6_universe.code_hash, &code, 0, MDL);
119*83ee113eSDavid van Moolenbroek
120*83ee113eSDavid van Moolenbroek for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
121*83ee113eSDavid van Moolenbroek if (default_requested_options[code] == NULL)
122*83ee113eSDavid van Moolenbroek log_fatal("Unable to find option definition for "
123*83ee113eSDavid van Moolenbroek "index %u during default parameter request "
124*83ee113eSDavid van Moolenbroek "assembly.", code);
125*83ee113eSDavid van Moolenbroek }
126*83ee113eSDavid van Moolenbroek
127*83ee113eSDavid van Moolenbroek /* Initialize the top level client configuration. */
128*83ee113eSDavid van Moolenbroek memset (&top_level_config, 0, sizeof top_level_config);
129*83ee113eSDavid van Moolenbroek
130*83ee113eSDavid van Moolenbroek /* Set some defaults... */
131*83ee113eSDavid van Moolenbroek top_level_config.timeout = 60;
132*83ee113eSDavid van Moolenbroek top_level_config.select_interval = 0;
133*83ee113eSDavid van Moolenbroek top_level_config.reboot_timeout = 10;
134*83ee113eSDavid van Moolenbroek top_level_config.retry_interval = 300;
135*83ee113eSDavid van Moolenbroek top_level_config.backoff_cutoff = 15;
136*83ee113eSDavid van Moolenbroek top_level_config.initial_interval = 3;
137*83ee113eSDavid van Moolenbroek
138*83ee113eSDavid van Moolenbroek /*
139*83ee113eSDavid van Moolenbroek * RFC 2131, section 4.4.1 specifies that the client SHOULD wait a
140*83ee113eSDavid van Moolenbroek * random time between 1 and 10 seconds. However, we choose to not
141*83ee113eSDavid van Moolenbroek * implement this default. If user is inclined to really have that
142*83ee113eSDavid van Moolenbroek * delay, he is welcome to do so, using 'initial-delay X;' parameter
143*83ee113eSDavid van Moolenbroek * in config file.
144*83ee113eSDavid van Moolenbroek */
145*83ee113eSDavid van Moolenbroek top_level_config.initial_delay = 0;
146*83ee113eSDavid van Moolenbroek
147*83ee113eSDavid van Moolenbroek top_level_config.bootp_policy = P_ACCEPT;
148*83ee113eSDavid van Moolenbroek top_level_config.script_name = path_dhclient_script;
149*83ee113eSDavid van Moolenbroek top_level_config.requested_options = default_requested_options;
150*83ee113eSDavid van Moolenbroek top_level_config.omapi_port = -1;
151*83ee113eSDavid van Moolenbroek top_level_config.do_forward_update = 1;
152*83ee113eSDavid van Moolenbroek /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache)
153*83ee113eSDavid van Moolenbroek */
154*83ee113eSDavid van Moolenbroek top_level_config.requested_lease = 7200;
155*83ee113eSDavid van Moolenbroek
156*83ee113eSDavid van Moolenbroek group_allocate (&top_level_config.on_receipt, MDL);
157*83ee113eSDavid van Moolenbroek if (!top_level_config.on_receipt)
158*83ee113eSDavid van Moolenbroek log_fatal ("no memory for top-level on_receipt group");
159*83ee113eSDavid van Moolenbroek
160*83ee113eSDavid van Moolenbroek group_allocate (&top_level_config.on_transmission, MDL);
161*83ee113eSDavid van Moolenbroek if (!top_level_config.on_transmission)
162*83ee113eSDavid van Moolenbroek log_fatal ("no memory for top-level on_transmission group");
163*83ee113eSDavid van Moolenbroek
164*83ee113eSDavid van Moolenbroek status = read_client_conf_file (path_dhclient_conf,
165*83ee113eSDavid van Moolenbroek (struct interface_info *)0,
166*83ee113eSDavid van Moolenbroek &top_level_config);
167*83ee113eSDavid van Moolenbroek
168*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS) {
169*83ee113eSDavid van Moolenbroek ;
170*83ee113eSDavid van Moolenbroek #ifdef LATER
171*83ee113eSDavid van Moolenbroek /* Set up the standard name service updater routine. */
172*83ee113eSDavid van Moolenbroek status = new_parse(&parse, -1, default_client_config,
173*83ee113eSDavid van Moolenbroek sizeof(default_client_config) - 1,
174*83ee113eSDavid van Moolenbroek "default client configuration", 0);
175*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS)
176*83ee113eSDavid van Moolenbroek log_fatal ("can't begin default client config!");
177*83ee113eSDavid van Moolenbroek }
178*83ee113eSDavid van Moolenbroek
179*83ee113eSDavid van Moolenbroek if (parse != NULL) {
180*83ee113eSDavid van Moolenbroek do {
181*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
182*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE)
183*83ee113eSDavid van Moolenbroek break;
184*83ee113eSDavid van Moolenbroek parse_client_statement(cfile, NULL, &top_level_config);
185*83ee113eSDavid van Moolenbroek } while (1);
186*83ee113eSDavid van Moolenbroek end_parse(&parse);
187*83ee113eSDavid van Moolenbroek #endif
188*83ee113eSDavid van Moolenbroek }
189*83ee113eSDavid van Moolenbroek
190*83ee113eSDavid van Moolenbroek /* Set up state and config structures for clients that don't
191*83ee113eSDavid van Moolenbroek have per-interface configuration statements. */
192*83ee113eSDavid van Moolenbroek config = (struct client_config *)0;
193*83ee113eSDavid van Moolenbroek for (ip = interfaces; ip; ip = ip -> next) {
194*83ee113eSDavid van Moolenbroek if (!ip -> client) {
195*83ee113eSDavid van Moolenbroek ip -> client = (struct client_state *)
196*83ee113eSDavid van Moolenbroek dmalloc (sizeof (struct client_state), MDL);
197*83ee113eSDavid van Moolenbroek if (!ip -> client)
198*83ee113eSDavid van Moolenbroek log_fatal ("no memory for client state.");
199*83ee113eSDavid van Moolenbroek memset (ip -> client, 0, sizeof *(ip -> client));
200*83ee113eSDavid van Moolenbroek ip -> client -> interface = ip;
201*83ee113eSDavid van Moolenbroek }
202*83ee113eSDavid van Moolenbroek
203*83ee113eSDavid van Moolenbroek if (!ip -> client -> config) {
204*83ee113eSDavid van Moolenbroek if (!config) {
205*83ee113eSDavid van Moolenbroek config = (struct client_config *)
206*83ee113eSDavid van Moolenbroek dmalloc (sizeof (struct client_config),
207*83ee113eSDavid van Moolenbroek MDL);
208*83ee113eSDavid van Moolenbroek if (!config)
209*83ee113eSDavid van Moolenbroek log_fatal ("no memory for client config.");
210*83ee113eSDavid van Moolenbroek memcpy (config, &top_level_config,
211*83ee113eSDavid van Moolenbroek sizeof top_level_config);
212*83ee113eSDavid van Moolenbroek }
213*83ee113eSDavid van Moolenbroek ip -> client -> config = config;
214*83ee113eSDavid van Moolenbroek }
215*83ee113eSDavid van Moolenbroek }
216*83ee113eSDavid van Moolenbroek return status;
217*83ee113eSDavid van Moolenbroek }
218*83ee113eSDavid van Moolenbroek
read_client_conf_file(const char * name,struct interface_info * ip,struct client_config * client)219*83ee113eSDavid van Moolenbroek int read_client_conf_file (const char *name, struct interface_info *ip,
220*83ee113eSDavid van Moolenbroek struct client_config *client)
221*83ee113eSDavid van Moolenbroek {
222*83ee113eSDavid van Moolenbroek int file;
223*83ee113eSDavid van Moolenbroek struct parse *cfile;
224*83ee113eSDavid van Moolenbroek const char *val;
225*83ee113eSDavid van Moolenbroek int token;
226*83ee113eSDavid van Moolenbroek isc_result_t status;
227*83ee113eSDavid van Moolenbroek
228*83ee113eSDavid van Moolenbroek if ((file = open (name, O_RDONLY)) < 0)
229*83ee113eSDavid van Moolenbroek return uerr2isc (errno);
230*83ee113eSDavid van Moolenbroek
231*83ee113eSDavid van Moolenbroek cfile = NULL;
232*83ee113eSDavid van Moolenbroek status = new_parse(&cfile, file, NULL, 0, path_dhclient_conf, 0);
233*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || cfile == NULL)
234*83ee113eSDavid van Moolenbroek return status;
235*83ee113eSDavid van Moolenbroek
236*83ee113eSDavid van Moolenbroek do {
237*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
238*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE)
239*83ee113eSDavid van Moolenbroek break;
240*83ee113eSDavid van Moolenbroek parse_client_statement (cfile, ip, client);
241*83ee113eSDavid van Moolenbroek } while (1);
242*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
243*83ee113eSDavid van Moolenbroek status = (cfile -> warnings_occurred
244*83ee113eSDavid van Moolenbroek ? DHCP_R_BADPARSE
245*83ee113eSDavid van Moolenbroek : ISC_R_SUCCESS);
246*83ee113eSDavid van Moolenbroek end_parse (&cfile);
247*83ee113eSDavid van Moolenbroek return status;
248*83ee113eSDavid van Moolenbroek }
249*83ee113eSDavid van Moolenbroek
250*83ee113eSDavid van Moolenbroek
251*83ee113eSDavid van Moolenbroek /* lease-file :== client-lease-statements END_OF_FILE
252*83ee113eSDavid van Moolenbroek client-lease-statements :== <nil>
253*83ee113eSDavid van Moolenbroek | client-lease-statements LEASE client-lease-statement */
254*83ee113eSDavid van Moolenbroek
read_client_leases()255*83ee113eSDavid van Moolenbroek void read_client_leases ()
256*83ee113eSDavid van Moolenbroek {
257*83ee113eSDavid van Moolenbroek int file;
258*83ee113eSDavid van Moolenbroek isc_result_t status;
259*83ee113eSDavid van Moolenbroek struct parse *cfile;
260*83ee113eSDavid van Moolenbroek const char *val;
261*83ee113eSDavid van Moolenbroek int token;
262*83ee113eSDavid van Moolenbroek
263*83ee113eSDavid van Moolenbroek /* Open the lease file. If we can't open it, just return -
264*83ee113eSDavid van Moolenbroek we can safely trust the server to remember our state. */
265*83ee113eSDavid van Moolenbroek if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
266*83ee113eSDavid van Moolenbroek return;
267*83ee113eSDavid van Moolenbroek
268*83ee113eSDavid van Moolenbroek cfile = NULL;
269*83ee113eSDavid van Moolenbroek status = new_parse(&cfile, file, NULL, 0, path_dhclient_db, 0);
270*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || cfile == NULL)
271*83ee113eSDavid van Moolenbroek return;
272*83ee113eSDavid van Moolenbroek
273*83ee113eSDavid van Moolenbroek do {
274*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
275*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE)
276*83ee113eSDavid van Moolenbroek break;
277*83ee113eSDavid van Moolenbroek
278*83ee113eSDavid van Moolenbroek switch (token) {
279*83ee113eSDavid van Moolenbroek case DEFAULT_DUID:
280*83ee113eSDavid van Moolenbroek parse_client_default_duid(cfile);
281*83ee113eSDavid van Moolenbroek break;
282*83ee113eSDavid van Moolenbroek
283*83ee113eSDavid van Moolenbroek case LEASE:
284*83ee113eSDavid van Moolenbroek parse_client_lease_statement(cfile, 0);
285*83ee113eSDavid van Moolenbroek break;
286*83ee113eSDavid van Moolenbroek
287*83ee113eSDavid van Moolenbroek case LEASE6:
288*83ee113eSDavid van Moolenbroek parse_client6_lease_statement(cfile);
289*83ee113eSDavid van Moolenbroek break;
290*83ee113eSDavid van Moolenbroek
291*83ee113eSDavid van Moolenbroek default:
292*83ee113eSDavid van Moolenbroek log_error ("Corrupt lease file - possible data loss!");
293*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
294*83ee113eSDavid van Moolenbroek break;
295*83ee113eSDavid van Moolenbroek }
296*83ee113eSDavid van Moolenbroek } while (1);
297*83ee113eSDavid van Moolenbroek
298*83ee113eSDavid van Moolenbroek end_parse (&cfile);
299*83ee113eSDavid van Moolenbroek }
300*83ee113eSDavid van Moolenbroek
301*83ee113eSDavid van Moolenbroek /* client-declaration :==
302*83ee113eSDavid van Moolenbroek SEND option-decl |
303*83ee113eSDavid van Moolenbroek DEFAULT option-decl |
304*83ee113eSDavid van Moolenbroek SUPERSEDE option-decl |
305*83ee113eSDavid van Moolenbroek PREPEND option-decl |
306*83ee113eSDavid van Moolenbroek APPEND option-decl |
307*83ee113eSDavid van Moolenbroek hardware-declaration |
308*83ee113eSDavid van Moolenbroek ALSO REQUEST option-list |
309*83ee113eSDavid van Moolenbroek ALSO REQUIRE option-list |
310*83ee113eSDavid van Moolenbroek REQUEST option-list |
311*83ee113eSDavid van Moolenbroek REQUIRE option-list |
312*83ee113eSDavid van Moolenbroek TIMEOUT number |
313*83ee113eSDavid van Moolenbroek RETRY number |
314*83ee113eSDavid van Moolenbroek REBOOT number |
315*83ee113eSDavid van Moolenbroek SELECT_TIMEOUT number |
316*83ee113eSDavid van Moolenbroek SCRIPT string |
317*83ee113eSDavid van Moolenbroek VENDOR_SPACE string |
318*83ee113eSDavid van Moolenbroek interface-declaration |
319*83ee113eSDavid van Moolenbroek LEASE client-lease-statement |
320*83ee113eSDavid van Moolenbroek ALIAS client-lease-statement |
321*83ee113eSDavid van Moolenbroek KEY key-definition */
322*83ee113eSDavid van Moolenbroek
parse_client_statement(cfile,ip,config)323*83ee113eSDavid van Moolenbroek void parse_client_statement (cfile, ip, config)
324*83ee113eSDavid van Moolenbroek struct parse *cfile;
325*83ee113eSDavid van Moolenbroek struct interface_info *ip;
326*83ee113eSDavid van Moolenbroek struct client_config *config;
327*83ee113eSDavid van Moolenbroek {
328*83ee113eSDavid van Moolenbroek int token;
329*83ee113eSDavid van Moolenbroek const char *val;
330*83ee113eSDavid van Moolenbroek struct option *option = NULL;
331*83ee113eSDavid van Moolenbroek struct executable_statement *stmt;
332*83ee113eSDavid van Moolenbroek int lose;
333*83ee113eSDavid van Moolenbroek char *name;
334*83ee113eSDavid van Moolenbroek enum policy policy;
335*83ee113eSDavid van Moolenbroek int known;
336*83ee113eSDavid van Moolenbroek int tmp, i;
337*83ee113eSDavid van Moolenbroek isc_result_t status;
338*83ee113eSDavid van Moolenbroek struct option ***append_list, **new_list, **cat_list;
339*83ee113eSDavid van Moolenbroek
340*83ee113eSDavid van Moolenbroek switch (peek_token (&val, (unsigned *)0, cfile)) {
341*83ee113eSDavid van Moolenbroek case INCLUDE:
342*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
343*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
344*83ee113eSDavid van Moolenbroek if (token != STRING) {
345*83ee113eSDavid van Moolenbroek parse_warn (cfile, "filename string expected.");
346*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
347*83ee113eSDavid van Moolenbroek } else {
348*83ee113eSDavid van Moolenbroek status = read_client_conf_file (val, ip, config);
349*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS)
350*83ee113eSDavid van Moolenbroek parse_warn (cfile, "%s: bad parse.", val);
351*83ee113eSDavid van Moolenbroek parse_semi (cfile);
352*83ee113eSDavid van Moolenbroek }
353*83ee113eSDavid van Moolenbroek return;
354*83ee113eSDavid van Moolenbroek
355*83ee113eSDavid van Moolenbroek case KEY:
356*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
357*83ee113eSDavid van Moolenbroek if (ip) {
358*83ee113eSDavid van Moolenbroek /* This may seem arbitrary, but there's a reason for
359*83ee113eSDavid van Moolenbroek doing it: the authentication key database is not
360*83ee113eSDavid van Moolenbroek scoped. If we allow the user to declare a key other
361*83ee113eSDavid van Moolenbroek than in the outer scope, the user is very likely to
362*83ee113eSDavid van Moolenbroek believe that the key will only be used in that
363*83ee113eSDavid van Moolenbroek scope. If the user only wants the key to be used on
364*83ee113eSDavid van Moolenbroek one interface, because it's known that the other
365*83ee113eSDavid van Moolenbroek interface may be connected to an insecure net and
366*83ee113eSDavid van Moolenbroek the secret key is considered sensitive, we don't
367*83ee113eSDavid van Moolenbroek want to lull them into believing they've gotten
368*83ee113eSDavid van Moolenbroek their way. This is a bit contrived, but people
369*83ee113eSDavid van Moolenbroek tend not to be entirely rational about security. */
370*83ee113eSDavid van Moolenbroek parse_warn (cfile, "key definition not allowed here.");
371*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
372*83ee113eSDavid van Moolenbroek break;
373*83ee113eSDavid van Moolenbroek }
374*83ee113eSDavid van Moolenbroek parse_key (cfile);
375*83ee113eSDavid van Moolenbroek return;
376*83ee113eSDavid van Moolenbroek
377*83ee113eSDavid van Moolenbroek case TOKEN_ALSO:
378*83ee113eSDavid van Moolenbroek /* consume ALSO */
379*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
380*83ee113eSDavid van Moolenbroek
381*83ee113eSDavid van Moolenbroek /* consume type of ALSO list. */
382*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
383*83ee113eSDavid van Moolenbroek
384*83ee113eSDavid van Moolenbroek if (token == REQUEST) {
385*83ee113eSDavid van Moolenbroek append_list = &config->requested_options;
386*83ee113eSDavid van Moolenbroek } else if (token == REQUIRE) {
387*83ee113eSDavid van Moolenbroek append_list = &config->required_options;
388*83ee113eSDavid van Moolenbroek } else {
389*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expected REQUEST or REQUIRE list");
390*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
391*83ee113eSDavid van Moolenbroek return;
392*83ee113eSDavid van Moolenbroek }
393*83ee113eSDavid van Moolenbroek
394*83ee113eSDavid van Moolenbroek /* If there is no list, cut the concat short. */
395*83ee113eSDavid van Moolenbroek if (*append_list == NULL) {
396*83ee113eSDavid van Moolenbroek parse_option_list(cfile, append_list);
397*83ee113eSDavid van Moolenbroek return;
398*83ee113eSDavid van Moolenbroek }
399*83ee113eSDavid van Moolenbroek
400*83ee113eSDavid van Moolenbroek /* Count the length of the existing list. */
401*83ee113eSDavid van Moolenbroek for (i = 0 ; (*append_list)[i] != NULL ; i++)
402*83ee113eSDavid van Moolenbroek ; /* This space intentionally left blank. */
403*83ee113eSDavid van Moolenbroek
404*83ee113eSDavid van Moolenbroek /* If there's no codes on the list, cut the concat short. */
405*83ee113eSDavid van Moolenbroek if (i == 0) {
406*83ee113eSDavid van Moolenbroek parse_option_list(cfile, append_list);
407*83ee113eSDavid van Moolenbroek return;
408*83ee113eSDavid van Moolenbroek }
409*83ee113eSDavid van Moolenbroek
410*83ee113eSDavid van Moolenbroek tmp = parse_option_list(cfile, &new_list);
411*83ee113eSDavid van Moolenbroek
412*83ee113eSDavid van Moolenbroek if (tmp == 0 || new_list == NULL)
413*83ee113eSDavid van Moolenbroek return;
414*83ee113eSDavid van Moolenbroek
415*83ee113eSDavid van Moolenbroek /* Allocate 'i + tmp' buckets plus a terminator. */
416*83ee113eSDavid van Moolenbroek cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
417*83ee113eSDavid van Moolenbroek MDL);
418*83ee113eSDavid van Moolenbroek
419*83ee113eSDavid van Moolenbroek if (cat_list == NULL) {
420*83ee113eSDavid van Moolenbroek log_error("Unable to allocate memory for new "
421*83ee113eSDavid van Moolenbroek "request list.");
422*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
423*83ee113eSDavid van Moolenbroek return;
424*83ee113eSDavid van Moolenbroek }
425*83ee113eSDavid van Moolenbroek
426*83ee113eSDavid van Moolenbroek for (i = 0 ; (*append_list)[i] != NULL ; i++)
427*83ee113eSDavid van Moolenbroek option_reference(&cat_list[i], (*append_list)[i], MDL);
428*83ee113eSDavid van Moolenbroek
429*83ee113eSDavid van Moolenbroek tmp = i;
430*83ee113eSDavid van Moolenbroek
431*83ee113eSDavid van Moolenbroek for (i = 0 ; new_list[i] != 0 ; i++)
432*83ee113eSDavid van Moolenbroek option_reference(&cat_list[tmp++], new_list[i], MDL);
433*83ee113eSDavid van Moolenbroek
434*83ee113eSDavid van Moolenbroek cat_list[tmp] = 0;
435*83ee113eSDavid van Moolenbroek
436*83ee113eSDavid van Moolenbroek /* XXX: We cannot free the old list, because it may have been
437*83ee113eSDavid van Moolenbroek * XXX: assigned from an outer configuration scope (or may be
438*83ee113eSDavid van Moolenbroek * XXX: the static default setting).
439*83ee113eSDavid van Moolenbroek */
440*83ee113eSDavid van Moolenbroek *append_list = cat_list;
441*83ee113eSDavid van Moolenbroek
442*83ee113eSDavid van Moolenbroek return;
443*83ee113eSDavid van Moolenbroek
444*83ee113eSDavid van Moolenbroek /* REQUIRE can either start a policy statement or a
445*83ee113eSDavid van Moolenbroek comma-separated list of names of required options. */
446*83ee113eSDavid van Moolenbroek case REQUIRE:
447*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
448*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
449*83ee113eSDavid van Moolenbroek if (token == AUTHENTICATION) {
450*83ee113eSDavid van Moolenbroek policy = P_REQUIRE;
451*83ee113eSDavid van Moolenbroek goto do_policy;
452*83ee113eSDavid van Moolenbroek }
453*83ee113eSDavid van Moolenbroek parse_option_list (cfile, &config -> required_options);
454*83ee113eSDavid van Moolenbroek return;
455*83ee113eSDavid van Moolenbroek
456*83ee113eSDavid van Moolenbroek case IGNORE:
457*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
458*83ee113eSDavid van Moolenbroek policy = P_IGNORE;
459*83ee113eSDavid van Moolenbroek goto do_policy;
460*83ee113eSDavid van Moolenbroek
461*83ee113eSDavid van Moolenbroek case ACCEPT:
462*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
463*83ee113eSDavid van Moolenbroek policy = P_ACCEPT;
464*83ee113eSDavid van Moolenbroek goto do_policy;
465*83ee113eSDavid van Moolenbroek
466*83ee113eSDavid van Moolenbroek case PREFER:
467*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
468*83ee113eSDavid van Moolenbroek policy = P_PREFER;
469*83ee113eSDavid van Moolenbroek goto do_policy;
470*83ee113eSDavid van Moolenbroek
471*83ee113eSDavid van Moolenbroek case DONT:
472*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
473*83ee113eSDavid van Moolenbroek policy = P_DONT;
474*83ee113eSDavid van Moolenbroek goto do_policy;
475*83ee113eSDavid van Moolenbroek
476*83ee113eSDavid van Moolenbroek do_policy:
477*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
478*83ee113eSDavid van Moolenbroek if (token == AUTHENTICATION) {
479*83ee113eSDavid van Moolenbroek if (policy != P_PREFER &&
480*83ee113eSDavid van Moolenbroek policy != P_REQUIRE &&
481*83ee113eSDavid van Moolenbroek policy != P_DONT) {
482*83ee113eSDavid van Moolenbroek parse_warn (cfile,
483*83ee113eSDavid van Moolenbroek "invalid authentication policy.");
484*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
485*83ee113eSDavid van Moolenbroek return;
486*83ee113eSDavid van Moolenbroek }
487*83ee113eSDavid van Moolenbroek config -> auth_policy = policy;
488*83ee113eSDavid van Moolenbroek } else if (token != TOKEN_BOOTP) {
489*83ee113eSDavid van Moolenbroek if (policy != P_PREFER &&
490*83ee113eSDavid van Moolenbroek policy != P_IGNORE &&
491*83ee113eSDavid van Moolenbroek policy != P_ACCEPT) {
492*83ee113eSDavid van Moolenbroek parse_warn (cfile, "invalid bootp policy.");
493*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
494*83ee113eSDavid van Moolenbroek return;
495*83ee113eSDavid van Moolenbroek }
496*83ee113eSDavid van Moolenbroek config -> bootp_policy = policy;
497*83ee113eSDavid van Moolenbroek } else {
498*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting a policy type.");
499*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
500*83ee113eSDavid van Moolenbroek return;
501*83ee113eSDavid van Moolenbroek }
502*83ee113eSDavid van Moolenbroek break;
503*83ee113eSDavid van Moolenbroek
504*83ee113eSDavid van Moolenbroek case OPTION:
505*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
506*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
507*83ee113eSDavid van Moolenbroek if (token == SPACE) {
508*83ee113eSDavid van Moolenbroek if (ip) {
509*83ee113eSDavid van Moolenbroek parse_warn (cfile,
510*83ee113eSDavid van Moolenbroek "option space definitions %s",
511*83ee113eSDavid van Moolenbroek " may not be scoped.");
512*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
513*83ee113eSDavid van Moolenbroek break;
514*83ee113eSDavid van Moolenbroek }
515*83ee113eSDavid van Moolenbroek parse_option_space_decl (cfile);
516*83ee113eSDavid van Moolenbroek return;
517*83ee113eSDavid van Moolenbroek }
518*83ee113eSDavid van Moolenbroek
519*83ee113eSDavid van Moolenbroek known = 0;
520*83ee113eSDavid van Moolenbroek status = parse_option_name(cfile, 1, &known, &option);
521*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL)
522*83ee113eSDavid van Moolenbroek return;
523*83ee113eSDavid van Moolenbroek
524*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
525*83ee113eSDavid van Moolenbroek if (token != CODE) {
526*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting \"code\" keyword.");
527*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
528*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
529*83ee113eSDavid van Moolenbroek return;
530*83ee113eSDavid van Moolenbroek }
531*83ee113eSDavid van Moolenbroek if (ip) {
532*83ee113eSDavid van Moolenbroek parse_warn (cfile,
533*83ee113eSDavid van Moolenbroek "option definitions may only appear in %s",
534*83ee113eSDavid van Moolenbroek "the outermost scope.");
535*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
536*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
537*83ee113eSDavid van Moolenbroek return;
538*83ee113eSDavid van Moolenbroek }
539*83ee113eSDavid van Moolenbroek
540*83ee113eSDavid van Moolenbroek /*
541*83ee113eSDavid van Moolenbroek * If the option was known, remove it from the code and name
542*83ee113eSDavid van Moolenbroek * hash tables before redefining it.
543*83ee113eSDavid van Moolenbroek */
544*83ee113eSDavid van Moolenbroek if (known) {
545*83ee113eSDavid van Moolenbroek option_name_hash_delete(option->universe->name_hash,
546*83ee113eSDavid van Moolenbroek option->name, 0, MDL);
547*83ee113eSDavid van Moolenbroek option_code_hash_delete(option->universe->code_hash,
548*83ee113eSDavid van Moolenbroek &option->code, 0, MDL);
549*83ee113eSDavid van Moolenbroek }
550*83ee113eSDavid van Moolenbroek
551*83ee113eSDavid van Moolenbroek parse_option_code_definition(cfile, option);
552*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
553*83ee113eSDavid van Moolenbroek return;
554*83ee113eSDavid van Moolenbroek
555*83ee113eSDavid van Moolenbroek case MEDIA:
556*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
557*83ee113eSDavid van Moolenbroek parse_string_list (cfile, &config -> media, 1);
558*83ee113eSDavid van Moolenbroek return;
559*83ee113eSDavid van Moolenbroek
560*83ee113eSDavid van Moolenbroek case HARDWARE:
561*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
562*83ee113eSDavid van Moolenbroek if (ip) {
563*83ee113eSDavid van Moolenbroek parse_hardware_param (cfile, &ip -> hw_address);
564*83ee113eSDavid van Moolenbroek } else {
565*83ee113eSDavid van Moolenbroek parse_warn (cfile, "hardware address parameter %s",
566*83ee113eSDavid van Moolenbroek "not allowed here.");
567*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
568*83ee113eSDavid van Moolenbroek }
569*83ee113eSDavid van Moolenbroek return;
570*83ee113eSDavid van Moolenbroek
571*83ee113eSDavid van Moolenbroek case ANYCAST_MAC:
572*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
573*83ee113eSDavid van Moolenbroek if (ip != NULL) {
574*83ee113eSDavid van Moolenbroek parse_hardware_param(cfile, &ip->anycast_mac_addr);
575*83ee113eSDavid van Moolenbroek } else {
576*83ee113eSDavid van Moolenbroek parse_warn(cfile, "anycast mac address parameter "
577*83ee113eSDavid van Moolenbroek "not allowed here.");
578*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
579*83ee113eSDavid van Moolenbroek }
580*83ee113eSDavid van Moolenbroek return;
581*83ee113eSDavid van Moolenbroek
582*83ee113eSDavid van Moolenbroek case REQUEST:
583*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
584*83ee113eSDavid van Moolenbroek if (config -> requested_options == default_requested_options)
585*83ee113eSDavid van Moolenbroek config -> requested_options = NULL;
586*83ee113eSDavid van Moolenbroek parse_option_list (cfile, &config -> requested_options);
587*83ee113eSDavid van Moolenbroek return;
588*83ee113eSDavid van Moolenbroek
589*83ee113eSDavid van Moolenbroek case TIMEOUT:
590*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
591*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> timeout);
592*83ee113eSDavid van Moolenbroek return;
593*83ee113eSDavid van Moolenbroek
594*83ee113eSDavid van Moolenbroek case RETRY:
595*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
596*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> retry_interval);
597*83ee113eSDavid van Moolenbroek return;
598*83ee113eSDavid van Moolenbroek
599*83ee113eSDavid van Moolenbroek case SELECT_TIMEOUT:
600*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
601*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> select_interval);
602*83ee113eSDavid van Moolenbroek return;
603*83ee113eSDavid van Moolenbroek
604*83ee113eSDavid van Moolenbroek case OMAPI:
605*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
606*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
607*83ee113eSDavid van Moolenbroek if (token != PORT) {
608*83ee113eSDavid van Moolenbroek parse_warn (cfile,
609*83ee113eSDavid van Moolenbroek "unexpected omapi subtype: %s", val);
610*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
611*83ee113eSDavid van Moolenbroek return;
612*83ee113eSDavid van Moolenbroek }
613*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
614*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
615*83ee113eSDavid van Moolenbroek parse_warn (cfile, "invalid port number: `%s'", val);
616*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
617*83ee113eSDavid van Moolenbroek return;
618*83ee113eSDavid van Moolenbroek }
619*83ee113eSDavid van Moolenbroek tmp = atoi (val);
620*83ee113eSDavid van Moolenbroek if (tmp < 0 || tmp > 65535)
621*83ee113eSDavid van Moolenbroek parse_warn (cfile, "invalid omapi port %d.", tmp);
622*83ee113eSDavid van Moolenbroek else if (config != &top_level_config)
623*83ee113eSDavid van Moolenbroek parse_warn (cfile,
624*83ee113eSDavid van Moolenbroek "omapi port only works at top level.");
625*83ee113eSDavid van Moolenbroek else
626*83ee113eSDavid van Moolenbroek config -> omapi_port = tmp;
627*83ee113eSDavid van Moolenbroek parse_semi (cfile);
628*83ee113eSDavid van Moolenbroek return;
629*83ee113eSDavid van Moolenbroek
630*83ee113eSDavid van Moolenbroek case DO_FORWARD_UPDATE:
631*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
632*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
633*83ee113eSDavid van Moolenbroek if (!strcasecmp (val, "on") ||
634*83ee113eSDavid van Moolenbroek !strcasecmp (val, "true"))
635*83ee113eSDavid van Moolenbroek config -> do_forward_update = 1;
636*83ee113eSDavid van Moolenbroek else if (!strcasecmp (val, "off") ||
637*83ee113eSDavid van Moolenbroek !strcasecmp (val, "false"))
638*83ee113eSDavid van Moolenbroek config -> do_forward_update = 0;
639*83ee113eSDavid van Moolenbroek else {
640*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting boolean value.");
641*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
642*83ee113eSDavid van Moolenbroek return;
643*83ee113eSDavid van Moolenbroek }
644*83ee113eSDavid van Moolenbroek parse_semi (cfile);
645*83ee113eSDavid van Moolenbroek return;
646*83ee113eSDavid van Moolenbroek
647*83ee113eSDavid van Moolenbroek case REBOOT:
648*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
649*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> reboot_timeout);
650*83ee113eSDavid van Moolenbroek return;
651*83ee113eSDavid van Moolenbroek
652*83ee113eSDavid van Moolenbroek case BACKOFF_CUTOFF:
653*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
654*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> backoff_cutoff);
655*83ee113eSDavid van Moolenbroek return;
656*83ee113eSDavid van Moolenbroek
657*83ee113eSDavid van Moolenbroek case INITIAL_INTERVAL:
658*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
659*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> initial_interval);
660*83ee113eSDavid van Moolenbroek return;
661*83ee113eSDavid van Moolenbroek
662*83ee113eSDavid van Moolenbroek case INITIAL_DELAY:
663*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
664*83ee113eSDavid van Moolenbroek parse_lease_time (cfile, &config -> initial_delay);
665*83ee113eSDavid van Moolenbroek return;
666*83ee113eSDavid van Moolenbroek
667*83ee113eSDavid van Moolenbroek case SCRIPT:
668*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
669*83ee113eSDavid van Moolenbroek parse_string (cfile, &config -> script_name, (unsigned *)0);
670*83ee113eSDavid van Moolenbroek return;
671*83ee113eSDavid van Moolenbroek
672*83ee113eSDavid van Moolenbroek case VENDOR:
673*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
674*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
675*83ee113eSDavid van Moolenbroek if (token != OPTION) {
676*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting 'vendor option space'");
677*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
678*83ee113eSDavid van Moolenbroek return;
679*83ee113eSDavid van Moolenbroek }
680*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
681*83ee113eSDavid van Moolenbroek if (token != SPACE) {
682*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting 'vendor option space'");
683*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
684*83ee113eSDavid van Moolenbroek return;
685*83ee113eSDavid van Moolenbroek }
686*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
687*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
688*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting an identifier.");
689*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
690*83ee113eSDavid van Moolenbroek return;
691*83ee113eSDavid van Moolenbroek }
692*83ee113eSDavid van Moolenbroek config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
693*83ee113eSDavid van Moolenbroek if (!config -> vendor_space_name)
694*83ee113eSDavid van Moolenbroek log_fatal ("no memory for vendor option space name.");
695*83ee113eSDavid van Moolenbroek strcpy (config -> vendor_space_name, val);
696*83ee113eSDavid van Moolenbroek for (i = 0; i < universe_count; i++)
697*83ee113eSDavid van Moolenbroek if (!strcmp (universes [i] -> name,
698*83ee113eSDavid van Moolenbroek config -> vendor_space_name))
699*83ee113eSDavid van Moolenbroek break;
700*83ee113eSDavid van Moolenbroek if (i == universe_count) {
701*83ee113eSDavid van Moolenbroek log_error ("vendor option space %s not found.",
702*83ee113eSDavid van Moolenbroek config -> vendor_space_name);
703*83ee113eSDavid van Moolenbroek }
704*83ee113eSDavid van Moolenbroek parse_semi (cfile);
705*83ee113eSDavid van Moolenbroek return;
706*83ee113eSDavid van Moolenbroek
707*83ee113eSDavid van Moolenbroek case INTERFACE:
708*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
709*83ee113eSDavid van Moolenbroek if (ip)
710*83ee113eSDavid van Moolenbroek parse_warn (cfile, "nested interface declaration.");
711*83ee113eSDavid van Moolenbroek parse_interface_declaration (cfile, config, (char *)0);
712*83ee113eSDavid van Moolenbroek return;
713*83ee113eSDavid van Moolenbroek
714*83ee113eSDavid van Moolenbroek case PSEUDO:
715*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
716*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
717*83ee113eSDavid van Moolenbroek name = dmalloc (strlen (val) + 1, MDL);
718*83ee113eSDavid van Moolenbroek if (!name)
719*83ee113eSDavid van Moolenbroek log_fatal ("no memory for pseudo interface name");
720*83ee113eSDavid van Moolenbroek strcpy (name, val);
721*83ee113eSDavid van Moolenbroek parse_interface_declaration (cfile, config, name);
722*83ee113eSDavid van Moolenbroek return;
723*83ee113eSDavid van Moolenbroek
724*83ee113eSDavid van Moolenbroek case LEASE:
725*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
726*83ee113eSDavid van Moolenbroek parse_client_lease_statement (cfile, 1);
727*83ee113eSDavid van Moolenbroek return;
728*83ee113eSDavid van Moolenbroek
729*83ee113eSDavid van Moolenbroek case ALIAS:
730*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
731*83ee113eSDavid van Moolenbroek parse_client_lease_statement (cfile, 2);
732*83ee113eSDavid van Moolenbroek return;
733*83ee113eSDavid van Moolenbroek
734*83ee113eSDavid van Moolenbroek case REJECT:
735*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
736*83ee113eSDavid van Moolenbroek parse_reject_statement (cfile, config);
737*83ee113eSDavid van Moolenbroek return;
738*83ee113eSDavid van Moolenbroek
739*83ee113eSDavid van Moolenbroek default:
740*83ee113eSDavid van Moolenbroek lose = 0;
741*83ee113eSDavid van Moolenbroek stmt = (struct executable_statement *)0;
742*83ee113eSDavid van Moolenbroek if (!parse_executable_statement (&stmt,
743*83ee113eSDavid van Moolenbroek cfile, &lose, context_any)) {
744*83ee113eSDavid van Moolenbroek if (!lose) {
745*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting a statement.");
746*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
747*83ee113eSDavid van Moolenbroek }
748*83ee113eSDavid van Moolenbroek } else {
749*83ee113eSDavid van Moolenbroek struct executable_statement **eptr, *sptr;
750*83ee113eSDavid van Moolenbroek if (stmt &&
751*83ee113eSDavid van Moolenbroek (stmt -> op == send_option_statement ||
752*83ee113eSDavid van Moolenbroek (stmt -> op == on_statement &&
753*83ee113eSDavid van Moolenbroek (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
754*83ee113eSDavid van Moolenbroek eptr = &config -> on_transmission -> statements;
755*83ee113eSDavid van Moolenbroek if (stmt -> op == on_statement) {
756*83ee113eSDavid van Moolenbroek sptr = (struct executable_statement *)0;
757*83ee113eSDavid van Moolenbroek executable_statement_reference
758*83ee113eSDavid van Moolenbroek (&sptr,
759*83ee113eSDavid van Moolenbroek stmt -> data.on.statements, MDL);
760*83ee113eSDavid van Moolenbroek executable_statement_dereference (&stmt,
761*83ee113eSDavid van Moolenbroek MDL);
762*83ee113eSDavid van Moolenbroek executable_statement_reference (&stmt,
763*83ee113eSDavid van Moolenbroek sptr,
764*83ee113eSDavid van Moolenbroek MDL);
765*83ee113eSDavid van Moolenbroek executable_statement_dereference (&sptr,
766*83ee113eSDavid van Moolenbroek MDL);
767*83ee113eSDavid van Moolenbroek }
768*83ee113eSDavid van Moolenbroek } else
769*83ee113eSDavid van Moolenbroek eptr = &config -> on_receipt -> statements;
770*83ee113eSDavid van Moolenbroek
771*83ee113eSDavid van Moolenbroek if (stmt) {
772*83ee113eSDavid van Moolenbroek for (; *eptr; eptr = &(*eptr) -> next)
773*83ee113eSDavid van Moolenbroek ;
774*83ee113eSDavid van Moolenbroek executable_statement_reference (eptr,
775*83ee113eSDavid van Moolenbroek stmt, MDL);
776*83ee113eSDavid van Moolenbroek }
777*83ee113eSDavid van Moolenbroek return;
778*83ee113eSDavid van Moolenbroek }
779*83ee113eSDavid van Moolenbroek break;
780*83ee113eSDavid van Moolenbroek }
781*83ee113eSDavid van Moolenbroek parse_semi (cfile);
782*83ee113eSDavid van Moolenbroek }
783*83ee113eSDavid van Moolenbroek
784*83ee113eSDavid van Moolenbroek /* option-list :== option_name |
785*83ee113eSDavid van Moolenbroek option_list COMMA option_name */
786*83ee113eSDavid van Moolenbroek
787*83ee113eSDavid van Moolenbroek int
parse_option_list(struct parse * cfile,struct option *** list)788*83ee113eSDavid van Moolenbroek parse_option_list(struct parse *cfile, struct option ***list)
789*83ee113eSDavid van Moolenbroek {
790*83ee113eSDavid van Moolenbroek int ix;
791*83ee113eSDavid van Moolenbroek int token;
792*83ee113eSDavid van Moolenbroek const char *val;
793*83ee113eSDavid van Moolenbroek pair p = (pair)0, q = (pair)0, r;
794*83ee113eSDavid van Moolenbroek struct option *option = NULL;
795*83ee113eSDavid van Moolenbroek isc_result_t status;
796*83ee113eSDavid van Moolenbroek
797*83ee113eSDavid van Moolenbroek ix = 0;
798*83ee113eSDavid van Moolenbroek do {
799*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
800*83ee113eSDavid van Moolenbroek if (token == SEMI) {
801*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
802*83ee113eSDavid van Moolenbroek break;
803*83ee113eSDavid van Moolenbroek }
804*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
805*83ee113eSDavid van Moolenbroek parse_warn (cfile, "%s: expected option name.", val);
806*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
807*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
808*83ee113eSDavid van Moolenbroek return 0;
809*83ee113eSDavid van Moolenbroek }
810*83ee113eSDavid van Moolenbroek status = parse_option_name(cfile, 0, NULL, &option);
811*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL) {
812*83ee113eSDavid van Moolenbroek parse_warn (cfile, "%s: expected option name.", val);
813*83ee113eSDavid van Moolenbroek return 0;
814*83ee113eSDavid van Moolenbroek }
815*83ee113eSDavid van Moolenbroek r = new_pair (MDL);
816*83ee113eSDavid van Moolenbroek if (!r)
817*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate pair for option code.");
818*83ee113eSDavid van Moolenbroek /* XXX: we should probably carry a reference across this */
819*83ee113eSDavid van Moolenbroek r->car = (caddr_t)option;
820*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
821*83ee113eSDavid van Moolenbroek r -> cdr = (pair)0;
822*83ee113eSDavid van Moolenbroek if (p)
823*83ee113eSDavid van Moolenbroek q -> cdr = r;
824*83ee113eSDavid van Moolenbroek else
825*83ee113eSDavid van Moolenbroek p = r;
826*83ee113eSDavid van Moolenbroek q = r;
827*83ee113eSDavid van Moolenbroek ++ix;
828*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
829*83ee113eSDavid van Moolenbroek } while (token == COMMA);
830*83ee113eSDavid van Moolenbroek if (token != SEMI) {
831*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting semicolon.");
832*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
833*83ee113eSDavid van Moolenbroek return 0;
834*83ee113eSDavid van Moolenbroek }
835*83ee113eSDavid van Moolenbroek /* XXX we can't free the list here, because we may have copied
836*83ee113eSDavid van Moolenbroek XXX it from an outer config state. */
837*83ee113eSDavid van Moolenbroek *list = NULL;
838*83ee113eSDavid van Moolenbroek if (ix) {
839*83ee113eSDavid van Moolenbroek *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
840*83ee113eSDavid van Moolenbroek if (!*list)
841*83ee113eSDavid van Moolenbroek log_error ("no memory for option list.");
842*83ee113eSDavid van Moolenbroek else {
843*83ee113eSDavid van Moolenbroek ix = 0;
844*83ee113eSDavid van Moolenbroek for (q = p; q; q = q -> cdr)
845*83ee113eSDavid van Moolenbroek option_reference(&(*list)[ix++],
846*83ee113eSDavid van Moolenbroek (struct option *)q->car, MDL);
847*83ee113eSDavid van Moolenbroek (*list)[ix] = NULL;
848*83ee113eSDavid van Moolenbroek }
849*83ee113eSDavid van Moolenbroek while (p) {
850*83ee113eSDavid van Moolenbroek q = p -> cdr;
851*83ee113eSDavid van Moolenbroek free_pair (p, MDL);
852*83ee113eSDavid van Moolenbroek p = q;
853*83ee113eSDavid van Moolenbroek }
854*83ee113eSDavid van Moolenbroek }
855*83ee113eSDavid van Moolenbroek
856*83ee113eSDavid van Moolenbroek return ix;
857*83ee113eSDavid van Moolenbroek }
858*83ee113eSDavid van Moolenbroek
859*83ee113eSDavid van Moolenbroek /* interface-declaration :==
860*83ee113eSDavid van Moolenbroek INTERFACE string LBRACE client-declarations RBRACE */
861*83ee113eSDavid van Moolenbroek
parse_interface_declaration(cfile,outer_config,name)862*83ee113eSDavid van Moolenbroek void parse_interface_declaration (cfile, outer_config, name)
863*83ee113eSDavid van Moolenbroek struct parse *cfile;
864*83ee113eSDavid van Moolenbroek struct client_config *outer_config;
865*83ee113eSDavid van Moolenbroek char *name;
866*83ee113eSDavid van Moolenbroek {
867*83ee113eSDavid van Moolenbroek int token;
868*83ee113eSDavid van Moolenbroek const char *val;
869*83ee113eSDavid van Moolenbroek struct client_state *client, **cp;
870*83ee113eSDavid van Moolenbroek struct interface_info *ip = (struct interface_info *)0;
871*83ee113eSDavid van Moolenbroek
872*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
873*83ee113eSDavid van Moolenbroek if (token != STRING) {
874*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting interface name (in quotes).");
875*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
876*83ee113eSDavid van Moolenbroek return;
877*83ee113eSDavid van Moolenbroek }
878*83ee113eSDavid van Moolenbroek
879*83ee113eSDavid van Moolenbroek if (!interface_or_dummy (&ip, val))
880*83ee113eSDavid van Moolenbroek log_fatal ("Can't allocate interface %s.", val);
881*83ee113eSDavid van Moolenbroek
882*83ee113eSDavid van Moolenbroek /* If we were given a name, this is a pseudo-interface. */
883*83ee113eSDavid van Moolenbroek if (name) {
884*83ee113eSDavid van Moolenbroek make_client_state (&client);
885*83ee113eSDavid van Moolenbroek client -> name = name;
886*83ee113eSDavid van Moolenbroek client -> interface = ip;
887*83ee113eSDavid van Moolenbroek for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
888*83ee113eSDavid van Moolenbroek ;
889*83ee113eSDavid van Moolenbroek *cp = client;
890*83ee113eSDavid van Moolenbroek } else {
891*83ee113eSDavid van Moolenbroek if (!ip -> client) {
892*83ee113eSDavid van Moolenbroek make_client_state (&ip -> client);
893*83ee113eSDavid van Moolenbroek ip -> client -> interface = ip;
894*83ee113eSDavid van Moolenbroek }
895*83ee113eSDavid van Moolenbroek client = ip -> client;
896*83ee113eSDavid van Moolenbroek }
897*83ee113eSDavid van Moolenbroek
898*83ee113eSDavid van Moolenbroek if (!client -> config)
899*83ee113eSDavid van Moolenbroek make_client_config (client, outer_config);
900*83ee113eSDavid van Moolenbroek
901*83ee113eSDavid van Moolenbroek ip -> flags &= ~INTERFACE_AUTOMATIC;
902*83ee113eSDavid van Moolenbroek interfaces_requested = 1;
903*83ee113eSDavid van Moolenbroek
904*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
905*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
906*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting left brace.");
907*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
908*83ee113eSDavid van Moolenbroek return;
909*83ee113eSDavid van Moolenbroek }
910*83ee113eSDavid van Moolenbroek
911*83ee113eSDavid van Moolenbroek do {
912*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
913*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
914*83ee113eSDavid van Moolenbroek parse_warn (cfile,
915*83ee113eSDavid van Moolenbroek "unterminated interface declaration.");
916*83ee113eSDavid van Moolenbroek return;
917*83ee113eSDavid van Moolenbroek }
918*83ee113eSDavid van Moolenbroek if (token == RBRACE)
919*83ee113eSDavid van Moolenbroek break;
920*83ee113eSDavid van Moolenbroek parse_client_statement (cfile, ip, client -> config);
921*83ee113eSDavid van Moolenbroek } while (1);
922*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
923*83ee113eSDavid van Moolenbroek }
924*83ee113eSDavid van Moolenbroek
interface_or_dummy(struct interface_info ** pi,const char * name)925*83ee113eSDavid van Moolenbroek int interface_or_dummy (struct interface_info **pi, const char *name)
926*83ee113eSDavid van Moolenbroek {
927*83ee113eSDavid van Moolenbroek struct interface_info *i;
928*83ee113eSDavid van Moolenbroek struct interface_info *ip = (struct interface_info *)0;
929*83ee113eSDavid van Moolenbroek isc_result_t status;
930*83ee113eSDavid van Moolenbroek
931*83ee113eSDavid van Moolenbroek /* Find the interface (if any) that matches the name. */
932*83ee113eSDavid van Moolenbroek for (i = interfaces; i; i = i -> next) {
933*83ee113eSDavid van Moolenbroek if (!strcmp (i -> name, name)) {
934*83ee113eSDavid van Moolenbroek interface_reference (&ip, i, MDL);
935*83ee113eSDavid van Moolenbroek break;
936*83ee113eSDavid van Moolenbroek }
937*83ee113eSDavid van Moolenbroek }
938*83ee113eSDavid van Moolenbroek
939*83ee113eSDavid van Moolenbroek /* If it's not a real interface, see if it's on the dummy list. */
940*83ee113eSDavid van Moolenbroek if (!ip) {
941*83ee113eSDavid van Moolenbroek for (ip = dummy_interfaces; ip; ip = ip -> next) {
942*83ee113eSDavid van Moolenbroek if (!strcmp (ip -> name, name)) {
943*83ee113eSDavid van Moolenbroek interface_reference (&ip, i, MDL);
944*83ee113eSDavid van Moolenbroek break;
945*83ee113eSDavid van Moolenbroek }
946*83ee113eSDavid van Moolenbroek }
947*83ee113eSDavid van Moolenbroek }
948*83ee113eSDavid van Moolenbroek
949*83ee113eSDavid van Moolenbroek /* If we didn't find an interface, make a dummy interface as
950*83ee113eSDavid van Moolenbroek a placeholder. */
951*83ee113eSDavid van Moolenbroek if (!ip) {
952*83ee113eSDavid van Moolenbroek if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
953*83ee113eSDavid van Moolenbroek log_fatal ("Can't record interface %s: %s",
954*83ee113eSDavid van Moolenbroek name, isc_result_totext (status));
955*83ee113eSDavid van Moolenbroek
956*83ee113eSDavid van Moolenbroek if (strlen(name) >= sizeof(ip->name)) {
957*83ee113eSDavid van Moolenbroek interface_dereference(&ip, MDL);
958*83ee113eSDavid van Moolenbroek return 0;
959*83ee113eSDavid van Moolenbroek }
960*83ee113eSDavid van Moolenbroek strcpy(ip->name, name);
961*83ee113eSDavid van Moolenbroek
962*83ee113eSDavid van Moolenbroek if (dummy_interfaces) {
963*83ee113eSDavid van Moolenbroek interface_reference (&ip -> next,
964*83ee113eSDavid van Moolenbroek dummy_interfaces, MDL);
965*83ee113eSDavid van Moolenbroek interface_dereference (&dummy_interfaces, MDL);
966*83ee113eSDavid van Moolenbroek }
967*83ee113eSDavid van Moolenbroek interface_reference (&dummy_interfaces, ip, MDL);
968*83ee113eSDavid van Moolenbroek }
969*83ee113eSDavid van Moolenbroek if (pi)
970*83ee113eSDavid van Moolenbroek status = interface_reference (pi, ip, MDL);
971*83ee113eSDavid van Moolenbroek else
972*83ee113eSDavid van Moolenbroek status = ISC_R_FAILURE;
973*83ee113eSDavid van Moolenbroek interface_dereference (&ip, MDL);
974*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS)
975*83ee113eSDavid van Moolenbroek return 0;
976*83ee113eSDavid van Moolenbroek return 1;
977*83ee113eSDavid van Moolenbroek }
978*83ee113eSDavid van Moolenbroek
make_client_state(state)979*83ee113eSDavid van Moolenbroek void make_client_state (state)
980*83ee113eSDavid van Moolenbroek struct client_state **state;
981*83ee113eSDavid van Moolenbroek {
982*83ee113eSDavid van Moolenbroek *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
983*83ee113eSDavid van Moolenbroek if (!*state)
984*83ee113eSDavid van Moolenbroek log_fatal ("no memory for client state\n");
985*83ee113eSDavid van Moolenbroek memset (*state, 0, sizeof **state);
986*83ee113eSDavid van Moolenbroek }
987*83ee113eSDavid van Moolenbroek
make_client_config(client,config)988*83ee113eSDavid van Moolenbroek void make_client_config (client, config)
989*83ee113eSDavid van Moolenbroek struct client_state *client;
990*83ee113eSDavid van Moolenbroek struct client_config *config;
991*83ee113eSDavid van Moolenbroek {
992*83ee113eSDavid van Moolenbroek client -> config = (((struct client_config *)
993*83ee113eSDavid van Moolenbroek dmalloc (sizeof (struct client_config), MDL)));
994*83ee113eSDavid van Moolenbroek if (!client -> config)
995*83ee113eSDavid van Moolenbroek log_fatal ("no memory for client config\n");
996*83ee113eSDavid van Moolenbroek memcpy (client -> config, config, sizeof *config);
997*83ee113eSDavid van Moolenbroek if (!clone_group (&client -> config -> on_receipt,
998*83ee113eSDavid van Moolenbroek config -> on_receipt, MDL) ||
999*83ee113eSDavid van Moolenbroek !clone_group (&client -> config -> on_transmission,
1000*83ee113eSDavid van Moolenbroek config -> on_transmission, MDL))
1001*83ee113eSDavid van Moolenbroek log_fatal ("no memory for client state groups.");
1002*83ee113eSDavid van Moolenbroek }
1003*83ee113eSDavid van Moolenbroek
1004*83ee113eSDavid van Moolenbroek /* client-lease-statement :==
1005*83ee113eSDavid van Moolenbroek LBRACE client-lease-declarations RBRACE
1006*83ee113eSDavid van Moolenbroek
1007*83ee113eSDavid van Moolenbroek client-lease-declarations :==
1008*83ee113eSDavid van Moolenbroek <nil> |
1009*83ee113eSDavid van Moolenbroek client-lease-declaration |
1010*83ee113eSDavid van Moolenbroek client-lease-declarations client-lease-declaration */
1011*83ee113eSDavid van Moolenbroek
1012*83ee113eSDavid van Moolenbroek
parse_client_lease_statement(cfile,is_static)1013*83ee113eSDavid van Moolenbroek void parse_client_lease_statement (cfile, is_static)
1014*83ee113eSDavid van Moolenbroek struct parse *cfile;
1015*83ee113eSDavid van Moolenbroek int is_static;
1016*83ee113eSDavid van Moolenbroek {
1017*83ee113eSDavid van Moolenbroek struct client_lease *lease, *lp, *pl, *next;
1018*83ee113eSDavid van Moolenbroek struct interface_info *ip = (struct interface_info *)0;
1019*83ee113eSDavid van Moolenbroek int token;
1020*83ee113eSDavid van Moolenbroek const char *val;
1021*83ee113eSDavid van Moolenbroek struct client_state *client = (struct client_state *)0;
1022*83ee113eSDavid van Moolenbroek
1023*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1024*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
1025*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting left brace.");
1026*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1027*83ee113eSDavid van Moolenbroek return;
1028*83ee113eSDavid van Moolenbroek }
1029*83ee113eSDavid van Moolenbroek
1030*83ee113eSDavid van Moolenbroek lease = ((struct client_lease *)
1031*83ee113eSDavid van Moolenbroek dmalloc (sizeof (struct client_lease), MDL));
1032*83ee113eSDavid van Moolenbroek if (!lease)
1033*83ee113eSDavid van Moolenbroek log_fatal ("no memory for lease.\n");
1034*83ee113eSDavid van Moolenbroek memset (lease, 0, sizeof *lease);
1035*83ee113eSDavid van Moolenbroek lease -> is_static = is_static;
1036*83ee113eSDavid van Moolenbroek if (!option_state_allocate (&lease -> options, MDL))
1037*83ee113eSDavid van Moolenbroek log_fatal ("no memory for lease options.\n");
1038*83ee113eSDavid van Moolenbroek
1039*83ee113eSDavid van Moolenbroek do {
1040*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
1041*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
1042*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unterminated lease declaration.");
1043*83ee113eSDavid van Moolenbroek return;
1044*83ee113eSDavid van Moolenbroek }
1045*83ee113eSDavid van Moolenbroek if (token == RBRACE)
1046*83ee113eSDavid van Moolenbroek break;
1047*83ee113eSDavid van Moolenbroek parse_client_lease_declaration (cfile, lease, &ip, &client);
1048*83ee113eSDavid van Moolenbroek } while (1);
1049*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
1050*83ee113eSDavid van Moolenbroek
1051*83ee113eSDavid van Moolenbroek /* If the lease declaration didn't include an interface
1052*83ee113eSDavid van Moolenbroek declaration that we recognized, it's of no use to us. */
1053*83ee113eSDavid van Moolenbroek if (!ip) {
1054*83ee113eSDavid van Moolenbroek destroy_client_lease (lease);
1055*83ee113eSDavid van Moolenbroek return;
1056*83ee113eSDavid van Moolenbroek }
1057*83ee113eSDavid van Moolenbroek
1058*83ee113eSDavid van Moolenbroek /* Make sure there's a client state structure... */
1059*83ee113eSDavid van Moolenbroek if (!ip -> client) {
1060*83ee113eSDavid van Moolenbroek make_client_state (&ip -> client);
1061*83ee113eSDavid van Moolenbroek ip -> client -> interface = ip;
1062*83ee113eSDavid van Moolenbroek }
1063*83ee113eSDavid van Moolenbroek if (!client)
1064*83ee113eSDavid van Moolenbroek client = ip -> client;
1065*83ee113eSDavid van Moolenbroek
1066*83ee113eSDavid van Moolenbroek /* If this is an alias lease, it doesn't need to be sorted in. */
1067*83ee113eSDavid van Moolenbroek if (is_static == 2) {
1068*83ee113eSDavid van Moolenbroek ip -> client -> alias = lease;
1069*83ee113eSDavid van Moolenbroek return;
1070*83ee113eSDavid van Moolenbroek }
1071*83ee113eSDavid van Moolenbroek
1072*83ee113eSDavid van Moolenbroek /* The new lease may supersede a lease that's not the
1073*83ee113eSDavid van Moolenbroek active lease but is still on the lease list, so scan the
1074*83ee113eSDavid van Moolenbroek lease list looking for a lease with the same address, and
1075*83ee113eSDavid van Moolenbroek if we find it, toss it. */
1076*83ee113eSDavid van Moolenbroek pl = (struct client_lease *)0;
1077*83ee113eSDavid van Moolenbroek for (lp = client -> leases; lp; lp = next) {
1078*83ee113eSDavid van Moolenbroek next = lp -> next;
1079*83ee113eSDavid van Moolenbroek if (lp -> address.len == lease -> address.len &&
1080*83ee113eSDavid van Moolenbroek !memcmp (lp -> address.iabuf, lease -> address.iabuf,
1081*83ee113eSDavid van Moolenbroek lease -> address.len)) {
1082*83ee113eSDavid van Moolenbroek if (pl)
1083*83ee113eSDavid van Moolenbroek pl -> next = next;
1084*83ee113eSDavid van Moolenbroek else
1085*83ee113eSDavid van Moolenbroek client -> leases = next;
1086*83ee113eSDavid van Moolenbroek destroy_client_lease (lp);
1087*83ee113eSDavid van Moolenbroek break;
1088*83ee113eSDavid van Moolenbroek } else
1089*83ee113eSDavid van Moolenbroek pl = lp;
1090*83ee113eSDavid van Moolenbroek }
1091*83ee113eSDavid van Moolenbroek
1092*83ee113eSDavid van Moolenbroek /* If this is a preloaded lease, just put it on the list of recorded
1093*83ee113eSDavid van Moolenbroek leases - don't make it the active lease. */
1094*83ee113eSDavid van Moolenbroek if (is_static) {
1095*83ee113eSDavid van Moolenbroek lease -> next = client -> leases;
1096*83ee113eSDavid van Moolenbroek client -> leases = lease;
1097*83ee113eSDavid van Moolenbroek return;
1098*83ee113eSDavid van Moolenbroek }
1099*83ee113eSDavid van Moolenbroek
1100*83ee113eSDavid van Moolenbroek /* The last lease in the lease file on a particular interface is
1101*83ee113eSDavid van Moolenbroek the active lease for that interface. Of course, we don't know
1102*83ee113eSDavid van Moolenbroek what the last lease in the file is until we've parsed the whole
1103*83ee113eSDavid van Moolenbroek file, so at this point, we assume that the lease we just parsed
1104*83ee113eSDavid van Moolenbroek is the active lease for its interface. If there's already
1105*83ee113eSDavid van Moolenbroek an active lease for the interface, and this lease is for the same
1106*83ee113eSDavid van Moolenbroek ip address, then we just toss the old active lease and replace
1107*83ee113eSDavid van Moolenbroek it with this one. If this lease is for a different address,
1108*83ee113eSDavid van Moolenbroek then if the old active lease has expired, we dump it; if not,
1109*83ee113eSDavid van Moolenbroek we put it on the list of leases for this interface which are
1110*83ee113eSDavid van Moolenbroek still valid but no longer active. */
1111*83ee113eSDavid van Moolenbroek if (client -> active) {
1112*83ee113eSDavid van Moolenbroek if (client -> active -> expiry < cur_time)
1113*83ee113eSDavid van Moolenbroek destroy_client_lease (client -> active);
1114*83ee113eSDavid van Moolenbroek else if (client -> active -> address.len ==
1115*83ee113eSDavid van Moolenbroek lease -> address.len &&
1116*83ee113eSDavid van Moolenbroek !memcmp (client -> active -> address.iabuf,
1117*83ee113eSDavid van Moolenbroek lease -> address.iabuf,
1118*83ee113eSDavid van Moolenbroek lease -> address.len))
1119*83ee113eSDavid van Moolenbroek destroy_client_lease (client -> active);
1120*83ee113eSDavid van Moolenbroek else {
1121*83ee113eSDavid van Moolenbroek client -> active -> next = client -> leases;
1122*83ee113eSDavid van Moolenbroek client -> leases = client -> active;
1123*83ee113eSDavid van Moolenbroek }
1124*83ee113eSDavid van Moolenbroek }
1125*83ee113eSDavid van Moolenbroek client -> active = lease;
1126*83ee113eSDavid van Moolenbroek
1127*83ee113eSDavid van Moolenbroek /* phew. */
1128*83ee113eSDavid van Moolenbroek }
1129*83ee113eSDavid van Moolenbroek
1130*83ee113eSDavid van Moolenbroek /* client-lease-declaration :==
1131*83ee113eSDavid van Moolenbroek BOOTP |
1132*83ee113eSDavid van Moolenbroek INTERFACE string |
1133*83ee113eSDavid van Moolenbroek FIXED_ADDR ip_address |
1134*83ee113eSDavid van Moolenbroek FILENAME string |
1135*83ee113eSDavid van Moolenbroek SERVER_NAME string |
1136*83ee113eSDavid van Moolenbroek OPTION option-decl |
1137*83ee113eSDavid van Moolenbroek RENEW time-decl |
1138*83ee113eSDavid van Moolenbroek REBIND time-decl |
1139*83ee113eSDavid van Moolenbroek EXPIRE time-decl |
1140*83ee113eSDavid van Moolenbroek KEY id */
1141*83ee113eSDavid van Moolenbroek
parse_client_lease_declaration(cfile,lease,ipp,clientp)1142*83ee113eSDavid van Moolenbroek void parse_client_lease_declaration (cfile, lease, ipp, clientp)
1143*83ee113eSDavid van Moolenbroek struct parse *cfile;
1144*83ee113eSDavid van Moolenbroek struct client_lease *lease;
1145*83ee113eSDavid van Moolenbroek struct interface_info **ipp;
1146*83ee113eSDavid van Moolenbroek struct client_state **clientp;
1147*83ee113eSDavid van Moolenbroek {
1148*83ee113eSDavid van Moolenbroek int token;
1149*83ee113eSDavid van Moolenbroek const char *val;
1150*83ee113eSDavid van Moolenbroek struct interface_info *ip;
1151*83ee113eSDavid van Moolenbroek struct option_cache *oc;
1152*83ee113eSDavid van Moolenbroek struct client_state *client = (struct client_state *)0;
1153*83ee113eSDavid van Moolenbroek
1154*83ee113eSDavid van Moolenbroek switch (next_token (&val, (unsigned *)0, cfile)) {
1155*83ee113eSDavid van Moolenbroek case KEY:
1156*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1157*83ee113eSDavid van Moolenbroek if (token != STRING && !is_identifier (token)) {
1158*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting key name.");
1159*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1160*83ee113eSDavid van Moolenbroek break;
1161*83ee113eSDavid van Moolenbroek }
1162*83ee113eSDavid van Moolenbroek if (omapi_auth_key_lookup_name (&lease -> key, val) !=
1163*83ee113eSDavid van Moolenbroek ISC_R_SUCCESS)
1164*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unknown key %s", val);
1165*83ee113eSDavid van Moolenbroek parse_semi (cfile);
1166*83ee113eSDavid van Moolenbroek break;
1167*83ee113eSDavid van Moolenbroek case TOKEN_BOOTP:
1168*83ee113eSDavid van Moolenbroek lease -> is_bootp = 1;
1169*83ee113eSDavid van Moolenbroek break;
1170*83ee113eSDavid van Moolenbroek
1171*83ee113eSDavid van Moolenbroek case INTERFACE:
1172*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1173*83ee113eSDavid van Moolenbroek if (token != STRING) {
1174*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1175*83ee113eSDavid van Moolenbroek "expecting interface name (in quotes).");
1176*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1177*83ee113eSDavid van Moolenbroek break;
1178*83ee113eSDavid van Moolenbroek }
1179*83ee113eSDavid van Moolenbroek if (!interface_or_dummy (ipp, val))
1180*83ee113eSDavid van Moolenbroek log_fatal ("Can't allocate interface %s.", val);
1181*83ee113eSDavid van Moolenbroek break;
1182*83ee113eSDavid van Moolenbroek
1183*83ee113eSDavid van Moolenbroek case NAME:
1184*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1185*83ee113eSDavid van Moolenbroek ip = *ipp;
1186*83ee113eSDavid van Moolenbroek if (!ip) {
1187*83ee113eSDavid van Moolenbroek parse_warn (cfile, "state name precedes interface.");
1188*83ee113eSDavid van Moolenbroek break;
1189*83ee113eSDavid van Moolenbroek }
1190*83ee113eSDavid van Moolenbroek for (client = ip -> client; client; client = client -> next)
1191*83ee113eSDavid van Moolenbroek if (client -> name && !strcmp (client -> name, val))
1192*83ee113eSDavid van Moolenbroek break;
1193*83ee113eSDavid van Moolenbroek if (!client)
1194*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1195*83ee113eSDavid van Moolenbroek "lease specified for unknown pseudo.");
1196*83ee113eSDavid van Moolenbroek *clientp = client;
1197*83ee113eSDavid van Moolenbroek break;
1198*83ee113eSDavid van Moolenbroek
1199*83ee113eSDavid van Moolenbroek case FIXED_ADDR:
1200*83ee113eSDavid van Moolenbroek if (!parse_ip_addr (cfile, &lease -> address))
1201*83ee113eSDavid van Moolenbroek return;
1202*83ee113eSDavid van Moolenbroek break;
1203*83ee113eSDavid van Moolenbroek
1204*83ee113eSDavid van Moolenbroek case MEDIUM:
1205*83ee113eSDavid van Moolenbroek parse_string_list (cfile, &lease -> medium, 0);
1206*83ee113eSDavid van Moolenbroek return;
1207*83ee113eSDavid van Moolenbroek
1208*83ee113eSDavid van Moolenbroek case FILENAME:
1209*83ee113eSDavid van Moolenbroek parse_string (cfile, &lease -> filename, (unsigned *)0);
1210*83ee113eSDavid van Moolenbroek return;
1211*83ee113eSDavid van Moolenbroek
1212*83ee113eSDavid van Moolenbroek case SERVER_NAME:
1213*83ee113eSDavid van Moolenbroek parse_string (cfile, &lease -> server_name, (unsigned *)0);
1214*83ee113eSDavid van Moolenbroek return;
1215*83ee113eSDavid van Moolenbroek
1216*83ee113eSDavid van Moolenbroek case RENEW:
1217*83ee113eSDavid van Moolenbroek lease -> renewal = parse_date (cfile);
1218*83ee113eSDavid van Moolenbroek return;
1219*83ee113eSDavid van Moolenbroek
1220*83ee113eSDavid van Moolenbroek case REBIND:
1221*83ee113eSDavid van Moolenbroek lease -> rebind = parse_date (cfile);
1222*83ee113eSDavid van Moolenbroek return;
1223*83ee113eSDavid van Moolenbroek
1224*83ee113eSDavid van Moolenbroek case EXPIRE:
1225*83ee113eSDavid van Moolenbroek lease -> expiry = parse_date (cfile);
1226*83ee113eSDavid van Moolenbroek return;
1227*83ee113eSDavid van Moolenbroek
1228*83ee113eSDavid van Moolenbroek case OPTION:
1229*83ee113eSDavid van Moolenbroek oc = (struct option_cache *)0;
1230*83ee113eSDavid van Moolenbroek if (parse_option_decl (&oc, cfile)) {
1231*83ee113eSDavid van Moolenbroek save_option(oc->option->universe, lease->options, oc);
1232*83ee113eSDavid van Moolenbroek option_cache_dereference (&oc, MDL);
1233*83ee113eSDavid van Moolenbroek }
1234*83ee113eSDavid van Moolenbroek return;
1235*83ee113eSDavid van Moolenbroek
1236*83ee113eSDavid van Moolenbroek default:
1237*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting lease declaration.");
1238*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1239*83ee113eSDavid van Moolenbroek break;
1240*83ee113eSDavid van Moolenbroek }
1241*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1242*83ee113eSDavid van Moolenbroek if (token != SEMI) {
1243*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting semicolon.");
1244*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1245*83ee113eSDavid van Moolenbroek }
1246*83ee113eSDavid van Moolenbroek }
1247*83ee113eSDavid van Moolenbroek
1248*83ee113eSDavid van Moolenbroek /* Parse a default-duid ""; statement.
1249*83ee113eSDavid van Moolenbroek */
1250*83ee113eSDavid van Moolenbroek static void
parse_client_default_duid(struct parse * cfile)1251*83ee113eSDavid van Moolenbroek parse_client_default_duid(struct parse *cfile)
1252*83ee113eSDavid van Moolenbroek {
1253*83ee113eSDavid van Moolenbroek struct data_string new_duid;
1254*83ee113eSDavid van Moolenbroek const char *val = NULL;
1255*83ee113eSDavid van Moolenbroek unsigned len;
1256*83ee113eSDavid van Moolenbroek int token;
1257*83ee113eSDavid van Moolenbroek
1258*83ee113eSDavid van Moolenbroek memset(&new_duid, 0, sizeof(new_duid));
1259*83ee113eSDavid van Moolenbroek
1260*83ee113eSDavid van Moolenbroek token = next_token(&val, &len, cfile);
1261*83ee113eSDavid van Moolenbroek if (token != STRING) {
1262*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expected DUID string.");
1263*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1264*83ee113eSDavid van Moolenbroek return;
1265*83ee113eSDavid van Moolenbroek }
1266*83ee113eSDavid van Moolenbroek
1267*83ee113eSDavid van Moolenbroek if (len <= 2) {
1268*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Invalid DUID contents.");
1269*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1270*83ee113eSDavid van Moolenbroek return;
1271*83ee113eSDavid van Moolenbroek }
1272*83ee113eSDavid van Moolenbroek
1273*83ee113eSDavid van Moolenbroek if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
1274*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Out of memory parsing default DUID.");
1275*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1276*83ee113eSDavid van Moolenbroek return;
1277*83ee113eSDavid van Moolenbroek }
1278*83ee113eSDavid van Moolenbroek new_duid.data = new_duid.buffer->data;
1279*83ee113eSDavid van Moolenbroek new_duid.len = len;
1280*83ee113eSDavid van Moolenbroek
1281*83ee113eSDavid van Moolenbroek memcpy(new_duid.buffer->data, val, len);
1282*83ee113eSDavid van Moolenbroek
1283*83ee113eSDavid van Moolenbroek /* Rotate the last entry into place. */
1284*83ee113eSDavid van Moolenbroek if (default_duid.buffer != NULL)
1285*83ee113eSDavid van Moolenbroek data_string_forget(&default_duid, MDL);
1286*83ee113eSDavid van Moolenbroek data_string_copy(&default_duid, &new_duid, MDL);
1287*83ee113eSDavid van Moolenbroek data_string_forget(&new_duid, MDL);
1288*83ee113eSDavid van Moolenbroek
1289*83ee113eSDavid van Moolenbroek parse_semi(cfile);
1290*83ee113eSDavid van Moolenbroek }
1291*83ee113eSDavid van Moolenbroek
1292*83ee113eSDavid van Moolenbroek /* Parse a lease6 {} construct. The v6 client is a little different
1293*83ee113eSDavid van Moolenbroek * than the v4 client today, in that it only retains one lease, the
1294*83ee113eSDavid van Moolenbroek * active lease, and discards any less recent information. It may
1295*83ee113eSDavid van Moolenbroek * be useful in the future to cache additional information, but it
1296*83ee113eSDavid van Moolenbroek * is not worth the effort for the moment.
1297*83ee113eSDavid van Moolenbroek */
1298*83ee113eSDavid van Moolenbroek static void
parse_client6_lease_statement(struct parse * cfile)1299*83ee113eSDavid van Moolenbroek parse_client6_lease_statement(struct parse *cfile)
1300*83ee113eSDavid van Moolenbroek {
1301*83ee113eSDavid van Moolenbroek #if !defined(DHCPv6)
1302*83ee113eSDavid van Moolenbroek parse_warn(cfile, "No DHCPv6 support.");
1303*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1304*83ee113eSDavid van Moolenbroek #else /* defined(DHCPv6) */
1305*83ee113eSDavid van Moolenbroek struct option_cache *oc = NULL;
1306*83ee113eSDavid van Moolenbroek struct dhc6_lease *lease;
1307*83ee113eSDavid van Moolenbroek struct dhc6_ia **ia;
1308*83ee113eSDavid van Moolenbroek struct client_state *client = NULL;
1309*83ee113eSDavid van Moolenbroek struct interface_info *iface = NULL;
1310*83ee113eSDavid van Moolenbroek struct data_string ds;
1311*83ee113eSDavid van Moolenbroek const char *val;
1312*83ee113eSDavid van Moolenbroek unsigned len;
1313*83ee113eSDavid van Moolenbroek int token, has_ia, no_semi, has_name;
1314*83ee113eSDavid van Moolenbroek
1315*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
1316*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
1317*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting open curly brace.");
1318*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1319*83ee113eSDavid van Moolenbroek return;
1320*83ee113eSDavid van Moolenbroek }
1321*83ee113eSDavid van Moolenbroek
1322*83ee113eSDavid van Moolenbroek lease = dmalloc(sizeof(*lease), MDL);
1323*83ee113eSDavid van Moolenbroek if (lease == NULL) {
1324*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate lease state.");
1325*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
1326*83ee113eSDavid van Moolenbroek return;
1327*83ee113eSDavid van Moolenbroek }
1328*83ee113eSDavid van Moolenbroek
1329*83ee113eSDavid van Moolenbroek option_state_allocate(&lease->options, MDL);
1330*83ee113eSDavid van Moolenbroek if (lease->options == NULL) {
1331*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate option cache.");
1332*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
1333*83ee113eSDavid van Moolenbroek dfree(lease, MDL);
1334*83ee113eSDavid van Moolenbroek return;
1335*83ee113eSDavid van Moolenbroek }
1336*83ee113eSDavid van Moolenbroek
1337*83ee113eSDavid van Moolenbroek has_ia = 0;
1338*83ee113eSDavid van Moolenbroek has_name = 0;
1339*83ee113eSDavid van Moolenbroek ia = &lease->bindings;
1340*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1341*83ee113eSDavid van Moolenbroek while (token != RBRACE) {
1342*83ee113eSDavid van Moolenbroek no_semi = 0;
1343*83ee113eSDavid van Moolenbroek
1344*83ee113eSDavid van Moolenbroek switch(token) {
1345*83ee113eSDavid van Moolenbroek case IA_NA:
1346*83ee113eSDavid van Moolenbroek *ia = parse_client6_ia_na_statement(cfile);
1347*83ee113eSDavid van Moolenbroek if (*ia != NULL) {
1348*83ee113eSDavid van Moolenbroek ia = &(*ia)->next;
1349*83ee113eSDavid van Moolenbroek has_ia = 1;
1350*83ee113eSDavid van Moolenbroek }
1351*83ee113eSDavid van Moolenbroek
1352*83ee113eSDavid van Moolenbroek no_semi = 1;
1353*83ee113eSDavid van Moolenbroek
1354*83ee113eSDavid van Moolenbroek break;
1355*83ee113eSDavid van Moolenbroek
1356*83ee113eSDavid van Moolenbroek case IA_TA:
1357*83ee113eSDavid van Moolenbroek *ia = parse_client6_ia_ta_statement(cfile);
1358*83ee113eSDavid van Moolenbroek if (*ia != NULL) {
1359*83ee113eSDavid van Moolenbroek ia = &(*ia)->next;
1360*83ee113eSDavid van Moolenbroek has_ia = 1;
1361*83ee113eSDavid van Moolenbroek }
1362*83ee113eSDavid van Moolenbroek
1363*83ee113eSDavid van Moolenbroek no_semi = 1;
1364*83ee113eSDavid van Moolenbroek
1365*83ee113eSDavid van Moolenbroek break;
1366*83ee113eSDavid van Moolenbroek
1367*83ee113eSDavid van Moolenbroek case IA_PD:
1368*83ee113eSDavid van Moolenbroek *ia = parse_client6_ia_pd_statement(cfile);
1369*83ee113eSDavid van Moolenbroek if (*ia != NULL) {
1370*83ee113eSDavid van Moolenbroek ia = &(*ia)->next;
1371*83ee113eSDavid van Moolenbroek has_ia = 1;
1372*83ee113eSDavid van Moolenbroek }
1373*83ee113eSDavid van Moolenbroek
1374*83ee113eSDavid van Moolenbroek no_semi = 1;
1375*83ee113eSDavid van Moolenbroek
1376*83ee113eSDavid van Moolenbroek break;
1377*83ee113eSDavid van Moolenbroek
1378*83ee113eSDavid van Moolenbroek case INTERFACE:
1379*83ee113eSDavid van Moolenbroek if (iface != NULL) {
1380*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Multiple interface names?");
1381*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1382*83ee113eSDavid van Moolenbroek no_semi = 1;
1383*83ee113eSDavid van Moolenbroek break;
1384*83ee113eSDavid van Moolenbroek }
1385*83ee113eSDavid van Moolenbroek
1386*83ee113eSDavid van Moolenbroek token = next_token(&val, &len, cfile);
1387*83ee113eSDavid van Moolenbroek if (token != STRING) {
1388*83ee113eSDavid van Moolenbroek strerror:
1389*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a string.");
1390*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1391*83ee113eSDavid van Moolenbroek no_semi = 1;
1392*83ee113eSDavid van Moolenbroek break;
1393*83ee113eSDavid van Moolenbroek }
1394*83ee113eSDavid van Moolenbroek
1395*83ee113eSDavid van Moolenbroek for (iface = interfaces ; iface != NULL ;
1396*83ee113eSDavid van Moolenbroek iface = iface->next) {
1397*83ee113eSDavid van Moolenbroek if (strcmp(iface->name, val) == 0)
1398*83ee113eSDavid van Moolenbroek break;
1399*83ee113eSDavid van Moolenbroek }
1400*83ee113eSDavid van Moolenbroek
1401*83ee113eSDavid van Moolenbroek if (iface == NULL) {
1402*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unknown interface.");
1403*83ee113eSDavid van Moolenbroek break;
1404*83ee113eSDavid van Moolenbroek }
1405*83ee113eSDavid van Moolenbroek
1406*83ee113eSDavid van Moolenbroek break;
1407*83ee113eSDavid van Moolenbroek
1408*83ee113eSDavid van Moolenbroek case NAME:
1409*83ee113eSDavid van Moolenbroek has_name = 1;
1410*83ee113eSDavid van Moolenbroek
1411*83ee113eSDavid van Moolenbroek if (client != NULL) {
1412*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Multiple state names?");
1413*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1414*83ee113eSDavid van Moolenbroek no_semi = 1;
1415*83ee113eSDavid van Moolenbroek break;
1416*83ee113eSDavid van Moolenbroek }
1417*83ee113eSDavid van Moolenbroek
1418*83ee113eSDavid van Moolenbroek if (iface == NULL) {
1419*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Client name without "
1420*83ee113eSDavid van Moolenbroek "interface.");
1421*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1422*83ee113eSDavid van Moolenbroek no_semi = 1;
1423*83ee113eSDavid van Moolenbroek break;
1424*83ee113eSDavid van Moolenbroek }
1425*83ee113eSDavid van Moolenbroek
1426*83ee113eSDavid van Moolenbroek token = next_token(&val, &len, cfile);
1427*83ee113eSDavid van Moolenbroek if (token != STRING)
1428*83ee113eSDavid van Moolenbroek goto strerror;
1429*83ee113eSDavid van Moolenbroek
1430*83ee113eSDavid van Moolenbroek for (client = iface->client ; client != NULL ;
1431*83ee113eSDavid van Moolenbroek client = client->next) {
1432*83ee113eSDavid van Moolenbroek if ((client->name != NULL) &&
1433*83ee113eSDavid van Moolenbroek (strcmp(client->name, val) == 0))
1434*83ee113eSDavid van Moolenbroek break;
1435*83ee113eSDavid van Moolenbroek }
1436*83ee113eSDavid van Moolenbroek
1437*83ee113eSDavid van Moolenbroek if (client == NULL) {
1438*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unknown client state %s.",
1439*83ee113eSDavid van Moolenbroek val);
1440*83ee113eSDavid van Moolenbroek break;
1441*83ee113eSDavid van Moolenbroek }
1442*83ee113eSDavid van Moolenbroek
1443*83ee113eSDavid van Moolenbroek break;
1444*83ee113eSDavid van Moolenbroek
1445*83ee113eSDavid van Moolenbroek case OPTION:
1446*83ee113eSDavid van Moolenbroek if (parse_option_decl(&oc, cfile)) {
1447*83ee113eSDavid van Moolenbroek save_option(oc->option->universe,
1448*83ee113eSDavid van Moolenbroek lease->options, oc);
1449*83ee113eSDavid van Moolenbroek option_cache_dereference(&oc, MDL);
1450*83ee113eSDavid van Moolenbroek }
1451*83ee113eSDavid van Moolenbroek no_semi = 1;
1452*83ee113eSDavid van Moolenbroek break;
1453*83ee113eSDavid van Moolenbroek
1454*83ee113eSDavid van Moolenbroek case TOKEN_RELEASED:
1455*83ee113eSDavid van Moolenbroek case TOKEN_ABANDONED:
1456*83ee113eSDavid van Moolenbroek lease->released = ISC_TRUE;
1457*83ee113eSDavid van Moolenbroek break;
1458*83ee113eSDavid van Moolenbroek
1459*83ee113eSDavid van Moolenbroek default:
1460*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token, %s.", val);
1461*83ee113eSDavid van Moolenbroek no_semi = 1;
1462*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1463*83ee113eSDavid van Moolenbroek break;
1464*83ee113eSDavid van Moolenbroek }
1465*83ee113eSDavid van Moolenbroek
1466*83ee113eSDavid van Moolenbroek if (!no_semi)
1467*83ee113eSDavid van Moolenbroek parse_semi(cfile);
1468*83ee113eSDavid van Moolenbroek
1469*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1470*83ee113eSDavid van Moolenbroek
1471*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
1472*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected end of file.");
1473*83ee113eSDavid van Moolenbroek break;
1474*83ee113eSDavid van Moolenbroek }
1475*83ee113eSDavid van Moolenbroek }
1476*83ee113eSDavid van Moolenbroek
1477*83ee113eSDavid van Moolenbroek if (!has_ia) {
1478*83ee113eSDavid van Moolenbroek log_debug("Lease with no IA's discarded from lease db.");
1479*83ee113eSDavid van Moolenbroek dhc6_lease_destroy(&lease, MDL);
1480*83ee113eSDavid van Moolenbroek return;
1481*83ee113eSDavid van Moolenbroek }
1482*83ee113eSDavid van Moolenbroek
1483*83ee113eSDavid van Moolenbroek if (iface == NULL)
1484*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Lease has no interface designation.");
1485*83ee113eSDavid van Moolenbroek else if (!has_name && (client == NULL)) {
1486*83ee113eSDavid van Moolenbroek for (client = iface->client ; client != NULL ;
1487*83ee113eSDavid van Moolenbroek client = client->next) {
1488*83ee113eSDavid van Moolenbroek if (client->name == NULL)
1489*83ee113eSDavid van Moolenbroek break;
1490*83ee113eSDavid van Moolenbroek }
1491*83ee113eSDavid van Moolenbroek }
1492*83ee113eSDavid van Moolenbroek
1493*83ee113eSDavid van Moolenbroek if (client == NULL) {
1494*83ee113eSDavid van Moolenbroek parse_warn(cfile, "No matching client state.");
1495*83ee113eSDavid van Moolenbroek dhc6_lease_destroy(&lease, MDL);
1496*83ee113eSDavid van Moolenbroek return;
1497*83ee113eSDavid van Moolenbroek }
1498*83ee113eSDavid van Moolenbroek
1499*83ee113eSDavid van Moolenbroek /* Fetch Preference option from option cache. */
1500*83ee113eSDavid van Moolenbroek memset(&ds, 0, sizeof(ds));
1501*83ee113eSDavid van Moolenbroek oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
1502*83ee113eSDavid van Moolenbroek if ((oc != NULL) &&
1503*83ee113eSDavid van Moolenbroek evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
1504*83ee113eSDavid van Moolenbroek NULL, &global_scope, oc, MDL)) {
1505*83ee113eSDavid van Moolenbroek if (ds.len != 1) {
1506*83ee113eSDavid van Moolenbroek log_error("Invalid length of DHCPv6 Preference option "
1507*83ee113eSDavid van Moolenbroek "(%d != 1)", ds.len);
1508*83ee113eSDavid van Moolenbroek data_string_forget(&ds, MDL);
1509*83ee113eSDavid van Moolenbroek dhc6_lease_destroy(&lease, MDL);
1510*83ee113eSDavid van Moolenbroek return;
1511*83ee113eSDavid van Moolenbroek } else
1512*83ee113eSDavid van Moolenbroek lease->pref = ds.data[0];
1513*83ee113eSDavid van Moolenbroek
1514*83ee113eSDavid van Moolenbroek data_string_forget(&ds, MDL);
1515*83ee113eSDavid van Moolenbroek }
1516*83ee113eSDavid van Moolenbroek
1517*83ee113eSDavid van Moolenbroek /* Fetch server-id option from option cache. */
1518*83ee113eSDavid van Moolenbroek oc = lookup_option(&dhcpv6_universe, lease->options, D6O_SERVERID);
1519*83ee113eSDavid van Moolenbroek if ((oc == NULL) ||
1520*83ee113eSDavid van Moolenbroek !evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
1521*83ee113eSDavid van Moolenbroek lease->options, NULL, &global_scope, oc,
1522*83ee113eSDavid van Moolenbroek MDL) ||
1523*83ee113eSDavid van Moolenbroek (lease->server_id.len == 0)) {
1524*83ee113eSDavid van Moolenbroek /* This should be impossible... */
1525*83ee113eSDavid van Moolenbroek log_error("Invalid SERVERID option cache.");
1526*83ee113eSDavid van Moolenbroek dhc6_lease_destroy(&lease, MDL);
1527*83ee113eSDavid van Moolenbroek return;
1528*83ee113eSDavid van Moolenbroek }
1529*83ee113eSDavid van Moolenbroek
1530*83ee113eSDavid van Moolenbroek if (client->active_lease != NULL)
1531*83ee113eSDavid van Moolenbroek dhc6_lease_destroy(&client->active_lease, MDL);
1532*83ee113eSDavid van Moolenbroek
1533*83ee113eSDavid van Moolenbroek client->active_lease = lease;
1534*83ee113eSDavid van Moolenbroek #endif /* defined(DHCPv6) */
1535*83ee113eSDavid van Moolenbroek }
1536*83ee113eSDavid van Moolenbroek
1537*83ee113eSDavid van Moolenbroek /* Parse an ia_na object from the client lease.
1538*83ee113eSDavid van Moolenbroek */
1539*83ee113eSDavid van Moolenbroek #ifdef DHCPv6
1540*83ee113eSDavid van Moolenbroek static struct dhc6_ia *
parse_client6_ia_na_statement(struct parse * cfile)1541*83ee113eSDavid van Moolenbroek parse_client6_ia_na_statement(struct parse *cfile)
1542*83ee113eSDavid van Moolenbroek {
1543*83ee113eSDavid van Moolenbroek struct option_cache *oc = NULL;
1544*83ee113eSDavid van Moolenbroek struct dhc6_ia *ia;
1545*83ee113eSDavid van Moolenbroek struct dhc6_addr **addr;
1546*83ee113eSDavid van Moolenbroek const char *val;
1547*83ee113eSDavid van Moolenbroek int token, no_semi, len;
1548*83ee113eSDavid van Moolenbroek u_int8_t buf[5];
1549*83ee113eSDavid van Moolenbroek
1550*83ee113eSDavid van Moolenbroek ia = dmalloc(sizeof(*ia), MDL);
1551*83ee113eSDavid van Moolenbroek if (ia == NULL) {
1552*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Out of memory allocating IA_NA state.");
1553*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1554*83ee113eSDavid van Moolenbroek return NULL;
1555*83ee113eSDavid van Moolenbroek }
1556*83ee113eSDavid van Moolenbroek ia->ia_type = D6O_IA_NA;
1557*83ee113eSDavid van Moolenbroek
1558*83ee113eSDavid van Moolenbroek /* Get IAID. */
1559*83ee113eSDavid van Moolenbroek len = parse_X(cfile, buf, 5);
1560*83ee113eSDavid van Moolenbroek if (len == 4) {
1561*83ee113eSDavid van Moolenbroek memcpy(ia->iaid, buf, 4);
1562*83ee113eSDavid van Moolenbroek } else {
1563*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
1564*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1565*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1566*83ee113eSDavid van Moolenbroek return NULL;
1567*83ee113eSDavid van Moolenbroek }
1568*83ee113eSDavid van Moolenbroek
1569*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
1570*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
1571*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting open curly brace.");
1572*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1573*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1574*83ee113eSDavid van Moolenbroek return NULL;
1575*83ee113eSDavid van Moolenbroek }
1576*83ee113eSDavid van Moolenbroek
1577*83ee113eSDavid van Moolenbroek option_state_allocate(&ia->options, MDL);
1578*83ee113eSDavid van Moolenbroek if (ia->options == NULL) {
1579*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate option state.");
1580*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
1581*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1582*83ee113eSDavid van Moolenbroek return NULL;
1583*83ee113eSDavid van Moolenbroek }
1584*83ee113eSDavid van Moolenbroek
1585*83ee113eSDavid van Moolenbroek addr = &ia->addrs;
1586*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1587*83ee113eSDavid van Moolenbroek while (token != RBRACE) {
1588*83ee113eSDavid van Moolenbroek no_semi = 0;
1589*83ee113eSDavid van Moolenbroek
1590*83ee113eSDavid van Moolenbroek switch (token) {
1591*83ee113eSDavid van Moolenbroek case STARTS:
1592*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1593*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1594*83ee113eSDavid van Moolenbroek ia->starts = atoi(val);
1595*83ee113eSDavid van Moolenbroek } else {
1596*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1597*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1598*83ee113eSDavid van Moolenbroek no_semi = 1;
1599*83ee113eSDavid van Moolenbroek }
1600*83ee113eSDavid van Moolenbroek break;
1601*83ee113eSDavid van Moolenbroek
1602*83ee113eSDavid van Moolenbroek case RENEW:
1603*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1604*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1605*83ee113eSDavid van Moolenbroek ia->renew = atoi(val);
1606*83ee113eSDavid van Moolenbroek } else {
1607*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1608*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1609*83ee113eSDavid van Moolenbroek no_semi = 1;
1610*83ee113eSDavid van Moolenbroek }
1611*83ee113eSDavid van Moolenbroek break;
1612*83ee113eSDavid van Moolenbroek
1613*83ee113eSDavid van Moolenbroek case REBIND:
1614*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1615*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1616*83ee113eSDavid van Moolenbroek ia->rebind = atoi(val);
1617*83ee113eSDavid van Moolenbroek } else {
1618*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1619*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1620*83ee113eSDavid van Moolenbroek no_semi = 1;
1621*83ee113eSDavid van Moolenbroek }
1622*83ee113eSDavid van Moolenbroek break;
1623*83ee113eSDavid van Moolenbroek
1624*83ee113eSDavid van Moolenbroek case IAADDR:
1625*83ee113eSDavid van Moolenbroek *addr = parse_client6_iaaddr_statement(cfile);
1626*83ee113eSDavid van Moolenbroek
1627*83ee113eSDavid van Moolenbroek if (*addr != NULL)
1628*83ee113eSDavid van Moolenbroek addr = &(*addr)->next;
1629*83ee113eSDavid van Moolenbroek
1630*83ee113eSDavid van Moolenbroek no_semi = 1;
1631*83ee113eSDavid van Moolenbroek
1632*83ee113eSDavid van Moolenbroek break;
1633*83ee113eSDavid van Moolenbroek
1634*83ee113eSDavid van Moolenbroek case OPTION:
1635*83ee113eSDavid van Moolenbroek if (parse_option_decl(&oc, cfile)) {
1636*83ee113eSDavid van Moolenbroek save_option(oc->option->universe,
1637*83ee113eSDavid van Moolenbroek ia->options, oc);
1638*83ee113eSDavid van Moolenbroek option_cache_dereference(&oc, MDL);
1639*83ee113eSDavid van Moolenbroek }
1640*83ee113eSDavid van Moolenbroek no_semi = 1;
1641*83ee113eSDavid van Moolenbroek break;
1642*83ee113eSDavid van Moolenbroek
1643*83ee113eSDavid van Moolenbroek default:
1644*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token.");
1645*83ee113eSDavid van Moolenbroek no_semi = 1;
1646*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1647*83ee113eSDavid van Moolenbroek break;
1648*83ee113eSDavid van Moolenbroek }
1649*83ee113eSDavid van Moolenbroek
1650*83ee113eSDavid van Moolenbroek if (!no_semi)
1651*83ee113eSDavid van Moolenbroek parse_semi(cfile);
1652*83ee113eSDavid van Moolenbroek
1653*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1654*83ee113eSDavid van Moolenbroek
1655*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
1656*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected end of file.");
1657*83ee113eSDavid van Moolenbroek break;
1658*83ee113eSDavid van Moolenbroek }
1659*83ee113eSDavid van Moolenbroek }
1660*83ee113eSDavid van Moolenbroek
1661*83ee113eSDavid van Moolenbroek return ia;
1662*83ee113eSDavid van Moolenbroek }
1663*83ee113eSDavid van Moolenbroek #endif /* DHCPv6 */
1664*83ee113eSDavid van Moolenbroek
1665*83ee113eSDavid van Moolenbroek /* Parse an ia_ta object from the client lease.
1666*83ee113eSDavid van Moolenbroek */
1667*83ee113eSDavid van Moolenbroek #ifdef DHCPv6
1668*83ee113eSDavid van Moolenbroek static struct dhc6_ia *
parse_client6_ia_ta_statement(struct parse * cfile)1669*83ee113eSDavid van Moolenbroek parse_client6_ia_ta_statement(struct parse *cfile)
1670*83ee113eSDavid van Moolenbroek {
1671*83ee113eSDavid van Moolenbroek struct option_cache *oc = NULL;
1672*83ee113eSDavid van Moolenbroek struct dhc6_ia *ia;
1673*83ee113eSDavid van Moolenbroek struct dhc6_addr **addr;
1674*83ee113eSDavid van Moolenbroek const char *val;
1675*83ee113eSDavid van Moolenbroek int token, no_semi, len;
1676*83ee113eSDavid van Moolenbroek u_int8_t buf[5];
1677*83ee113eSDavid van Moolenbroek
1678*83ee113eSDavid van Moolenbroek ia = dmalloc(sizeof(*ia), MDL);
1679*83ee113eSDavid van Moolenbroek if (ia == NULL) {
1680*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Out of memory allocating IA_TA state.");
1681*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1682*83ee113eSDavid van Moolenbroek return NULL;
1683*83ee113eSDavid van Moolenbroek }
1684*83ee113eSDavid van Moolenbroek ia->ia_type = D6O_IA_TA;
1685*83ee113eSDavid van Moolenbroek
1686*83ee113eSDavid van Moolenbroek /* Get IAID. */
1687*83ee113eSDavid van Moolenbroek len = parse_X(cfile, buf, 5);
1688*83ee113eSDavid van Moolenbroek if (len == 4) {
1689*83ee113eSDavid van Moolenbroek memcpy(ia->iaid, buf, 4);
1690*83ee113eSDavid van Moolenbroek } else {
1691*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
1692*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1693*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1694*83ee113eSDavid van Moolenbroek return NULL;
1695*83ee113eSDavid van Moolenbroek }
1696*83ee113eSDavid van Moolenbroek
1697*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
1698*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
1699*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting open curly brace.");
1700*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1701*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1702*83ee113eSDavid van Moolenbroek return NULL;
1703*83ee113eSDavid van Moolenbroek }
1704*83ee113eSDavid van Moolenbroek
1705*83ee113eSDavid van Moolenbroek option_state_allocate(&ia->options, MDL);
1706*83ee113eSDavid van Moolenbroek if (ia->options == NULL) {
1707*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate option state.");
1708*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
1709*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1710*83ee113eSDavid van Moolenbroek return NULL;
1711*83ee113eSDavid van Moolenbroek }
1712*83ee113eSDavid van Moolenbroek
1713*83ee113eSDavid van Moolenbroek addr = &ia->addrs;
1714*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1715*83ee113eSDavid van Moolenbroek while (token != RBRACE) {
1716*83ee113eSDavid van Moolenbroek no_semi = 0;
1717*83ee113eSDavid van Moolenbroek
1718*83ee113eSDavid van Moolenbroek switch (token) {
1719*83ee113eSDavid van Moolenbroek case STARTS:
1720*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1721*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1722*83ee113eSDavid van Moolenbroek ia->starts = atoi(val);
1723*83ee113eSDavid van Moolenbroek } else {
1724*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1725*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1726*83ee113eSDavid van Moolenbroek no_semi = 1;
1727*83ee113eSDavid van Moolenbroek }
1728*83ee113eSDavid van Moolenbroek break;
1729*83ee113eSDavid van Moolenbroek
1730*83ee113eSDavid van Moolenbroek /* No RENEW or REBIND */
1731*83ee113eSDavid van Moolenbroek
1732*83ee113eSDavid van Moolenbroek case IAADDR:
1733*83ee113eSDavid van Moolenbroek *addr = parse_client6_iaaddr_statement(cfile);
1734*83ee113eSDavid van Moolenbroek
1735*83ee113eSDavid van Moolenbroek if (*addr != NULL)
1736*83ee113eSDavid van Moolenbroek addr = &(*addr)->next;
1737*83ee113eSDavid van Moolenbroek
1738*83ee113eSDavid van Moolenbroek no_semi = 1;
1739*83ee113eSDavid van Moolenbroek
1740*83ee113eSDavid van Moolenbroek break;
1741*83ee113eSDavid van Moolenbroek
1742*83ee113eSDavid van Moolenbroek case OPTION:
1743*83ee113eSDavid van Moolenbroek if (parse_option_decl(&oc, cfile)) {
1744*83ee113eSDavid van Moolenbroek save_option(oc->option->universe,
1745*83ee113eSDavid van Moolenbroek ia->options, oc);
1746*83ee113eSDavid van Moolenbroek option_cache_dereference(&oc, MDL);
1747*83ee113eSDavid van Moolenbroek }
1748*83ee113eSDavid van Moolenbroek no_semi = 1;
1749*83ee113eSDavid van Moolenbroek break;
1750*83ee113eSDavid van Moolenbroek
1751*83ee113eSDavid van Moolenbroek default:
1752*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token.");
1753*83ee113eSDavid van Moolenbroek no_semi = 1;
1754*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1755*83ee113eSDavid van Moolenbroek break;
1756*83ee113eSDavid van Moolenbroek }
1757*83ee113eSDavid van Moolenbroek
1758*83ee113eSDavid van Moolenbroek if (!no_semi)
1759*83ee113eSDavid van Moolenbroek parse_semi(cfile);
1760*83ee113eSDavid van Moolenbroek
1761*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1762*83ee113eSDavid van Moolenbroek
1763*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
1764*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected end of file.");
1765*83ee113eSDavid van Moolenbroek break;
1766*83ee113eSDavid van Moolenbroek }
1767*83ee113eSDavid van Moolenbroek }
1768*83ee113eSDavid van Moolenbroek
1769*83ee113eSDavid van Moolenbroek return ia;
1770*83ee113eSDavid van Moolenbroek }
1771*83ee113eSDavid van Moolenbroek #endif /* DHCPv6 */
1772*83ee113eSDavid van Moolenbroek
1773*83ee113eSDavid van Moolenbroek /* Parse an ia_pd object from the client lease.
1774*83ee113eSDavid van Moolenbroek */
1775*83ee113eSDavid van Moolenbroek #ifdef DHCPv6
1776*83ee113eSDavid van Moolenbroek static struct dhc6_ia *
parse_client6_ia_pd_statement(struct parse * cfile)1777*83ee113eSDavid van Moolenbroek parse_client6_ia_pd_statement(struct parse *cfile)
1778*83ee113eSDavid van Moolenbroek {
1779*83ee113eSDavid van Moolenbroek struct option_cache *oc = NULL;
1780*83ee113eSDavid van Moolenbroek struct dhc6_ia *ia;
1781*83ee113eSDavid van Moolenbroek struct dhc6_addr **pref;
1782*83ee113eSDavid van Moolenbroek const char *val;
1783*83ee113eSDavid van Moolenbroek int token, no_semi, len;
1784*83ee113eSDavid van Moolenbroek u_int8_t buf[5];
1785*83ee113eSDavid van Moolenbroek
1786*83ee113eSDavid van Moolenbroek ia = dmalloc(sizeof(*ia), MDL);
1787*83ee113eSDavid van Moolenbroek if (ia == NULL) {
1788*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Out of memory allocating IA_PD state.");
1789*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1790*83ee113eSDavid van Moolenbroek return NULL;
1791*83ee113eSDavid van Moolenbroek }
1792*83ee113eSDavid van Moolenbroek ia->ia_type = D6O_IA_PD;
1793*83ee113eSDavid van Moolenbroek
1794*83ee113eSDavid van Moolenbroek /* Get IAID. */
1795*83ee113eSDavid van Moolenbroek len = parse_X(cfile, buf, 5);
1796*83ee113eSDavid van Moolenbroek if (len == 4) {
1797*83ee113eSDavid van Moolenbroek memcpy(ia->iaid, buf, 4);
1798*83ee113eSDavid van Moolenbroek } else {
1799*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
1800*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1801*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1802*83ee113eSDavid van Moolenbroek return NULL;
1803*83ee113eSDavid van Moolenbroek }
1804*83ee113eSDavid van Moolenbroek
1805*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
1806*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
1807*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting open curly brace.");
1808*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1809*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1810*83ee113eSDavid van Moolenbroek return NULL;
1811*83ee113eSDavid van Moolenbroek }
1812*83ee113eSDavid van Moolenbroek
1813*83ee113eSDavid van Moolenbroek option_state_allocate(&ia->options, MDL);
1814*83ee113eSDavid van Moolenbroek if (ia->options == NULL) {
1815*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate option state.");
1816*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
1817*83ee113eSDavid van Moolenbroek dfree(ia, MDL);
1818*83ee113eSDavid van Moolenbroek return NULL;
1819*83ee113eSDavid van Moolenbroek }
1820*83ee113eSDavid van Moolenbroek
1821*83ee113eSDavid van Moolenbroek pref = &ia->addrs;
1822*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1823*83ee113eSDavid van Moolenbroek while (token != RBRACE) {
1824*83ee113eSDavid van Moolenbroek no_semi = 0;
1825*83ee113eSDavid van Moolenbroek
1826*83ee113eSDavid van Moolenbroek switch (token) {
1827*83ee113eSDavid van Moolenbroek case STARTS:
1828*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1829*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1830*83ee113eSDavid van Moolenbroek ia->starts = atoi(val);
1831*83ee113eSDavid van Moolenbroek } else {
1832*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1833*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1834*83ee113eSDavid van Moolenbroek no_semi = 1;
1835*83ee113eSDavid van Moolenbroek }
1836*83ee113eSDavid van Moolenbroek break;
1837*83ee113eSDavid van Moolenbroek
1838*83ee113eSDavid van Moolenbroek case RENEW:
1839*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1840*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1841*83ee113eSDavid van Moolenbroek ia->renew = atoi(val);
1842*83ee113eSDavid van Moolenbroek } else {
1843*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1844*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1845*83ee113eSDavid van Moolenbroek no_semi = 1;
1846*83ee113eSDavid van Moolenbroek }
1847*83ee113eSDavid van Moolenbroek break;
1848*83ee113eSDavid van Moolenbroek
1849*83ee113eSDavid van Moolenbroek case REBIND:
1850*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1851*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1852*83ee113eSDavid van Moolenbroek ia->rebind = atoi(val);
1853*83ee113eSDavid van Moolenbroek } else {
1854*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1855*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1856*83ee113eSDavid van Moolenbroek no_semi = 1;
1857*83ee113eSDavid van Moolenbroek }
1858*83ee113eSDavid van Moolenbroek break;
1859*83ee113eSDavid van Moolenbroek
1860*83ee113eSDavid van Moolenbroek case IAPREFIX:
1861*83ee113eSDavid van Moolenbroek *pref = parse_client6_iaprefix_statement(cfile);
1862*83ee113eSDavid van Moolenbroek
1863*83ee113eSDavid van Moolenbroek if (*pref != NULL)
1864*83ee113eSDavid van Moolenbroek pref = &(*pref)->next;
1865*83ee113eSDavid van Moolenbroek
1866*83ee113eSDavid van Moolenbroek no_semi = 1;
1867*83ee113eSDavid van Moolenbroek
1868*83ee113eSDavid van Moolenbroek break;
1869*83ee113eSDavid van Moolenbroek
1870*83ee113eSDavid van Moolenbroek case OPTION:
1871*83ee113eSDavid van Moolenbroek if (parse_option_decl(&oc, cfile)) {
1872*83ee113eSDavid van Moolenbroek save_option(oc->option->universe,
1873*83ee113eSDavid van Moolenbroek ia->options, oc);
1874*83ee113eSDavid van Moolenbroek option_cache_dereference(&oc, MDL);
1875*83ee113eSDavid van Moolenbroek }
1876*83ee113eSDavid van Moolenbroek no_semi = 1;
1877*83ee113eSDavid van Moolenbroek break;
1878*83ee113eSDavid van Moolenbroek
1879*83ee113eSDavid van Moolenbroek default:
1880*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token.");
1881*83ee113eSDavid van Moolenbroek no_semi = 1;
1882*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1883*83ee113eSDavid van Moolenbroek break;
1884*83ee113eSDavid van Moolenbroek }
1885*83ee113eSDavid van Moolenbroek
1886*83ee113eSDavid van Moolenbroek if (!no_semi)
1887*83ee113eSDavid van Moolenbroek parse_semi(cfile);
1888*83ee113eSDavid van Moolenbroek
1889*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1890*83ee113eSDavid van Moolenbroek
1891*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
1892*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected end of file.");
1893*83ee113eSDavid van Moolenbroek break;
1894*83ee113eSDavid van Moolenbroek }
1895*83ee113eSDavid van Moolenbroek }
1896*83ee113eSDavid van Moolenbroek
1897*83ee113eSDavid van Moolenbroek return ia;
1898*83ee113eSDavid van Moolenbroek }
1899*83ee113eSDavid van Moolenbroek #endif /* DHCPv6 */
1900*83ee113eSDavid van Moolenbroek
1901*83ee113eSDavid van Moolenbroek /* Parse an iaaddr {} structure. */
1902*83ee113eSDavid van Moolenbroek #ifdef DHCPv6
1903*83ee113eSDavid van Moolenbroek static struct dhc6_addr *
parse_client6_iaaddr_statement(struct parse * cfile)1904*83ee113eSDavid van Moolenbroek parse_client6_iaaddr_statement(struct parse *cfile)
1905*83ee113eSDavid van Moolenbroek {
1906*83ee113eSDavid van Moolenbroek struct option_cache *oc = NULL;
1907*83ee113eSDavid van Moolenbroek struct dhc6_addr *addr;
1908*83ee113eSDavid van Moolenbroek const char *val;
1909*83ee113eSDavid van Moolenbroek int token, no_semi;
1910*83ee113eSDavid van Moolenbroek
1911*83ee113eSDavid van Moolenbroek addr = dmalloc(sizeof(*addr), MDL);
1912*83ee113eSDavid van Moolenbroek if (addr == NULL) {
1913*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate IAADDR state.");
1914*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1915*83ee113eSDavid van Moolenbroek return NULL;
1916*83ee113eSDavid van Moolenbroek }
1917*83ee113eSDavid van Moolenbroek
1918*83ee113eSDavid van Moolenbroek /* Get IP address. */
1919*83ee113eSDavid van Moolenbroek if (!parse_ip6_addr(cfile, &addr->address)) {
1920*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1921*83ee113eSDavid van Moolenbroek dfree(addr, MDL);
1922*83ee113eSDavid van Moolenbroek return NULL;
1923*83ee113eSDavid van Moolenbroek }
1924*83ee113eSDavid van Moolenbroek
1925*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
1926*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
1927*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting open curly bracket.");
1928*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1929*83ee113eSDavid van Moolenbroek dfree(addr, MDL);
1930*83ee113eSDavid van Moolenbroek return NULL;
1931*83ee113eSDavid van Moolenbroek }
1932*83ee113eSDavid van Moolenbroek
1933*83ee113eSDavid van Moolenbroek option_state_allocate(&addr->options, MDL);
1934*83ee113eSDavid van Moolenbroek if (addr->options == NULL) {
1935*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate option state.");
1936*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1937*83ee113eSDavid van Moolenbroek dfree(addr, MDL);
1938*83ee113eSDavid van Moolenbroek return NULL;
1939*83ee113eSDavid van Moolenbroek }
1940*83ee113eSDavid van Moolenbroek
1941*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1942*83ee113eSDavid van Moolenbroek while (token != RBRACE) {
1943*83ee113eSDavid van Moolenbroek no_semi = 0;
1944*83ee113eSDavid van Moolenbroek
1945*83ee113eSDavid van Moolenbroek switch (token) {
1946*83ee113eSDavid van Moolenbroek case STARTS:
1947*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1948*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1949*83ee113eSDavid van Moolenbroek addr->starts = atoi(val);
1950*83ee113eSDavid van Moolenbroek } else {
1951*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1952*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1953*83ee113eSDavid van Moolenbroek no_semi = 1;
1954*83ee113eSDavid van Moolenbroek }
1955*83ee113eSDavid van Moolenbroek break;
1956*83ee113eSDavid van Moolenbroek
1957*83ee113eSDavid van Moolenbroek case PREFERRED_LIFE:
1958*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1959*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1960*83ee113eSDavid van Moolenbroek addr->preferred_life = atoi(val);
1961*83ee113eSDavid van Moolenbroek } else {
1962*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1963*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1964*83ee113eSDavid van Moolenbroek no_semi = 1;
1965*83ee113eSDavid van Moolenbroek }
1966*83ee113eSDavid van Moolenbroek break;
1967*83ee113eSDavid van Moolenbroek
1968*83ee113eSDavid van Moolenbroek case MAX_LIFE:
1969*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1970*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1971*83ee113eSDavid van Moolenbroek addr->max_life = atoi(val);
1972*83ee113eSDavid van Moolenbroek } else {
1973*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
1974*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1975*83ee113eSDavid van Moolenbroek no_semi = 1;
1976*83ee113eSDavid van Moolenbroek }
1977*83ee113eSDavid van Moolenbroek break;
1978*83ee113eSDavid van Moolenbroek
1979*83ee113eSDavid van Moolenbroek case OPTION:
1980*83ee113eSDavid van Moolenbroek if (parse_option_decl(&oc, cfile)) {
1981*83ee113eSDavid van Moolenbroek save_option(oc->option->universe,
1982*83ee113eSDavid van Moolenbroek addr->options, oc);
1983*83ee113eSDavid van Moolenbroek option_cache_dereference(&oc, MDL);
1984*83ee113eSDavid van Moolenbroek }
1985*83ee113eSDavid van Moolenbroek no_semi = 1;
1986*83ee113eSDavid van Moolenbroek break;
1987*83ee113eSDavid van Moolenbroek
1988*83ee113eSDavid van Moolenbroek default:
1989*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token.");
1990*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
1991*83ee113eSDavid van Moolenbroek no_semi = 1;
1992*83ee113eSDavid van Moolenbroek break;
1993*83ee113eSDavid van Moolenbroek }
1994*83ee113eSDavid van Moolenbroek
1995*83ee113eSDavid van Moolenbroek if (!no_semi)
1996*83ee113eSDavid van Moolenbroek parse_semi(cfile);
1997*83ee113eSDavid van Moolenbroek
1998*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1999*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
2000*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected end of file.");
2001*83ee113eSDavid van Moolenbroek break;
2002*83ee113eSDavid van Moolenbroek }
2003*83ee113eSDavid van Moolenbroek }
2004*83ee113eSDavid van Moolenbroek
2005*83ee113eSDavid van Moolenbroek return addr;
2006*83ee113eSDavid van Moolenbroek }
2007*83ee113eSDavid van Moolenbroek #endif /* DHCPv6 */
2008*83ee113eSDavid van Moolenbroek
2009*83ee113eSDavid van Moolenbroek /* Parse an iaprefix {} structure. */
2010*83ee113eSDavid van Moolenbroek #ifdef DHCPv6
2011*83ee113eSDavid van Moolenbroek static struct dhc6_addr *
parse_client6_iaprefix_statement(struct parse * cfile)2012*83ee113eSDavid van Moolenbroek parse_client6_iaprefix_statement(struct parse *cfile)
2013*83ee113eSDavid van Moolenbroek {
2014*83ee113eSDavid van Moolenbroek struct option_cache *oc = NULL;
2015*83ee113eSDavid van Moolenbroek struct dhc6_addr *pref;
2016*83ee113eSDavid van Moolenbroek const char *val;
2017*83ee113eSDavid van Moolenbroek int token, no_semi;
2018*83ee113eSDavid van Moolenbroek
2019*83ee113eSDavid van Moolenbroek pref = dmalloc(sizeof(*pref), MDL);
2020*83ee113eSDavid van Moolenbroek if (pref == NULL) {
2021*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate IAPREFIX state.");
2022*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2023*83ee113eSDavid van Moolenbroek return NULL;
2024*83ee113eSDavid van Moolenbroek }
2025*83ee113eSDavid van Moolenbroek
2026*83ee113eSDavid van Moolenbroek /* Get IP prefix. */
2027*83ee113eSDavid van Moolenbroek if (!parse_ip6_prefix(cfile, &pref->address, &pref->plen)) {
2028*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2029*83ee113eSDavid van Moolenbroek dfree(pref, MDL);
2030*83ee113eSDavid van Moolenbroek return NULL;
2031*83ee113eSDavid van Moolenbroek }
2032*83ee113eSDavid van Moolenbroek
2033*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
2034*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
2035*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting open curly bracket.");
2036*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2037*83ee113eSDavid van Moolenbroek dfree(pref, MDL);
2038*83ee113eSDavid van Moolenbroek return NULL;
2039*83ee113eSDavid van Moolenbroek }
2040*83ee113eSDavid van Moolenbroek
2041*83ee113eSDavid van Moolenbroek option_state_allocate(&pref->options, MDL);
2042*83ee113eSDavid van Moolenbroek if (pref->options == NULL) {
2043*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unable to allocate option state.");
2044*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2045*83ee113eSDavid van Moolenbroek dfree(pref, MDL);
2046*83ee113eSDavid van Moolenbroek return NULL;
2047*83ee113eSDavid van Moolenbroek }
2048*83ee113eSDavid van Moolenbroek
2049*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2050*83ee113eSDavid van Moolenbroek while (token != RBRACE) {
2051*83ee113eSDavid van Moolenbroek no_semi = 0;
2052*83ee113eSDavid van Moolenbroek
2053*83ee113eSDavid van Moolenbroek switch (token) {
2054*83ee113eSDavid van Moolenbroek case STARTS:
2055*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2056*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
2057*83ee113eSDavid van Moolenbroek pref->starts = atoi(val);
2058*83ee113eSDavid van Moolenbroek } else {
2059*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
2060*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2061*83ee113eSDavid van Moolenbroek no_semi = 1;
2062*83ee113eSDavid van Moolenbroek }
2063*83ee113eSDavid van Moolenbroek break;
2064*83ee113eSDavid van Moolenbroek
2065*83ee113eSDavid van Moolenbroek case PREFERRED_LIFE:
2066*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2067*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
2068*83ee113eSDavid van Moolenbroek pref->preferred_life = atoi(val);
2069*83ee113eSDavid van Moolenbroek } else {
2070*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
2071*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2072*83ee113eSDavid van Moolenbroek no_semi = 1;
2073*83ee113eSDavid van Moolenbroek }
2074*83ee113eSDavid van Moolenbroek break;
2075*83ee113eSDavid van Moolenbroek
2076*83ee113eSDavid van Moolenbroek case MAX_LIFE:
2077*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2078*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
2079*83ee113eSDavid van Moolenbroek pref->max_life = atoi(val);
2080*83ee113eSDavid van Moolenbroek } else {
2081*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a number.");
2082*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2083*83ee113eSDavid van Moolenbroek no_semi = 1;
2084*83ee113eSDavid van Moolenbroek }
2085*83ee113eSDavid van Moolenbroek break;
2086*83ee113eSDavid van Moolenbroek
2087*83ee113eSDavid van Moolenbroek case OPTION:
2088*83ee113eSDavid van Moolenbroek if (parse_option_decl(&oc, cfile)) {
2089*83ee113eSDavid van Moolenbroek save_option(oc->option->universe,
2090*83ee113eSDavid van Moolenbroek pref->options, oc);
2091*83ee113eSDavid van Moolenbroek option_cache_dereference(&oc, MDL);
2092*83ee113eSDavid van Moolenbroek }
2093*83ee113eSDavid van Moolenbroek no_semi = 1;
2094*83ee113eSDavid van Moolenbroek break;
2095*83ee113eSDavid van Moolenbroek
2096*83ee113eSDavid van Moolenbroek default:
2097*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token.");
2098*83ee113eSDavid van Moolenbroek skip_to_rbrace(cfile, 1);
2099*83ee113eSDavid van Moolenbroek no_semi = 1;
2100*83ee113eSDavid van Moolenbroek break;
2101*83ee113eSDavid van Moolenbroek }
2102*83ee113eSDavid van Moolenbroek
2103*83ee113eSDavid van Moolenbroek if (!no_semi)
2104*83ee113eSDavid van Moolenbroek parse_semi(cfile);
2105*83ee113eSDavid van Moolenbroek
2106*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2107*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
2108*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected end of file.");
2109*83ee113eSDavid van Moolenbroek break;
2110*83ee113eSDavid van Moolenbroek }
2111*83ee113eSDavid van Moolenbroek }
2112*83ee113eSDavid van Moolenbroek
2113*83ee113eSDavid van Moolenbroek return pref;
2114*83ee113eSDavid van Moolenbroek }
2115*83ee113eSDavid van Moolenbroek #endif /* DHCPv6 */
2116*83ee113eSDavid van Moolenbroek
parse_string_list(cfile,lp,multiple)2117*83ee113eSDavid van Moolenbroek void parse_string_list (cfile, lp, multiple)
2118*83ee113eSDavid van Moolenbroek struct parse *cfile;
2119*83ee113eSDavid van Moolenbroek struct string_list **lp;
2120*83ee113eSDavid van Moolenbroek int multiple;
2121*83ee113eSDavid van Moolenbroek {
2122*83ee113eSDavid van Moolenbroek int token;
2123*83ee113eSDavid van Moolenbroek const char *val;
2124*83ee113eSDavid van Moolenbroek struct string_list *cur, *tmp;
2125*83ee113eSDavid van Moolenbroek
2126*83ee113eSDavid van Moolenbroek /* Find the last medium in the media list. */
2127*83ee113eSDavid van Moolenbroek if (*lp) {
2128*83ee113eSDavid van Moolenbroek for (cur = *lp; cur -> next; cur = cur -> next)
2129*83ee113eSDavid van Moolenbroek ;
2130*83ee113eSDavid van Moolenbroek } else {
2131*83ee113eSDavid van Moolenbroek cur = (struct string_list *)0;
2132*83ee113eSDavid van Moolenbroek }
2133*83ee113eSDavid van Moolenbroek
2134*83ee113eSDavid van Moolenbroek do {
2135*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2136*83ee113eSDavid van Moolenbroek if (token != STRING) {
2137*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Expecting media options.");
2138*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2139*83ee113eSDavid van Moolenbroek return;
2140*83ee113eSDavid van Moolenbroek }
2141*83ee113eSDavid van Moolenbroek
2142*83ee113eSDavid van Moolenbroek tmp = ((struct string_list *)
2143*83ee113eSDavid van Moolenbroek dmalloc (strlen (val) + sizeof (struct string_list),
2144*83ee113eSDavid van Moolenbroek MDL));
2145*83ee113eSDavid van Moolenbroek if (!tmp)
2146*83ee113eSDavid van Moolenbroek log_fatal ("no memory for string list entry.");
2147*83ee113eSDavid van Moolenbroek
2148*83ee113eSDavid van Moolenbroek strcpy (tmp -> string, val);
2149*83ee113eSDavid van Moolenbroek tmp -> next = (struct string_list *)0;
2150*83ee113eSDavid van Moolenbroek
2151*83ee113eSDavid van Moolenbroek /* Store this medium at the end of the media list. */
2152*83ee113eSDavid van Moolenbroek if (cur)
2153*83ee113eSDavid van Moolenbroek cur -> next = tmp;
2154*83ee113eSDavid van Moolenbroek else
2155*83ee113eSDavid van Moolenbroek *lp = tmp;
2156*83ee113eSDavid van Moolenbroek cur = tmp;
2157*83ee113eSDavid van Moolenbroek
2158*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2159*83ee113eSDavid van Moolenbroek } while (multiple && token == COMMA);
2160*83ee113eSDavid van Moolenbroek
2161*83ee113eSDavid van Moolenbroek if (token != SEMI) {
2162*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting semicolon.");
2163*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2164*83ee113eSDavid van Moolenbroek }
2165*83ee113eSDavid van Moolenbroek }
2166*83ee113eSDavid van Moolenbroek
parse_reject_statement(cfile,config)2167*83ee113eSDavid van Moolenbroek void parse_reject_statement (cfile, config)
2168*83ee113eSDavid van Moolenbroek struct parse *cfile;
2169*83ee113eSDavid van Moolenbroek struct client_config *config;
2170*83ee113eSDavid van Moolenbroek {
2171*83ee113eSDavid van Moolenbroek int token;
2172*83ee113eSDavid van Moolenbroek const char *val;
2173*83ee113eSDavid van Moolenbroek struct iaddrmatch match;
2174*83ee113eSDavid van Moolenbroek struct iaddrmatchlist *list;
2175*83ee113eSDavid van Moolenbroek int i;
2176*83ee113eSDavid van Moolenbroek
2177*83ee113eSDavid van Moolenbroek do {
2178*83ee113eSDavid van Moolenbroek if (!parse_ip_addr_with_subnet (cfile, &match)) {
2179*83ee113eSDavid van Moolenbroek /* no warn: parser will have reported what's wrong */
2180*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2181*83ee113eSDavid van Moolenbroek return;
2182*83ee113eSDavid van Moolenbroek }
2183*83ee113eSDavid van Moolenbroek
2184*83ee113eSDavid van Moolenbroek /* check mask is not all zeros (because that would
2185*83ee113eSDavid van Moolenbroek * reject EVERY address). This check could be
2186*83ee113eSDavid van Moolenbroek * simplified if we assume that the mask *always*
2187*83ee113eSDavid van Moolenbroek * represents a prefix .. but perhaps it might be
2188*83ee113eSDavid van Moolenbroek * useful to have a mask which is not a proper prefix
2189*83ee113eSDavid van Moolenbroek * (perhaps for ipv6?). The following is almost as
2190*83ee113eSDavid van Moolenbroek * efficient as inspection of match.mask.iabuf[0] when
2191*83ee113eSDavid van Moolenbroek * it IS a true prefix, and is more general when it is
2192*83ee113eSDavid van Moolenbroek * not.
2193*83ee113eSDavid van Moolenbroek */
2194*83ee113eSDavid van Moolenbroek
2195*83ee113eSDavid van Moolenbroek for (i=0 ; i < match.mask.len ; i++) {
2196*83ee113eSDavid van Moolenbroek if (match.mask.iabuf[i]) {
2197*83ee113eSDavid van Moolenbroek break;
2198*83ee113eSDavid van Moolenbroek }
2199*83ee113eSDavid van Moolenbroek }
2200*83ee113eSDavid van Moolenbroek
2201*83ee113eSDavid van Moolenbroek if (i == match.mask.len) {
2202*83ee113eSDavid van Moolenbroek /* oops we found all zeros */
2203*83ee113eSDavid van Moolenbroek parse_warn(cfile, "zero-length prefix is not permitted "
2204*83ee113eSDavid van Moolenbroek "for reject statement");
2205*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2206*83ee113eSDavid van Moolenbroek return;
2207*83ee113eSDavid van Moolenbroek }
2208*83ee113eSDavid van Moolenbroek
2209*83ee113eSDavid van Moolenbroek list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
2210*83ee113eSDavid van Moolenbroek if (!list)
2211*83ee113eSDavid van Moolenbroek log_fatal ("no memory for reject list!");
2212*83ee113eSDavid van Moolenbroek
2213*83ee113eSDavid van Moolenbroek list->match = match;
2214*83ee113eSDavid van Moolenbroek list->next = config->reject_list;
2215*83ee113eSDavid van Moolenbroek config->reject_list = list;
2216*83ee113eSDavid van Moolenbroek
2217*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2218*83ee113eSDavid van Moolenbroek } while (token == COMMA);
2219*83ee113eSDavid van Moolenbroek
2220*83ee113eSDavid van Moolenbroek if (token != SEMI) {
2221*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting semicolon.");
2222*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2223*83ee113eSDavid van Moolenbroek }
2224*83ee113eSDavid van Moolenbroek }
2225*83ee113eSDavid van Moolenbroek
2226*83ee113eSDavid van Moolenbroek /* allow-deny-keyword :== BOOTP
2227*83ee113eSDavid van Moolenbroek | BOOTING
2228*83ee113eSDavid van Moolenbroek | DYNAMIC_BOOTP
2229*83ee113eSDavid van Moolenbroek | UNKNOWN_CLIENTS */
2230*83ee113eSDavid van Moolenbroek
parse_allow_deny(oc,cfile,flag)2231*83ee113eSDavid van Moolenbroek int parse_allow_deny (oc, cfile, flag)
2232*83ee113eSDavid van Moolenbroek struct option_cache **oc;
2233*83ee113eSDavid van Moolenbroek struct parse *cfile;
2234*83ee113eSDavid van Moolenbroek int flag;
2235*83ee113eSDavid van Moolenbroek {
2236*83ee113eSDavid van Moolenbroek parse_warn (cfile, "allow/deny/ignore not permitted here.");
2237*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2238*83ee113eSDavid van Moolenbroek return 0;
2239*83ee113eSDavid van Moolenbroek }
2240