1*83ee113eSDavid van Moolenbroek /* $NetBSD: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $ */
2*83ee113eSDavid van Moolenbroek /* parse.c
3*83ee113eSDavid van Moolenbroek
4*83ee113eSDavid van Moolenbroek Common parser code for dhcpd and dhclient. */
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) 1995-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: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $");
32*83ee113eSDavid van Moolenbroek
33*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
34*83ee113eSDavid van Moolenbroek #include <syslog.h>
35*83ee113eSDavid van Moolenbroek
36*83ee113eSDavid van Moolenbroek /* Enumerations can be specified in option formats, and are used for
37*83ee113eSDavid van Moolenbroek parsing, so we define the routines that manage them here. */
38*83ee113eSDavid van Moolenbroek
39*83ee113eSDavid van Moolenbroek struct enumeration *enumerations;
40*83ee113eSDavid van Moolenbroek
add_enumeration(struct enumeration * enumeration)41*83ee113eSDavid van Moolenbroek void add_enumeration (struct enumeration *enumeration)
42*83ee113eSDavid van Moolenbroek {
43*83ee113eSDavid van Moolenbroek enumeration -> next = enumerations;
44*83ee113eSDavid van Moolenbroek enumerations = enumeration;
45*83ee113eSDavid van Moolenbroek }
46*83ee113eSDavid van Moolenbroek
find_enumeration(const char * name,int length)47*83ee113eSDavid van Moolenbroek struct enumeration *find_enumeration (const char *name, int length)
48*83ee113eSDavid van Moolenbroek {
49*83ee113eSDavid van Moolenbroek struct enumeration *e;
50*83ee113eSDavid van Moolenbroek
51*83ee113eSDavid van Moolenbroek for (e = enumerations; e; e = e -> next)
52*83ee113eSDavid van Moolenbroek if (strlen (e -> name) == length &&
53*83ee113eSDavid van Moolenbroek !memcmp (e -> name, name, (unsigned)length))
54*83ee113eSDavid van Moolenbroek return e;
55*83ee113eSDavid van Moolenbroek return (struct enumeration *)0;
56*83ee113eSDavid van Moolenbroek }
57*83ee113eSDavid van Moolenbroek
find_enumeration_value(const char * name,int length,unsigned * widthp,const char * value)58*83ee113eSDavid van Moolenbroek struct enumeration_value *find_enumeration_value (const char *name,
59*83ee113eSDavid van Moolenbroek int length,
60*83ee113eSDavid van Moolenbroek unsigned *widthp,
61*83ee113eSDavid van Moolenbroek const char *value)
62*83ee113eSDavid van Moolenbroek {
63*83ee113eSDavid van Moolenbroek struct enumeration *e;
64*83ee113eSDavid van Moolenbroek int i;
65*83ee113eSDavid van Moolenbroek
66*83ee113eSDavid van Moolenbroek e = find_enumeration (name, length);
67*83ee113eSDavid van Moolenbroek if (e) {
68*83ee113eSDavid van Moolenbroek if (widthp != NULL)
69*83ee113eSDavid van Moolenbroek *widthp = e->width;
70*83ee113eSDavid van Moolenbroek for (i = 0; e -> values [i].name; i++) {
71*83ee113eSDavid van Moolenbroek if (!strcmp (value, e -> values [i].name))
72*83ee113eSDavid van Moolenbroek return &e -> values [i];
73*83ee113eSDavid van Moolenbroek }
74*83ee113eSDavid van Moolenbroek }
75*83ee113eSDavid van Moolenbroek return (struct enumeration_value *)0;
76*83ee113eSDavid van Moolenbroek }
77*83ee113eSDavid van Moolenbroek
78*83ee113eSDavid van Moolenbroek /* Skip to the semicolon ending the current statement. If we encounter
79*83ee113eSDavid van Moolenbroek braces, the matching closing brace terminates the statement. If we
80*83ee113eSDavid van Moolenbroek encounter a right brace but haven't encountered a left brace, return
81*83ee113eSDavid van Moolenbroek leaving the brace in the token buffer for the caller. If we see a
82*83ee113eSDavid van Moolenbroek semicolon and haven't seen a left brace, return. This lets us skip
83*83ee113eSDavid van Moolenbroek over:
84*83ee113eSDavid van Moolenbroek
85*83ee113eSDavid van Moolenbroek statement;
86*83ee113eSDavid van Moolenbroek statement foo bar { }
87*83ee113eSDavid van Moolenbroek statement foo bar { statement { } }
88*83ee113eSDavid van Moolenbroek statement}
89*83ee113eSDavid van Moolenbroek
90*83ee113eSDavid van Moolenbroek ...et cetera. */
91*83ee113eSDavid van Moolenbroek
skip_to_semi(cfile)92*83ee113eSDavid van Moolenbroek void skip_to_semi (cfile)
93*83ee113eSDavid van Moolenbroek struct parse *cfile;
94*83ee113eSDavid van Moolenbroek {
95*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 0);
96*83ee113eSDavid van Moolenbroek }
97*83ee113eSDavid van Moolenbroek
skip_to_rbrace(cfile,brace_count)98*83ee113eSDavid van Moolenbroek void skip_to_rbrace (cfile, brace_count)
99*83ee113eSDavid van Moolenbroek struct parse *cfile;
100*83ee113eSDavid van Moolenbroek int brace_count;
101*83ee113eSDavid van Moolenbroek {
102*83ee113eSDavid van Moolenbroek enum dhcp_token token;
103*83ee113eSDavid van Moolenbroek const char *val;
104*83ee113eSDavid van Moolenbroek
105*83ee113eSDavid van Moolenbroek #if defined (DEBUG_TOKEN)
106*83ee113eSDavid van Moolenbroek log_error ("skip_to_rbrace: %d\n", brace_count);
107*83ee113eSDavid van Moolenbroek #endif
108*83ee113eSDavid van Moolenbroek do {
109*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
110*83ee113eSDavid van Moolenbroek if (token == RBRACE) {
111*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
112*83ee113eSDavid van Moolenbroek if (brace_count) {
113*83ee113eSDavid van Moolenbroek if (!--brace_count)
114*83ee113eSDavid van Moolenbroek return;
115*83ee113eSDavid van Moolenbroek } else
116*83ee113eSDavid van Moolenbroek return;
117*83ee113eSDavid van Moolenbroek } else if (token == LBRACE) {
118*83ee113eSDavid van Moolenbroek brace_count++;
119*83ee113eSDavid van Moolenbroek } else if (token == SEMI && !brace_count) {
120*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
121*83ee113eSDavid van Moolenbroek return;
122*83ee113eSDavid van Moolenbroek } else if (token == EOL) {
123*83ee113eSDavid van Moolenbroek /* EOL only happens when parsing /etc/resolv.conf,
124*83ee113eSDavid van Moolenbroek and we treat it like a semicolon because the
125*83ee113eSDavid van Moolenbroek resolv.conf file is line-oriented. */
126*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
127*83ee113eSDavid van Moolenbroek return;
128*83ee113eSDavid van Moolenbroek }
129*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
130*83ee113eSDavid van Moolenbroek } while (token != END_OF_FILE);
131*83ee113eSDavid van Moolenbroek }
132*83ee113eSDavid van Moolenbroek
parse_semi(cfile)133*83ee113eSDavid van Moolenbroek int parse_semi (cfile)
134*83ee113eSDavid van Moolenbroek struct parse *cfile;
135*83ee113eSDavid van Moolenbroek {
136*83ee113eSDavid van Moolenbroek enum dhcp_token token;
137*83ee113eSDavid van Moolenbroek const char *val;
138*83ee113eSDavid van Moolenbroek
139*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
140*83ee113eSDavid van Moolenbroek if (token != SEMI) {
141*83ee113eSDavid van Moolenbroek parse_warn (cfile, "semicolon expected.");
142*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
143*83ee113eSDavid van Moolenbroek return 0;
144*83ee113eSDavid van Moolenbroek }
145*83ee113eSDavid van Moolenbroek return 1;
146*83ee113eSDavid van Moolenbroek }
147*83ee113eSDavid van Moolenbroek
148*83ee113eSDavid van Moolenbroek /* string-parameter :== STRING SEMI */
149*83ee113eSDavid van Moolenbroek
parse_string(cfile,sptr,lptr)150*83ee113eSDavid van Moolenbroek int parse_string (cfile, sptr, lptr)
151*83ee113eSDavid van Moolenbroek struct parse *cfile;
152*83ee113eSDavid van Moolenbroek char **sptr;
153*83ee113eSDavid van Moolenbroek unsigned *lptr;
154*83ee113eSDavid van Moolenbroek {
155*83ee113eSDavid van Moolenbroek const char *val;
156*83ee113eSDavid van Moolenbroek enum dhcp_token token;
157*83ee113eSDavid van Moolenbroek char *s;
158*83ee113eSDavid van Moolenbroek unsigned len;
159*83ee113eSDavid van Moolenbroek
160*83ee113eSDavid van Moolenbroek token = next_token (&val, &len, cfile);
161*83ee113eSDavid van Moolenbroek if (token != STRING) {
162*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting a string");
163*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
164*83ee113eSDavid van Moolenbroek return 0;
165*83ee113eSDavid van Moolenbroek }
166*83ee113eSDavid van Moolenbroek s = (char *)dmalloc (len + 1, MDL);
167*83ee113eSDavid van Moolenbroek if (!s)
168*83ee113eSDavid van Moolenbroek log_fatal ("no memory for string %s.", val);
169*83ee113eSDavid van Moolenbroek memcpy (s, val, len + 1);
170*83ee113eSDavid van Moolenbroek
171*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
172*83ee113eSDavid van Moolenbroek dfree (s, MDL);
173*83ee113eSDavid van Moolenbroek return 0;
174*83ee113eSDavid van Moolenbroek }
175*83ee113eSDavid van Moolenbroek if (sptr)
176*83ee113eSDavid van Moolenbroek *sptr = s;
177*83ee113eSDavid van Moolenbroek else
178*83ee113eSDavid van Moolenbroek dfree (s, MDL);
179*83ee113eSDavid van Moolenbroek if (lptr)
180*83ee113eSDavid van Moolenbroek *lptr = len;
181*83ee113eSDavid van Moolenbroek return 1;
182*83ee113eSDavid van Moolenbroek }
183*83ee113eSDavid van Moolenbroek
184*83ee113eSDavid van Moolenbroek /*
185*83ee113eSDavid van Moolenbroek * hostname :== IDENTIFIER
186*83ee113eSDavid van Moolenbroek * | IDENTIFIER DOT
187*83ee113eSDavid van Moolenbroek * | hostname DOT IDENTIFIER
188*83ee113eSDavid van Moolenbroek */
189*83ee113eSDavid van Moolenbroek
parse_host_name(cfile)190*83ee113eSDavid van Moolenbroek char *parse_host_name (cfile)
191*83ee113eSDavid van Moolenbroek struct parse *cfile;
192*83ee113eSDavid van Moolenbroek {
193*83ee113eSDavid van Moolenbroek const char *val;
194*83ee113eSDavid van Moolenbroek enum dhcp_token token;
195*83ee113eSDavid van Moolenbroek unsigned len = 0;
196*83ee113eSDavid van Moolenbroek char *s;
197*83ee113eSDavid van Moolenbroek char *t;
198*83ee113eSDavid van Moolenbroek pair c = (pair)0;
199*83ee113eSDavid van Moolenbroek int ltid = 0;
200*83ee113eSDavid van Moolenbroek
201*83ee113eSDavid van Moolenbroek /* Read a dotted hostname... */
202*83ee113eSDavid van Moolenbroek do {
203*83ee113eSDavid van Moolenbroek /* Read a token, which should be an identifier. */
204*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
205*83ee113eSDavid van Moolenbroek if (!is_identifier (token) && token != NUMBER)
206*83ee113eSDavid van Moolenbroek break;
207*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
208*83ee113eSDavid van Moolenbroek
209*83ee113eSDavid van Moolenbroek /* Store this identifier... */
210*83ee113eSDavid van Moolenbroek if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
211*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate temp space for hostname.");
212*83ee113eSDavid van Moolenbroek strcpy (s, val);
213*83ee113eSDavid van Moolenbroek c = cons ((caddr_t)s, c);
214*83ee113eSDavid van Moolenbroek len += strlen (s) + 1;
215*83ee113eSDavid van Moolenbroek /* Look for a dot; if it's there, keep going, otherwise
216*83ee113eSDavid van Moolenbroek we're done. */
217*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
218*83ee113eSDavid van Moolenbroek if (token == DOT) {
219*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
220*83ee113eSDavid van Moolenbroek ltid = 1;
221*83ee113eSDavid van Moolenbroek } else
222*83ee113eSDavid van Moolenbroek ltid = 0;
223*83ee113eSDavid van Moolenbroek } while (token == DOT);
224*83ee113eSDavid van Moolenbroek
225*83ee113eSDavid van Moolenbroek /* Should be at least one token. */
226*83ee113eSDavid van Moolenbroek if (!len)
227*83ee113eSDavid van Moolenbroek return (char *)0;
228*83ee113eSDavid van Moolenbroek
229*83ee113eSDavid van Moolenbroek /* Assemble the hostname together into a string. */
230*83ee113eSDavid van Moolenbroek if (!(s = (char *)dmalloc (len + ltid, MDL)))
231*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate space for hostname.");
232*83ee113eSDavid van Moolenbroek t = s + len + ltid;
233*83ee113eSDavid van Moolenbroek *--t = 0;
234*83ee113eSDavid van Moolenbroek if (ltid)
235*83ee113eSDavid van Moolenbroek *--t = '.';
236*83ee113eSDavid van Moolenbroek while (c) {
237*83ee113eSDavid van Moolenbroek pair cdr = c -> cdr;
238*83ee113eSDavid van Moolenbroek unsigned l = strlen ((char *)(c -> car));
239*83ee113eSDavid van Moolenbroek t -= l;
240*83ee113eSDavid van Moolenbroek memcpy (t, (char *)(c -> car), l);
241*83ee113eSDavid van Moolenbroek /* Free up temp space. */
242*83ee113eSDavid van Moolenbroek dfree (c -> car, MDL);
243*83ee113eSDavid van Moolenbroek dfree (c, MDL);
244*83ee113eSDavid van Moolenbroek c = cdr;
245*83ee113eSDavid van Moolenbroek if (t != s)
246*83ee113eSDavid van Moolenbroek *--t = '.';
247*83ee113eSDavid van Moolenbroek }
248*83ee113eSDavid van Moolenbroek return s;
249*83ee113eSDavid van Moolenbroek }
250*83ee113eSDavid van Moolenbroek
251*83ee113eSDavid van Moolenbroek /* ip-addr-or-hostname :== ip-address | hostname
252*83ee113eSDavid van Moolenbroek ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
253*83ee113eSDavid van Moolenbroek
254*83ee113eSDavid van Moolenbroek Parse an ip address or a hostname. If uniform is zero, put in
255*83ee113eSDavid van Moolenbroek an expr_substring node to limit hostnames that evaluate to more
256*83ee113eSDavid van Moolenbroek than one IP address.
257*83ee113eSDavid van Moolenbroek
258*83ee113eSDavid van Moolenbroek Note that RFC1123 permits hostnames to consist of all digits,
259*83ee113eSDavid van Moolenbroek making it difficult to quickly disambiguate them from ip addresses.
260*83ee113eSDavid van Moolenbroek */
261*83ee113eSDavid van Moolenbroek
parse_ip_addr_or_hostname(expr,cfile,uniform)262*83ee113eSDavid van Moolenbroek int parse_ip_addr_or_hostname (expr, cfile, uniform)
263*83ee113eSDavid van Moolenbroek struct expression **expr;
264*83ee113eSDavid van Moolenbroek struct parse *cfile;
265*83ee113eSDavid van Moolenbroek int uniform;
266*83ee113eSDavid van Moolenbroek {
267*83ee113eSDavid van Moolenbroek const char *val;
268*83ee113eSDavid van Moolenbroek enum dhcp_token token;
269*83ee113eSDavid van Moolenbroek unsigned char addr [4];
270*83ee113eSDavid van Moolenbroek unsigned len = sizeof addr;
271*83ee113eSDavid van Moolenbroek char *name;
272*83ee113eSDavid van Moolenbroek struct expression *x = (struct expression *)0;
273*83ee113eSDavid van Moolenbroek int ipaddr = 0;
274*83ee113eSDavid van Moolenbroek
275*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
276*83ee113eSDavid van Moolenbroek
277*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
278*83ee113eSDavid van Moolenbroek /*
279*83ee113eSDavid van Moolenbroek * a hostname may be numeric, but domain names must
280*83ee113eSDavid van Moolenbroek * start with a letter, so we can disambiguate by
281*83ee113eSDavid van Moolenbroek * looking ahead a few tokens. we save the parse
282*83ee113eSDavid van Moolenbroek * context first, and restore it after we know what
283*83ee113eSDavid van Moolenbroek * we're dealing with.
284*83ee113eSDavid van Moolenbroek */
285*83ee113eSDavid van Moolenbroek save_parse_state(cfile);
286*83ee113eSDavid van Moolenbroek skip_token(NULL, NULL, cfile);
287*83ee113eSDavid van Moolenbroek if (next_token(NULL, NULL, cfile) == DOT &&
288*83ee113eSDavid van Moolenbroek next_token(NULL, NULL, cfile) == NUMBER)
289*83ee113eSDavid van Moolenbroek ipaddr = 1;
290*83ee113eSDavid van Moolenbroek restore_parse_state(cfile);
291*83ee113eSDavid van Moolenbroek
292*83ee113eSDavid van Moolenbroek if (ipaddr &&
293*83ee113eSDavid van Moolenbroek parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
294*83ee113eSDavid van Moolenbroek return make_const_data (expr, addr, len, 0, 1, MDL);
295*83ee113eSDavid van Moolenbroek
296*83ee113eSDavid van Moolenbroek }
297*83ee113eSDavid van Moolenbroek
298*83ee113eSDavid van Moolenbroek if (is_identifier (token) || token == NUMBER) {
299*83ee113eSDavid van Moolenbroek name = parse_host_name (cfile);
300*83ee113eSDavid van Moolenbroek if (!name)
301*83ee113eSDavid van Moolenbroek return 0;
302*83ee113eSDavid van Moolenbroek if (!make_host_lookup (expr, name)) {
303*83ee113eSDavid van Moolenbroek dfree(name, MDL);
304*83ee113eSDavid van Moolenbroek return 0;
305*83ee113eSDavid van Moolenbroek }
306*83ee113eSDavid van Moolenbroek dfree(name, MDL);
307*83ee113eSDavid van Moolenbroek if (!uniform) {
308*83ee113eSDavid van Moolenbroek if (!make_limit (&x, *expr, 4))
309*83ee113eSDavid van Moolenbroek return 0;
310*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
311*83ee113eSDavid van Moolenbroek *expr = x;
312*83ee113eSDavid van Moolenbroek }
313*83ee113eSDavid van Moolenbroek } else {
314*83ee113eSDavid van Moolenbroek if (token != RBRACE && token != LBRACE)
315*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
316*83ee113eSDavid van Moolenbroek parse_warn (cfile, "%s (%d): expecting IP address or hostname",
317*83ee113eSDavid van Moolenbroek val, token);
318*83ee113eSDavid van Moolenbroek if (token != SEMI)
319*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
320*83ee113eSDavid van Moolenbroek return 0;
321*83ee113eSDavid van Moolenbroek }
322*83ee113eSDavid van Moolenbroek
323*83ee113eSDavid van Moolenbroek return 1;
324*83ee113eSDavid van Moolenbroek }
325*83ee113eSDavid van Moolenbroek
326*83ee113eSDavid van Moolenbroek /*
327*83ee113eSDavid van Moolenbroek * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
328*83ee113eSDavid van Moolenbroek */
329*83ee113eSDavid van Moolenbroek
parse_ip_addr(cfile,addr)330*83ee113eSDavid van Moolenbroek int parse_ip_addr (cfile, addr)
331*83ee113eSDavid van Moolenbroek struct parse *cfile;
332*83ee113eSDavid van Moolenbroek struct iaddr *addr;
333*83ee113eSDavid van Moolenbroek {
334*83ee113eSDavid van Moolenbroek addr -> len = 4;
335*83ee113eSDavid van Moolenbroek if (parse_numeric_aggregate (cfile, addr -> iabuf,
336*83ee113eSDavid van Moolenbroek &addr -> len, DOT, 10, 8))
337*83ee113eSDavid van Moolenbroek return 1;
338*83ee113eSDavid van Moolenbroek return 0;
339*83ee113eSDavid van Moolenbroek }
340*83ee113eSDavid van Moolenbroek
341*83ee113eSDavid van Moolenbroek /*
342*83ee113eSDavid van Moolenbroek * Return true if every character in the string is hexadecimal.
343*83ee113eSDavid van Moolenbroek */
344*83ee113eSDavid van Moolenbroek static int
is_hex_string(const char * s)345*83ee113eSDavid van Moolenbroek is_hex_string(const char *s) {
346*83ee113eSDavid van Moolenbroek while (*s != '\0') {
347*83ee113eSDavid van Moolenbroek if (!isxdigit((int)*s)) {
348*83ee113eSDavid van Moolenbroek return 0;
349*83ee113eSDavid van Moolenbroek }
350*83ee113eSDavid van Moolenbroek s++;
351*83ee113eSDavid van Moolenbroek }
352*83ee113eSDavid van Moolenbroek return 1;
353*83ee113eSDavid van Moolenbroek }
354*83ee113eSDavid van Moolenbroek
355*83ee113eSDavid van Moolenbroek /*
356*83ee113eSDavid van Moolenbroek * ip-address6 :== (complicated set of rules)
357*83ee113eSDavid van Moolenbroek *
358*83ee113eSDavid van Moolenbroek * See section 2.2 of RFC 1884 for details.
359*83ee113eSDavid van Moolenbroek *
360*83ee113eSDavid van Moolenbroek * We are lazy for this. We pull numbers, names, colons, and dots
361*83ee113eSDavid van Moolenbroek * together and then throw the resulting string at the inet_pton()
362*83ee113eSDavid van Moolenbroek * function.
363*83ee113eSDavid van Moolenbroek */
364*83ee113eSDavid van Moolenbroek
365*83ee113eSDavid van Moolenbroek int
parse_ip6_addr(struct parse * cfile,struct iaddr * addr)366*83ee113eSDavid van Moolenbroek parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
367*83ee113eSDavid van Moolenbroek enum dhcp_token token;
368*83ee113eSDavid van Moolenbroek const char *val;
369*83ee113eSDavid van Moolenbroek int val_len;
370*83ee113eSDavid van Moolenbroek
371*83ee113eSDavid van Moolenbroek char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
372*83ee113eSDavid van Moolenbroek int v6_len;
373*83ee113eSDavid van Moolenbroek
374*83ee113eSDavid van Moolenbroek /*
375*83ee113eSDavid van Moolenbroek * First token is non-raw. This way we eat any whitespace before
376*83ee113eSDavid van Moolenbroek * our IPv6 address begins, like one would expect.
377*83ee113eSDavid van Moolenbroek */
378*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
379*83ee113eSDavid van Moolenbroek
380*83ee113eSDavid van Moolenbroek /*
381*83ee113eSDavid van Moolenbroek * Gather symbols.
382*83ee113eSDavid van Moolenbroek */
383*83ee113eSDavid van Moolenbroek v6_len = 0;
384*83ee113eSDavid van Moolenbroek for (;;) {
385*83ee113eSDavid van Moolenbroek if ((((token == NAME) || (token == NUMBER_OR_NAME)) &&
386*83ee113eSDavid van Moolenbroek is_hex_string(val)) ||
387*83ee113eSDavid van Moolenbroek (token == NUMBER) ||
388*83ee113eSDavid van Moolenbroek (token == DOT) ||
389*83ee113eSDavid van Moolenbroek (token == COLON)) {
390*83ee113eSDavid van Moolenbroek
391*83ee113eSDavid van Moolenbroek next_raw_token(&val, NULL, cfile);
392*83ee113eSDavid van Moolenbroek val_len = strlen(val);
393*83ee113eSDavid van Moolenbroek if ((v6_len + val_len) >= sizeof(v6)) {
394*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Invalid IPv6 address.");
395*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
396*83ee113eSDavid van Moolenbroek return 0;
397*83ee113eSDavid van Moolenbroek }
398*83ee113eSDavid van Moolenbroek memcpy(v6+v6_len, val, val_len);
399*83ee113eSDavid van Moolenbroek v6_len += val_len;
400*83ee113eSDavid van Moolenbroek
401*83ee113eSDavid van Moolenbroek } else {
402*83ee113eSDavid van Moolenbroek break;
403*83ee113eSDavid van Moolenbroek }
404*83ee113eSDavid van Moolenbroek token = peek_raw_token(&val, NULL, cfile);
405*83ee113eSDavid van Moolenbroek }
406*83ee113eSDavid van Moolenbroek v6[v6_len] = '\0';
407*83ee113eSDavid van Moolenbroek
408*83ee113eSDavid van Moolenbroek /*
409*83ee113eSDavid van Moolenbroek * Use inet_pton() for actual work.
410*83ee113eSDavid van Moolenbroek */
411*83ee113eSDavid van Moolenbroek if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
412*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Invalid IPv6 address.");
413*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
414*83ee113eSDavid van Moolenbroek return 0;
415*83ee113eSDavid van Moolenbroek }
416*83ee113eSDavid van Moolenbroek addr->len = 16;
417*83ee113eSDavid van Moolenbroek return 1;
418*83ee113eSDavid van Moolenbroek }
419*83ee113eSDavid van Moolenbroek
420*83ee113eSDavid van Moolenbroek /*
421*83ee113eSDavid van Moolenbroek * Same as parse_ip6_addr() above, but returns the value in the
422*83ee113eSDavid van Moolenbroek * expression rather than in an address structure.
423*83ee113eSDavid van Moolenbroek */
424*83ee113eSDavid van Moolenbroek int
parse_ip6_addr_expr(struct expression ** expr,struct parse * cfile)425*83ee113eSDavid van Moolenbroek parse_ip6_addr_expr(struct expression **expr,
426*83ee113eSDavid van Moolenbroek struct parse *cfile) {
427*83ee113eSDavid van Moolenbroek struct iaddr addr;
428*83ee113eSDavid van Moolenbroek
429*83ee113eSDavid van Moolenbroek if (!parse_ip6_addr(cfile, &addr)) {
430*83ee113eSDavid van Moolenbroek return 0;
431*83ee113eSDavid van Moolenbroek }
432*83ee113eSDavid van Moolenbroek return make_const_data(expr, addr.iabuf, addr.len, 0, 1, MDL);
433*83ee113eSDavid van Moolenbroek }
434*83ee113eSDavid van Moolenbroek
435*83ee113eSDavid van Moolenbroek /*
436*83ee113eSDavid van Moolenbroek * ip6-prefix :== ip6-address "/" NUMBER
437*83ee113eSDavid van Moolenbroek */
438*83ee113eSDavid van Moolenbroek int
parse_ip6_prefix(struct parse * cfile,struct iaddr * addr,u_int8_t * plen)439*83ee113eSDavid van Moolenbroek parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen) {
440*83ee113eSDavid van Moolenbroek enum dhcp_token token;
441*83ee113eSDavid van Moolenbroek const char *val;
442*83ee113eSDavid van Moolenbroek int n;
443*83ee113eSDavid van Moolenbroek
444*83ee113eSDavid van Moolenbroek if (!parse_ip6_addr(cfile, addr)) {
445*83ee113eSDavid van Moolenbroek return 0;
446*83ee113eSDavid van Moolenbroek }
447*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
448*83ee113eSDavid van Moolenbroek if (token != SLASH) {
449*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Slash expected.");
450*83ee113eSDavid van Moolenbroek if (token != SEMI)
451*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
452*83ee113eSDavid van Moolenbroek return 0;
453*83ee113eSDavid van Moolenbroek }
454*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
455*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
456*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Number expected.");
457*83ee113eSDavid van Moolenbroek if (token != SEMI)
458*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
459*83ee113eSDavid van Moolenbroek return 0;
460*83ee113eSDavid van Moolenbroek }
461*83ee113eSDavid van Moolenbroek n = atoi(val);
462*83ee113eSDavid van Moolenbroek if ((n < 0) || (n > 128)) {
463*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Invalid IPv6 prefix length.");
464*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
465*83ee113eSDavid van Moolenbroek return 0;
466*83ee113eSDavid van Moolenbroek }
467*83ee113eSDavid van Moolenbroek if (!is_cidr_mask_valid(addr, n)) {
468*83ee113eSDavid van Moolenbroek parse_warn(cfile, "network mask too short.");
469*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
470*83ee113eSDavid van Moolenbroek return 0;
471*83ee113eSDavid van Moolenbroek }
472*83ee113eSDavid van Moolenbroek *plen = n;
473*83ee113eSDavid van Moolenbroek return 1;
474*83ee113eSDavid van Moolenbroek }
475*83ee113eSDavid van Moolenbroek
476*83ee113eSDavid van Moolenbroek /*
477*83ee113eSDavid van Moolenbroek * ip-address-with-subnet :== ip-address |
478*83ee113eSDavid van Moolenbroek * ip-address "/" NUMBER
479*83ee113eSDavid van Moolenbroek */
480*83ee113eSDavid van Moolenbroek
481*83ee113eSDavid van Moolenbroek int
parse_ip_addr_with_subnet(cfile,match)482*83ee113eSDavid van Moolenbroek parse_ip_addr_with_subnet(cfile, match)
483*83ee113eSDavid van Moolenbroek struct parse *cfile;
484*83ee113eSDavid van Moolenbroek struct iaddrmatch *match;
485*83ee113eSDavid van Moolenbroek {
486*83ee113eSDavid van Moolenbroek const char *val, *orig;
487*83ee113eSDavid van Moolenbroek enum dhcp_token token;
488*83ee113eSDavid van Moolenbroek int prefixlen;
489*83ee113eSDavid van Moolenbroek int fflen;
490*83ee113eSDavid van Moolenbroek unsigned char newval, warnmask=0;
491*83ee113eSDavid van Moolenbroek
492*83ee113eSDavid van Moolenbroek if (parse_ip_addr(cfile, &match->addr)) {
493*83ee113eSDavid van Moolenbroek /* default to host mask */
494*83ee113eSDavid van Moolenbroek prefixlen = match->addr.len * 8;
495*83ee113eSDavid van Moolenbroek
496*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
497*83ee113eSDavid van Moolenbroek
498*83ee113eSDavid van Moolenbroek if (token == SLASH) {
499*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
500*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
501*83ee113eSDavid van Moolenbroek
502*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
503*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Invalid CIDR prefix length:"
504*83ee113eSDavid van Moolenbroek " expecting a number.");
505*83ee113eSDavid van Moolenbroek return 0;
506*83ee113eSDavid van Moolenbroek }
507*83ee113eSDavid van Moolenbroek
508*83ee113eSDavid van Moolenbroek prefixlen = atoi(val);
509*83ee113eSDavid van Moolenbroek
510*83ee113eSDavid van Moolenbroek if (prefixlen < 0 ||
511*83ee113eSDavid van Moolenbroek prefixlen > (match->addr.len * 8)) {
512*83ee113eSDavid van Moolenbroek parse_warn(cfile, "subnet prefix is out of "
513*83ee113eSDavid van Moolenbroek "range [0..%d].",
514*83ee113eSDavid van Moolenbroek match->addr.len * 8);
515*83ee113eSDavid van Moolenbroek return 0;
516*83ee113eSDavid van Moolenbroek }
517*83ee113eSDavid van Moolenbroek }
518*83ee113eSDavid van Moolenbroek
519*83ee113eSDavid van Moolenbroek /* construct a suitable mask field */
520*83ee113eSDavid van Moolenbroek
521*83ee113eSDavid van Moolenbroek /* copy length */
522*83ee113eSDavid van Moolenbroek match->mask.len = match->addr.len;
523*83ee113eSDavid van Moolenbroek
524*83ee113eSDavid van Moolenbroek /* count of 0xff bytes in mask */
525*83ee113eSDavid van Moolenbroek fflen = prefixlen / 8;
526*83ee113eSDavid van Moolenbroek
527*83ee113eSDavid van Moolenbroek /* set leading mask */
528*83ee113eSDavid van Moolenbroek memset(match->mask.iabuf, 0xff, fflen);
529*83ee113eSDavid van Moolenbroek
530*83ee113eSDavid van Moolenbroek /* set zeroes */
531*83ee113eSDavid van Moolenbroek if (fflen < match->mask.len) {
532*83ee113eSDavid van Moolenbroek match->mask.iabuf[fflen] =
533*83ee113eSDavid van Moolenbroek "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen % 8];
534*83ee113eSDavid van Moolenbroek
535*83ee113eSDavid van Moolenbroek memset(match->mask.iabuf+fflen+1, 0x00,
536*83ee113eSDavid van Moolenbroek match->mask.len - fflen - 1);
537*83ee113eSDavid van Moolenbroek
538*83ee113eSDavid van Moolenbroek /* AND-out insignificant bits from supplied netmask. */
539*83ee113eSDavid van Moolenbroek orig = piaddr(match->addr);
540*83ee113eSDavid van Moolenbroek do {
541*83ee113eSDavid van Moolenbroek newval = match->addr.iabuf[fflen] &
542*83ee113eSDavid van Moolenbroek match->mask.iabuf[fflen];
543*83ee113eSDavid van Moolenbroek
544*83ee113eSDavid van Moolenbroek if (newval != match->addr.iabuf[fflen]) {
545*83ee113eSDavid van Moolenbroek warnmask = 1;
546*83ee113eSDavid van Moolenbroek match->addr.iabuf[fflen] = newval;
547*83ee113eSDavid van Moolenbroek }
548*83ee113eSDavid van Moolenbroek } while (++fflen < match->mask.len);
549*83ee113eSDavid van Moolenbroek
550*83ee113eSDavid van Moolenbroek if (warnmask) {
551*83ee113eSDavid van Moolenbroek log_error("Warning: Extraneous bits removed "
552*83ee113eSDavid van Moolenbroek "in address component of %s/%d.",
553*83ee113eSDavid van Moolenbroek orig, prefixlen);
554*83ee113eSDavid van Moolenbroek log_error("New value: %s/%d.",
555*83ee113eSDavid van Moolenbroek piaddr(match->addr), prefixlen);
556*83ee113eSDavid van Moolenbroek }
557*83ee113eSDavid van Moolenbroek }
558*83ee113eSDavid van Moolenbroek
559*83ee113eSDavid van Moolenbroek return 1;
560*83ee113eSDavid van Moolenbroek }
561*83ee113eSDavid van Moolenbroek
562*83ee113eSDavid van Moolenbroek parse_warn(cfile,
563*83ee113eSDavid van Moolenbroek "expecting ip-address or ip-address/prefixlen");
564*83ee113eSDavid van Moolenbroek
565*83ee113eSDavid van Moolenbroek return 0; /* let caller pick up pieces */
566*83ee113eSDavid van Moolenbroek }
567*83ee113eSDavid van Moolenbroek
568*83ee113eSDavid van Moolenbroek /*
569*83ee113eSDavid van Moolenbroek * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
570*83ee113eSDavid van Moolenbroek * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI | INFINIBAND
571*83ee113eSDavid van Moolenbroek * Note that INFINIBAND may not be useful for some items, such as classification
572*83ee113eSDavid van Moolenbroek * as the hardware address won't always be available.
573*83ee113eSDavid van Moolenbroek */
574*83ee113eSDavid van Moolenbroek
parse_hardware_param(cfile,hardware)575*83ee113eSDavid van Moolenbroek void parse_hardware_param (cfile, hardware)
576*83ee113eSDavid van Moolenbroek struct parse *cfile;
577*83ee113eSDavid van Moolenbroek struct hardware *hardware;
578*83ee113eSDavid van Moolenbroek {
579*83ee113eSDavid van Moolenbroek const char *val;
580*83ee113eSDavid van Moolenbroek enum dhcp_token token;
581*83ee113eSDavid van Moolenbroek unsigned hlen;
582*83ee113eSDavid van Moolenbroek unsigned char *t;
583*83ee113eSDavid van Moolenbroek
584*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
585*83ee113eSDavid van Moolenbroek switch (token) {
586*83ee113eSDavid van Moolenbroek case ETHERNET:
587*83ee113eSDavid van Moolenbroek hardware->hbuf[0] = HTYPE_ETHER;
588*83ee113eSDavid van Moolenbroek break;
589*83ee113eSDavid van Moolenbroek case TOKEN_RING:
590*83ee113eSDavid van Moolenbroek hardware->hbuf[0] = HTYPE_IEEE802;
591*83ee113eSDavid van Moolenbroek break;
592*83ee113eSDavid van Moolenbroek case TOKEN_FDDI:
593*83ee113eSDavid van Moolenbroek hardware->hbuf[0] = HTYPE_FDDI;
594*83ee113eSDavid van Moolenbroek break;
595*83ee113eSDavid van Moolenbroek case TOKEN_INFINIBAND:
596*83ee113eSDavid van Moolenbroek hardware->hbuf[0] = HTYPE_INFINIBAND;
597*83ee113eSDavid van Moolenbroek break;
598*83ee113eSDavid van Moolenbroek default:
599*83ee113eSDavid van Moolenbroek if (!strncmp(val, "unknown-", 8)) {
600*83ee113eSDavid van Moolenbroek hardware->hbuf[0] = atoi(&val[8]);
601*83ee113eSDavid van Moolenbroek } else {
602*83ee113eSDavid van Moolenbroek parse_warn(cfile,
603*83ee113eSDavid van Moolenbroek "expecting a network hardware type");
604*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
605*83ee113eSDavid van Moolenbroek
606*83ee113eSDavid van Moolenbroek return;
607*83ee113eSDavid van Moolenbroek }
608*83ee113eSDavid van Moolenbroek }
609*83ee113eSDavid van Moolenbroek
610*83ee113eSDavid van Moolenbroek /* Parse the hardware address information. Technically,
611*83ee113eSDavid van Moolenbroek it would make a lot of sense to restrict the length of the
612*83ee113eSDavid van Moolenbroek data we'll accept here to the length of a particular hardware
613*83ee113eSDavid van Moolenbroek address type. Unfortunately, there are some broken clients
614*83ee113eSDavid van Moolenbroek out there that put bogus data in the chaddr buffer, and we accept
615*83ee113eSDavid van Moolenbroek that data in the lease file rather than simply failing on such
616*83ee113eSDavid van Moolenbroek clients. Yuck. */
617*83ee113eSDavid van Moolenbroek hlen = 0;
618*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
619*83ee113eSDavid van Moolenbroek if (token == SEMI) {
620*83ee113eSDavid van Moolenbroek hardware->hlen = 1;
621*83ee113eSDavid van Moolenbroek goto out;
622*83ee113eSDavid van Moolenbroek }
623*83ee113eSDavid van Moolenbroek t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
624*83ee113eSDavid van Moolenbroek if (t == NULL) {
625*83ee113eSDavid van Moolenbroek hardware->hlen = 1;
626*83ee113eSDavid van Moolenbroek return;
627*83ee113eSDavid van Moolenbroek }
628*83ee113eSDavid van Moolenbroek if (hlen + 1 > sizeof(hardware->hbuf)) {
629*83ee113eSDavid van Moolenbroek dfree(t, MDL);
630*83ee113eSDavid van Moolenbroek parse_warn(cfile, "hardware address too long");
631*83ee113eSDavid van Moolenbroek } else {
632*83ee113eSDavid van Moolenbroek hardware->hlen = hlen + 1;
633*83ee113eSDavid van Moolenbroek memcpy((unsigned char *)&hardware->hbuf[1], t, hlen);
634*83ee113eSDavid van Moolenbroek if (hlen + 1 < sizeof(hardware->hbuf))
635*83ee113eSDavid van Moolenbroek memset(&hardware->hbuf[hlen + 1], 0,
636*83ee113eSDavid van Moolenbroek (sizeof(hardware->hbuf)) - hlen - 1);
637*83ee113eSDavid van Moolenbroek dfree(t, MDL);
638*83ee113eSDavid van Moolenbroek }
639*83ee113eSDavid van Moolenbroek
640*83ee113eSDavid van Moolenbroek out:
641*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
642*83ee113eSDavid van Moolenbroek if (token != SEMI) {
643*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting semicolon.");
644*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
645*83ee113eSDavid van Moolenbroek }
646*83ee113eSDavid van Moolenbroek }
647*83ee113eSDavid van Moolenbroek
648*83ee113eSDavid van Moolenbroek /* lease-time :== NUMBER SEMI */
649*83ee113eSDavid van Moolenbroek
parse_lease_time(cfile,timep)650*83ee113eSDavid van Moolenbroek void parse_lease_time (cfile, timep)
651*83ee113eSDavid van Moolenbroek struct parse *cfile;
652*83ee113eSDavid van Moolenbroek TIME *timep;
653*83ee113eSDavid van Moolenbroek {
654*83ee113eSDavid van Moolenbroek const char *val;
655*83ee113eSDavid van Moolenbroek enum dhcp_token token;
656*83ee113eSDavid van Moolenbroek u_int32_t num;
657*83ee113eSDavid van Moolenbroek
658*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
659*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
660*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Expecting numeric lease time");
661*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
662*83ee113eSDavid van Moolenbroek return;
663*83ee113eSDavid van Moolenbroek }
664*83ee113eSDavid van Moolenbroek convert_num(cfile, (unsigned char *)&num, val, 10, 32);
665*83ee113eSDavid van Moolenbroek /* Unswap the number - convert_num returns stuff in NBO. */
666*83ee113eSDavid van Moolenbroek *timep = ntohl(num);
667*83ee113eSDavid van Moolenbroek
668*83ee113eSDavid van Moolenbroek parse_semi (cfile);
669*83ee113eSDavid van Moolenbroek }
670*83ee113eSDavid van Moolenbroek
671*83ee113eSDavid van Moolenbroek /* No BNF for numeric aggregates - that's defined by the caller. What
672*83ee113eSDavid van Moolenbroek this function does is to parse a sequence of numbers separated by
673*83ee113eSDavid van Moolenbroek the token specified in separator. If max is zero, any number of
674*83ee113eSDavid van Moolenbroek numbers will be parsed; otherwise, exactly max numbers are
675*83ee113eSDavid van Moolenbroek expected. Base and size tell us how to internalize the numbers
676*83ee113eSDavid van Moolenbroek once they've been tokenized.
677*83ee113eSDavid van Moolenbroek
678*83ee113eSDavid van Moolenbroek buf - A pointer to space to return the parsed value, if it is null
679*83ee113eSDavid van Moolenbroek then the function will allocate space for the return.
680*83ee113eSDavid van Moolenbroek
681*83ee113eSDavid van Moolenbroek max - The maximum number of items to store. If zero there is no
682*83ee113eSDavid van Moolenbroek maximum. When buf is null and the function needs to allocate space
683*83ee113eSDavid van Moolenbroek it will do an allocation of max size at the beginning if max is non
684*83ee113eSDavid van Moolenbroek zero. If max is zero then the allocation will be done later, after
685*83ee113eSDavid van Moolenbroek the function has determined the size necessary for the incoming
686*83ee113eSDavid van Moolenbroek string.
687*83ee113eSDavid van Moolenbroek
688*83ee113eSDavid van Moolenbroek returns NULL on errors or a pointer to the value string on success.
689*83ee113eSDavid van Moolenbroek The pointer will either be buf if it was non-NULL or newly allocated
690*83ee113eSDavid van Moolenbroek space if buf was NULL
691*83ee113eSDavid van Moolenbroek */
692*83ee113eSDavid van Moolenbroek
693*83ee113eSDavid van Moolenbroek
parse_numeric_aggregate(cfile,buf,max,separator,base,size)694*83ee113eSDavid van Moolenbroek unsigned char *parse_numeric_aggregate (cfile, buf,
695*83ee113eSDavid van Moolenbroek max, separator, base, size)
696*83ee113eSDavid van Moolenbroek struct parse *cfile;
697*83ee113eSDavid van Moolenbroek unsigned char *buf;
698*83ee113eSDavid van Moolenbroek unsigned *max;
699*83ee113eSDavid van Moolenbroek int separator;
700*83ee113eSDavid van Moolenbroek int base;
701*83ee113eSDavid van Moolenbroek unsigned size;
702*83ee113eSDavid van Moolenbroek {
703*83ee113eSDavid van Moolenbroek const char *val;
704*83ee113eSDavid van Moolenbroek enum dhcp_token token;
705*83ee113eSDavid van Moolenbroek unsigned char *bufp = buf, *s, *t;
706*83ee113eSDavid van Moolenbroek unsigned count = 0;
707*83ee113eSDavid van Moolenbroek pair c = (pair)0;
708*83ee113eSDavid van Moolenbroek
709*83ee113eSDavid van Moolenbroek if (!bufp && *max) {
710*83ee113eSDavid van Moolenbroek bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
711*83ee113eSDavid van Moolenbroek if (!bufp)
712*83ee113eSDavid van Moolenbroek log_fatal ("no space for numeric aggregate");
713*83ee113eSDavid van Moolenbroek }
714*83ee113eSDavid van Moolenbroek s = bufp;
715*83ee113eSDavid van Moolenbroek
716*83ee113eSDavid van Moolenbroek do {
717*83ee113eSDavid van Moolenbroek if (count) {
718*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
719*83ee113eSDavid van Moolenbroek if (token != separator) {
720*83ee113eSDavid van Moolenbroek if (!*max)
721*83ee113eSDavid van Moolenbroek break;
722*83ee113eSDavid van Moolenbroek if (token != RBRACE && token != LBRACE)
723*83ee113eSDavid van Moolenbroek token = next_token (&val,
724*83ee113eSDavid van Moolenbroek (unsigned *)0,
725*83ee113eSDavid van Moolenbroek cfile);
726*83ee113eSDavid van Moolenbroek parse_warn (cfile, "too few numbers.");
727*83ee113eSDavid van Moolenbroek if (token != SEMI)
728*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
729*83ee113eSDavid van Moolenbroek /* free bufp if it was allocated */
730*83ee113eSDavid van Moolenbroek if ((bufp != NULL) && (bufp != buf))
731*83ee113eSDavid van Moolenbroek dfree(bufp, MDL);
732*83ee113eSDavid van Moolenbroek return (unsigned char *)0;
733*83ee113eSDavid van Moolenbroek }
734*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
735*83ee113eSDavid van Moolenbroek }
736*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
737*83ee113eSDavid van Moolenbroek
738*83ee113eSDavid van Moolenbroek if (token == END_OF_FILE) {
739*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unexpected end of file");
740*83ee113eSDavid van Moolenbroek break;
741*83ee113eSDavid van Moolenbroek }
742*83ee113eSDavid van Moolenbroek
743*83ee113eSDavid van Moolenbroek /* Allow NUMBER_OR_NAME if base is 16. */
744*83ee113eSDavid van Moolenbroek if (token != NUMBER &&
745*83ee113eSDavid van Moolenbroek (base != 16 || token != NUMBER_OR_NAME)) {
746*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting numeric value.");
747*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
748*83ee113eSDavid van Moolenbroek /* free bufp if it was allocated */
749*83ee113eSDavid van Moolenbroek if ((bufp != NULL) && (bufp != buf))
750*83ee113eSDavid van Moolenbroek dfree(bufp, MDL);
751*83ee113eSDavid van Moolenbroek /* free any linked numbers we may have allocated */
752*83ee113eSDavid van Moolenbroek while (c) {
753*83ee113eSDavid van Moolenbroek pair cdr = c->cdr;
754*83ee113eSDavid van Moolenbroek dfree(c->car, MDL);
755*83ee113eSDavid van Moolenbroek dfree(c, MDL);
756*83ee113eSDavid van Moolenbroek c = cdr;
757*83ee113eSDavid van Moolenbroek }
758*83ee113eSDavid van Moolenbroek return (NULL);
759*83ee113eSDavid van Moolenbroek }
760*83ee113eSDavid van Moolenbroek /* If we can, convert the number now; otherwise, build
761*83ee113eSDavid van Moolenbroek a linked list of all the numbers. */
762*83ee113eSDavid van Moolenbroek if (s) {
763*83ee113eSDavid van Moolenbroek convert_num (cfile, s, val, base, size);
764*83ee113eSDavid van Moolenbroek s += size / 8;
765*83ee113eSDavid van Moolenbroek } else {
766*83ee113eSDavid van Moolenbroek t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
767*83ee113eSDavid van Moolenbroek if (!t)
768*83ee113eSDavid van Moolenbroek log_fatal ("no temp space for number.");
769*83ee113eSDavid van Moolenbroek strcpy ((char *)t, val);
770*83ee113eSDavid van Moolenbroek c = cons ((caddr_t)t, c);
771*83ee113eSDavid van Moolenbroek }
772*83ee113eSDavid van Moolenbroek } while (++count != *max);
773*83ee113eSDavid van Moolenbroek
774*83ee113eSDavid van Moolenbroek /* If we had to cons up a list, convert it now. */
775*83ee113eSDavid van Moolenbroek if (c) {
776*83ee113eSDavid van Moolenbroek /*
777*83ee113eSDavid van Moolenbroek * No need to cleanup bufp, to get here we didn't allocate
778*83ee113eSDavid van Moolenbroek * bufp above
779*83ee113eSDavid van Moolenbroek */
780*83ee113eSDavid van Moolenbroek bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
781*83ee113eSDavid van Moolenbroek if (!bufp)
782*83ee113eSDavid van Moolenbroek log_fatal ("no space for numeric aggregate.");
783*83ee113eSDavid van Moolenbroek s = bufp + count - size / 8;
784*83ee113eSDavid van Moolenbroek *max = count;
785*83ee113eSDavid van Moolenbroek }
786*83ee113eSDavid van Moolenbroek while (c) {
787*83ee113eSDavid van Moolenbroek pair cdr = c -> cdr;
788*83ee113eSDavid van Moolenbroek convert_num (cfile, s, (char *)(c -> car), base, size);
789*83ee113eSDavid van Moolenbroek s -= size / 8;
790*83ee113eSDavid van Moolenbroek /* Free up temp space. */
791*83ee113eSDavid van Moolenbroek dfree (c -> car, MDL);
792*83ee113eSDavid van Moolenbroek dfree (c, MDL);
793*83ee113eSDavid van Moolenbroek c = cdr;
794*83ee113eSDavid van Moolenbroek }
795*83ee113eSDavid van Moolenbroek return bufp;
796*83ee113eSDavid van Moolenbroek }
797*83ee113eSDavid van Moolenbroek
convert_num(cfile,buf,str,base,size)798*83ee113eSDavid van Moolenbroek void convert_num (cfile, buf, str, base, size)
799*83ee113eSDavid van Moolenbroek struct parse *cfile;
800*83ee113eSDavid van Moolenbroek unsigned char *buf;
801*83ee113eSDavid van Moolenbroek const char *str;
802*83ee113eSDavid van Moolenbroek int base;
803*83ee113eSDavid van Moolenbroek unsigned size;
804*83ee113eSDavid van Moolenbroek {
805*83ee113eSDavid van Moolenbroek const unsigned char *ptr = (const unsigned char *)str;
806*83ee113eSDavid van Moolenbroek int negative = 0;
807*83ee113eSDavid van Moolenbroek u_int32_t val = 0;
808*83ee113eSDavid van Moolenbroek int tval;
809*83ee113eSDavid van Moolenbroek int max;
810*83ee113eSDavid van Moolenbroek
811*83ee113eSDavid van Moolenbroek if (*ptr == '-') {
812*83ee113eSDavid van Moolenbroek negative = 1;
813*83ee113eSDavid van Moolenbroek ++ptr;
814*83ee113eSDavid van Moolenbroek }
815*83ee113eSDavid van Moolenbroek
816*83ee113eSDavid van Moolenbroek /* If base wasn't specified, figure it out from the data. */
817*83ee113eSDavid van Moolenbroek if (!base) {
818*83ee113eSDavid van Moolenbroek if (ptr [0] == '0') {
819*83ee113eSDavid van Moolenbroek if (ptr [1] == 'x') {
820*83ee113eSDavid van Moolenbroek base = 16;
821*83ee113eSDavid van Moolenbroek ptr += 2;
822*83ee113eSDavid van Moolenbroek } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
823*83ee113eSDavid van Moolenbroek base = 8;
824*83ee113eSDavid van Moolenbroek ptr += 1;
825*83ee113eSDavid van Moolenbroek } else {
826*83ee113eSDavid van Moolenbroek base = 10;
827*83ee113eSDavid van Moolenbroek }
828*83ee113eSDavid van Moolenbroek } else {
829*83ee113eSDavid van Moolenbroek base = 10;
830*83ee113eSDavid van Moolenbroek }
831*83ee113eSDavid van Moolenbroek }
832*83ee113eSDavid van Moolenbroek
833*83ee113eSDavid van Moolenbroek do {
834*83ee113eSDavid van Moolenbroek tval = *ptr++;
835*83ee113eSDavid van Moolenbroek /* XXX assumes ASCII... */
836*83ee113eSDavid van Moolenbroek if (tval >= 'a')
837*83ee113eSDavid van Moolenbroek tval = tval - 'a' + 10;
838*83ee113eSDavid van Moolenbroek else if (tval >= 'A')
839*83ee113eSDavid van Moolenbroek tval = tval - 'A' + 10;
840*83ee113eSDavid van Moolenbroek else if (tval >= '0')
841*83ee113eSDavid van Moolenbroek tval -= '0';
842*83ee113eSDavid van Moolenbroek else {
843*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Bogus number: %s.", str);
844*83ee113eSDavid van Moolenbroek break;
845*83ee113eSDavid van Moolenbroek }
846*83ee113eSDavid van Moolenbroek if (tval >= base) {
847*83ee113eSDavid van Moolenbroek parse_warn (cfile,
848*83ee113eSDavid van Moolenbroek "Bogus number %s: digit %d not in base %d",
849*83ee113eSDavid van Moolenbroek str, tval, base);
850*83ee113eSDavid van Moolenbroek break;
851*83ee113eSDavid van Moolenbroek }
852*83ee113eSDavid van Moolenbroek val = val * base + tval;
853*83ee113eSDavid van Moolenbroek } while (*ptr);
854*83ee113eSDavid van Moolenbroek
855*83ee113eSDavid van Moolenbroek if (negative)
856*83ee113eSDavid van Moolenbroek max = (1 << (size - 1));
857*83ee113eSDavid van Moolenbroek else
858*83ee113eSDavid van Moolenbroek max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
859*83ee113eSDavid van Moolenbroek if (val > max) {
860*83ee113eSDavid van Moolenbroek switch (base) {
861*83ee113eSDavid van Moolenbroek case 8:
862*83ee113eSDavid van Moolenbroek parse_warn (cfile,
863*83ee113eSDavid van Moolenbroek "%s%lo exceeds max (%d) for precision.",
864*83ee113eSDavid van Moolenbroek negative ? "-" : "",
865*83ee113eSDavid van Moolenbroek (unsigned long)val, max);
866*83ee113eSDavid van Moolenbroek break;
867*83ee113eSDavid van Moolenbroek case 16:
868*83ee113eSDavid van Moolenbroek parse_warn (cfile,
869*83ee113eSDavid van Moolenbroek "%s%lx exceeds max (%d) for precision.",
870*83ee113eSDavid van Moolenbroek negative ? "-" : "",
871*83ee113eSDavid van Moolenbroek (unsigned long)val, max);
872*83ee113eSDavid van Moolenbroek break;
873*83ee113eSDavid van Moolenbroek default:
874*83ee113eSDavid van Moolenbroek parse_warn (cfile,
875*83ee113eSDavid van Moolenbroek "%s%lu exceeds max (%d) for precision.",
876*83ee113eSDavid van Moolenbroek negative ? "-" : "",
877*83ee113eSDavid van Moolenbroek (unsigned long)val, max);
878*83ee113eSDavid van Moolenbroek break;
879*83ee113eSDavid van Moolenbroek }
880*83ee113eSDavid van Moolenbroek }
881*83ee113eSDavid van Moolenbroek
882*83ee113eSDavid van Moolenbroek if (negative) {
883*83ee113eSDavid van Moolenbroek switch (size) {
884*83ee113eSDavid van Moolenbroek case 8:
885*83ee113eSDavid van Moolenbroek *buf = -(unsigned long)val;
886*83ee113eSDavid van Moolenbroek break;
887*83ee113eSDavid van Moolenbroek case 16:
888*83ee113eSDavid van Moolenbroek putShort (buf, -(long)val);
889*83ee113eSDavid van Moolenbroek break;
890*83ee113eSDavid van Moolenbroek case 32:
891*83ee113eSDavid van Moolenbroek putLong (buf, -(long)val);
892*83ee113eSDavid van Moolenbroek break;
893*83ee113eSDavid van Moolenbroek default:
894*83ee113eSDavid van Moolenbroek parse_warn (cfile,
895*83ee113eSDavid van Moolenbroek "Unexpected integer size: %d\n", size);
896*83ee113eSDavid van Moolenbroek break;
897*83ee113eSDavid van Moolenbroek }
898*83ee113eSDavid van Moolenbroek } else {
899*83ee113eSDavid van Moolenbroek switch (size) {
900*83ee113eSDavid van Moolenbroek case 8:
901*83ee113eSDavid van Moolenbroek *buf = (u_int8_t)val;
902*83ee113eSDavid van Moolenbroek break;
903*83ee113eSDavid van Moolenbroek case 16:
904*83ee113eSDavid van Moolenbroek putUShort (buf, (u_int16_t)val);
905*83ee113eSDavid van Moolenbroek break;
906*83ee113eSDavid van Moolenbroek case 32:
907*83ee113eSDavid van Moolenbroek putULong (buf, val);
908*83ee113eSDavid van Moolenbroek break;
909*83ee113eSDavid van Moolenbroek default:
910*83ee113eSDavid van Moolenbroek parse_warn (cfile,
911*83ee113eSDavid van Moolenbroek "Unexpected integer size: %d\n", size);
912*83ee113eSDavid van Moolenbroek break;
913*83ee113eSDavid van Moolenbroek }
914*83ee113eSDavid van Moolenbroek }
915*83ee113eSDavid van Moolenbroek }
916*83ee113eSDavid van Moolenbroek
917*83ee113eSDavid van Moolenbroek /*
918*83ee113eSDavid van Moolenbroek * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
919*83ee113eSDavid van Moolenbroek * NUMBER COLON NUMBER COLON NUMBER |
920*83ee113eSDavid van Moolenbroek * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
921*83ee113eSDavid van Moolenbroek * NUMBER COLON NUMBER COLON NUMBER NUMBER |
922*83ee113eSDavid van Moolenbroek * EPOCH NUMBER |
923*83ee113eSDavid van Moolenbroek * NEVER
924*83ee113eSDavid van Moolenbroek *
925*83ee113eSDavid van Moolenbroek * Dates are stored in UTC or with a timezone offset; first number is day
926*83ee113eSDavid van Moolenbroek * of week; next is year/month/day; next is hours:minutes:seconds on a
927*83ee113eSDavid van Moolenbroek * 24-hour clock, followed by the timezone offset in seconds, which is
928*83ee113eSDavid van Moolenbroek * optional.
929*83ee113eSDavid van Moolenbroek */
930*83ee113eSDavid van Moolenbroek
931*83ee113eSDavid van Moolenbroek /*
932*83ee113eSDavid van Moolenbroek * just parse the date
933*83ee113eSDavid van Moolenbroek * any trailing semi must be consumed by the caller of this routine
934*83ee113eSDavid van Moolenbroek */
935*83ee113eSDavid van Moolenbroek TIME
parse_date_core(cfile)936*83ee113eSDavid van Moolenbroek parse_date_core(cfile)
937*83ee113eSDavid van Moolenbroek struct parse *cfile;
938*83ee113eSDavid van Moolenbroek {
939*83ee113eSDavid van Moolenbroek int guess;
940*83ee113eSDavid van Moolenbroek int tzoff, year, mon, mday, hour, min, sec;
941*83ee113eSDavid van Moolenbroek const char *val;
942*83ee113eSDavid van Moolenbroek enum dhcp_token token;
943*83ee113eSDavid van Moolenbroek static int months[11] = { 31, 59, 90, 120, 151, 181,
944*83ee113eSDavid van Moolenbroek 212, 243, 273, 304, 334 };
945*83ee113eSDavid van Moolenbroek
946*83ee113eSDavid van Moolenbroek /* "never", "epoch" or day of week */
947*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
948*83ee113eSDavid van Moolenbroek if (token == NEVER) {
949*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume NEVER */
950*83ee113eSDavid van Moolenbroek return(MAX_TIME);
951*83ee113eSDavid van Moolenbroek }
952*83ee113eSDavid van Moolenbroek
953*83ee113eSDavid van Moolenbroek /* This indicates 'local' time format. */
954*83ee113eSDavid van Moolenbroek if (token == EPOCH) {
955*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume EPOCH */
956*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
957*83ee113eSDavid van Moolenbroek
958*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
959*83ee113eSDavid van Moolenbroek if (token != SEMI)
960*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
961*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Seconds since epoch expected.");
962*83ee113eSDavid van Moolenbroek return((TIME)0);
963*83ee113eSDavid van Moolenbroek }
964*83ee113eSDavid van Moolenbroek
965*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume number */
966*83ee113eSDavid van Moolenbroek guess = atoi(val);
967*83ee113eSDavid van Moolenbroek
968*83ee113eSDavid van Moolenbroek return((TIME)guess);
969*83ee113eSDavid van Moolenbroek }
970*83ee113eSDavid van Moolenbroek
971*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
972*83ee113eSDavid van Moolenbroek if (token != SEMI)
973*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
974*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric day of week expected.");
975*83ee113eSDavid van Moolenbroek return((TIME)0);
976*83ee113eSDavid van Moolenbroek }
977*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume day of week */
978*83ee113eSDavid van Moolenbroek /* we are not using this for anything */
979*83ee113eSDavid van Moolenbroek
980*83ee113eSDavid van Moolenbroek /* Year... */
981*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
982*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
983*83ee113eSDavid van Moolenbroek if (token != SEMI)
984*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
985*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric year expected.");
986*83ee113eSDavid van Moolenbroek return((TIME)0);
987*83ee113eSDavid van Moolenbroek }
988*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume year */
989*83ee113eSDavid van Moolenbroek
990*83ee113eSDavid van Moolenbroek /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
991*83ee113eSDavid van Moolenbroek somebody invents a time machine, I think we can safely disregard
992*83ee113eSDavid van Moolenbroek it. This actually works around a stupid Y2K bug that was present
993*83ee113eSDavid van Moolenbroek in a very early beta release of dhcpd. */
994*83ee113eSDavid van Moolenbroek year = atoi(val);
995*83ee113eSDavid van Moolenbroek if (year > 1900)
996*83ee113eSDavid van Moolenbroek year -= 1900;
997*83ee113eSDavid van Moolenbroek
998*83ee113eSDavid van Moolenbroek /* Slash separating year from month... */
999*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1000*83ee113eSDavid van Moolenbroek if (token != SLASH) {
1001*83ee113eSDavid van Moolenbroek if (token != SEMI)
1002*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1003*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1004*83ee113eSDavid van Moolenbroek "expected slash separating year from month.");
1005*83ee113eSDavid van Moolenbroek return((TIME)0);
1006*83ee113eSDavid van Moolenbroek }
1007*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume SLASH */
1008*83ee113eSDavid van Moolenbroek
1009*83ee113eSDavid van Moolenbroek /* Month... */
1010*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1011*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1012*83ee113eSDavid van Moolenbroek if (token != SEMI)
1013*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1014*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric month expected.");
1015*83ee113eSDavid van Moolenbroek return((TIME)0);
1016*83ee113eSDavid van Moolenbroek }
1017*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume month */
1018*83ee113eSDavid van Moolenbroek mon = atoi(val) - 1;
1019*83ee113eSDavid van Moolenbroek
1020*83ee113eSDavid van Moolenbroek /* Slash separating month from day... */
1021*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1022*83ee113eSDavid van Moolenbroek if (token != SLASH) {
1023*83ee113eSDavid van Moolenbroek if (token != SEMI)
1024*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1025*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1026*83ee113eSDavid van Moolenbroek "expected slash separating month from day.");
1027*83ee113eSDavid van Moolenbroek return((TIME)0);
1028*83ee113eSDavid van Moolenbroek }
1029*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume SLASH */
1030*83ee113eSDavid van Moolenbroek
1031*83ee113eSDavid van Moolenbroek /* Day of month... */
1032*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1033*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1034*83ee113eSDavid van Moolenbroek if (token != SEMI)
1035*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1036*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric day of month expected.");
1037*83ee113eSDavid van Moolenbroek return((TIME)0);
1038*83ee113eSDavid van Moolenbroek }
1039*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume day of month */
1040*83ee113eSDavid van Moolenbroek mday = atoi(val);
1041*83ee113eSDavid van Moolenbroek
1042*83ee113eSDavid van Moolenbroek /* Hour... */
1043*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1044*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1045*83ee113eSDavid van Moolenbroek if (token != SEMI)
1046*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1047*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric hour expected.");
1048*83ee113eSDavid van Moolenbroek return((TIME)0);
1049*83ee113eSDavid van Moolenbroek }
1050*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume hour */
1051*83ee113eSDavid van Moolenbroek hour = atoi(val);
1052*83ee113eSDavid van Moolenbroek
1053*83ee113eSDavid van Moolenbroek /* Colon separating hour from minute... */
1054*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1055*83ee113eSDavid van Moolenbroek if (token != COLON) {
1056*83ee113eSDavid van Moolenbroek if (token != SEMI)
1057*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1058*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1059*83ee113eSDavid van Moolenbroek "expected colon separating hour from minute.");
1060*83ee113eSDavid van Moolenbroek return((TIME)0);
1061*83ee113eSDavid van Moolenbroek }
1062*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume colon */
1063*83ee113eSDavid van Moolenbroek
1064*83ee113eSDavid van Moolenbroek /* Minute... */
1065*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1066*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1067*83ee113eSDavid van Moolenbroek if (token != SEMI)
1068*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1069*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric minute expected.");
1070*83ee113eSDavid van Moolenbroek return((TIME)0);
1071*83ee113eSDavid van Moolenbroek }
1072*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume minute */
1073*83ee113eSDavid van Moolenbroek min = atoi(val);
1074*83ee113eSDavid van Moolenbroek
1075*83ee113eSDavid van Moolenbroek /* Colon separating minute from second... */
1076*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1077*83ee113eSDavid van Moolenbroek if (token != COLON) {
1078*83ee113eSDavid van Moolenbroek if (token != SEMI)
1079*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1080*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1081*83ee113eSDavid van Moolenbroek "expected colon separating minute from second.");
1082*83ee113eSDavid van Moolenbroek return((TIME)0);
1083*83ee113eSDavid van Moolenbroek }
1084*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume colon */
1085*83ee113eSDavid van Moolenbroek
1086*83ee113eSDavid van Moolenbroek /* Second... */
1087*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1088*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1089*83ee113eSDavid van Moolenbroek if (token != SEMI)
1090*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1091*83ee113eSDavid van Moolenbroek parse_warn(cfile, "numeric second expected.");
1092*83ee113eSDavid van Moolenbroek return((TIME)0);
1093*83ee113eSDavid van Moolenbroek }
1094*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume second */
1095*83ee113eSDavid van Moolenbroek sec = atoi(val);
1096*83ee113eSDavid van Moolenbroek
1097*83ee113eSDavid van Moolenbroek tzoff = 0;
1098*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1099*83ee113eSDavid van Moolenbroek if (token == NUMBER) {
1100*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile); /* consume tzoff */
1101*83ee113eSDavid van Moolenbroek tzoff = atoi(val);
1102*83ee113eSDavid van Moolenbroek } else if (token != SEMI) {
1103*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1104*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1105*83ee113eSDavid van Moolenbroek "Time zone offset or semicolon expected.");
1106*83ee113eSDavid van Moolenbroek return((TIME)0);
1107*83ee113eSDavid van Moolenbroek }
1108*83ee113eSDavid van Moolenbroek
1109*83ee113eSDavid van Moolenbroek /* Guess the time value... */
1110*83ee113eSDavid van Moolenbroek guess = ((((((365 * (year - 70) + /* Days in years since '70 */
1111*83ee113eSDavid van Moolenbroek (year - 69) / 4 + /* Leap days since '70 */
1112*83ee113eSDavid van Moolenbroek (mon /* Days in months this year */
1113*83ee113eSDavid van Moolenbroek ? months [mon - 1]
1114*83ee113eSDavid van Moolenbroek : 0) +
1115*83ee113eSDavid van Moolenbroek (mon > 1 && /* Leap day this year */
1116*83ee113eSDavid van Moolenbroek !((year - 72) & 3)) +
1117*83ee113eSDavid van Moolenbroek mday - 1) * 24) + /* Day of month */
1118*83ee113eSDavid van Moolenbroek hour) * 60) +
1119*83ee113eSDavid van Moolenbroek min) * 60) + sec + tzoff;
1120*83ee113eSDavid van Moolenbroek
1121*83ee113eSDavid van Moolenbroek /* This guess could be wrong because of leap seconds or other
1122*83ee113eSDavid van Moolenbroek weirdness we don't know about that the system does. For
1123*83ee113eSDavid van Moolenbroek now, we're just going to accept the guess, but at some point
1124*83ee113eSDavid van Moolenbroek it might be nice to do a successive approximation here to
1125*83ee113eSDavid van Moolenbroek get an exact value. Even if the error is small, if the
1126*83ee113eSDavid van Moolenbroek server is restarted frequently (and thus the lease database
1127*83ee113eSDavid van Moolenbroek is reread), the error could accumulate into something
1128*83ee113eSDavid van Moolenbroek significant. */
1129*83ee113eSDavid van Moolenbroek
1130*83ee113eSDavid van Moolenbroek return((TIME)guess);
1131*83ee113eSDavid van Moolenbroek }
1132*83ee113eSDavid van Moolenbroek
1133*83ee113eSDavid van Moolenbroek /*
1134*83ee113eSDavid van Moolenbroek * Wrapper to consume the semicolon after the date
1135*83ee113eSDavid van Moolenbroek * :== date semi
1136*83ee113eSDavid van Moolenbroek */
1137*83ee113eSDavid van Moolenbroek
1138*83ee113eSDavid van Moolenbroek TIME
parse_date(cfile)1139*83ee113eSDavid van Moolenbroek parse_date(cfile)
1140*83ee113eSDavid van Moolenbroek struct parse *cfile;
1141*83ee113eSDavid van Moolenbroek {
1142*83ee113eSDavid van Moolenbroek TIME guess;
1143*83ee113eSDavid van Moolenbroek guess = parse_date_core(cfile);
1144*83ee113eSDavid van Moolenbroek
1145*83ee113eSDavid van Moolenbroek /* Make sure the date ends in a semicolon... */
1146*83ee113eSDavid van Moolenbroek if (!parse_semi(cfile))
1147*83ee113eSDavid van Moolenbroek return((TIME)0);
1148*83ee113eSDavid van Moolenbroek return(guess);
1149*83ee113eSDavid van Moolenbroek }
1150*83ee113eSDavid van Moolenbroek
1151*83ee113eSDavid van Moolenbroek
1152*83ee113eSDavid van Moolenbroek
1153*83ee113eSDavid van Moolenbroek /*
1154*83ee113eSDavid van Moolenbroek * option-name :== IDENTIFIER |
1155*83ee113eSDavid van Moolenbroek IDENTIFIER . IDENTIFIER
1156*83ee113eSDavid van Moolenbroek */
1157*83ee113eSDavid van Moolenbroek
1158*83ee113eSDavid van Moolenbroek isc_result_t
parse_option_name(cfile,allocate,known,opt)1159*83ee113eSDavid van Moolenbroek parse_option_name (cfile, allocate, known, opt)
1160*83ee113eSDavid van Moolenbroek struct parse *cfile;
1161*83ee113eSDavid van Moolenbroek int allocate;
1162*83ee113eSDavid van Moolenbroek int *known;
1163*83ee113eSDavid van Moolenbroek struct option **opt;
1164*83ee113eSDavid van Moolenbroek {
1165*83ee113eSDavid van Moolenbroek const char *val;
1166*83ee113eSDavid van Moolenbroek enum dhcp_token token;
1167*83ee113eSDavid van Moolenbroek char *uname;
1168*83ee113eSDavid van Moolenbroek struct universe *universe;
1169*83ee113eSDavid van Moolenbroek struct option *option;
1170*83ee113eSDavid van Moolenbroek unsigned code;
1171*83ee113eSDavid van Moolenbroek
1172*83ee113eSDavid van Moolenbroek if (opt == NULL)
1173*83ee113eSDavid van Moolenbroek return DHCP_R_INVALIDARG;
1174*83ee113eSDavid van Moolenbroek
1175*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1176*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
1177*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1178*83ee113eSDavid van Moolenbroek "expecting identifier after option keyword.");
1179*83ee113eSDavid van Moolenbroek if (token != SEMI)
1180*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1181*83ee113eSDavid van Moolenbroek return DHCP_R_BADPARSE;
1182*83ee113eSDavid van Moolenbroek }
1183*83ee113eSDavid van Moolenbroek uname = dmalloc (strlen (val) + 1, MDL);
1184*83ee113eSDavid van Moolenbroek if (!uname)
1185*83ee113eSDavid van Moolenbroek log_fatal ("no memory for uname information.");
1186*83ee113eSDavid van Moolenbroek strcpy (uname, val);
1187*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
1188*83ee113eSDavid van Moolenbroek if (token == DOT) {
1189*83ee113eSDavid van Moolenbroek /* Go ahead and take the DOT token... */
1190*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
1191*83ee113eSDavid van Moolenbroek
1192*83ee113eSDavid van Moolenbroek /* The next token should be an identifier... */
1193*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1194*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
1195*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting identifier after '.'");
1196*83ee113eSDavid van Moolenbroek if (token != SEMI)
1197*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1198*83ee113eSDavid van Moolenbroek return DHCP_R_BADPARSE;
1199*83ee113eSDavid van Moolenbroek }
1200*83ee113eSDavid van Moolenbroek
1201*83ee113eSDavid van Moolenbroek /* Look up the option name hash table for the specified
1202*83ee113eSDavid van Moolenbroek uname. */
1203*83ee113eSDavid van Moolenbroek universe = (struct universe *)0;
1204*83ee113eSDavid van Moolenbroek if (!universe_hash_lookup (&universe, universe_hash,
1205*83ee113eSDavid van Moolenbroek uname, 0, MDL)) {
1206*83ee113eSDavid van Moolenbroek parse_warn (cfile, "no option space named %s.", uname);
1207*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1208*83ee113eSDavid van Moolenbroek return ISC_R_NOTFOUND;
1209*83ee113eSDavid van Moolenbroek }
1210*83ee113eSDavid van Moolenbroek } else {
1211*83ee113eSDavid van Moolenbroek /* Use the default hash table, which contains all the
1212*83ee113eSDavid van Moolenbroek standard dhcp option names. */
1213*83ee113eSDavid van Moolenbroek val = uname;
1214*83ee113eSDavid van Moolenbroek universe = &dhcp_universe;
1215*83ee113eSDavid van Moolenbroek }
1216*83ee113eSDavid van Moolenbroek
1217*83ee113eSDavid van Moolenbroek /* Look up the actual option info... */
1218*83ee113eSDavid van Moolenbroek option_name_hash_lookup(opt, universe->name_hash, val, 0, MDL);
1219*83ee113eSDavid van Moolenbroek option = *opt;
1220*83ee113eSDavid van Moolenbroek
1221*83ee113eSDavid van Moolenbroek /* If we didn't get an option structure, it's an undefined option. */
1222*83ee113eSDavid van Moolenbroek if (option) {
1223*83ee113eSDavid van Moolenbroek if (known)
1224*83ee113eSDavid van Moolenbroek *known = 1;
1225*83ee113eSDavid van Moolenbroek /* If the option name is of the form unknown-[decimal], use
1226*83ee113eSDavid van Moolenbroek * the trailing decimal value to find the option definition.
1227*83ee113eSDavid van Moolenbroek * If there is no definition, construct one. This is to
1228*83ee113eSDavid van Moolenbroek * support legacy use of unknown options in config files or
1229*83ee113eSDavid van Moolenbroek * lease databases.
1230*83ee113eSDavid van Moolenbroek */
1231*83ee113eSDavid van Moolenbroek } else if (strncasecmp(val, "unknown-", 8) == 0) {
1232*83ee113eSDavid van Moolenbroek code = atoi(val+8);
1233*83ee113eSDavid van Moolenbroek
1234*83ee113eSDavid van Moolenbroek /* Option code 0 is always illegal for us, thanks
1235*83ee113eSDavid van Moolenbroek * to the option decoder.
1236*83ee113eSDavid van Moolenbroek */
1237*83ee113eSDavid van Moolenbroek if (code == 0 || code == universe->end) {
1238*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Option codes 0 and %u are illegal "
1239*83ee113eSDavid van Moolenbroek "in the %s space.", universe->end,
1240*83ee113eSDavid van Moolenbroek universe->name);
1241*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
1242*83ee113eSDavid van Moolenbroek dfree(uname, MDL);
1243*83ee113eSDavid van Moolenbroek return ISC_R_FAILURE;
1244*83ee113eSDavid van Moolenbroek }
1245*83ee113eSDavid van Moolenbroek
1246*83ee113eSDavid van Moolenbroek /* It's odd to think of unknown option codes as
1247*83ee113eSDavid van Moolenbroek * being known, but this means we know what the
1248*83ee113eSDavid van Moolenbroek * parsed name is talking about.
1249*83ee113eSDavid van Moolenbroek */
1250*83ee113eSDavid van Moolenbroek if (known)
1251*83ee113eSDavid van Moolenbroek *known = 1;
1252*83ee113eSDavid van Moolenbroek
1253*83ee113eSDavid van Moolenbroek option_code_hash_lookup(opt, universe->code_hash,
1254*83ee113eSDavid van Moolenbroek &code, 0, MDL);
1255*83ee113eSDavid van Moolenbroek option = *opt;
1256*83ee113eSDavid van Moolenbroek
1257*83ee113eSDavid van Moolenbroek /* If we did not find an option of that code,
1258*83ee113eSDavid van Moolenbroek * manufacture an unknown-xxx option definition.
1259*83ee113eSDavid van Moolenbroek * Its single reference will ensure that it is
1260*83ee113eSDavid van Moolenbroek * deleted once the option is recycled out of
1261*83ee113eSDavid van Moolenbroek * existence (by the parent).
1262*83ee113eSDavid van Moolenbroek */
1263*83ee113eSDavid van Moolenbroek if (option == NULL) {
1264*83ee113eSDavid van Moolenbroek option = new_option(val, MDL);
1265*83ee113eSDavid van Moolenbroek option->universe = universe;
1266*83ee113eSDavid van Moolenbroek option->code = code;
1267*83ee113eSDavid van Moolenbroek option->format = default_option_format;
1268*83ee113eSDavid van Moolenbroek option_reference(opt, option, MDL);
1269*83ee113eSDavid van Moolenbroek } else
1270*83ee113eSDavid van Moolenbroek log_info("option %s has been redefined as option %s. "
1271*83ee113eSDavid van Moolenbroek "Please update your configs if neccessary.",
1272*83ee113eSDavid van Moolenbroek val, option->name);
1273*83ee113eSDavid van Moolenbroek /* If we've been told to allocate, that means that this
1274*83ee113eSDavid van Moolenbroek * (might) be an option code definition, so we'll create
1275*83ee113eSDavid van Moolenbroek * an option structure and return it for the parent to
1276*83ee113eSDavid van Moolenbroek * decide.
1277*83ee113eSDavid van Moolenbroek */
1278*83ee113eSDavid van Moolenbroek } else if (allocate) {
1279*83ee113eSDavid van Moolenbroek option = new_option(val, MDL);
1280*83ee113eSDavid van Moolenbroek option -> universe = universe;
1281*83ee113eSDavid van Moolenbroek option_reference(opt, option, MDL);
1282*83ee113eSDavid van Moolenbroek } else {
1283*83ee113eSDavid van Moolenbroek parse_warn(cfile, "no option named %s in space %s",
1284*83ee113eSDavid van Moolenbroek val, universe->name);
1285*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1286*83ee113eSDavid van Moolenbroek dfree(uname, MDL);
1287*83ee113eSDavid van Moolenbroek return ISC_R_NOTFOUND;
1288*83ee113eSDavid van Moolenbroek }
1289*83ee113eSDavid van Moolenbroek
1290*83ee113eSDavid van Moolenbroek /* Free the initial identifier token. */
1291*83ee113eSDavid van Moolenbroek dfree (uname, MDL);
1292*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
1293*83ee113eSDavid van Moolenbroek }
1294*83ee113eSDavid van Moolenbroek
1295*83ee113eSDavid van Moolenbroek /* IDENTIFIER [WIDTHS] SEMI
1296*83ee113eSDavid van Moolenbroek * WIDTHS ~= LENGTH WIDTH NUMBER
1297*83ee113eSDavid van Moolenbroek * CODE WIDTH NUMBER
1298*83ee113eSDavid van Moolenbroek */
1299*83ee113eSDavid van Moolenbroek
parse_option_space_decl(cfile)1300*83ee113eSDavid van Moolenbroek void parse_option_space_decl (cfile)
1301*83ee113eSDavid van Moolenbroek struct parse *cfile;
1302*83ee113eSDavid van Moolenbroek {
1303*83ee113eSDavid van Moolenbroek int token;
1304*83ee113eSDavid van Moolenbroek const char *val;
1305*83ee113eSDavid van Moolenbroek struct universe **ua, *nu;
1306*83ee113eSDavid van Moolenbroek char *nu_name;
1307*83ee113eSDavid van Moolenbroek int tsize=1, lsize=1, hsize = 0;
1308*83ee113eSDavid van Moolenbroek
1309*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile); /* Discard the SPACE token,
1310*83ee113eSDavid van Moolenbroek which was checked by the
1311*83ee113eSDavid van Moolenbroek caller. */
1312*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1313*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
1314*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting identifier.");
1315*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1316*83ee113eSDavid van Moolenbroek return;
1317*83ee113eSDavid van Moolenbroek }
1318*83ee113eSDavid van Moolenbroek nu = new_universe (MDL);
1319*83ee113eSDavid van Moolenbroek if (!nu)
1320*83ee113eSDavid van Moolenbroek log_fatal ("No memory for new option space.");
1321*83ee113eSDavid van Moolenbroek
1322*83ee113eSDavid van Moolenbroek /* Set up the server option universe... */
1323*83ee113eSDavid van Moolenbroek nu_name = dmalloc (strlen (val) + 1, MDL);
1324*83ee113eSDavid van Moolenbroek if (!nu_name)
1325*83ee113eSDavid van Moolenbroek log_fatal ("No memory for new option space name.");
1326*83ee113eSDavid van Moolenbroek strcpy (nu_name, val);
1327*83ee113eSDavid van Moolenbroek nu -> name = nu_name;
1328*83ee113eSDavid van Moolenbroek
1329*83ee113eSDavid van Moolenbroek do {
1330*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1331*83ee113eSDavid van Moolenbroek switch(token) {
1332*83ee113eSDavid van Moolenbroek case SEMI:
1333*83ee113eSDavid van Moolenbroek break;
1334*83ee113eSDavid van Moolenbroek
1335*83ee113eSDavid van Moolenbroek case CODE:
1336*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1337*83ee113eSDavid van Moolenbroek if (token != WIDTH) {
1338*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting width token.");
1339*83ee113eSDavid van Moolenbroek goto bad;
1340*83ee113eSDavid van Moolenbroek }
1341*83ee113eSDavid van Moolenbroek
1342*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1343*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1344*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting number 1, 2, 4.");
1345*83ee113eSDavid van Moolenbroek goto bad;
1346*83ee113eSDavid van Moolenbroek }
1347*83ee113eSDavid van Moolenbroek
1348*83ee113eSDavid van Moolenbroek tsize = atoi(val);
1349*83ee113eSDavid van Moolenbroek
1350*83ee113eSDavid van Moolenbroek
1351*83ee113eSDavid van Moolenbroek switch (tsize) {
1352*83ee113eSDavid van Moolenbroek case 1:
1353*83ee113eSDavid van Moolenbroek if (!hsize)
1354*83ee113eSDavid van Moolenbroek hsize = BYTE_NAME_HASH_SIZE;
1355*83ee113eSDavid van Moolenbroek break;
1356*83ee113eSDavid van Moolenbroek case 2:
1357*83ee113eSDavid van Moolenbroek if (!hsize)
1358*83ee113eSDavid van Moolenbroek hsize = WORD_NAME_HASH_SIZE;
1359*83ee113eSDavid van Moolenbroek break;
1360*83ee113eSDavid van Moolenbroek case 4:
1361*83ee113eSDavid van Moolenbroek if (!hsize)
1362*83ee113eSDavid van Moolenbroek hsize = QUAD_NAME_HASH_SIZE;
1363*83ee113eSDavid van Moolenbroek break;
1364*83ee113eSDavid van Moolenbroek default:
1365*83ee113eSDavid van Moolenbroek parse_warn(cfile, "invalid code width (%d), "
1366*83ee113eSDavid van Moolenbroek "expecting a 1, 2 or 4.",
1367*83ee113eSDavid van Moolenbroek tsize);
1368*83ee113eSDavid van Moolenbroek goto bad;
1369*83ee113eSDavid van Moolenbroek }
1370*83ee113eSDavid van Moolenbroek break;
1371*83ee113eSDavid van Moolenbroek
1372*83ee113eSDavid van Moolenbroek case LENGTH:
1373*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1374*83ee113eSDavid van Moolenbroek if (token != WIDTH) {
1375*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting width token.");
1376*83ee113eSDavid van Moolenbroek goto bad;
1377*83ee113eSDavid van Moolenbroek }
1378*83ee113eSDavid van Moolenbroek
1379*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1380*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1381*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting number 1 or 2.");
1382*83ee113eSDavid van Moolenbroek goto bad;
1383*83ee113eSDavid van Moolenbroek }
1384*83ee113eSDavid van Moolenbroek
1385*83ee113eSDavid van Moolenbroek lsize = atoi(val);
1386*83ee113eSDavid van Moolenbroek if (lsize != 1 && lsize != 2) {
1387*83ee113eSDavid van Moolenbroek parse_warn(cfile, "invalid length width (%d) "
1388*83ee113eSDavid van Moolenbroek "expecting 1 or 2.", lsize);
1389*83ee113eSDavid van Moolenbroek goto bad;
1390*83ee113eSDavid van Moolenbroek }
1391*83ee113eSDavid van Moolenbroek
1392*83ee113eSDavid van Moolenbroek break;
1393*83ee113eSDavid van Moolenbroek
1394*83ee113eSDavid van Moolenbroek case HASH:
1395*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1396*83ee113eSDavid van Moolenbroek if (token != SIZE) {
1397*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting size token.");
1398*83ee113eSDavid van Moolenbroek goto bad;
1399*83ee113eSDavid van Moolenbroek }
1400*83ee113eSDavid van Moolenbroek
1401*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
1402*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1403*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting a 10base number");
1404*83ee113eSDavid van Moolenbroek goto bad;
1405*83ee113eSDavid van Moolenbroek }
1406*83ee113eSDavid van Moolenbroek
1407*83ee113eSDavid van Moolenbroek /* (2^31)-1 is the highest Mersenne prime we should
1408*83ee113eSDavid van Moolenbroek * probably allow...
1409*83ee113eSDavid van Moolenbroek */
1410*83ee113eSDavid van Moolenbroek hsize = atoi(val);
1411*83ee113eSDavid van Moolenbroek if (hsize < 0 || hsize > 0x7FFFFFFF) {
1412*83ee113eSDavid van Moolenbroek parse_warn(cfile, "invalid hash length: %d",
1413*83ee113eSDavid van Moolenbroek hsize);
1414*83ee113eSDavid van Moolenbroek goto bad;
1415*83ee113eSDavid van Moolenbroek }
1416*83ee113eSDavid van Moolenbroek
1417*83ee113eSDavid van Moolenbroek break;
1418*83ee113eSDavid van Moolenbroek
1419*83ee113eSDavid van Moolenbroek default:
1420*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Unexpected token.");
1421*83ee113eSDavid van Moolenbroek }
1422*83ee113eSDavid van Moolenbroek } while (token != SEMI);
1423*83ee113eSDavid van Moolenbroek
1424*83ee113eSDavid van Moolenbroek if (!hsize)
1425*83ee113eSDavid van Moolenbroek hsize = DEFAULT_SPACE_HASH_SIZE;
1426*83ee113eSDavid van Moolenbroek
1427*83ee113eSDavid van Moolenbroek nu -> lookup_func = lookup_hashed_option;
1428*83ee113eSDavid van Moolenbroek nu -> option_state_dereference = hashed_option_state_dereference;
1429*83ee113eSDavid van Moolenbroek nu -> foreach = hashed_option_space_foreach;
1430*83ee113eSDavid van Moolenbroek nu -> save_func = save_hashed_option;
1431*83ee113eSDavid van Moolenbroek nu -> delete_func = delete_hashed_option;
1432*83ee113eSDavid van Moolenbroek nu -> encapsulate = hashed_option_space_encapsulate;
1433*83ee113eSDavid van Moolenbroek nu -> decode = parse_option_buffer;
1434*83ee113eSDavid van Moolenbroek nu -> length_size = lsize;
1435*83ee113eSDavid van Moolenbroek nu -> tag_size = tsize;
1436*83ee113eSDavid van Moolenbroek switch(tsize) {
1437*83ee113eSDavid van Moolenbroek case 1:
1438*83ee113eSDavid van Moolenbroek nu->get_tag = getUChar;
1439*83ee113eSDavid van Moolenbroek nu->store_tag = putUChar;
1440*83ee113eSDavid van Moolenbroek break;
1441*83ee113eSDavid van Moolenbroek case 2:
1442*83ee113eSDavid van Moolenbroek nu->get_tag = getUShort;
1443*83ee113eSDavid van Moolenbroek nu->store_tag = putUShort;
1444*83ee113eSDavid van Moolenbroek break;
1445*83ee113eSDavid van Moolenbroek case 4:
1446*83ee113eSDavid van Moolenbroek nu->get_tag = getULong;
1447*83ee113eSDavid van Moolenbroek nu->store_tag = putULong;
1448*83ee113eSDavid van Moolenbroek break;
1449*83ee113eSDavid van Moolenbroek default:
1450*83ee113eSDavid van Moolenbroek log_fatal("Impossible condition at %s:%d.", MDL);
1451*83ee113eSDavid van Moolenbroek }
1452*83ee113eSDavid van Moolenbroek switch(lsize) {
1453*83ee113eSDavid van Moolenbroek case 0:
1454*83ee113eSDavid van Moolenbroek nu->get_length = NULL;
1455*83ee113eSDavid van Moolenbroek nu->store_length = NULL;
1456*83ee113eSDavid van Moolenbroek break;
1457*83ee113eSDavid van Moolenbroek case 1:
1458*83ee113eSDavid van Moolenbroek nu->get_length = getUChar;
1459*83ee113eSDavid van Moolenbroek nu->store_length = putUChar;
1460*83ee113eSDavid van Moolenbroek break;
1461*83ee113eSDavid van Moolenbroek case 2:
1462*83ee113eSDavid van Moolenbroek nu->get_length = getUShort;
1463*83ee113eSDavid van Moolenbroek nu->store_length = putUShort;
1464*83ee113eSDavid van Moolenbroek break;
1465*83ee113eSDavid van Moolenbroek default:
1466*83ee113eSDavid van Moolenbroek log_fatal("Impossible condition at %s:%d.", MDL);
1467*83ee113eSDavid van Moolenbroek }
1468*83ee113eSDavid van Moolenbroek nu -> index = universe_count++;
1469*83ee113eSDavid van Moolenbroek if (nu -> index >= universe_max) {
1470*83ee113eSDavid van Moolenbroek ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
1471*83ee113eSDavid van Moolenbroek if (!ua)
1472*83ee113eSDavid van Moolenbroek log_fatal ("No memory to expand option space array.");
1473*83ee113eSDavid van Moolenbroek memcpy (ua, universes, universe_max * sizeof *ua);
1474*83ee113eSDavid van Moolenbroek universe_max *= 2;
1475*83ee113eSDavid van Moolenbroek dfree (universes, MDL);
1476*83ee113eSDavid van Moolenbroek universes = ua;
1477*83ee113eSDavid van Moolenbroek }
1478*83ee113eSDavid van Moolenbroek universes [nu -> index] = nu;
1479*83ee113eSDavid van Moolenbroek if (!option_name_new_hash(&nu->name_hash, hsize, MDL) ||
1480*83ee113eSDavid van Moolenbroek !option_code_new_hash(&nu->code_hash, hsize, MDL))
1481*83ee113eSDavid van Moolenbroek log_fatal("Can't allocate %s option hash table.", nu->name);
1482*83ee113eSDavid van Moolenbroek universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
1483*83ee113eSDavid van Moolenbroek return;
1484*83ee113eSDavid van Moolenbroek
1485*83ee113eSDavid van Moolenbroek bad:
1486*83ee113eSDavid van Moolenbroek dfree(nu_name, MDL);
1487*83ee113eSDavid van Moolenbroek dfree(nu, MDL);
1488*83ee113eSDavid van Moolenbroek }
1489*83ee113eSDavid van Moolenbroek
1490*83ee113eSDavid van Moolenbroek /* This is faked up to look good right now. Ideally, this should do a
1491*83ee113eSDavid van Moolenbroek recursive parse and allow arbitrary data structure definitions, but for
1492*83ee113eSDavid van Moolenbroek now it just allows you to specify a single type, an array of single types,
1493*83ee113eSDavid van Moolenbroek a sequence of types, or an array of sequences of types.
1494*83ee113eSDavid van Moolenbroek
1495*83ee113eSDavid van Moolenbroek ocd :== NUMBER EQUALS ocsd SEMI
1496*83ee113eSDavid van Moolenbroek
1497*83ee113eSDavid van Moolenbroek ocsd :== ocsd_type |
1498*83ee113eSDavid van Moolenbroek ocsd_type_sequence |
1499*83ee113eSDavid van Moolenbroek ARRAY OF ocsd_simple_type_sequence
1500*83ee113eSDavid van Moolenbroek
1501*83ee113eSDavid van Moolenbroek ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1502*83ee113eSDavid van Moolenbroek
1503*83ee113eSDavid van Moolenbroek ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1504*83ee113eSDavid van Moolenbroek
1505*83ee113eSDavid van Moolenbroek ocsd_types :== ocsd_type |
1506*83ee113eSDavid van Moolenbroek ocsd_types ocsd_type
1507*83ee113eSDavid van Moolenbroek
1508*83ee113eSDavid van Moolenbroek ocsd_type :== ocsd_simple_type |
1509*83ee113eSDavid van Moolenbroek ARRAY OF ocsd_simple_type
1510*83ee113eSDavid van Moolenbroek
1511*83ee113eSDavid van Moolenbroek ocsd_simple_types :== ocsd_simple_type |
1512*83ee113eSDavid van Moolenbroek ocsd_simple_types ocsd_simple_type
1513*83ee113eSDavid van Moolenbroek
1514*83ee113eSDavid van Moolenbroek ocsd_simple_type :== BOOLEAN |
1515*83ee113eSDavid van Moolenbroek INTEGER NUMBER |
1516*83ee113eSDavid van Moolenbroek SIGNED INTEGER NUMBER |
1517*83ee113eSDavid van Moolenbroek UNSIGNED INTEGER NUMBER |
1518*83ee113eSDavid van Moolenbroek IP-ADDRESS |
1519*83ee113eSDavid van Moolenbroek TEXT |
1520*83ee113eSDavid van Moolenbroek STRING |
1521*83ee113eSDavid van Moolenbroek ENCAPSULATE identifier */
1522*83ee113eSDavid van Moolenbroek
parse_option_code_definition(cfile,option)1523*83ee113eSDavid van Moolenbroek int parse_option_code_definition (cfile, option)
1524*83ee113eSDavid van Moolenbroek struct parse *cfile;
1525*83ee113eSDavid van Moolenbroek struct option *option;
1526*83ee113eSDavid van Moolenbroek {
1527*83ee113eSDavid van Moolenbroek const char *val;
1528*83ee113eSDavid van Moolenbroek enum dhcp_token token;
1529*83ee113eSDavid van Moolenbroek struct option *oldopt;
1530*83ee113eSDavid van Moolenbroek unsigned arrayp = 0;
1531*83ee113eSDavid van Moolenbroek int recordp = 0;
1532*83ee113eSDavid van Moolenbroek int no_more_in_record = 0;
1533*83ee113eSDavid van Moolenbroek char tokbuf [128];
1534*83ee113eSDavid van Moolenbroek unsigned tokix = 0;
1535*83ee113eSDavid van Moolenbroek char type;
1536*83ee113eSDavid van Moolenbroek int is_signed;
1537*83ee113eSDavid van Moolenbroek char *s;
1538*83ee113eSDavid van Moolenbroek int has_encapsulation = 0;
1539*83ee113eSDavid van Moolenbroek struct universe *encapsulated;
1540*83ee113eSDavid van Moolenbroek
1541*83ee113eSDavid van Moolenbroek /* Parse the option code. */
1542*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1543*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1544*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting option code number.");
1545*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1546*83ee113eSDavid van Moolenbroek return 0;
1547*83ee113eSDavid van Moolenbroek }
1548*83ee113eSDavid van Moolenbroek option -> code = atoi (val);
1549*83ee113eSDavid van Moolenbroek
1550*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1551*83ee113eSDavid van Moolenbroek if (token != EQUAL) {
1552*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting \"=\"");
1553*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1554*83ee113eSDavid van Moolenbroek return 0;
1555*83ee113eSDavid van Moolenbroek }
1556*83ee113eSDavid van Moolenbroek
1557*83ee113eSDavid van Moolenbroek /* See if this is an array. */
1558*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1559*83ee113eSDavid van Moolenbroek if (token == ARRAY) {
1560*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1561*83ee113eSDavid van Moolenbroek if (token != OF) {
1562*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting \"of\".");
1563*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1564*83ee113eSDavid van Moolenbroek return 0;
1565*83ee113eSDavid van Moolenbroek }
1566*83ee113eSDavid van Moolenbroek arrayp = 1;
1567*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1568*83ee113eSDavid van Moolenbroek }
1569*83ee113eSDavid van Moolenbroek
1570*83ee113eSDavid van Moolenbroek if (token == LBRACE) {
1571*83ee113eSDavid van Moolenbroek recordp = 1;
1572*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1573*83ee113eSDavid van Moolenbroek }
1574*83ee113eSDavid van Moolenbroek
1575*83ee113eSDavid van Moolenbroek /* At this point we're expecting a data type. */
1576*83ee113eSDavid van Moolenbroek next_type:
1577*83ee113eSDavid van Moolenbroek if (has_encapsulation) {
1578*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1579*83ee113eSDavid van Moolenbroek "encapsulate must always be the last item.");
1580*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1581*83ee113eSDavid van Moolenbroek return 0;
1582*83ee113eSDavid van Moolenbroek }
1583*83ee113eSDavid van Moolenbroek
1584*83ee113eSDavid van Moolenbroek switch (token) {
1585*83ee113eSDavid van Moolenbroek case ARRAY:
1586*83ee113eSDavid van Moolenbroek if (arrayp) {
1587*83ee113eSDavid van Moolenbroek parse_warn (cfile, "no nested arrays.");
1588*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1589*83ee113eSDavid van Moolenbroek if (recordp)
1590*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1591*83ee113eSDavid van Moolenbroek return 0;
1592*83ee113eSDavid van Moolenbroek }
1593*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1594*83ee113eSDavid van Moolenbroek if (token != OF) {
1595*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting \"of\".");
1596*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1597*83ee113eSDavid van Moolenbroek return 0;
1598*83ee113eSDavid van Moolenbroek }
1599*83ee113eSDavid van Moolenbroek arrayp = recordp + 1;
1600*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1601*83ee113eSDavid van Moolenbroek if ((recordp) && (token == LBRACE)) {
1602*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1603*83ee113eSDavid van Moolenbroek "only uniform array inside record.");
1604*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp + 1);
1605*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1606*83ee113eSDavid van Moolenbroek return 0;
1607*83ee113eSDavid van Moolenbroek }
1608*83ee113eSDavid van Moolenbroek goto next_type;
1609*83ee113eSDavid van Moolenbroek case BOOLEAN:
1610*83ee113eSDavid van Moolenbroek type = 'f';
1611*83ee113eSDavid van Moolenbroek break;
1612*83ee113eSDavid van Moolenbroek case INTEGER:
1613*83ee113eSDavid van Moolenbroek is_signed = 1;
1614*83ee113eSDavid van Moolenbroek parse_integer:
1615*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1616*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
1617*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting number.");
1618*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1619*83ee113eSDavid van Moolenbroek if (recordp)
1620*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1621*83ee113eSDavid van Moolenbroek return 0;
1622*83ee113eSDavid van Moolenbroek }
1623*83ee113eSDavid van Moolenbroek switch (atoi (val)) {
1624*83ee113eSDavid van Moolenbroek case 8:
1625*83ee113eSDavid van Moolenbroek type = is_signed ? 'b' : 'B';
1626*83ee113eSDavid van Moolenbroek break;
1627*83ee113eSDavid van Moolenbroek case 16:
1628*83ee113eSDavid van Moolenbroek type = is_signed ? 's' : 'S';
1629*83ee113eSDavid van Moolenbroek break;
1630*83ee113eSDavid van Moolenbroek case 32:
1631*83ee113eSDavid van Moolenbroek type = is_signed ? 'l' : 'L';
1632*83ee113eSDavid van Moolenbroek break;
1633*83ee113eSDavid van Moolenbroek default:
1634*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1635*83ee113eSDavid van Moolenbroek "%s bit precision is not supported.", val);
1636*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1637*83ee113eSDavid van Moolenbroek if (recordp)
1638*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1639*83ee113eSDavid van Moolenbroek return 0;
1640*83ee113eSDavid van Moolenbroek }
1641*83ee113eSDavid van Moolenbroek break;
1642*83ee113eSDavid van Moolenbroek case SIGNED:
1643*83ee113eSDavid van Moolenbroek is_signed = 1;
1644*83ee113eSDavid van Moolenbroek parse_signed:
1645*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1646*83ee113eSDavid van Moolenbroek if (token != INTEGER) {
1647*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting \"integer\" keyword.");
1648*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1649*83ee113eSDavid van Moolenbroek if (recordp)
1650*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1651*83ee113eSDavid van Moolenbroek return 0;
1652*83ee113eSDavid van Moolenbroek }
1653*83ee113eSDavid van Moolenbroek goto parse_integer;
1654*83ee113eSDavid van Moolenbroek case UNSIGNED:
1655*83ee113eSDavid van Moolenbroek is_signed = 0;
1656*83ee113eSDavid van Moolenbroek goto parse_signed;
1657*83ee113eSDavid van Moolenbroek
1658*83ee113eSDavid van Moolenbroek case IP_ADDRESS:
1659*83ee113eSDavid van Moolenbroek type = 'I';
1660*83ee113eSDavid van Moolenbroek break;
1661*83ee113eSDavid van Moolenbroek case IP6_ADDRESS:
1662*83ee113eSDavid van Moolenbroek type = '6';
1663*83ee113eSDavid van Moolenbroek break;
1664*83ee113eSDavid van Moolenbroek case DOMAIN_NAME:
1665*83ee113eSDavid van Moolenbroek type = 'd';
1666*83ee113eSDavid van Moolenbroek goto no_arrays;
1667*83ee113eSDavid van Moolenbroek case DOMAIN_LIST:
1668*83ee113eSDavid van Moolenbroek /* Consume optional compression indicator. */
1669*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
1670*83ee113eSDavid van Moolenbroek if (token == COMPRESSED) {
1671*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
1672*83ee113eSDavid van Moolenbroek tokbuf[tokix++] = 'D';
1673*83ee113eSDavid van Moolenbroek type = 'c';
1674*83ee113eSDavid van Moolenbroek } else
1675*83ee113eSDavid van Moolenbroek type = 'D';
1676*83ee113eSDavid van Moolenbroek goto no_arrays;
1677*83ee113eSDavid van Moolenbroek case TEXT:
1678*83ee113eSDavid van Moolenbroek type = 't';
1679*83ee113eSDavid van Moolenbroek no_arrays:
1680*83ee113eSDavid van Moolenbroek if (arrayp) {
1681*83ee113eSDavid van Moolenbroek parse_warn (cfile, "arrays of text strings not %s",
1682*83ee113eSDavid van Moolenbroek "yet supported.");
1683*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1684*83ee113eSDavid van Moolenbroek if (recordp)
1685*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1686*83ee113eSDavid van Moolenbroek return 0;
1687*83ee113eSDavid van Moolenbroek }
1688*83ee113eSDavid van Moolenbroek no_more_in_record = 1;
1689*83ee113eSDavid van Moolenbroek break;
1690*83ee113eSDavid van Moolenbroek case STRING_TOKEN:
1691*83ee113eSDavid van Moolenbroek type = 'X';
1692*83ee113eSDavid van Moolenbroek goto no_arrays;
1693*83ee113eSDavid van Moolenbroek
1694*83ee113eSDavid van Moolenbroek case ENCAPSULATE:
1695*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1696*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
1697*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1698*83ee113eSDavid van Moolenbroek "expecting option space identifier");
1699*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1700*83ee113eSDavid van Moolenbroek return 0;
1701*83ee113eSDavid van Moolenbroek }
1702*83ee113eSDavid van Moolenbroek encapsulated = NULL;
1703*83ee113eSDavid van Moolenbroek if (!universe_hash_lookup(&encapsulated, universe_hash,
1704*83ee113eSDavid van Moolenbroek val, strlen(val), MDL)) {
1705*83ee113eSDavid van Moolenbroek parse_warn(cfile, "unknown option space %s", val);
1706*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1707*83ee113eSDavid van Moolenbroek return 0;
1708*83ee113eSDavid van Moolenbroek }
1709*83ee113eSDavid van Moolenbroek if (strlen (val) + tokix + 2 > sizeof (tokbuf))
1710*83ee113eSDavid van Moolenbroek goto toobig;
1711*83ee113eSDavid van Moolenbroek tokbuf [tokix++] = 'E';
1712*83ee113eSDavid van Moolenbroek strcpy (&tokbuf [tokix], val);
1713*83ee113eSDavid van Moolenbroek tokix += strlen (val);
1714*83ee113eSDavid van Moolenbroek type = '.';
1715*83ee113eSDavid van Moolenbroek has_encapsulation = 1;
1716*83ee113eSDavid van Moolenbroek break;
1717*83ee113eSDavid van Moolenbroek
1718*83ee113eSDavid van Moolenbroek case ZEROLEN:
1719*83ee113eSDavid van Moolenbroek type = 'Z';
1720*83ee113eSDavid van Moolenbroek if (arrayp) {
1721*83ee113eSDavid van Moolenbroek parse_warn (cfile, "array incompatible with zerolen.");
1722*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1723*83ee113eSDavid van Moolenbroek if (recordp)
1724*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1725*83ee113eSDavid van Moolenbroek return 0;
1726*83ee113eSDavid van Moolenbroek }
1727*83ee113eSDavid van Moolenbroek no_more_in_record = 1;
1728*83ee113eSDavid van Moolenbroek break;
1729*83ee113eSDavid van Moolenbroek
1730*83ee113eSDavid van Moolenbroek default:
1731*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unknown data type %s", val);
1732*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1733*83ee113eSDavid van Moolenbroek if (recordp)
1734*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1735*83ee113eSDavid van Moolenbroek return 0;
1736*83ee113eSDavid van Moolenbroek }
1737*83ee113eSDavid van Moolenbroek
1738*83ee113eSDavid van Moolenbroek if (tokix == sizeof tokbuf) {
1739*83ee113eSDavid van Moolenbroek toobig:
1740*83ee113eSDavid van Moolenbroek parse_warn (cfile, "too many types in record.");
1741*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, recordp);
1742*83ee113eSDavid van Moolenbroek if (recordp)
1743*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1744*83ee113eSDavid van Moolenbroek return 0;
1745*83ee113eSDavid van Moolenbroek }
1746*83ee113eSDavid van Moolenbroek tokbuf [tokix++] = type;
1747*83ee113eSDavid van Moolenbroek
1748*83ee113eSDavid van Moolenbroek if (recordp) {
1749*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1750*83ee113eSDavid van Moolenbroek if (arrayp > recordp) {
1751*83ee113eSDavid van Moolenbroek if (tokix == sizeof tokbuf) {
1752*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1753*83ee113eSDavid van Moolenbroek "too many types in record.");
1754*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 1);
1755*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1756*83ee113eSDavid van Moolenbroek return 0;
1757*83ee113eSDavid van Moolenbroek }
1758*83ee113eSDavid van Moolenbroek arrayp = 0;
1759*83ee113eSDavid van Moolenbroek tokbuf[tokix++] = 'a';
1760*83ee113eSDavid van Moolenbroek }
1761*83ee113eSDavid van Moolenbroek if (token == COMMA) {
1762*83ee113eSDavid van Moolenbroek if (no_more_in_record) {
1763*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1764*83ee113eSDavid van Moolenbroek "%s must be at end of record.",
1765*83ee113eSDavid van Moolenbroek type == 't' ? "text" : "string");
1766*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 1);
1767*83ee113eSDavid van Moolenbroek if (recordp)
1768*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1769*83ee113eSDavid van Moolenbroek return 0;
1770*83ee113eSDavid van Moolenbroek }
1771*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
1772*83ee113eSDavid van Moolenbroek goto next_type;
1773*83ee113eSDavid van Moolenbroek }
1774*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
1775*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting right brace.");
1776*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 1);
1777*83ee113eSDavid van Moolenbroek if (recordp)
1778*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1779*83ee113eSDavid van Moolenbroek return 0;
1780*83ee113eSDavid van Moolenbroek }
1781*83ee113eSDavid van Moolenbroek }
1782*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
1783*83ee113eSDavid van Moolenbroek parse_warn (cfile, "semicolon expected.");
1784*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1785*83ee113eSDavid van Moolenbroek if (recordp)
1786*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
1787*83ee113eSDavid van Moolenbroek return 0;
1788*83ee113eSDavid van Moolenbroek }
1789*83ee113eSDavid van Moolenbroek if (has_encapsulation && arrayp) {
1790*83ee113eSDavid van Moolenbroek parse_warn (cfile,
1791*83ee113eSDavid van Moolenbroek "Arrays of encapsulations don't make sense.");
1792*83ee113eSDavid van Moolenbroek return 0;
1793*83ee113eSDavid van Moolenbroek }
1794*83ee113eSDavid van Moolenbroek s = dmalloc(tokix + (arrayp ? 1 : 0) + 1, MDL);
1795*83ee113eSDavid van Moolenbroek if (s == NULL) {
1796*83ee113eSDavid van Moolenbroek log_fatal("no memory for option format.");
1797*83ee113eSDavid van Moolenbroek }
1798*83ee113eSDavid van Moolenbroek memcpy(s, tokbuf, tokix);
1799*83ee113eSDavid van Moolenbroek if (arrayp) {
1800*83ee113eSDavid van Moolenbroek s[tokix++] = (arrayp > recordp) ? 'a' : 'A';
1801*83ee113eSDavid van Moolenbroek }
1802*83ee113eSDavid van Moolenbroek s[tokix] = '\0';
1803*83ee113eSDavid van Moolenbroek
1804*83ee113eSDavid van Moolenbroek option -> format = s;
1805*83ee113eSDavid van Moolenbroek
1806*83ee113eSDavid van Moolenbroek oldopt = NULL;
1807*83ee113eSDavid van Moolenbroek option_code_hash_lookup(&oldopt, option->universe->code_hash,
1808*83ee113eSDavid van Moolenbroek &option->code, 0, MDL);
1809*83ee113eSDavid van Moolenbroek if (oldopt != NULL) {
1810*83ee113eSDavid van Moolenbroek /*
1811*83ee113eSDavid van Moolenbroek * XXX: This illegalizes a configuration syntax that was
1812*83ee113eSDavid van Moolenbroek * valid in 3.0.x, where multiple name->code mappings are
1813*83ee113eSDavid van Moolenbroek * given, but only one code->name mapping survives. It is
1814*83ee113eSDavid van Moolenbroek * unclear what can or should be done at this point, but it
1815*83ee113eSDavid van Moolenbroek * seems best to retain 3.0.x behaviour for upgrades to go
1816*83ee113eSDavid van Moolenbroek * smoothly.
1817*83ee113eSDavid van Moolenbroek *
1818*83ee113eSDavid van Moolenbroek option_name_hash_delete(option->universe->name_hash,
1819*83ee113eSDavid van Moolenbroek oldopt->name, 0, MDL);
1820*83ee113eSDavid van Moolenbroek */
1821*83ee113eSDavid van Moolenbroek option_code_hash_delete(option->universe->code_hash,
1822*83ee113eSDavid van Moolenbroek &oldopt->code, 0, MDL);
1823*83ee113eSDavid van Moolenbroek
1824*83ee113eSDavid van Moolenbroek option_dereference(&oldopt, MDL);
1825*83ee113eSDavid van Moolenbroek }
1826*83ee113eSDavid van Moolenbroek option_code_hash_add(option->universe->code_hash, &option->code, 0,
1827*83ee113eSDavid van Moolenbroek option, MDL);
1828*83ee113eSDavid van Moolenbroek option_name_hash_add(option->universe->name_hash, option->name, 0,
1829*83ee113eSDavid van Moolenbroek option, MDL);
1830*83ee113eSDavid van Moolenbroek if (has_encapsulation) {
1831*83ee113eSDavid van Moolenbroek /* INSIST(tokbuf[0] == 'E'); */
1832*83ee113eSDavid van Moolenbroek /* INSIST(encapsulated != NULL); */
1833*83ee113eSDavid van Moolenbroek if (!option_code_hash_lookup(&encapsulated->enc_opt,
1834*83ee113eSDavid van Moolenbroek option->universe->code_hash,
1835*83ee113eSDavid van Moolenbroek &option->code, 0, MDL)) {
1836*83ee113eSDavid van Moolenbroek log_fatal("error finding encapsulated option (%s:%d)",
1837*83ee113eSDavid van Moolenbroek MDL);
1838*83ee113eSDavid van Moolenbroek }
1839*83ee113eSDavid van Moolenbroek }
1840*83ee113eSDavid van Moolenbroek return 1;
1841*83ee113eSDavid van Moolenbroek }
1842*83ee113eSDavid van Moolenbroek
1843*83ee113eSDavid van Moolenbroek /*
1844*83ee113eSDavid van Moolenbroek * base64 :== NUMBER_OR_STRING
1845*83ee113eSDavid van Moolenbroek */
1846*83ee113eSDavid van Moolenbroek
parse_base64(data,cfile)1847*83ee113eSDavid van Moolenbroek int parse_base64 (data, cfile)
1848*83ee113eSDavid van Moolenbroek struct data_string *data;
1849*83ee113eSDavid van Moolenbroek struct parse *cfile;
1850*83ee113eSDavid van Moolenbroek {
1851*83ee113eSDavid van Moolenbroek const char *val;
1852*83ee113eSDavid van Moolenbroek int i, j, k;
1853*83ee113eSDavid van Moolenbroek unsigned acc = 0;
1854*83ee113eSDavid van Moolenbroek static unsigned char
1855*83ee113eSDavid van Moolenbroek from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1856*83ee113eSDavid van Moolenbroek 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1857*83ee113eSDavid van Moolenbroek 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1858*83ee113eSDavid van Moolenbroek 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1859*83ee113eSDavid van Moolenbroek 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1860*83ee113eSDavid van Moolenbroek 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1861*83ee113eSDavid van Moolenbroek 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1862*83ee113eSDavid van Moolenbroek 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1863*83ee113eSDavid van Moolenbroek 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1864*83ee113eSDavid van Moolenbroek 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1865*83ee113eSDavid van Moolenbroek 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1866*83ee113eSDavid van Moolenbroek 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1867*83ee113eSDavid van Moolenbroek struct string_list *bufs = NULL,
1868*83ee113eSDavid van Moolenbroek *last = NULL,
1869*83ee113eSDavid van Moolenbroek *t;
1870*83ee113eSDavid van Moolenbroek int cc = 0;
1871*83ee113eSDavid van Moolenbroek int terminated = 0;
1872*83ee113eSDavid van Moolenbroek int valid_base64;
1873*83ee113eSDavid van Moolenbroek
1874*83ee113eSDavid van Moolenbroek /* It's possible for a + or a / to cause a base64 quantity to be
1875*83ee113eSDavid van Moolenbroek tokenized into more than one token, so we have to parse them all
1876*83ee113eSDavid van Moolenbroek in before decoding. */
1877*83ee113eSDavid van Moolenbroek do {
1878*83ee113eSDavid van Moolenbroek unsigned l;
1879*83ee113eSDavid van Moolenbroek
1880*83ee113eSDavid van Moolenbroek (void)next_token(&val, &l, cfile);
1881*83ee113eSDavid van Moolenbroek t = dmalloc(l + sizeof(*t), MDL);
1882*83ee113eSDavid van Moolenbroek if (t == NULL)
1883*83ee113eSDavid van Moolenbroek log_fatal("no memory for base64 buffer.");
1884*83ee113eSDavid van Moolenbroek memset(t, 0, (sizeof(*t)) - 1);
1885*83ee113eSDavid van Moolenbroek memcpy(t->string, val, l + 1);
1886*83ee113eSDavid van Moolenbroek cc += l;
1887*83ee113eSDavid van Moolenbroek if (last)
1888*83ee113eSDavid van Moolenbroek last->next = t;
1889*83ee113eSDavid van Moolenbroek else
1890*83ee113eSDavid van Moolenbroek bufs = t;
1891*83ee113eSDavid van Moolenbroek last = t;
1892*83ee113eSDavid van Moolenbroek (void)peek_token(&val, NULL, cfile);
1893*83ee113eSDavid van Moolenbroek valid_base64 = 1;
1894*83ee113eSDavid van Moolenbroek for (i = 0; val[i]; i++) {
1895*83ee113eSDavid van Moolenbroek /* Check to see if the character is valid. It
1896*83ee113eSDavid van Moolenbroek may be out of range or within the right range
1897*83ee113eSDavid van Moolenbroek but not used in the mapping */
1898*83ee113eSDavid van Moolenbroek if (((val[i] < ' ') || (val[i] > 'z')) ||
1899*83ee113eSDavid van Moolenbroek ((from64[val[i] - ' '] > 63) && (val[i] != '='))) {
1900*83ee113eSDavid van Moolenbroek valid_base64 = 0;
1901*83ee113eSDavid van Moolenbroek break; /* no need to continue for loop */
1902*83ee113eSDavid van Moolenbroek }
1903*83ee113eSDavid van Moolenbroek }
1904*83ee113eSDavid van Moolenbroek } while (valid_base64);
1905*83ee113eSDavid van Moolenbroek
1906*83ee113eSDavid van Moolenbroek data->len = cc;
1907*83ee113eSDavid van Moolenbroek data->len = (data->len * 3) / 4;
1908*83ee113eSDavid van Moolenbroek if (!buffer_allocate(&data->buffer, data->len, MDL)) {
1909*83ee113eSDavid van Moolenbroek parse_warn (cfile, "can't allocate buffer for base64 data.");
1910*83ee113eSDavid van Moolenbroek data->len = 0;
1911*83ee113eSDavid van Moolenbroek data->data = NULL;
1912*83ee113eSDavid van Moolenbroek goto out;
1913*83ee113eSDavid van Moolenbroek }
1914*83ee113eSDavid van Moolenbroek
1915*83ee113eSDavid van Moolenbroek j = k = 0;
1916*83ee113eSDavid van Moolenbroek for (t = bufs; t; t = t->next) {
1917*83ee113eSDavid van Moolenbroek for (i = 0; t->string[i]; i++) {
1918*83ee113eSDavid van Moolenbroek unsigned foo = t->string[i];
1919*83ee113eSDavid van Moolenbroek if (terminated && foo != '=') {
1920*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1921*83ee113eSDavid van Moolenbroek "stuff after base64 '=' terminator: %s.",
1922*83ee113eSDavid van Moolenbroek &t->string[i]);
1923*83ee113eSDavid van Moolenbroek goto bad;
1924*83ee113eSDavid van Moolenbroek }
1925*83ee113eSDavid van Moolenbroek if ((foo < ' ') || (foo > 'z')) {
1926*83ee113eSDavid van Moolenbroek bad64:
1927*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1928*83ee113eSDavid van Moolenbroek "invalid base64 character %d.",
1929*83ee113eSDavid van Moolenbroek t->string[i]);
1930*83ee113eSDavid van Moolenbroek bad:
1931*83ee113eSDavid van Moolenbroek data_string_forget(data, MDL);
1932*83ee113eSDavid van Moolenbroek goto out;
1933*83ee113eSDavid van Moolenbroek }
1934*83ee113eSDavid van Moolenbroek if (foo == '=')
1935*83ee113eSDavid van Moolenbroek terminated = 1;
1936*83ee113eSDavid van Moolenbroek else {
1937*83ee113eSDavid van Moolenbroek foo = from64[foo - ' '];
1938*83ee113eSDavid van Moolenbroek if (foo == 64)
1939*83ee113eSDavid van Moolenbroek goto bad64;
1940*83ee113eSDavid van Moolenbroek acc = (acc << 6) + foo;
1941*83ee113eSDavid van Moolenbroek switch (k % 4) {
1942*83ee113eSDavid van Moolenbroek case 0:
1943*83ee113eSDavid van Moolenbroek break;
1944*83ee113eSDavid van Moolenbroek case 1:
1945*83ee113eSDavid van Moolenbroek data->buffer->data[j++] = (acc >> 4);
1946*83ee113eSDavid van Moolenbroek acc = acc & 0x0f;
1947*83ee113eSDavid van Moolenbroek break;
1948*83ee113eSDavid van Moolenbroek
1949*83ee113eSDavid van Moolenbroek case 2:
1950*83ee113eSDavid van Moolenbroek data->buffer->data[j++] = (acc >> 2);
1951*83ee113eSDavid van Moolenbroek acc = acc & 0x03;
1952*83ee113eSDavid van Moolenbroek break;
1953*83ee113eSDavid van Moolenbroek case 3:
1954*83ee113eSDavid van Moolenbroek data->buffer->data[j++] = acc;
1955*83ee113eSDavid van Moolenbroek acc = 0;
1956*83ee113eSDavid van Moolenbroek break;
1957*83ee113eSDavid van Moolenbroek }
1958*83ee113eSDavid van Moolenbroek }
1959*83ee113eSDavid van Moolenbroek k++;
1960*83ee113eSDavid van Moolenbroek }
1961*83ee113eSDavid van Moolenbroek }
1962*83ee113eSDavid van Moolenbroek if (k % 4) {
1963*83ee113eSDavid van Moolenbroek if (acc) {
1964*83ee113eSDavid van Moolenbroek parse_warn(cfile,
1965*83ee113eSDavid van Moolenbroek "partial base64 value left over: %d.",
1966*83ee113eSDavid van Moolenbroek acc);
1967*83ee113eSDavid van Moolenbroek }
1968*83ee113eSDavid van Moolenbroek }
1969*83ee113eSDavid van Moolenbroek data->len = j;
1970*83ee113eSDavid van Moolenbroek data->data = data->buffer->data;
1971*83ee113eSDavid van Moolenbroek out:
1972*83ee113eSDavid van Moolenbroek for (t = bufs; t; t = last) {
1973*83ee113eSDavid van Moolenbroek last = t->next;
1974*83ee113eSDavid van Moolenbroek dfree(t, MDL);
1975*83ee113eSDavid van Moolenbroek }
1976*83ee113eSDavid van Moolenbroek if (data->len)
1977*83ee113eSDavid van Moolenbroek return 1;
1978*83ee113eSDavid van Moolenbroek else
1979*83ee113eSDavid van Moolenbroek return 0;
1980*83ee113eSDavid van Moolenbroek }
1981*83ee113eSDavid van Moolenbroek
1982*83ee113eSDavid van Moolenbroek
1983*83ee113eSDavid van Moolenbroek /*
1984*83ee113eSDavid van Moolenbroek * colon-separated-hex-list :== NUMBER |
1985*83ee113eSDavid van Moolenbroek * NUMBER COLON colon-separated-hex-list
1986*83ee113eSDavid van Moolenbroek */
1987*83ee113eSDavid van Moolenbroek
parse_cshl(data,cfile)1988*83ee113eSDavid van Moolenbroek int parse_cshl (data, cfile)
1989*83ee113eSDavid van Moolenbroek struct data_string *data;
1990*83ee113eSDavid van Moolenbroek struct parse *cfile;
1991*83ee113eSDavid van Moolenbroek {
1992*83ee113eSDavid van Moolenbroek u_int8_t ibuf [128];
1993*83ee113eSDavid van Moolenbroek unsigned ilen = 0;
1994*83ee113eSDavid van Moolenbroek unsigned tlen = 0;
1995*83ee113eSDavid van Moolenbroek struct option_tag *sl = (struct option_tag *)0;
1996*83ee113eSDavid van Moolenbroek struct option_tag *next, **last = &sl;
1997*83ee113eSDavid van Moolenbroek enum dhcp_token token;
1998*83ee113eSDavid van Moolenbroek const char *val;
1999*83ee113eSDavid van Moolenbroek unsigned char *rvp;
2000*83ee113eSDavid van Moolenbroek
2001*83ee113eSDavid van Moolenbroek do {
2002*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2003*83ee113eSDavid van Moolenbroek if (token != NUMBER && token != NUMBER_OR_NAME) {
2004*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting hexadecimal number.");
2005*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2006*83ee113eSDavid van Moolenbroek for (; sl; sl = next) {
2007*83ee113eSDavid van Moolenbroek next = sl -> next;
2008*83ee113eSDavid van Moolenbroek dfree (sl, MDL);
2009*83ee113eSDavid van Moolenbroek }
2010*83ee113eSDavid van Moolenbroek return 0;
2011*83ee113eSDavid van Moolenbroek }
2012*83ee113eSDavid van Moolenbroek if (ilen == sizeof ibuf) {
2013*83ee113eSDavid van Moolenbroek next = (struct option_tag *)
2014*83ee113eSDavid van Moolenbroek dmalloc (ilen - 1 +
2015*83ee113eSDavid van Moolenbroek sizeof (struct option_tag), MDL);
2016*83ee113eSDavid van Moolenbroek if (!next)
2017*83ee113eSDavid van Moolenbroek log_fatal ("no memory for string list.");
2018*83ee113eSDavid van Moolenbroek memcpy (next -> data, ibuf, ilen);
2019*83ee113eSDavid van Moolenbroek *last = next;
2020*83ee113eSDavid van Moolenbroek last = &next -> next;
2021*83ee113eSDavid van Moolenbroek tlen += ilen;
2022*83ee113eSDavid van Moolenbroek ilen = 0;
2023*83ee113eSDavid van Moolenbroek }
2024*83ee113eSDavid van Moolenbroek convert_num (cfile, &ibuf [ilen++], val, 16, 8);
2025*83ee113eSDavid van Moolenbroek
2026*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2027*83ee113eSDavid van Moolenbroek if (token != COLON)
2028*83ee113eSDavid van Moolenbroek break;
2029*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2030*83ee113eSDavid van Moolenbroek } while (1);
2031*83ee113eSDavid van Moolenbroek
2032*83ee113eSDavid van Moolenbroek if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
2033*83ee113eSDavid van Moolenbroek log_fatal ("no memory to store octet data.");
2034*83ee113eSDavid van Moolenbroek data -> data = &data -> buffer -> data [0];
2035*83ee113eSDavid van Moolenbroek data -> len = tlen + ilen;
2036*83ee113eSDavid van Moolenbroek data -> terminated = 0;
2037*83ee113eSDavid van Moolenbroek
2038*83ee113eSDavid van Moolenbroek rvp = &data -> buffer -> data [0];
2039*83ee113eSDavid van Moolenbroek while (sl) {
2040*83ee113eSDavid van Moolenbroek next = sl -> next;
2041*83ee113eSDavid van Moolenbroek memcpy (rvp, sl -> data, sizeof ibuf);
2042*83ee113eSDavid van Moolenbroek rvp += sizeof ibuf;
2043*83ee113eSDavid van Moolenbroek dfree (sl, MDL);
2044*83ee113eSDavid van Moolenbroek sl = next;
2045*83ee113eSDavid van Moolenbroek }
2046*83ee113eSDavid van Moolenbroek
2047*83ee113eSDavid van Moolenbroek memcpy (rvp, ibuf, ilen);
2048*83ee113eSDavid van Moolenbroek return 1;
2049*83ee113eSDavid van Moolenbroek }
2050*83ee113eSDavid van Moolenbroek
2051*83ee113eSDavid van Moolenbroek /*
2052*83ee113eSDavid van Moolenbroek * executable-statements :== executable-statement executable-statements |
2053*83ee113eSDavid van Moolenbroek * executable-statement
2054*83ee113eSDavid van Moolenbroek *
2055*83ee113eSDavid van Moolenbroek * executable-statement :==
2056*83ee113eSDavid van Moolenbroek * IF if-statement |
2057*83ee113eSDavid van Moolenbroek * ADD class-name SEMI |
2058*83ee113eSDavid van Moolenbroek * BREAK SEMI |
2059*83ee113eSDavid van Moolenbroek * OPTION option-parameter SEMI |
2060*83ee113eSDavid van Moolenbroek * SUPERSEDE option-parameter SEMI |
2061*83ee113eSDavid van Moolenbroek * PREPEND option-parameter SEMI |
2062*83ee113eSDavid van Moolenbroek * APPEND option-parameter SEMI
2063*83ee113eSDavid van Moolenbroek */
2064*83ee113eSDavid van Moolenbroek
parse_executable_statements(statements,cfile,lose,case_context)2065*83ee113eSDavid van Moolenbroek int parse_executable_statements (statements, cfile, lose, case_context)
2066*83ee113eSDavid van Moolenbroek struct executable_statement **statements;
2067*83ee113eSDavid van Moolenbroek struct parse *cfile;
2068*83ee113eSDavid van Moolenbroek int *lose;
2069*83ee113eSDavid van Moolenbroek enum expression_context case_context;
2070*83ee113eSDavid van Moolenbroek {
2071*83ee113eSDavid van Moolenbroek struct executable_statement **next;
2072*83ee113eSDavid van Moolenbroek
2073*83ee113eSDavid van Moolenbroek next = statements;
2074*83ee113eSDavid van Moolenbroek while (parse_executable_statement (next, cfile, lose, case_context))
2075*83ee113eSDavid van Moolenbroek next = &((*next) -> next);
2076*83ee113eSDavid van Moolenbroek if (!*lose)
2077*83ee113eSDavid van Moolenbroek return 1;
2078*83ee113eSDavid van Moolenbroek return 0;
2079*83ee113eSDavid van Moolenbroek }
2080*83ee113eSDavid van Moolenbroek
parse_executable_statement(result,cfile,lose,case_context)2081*83ee113eSDavid van Moolenbroek int parse_executable_statement (result, cfile, lose, case_context)
2082*83ee113eSDavid van Moolenbroek struct executable_statement **result;
2083*83ee113eSDavid van Moolenbroek struct parse *cfile;
2084*83ee113eSDavid van Moolenbroek int *lose;
2085*83ee113eSDavid van Moolenbroek enum expression_context case_context;
2086*83ee113eSDavid van Moolenbroek {
2087*83ee113eSDavid van Moolenbroek #if defined(ENABLE_EXECUTE)
2088*83ee113eSDavid van Moolenbroek unsigned len;
2089*83ee113eSDavid van Moolenbroek struct expression **ep;
2090*83ee113eSDavid van Moolenbroek #endif
2091*83ee113eSDavid van Moolenbroek enum dhcp_token token;
2092*83ee113eSDavid van Moolenbroek const char *val;
2093*83ee113eSDavid van Moolenbroek struct class *cta;
2094*83ee113eSDavid van Moolenbroek struct option *option=NULL;
2095*83ee113eSDavid van Moolenbroek struct option_cache *cache;
2096*83ee113eSDavid van Moolenbroek int known;
2097*83ee113eSDavid van Moolenbroek int flag;
2098*83ee113eSDavid van Moolenbroek int i;
2099*83ee113eSDavid van Moolenbroek struct dns_zone *zone;
2100*83ee113eSDavid van Moolenbroek isc_result_t status;
2101*83ee113eSDavid van Moolenbroek char *s;
2102*83ee113eSDavid van Moolenbroek
2103*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2104*83ee113eSDavid van Moolenbroek switch (token) {
2105*83ee113eSDavid van Moolenbroek case DB_TIME_FORMAT:
2106*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
2107*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2108*83ee113eSDavid van Moolenbroek if (token == DEFAULT) {
2109*83ee113eSDavid van Moolenbroek db_time_format = DEFAULT_TIME_FORMAT;
2110*83ee113eSDavid van Moolenbroek } else if (token == LOCAL) {
2111*83ee113eSDavid van Moolenbroek db_time_format = LOCAL_TIME_FORMAT;
2112*83ee113eSDavid van Moolenbroek } else {
2113*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting 'local' or 'default'.");
2114*83ee113eSDavid van Moolenbroek if (token != SEMI)
2115*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2116*83ee113eSDavid van Moolenbroek *lose = 1;
2117*83ee113eSDavid van Moolenbroek return 0;
2118*83ee113eSDavid van Moolenbroek }
2119*83ee113eSDavid van Moolenbroek
2120*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2121*83ee113eSDavid van Moolenbroek if (token != SEMI) {
2122*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a semicolon.");
2123*83ee113eSDavid van Moolenbroek *lose = 1;
2124*83ee113eSDavid van Moolenbroek return 0;
2125*83ee113eSDavid van Moolenbroek }
2126*83ee113eSDavid van Moolenbroek
2127*83ee113eSDavid van Moolenbroek /* We're done here. */
2128*83ee113eSDavid van Moolenbroek return 1;
2129*83ee113eSDavid van Moolenbroek
2130*83ee113eSDavid van Moolenbroek case IF:
2131*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2132*83ee113eSDavid van Moolenbroek return parse_if_statement (result, cfile, lose);
2133*83ee113eSDavid van Moolenbroek
2134*83ee113eSDavid van Moolenbroek case TOKEN_ADD:
2135*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2136*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2137*83ee113eSDavid van Moolenbroek if (token != STRING) {
2138*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting class name.");
2139*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2140*83ee113eSDavid van Moolenbroek *lose = 1;
2141*83ee113eSDavid van Moolenbroek return 0;
2142*83ee113eSDavid van Moolenbroek }
2143*83ee113eSDavid van Moolenbroek cta = (struct class *)0;
2144*83ee113eSDavid van Moolenbroek status = find_class (&cta, val, MDL);
2145*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS) {
2146*83ee113eSDavid van Moolenbroek parse_warn (cfile, "class %s: %s",
2147*83ee113eSDavid van Moolenbroek val, isc_result_totext (status));
2148*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2149*83ee113eSDavid van Moolenbroek *lose = 1;
2150*83ee113eSDavid van Moolenbroek return 0;
2151*83ee113eSDavid van Moolenbroek }
2152*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2153*83ee113eSDavid van Moolenbroek *lose = 1;
2154*83ee113eSDavid van Moolenbroek return 0;
2155*83ee113eSDavid van Moolenbroek }
2156*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2157*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new statement.");
2158*83ee113eSDavid van Moolenbroek (*result) -> op = add_statement;
2159*83ee113eSDavid van Moolenbroek (*result) -> data.add = cta;
2160*83ee113eSDavid van Moolenbroek break;
2161*83ee113eSDavid van Moolenbroek
2162*83ee113eSDavid van Moolenbroek case BREAK:
2163*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2164*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2165*83ee113eSDavid van Moolenbroek *lose = 1;
2166*83ee113eSDavid van Moolenbroek return 0;
2167*83ee113eSDavid van Moolenbroek }
2168*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2169*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new statement.");
2170*83ee113eSDavid van Moolenbroek (*result) -> op = break_statement;
2171*83ee113eSDavid van Moolenbroek break;
2172*83ee113eSDavid van Moolenbroek
2173*83ee113eSDavid van Moolenbroek case SEND:
2174*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2175*83ee113eSDavid van Moolenbroek known = 0;
2176*83ee113eSDavid van Moolenbroek status = parse_option_name (cfile, 0, &known, &option);
2177*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL) {
2178*83ee113eSDavid van Moolenbroek *lose = 1;
2179*83ee113eSDavid van Moolenbroek return 0;
2180*83ee113eSDavid van Moolenbroek }
2181*83ee113eSDavid van Moolenbroek status = parse_option_statement(result, cfile, 1, option,
2182*83ee113eSDavid van Moolenbroek send_option_statement);
2183*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
2184*83ee113eSDavid van Moolenbroek return status;
2185*83ee113eSDavid van Moolenbroek
2186*83ee113eSDavid van Moolenbroek case SUPERSEDE:
2187*83ee113eSDavid van Moolenbroek case OPTION:
2188*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2189*83ee113eSDavid van Moolenbroek known = 0;
2190*83ee113eSDavid van Moolenbroek status = parse_option_name (cfile, 0, &known, &option);
2191*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL) {
2192*83ee113eSDavid van Moolenbroek *lose = 1;
2193*83ee113eSDavid van Moolenbroek return 0;
2194*83ee113eSDavid van Moolenbroek }
2195*83ee113eSDavid van Moolenbroek status = parse_option_statement(result, cfile, 1, option,
2196*83ee113eSDavid van Moolenbroek supersede_option_statement);
2197*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
2198*83ee113eSDavid van Moolenbroek return status;
2199*83ee113eSDavid van Moolenbroek
2200*83ee113eSDavid van Moolenbroek case ALLOW:
2201*83ee113eSDavid van Moolenbroek flag = 1;
2202*83ee113eSDavid van Moolenbroek goto pad;
2203*83ee113eSDavid van Moolenbroek case DENY:
2204*83ee113eSDavid van Moolenbroek flag = 0;
2205*83ee113eSDavid van Moolenbroek goto pad;
2206*83ee113eSDavid van Moolenbroek case IGNORE:
2207*83ee113eSDavid van Moolenbroek flag = 2;
2208*83ee113eSDavid van Moolenbroek pad:
2209*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2210*83ee113eSDavid van Moolenbroek cache = (struct option_cache *)0;
2211*83ee113eSDavid van Moolenbroek if (!parse_allow_deny (&cache, cfile, flag))
2212*83ee113eSDavid van Moolenbroek return 0;
2213*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2214*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new statement.");
2215*83ee113eSDavid van Moolenbroek (*result) -> op = supersede_option_statement;
2216*83ee113eSDavid van Moolenbroek (*result) -> data.option = cache;
2217*83ee113eSDavid van Moolenbroek break;
2218*83ee113eSDavid van Moolenbroek
2219*83ee113eSDavid van Moolenbroek case DEFAULT:
2220*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2221*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2222*83ee113eSDavid van Moolenbroek if (token == COLON)
2223*83ee113eSDavid van Moolenbroek goto switch_default;
2224*83ee113eSDavid van Moolenbroek known = 0;
2225*83ee113eSDavid van Moolenbroek status = parse_option_name (cfile, 0, &known, &option);
2226*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL) {
2227*83ee113eSDavid van Moolenbroek *lose = 1;
2228*83ee113eSDavid van Moolenbroek return 0;
2229*83ee113eSDavid van Moolenbroek }
2230*83ee113eSDavid van Moolenbroek status = parse_option_statement(result, cfile, 1, option,
2231*83ee113eSDavid van Moolenbroek default_option_statement);
2232*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
2233*83ee113eSDavid van Moolenbroek return status;
2234*83ee113eSDavid van Moolenbroek
2235*83ee113eSDavid van Moolenbroek case PREPEND:
2236*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2237*83ee113eSDavid van Moolenbroek known = 0;
2238*83ee113eSDavid van Moolenbroek status = parse_option_name (cfile, 0, &known, &option);
2239*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL) {
2240*83ee113eSDavid van Moolenbroek *lose = 1;
2241*83ee113eSDavid van Moolenbroek return 0;
2242*83ee113eSDavid van Moolenbroek }
2243*83ee113eSDavid van Moolenbroek status = parse_option_statement(result, cfile, 1, option,
2244*83ee113eSDavid van Moolenbroek prepend_option_statement);
2245*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
2246*83ee113eSDavid van Moolenbroek return status;
2247*83ee113eSDavid van Moolenbroek
2248*83ee113eSDavid van Moolenbroek case APPEND:
2249*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2250*83ee113eSDavid van Moolenbroek known = 0;
2251*83ee113eSDavid van Moolenbroek status = parse_option_name (cfile, 0, &known, &option);
2252*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL) {
2253*83ee113eSDavid van Moolenbroek *lose = 1;
2254*83ee113eSDavid van Moolenbroek return 0;
2255*83ee113eSDavid van Moolenbroek }
2256*83ee113eSDavid van Moolenbroek status = parse_option_statement(result, cfile, 1, option,
2257*83ee113eSDavid van Moolenbroek append_option_statement);
2258*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
2259*83ee113eSDavid van Moolenbroek return status;
2260*83ee113eSDavid van Moolenbroek
2261*83ee113eSDavid van Moolenbroek case ON:
2262*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2263*83ee113eSDavid van Moolenbroek return parse_on_statement (result, cfile, lose);
2264*83ee113eSDavid van Moolenbroek
2265*83ee113eSDavid van Moolenbroek case SWITCH:
2266*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2267*83ee113eSDavid van Moolenbroek return parse_switch_statement (result, cfile, lose);
2268*83ee113eSDavid van Moolenbroek
2269*83ee113eSDavid van Moolenbroek case CASE:
2270*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2271*83ee113eSDavid van Moolenbroek if (case_context == context_any) {
2272*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2273*83ee113eSDavid van Moolenbroek "case statement in inappropriate scope.");
2274*83ee113eSDavid van Moolenbroek *lose = 1;
2275*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2276*83ee113eSDavid van Moolenbroek return 0;
2277*83ee113eSDavid van Moolenbroek }
2278*83ee113eSDavid van Moolenbroek return parse_case_statement (result,
2279*83ee113eSDavid van Moolenbroek cfile, lose, case_context);
2280*83ee113eSDavid van Moolenbroek
2281*83ee113eSDavid van Moolenbroek switch_default:
2282*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2283*83ee113eSDavid van Moolenbroek if (case_context == context_any) {
2284*83ee113eSDavid van Moolenbroek parse_warn (cfile, "switch default statement in %s",
2285*83ee113eSDavid van Moolenbroek "inappropriate scope.");
2286*83ee113eSDavid van Moolenbroek
2287*83ee113eSDavid van Moolenbroek *lose = 1;
2288*83ee113eSDavid van Moolenbroek return 0;
2289*83ee113eSDavid van Moolenbroek } else {
2290*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2291*83ee113eSDavid van Moolenbroek log_fatal ("no memory for default statement.");
2292*83ee113eSDavid van Moolenbroek (*result) -> op = default_statement;
2293*83ee113eSDavid van Moolenbroek return 1;
2294*83ee113eSDavid van Moolenbroek }
2295*83ee113eSDavid van Moolenbroek
2296*83ee113eSDavid van Moolenbroek case DEFINE:
2297*83ee113eSDavid van Moolenbroek case TOKEN_SET:
2298*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2299*83ee113eSDavid van Moolenbroek if (token == DEFINE)
2300*83ee113eSDavid van Moolenbroek flag = 1;
2301*83ee113eSDavid van Moolenbroek else
2302*83ee113eSDavid van Moolenbroek flag = 0;
2303*83ee113eSDavid van Moolenbroek
2304*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2305*83ee113eSDavid van Moolenbroek if (token != NAME && token != NUMBER_OR_NAME) {
2306*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2307*83ee113eSDavid van Moolenbroek "%s can't be a variable name", val);
2308*83ee113eSDavid van Moolenbroek badset:
2309*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2310*83ee113eSDavid van Moolenbroek *lose = 1;
2311*83ee113eSDavid van Moolenbroek return 0;
2312*83ee113eSDavid van Moolenbroek }
2313*83ee113eSDavid van Moolenbroek
2314*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2315*83ee113eSDavid van Moolenbroek log_fatal ("no memory for set statement.");
2316*83ee113eSDavid van Moolenbroek (*result) -> op = flag ? define_statement : set_statement;
2317*83ee113eSDavid van Moolenbroek (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
2318*83ee113eSDavid van Moolenbroek if (!(*result)->data.set.name)
2319*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate variable name");
2320*83ee113eSDavid van Moolenbroek strcpy ((*result) -> data.set.name, val);
2321*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2322*83ee113eSDavid van Moolenbroek
2323*83ee113eSDavid van Moolenbroek if (token == LPAREN) {
2324*83ee113eSDavid van Moolenbroek struct string_list *head, *cur, *new;
2325*83ee113eSDavid van Moolenbroek struct expression *expr;
2326*83ee113eSDavid van Moolenbroek head = cur = (struct string_list *)0;
2327*83ee113eSDavid van Moolenbroek do {
2328*83ee113eSDavid van Moolenbroek token = next_token (&val,
2329*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
2330*83ee113eSDavid van Moolenbroek if (token == RPAREN)
2331*83ee113eSDavid van Moolenbroek break;
2332*83ee113eSDavid van Moolenbroek if (token != NAME && token != NUMBER_OR_NAME) {
2333*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2334*83ee113eSDavid van Moolenbroek "expecting argument name");
2335*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 0);
2336*83ee113eSDavid van Moolenbroek *lose = 1;
2337*83ee113eSDavid van Moolenbroek executable_statement_dereference
2338*83ee113eSDavid van Moolenbroek (result, MDL);
2339*83ee113eSDavid van Moolenbroek return 0;
2340*83ee113eSDavid van Moolenbroek }
2341*83ee113eSDavid van Moolenbroek new = ((struct string_list *)
2342*83ee113eSDavid van Moolenbroek dmalloc (sizeof (struct string_list) +
2343*83ee113eSDavid van Moolenbroek strlen (val), MDL));
2344*83ee113eSDavid van Moolenbroek if (!new)
2345*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate string.");
2346*83ee113eSDavid van Moolenbroek memset (new, 0, sizeof *new);
2347*83ee113eSDavid van Moolenbroek strcpy (new -> string, val);
2348*83ee113eSDavid van Moolenbroek if (cur) {
2349*83ee113eSDavid van Moolenbroek cur -> next = new;
2350*83ee113eSDavid van Moolenbroek cur = new;
2351*83ee113eSDavid van Moolenbroek } else {
2352*83ee113eSDavid van Moolenbroek head = cur = new;
2353*83ee113eSDavid van Moolenbroek }
2354*83ee113eSDavid van Moolenbroek token = next_token (&val,
2355*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
2356*83ee113eSDavid van Moolenbroek } while (token == COMMA);
2357*83ee113eSDavid van Moolenbroek
2358*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
2359*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting right paren.");
2360*83ee113eSDavid van Moolenbroek badx:
2361*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2362*83ee113eSDavid van Moolenbroek *lose = 1;
2363*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2364*83ee113eSDavid van Moolenbroek return 0;
2365*83ee113eSDavid van Moolenbroek }
2366*83ee113eSDavid van Moolenbroek
2367*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2368*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
2369*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting left brace.");
2370*83ee113eSDavid van Moolenbroek goto badx;
2371*83ee113eSDavid van Moolenbroek }
2372*83ee113eSDavid van Moolenbroek
2373*83ee113eSDavid van Moolenbroek expr = (struct expression *)0;
2374*83ee113eSDavid van Moolenbroek if (!(expression_allocate (&expr, MDL)))
2375*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression.");
2376*83ee113eSDavid van Moolenbroek expr -> op = expr_function;
2377*83ee113eSDavid van Moolenbroek if (!fundef_allocate (&expr -> data.func, MDL))
2378*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate fundef.");
2379*83ee113eSDavid van Moolenbroek expr -> data.func -> args = head;
2380*83ee113eSDavid van Moolenbroek (*result) -> data.set.expr = expr;
2381*83ee113eSDavid van Moolenbroek
2382*83ee113eSDavid van Moolenbroek if (!(parse_executable_statements
2383*83ee113eSDavid van Moolenbroek (&expr -> data.func -> statements, cfile, lose,
2384*83ee113eSDavid van Moolenbroek case_context))) {
2385*83ee113eSDavid van Moolenbroek if (*lose)
2386*83ee113eSDavid van Moolenbroek goto badx;
2387*83ee113eSDavid van Moolenbroek }
2388*83ee113eSDavid van Moolenbroek
2389*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2390*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
2391*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting rigt brace.");
2392*83ee113eSDavid van Moolenbroek goto badx;
2393*83ee113eSDavid van Moolenbroek }
2394*83ee113eSDavid van Moolenbroek } else {
2395*83ee113eSDavid van Moolenbroek if (token != EQUAL) {
2396*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2397*83ee113eSDavid van Moolenbroek "expecting '=' in %s statement.",
2398*83ee113eSDavid van Moolenbroek flag ? "define" : "set");
2399*83ee113eSDavid van Moolenbroek goto badset;
2400*83ee113eSDavid van Moolenbroek }
2401*83ee113eSDavid van Moolenbroek
2402*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*result) -> data.set.expr,
2403*83ee113eSDavid van Moolenbroek cfile, lose, context_any,
2404*83ee113eSDavid van Moolenbroek (struct expression **)0,
2405*83ee113eSDavid van Moolenbroek expr_none)) {
2406*83ee113eSDavid van Moolenbroek if (!*lose)
2407*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2408*83ee113eSDavid van Moolenbroek "expecting expression.");
2409*83ee113eSDavid van Moolenbroek else
2410*83ee113eSDavid van Moolenbroek *lose = 1;
2411*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2412*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2413*83ee113eSDavid van Moolenbroek return 0;
2414*83ee113eSDavid van Moolenbroek }
2415*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2416*83ee113eSDavid van Moolenbroek *lose = 1;
2417*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2418*83ee113eSDavid van Moolenbroek return 0;
2419*83ee113eSDavid van Moolenbroek }
2420*83ee113eSDavid van Moolenbroek }
2421*83ee113eSDavid van Moolenbroek break;
2422*83ee113eSDavid van Moolenbroek
2423*83ee113eSDavid van Moolenbroek case UNSET:
2424*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2425*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2426*83ee113eSDavid van Moolenbroek if (token != NAME && token != NUMBER_OR_NAME) {
2427*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2428*83ee113eSDavid van Moolenbroek "%s can't be a variable name", val);
2429*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2430*83ee113eSDavid van Moolenbroek *lose = 1;
2431*83ee113eSDavid van Moolenbroek return 0;
2432*83ee113eSDavid van Moolenbroek }
2433*83ee113eSDavid van Moolenbroek
2434*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2435*83ee113eSDavid van Moolenbroek log_fatal ("no memory for set statement.");
2436*83ee113eSDavid van Moolenbroek (*result) -> op = unset_statement;
2437*83ee113eSDavid van Moolenbroek (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
2438*83ee113eSDavid van Moolenbroek if (!(*result)->data.unset)
2439*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate variable name");
2440*83ee113eSDavid van Moolenbroek strcpy ((*result) -> data.unset, val);
2441*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2442*83ee113eSDavid van Moolenbroek *lose = 1;
2443*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2444*83ee113eSDavid van Moolenbroek return 0;
2445*83ee113eSDavid van Moolenbroek }
2446*83ee113eSDavid van Moolenbroek break;
2447*83ee113eSDavid van Moolenbroek
2448*83ee113eSDavid van Moolenbroek case EVAL:
2449*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2450*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2451*83ee113eSDavid van Moolenbroek log_fatal ("no memory for eval statement.");
2452*83ee113eSDavid van Moolenbroek (*result) -> op = eval_statement;
2453*83ee113eSDavid van Moolenbroek
2454*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*result) -> data.eval,
2455*83ee113eSDavid van Moolenbroek cfile, lose, context_data, /* XXX */
2456*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none)) {
2457*83ee113eSDavid van Moolenbroek if (!*lose)
2458*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2459*83ee113eSDavid van Moolenbroek "expecting data expression.");
2460*83ee113eSDavid van Moolenbroek else
2461*83ee113eSDavid van Moolenbroek *lose = 1;
2462*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2463*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2464*83ee113eSDavid van Moolenbroek return 0;
2465*83ee113eSDavid van Moolenbroek }
2466*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2467*83ee113eSDavid van Moolenbroek *lose = 1;
2468*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2469*83ee113eSDavid van Moolenbroek }
2470*83ee113eSDavid van Moolenbroek break;
2471*83ee113eSDavid van Moolenbroek
2472*83ee113eSDavid van Moolenbroek case EXECUTE:
2473*83ee113eSDavid van Moolenbroek #ifdef ENABLE_EXECUTE
2474*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
2475*83ee113eSDavid van Moolenbroek
2476*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2477*83ee113eSDavid van Moolenbroek log_fatal ("no memory for execute statement.");
2478*83ee113eSDavid van Moolenbroek (*result)->op = execute_statement;
2479*83ee113eSDavid van Moolenbroek
2480*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2481*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
2482*83ee113eSDavid van Moolenbroek parse_warn(cfile, "left parenthesis expected.");
2483*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2484*83ee113eSDavid van Moolenbroek *lose = 1;
2485*83ee113eSDavid van Moolenbroek return 0;
2486*83ee113eSDavid van Moolenbroek }
2487*83ee113eSDavid van Moolenbroek
2488*83ee113eSDavid van Moolenbroek token = next_token(&val, &len, cfile);
2489*83ee113eSDavid van Moolenbroek if (token != STRING) {
2490*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a quoted string.");
2491*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2492*83ee113eSDavid van Moolenbroek *lose = 1;
2493*83ee113eSDavid van Moolenbroek return 0;
2494*83ee113eSDavid van Moolenbroek }
2495*83ee113eSDavid van Moolenbroek
2496*83ee113eSDavid van Moolenbroek (*result)->data.execute.command = dmalloc(len + 1, MDL);
2497*83ee113eSDavid van Moolenbroek if ((*result)->data.execute.command == NULL)
2498*83ee113eSDavid van Moolenbroek log_fatal("can't allocate command name");
2499*83ee113eSDavid van Moolenbroek strcpy((*result)->data.execute.command, val);
2500*83ee113eSDavid van Moolenbroek
2501*83ee113eSDavid van Moolenbroek ep = &(*result)->data.execute.arglist;
2502*83ee113eSDavid van Moolenbroek (*result)->data.execute.argc = 0;
2503*83ee113eSDavid van Moolenbroek
2504*83ee113eSDavid van Moolenbroek while((token = next_token(&val, NULL, cfile)) == COMMA) {
2505*83ee113eSDavid van Moolenbroek if (!expression_allocate(ep, MDL))
2506*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
2507*83ee113eSDavid van Moolenbroek
2508*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*ep) -> data.arg.val,
2509*83ee113eSDavid van Moolenbroek cfile, lose)) {
2510*83ee113eSDavid van Moolenbroek if (!*lose) {
2511*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2512*83ee113eSDavid van Moolenbroek "expecting expression.");
2513*83ee113eSDavid van Moolenbroek *lose = 1;
2514*83ee113eSDavid van Moolenbroek }
2515*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2516*83ee113eSDavid van Moolenbroek *lose = 1;
2517*83ee113eSDavid van Moolenbroek return 0;
2518*83ee113eSDavid van Moolenbroek }
2519*83ee113eSDavid van Moolenbroek ep = &(*ep)->data.arg.next;
2520*83ee113eSDavid van Moolenbroek (*result)->data.execute.argc++;
2521*83ee113eSDavid van Moolenbroek }
2522*83ee113eSDavid van Moolenbroek
2523*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
2524*83ee113eSDavid van Moolenbroek parse_warn(cfile, "right parenthesis expected.");
2525*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2526*83ee113eSDavid van Moolenbroek *lose = 1;
2527*83ee113eSDavid van Moolenbroek return 0;
2528*83ee113eSDavid van Moolenbroek }
2529*83ee113eSDavid van Moolenbroek
2530*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2531*83ee113eSDavid van Moolenbroek *lose = 1;
2532*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2533*83ee113eSDavid van Moolenbroek }
2534*83ee113eSDavid van Moolenbroek #else /* ! ENABLE_EXECUTE */
2535*83ee113eSDavid van Moolenbroek parse_warn(cfile, "define ENABLE_EXECUTE in site.h to "
2536*83ee113eSDavid van Moolenbroek "enable execute(); expressions.");
2537*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2538*83ee113eSDavid van Moolenbroek *lose = 1;
2539*83ee113eSDavid van Moolenbroek return 0;
2540*83ee113eSDavid van Moolenbroek #endif /* ENABLE_EXECUTE */
2541*83ee113eSDavid van Moolenbroek break;
2542*83ee113eSDavid van Moolenbroek
2543*83ee113eSDavid van Moolenbroek case RETURN:
2544*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2545*83ee113eSDavid van Moolenbroek
2546*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2547*83ee113eSDavid van Moolenbroek log_fatal ("no memory for return statement.");
2548*83ee113eSDavid van Moolenbroek (*result) -> op = return_statement;
2549*83ee113eSDavid van Moolenbroek
2550*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*result) -> data.retval,
2551*83ee113eSDavid van Moolenbroek cfile, lose, context_data,
2552*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none)) {
2553*83ee113eSDavid van Moolenbroek if (!*lose)
2554*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2555*83ee113eSDavid van Moolenbroek "expecting data expression.");
2556*83ee113eSDavid van Moolenbroek else
2557*83ee113eSDavid van Moolenbroek *lose = 1;
2558*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2559*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2560*83ee113eSDavid van Moolenbroek return 0;
2561*83ee113eSDavid van Moolenbroek }
2562*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2563*83ee113eSDavid van Moolenbroek *lose = 1;
2564*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2565*83ee113eSDavid van Moolenbroek return 0;
2566*83ee113eSDavid van Moolenbroek }
2567*83ee113eSDavid van Moolenbroek break;
2568*83ee113eSDavid van Moolenbroek
2569*83ee113eSDavid van Moolenbroek case LOG:
2570*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2571*83ee113eSDavid van Moolenbroek
2572*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2573*83ee113eSDavid van Moolenbroek log_fatal ("no memory for log statement.");
2574*83ee113eSDavid van Moolenbroek (*result) -> op = log_statement;
2575*83ee113eSDavid van Moolenbroek
2576*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2577*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
2578*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left parenthesis expected.");
2579*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2580*83ee113eSDavid van Moolenbroek *lose = 1;
2581*83ee113eSDavid van Moolenbroek return 0;
2582*83ee113eSDavid van Moolenbroek }
2583*83ee113eSDavid van Moolenbroek
2584*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2585*83ee113eSDavid van Moolenbroek i = 1;
2586*83ee113eSDavid van Moolenbroek if (token == FATAL) {
2587*83ee113eSDavid van Moolenbroek (*result) -> data.log.priority = log_priority_fatal;
2588*83ee113eSDavid van Moolenbroek } else if (token == ERROR) {
2589*83ee113eSDavid van Moolenbroek (*result) -> data.log.priority = log_priority_error;
2590*83ee113eSDavid van Moolenbroek } else if (token == TOKEN_DEBUG) {
2591*83ee113eSDavid van Moolenbroek (*result) -> data.log.priority = log_priority_debug;
2592*83ee113eSDavid van Moolenbroek } else if (token == INFO) {
2593*83ee113eSDavid van Moolenbroek (*result) -> data.log.priority = log_priority_info;
2594*83ee113eSDavid van Moolenbroek } else {
2595*83ee113eSDavid van Moolenbroek (*result) -> data.log.priority = log_priority_debug;
2596*83ee113eSDavid van Moolenbroek i = 0;
2597*83ee113eSDavid van Moolenbroek }
2598*83ee113eSDavid van Moolenbroek if (i) {
2599*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2600*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2601*83ee113eSDavid van Moolenbroek if (token != COMMA) {
2602*83ee113eSDavid van Moolenbroek parse_warn (cfile, "comma expected.");
2603*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2604*83ee113eSDavid van Moolenbroek *lose = 1;
2605*83ee113eSDavid van Moolenbroek return 0;
2606*83ee113eSDavid van Moolenbroek }
2607*83ee113eSDavid van Moolenbroek }
2608*83ee113eSDavid van Moolenbroek
2609*83ee113eSDavid van Moolenbroek if (!(parse_data_expression
2610*83ee113eSDavid van Moolenbroek (&(*result) -> data.log.expr, cfile, lose))) {
2611*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2612*83ee113eSDavid van Moolenbroek *lose = 1;
2613*83ee113eSDavid van Moolenbroek return 0;
2614*83ee113eSDavid van Moolenbroek }
2615*83ee113eSDavid van Moolenbroek
2616*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2617*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
2618*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right parenthesis expected.");
2619*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2620*83ee113eSDavid van Moolenbroek *lose = 1;
2621*83ee113eSDavid van Moolenbroek return 0;
2622*83ee113eSDavid van Moolenbroek }
2623*83ee113eSDavid van Moolenbroek
2624*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2625*83ee113eSDavid van Moolenbroek if (token != SEMI) {
2626*83ee113eSDavid van Moolenbroek parse_warn (cfile, "semicolon expected.");
2627*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2628*83ee113eSDavid van Moolenbroek *lose = 1;
2629*83ee113eSDavid van Moolenbroek return 0;
2630*83ee113eSDavid van Moolenbroek }
2631*83ee113eSDavid van Moolenbroek break;
2632*83ee113eSDavid van Moolenbroek
2633*83ee113eSDavid van Moolenbroek /* Not really a statement, but we parse it here anyway
2634*83ee113eSDavid van Moolenbroek because it's appropriate for all DHCP agents with
2635*83ee113eSDavid van Moolenbroek parsers. */
2636*83ee113eSDavid van Moolenbroek case ZONE:
2637*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2638*83ee113eSDavid van Moolenbroek zone = (struct dns_zone *)0;
2639*83ee113eSDavid van Moolenbroek if (!dns_zone_allocate (&zone, MDL))
2640*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new zone.");
2641*83ee113eSDavid van Moolenbroek zone -> name = parse_host_name (cfile);
2642*83ee113eSDavid van Moolenbroek if (!zone -> name) {
2643*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting hostname.");
2644*83ee113eSDavid van Moolenbroek badzone:
2645*83ee113eSDavid van Moolenbroek *lose = 1;
2646*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2647*83ee113eSDavid van Moolenbroek dns_zone_dereference (&zone, MDL);
2648*83ee113eSDavid van Moolenbroek return 0;
2649*83ee113eSDavid van Moolenbroek }
2650*83ee113eSDavid van Moolenbroek i = strlen (zone -> name);
2651*83ee113eSDavid van Moolenbroek if (zone -> name [i - 1] != '.') {
2652*83ee113eSDavid van Moolenbroek s = dmalloc ((unsigned)i + 2, MDL);
2653*83ee113eSDavid van Moolenbroek if (!s) {
2654*83ee113eSDavid van Moolenbroek parse_warn (cfile, "no trailing '.' on zone");
2655*83ee113eSDavid van Moolenbroek goto badzone;
2656*83ee113eSDavid van Moolenbroek }
2657*83ee113eSDavid van Moolenbroek strcpy (s, zone -> name);
2658*83ee113eSDavid van Moolenbroek s [i] = '.';
2659*83ee113eSDavid van Moolenbroek s [i + 1] = 0;
2660*83ee113eSDavid van Moolenbroek dfree (zone -> name, MDL);
2661*83ee113eSDavid van Moolenbroek zone -> name = s;
2662*83ee113eSDavid van Moolenbroek }
2663*83ee113eSDavid van Moolenbroek if (!parse_zone (zone, cfile))
2664*83ee113eSDavid van Moolenbroek goto badzone;
2665*83ee113eSDavid van Moolenbroek status = enter_dns_zone (zone);
2666*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS) {
2667*83ee113eSDavid van Moolenbroek parse_warn (cfile, "dns zone key %s: %s",
2668*83ee113eSDavid van Moolenbroek zone -> name, isc_result_totext (status));
2669*83ee113eSDavid van Moolenbroek dns_zone_dereference (&zone, MDL);
2670*83ee113eSDavid van Moolenbroek return 0;
2671*83ee113eSDavid van Moolenbroek }
2672*83ee113eSDavid van Moolenbroek dns_zone_dereference (&zone, MDL);
2673*83ee113eSDavid van Moolenbroek return 1;
2674*83ee113eSDavid van Moolenbroek
2675*83ee113eSDavid van Moolenbroek /* Also not really a statement, but same idea as above. */
2676*83ee113eSDavid van Moolenbroek case KEY:
2677*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2678*83ee113eSDavid van Moolenbroek if (!parse_key (cfile)) {
2679*83ee113eSDavid van Moolenbroek *lose = 1;
2680*83ee113eSDavid van Moolenbroek return 0;
2681*83ee113eSDavid van Moolenbroek }
2682*83ee113eSDavid van Moolenbroek return 1;
2683*83ee113eSDavid van Moolenbroek
2684*83ee113eSDavid van Moolenbroek default:
2685*83ee113eSDavid van Moolenbroek if (config_universe && is_identifier (token)) {
2686*83ee113eSDavid van Moolenbroek option = (struct option *)0;
2687*83ee113eSDavid van Moolenbroek option_name_hash_lookup(&option,
2688*83ee113eSDavid van Moolenbroek config_universe->name_hash,
2689*83ee113eSDavid van Moolenbroek val, 0, MDL);
2690*83ee113eSDavid van Moolenbroek if (option) {
2691*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2692*83ee113eSDavid van Moolenbroek status = parse_option_statement
2693*83ee113eSDavid van Moolenbroek (result, cfile, 1, option,
2694*83ee113eSDavid van Moolenbroek supersede_option_statement);
2695*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
2696*83ee113eSDavid van Moolenbroek return status;
2697*83ee113eSDavid van Moolenbroek }
2698*83ee113eSDavid van Moolenbroek }
2699*83ee113eSDavid van Moolenbroek
2700*83ee113eSDavid van Moolenbroek if (token == NUMBER_OR_NAME || token == NAME) {
2701*83ee113eSDavid van Moolenbroek /* This is rather ugly. Since function calls are
2702*83ee113eSDavid van Moolenbroek data expressions, fake up an eval statement. */
2703*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
2704*83ee113eSDavid van Moolenbroek log_fatal ("no memory for eval statement.");
2705*83ee113eSDavid van Moolenbroek (*result) -> op = eval_statement;
2706*83ee113eSDavid van Moolenbroek
2707*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*result) -> data.eval,
2708*83ee113eSDavid van Moolenbroek cfile, lose, context_data,
2709*83ee113eSDavid van Moolenbroek (struct expression **)0,
2710*83ee113eSDavid van Moolenbroek expr_none)) {
2711*83ee113eSDavid van Moolenbroek if (!*lose)
2712*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting "
2713*83ee113eSDavid van Moolenbroek "function call.");
2714*83ee113eSDavid van Moolenbroek else
2715*83ee113eSDavid van Moolenbroek *lose = 1;
2716*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2717*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2718*83ee113eSDavid van Moolenbroek return 0;
2719*83ee113eSDavid van Moolenbroek }
2720*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile)) {
2721*83ee113eSDavid van Moolenbroek *lose = 1;
2722*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
2723*83ee113eSDavid van Moolenbroek return 0;
2724*83ee113eSDavid van Moolenbroek }
2725*83ee113eSDavid van Moolenbroek break;
2726*83ee113eSDavid van Moolenbroek }
2727*83ee113eSDavid van Moolenbroek
2728*83ee113eSDavid van Moolenbroek *lose = 0;
2729*83ee113eSDavid van Moolenbroek return 0;
2730*83ee113eSDavid van Moolenbroek }
2731*83ee113eSDavid van Moolenbroek
2732*83ee113eSDavid van Moolenbroek return 1;
2733*83ee113eSDavid van Moolenbroek }
2734*83ee113eSDavid van Moolenbroek
2735*83ee113eSDavid van Moolenbroek /* zone-statements :== zone-statement |
2736*83ee113eSDavid van Moolenbroek zone-statement zone-statements
2737*83ee113eSDavid van Moolenbroek zone-statement :==
2738*83ee113eSDavid van Moolenbroek PRIMARY ip-addresses SEMI |
2739*83ee113eSDavid van Moolenbroek SECONDARY ip-addresses SEMI |
2740*83ee113eSDavid van Moolenbroek PRIMARY6 ip-address6 SEMI |
2741*83ee113eSDavid van Moolenbroek SECONDARY6 ip-address6 SEMI |
2742*83ee113eSDavid van Moolenbroek key-reference SEMI
2743*83ee113eSDavid van Moolenbroek ip-addresses :== ip-addr-or-hostname |
2744*83ee113eSDavid van Moolenbroek ip-addr-or-hostname COMMA ip-addresses
2745*83ee113eSDavid van Moolenbroek key-reference :== KEY STRING |
2746*83ee113eSDavid van Moolenbroek KEY identifier */
2747*83ee113eSDavid van Moolenbroek
parse_zone(struct dns_zone * zone,struct parse * cfile)2748*83ee113eSDavid van Moolenbroek int parse_zone (struct dns_zone *zone, struct parse *cfile)
2749*83ee113eSDavid van Moolenbroek {
2750*83ee113eSDavid van Moolenbroek int token;
2751*83ee113eSDavid van Moolenbroek const char *val;
2752*83ee113eSDavid van Moolenbroek char *key_name;
2753*83ee113eSDavid van Moolenbroek struct option_cache *oc;
2754*83ee113eSDavid van Moolenbroek int done = 0;
2755*83ee113eSDavid van Moolenbroek
2756*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2757*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
2758*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting left brace");
2759*83ee113eSDavid van Moolenbroek return 0;
2760*83ee113eSDavid van Moolenbroek }
2761*83ee113eSDavid van Moolenbroek
2762*83ee113eSDavid van Moolenbroek do {
2763*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2764*83ee113eSDavid van Moolenbroek switch (token) {
2765*83ee113eSDavid van Moolenbroek case PRIMARY:
2766*83ee113eSDavid van Moolenbroek if (zone -> primary) {
2767*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2768*83ee113eSDavid van Moolenbroek "more than one primary.");
2769*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2770*83ee113eSDavid van Moolenbroek return 0;
2771*83ee113eSDavid van Moolenbroek }
2772*83ee113eSDavid van Moolenbroek if (!option_cache_allocate (&zone -> primary, MDL))
2773*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate primary option cache.");
2774*83ee113eSDavid van Moolenbroek oc = zone -> primary;
2775*83ee113eSDavid van Moolenbroek goto consemup;
2776*83ee113eSDavid van Moolenbroek
2777*83ee113eSDavid van Moolenbroek case SECONDARY:
2778*83ee113eSDavid van Moolenbroek if (zone -> secondary) {
2779*83ee113eSDavid van Moolenbroek parse_warn (cfile, "more than one secondary.");
2780*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2781*83ee113eSDavid van Moolenbroek return 0;
2782*83ee113eSDavid van Moolenbroek }
2783*83ee113eSDavid van Moolenbroek if (!option_cache_allocate (&zone -> secondary, MDL))
2784*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate secondary.");
2785*83ee113eSDavid van Moolenbroek oc = zone -> secondary;
2786*83ee113eSDavid van Moolenbroek consemup:
2787*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2788*83ee113eSDavid van Moolenbroek do {
2789*83ee113eSDavid van Moolenbroek struct expression *expr = (struct expression *)0;
2790*83ee113eSDavid van Moolenbroek if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
2791*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2792*83ee113eSDavid van Moolenbroek "expecting IP addr or hostname.");
2793*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2794*83ee113eSDavid van Moolenbroek return 0;
2795*83ee113eSDavid van Moolenbroek }
2796*83ee113eSDavid van Moolenbroek if (oc -> expression) {
2797*83ee113eSDavid van Moolenbroek struct expression *old =
2798*83ee113eSDavid van Moolenbroek (struct expression *)0;
2799*83ee113eSDavid van Moolenbroek expression_reference (&old,
2800*83ee113eSDavid van Moolenbroek oc -> expression,
2801*83ee113eSDavid van Moolenbroek MDL);
2802*83ee113eSDavid van Moolenbroek expression_dereference (&oc -> expression,
2803*83ee113eSDavid van Moolenbroek MDL);
2804*83ee113eSDavid van Moolenbroek if (!make_concat (&oc -> expression,
2805*83ee113eSDavid van Moolenbroek old, expr))
2806*83ee113eSDavid van Moolenbroek log_fatal ("no memory for concat.");
2807*83ee113eSDavid van Moolenbroek expression_dereference (&expr, MDL);
2808*83ee113eSDavid van Moolenbroek expression_dereference (&old, MDL);
2809*83ee113eSDavid van Moolenbroek } else {
2810*83ee113eSDavid van Moolenbroek expression_reference (&oc -> expression,
2811*83ee113eSDavid van Moolenbroek expr, MDL);
2812*83ee113eSDavid van Moolenbroek expression_dereference (&expr, MDL);
2813*83ee113eSDavid van Moolenbroek }
2814*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2815*83ee113eSDavid van Moolenbroek } while (token == COMMA);
2816*83ee113eSDavid van Moolenbroek if (token != SEMI) {
2817*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting semicolon.");
2818*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2819*83ee113eSDavid van Moolenbroek return 0;
2820*83ee113eSDavid van Moolenbroek }
2821*83ee113eSDavid van Moolenbroek break;
2822*83ee113eSDavid van Moolenbroek
2823*83ee113eSDavid van Moolenbroek case PRIMARY6:
2824*83ee113eSDavid van Moolenbroek if (zone->primary6) {
2825*83ee113eSDavid van Moolenbroek parse_warn(cfile, "more than one primary6.");
2826*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2827*83ee113eSDavid van Moolenbroek return (0);
2828*83ee113eSDavid van Moolenbroek }
2829*83ee113eSDavid van Moolenbroek if (!option_cache_allocate (&zone->primary6, MDL))
2830*83ee113eSDavid van Moolenbroek log_fatal("can't allocate primary6 option cache.");
2831*83ee113eSDavid van Moolenbroek oc = zone->primary6;
2832*83ee113eSDavid van Moolenbroek goto consemup6;
2833*83ee113eSDavid van Moolenbroek
2834*83ee113eSDavid van Moolenbroek case SECONDARY6:
2835*83ee113eSDavid van Moolenbroek if (zone->secondary6) {
2836*83ee113eSDavid van Moolenbroek parse_warn(cfile, "more than one secondary6.");
2837*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2838*83ee113eSDavid van Moolenbroek return (0);
2839*83ee113eSDavid van Moolenbroek }
2840*83ee113eSDavid van Moolenbroek if (!option_cache_allocate (&zone->secondary6, MDL))
2841*83ee113eSDavid van Moolenbroek log_fatal("can't allocate secondary6 "
2842*83ee113eSDavid van Moolenbroek "option cache.");
2843*83ee113eSDavid van Moolenbroek oc = zone->secondary6;
2844*83ee113eSDavid van Moolenbroek consemup6:
2845*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
2846*83ee113eSDavid van Moolenbroek do {
2847*83ee113eSDavid van Moolenbroek struct expression *expr = NULL;
2848*83ee113eSDavid van Moolenbroek if (parse_ip6_addr_expr(&expr, cfile) == 0) {
2849*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting IPv6 addr.");
2850*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2851*83ee113eSDavid van Moolenbroek return (0);
2852*83ee113eSDavid van Moolenbroek }
2853*83ee113eSDavid van Moolenbroek if (oc->expression) {
2854*83ee113eSDavid van Moolenbroek struct expression *old = NULL;
2855*83ee113eSDavid van Moolenbroek expression_reference(&old, oc->expression,
2856*83ee113eSDavid van Moolenbroek MDL);
2857*83ee113eSDavid van Moolenbroek expression_dereference(&oc->expression,
2858*83ee113eSDavid van Moolenbroek MDL);
2859*83ee113eSDavid van Moolenbroek if (!make_concat(&oc->expression,
2860*83ee113eSDavid van Moolenbroek old, expr))
2861*83ee113eSDavid van Moolenbroek log_fatal("no memory for concat.");
2862*83ee113eSDavid van Moolenbroek expression_dereference(&expr, MDL);
2863*83ee113eSDavid van Moolenbroek expression_dereference(&old, MDL);
2864*83ee113eSDavid van Moolenbroek } else {
2865*83ee113eSDavid van Moolenbroek expression_reference(&oc->expression,
2866*83ee113eSDavid van Moolenbroek expr, MDL);
2867*83ee113eSDavid van Moolenbroek expression_dereference(&expr, MDL);
2868*83ee113eSDavid van Moolenbroek }
2869*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
2870*83ee113eSDavid van Moolenbroek } while (token == COMMA);
2871*83ee113eSDavid van Moolenbroek if (token != SEMI) {
2872*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting semicolon.");
2873*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
2874*83ee113eSDavid van Moolenbroek return (0);
2875*83ee113eSDavid van Moolenbroek }
2876*83ee113eSDavid van Moolenbroek break;
2877*83ee113eSDavid van Moolenbroek
2878*83ee113eSDavid van Moolenbroek case KEY:
2879*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2880*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2881*83ee113eSDavid van Moolenbroek if (token == STRING) {
2882*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2883*83ee113eSDavid van Moolenbroek key_name = (char *)0;
2884*83ee113eSDavid van Moolenbroek } else {
2885*83ee113eSDavid van Moolenbroek key_name = parse_host_name (cfile);
2886*83ee113eSDavid van Moolenbroek if (!key_name) {
2887*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting key name.");
2888*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2889*83ee113eSDavid van Moolenbroek return 0;
2890*83ee113eSDavid van Moolenbroek }
2891*83ee113eSDavid van Moolenbroek val = key_name;
2892*83ee113eSDavid van Moolenbroek }
2893*83ee113eSDavid van Moolenbroek if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2894*83ee113eSDavid van Moolenbroek ISC_R_SUCCESS)
2895*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unknown key %s", val);
2896*83ee113eSDavid van Moolenbroek if (key_name)
2897*83ee113eSDavid van Moolenbroek dfree (key_name, MDL);
2898*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile))
2899*83ee113eSDavid van Moolenbroek return 0;
2900*83ee113eSDavid van Moolenbroek break;
2901*83ee113eSDavid van Moolenbroek
2902*83ee113eSDavid van Moolenbroek default:
2903*83ee113eSDavid van Moolenbroek done = 1;
2904*83ee113eSDavid van Moolenbroek break;
2905*83ee113eSDavid van Moolenbroek }
2906*83ee113eSDavid van Moolenbroek } while (!done);
2907*83ee113eSDavid van Moolenbroek
2908*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2909*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
2910*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting right brace.");
2911*83ee113eSDavid van Moolenbroek return 0;
2912*83ee113eSDavid van Moolenbroek }
2913*83ee113eSDavid van Moolenbroek return 1;
2914*83ee113eSDavid van Moolenbroek }
2915*83ee113eSDavid van Moolenbroek
2916*83ee113eSDavid van Moolenbroek /* key-statements :== key-statement |
2917*83ee113eSDavid van Moolenbroek key-statement key-statements
2918*83ee113eSDavid van Moolenbroek key-statement :==
2919*83ee113eSDavid van Moolenbroek ALGORITHM host-name SEMI |
2920*83ee113eSDavid van Moolenbroek secret-definition SEMI
2921*83ee113eSDavid van Moolenbroek secret-definition :== SECRET base64val |
2922*83ee113eSDavid van Moolenbroek SECRET STRING */
2923*83ee113eSDavid van Moolenbroek
parse_key(struct parse * cfile)2924*83ee113eSDavid van Moolenbroek int parse_key (struct parse *cfile)
2925*83ee113eSDavid van Moolenbroek {
2926*83ee113eSDavid van Moolenbroek int token;
2927*83ee113eSDavid van Moolenbroek const char *val;
2928*83ee113eSDavid van Moolenbroek int done = 0;
2929*83ee113eSDavid van Moolenbroek struct auth_key *key;
2930*83ee113eSDavid van Moolenbroek struct data_string ds;
2931*83ee113eSDavid van Moolenbroek isc_result_t status;
2932*83ee113eSDavid van Moolenbroek char *s;
2933*83ee113eSDavid van Moolenbroek
2934*83ee113eSDavid van Moolenbroek key = (struct auth_key *)0;
2935*83ee113eSDavid van Moolenbroek if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2936*83ee113eSDavid van Moolenbroek log_fatal ("no memory for key");
2937*83ee113eSDavid van Moolenbroek
2938*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
2939*83ee113eSDavid van Moolenbroek if (token == STRING) {
2940*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
2941*83ee113eSDavid van Moolenbroek key -> name = dmalloc (strlen (val) + 1, MDL);
2942*83ee113eSDavid van Moolenbroek if (!key -> name)
2943*83ee113eSDavid van Moolenbroek log_fatal ("no memory for key name.");
2944*83ee113eSDavid van Moolenbroek strcpy (key -> name, val);
2945*83ee113eSDavid van Moolenbroek
2946*83ee113eSDavid van Moolenbroek } else {
2947*83ee113eSDavid van Moolenbroek key -> name = parse_host_name (cfile);
2948*83ee113eSDavid van Moolenbroek if (!key -> name) {
2949*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting key name.");
2950*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
2951*83ee113eSDavid van Moolenbroek goto bad;
2952*83ee113eSDavid van Moolenbroek }
2953*83ee113eSDavid van Moolenbroek }
2954*83ee113eSDavid van Moolenbroek
2955*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2956*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
2957*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting left brace");
2958*83ee113eSDavid van Moolenbroek goto bad;
2959*83ee113eSDavid van Moolenbroek }
2960*83ee113eSDavid van Moolenbroek
2961*83ee113eSDavid van Moolenbroek do {
2962*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
2963*83ee113eSDavid van Moolenbroek switch (token) {
2964*83ee113eSDavid van Moolenbroek case ALGORITHM:
2965*83ee113eSDavid van Moolenbroek if (key -> algorithm) {
2966*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2967*83ee113eSDavid van Moolenbroek "key %s: too many algorithms",
2968*83ee113eSDavid van Moolenbroek key -> name);
2969*83ee113eSDavid van Moolenbroek goto rbad;
2970*83ee113eSDavid van Moolenbroek }
2971*83ee113eSDavid van Moolenbroek key -> algorithm = parse_host_name (cfile);
2972*83ee113eSDavid van Moolenbroek if (!key -> algorithm) {
2973*83ee113eSDavid van Moolenbroek parse_warn (cfile,
2974*83ee113eSDavid van Moolenbroek "expecting key algorithm name.");
2975*83ee113eSDavid van Moolenbroek goto rbad;
2976*83ee113eSDavid van Moolenbroek }
2977*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile))
2978*83ee113eSDavid van Moolenbroek goto rbad;
2979*83ee113eSDavid van Moolenbroek /* If the algorithm name isn't an FQDN, tack on
2980*83ee113eSDavid van Moolenbroek the .SIG-ALG.REG.NET. domain. */
2981*83ee113eSDavid van Moolenbroek s = strrchr (key -> algorithm, '.');
2982*83ee113eSDavid van Moolenbroek if (!s) {
2983*83ee113eSDavid van Moolenbroek static char add [] = ".SIG-ALG.REG.INT.";
2984*83ee113eSDavid van Moolenbroek s = dmalloc (strlen (key -> algorithm) +
2985*83ee113eSDavid van Moolenbroek sizeof (add), MDL);
2986*83ee113eSDavid van Moolenbroek if (!s) {
2987*83ee113eSDavid van Moolenbroek log_error ("no memory for key %s.",
2988*83ee113eSDavid van Moolenbroek "algorithm");
2989*83ee113eSDavid van Moolenbroek goto rbad;
2990*83ee113eSDavid van Moolenbroek }
2991*83ee113eSDavid van Moolenbroek strcpy (s, key -> algorithm);
2992*83ee113eSDavid van Moolenbroek strcat (s, add);
2993*83ee113eSDavid van Moolenbroek dfree (key -> algorithm, MDL);
2994*83ee113eSDavid van Moolenbroek key -> algorithm = s;
2995*83ee113eSDavid van Moolenbroek } else if (s [1]) {
2996*83ee113eSDavid van Moolenbroek /* If there is no trailing '.', hack one in. */
2997*83ee113eSDavid van Moolenbroek s = dmalloc (strlen (key -> algorithm) + 2, MDL);
2998*83ee113eSDavid van Moolenbroek if (!s) {
2999*83ee113eSDavid van Moolenbroek log_error ("no memory for key %s.",
3000*83ee113eSDavid van Moolenbroek key -> algorithm);
3001*83ee113eSDavid van Moolenbroek goto rbad;
3002*83ee113eSDavid van Moolenbroek }
3003*83ee113eSDavid van Moolenbroek strcpy (s, key -> algorithm);
3004*83ee113eSDavid van Moolenbroek strcat (s, ".");
3005*83ee113eSDavid van Moolenbroek dfree (key -> algorithm, MDL);
3006*83ee113eSDavid van Moolenbroek key -> algorithm = s;
3007*83ee113eSDavid van Moolenbroek }
3008*83ee113eSDavid van Moolenbroek break;
3009*83ee113eSDavid van Moolenbroek
3010*83ee113eSDavid van Moolenbroek case SECRET:
3011*83ee113eSDavid van Moolenbroek if (key -> key) {
3012*83ee113eSDavid van Moolenbroek parse_warn (cfile, "key %s: too many secrets",
3013*83ee113eSDavid van Moolenbroek key -> name);
3014*83ee113eSDavid van Moolenbroek goto rbad;
3015*83ee113eSDavid van Moolenbroek }
3016*83ee113eSDavid van Moolenbroek
3017*83ee113eSDavid van Moolenbroek memset (&ds, 0, sizeof(ds));
3018*83ee113eSDavid van Moolenbroek if (!parse_base64 (&ds, cfile))
3019*83ee113eSDavid van Moolenbroek goto rbad;
3020*83ee113eSDavid van Moolenbroek status = omapi_data_string_new (&key -> key, ds.len,
3021*83ee113eSDavid van Moolenbroek MDL);
3022*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS)
3023*83ee113eSDavid van Moolenbroek goto rbad;
3024*83ee113eSDavid van Moolenbroek memcpy (key -> key -> value,
3025*83ee113eSDavid van Moolenbroek ds.buffer -> data, ds.len);
3026*83ee113eSDavid van Moolenbroek data_string_forget (&ds, MDL);
3027*83ee113eSDavid van Moolenbroek
3028*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile))
3029*83ee113eSDavid van Moolenbroek goto rbad;
3030*83ee113eSDavid van Moolenbroek break;
3031*83ee113eSDavid van Moolenbroek
3032*83ee113eSDavid van Moolenbroek default:
3033*83ee113eSDavid van Moolenbroek done = 1;
3034*83ee113eSDavid van Moolenbroek break;
3035*83ee113eSDavid van Moolenbroek }
3036*83ee113eSDavid van Moolenbroek } while (!done);
3037*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
3038*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting right brace.");
3039*83ee113eSDavid van Moolenbroek goto rbad;
3040*83ee113eSDavid van Moolenbroek }
3041*83ee113eSDavid van Moolenbroek /* Allow the BIND 8 syntax, which has a semicolon after each
3042*83ee113eSDavid van Moolenbroek closing brace. */
3043*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
3044*83ee113eSDavid van Moolenbroek if (token == SEMI) {
3045*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3046*83ee113eSDavid van Moolenbroek }
3047*83ee113eSDavid van Moolenbroek
3048*83ee113eSDavid van Moolenbroek /* Remember the key. */
3049*83ee113eSDavid van Moolenbroek status = omapi_auth_key_enter (key);
3050*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS) {
3051*83ee113eSDavid van Moolenbroek parse_warn (cfile, "tsig key %s: %s",
3052*83ee113eSDavid van Moolenbroek key -> name, isc_result_totext (status));
3053*83ee113eSDavid van Moolenbroek goto bad;
3054*83ee113eSDavid van Moolenbroek }
3055*83ee113eSDavid van Moolenbroek omapi_auth_key_dereference (&key, MDL);
3056*83ee113eSDavid van Moolenbroek return 1;
3057*83ee113eSDavid van Moolenbroek
3058*83ee113eSDavid van Moolenbroek rbad:
3059*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 1);
3060*83ee113eSDavid van Moolenbroek bad:
3061*83ee113eSDavid van Moolenbroek omapi_auth_key_dereference (&key, MDL);
3062*83ee113eSDavid van Moolenbroek return 0;
3063*83ee113eSDavid van Moolenbroek }
3064*83ee113eSDavid van Moolenbroek
3065*83ee113eSDavid van Moolenbroek /*
3066*83ee113eSDavid van Moolenbroek * on-statement :== event-types LBRACE executable-statements RBRACE
3067*83ee113eSDavid van Moolenbroek * event-types :== event-type OR event-types |
3068*83ee113eSDavid van Moolenbroek * event-type
3069*83ee113eSDavid van Moolenbroek * event-type :== EXPIRY | COMMIT | RELEASE
3070*83ee113eSDavid van Moolenbroek */
3071*83ee113eSDavid van Moolenbroek
parse_on_statement(result,cfile,lose)3072*83ee113eSDavid van Moolenbroek int parse_on_statement (result, cfile, lose)
3073*83ee113eSDavid van Moolenbroek struct executable_statement **result;
3074*83ee113eSDavid van Moolenbroek struct parse *cfile;
3075*83ee113eSDavid van Moolenbroek int *lose;
3076*83ee113eSDavid van Moolenbroek {
3077*83ee113eSDavid van Moolenbroek enum dhcp_token token;
3078*83ee113eSDavid van Moolenbroek const char *val;
3079*83ee113eSDavid van Moolenbroek
3080*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
3081*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new statement.");
3082*83ee113eSDavid van Moolenbroek (*result) -> op = on_statement;
3083*83ee113eSDavid van Moolenbroek
3084*83ee113eSDavid van Moolenbroek do {
3085*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3086*83ee113eSDavid van Moolenbroek switch (token) {
3087*83ee113eSDavid van Moolenbroek case EXPIRY:
3088*83ee113eSDavid van Moolenbroek (*result) -> data.on.evtypes |= ON_EXPIRY;
3089*83ee113eSDavid van Moolenbroek break;
3090*83ee113eSDavid van Moolenbroek
3091*83ee113eSDavid van Moolenbroek case COMMIT:
3092*83ee113eSDavid van Moolenbroek (*result) -> data.on.evtypes |= ON_COMMIT;
3093*83ee113eSDavid van Moolenbroek break;
3094*83ee113eSDavid van Moolenbroek
3095*83ee113eSDavid van Moolenbroek case RELEASE:
3096*83ee113eSDavid van Moolenbroek (*result) -> data.on.evtypes |= ON_RELEASE;
3097*83ee113eSDavid van Moolenbroek break;
3098*83ee113eSDavid van Moolenbroek
3099*83ee113eSDavid van Moolenbroek case TRANSMISSION:
3100*83ee113eSDavid van Moolenbroek (*result) -> data.on.evtypes |= ON_TRANSMISSION;
3101*83ee113eSDavid van Moolenbroek break;
3102*83ee113eSDavid van Moolenbroek
3103*83ee113eSDavid van Moolenbroek default:
3104*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting a lease event type");
3105*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3106*83ee113eSDavid van Moolenbroek *lose = 1;
3107*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3108*83ee113eSDavid van Moolenbroek return 0;
3109*83ee113eSDavid van Moolenbroek }
3110*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3111*83ee113eSDavid van Moolenbroek } while (token == OR);
3112*83ee113eSDavid van Moolenbroek
3113*83ee113eSDavid van Moolenbroek /* Semicolon means no statements. */
3114*83ee113eSDavid van Moolenbroek if (token == SEMI)
3115*83ee113eSDavid van Moolenbroek return 1;
3116*83ee113eSDavid van Moolenbroek
3117*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
3118*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left brace expected.");
3119*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3120*83ee113eSDavid van Moolenbroek *lose = 1;
3121*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3122*83ee113eSDavid van Moolenbroek return 0;
3123*83ee113eSDavid van Moolenbroek }
3124*83ee113eSDavid van Moolenbroek if (!parse_executable_statements (&(*result) -> data.on.statements,
3125*83ee113eSDavid van Moolenbroek cfile, lose, context_any)) {
3126*83ee113eSDavid van Moolenbroek if (*lose) {
3127*83ee113eSDavid van Moolenbroek /* Try to even things up. */
3128*83ee113eSDavid van Moolenbroek do {
3129*83ee113eSDavid van Moolenbroek token = next_token (&val,
3130*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
3131*83ee113eSDavid van Moolenbroek } while (token != END_OF_FILE && token != RBRACE);
3132*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3133*83ee113eSDavid van Moolenbroek return 0;
3134*83ee113eSDavid van Moolenbroek }
3135*83ee113eSDavid van Moolenbroek }
3136*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3137*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
3138*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right brace expected.");
3139*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3140*83ee113eSDavid van Moolenbroek *lose = 1;
3141*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3142*83ee113eSDavid van Moolenbroek return 0;
3143*83ee113eSDavid van Moolenbroek }
3144*83ee113eSDavid van Moolenbroek return 1;
3145*83ee113eSDavid van Moolenbroek }
3146*83ee113eSDavid van Moolenbroek
3147*83ee113eSDavid van Moolenbroek /*
3148*83ee113eSDavid van Moolenbroek * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3149*83ee113eSDavid van Moolenbroek *
3150*83ee113eSDavid van Moolenbroek */
3151*83ee113eSDavid van Moolenbroek
parse_switch_statement(result,cfile,lose)3152*83ee113eSDavid van Moolenbroek int parse_switch_statement (result, cfile, lose)
3153*83ee113eSDavid van Moolenbroek struct executable_statement **result;
3154*83ee113eSDavid van Moolenbroek struct parse *cfile;
3155*83ee113eSDavid van Moolenbroek int *lose;
3156*83ee113eSDavid van Moolenbroek {
3157*83ee113eSDavid van Moolenbroek enum dhcp_token token;
3158*83ee113eSDavid van Moolenbroek const char *val;
3159*83ee113eSDavid van Moolenbroek
3160*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
3161*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new statement.");
3162*83ee113eSDavid van Moolenbroek (*result) -> op = switch_statement;
3163*83ee113eSDavid van Moolenbroek
3164*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3165*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
3166*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting left brace.");
3167*83ee113eSDavid van Moolenbroek pfui:
3168*83ee113eSDavid van Moolenbroek *lose = 1;
3169*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3170*83ee113eSDavid van Moolenbroek gnorf:
3171*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3172*83ee113eSDavid van Moolenbroek return 0;
3173*83ee113eSDavid van Moolenbroek }
3174*83ee113eSDavid van Moolenbroek
3175*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*result) -> data.s_switch.expr,
3176*83ee113eSDavid van Moolenbroek cfile, lose, context_data_or_numeric,
3177*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none)) {
3178*83ee113eSDavid van Moolenbroek if (!*lose) {
3179*83ee113eSDavid van Moolenbroek parse_warn (cfile,
3180*83ee113eSDavid van Moolenbroek "expecting data or numeric expression.");
3181*83ee113eSDavid van Moolenbroek goto pfui;
3182*83ee113eSDavid van Moolenbroek }
3183*83ee113eSDavid van Moolenbroek goto gnorf;
3184*83ee113eSDavid van Moolenbroek }
3185*83ee113eSDavid van Moolenbroek
3186*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3187*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
3188*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right paren expected.");
3189*83ee113eSDavid van Moolenbroek goto pfui;
3190*83ee113eSDavid van Moolenbroek }
3191*83ee113eSDavid van Moolenbroek
3192*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3193*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
3194*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left brace expected.");
3195*83ee113eSDavid van Moolenbroek goto pfui;
3196*83ee113eSDavid van Moolenbroek }
3197*83ee113eSDavid van Moolenbroek if (!(parse_executable_statements
3198*83ee113eSDavid van Moolenbroek (&(*result) -> data.s_switch.statements, cfile, lose,
3199*83ee113eSDavid van Moolenbroek (is_data_expression ((*result) -> data.s_switch.expr)
3200*83ee113eSDavid van Moolenbroek ? context_data : context_numeric)))) {
3201*83ee113eSDavid van Moolenbroek if (*lose) {
3202*83ee113eSDavid van Moolenbroek skip_to_rbrace (cfile, 1);
3203*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3204*83ee113eSDavid van Moolenbroek return 0;
3205*83ee113eSDavid van Moolenbroek }
3206*83ee113eSDavid van Moolenbroek }
3207*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3208*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
3209*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right brace expected.");
3210*83ee113eSDavid van Moolenbroek goto pfui;
3211*83ee113eSDavid van Moolenbroek }
3212*83ee113eSDavid van Moolenbroek return 1;
3213*83ee113eSDavid van Moolenbroek }
3214*83ee113eSDavid van Moolenbroek
3215*83ee113eSDavid van Moolenbroek /*
3216*83ee113eSDavid van Moolenbroek * case-statement :== CASE expr COLON
3217*83ee113eSDavid van Moolenbroek *
3218*83ee113eSDavid van Moolenbroek */
3219*83ee113eSDavid van Moolenbroek
parse_case_statement(result,cfile,lose,case_context)3220*83ee113eSDavid van Moolenbroek int parse_case_statement (result, cfile, lose, case_context)
3221*83ee113eSDavid van Moolenbroek struct executable_statement **result;
3222*83ee113eSDavid van Moolenbroek struct parse *cfile;
3223*83ee113eSDavid van Moolenbroek int *lose;
3224*83ee113eSDavid van Moolenbroek enum expression_context case_context;
3225*83ee113eSDavid van Moolenbroek {
3226*83ee113eSDavid van Moolenbroek enum dhcp_token token;
3227*83ee113eSDavid van Moolenbroek const char *val;
3228*83ee113eSDavid van Moolenbroek
3229*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
3230*83ee113eSDavid van Moolenbroek log_fatal ("no memory for new statement.");
3231*83ee113eSDavid van Moolenbroek (*result) -> op = case_statement;
3232*83ee113eSDavid van Moolenbroek
3233*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*result) -> data.c_case,
3234*83ee113eSDavid van Moolenbroek cfile, lose, case_context,
3235*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none))
3236*83ee113eSDavid van Moolenbroek {
3237*83ee113eSDavid van Moolenbroek if (!*lose) {
3238*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting %s expression.",
3239*83ee113eSDavid van Moolenbroek (case_context == context_data
3240*83ee113eSDavid van Moolenbroek ? "data" : "numeric"));
3241*83ee113eSDavid van Moolenbroek }
3242*83ee113eSDavid van Moolenbroek pfui:
3243*83ee113eSDavid van Moolenbroek *lose = 1;
3244*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3245*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3246*83ee113eSDavid van Moolenbroek return 0;
3247*83ee113eSDavid van Moolenbroek }
3248*83ee113eSDavid van Moolenbroek
3249*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3250*83ee113eSDavid van Moolenbroek if (token != COLON) {
3251*83ee113eSDavid van Moolenbroek parse_warn (cfile, "colon expected.");
3252*83ee113eSDavid van Moolenbroek goto pfui;
3253*83ee113eSDavid van Moolenbroek }
3254*83ee113eSDavid van Moolenbroek return 1;
3255*83ee113eSDavid van Moolenbroek }
3256*83ee113eSDavid van Moolenbroek
3257*83ee113eSDavid van Moolenbroek /*
3258*83ee113eSDavid van Moolenbroek * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3259*83ee113eSDavid van Moolenbroek * else-statement
3260*83ee113eSDavid van Moolenbroek *
3261*83ee113eSDavid van Moolenbroek * else-statement :== <null> |
3262*83ee113eSDavid van Moolenbroek * ELSE LBRACE executable-statements RBRACE |
3263*83ee113eSDavid van Moolenbroek * ELSE IF if-statement |
3264*83ee113eSDavid van Moolenbroek * ELSIF if-statement
3265*83ee113eSDavid van Moolenbroek */
3266*83ee113eSDavid van Moolenbroek
parse_if_statement(result,cfile,lose)3267*83ee113eSDavid van Moolenbroek int parse_if_statement (result, cfile, lose)
3268*83ee113eSDavid van Moolenbroek struct executable_statement **result;
3269*83ee113eSDavid van Moolenbroek struct parse *cfile;
3270*83ee113eSDavid van Moolenbroek int *lose;
3271*83ee113eSDavid van Moolenbroek {
3272*83ee113eSDavid van Moolenbroek enum dhcp_token token;
3273*83ee113eSDavid van Moolenbroek const char *val;
3274*83ee113eSDavid van Moolenbroek int parenp;
3275*83ee113eSDavid van Moolenbroek
3276*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
3277*83ee113eSDavid van Moolenbroek log_fatal ("no memory for if statement.");
3278*83ee113eSDavid van Moolenbroek
3279*83ee113eSDavid van Moolenbroek (*result) -> op = if_statement;
3280*83ee113eSDavid van Moolenbroek
3281*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
3282*83ee113eSDavid van Moolenbroek if (token == LPAREN) {
3283*83ee113eSDavid van Moolenbroek parenp = 1;
3284*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3285*83ee113eSDavid van Moolenbroek } else
3286*83ee113eSDavid van Moolenbroek parenp = 0;
3287*83ee113eSDavid van Moolenbroek
3288*83ee113eSDavid van Moolenbroek
3289*83ee113eSDavid van Moolenbroek if (!parse_boolean_expression (&(*result) -> data.ie.expr,
3290*83ee113eSDavid van Moolenbroek cfile, lose)) {
3291*83ee113eSDavid van Moolenbroek if (!*lose)
3292*83ee113eSDavid van Moolenbroek parse_warn (cfile, "boolean expression expected.");
3293*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3294*83ee113eSDavid van Moolenbroek *lose = 1;
3295*83ee113eSDavid van Moolenbroek return 0;
3296*83ee113eSDavid van Moolenbroek }
3297*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSION_PARSE)
3298*83ee113eSDavid van Moolenbroek print_expression ("if condition", (*result) -> data.ie.expr);
3299*83ee113eSDavid van Moolenbroek #endif
3300*83ee113eSDavid van Moolenbroek if (parenp) {
3301*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3302*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
3303*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting right paren.");
3304*83ee113eSDavid van Moolenbroek *lose = 1;
3305*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3306*83ee113eSDavid van Moolenbroek return 0;
3307*83ee113eSDavid van Moolenbroek }
3308*83ee113eSDavid van Moolenbroek }
3309*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3310*83ee113eSDavid van Moolenbroek if (token != LBRACE) {
3311*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left brace expected.");
3312*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3313*83ee113eSDavid van Moolenbroek *lose = 1;
3314*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3315*83ee113eSDavid van Moolenbroek return 0;
3316*83ee113eSDavid van Moolenbroek }
3317*83ee113eSDavid van Moolenbroek if (!parse_executable_statements (&(*result) -> data.ie.tc,
3318*83ee113eSDavid van Moolenbroek cfile, lose, context_any)) {
3319*83ee113eSDavid van Moolenbroek if (*lose) {
3320*83ee113eSDavid van Moolenbroek /* Try to even things up. */
3321*83ee113eSDavid van Moolenbroek do {
3322*83ee113eSDavid van Moolenbroek token = next_token (&val,
3323*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
3324*83ee113eSDavid van Moolenbroek } while (token != END_OF_FILE && token != RBRACE);
3325*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3326*83ee113eSDavid van Moolenbroek return 0;
3327*83ee113eSDavid van Moolenbroek }
3328*83ee113eSDavid van Moolenbroek }
3329*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3330*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
3331*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right brace expected.");
3332*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3333*83ee113eSDavid van Moolenbroek *lose = 1;
3334*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3335*83ee113eSDavid van Moolenbroek return 0;
3336*83ee113eSDavid van Moolenbroek }
3337*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
3338*83ee113eSDavid van Moolenbroek if (token == ELSE) {
3339*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3340*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
3341*83ee113eSDavid van Moolenbroek if (token == IF) {
3342*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3343*83ee113eSDavid van Moolenbroek if (!parse_if_statement (&(*result) -> data.ie.fc,
3344*83ee113eSDavid van Moolenbroek cfile, lose)) {
3345*83ee113eSDavid van Moolenbroek if (!*lose)
3346*83ee113eSDavid van Moolenbroek parse_warn (cfile,
3347*83ee113eSDavid van Moolenbroek "expecting if statement");
3348*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3349*83ee113eSDavid van Moolenbroek *lose = 1;
3350*83ee113eSDavid van Moolenbroek return 0;
3351*83ee113eSDavid van Moolenbroek }
3352*83ee113eSDavid van Moolenbroek } else if (token != LBRACE) {
3353*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left brace or if expected.");
3354*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3355*83ee113eSDavid van Moolenbroek *lose = 1;
3356*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3357*83ee113eSDavid van Moolenbroek return 0;
3358*83ee113eSDavid van Moolenbroek } else {
3359*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3360*83ee113eSDavid van Moolenbroek if (!(parse_executable_statements
3361*83ee113eSDavid van Moolenbroek (&(*result) -> data.ie.fc,
3362*83ee113eSDavid van Moolenbroek cfile, lose, context_any))) {
3363*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3364*83ee113eSDavid van Moolenbroek return 0;
3365*83ee113eSDavid van Moolenbroek }
3366*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3367*83ee113eSDavid van Moolenbroek if (token != RBRACE) {
3368*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right brace expected.");
3369*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3370*83ee113eSDavid van Moolenbroek *lose = 1;
3371*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3372*83ee113eSDavid van Moolenbroek return 0;
3373*83ee113eSDavid van Moolenbroek }
3374*83ee113eSDavid van Moolenbroek }
3375*83ee113eSDavid van Moolenbroek } else if (token == ELSIF) {
3376*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3377*83ee113eSDavid van Moolenbroek if (!parse_if_statement (&(*result) -> data.ie.fc,
3378*83ee113eSDavid van Moolenbroek cfile, lose)) {
3379*83ee113eSDavid van Moolenbroek if (!*lose)
3380*83ee113eSDavid van Moolenbroek parse_warn (cfile,
3381*83ee113eSDavid van Moolenbroek "expecting conditional.");
3382*83ee113eSDavid van Moolenbroek executable_statement_dereference (result, MDL);
3383*83ee113eSDavid van Moolenbroek *lose = 1;
3384*83ee113eSDavid van Moolenbroek return 0;
3385*83ee113eSDavid van Moolenbroek }
3386*83ee113eSDavid van Moolenbroek } else
3387*83ee113eSDavid van Moolenbroek (*result) -> data.ie.fc = (struct executable_statement *)0;
3388*83ee113eSDavid van Moolenbroek
3389*83ee113eSDavid van Moolenbroek return 1;
3390*83ee113eSDavid van Moolenbroek }
3391*83ee113eSDavid van Moolenbroek
3392*83ee113eSDavid van Moolenbroek /*
3393*83ee113eSDavid van Moolenbroek * boolean_expression :== CHECK STRING |
3394*83ee113eSDavid van Moolenbroek * NOT boolean-expression |
3395*83ee113eSDavid van Moolenbroek * data-expression EQUAL data-expression |
3396*83ee113eSDavid van Moolenbroek * data-expression BANG EQUAL data-expression |
3397*83ee113eSDavid van Moolenbroek * data-expression REGEX_MATCH data-expression |
3398*83ee113eSDavid van Moolenbroek * boolean-expression AND boolean-expression |
3399*83ee113eSDavid van Moolenbroek * boolean-expression OR boolean-expression
3400*83ee113eSDavid van Moolenbroek * EXISTS OPTION-NAME
3401*83ee113eSDavid van Moolenbroek */
3402*83ee113eSDavid van Moolenbroek
parse_boolean_expression(expr,cfile,lose)3403*83ee113eSDavid van Moolenbroek int parse_boolean_expression (expr, cfile, lose)
3404*83ee113eSDavid van Moolenbroek struct expression **expr;
3405*83ee113eSDavid van Moolenbroek struct parse *cfile;
3406*83ee113eSDavid van Moolenbroek int *lose;
3407*83ee113eSDavid van Moolenbroek {
3408*83ee113eSDavid van Moolenbroek /* Parse an expression... */
3409*83ee113eSDavid van Moolenbroek if (!parse_expression (expr, cfile, lose, context_boolean,
3410*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none))
3411*83ee113eSDavid van Moolenbroek return 0;
3412*83ee113eSDavid van Moolenbroek
3413*83ee113eSDavid van Moolenbroek if (!is_boolean_expression (*expr) &&
3414*83ee113eSDavid van Moolenbroek (*expr) -> op != expr_variable_reference &&
3415*83ee113eSDavid van Moolenbroek (*expr) -> op != expr_funcall) {
3416*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Expecting a boolean expression.");
3417*83ee113eSDavid van Moolenbroek *lose = 1;
3418*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3419*83ee113eSDavid van Moolenbroek return 0;
3420*83ee113eSDavid van Moolenbroek }
3421*83ee113eSDavid van Moolenbroek return 1;
3422*83ee113eSDavid van Moolenbroek }
3423*83ee113eSDavid van Moolenbroek
3424*83ee113eSDavid van Moolenbroek /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3425*83ee113eSDavid van Moolenbroek
parse_boolean(cfile)3426*83ee113eSDavid van Moolenbroek int parse_boolean (cfile)
3427*83ee113eSDavid van Moolenbroek struct parse *cfile;
3428*83ee113eSDavid van Moolenbroek {
3429*83ee113eSDavid van Moolenbroek const char *val;
3430*83ee113eSDavid van Moolenbroek int rv;
3431*83ee113eSDavid van Moolenbroek
3432*83ee113eSDavid van Moolenbroek (void)next_token(&val, NULL, cfile);
3433*83ee113eSDavid van Moolenbroek if (!strcasecmp (val, "true")
3434*83ee113eSDavid van Moolenbroek || !strcasecmp (val, "on"))
3435*83ee113eSDavid van Moolenbroek rv = 1;
3436*83ee113eSDavid van Moolenbroek else if (!strcasecmp (val, "false")
3437*83ee113eSDavid van Moolenbroek || !strcasecmp (val, "off"))
3438*83ee113eSDavid van Moolenbroek rv = 0;
3439*83ee113eSDavid van Moolenbroek else {
3440*83ee113eSDavid van Moolenbroek parse_warn (cfile,
3441*83ee113eSDavid van Moolenbroek "boolean value (true/false/on/off) expected");
3442*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3443*83ee113eSDavid van Moolenbroek return 0;
3444*83ee113eSDavid van Moolenbroek }
3445*83ee113eSDavid van Moolenbroek parse_semi (cfile);
3446*83ee113eSDavid van Moolenbroek return rv;
3447*83ee113eSDavid van Moolenbroek }
3448*83ee113eSDavid van Moolenbroek
3449*83ee113eSDavid van Moolenbroek
3450*83ee113eSDavid van Moolenbroek /*
3451*83ee113eSDavid van Moolenbroek * data_expression :== SUBSTRING LPAREN data-expression COMMA
3452*83ee113eSDavid van Moolenbroek * numeric-expression COMMA
3453*83ee113eSDavid van Moolenbroek * numeric-expression RPAREN |
3454*83ee113eSDavid van Moolenbroek * CONCAT LPAREN data-expression COMMA
3455*83ee113eSDavid van Moolenbroek * data-expression RPAREN
3456*83ee113eSDavid van Moolenbroek * SUFFIX LPAREN data_expression COMMA
3457*83ee113eSDavid van Moolenbroek * numeric-expression RPAREN |
3458*83ee113eSDavid van Moolenbroek * LCASE LPAREN data_expression RPAREN |
3459*83ee113eSDavid van Moolenbroek * UCASE LPAREN data_expression RPAREN |
3460*83ee113eSDavid van Moolenbroek * OPTION option_name |
3461*83ee113eSDavid van Moolenbroek * HARDWARE |
3462*83ee113eSDavid van Moolenbroek * PACKET LPAREN numeric-expression COMMA
3463*83ee113eSDavid van Moolenbroek * numeric-expression RPAREN |
3464*83ee113eSDavid van Moolenbroek * V6RELAY LPAREN numeric-expression COMMA
3465*83ee113eSDavid van Moolenbroek * data-expression RPAREN |
3466*83ee113eSDavid van Moolenbroek * STRING |
3467*83ee113eSDavid van Moolenbroek * colon_separated_hex_list
3468*83ee113eSDavid van Moolenbroek */
3469*83ee113eSDavid van Moolenbroek
parse_data_expression(expr,cfile,lose)3470*83ee113eSDavid van Moolenbroek int parse_data_expression (expr, cfile, lose)
3471*83ee113eSDavid van Moolenbroek struct expression **expr;
3472*83ee113eSDavid van Moolenbroek struct parse *cfile;
3473*83ee113eSDavid van Moolenbroek int *lose;
3474*83ee113eSDavid van Moolenbroek {
3475*83ee113eSDavid van Moolenbroek /* Parse an expression... */
3476*83ee113eSDavid van Moolenbroek if (!parse_expression (expr, cfile, lose, context_data,
3477*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none))
3478*83ee113eSDavid van Moolenbroek return 0;
3479*83ee113eSDavid van Moolenbroek
3480*83ee113eSDavid van Moolenbroek if (!is_data_expression (*expr) &&
3481*83ee113eSDavid van Moolenbroek (*expr) -> op != expr_variable_reference &&
3482*83ee113eSDavid van Moolenbroek (*expr) -> op != expr_funcall) {
3483*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3484*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Expecting a data expression.");
3485*83ee113eSDavid van Moolenbroek *lose = 1;
3486*83ee113eSDavid van Moolenbroek return 0;
3487*83ee113eSDavid van Moolenbroek }
3488*83ee113eSDavid van Moolenbroek return 1;
3489*83ee113eSDavid van Moolenbroek }
3490*83ee113eSDavid van Moolenbroek
3491*83ee113eSDavid van Moolenbroek /*
3492*83ee113eSDavid van Moolenbroek * numeric-expression :== EXTRACT_INT LPAREN data-expression
3493*83ee113eSDavid van Moolenbroek * COMMA number RPAREN |
3494*83ee113eSDavid van Moolenbroek * NUMBER
3495*83ee113eSDavid van Moolenbroek */
3496*83ee113eSDavid van Moolenbroek
parse_numeric_expression(expr,cfile,lose)3497*83ee113eSDavid van Moolenbroek int parse_numeric_expression (expr, cfile, lose)
3498*83ee113eSDavid van Moolenbroek struct expression **expr;
3499*83ee113eSDavid van Moolenbroek struct parse *cfile;
3500*83ee113eSDavid van Moolenbroek int *lose;
3501*83ee113eSDavid van Moolenbroek {
3502*83ee113eSDavid van Moolenbroek /* Parse an expression... */
3503*83ee113eSDavid van Moolenbroek if (!parse_expression (expr, cfile, lose, context_numeric,
3504*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none))
3505*83ee113eSDavid van Moolenbroek return 0;
3506*83ee113eSDavid van Moolenbroek
3507*83ee113eSDavid van Moolenbroek if (!is_numeric_expression (*expr) &&
3508*83ee113eSDavid van Moolenbroek (*expr) -> op != expr_variable_reference &&
3509*83ee113eSDavid van Moolenbroek (*expr) -> op != expr_funcall) {
3510*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3511*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Expecting a numeric expression.");
3512*83ee113eSDavid van Moolenbroek *lose = 1;
3513*83ee113eSDavid van Moolenbroek return 0;
3514*83ee113eSDavid van Moolenbroek }
3515*83ee113eSDavid van Moolenbroek return 1;
3516*83ee113eSDavid van Moolenbroek }
3517*83ee113eSDavid van Moolenbroek
3518*83ee113eSDavid van Moolenbroek /* Parse a subexpression that does not contain a binary operator. */
3519*83ee113eSDavid van Moolenbroek
parse_non_binary(expr,cfile,lose,context)3520*83ee113eSDavid van Moolenbroek int parse_non_binary (expr, cfile, lose, context)
3521*83ee113eSDavid van Moolenbroek struct expression **expr;
3522*83ee113eSDavid van Moolenbroek struct parse *cfile;
3523*83ee113eSDavid van Moolenbroek int *lose;
3524*83ee113eSDavid van Moolenbroek enum expression_context context;
3525*83ee113eSDavid van Moolenbroek {
3526*83ee113eSDavid van Moolenbroek enum dhcp_token token;
3527*83ee113eSDavid van Moolenbroek const char *val;
3528*83ee113eSDavid van Moolenbroek struct collection *col;
3529*83ee113eSDavid van Moolenbroek struct expression *nexp, **ep;
3530*83ee113eSDavid van Moolenbroek int known;
3531*83ee113eSDavid van Moolenbroek char *cptr;
3532*83ee113eSDavid van Moolenbroek isc_result_t status;
3533*83ee113eSDavid van Moolenbroek unsigned len;
3534*83ee113eSDavid van Moolenbroek
3535*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
3536*83ee113eSDavid van Moolenbroek
3537*83ee113eSDavid van Moolenbroek /* Check for unary operators... */
3538*83ee113eSDavid van Moolenbroek switch (token) {
3539*83ee113eSDavid van Moolenbroek case CHECK:
3540*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3541*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3542*83ee113eSDavid van Moolenbroek if (token != STRING) {
3543*83ee113eSDavid van Moolenbroek parse_warn (cfile, "string expected.");
3544*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3545*83ee113eSDavid van Moolenbroek *lose = 1;
3546*83ee113eSDavid van Moolenbroek return 0;
3547*83ee113eSDavid van Moolenbroek }
3548*83ee113eSDavid van Moolenbroek for (col = collections; col; col = col -> next)
3549*83ee113eSDavid van Moolenbroek if (!strcmp (col -> name, val))
3550*83ee113eSDavid van Moolenbroek break;
3551*83ee113eSDavid van Moolenbroek if (!col) {
3552*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unknown collection.");
3553*83ee113eSDavid van Moolenbroek *lose = 1;
3554*83ee113eSDavid van Moolenbroek return 0;
3555*83ee113eSDavid van Moolenbroek }
3556*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3557*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3558*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_check;
3559*83ee113eSDavid van Moolenbroek (*expr) -> data.check = col;
3560*83ee113eSDavid van Moolenbroek break;
3561*83ee113eSDavid van Moolenbroek
3562*83ee113eSDavid van Moolenbroek case TOKEN_NOT:
3563*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
3564*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3565*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3566*83ee113eSDavid van Moolenbroek (*expr)->op = expr_not;
3567*83ee113eSDavid van Moolenbroek if (!parse_non_binary (&(*expr)->data.not,
3568*83ee113eSDavid van Moolenbroek cfile, lose, context_boolean)) {
3569*83ee113eSDavid van Moolenbroek if (!*lose) {
3570*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expression expected");
3571*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3572*83ee113eSDavid van Moolenbroek }
3573*83ee113eSDavid van Moolenbroek *lose = 1;
3574*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3575*83ee113eSDavid van Moolenbroek return (0);
3576*83ee113eSDavid van Moolenbroek }
3577*83ee113eSDavid van Moolenbroek if (!is_boolean_expression ((*expr) -> data.not)) {
3578*83ee113eSDavid van Moolenbroek *lose = 1;
3579*83ee113eSDavid van Moolenbroek parse_warn (cfile, "boolean expression expected");
3580*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3581*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3582*83ee113eSDavid van Moolenbroek return 0;
3583*83ee113eSDavid van Moolenbroek }
3584*83ee113eSDavid van Moolenbroek break;
3585*83ee113eSDavid van Moolenbroek
3586*83ee113eSDavid van Moolenbroek case LPAREN:
3587*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3588*83ee113eSDavid van Moolenbroek if (!parse_expression (expr, cfile, lose, context,
3589*83ee113eSDavid van Moolenbroek (struct expression **)0, expr_none)) {
3590*83ee113eSDavid van Moolenbroek if (!*lose) {
3591*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expression expected");
3592*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3593*83ee113eSDavid van Moolenbroek }
3594*83ee113eSDavid van Moolenbroek *lose = 1;
3595*83ee113eSDavid van Moolenbroek return 0;
3596*83ee113eSDavid van Moolenbroek }
3597*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3598*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
3599*83ee113eSDavid van Moolenbroek *lose = 1;
3600*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right paren expected");
3601*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3602*83ee113eSDavid van Moolenbroek return 0;
3603*83ee113eSDavid van Moolenbroek }
3604*83ee113eSDavid van Moolenbroek break;
3605*83ee113eSDavid van Moolenbroek
3606*83ee113eSDavid van Moolenbroek case EXISTS:
3607*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
3608*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3609*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3610*83ee113eSDavid van Moolenbroek (*expr)->op = expr_exists;
3611*83ee113eSDavid van Moolenbroek known = 0;
3612*83ee113eSDavid van Moolenbroek /* Pass reference directly to expression structure. */
3613*83ee113eSDavid van Moolenbroek status = parse_option_name(cfile, 0, &known,
3614*83ee113eSDavid van Moolenbroek &(*expr)->data.option);
3615*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS ||
3616*83ee113eSDavid van Moolenbroek (*expr)->data.option == NULL) {
3617*83ee113eSDavid van Moolenbroek *lose = 1;
3618*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3619*83ee113eSDavid van Moolenbroek return (0);
3620*83ee113eSDavid van Moolenbroek }
3621*83ee113eSDavid van Moolenbroek break;
3622*83ee113eSDavid van Moolenbroek
3623*83ee113eSDavid van Moolenbroek case STATIC:
3624*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3625*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3626*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3627*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_static;
3628*83ee113eSDavid van Moolenbroek break;
3629*83ee113eSDavid van Moolenbroek
3630*83ee113eSDavid van Moolenbroek case KNOWN:
3631*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3632*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3633*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3634*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_known;
3635*83ee113eSDavid van Moolenbroek break;
3636*83ee113eSDavid van Moolenbroek
3637*83ee113eSDavid van Moolenbroek case SUBSTRING:
3638*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3639*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3640*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3641*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_substring;
3642*83ee113eSDavid van Moolenbroek
3643*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3644*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
3645*83ee113eSDavid van Moolenbroek nolparen:
3646*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3647*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left parenthesis expected.");
3648*83ee113eSDavid van Moolenbroek *lose = 1;
3649*83ee113eSDavid van Moolenbroek return 0;
3650*83ee113eSDavid van Moolenbroek }
3651*83ee113eSDavid van Moolenbroek
3652*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.substring.expr,
3653*83ee113eSDavid van Moolenbroek cfile, lose)) {
3654*83ee113eSDavid van Moolenbroek nodata:
3655*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3656*83ee113eSDavid van Moolenbroek if (!*lose) {
3657*83ee113eSDavid van Moolenbroek parse_warn (cfile,
3658*83ee113eSDavid van Moolenbroek "expecting data expression.");
3659*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3660*83ee113eSDavid van Moolenbroek *lose = 1;
3661*83ee113eSDavid van Moolenbroek }
3662*83ee113eSDavid van Moolenbroek return 0;
3663*83ee113eSDavid van Moolenbroek }
3664*83ee113eSDavid van Moolenbroek
3665*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3666*83ee113eSDavid van Moolenbroek if (token != COMMA) {
3667*83ee113eSDavid van Moolenbroek nocomma:
3668*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3669*83ee113eSDavid van Moolenbroek parse_warn (cfile, "comma expected.");
3670*83ee113eSDavid van Moolenbroek *lose = 1;
3671*83ee113eSDavid van Moolenbroek
3672*83ee113eSDavid van Moolenbroek return 0;
3673*83ee113eSDavid van Moolenbroek }
3674*83ee113eSDavid van Moolenbroek
3675*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression
3676*83ee113eSDavid van Moolenbroek (&(*expr) -> data.substring.offset,cfile, lose)) {
3677*83ee113eSDavid van Moolenbroek nonum:
3678*83ee113eSDavid van Moolenbroek if (!*lose) {
3679*83ee113eSDavid van Moolenbroek parse_warn (cfile,
3680*83ee113eSDavid van Moolenbroek "expecting numeric expression.");
3681*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
3682*83ee113eSDavid van Moolenbroek *lose = 1;
3683*83ee113eSDavid van Moolenbroek }
3684*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3685*83ee113eSDavid van Moolenbroek return 0;
3686*83ee113eSDavid van Moolenbroek }
3687*83ee113eSDavid van Moolenbroek
3688*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3689*83ee113eSDavid van Moolenbroek if (token != COMMA)
3690*83ee113eSDavid van Moolenbroek goto nocomma;
3691*83ee113eSDavid van Moolenbroek
3692*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression
3693*83ee113eSDavid van Moolenbroek (&(*expr) -> data.substring.len, cfile, lose))
3694*83ee113eSDavid van Moolenbroek goto nonum;
3695*83ee113eSDavid van Moolenbroek
3696*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3697*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
3698*83ee113eSDavid van Moolenbroek norparen:
3699*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right parenthesis expected.");
3700*83ee113eSDavid van Moolenbroek *lose = 1;
3701*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3702*83ee113eSDavid van Moolenbroek return 0;
3703*83ee113eSDavid van Moolenbroek }
3704*83ee113eSDavid van Moolenbroek break;
3705*83ee113eSDavid van Moolenbroek
3706*83ee113eSDavid van Moolenbroek case SUFFIX:
3707*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3708*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3709*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3710*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_suffix;
3711*83ee113eSDavid van Moolenbroek
3712*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3713*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3714*83ee113eSDavid van Moolenbroek goto nolparen;
3715*83ee113eSDavid van Moolenbroek
3716*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.suffix.expr,
3717*83ee113eSDavid van Moolenbroek cfile, lose))
3718*83ee113eSDavid van Moolenbroek goto nodata;
3719*83ee113eSDavid van Moolenbroek
3720*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3721*83ee113eSDavid van Moolenbroek if (token != COMMA)
3722*83ee113eSDavid van Moolenbroek goto nocomma;
3723*83ee113eSDavid van Moolenbroek
3724*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
3725*83ee113eSDavid van Moolenbroek cfile, lose))
3726*83ee113eSDavid van Moolenbroek goto nonum;
3727*83ee113eSDavid van Moolenbroek
3728*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3729*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3730*83ee113eSDavid van Moolenbroek goto norparen;
3731*83ee113eSDavid van Moolenbroek break;
3732*83ee113eSDavid van Moolenbroek
3733*83ee113eSDavid van Moolenbroek case LCASE:
3734*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3735*83ee113eSDavid van Moolenbroek if (!expression_allocate(expr, MDL))
3736*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3737*83ee113eSDavid van Moolenbroek (*expr)->op = expr_lcase;
3738*83ee113eSDavid van Moolenbroek
3739*83ee113eSDavid van Moolenbroek token = next_token(&val, (unsigned *)0, cfile);
3740*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3741*83ee113eSDavid van Moolenbroek goto nolparen;
3742*83ee113eSDavid van Moolenbroek
3743*83ee113eSDavid van Moolenbroek if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose))
3744*83ee113eSDavid van Moolenbroek goto nodata;
3745*83ee113eSDavid van Moolenbroek
3746*83ee113eSDavid van Moolenbroek token = next_token(&val, (unsigned *)0, cfile);
3747*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3748*83ee113eSDavid van Moolenbroek goto norparen;
3749*83ee113eSDavid van Moolenbroek break;
3750*83ee113eSDavid van Moolenbroek
3751*83ee113eSDavid van Moolenbroek case UCASE:
3752*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3753*83ee113eSDavid van Moolenbroek if (!expression_allocate(expr, MDL))
3754*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3755*83ee113eSDavid van Moolenbroek (*expr)->op = expr_ucase;
3756*83ee113eSDavid van Moolenbroek
3757*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3758*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3759*83ee113eSDavid van Moolenbroek goto nolparen;
3760*83ee113eSDavid van Moolenbroek
3761*83ee113eSDavid van Moolenbroek if (!parse_data_expression(&(*expr)->data.ucase,
3762*83ee113eSDavid van Moolenbroek cfile, lose))
3763*83ee113eSDavid van Moolenbroek goto nodata;
3764*83ee113eSDavid van Moolenbroek
3765*83ee113eSDavid van Moolenbroek token = next_token(&val, (unsigned *)0, cfile);
3766*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3767*83ee113eSDavid van Moolenbroek goto norparen;
3768*83ee113eSDavid van Moolenbroek break;
3769*83ee113eSDavid van Moolenbroek
3770*83ee113eSDavid van Moolenbroek case CONCAT:
3771*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3772*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3773*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3774*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_concat;
3775*83ee113eSDavid van Moolenbroek
3776*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3777*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3778*83ee113eSDavid van Moolenbroek goto nolparen;
3779*83ee113eSDavid van Moolenbroek
3780*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.concat [0],
3781*83ee113eSDavid van Moolenbroek cfile, lose))
3782*83ee113eSDavid van Moolenbroek goto nodata;
3783*83ee113eSDavid van Moolenbroek
3784*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3785*83ee113eSDavid van Moolenbroek if (token != COMMA)
3786*83ee113eSDavid van Moolenbroek goto nocomma;
3787*83ee113eSDavid van Moolenbroek
3788*83ee113eSDavid van Moolenbroek concat_another:
3789*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.concat [1],
3790*83ee113eSDavid van Moolenbroek cfile, lose))
3791*83ee113eSDavid van Moolenbroek goto nodata;
3792*83ee113eSDavid van Moolenbroek
3793*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3794*83ee113eSDavid van Moolenbroek
3795*83ee113eSDavid van Moolenbroek if (token == COMMA) {
3796*83ee113eSDavid van Moolenbroek nexp = (struct expression *)0;
3797*83ee113eSDavid van Moolenbroek if (!expression_allocate (&nexp, MDL))
3798*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate at CONCAT2");
3799*83ee113eSDavid van Moolenbroek nexp -> op = expr_concat;
3800*83ee113eSDavid van Moolenbroek expression_reference (&nexp -> data.concat [0],
3801*83ee113eSDavid van Moolenbroek *expr, MDL);
3802*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3803*83ee113eSDavid van Moolenbroek expression_reference (expr, nexp, MDL);
3804*83ee113eSDavid van Moolenbroek expression_dereference (&nexp, MDL);
3805*83ee113eSDavid van Moolenbroek goto concat_another;
3806*83ee113eSDavid van Moolenbroek }
3807*83ee113eSDavid van Moolenbroek
3808*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3809*83ee113eSDavid van Moolenbroek goto norparen;
3810*83ee113eSDavid van Moolenbroek break;
3811*83ee113eSDavid van Moolenbroek
3812*83ee113eSDavid van Moolenbroek case BINARY_TO_ASCII:
3813*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3814*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3815*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3816*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_binary_to_ascii;
3817*83ee113eSDavid van Moolenbroek
3818*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3819*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3820*83ee113eSDavid van Moolenbroek goto nolparen;
3821*83ee113eSDavid van Moolenbroek
3822*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3823*83ee113eSDavid van Moolenbroek cfile, lose))
3824*83ee113eSDavid van Moolenbroek goto nodata;
3825*83ee113eSDavid van Moolenbroek
3826*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3827*83ee113eSDavid van Moolenbroek if (token != COMMA)
3828*83ee113eSDavid van Moolenbroek goto nocomma;
3829*83ee113eSDavid van Moolenbroek
3830*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3831*83ee113eSDavid van Moolenbroek cfile, lose))
3832*83ee113eSDavid van Moolenbroek goto nodata;
3833*83ee113eSDavid van Moolenbroek
3834*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3835*83ee113eSDavid van Moolenbroek if (token != COMMA)
3836*83ee113eSDavid van Moolenbroek goto nocomma;
3837*83ee113eSDavid van Moolenbroek
3838*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.b2a.separator,
3839*83ee113eSDavid van Moolenbroek cfile, lose))
3840*83ee113eSDavid van Moolenbroek goto nodata;
3841*83ee113eSDavid van Moolenbroek
3842*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3843*83ee113eSDavid van Moolenbroek if (token != COMMA)
3844*83ee113eSDavid van Moolenbroek goto nocomma;
3845*83ee113eSDavid van Moolenbroek
3846*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3847*83ee113eSDavid van Moolenbroek cfile, lose))
3848*83ee113eSDavid van Moolenbroek goto nodata;
3849*83ee113eSDavid van Moolenbroek
3850*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3851*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3852*83ee113eSDavid van Moolenbroek goto norparen;
3853*83ee113eSDavid van Moolenbroek break;
3854*83ee113eSDavid van Moolenbroek
3855*83ee113eSDavid van Moolenbroek case REVERSE:
3856*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3857*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3858*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3859*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_reverse;
3860*83ee113eSDavid van Moolenbroek
3861*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3862*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3863*83ee113eSDavid van Moolenbroek goto nolparen;
3864*83ee113eSDavid van Moolenbroek
3865*83ee113eSDavid van Moolenbroek if (!(parse_numeric_expression
3866*83ee113eSDavid van Moolenbroek (&(*expr) -> data.reverse.width, cfile, lose)))
3867*83ee113eSDavid van Moolenbroek goto nodata;
3868*83ee113eSDavid van Moolenbroek
3869*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3870*83ee113eSDavid van Moolenbroek if (token != COMMA)
3871*83ee113eSDavid van Moolenbroek goto nocomma;
3872*83ee113eSDavid van Moolenbroek
3873*83ee113eSDavid van Moolenbroek if (!(parse_data_expression
3874*83ee113eSDavid van Moolenbroek (&(*expr) -> data.reverse.buffer, cfile, lose)))
3875*83ee113eSDavid van Moolenbroek goto nodata;
3876*83ee113eSDavid van Moolenbroek
3877*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3878*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3879*83ee113eSDavid van Moolenbroek goto norparen;
3880*83ee113eSDavid van Moolenbroek break;
3881*83ee113eSDavid van Moolenbroek
3882*83ee113eSDavid van Moolenbroek case PICK:
3883*83ee113eSDavid van Moolenbroek /* pick (a, b, c) actually produces an internal representation
3884*83ee113eSDavid van Moolenbroek that looks like pick (a, pick (b, pick (c, nil))). */
3885*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3886*83ee113eSDavid van Moolenbroek if (!(expression_allocate (expr, MDL)))
3887*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3888*83ee113eSDavid van Moolenbroek
3889*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3890*83ee113eSDavid van Moolenbroek if (token != LPAREN)
3891*83ee113eSDavid van Moolenbroek goto nolparen;
3892*83ee113eSDavid van Moolenbroek
3893*83ee113eSDavid van Moolenbroek nexp = (struct expression *)0;
3894*83ee113eSDavid van Moolenbroek expression_reference (&nexp, *expr, MDL);
3895*83ee113eSDavid van Moolenbroek do {
3896*83ee113eSDavid van Moolenbroek nexp -> op = expr_pick_first_value;
3897*83ee113eSDavid van Moolenbroek if (!(parse_data_expression
3898*83ee113eSDavid van Moolenbroek (&nexp -> data.pick_first_value.car,
3899*83ee113eSDavid van Moolenbroek cfile, lose)))
3900*83ee113eSDavid van Moolenbroek goto nodata;
3901*83ee113eSDavid van Moolenbroek
3902*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
3903*83ee113eSDavid van Moolenbroek if (token == COMMA) {
3904*83ee113eSDavid van Moolenbroek struct expression *foo = (struct expression *)0;
3905*83ee113eSDavid van Moolenbroek if (!expression_allocate (&foo, MDL))
3906*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expr");
3907*83ee113eSDavid van Moolenbroek expression_reference
3908*83ee113eSDavid van Moolenbroek (&nexp -> data.pick_first_value.cdr, foo, MDL);
3909*83ee113eSDavid van Moolenbroek expression_dereference (&nexp, MDL);
3910*83ee113eSDavid van Moolenbroek expression_reference (&nexp, foo, MDL);
3911*83ee113eSDavid van Moolenbroek expression_dereference (&foo, MDL);
3912*83ee113eSDavid van Moolenbroek }
3913*83ee113eSDavid van Moolenbroek } while (token == COMMA);
3914*83ee113eSDavid van Moolenbroek expression_dereference (&nexp, MDL);
3915*83ee113eSDavid van Moolenbroek
3916*83ee113eSDavid van Moolenbroek if (token != RPAREN)
3917*83ee113eSDavid van Moolenbroek goto norparen;
3918*83ee113eSDavid van Moolenbroek break;
3919*83ee113eSDavid van Moolenbroek
3920*83ee113eSDavid van Moolenbroek case OPTION:
3921*83ee113eSDavid van Moolenbroek case CONFIG_OPTION:
3922*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3923*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3924*83ee113eSDavid van Moolenbroek (*expr) -> op = (token == OPTION
3925*83ee113eSDavid van Moolenbroek ? expr_option
3926*83ee113eSDavid van Moolenbroek : expr_config_option);
3927*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3928*83ee113eSDavid van Moolenbroek known = 0;
3929*83ee113eSDavid van Moolenbroek /* Pass reference directly to expression structure. */
3930*83ee113eSDavid van Moolenbroek status = parse_option_name(cfile, 0, &known,
3931*83ee113eSDavid van Moolenbroek &(*expr)->data.option);
3932*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS ||
3933*83ee113eSDavid van Moolenbroek (*expr)->data.option == NULL) {
3934*83ee113eSDavid van Moolenbroek *lose = 1;
3935*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
3936*83ee113eSDavid van Moolenbroek return 0;
3937*83ee113eSDavid van Moolenbroek }
3938*83ee113eSDavid van Moolenbroek break;
3939*83ee113eSDavid van Moolenbroek
3940*83ee113eSDavid van Moolenbroek case HARDWARE:
3941*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3942*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3943*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3944*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_hardware;
3945*83ee113eSDavid van Moolenbroek break;
3946*83ee113eSDavid van Moolenbroek
3947*83ee113eSDavid van Moolenbroek case LEASED_ADDRESS:
3948*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3949*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3950*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3951*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_leased_address;
3952*83ee113eSDavid van Moolenbroek break;
3953*83ee113eSDavid van Moolenbroek
3954*83ee113eSDavid van Moolenbroek case CLIENT_STATE:
3955*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3956*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3957*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3958*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_client_state;
3959*83ee113eSDavid van Moolenbroek break;
3960*83ee113eSDavid van Moolenbroek
3961*83ee113eSDavid van Moolenbroek case FILENAME:
3962*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3963*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3964*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3965*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_filename;
3966*83ee113eSDavid van Moolenbroek break;
3967*83ee113eSDavid van Moolenbroek
3968*83ee113eSDavid van Moolenbroek case SERVER_NAME:
3969*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3970*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3971*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3972*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_sname;
3973*83ee113eSDavid van Moolenbroek break;
3974*83ee113eSDavid van Moolenbroek
3975*83ee113eSDavid van Moolenbroek case LEASE_TIME:
3976*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3977*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3978*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3979*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_lease_time;
3980*83ee113eSDavid van Moolenbroek break;
3981*83ee113eSDavid van Moolenbroek
3982*83ee113eSDavid van Moolenbroek case TOKEN_NULL:
3983*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3984*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3985*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3986*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_null;
3987*83ee113eSDavid van Moolenbroek break;
3988*83ee113eSDavid van Moolenbroek
3989*83ee113eSDavid van Moolenbroek case HOST_DECL_NAME:
3990*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3991*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3992*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
3993*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_host_decl_name;
3994*83ee113eSDavid van Moolenbroek break;
3995*83ee113eSDavid van Moolenbroek
3996*83ee113eSDavid van Moolenbroek case PACKET:
3997*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
3998*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
3999*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4000*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_packet;
4001*83ee113eSDavid van Moolenbroek
4002*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4003*83ee113eSDavid van Moolenbroek if (token != LPAREN)
4004*83ee113eSDavid van Moolenbroek goto nolparen;
4005*83ee113eSDavid van Moolenbroek
4006*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
4007*83ee113eSDavid van Moolenbroek cfile, lose))
4008*83ee113eSDavid van Moolenbroek goto nonum;
4009*83ee113eSDavid van Moolenbroek
4010*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4011*83ee113eSDavid van Moolenbroek if (token != COMMA)
4012*83ee113eSDavid van Moolenbroek goto nocomma;
4013*83ee113eSDavid van Moolenbroek
4014*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr) -> data.packet.len,
4015*83ee113eSDavid van Moolenbroek cfile, lose))
4016*83ee113eSDavid van Moolenbroek goto nonum;
4017*83ee113eSDavid van Moolenbroek
4018*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4019*83ee113eSDavid van Moolenbroek if (token != RPAREN)
4020*83ee113eSDavid van Moolenbroek goto norparen;
4021*83ee113eSDavid van Moolenbroek break;
4022*83ee113eSDavid van Moolenbroek
4023*83ee113eSDavid van Moolenbroek case STRING:
4024*83ee113eSDavid van Moolenbroek skip_token(&val, &len, cfile);
4025*83ee113eSDavid van Moolenbroek if (!make_const_data (expr, (const unsigned char *)val,
4026*83ee113eSDavid van Moolenbroek len, 1, 1, MDL))
4027*83ee113eSDavid van Moolenbroek log_fatal ("can't make constant string expression.");
4028*83ee113eSDavid van Moolenbroek break;
4029*83ee113eSDavid van Moolenbroek
4030*83ee113eSDavid van Moolenbroek case EXTRACT_INT:
4031*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4032*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4033*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
4034*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left parenthesis expected.");
4035*83ee113eSDavid van Moolenbroek *lose = 1;
4036*83ee113eSDavid van Moolenbroek return 0;
4037*83ee113eSDavid van Moolenbroek }
4038*83ee113eSDavid van Moolenbroek
4039*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4040*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4041*83ee113eSDavid van Moolenbroek
4042*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr) -> data.extract_int,
4043*83ee113eSDavid van Moolenbroek cfile, lose)) {
4044*83ee113eSDavid van Moolenbroek if (!*lose) {
4045*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4046*83ee113eSDavid van Moolenbroek "expecting data expression.");
4047*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4048*83ee113eSDavid van Moolenbroek *lose = 1;
4049*83ee113eSDavid van Moolenbroek }
4050*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4051*83ee113eSDavid van Moolenbroek return 0;
4052*83ee113eSDavid van Moolenbroek }
4053*83ee113eSDavid van Moolenbroek
4054*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4055*83ee113eSDavid van Moolenbroek if (token != COMMA) {
4056*83ee113eSDavid van Moolenbroek parse_warn (cfile, "comma expected.");
4057*83ee113eSDavid van Moolenbroek *lose = 1;
4058*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4059*83ee113eSDavid van Moolenbroek return 0;
4060*83ee113eSDavid van Moolenbroek }
4061*83ee113eSDavid van Moolenbroek
4062*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4063*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
4064*83ee113eSDavid van Moolenbroek parse_warn (cfile, "number expected.");
4065*83ee113eSDavid van Moolenbroek *lose = 1;
4066*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4067*83ee113eSDavid van Moolenbroek return 0;
4068*83ee113eSDavid van Moolenbroek }
4069*83ee113eSDavid van Moolenbroek switch (atoi (val)) {
4070*83ee113eSDavid van Moolenbroek case 8:
4071*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_extract_int8;
4072*83ee113eSDavid van Moolenbroek break;
4073*83ee113eSDavid van Moolenbroek
4074*83ee113eSDavid van Moolenbroek case 16:
4075*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_extract_int16;
4076*83ee113eSDavid van Moolenbroek break;
4077*83ee113eSDavid van Moolenbroek
4078*83ee113eSDavid van Moolenbroek case 32:
4079*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_extract_int32;
4080*83ee113eSDavid van Moolenbroek break;
4081*83ee113eSDavid van Moolenbroek
4082*83ee113eSDavid van Moolenbroek default:
4083*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4084*83ee113eSDavid van Moolenbroek "unsupported integer size %d", atoi (val));
4085*83ee113eSDavid van Moolenbroek *lose = 1;
4086*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4087*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4088*83ee113eSDavid van Moolenbroek return 0;
4089*83ee113eSDavid van Moolenbroek }
4090*83ee113eSDavid van Moolenbroek
4091*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4092*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
4093*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right parenthesis expected.");
4094*83ee113eSDavid van Moolenbroek *lose = 1;
4095*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4096*83ee113eSDavid van Moolenbroek return 0;
4097*83ee113eSDavid van Moolenbroek }
4098*83ee113eSDavid van Moolenbroek break;
4099*83ee113eSDavid van Moolenbroek
4100*83ee113eSDavid van Moolenbroek case ENCODE_INT:
4101*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4102*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4103*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
4104*83ee113eSDavid van Moolenbroek parse_warn (cfile, "left parenthesis expected.");
4105*83ee113eSDavid van Moolenbroek *lose = 1;
4106*83ee113eSDavid van Moolenbroek return 0;
4107*83ee113eSDavid van Moolenbroek }
4108*83ee113eSDavid van Moolenbroek
4109*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4110*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4111*83ee113eSDavid van Moolenbroek
4112*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr) -> data.encode_int,
4113*83ee113eSDavid van Moolenbroek cfile, lose)) {
4114*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting numeric expression.");
4115*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4116*83ee113eSDavid van Moolenbroek *lose = 1;
4117*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4118*83ee113eSDavid van Moolenbroek return 0;
4119*83ee113eSDavid van Moolenbroek }
4120*83ee113eSDavid van Moolenbroek
4121*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4122*83ee113eSDavid van Moolenbroek if (token != COMMA) {
4123*83ee113eSDavid van Moolenbroek parse_warn (cfile, "comma expected.");
4124*83ee113eSDavid van Moolenbroek *lose = 1;
4125*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4126*83ee113eSDavid van Moolenbroek return 0;
4127*83ee113eSDavid van Moolenbroek }
4128*83ee113eSDavid van Moolenbroek
4129*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4130*83ee113eSDavid van Moolenbroek if (token != NUMBER) {
4131*83ee113eSDavid van Moolenbroek parse_warn (cfile, "number expected.");
4132*83ee113eSDavid van Moolenbroek *lose = 1;
4133*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4134*83ee113eSDavid van Moolenbroek return 0;
4135*83ee113eSDavid van Moolenbroek }
4136*83ee113eSDavid van Moolenbroek switch (atoi (val)) {
4137*83ee113eSDavid van Moolenbroek case 8:
4138*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_encode_int8;
4139*83ee113eSDavid van Moolenbroek break;
4140*83ee113eSDavid van Moolenbroek
4141*83ee113eSDavid van Moolenbroek case 16:
4142*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_encode_int16;
4143*83ee113eSDavid van Moolenbroek break;
4144*83ee113eSDavid van Moolenbroek
4145*83ee113eSDavid van Moolenbroek case 32:
4146*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_encode_int32;
4147*83ee113eSDavid van Moolenbroek break;
4148*83ee113eSDavid van Moolenbroek
4149*83ee113eSDavid van Moolenbroek default:
4150*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4151*83ee113eSDavid van Moolenbroek "unsupported integer size %d", atoi (val));
4152*83ee113eSDavid van Moolenbroek *lose = 1;
4153*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4154*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4155*83ee113eSDavid van Moolenbroek return 0;
4156*83ee113eSDavid van Moolenbroek }
4157*83ee113eSDavid van Moolenbroek
4158*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4159*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
4160*83ee113eSDavid van Moolenbroek parse_warn (cfile, "right parenthesis expected.");
4161*83ee113eSDavid van Moolenbroek *lose = 1;
4162*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4163*83ee113eSDavid van Moolenbroek return 0;
4164*83ee113eSDavid van Moolenbroek }
4165*83ee113eSDavid van Moolenbroek break;
4166*83ee113eSDavid van Moolenbroek
4167*83ee113eSDavid van Moolenbroek case NUMBER:
4168*83ee113eSDavid van Moolenbroek /* If we're in a numeric context, this should just be a
4169*83ee113eSDavid van Moolenbroek number, by itself. */
4170*83ee113eSDavid van Moolenbroek if (context == context_numeric ||
4171*83ee113eSDavid van Moolenbroek context == context_data_or_numeric) {
4172*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4173*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4174*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4175*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_const_int;
4176*83ee113eSDavid van Moolenbroek (*expr) -> data.const_int = atoi (val);
4177*83ee113eSDavid van Moolenbroek break;
4178*83ee113eSDavid van Moolenbroek }
4179*83ee113eSDavid van Moolenbroek
4180*83ee113eSDavid van Moolenbroek case NUMBER_OR_NAME:
4181*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4182*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4183*83ee113eSDavid van Moolenbroek
4184*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_const_data;
4185*83ee113eSDavid van Moolenbroek if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
4186*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4187*83ee113eSDavid van Moolenbroek return 0;
4188*83ee113eSDavid van Moolenbroek }
4189*83ee113eSDavid van Moolenbroek break;
4190*83ee113eSDavid van Moolenbroek
4191*83ee113eSDavid van Moolenbroek case NS_FORMERR:
4192*83ee113eSDavid van Moolenbroek known = FORMERR;
4193*83ee113eSDavid van Moolenbroek goto ns_const;
4194*83ee113eSDavid van Moolenbroek ns_const:
4195*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4196*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4197*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4198*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_const_int;
4199*83ee113eSDavid van Moolenbroek (*expr) -> data.const_int = known;
4200*83ee113eSDavid van Moolenbroek break;
4201*83ee113eSDavid van Moolenbroek
4202*83ee113eSDavid van Moolenbroek case NS_NOERROR:
4203*83ee113eSDavid van Moolenbroek known = ISC_R_SUCCESS;
4204*83ee113eSDavid van Moolenbroek goto ns_const;
4205*83ee113eSDavid van Moolenbroek
4206*83ee113eSDavid van Moolenbroek case NS_NOTAUTH:
4207*83ee113eSDavid van Moolenbroek known = DHCP_R_NOTAUTH;
4208*83ee113eSDavid van Moolenbroek goto ns_const;
4209*83ee113eSDavid van Moolenbroek
4210*83ee113eSDavid van Moolenbroek case NS_NOTIMP:
4211*83ee113eSDavid van Moolenbroek known = ISC_R_NOTIMPLEMENTED;
4212*83ee113eSDavid van Moolenbroek goto ns_const;
4213*83ee113eSDavid van Moolenbroek
4214*83ee113eSDavid van Moolenbroek case NS_NOTZONE:
4215*83ee113eSDavid van Moolenbroek known = DHCP_R_NOTZONE;
4216*83ee113eSDavid van Moolenbroek goto ns_const;
4217*83ee113eSDavid van Moolenbroek
4218*83ee113eSDavid van Moolenbroek case NS_NXDOMAIN:
4219*83ee113eSDavid van Moolenbroek known = DHCP_R_NXDOMAIN;
4220*83ee113eSDavid van Moolenbroek goto ns_const;
4221*83ee113eSDavid van Moolenbroek
4222*83ee113eSDavid van Moolenbroek case NS_NXRRSET:
4223*83ee113eSDavid van Moolenbroek known = DHCP_R_NXRRSET;
4224*83ee113eSDavid van Moolenbroek goto ns_const;
4225*83ee113eSDavid van Moolenbroek
4226*83ee113eSDavid van Moolenbroek case NS_REFUSED:
4227*83ee113eSDavid van Moolenbroek known = DHCP_R_REFUSED;
4228*83ee113eSDavid van Moolenbroek goto ns_const;
4229*83ee113eSDavid van Moolenbroek
4230*83ee113eSDavid van Moolenbroek case NS_SERVFAIL:
4231*83ee113eSDavid van Moolenbroek known = DHCP_R_SERVFAIL;
4232*83ee113eSDavid van Moolenbroek goto ns_const;
4233*83ee113eSDavid van Moolenbroek
4234*83ee113eSDavid van Moolenbroek case NS_YXDOMAIN:
4235*83ee113eSDavid van Moolenbroek known = DHCP_R_YXDOMAIN;
4236*83ee113eSDavid van Moolenbroek goto ns_const;
4237*83ee113eSDavid van Moolenbroek
4238*83ee113eSDavid van Moolenbroek case NS_YXRRSET:
4239*83ee113eSDavid van Moolenbroek known = DHCP_R_YXRRSET;
4240*83ee113eSDavid van Moolenbroek goto ns_const;
4241*83ee113eSDavid van Moolenbroek
4242*83ee113eSDavid van Moolenbroek case BOOTING:
4243*83ee113eSDavid van Moolenbroek known = S_INIT;
4244*83ee113eSDavid van Moolenbroek goto ns_const;
4245*83ee113eSDavid van Moolenbroek
4246*83ee113eSDavid van Moolenbroek case REBOOT:
4247*83ee113eSDavid van Moolenbroek known = S_REBOOTING;
4248*83ee113eSDavid van Moolenbroek goto ns_const;
4249*83ee113eSDavid van Moolenbroek
4250*83ee113eSDavid van Moolenbroek case SELECT:
4251*83ee113eSDavid van Moolenbroek known = S_SELECTING;
4252*83ee113eSDavid van Moolenbroek goto ns_const;
4253*83ee113eSDavid van Moolenbroek
4254*83ee113eSDavid van Moolenbroek case REQUEST:
4255*83ee113eSDavid van Moolenbroek known = S_REQUESTING;
4256*83ee113eSDavid van Moolenbroek goto ns_const;
4257*83ee113eSDavid van Moolenbroek
4258*83ee113eSDavid van Moolenbroek case BOUND:
4259*83ee113eSDavid van Moolenbroek known = S_BOUND;
4260*83ee113eSDavid van Moolenbroek goto ns_const;
4261*83ee113eSDavid van Moolenbroek
4262*83ee113eSDavid van Moolenbroek case RENEW:
4263*83ee113eSDavid van Moolenbroek known = S_RENEWING;
4264*83ee113eSDavid van Moolenbroek goto ns_const;
4265*83ee113eSDavid van Moolenbroek
4266*83ee113eSDavid van Moolenbroek case REBIND:
4267*83ee113eSDavid van Moolenbroek known = S_REBINDING;
4268*83ee113eSDavid van Moolenbroek goto ns_const;
4269*83ee113eSDavid van Moolenbroek
4270*83ee113eSDavid van Moolenbroek case DEFINED:
4271*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4272*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4273*83ee113eSDavid van Moolenbroek if (token != LPAREN)
4274*83ee113eSDavid van Moolenbroek goto nolparen;
4275*83ee113eSDavid van Moolenbroek
4276*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4277*83ee113eSDavid van Moolenbroek if (token != NAME && token != NUMBER_OR_NAME) {
4278*83ee113eSDavid van Moolenbroek parse_warn (cfile, "%s can't be a variable name", val);
4279*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4280*83ee113eSDavid van Moolenbroek *lose = 1;
4281*83ee113eSDavid van Moolenbroek return 0;
4282*83ee113eSDavid van Moolenbroek }
4283*83ee113eSDavid van Moolenbroek
4284*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4285*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4286*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_variable_exists;
4287*83ee113eSDavid van Moolenbroek (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
4288*83ee113eSDavid van Moolenbroek if (!(*expr)->data.variable)
4289*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate variable name");
4290*83ee113eSDavid van Moolenbroek strcpy ((*expr) -> data.variable, val);
4291*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4292*83ee113eSDavid van Moolenbroek if (token != RPAREN)
4293*83ee113eSDavid van Moolenbroek goto norparen;
4294*83ee113eSDavid van Moolenbroek break;
4295*83ee113eSDavid van Moolenbroek
4296*83ee113eSDavid van Moolenbroek /* This parses 'gethostname()'. */
4297*83ee113eSDavid van Moolenbroek case GETHOSTNAME:
4298*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
4299*83ee113eSDavid van Moolenbroek if (!expression_allocate(expr, MDL))
4300*83ee113eSDavid van Moolenbroek log_fatal("can't allocate expression");
4301*83ee113eSDavid van Moolenbroek (*expr)->op = expr_gethostname;
4302*83ee113eSDavid van Moolenbroek
4303*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
4304*83ee113eSDavid van Moolenbroek if (token != LPAREN)
4305*83ee113eSDavid van Moolenbroek goto nolparen;
4306*83ee113eSDavid van Moolenbroek
4307*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
4308*83ee113eSDavid van Moolenbroek if (token != RPAREN)
4309*83ee113eSDavid van Moolenbroek goto norparen;
4310*83ee113eSDavid van Moolenbroek break;
4311*83ee113eSDavid van Moolenbroek
4312*83ee113eSDavid van Moolenbroek case GETHOSTBYNAME:
4313*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
4314*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
4315*83ee113eSDavid van Moolenbroek if (token != LPAREN)
4316*83ee113eSDavid van Moolenbroek goto nolparen;
4317*83ee113eSDavid van Moolenbroek
4318*83ee113eSDavid van Moolenbroek /* The argument is a quoted string. */
4319*83ee113eSDavid van Moolenbroek token = next_token(&val, NULL, cfile);
4320*83ee113eSDavid van Moolenbroek if (token != STRING) {
4321*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting quoted literal: "
4322*83ee113eSDavid van Moolenbroek "\"foo.example.com\"");
4323*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
4324*83ee113eSDavid van Moolenbroek *lose = 1;
4325*83ee113eSDavid van Moolenbroek return 0;
4326*83ee113eSDavid van Moolenbroek }
4327*83ee113eSDavid van Moolenbroek if (!make_host_lookup(expr, val))
4328*83ee113eSDavid van Moolenbroek log_fatal("Error creating gethostbyname() internal "
4329*83ee113eSDavid van Moolenbroek "record. (%s:%d)", MDL);
4330*83ee113eSDavid van Moolenbroek
4331*83ee113eSDavid van Moolenbroek token = next_token(NULL, NULL, cfile);
4332*83ee113eSDavid van Moolenbroek if (token != RPAREN)
4333*83ee113eSDavid van Moolenbroek goto norparen;
4334*83ee113eSDavid van Moolenbroek break;
4335*83ee113eSDavid van Moolenbroek
4336*83ee113eSDavid van Moolenbroek case V6RELAY:
4337*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
4338*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4339*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4340*83ee113eSDavid van Moolenbroek (*expr)->op = expr_v6relay;
4341*83ee113eSDavid van Moolenbroek
4342*83ee113eSDavid van Moolenbroek token = next_token (&val, NULL, cfile);
4343*83ee113eSDavid van Moolenbroek if (token != LPAREN)
4344*83ee113eSDavid van Moolenbroek goto nolparen;
4345*83ee113eSDavid van Moolenbroek
4346*83ee113eSDavid van Moolenbroek if (!parse_numeric_expression (&(*expr)->data.v6relay.relay,
4347*83ee113eSDavid van Moolenbroek cfile, lose))
4348*83ee113eSDavid van Moolenbroek goto nodata;
4349*83ee113eSDavid van Moolenbroek
4350*83ee113eSDavid van Moolenbroek token = next_token (&val, NULL, cfile);
4351*83ee113eSDavid van Moolenbroek if (token != COMMA)
4352*83ee113eSDavid van Moolenbroek goto nocomma;
4353*83ee113eSDavid van Moolenbroek
4354*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&(*expr)->data.v6relay.roption,
4355*83ee113eSDavid van Moolenbroek cfile, lose))
4356*83ee113eSDavid van Moolenbroek goto nodata;
4357*83ee113eSDavid van Moolenbroek
4358*83ee113eSDavid van Moolenbroek token = next_token (&val, NULL, cfile);
4359*83ee113eSDavid van Moolenbroek
4360*83ee113eSDavid van Moolenbroek if (token != RPAREN)
4361*83ee113eSDavid van Moolenbroek goto norparen;
4362*83ee113eSDavid van Moolenbroek break;
4363*83ee113eSDavid van Moolenbroek
4364*83ee113eSDavid van Moolenbroek /* Not a valid start to an expression... */
4365*83ee113eSDavid van Moolenbroek default:
4366*83ee113eSDavid van Moolenbroek if (token != NAME && token != NUMBER_OR_NAME)
4367*83ee113eSDavid van Moolenbroek return 0;
4368*83ee113eSDavid van Moolenbroek
4369*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4370*83ee113eSDavid van Moolenbroek
4371*83ee113eSDavid van Moolenbroek /* Save the name of the variable being referenced. */
4372*83ee113eSDavid van Moolenbroek cptr = dmalloc (strlen (val) + 1, MDL);
4373*83ee113eSDavid van Moolenbroek if (!cptr)
4374*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate variable name");
4375*83ee113eSDavid van Moolenbroek strcpy (cptr, val);
4376*83ee113eSDavid van Moolenbroek
4377*83ee113eSDavid van Moolenbroek /* Simple variable reference, as far as we can tell. */
4378*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
4379*83ee113eSDavid van Moolenbroek if (token != LPAREN) {
4380*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4381*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4382*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_variable_reference;
4383*83ee113eSDavid van Moolenbroek (*expr) -> data.variable = cptr;
4384*83ee113eSDavid van Moolenbroek break;
4385*83ee113eSDavid van Moolenbroek }
4386*83ee113eSDavid van Moolenbroek
4387*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4388*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4389*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4390*83ee113eSDavid van Moolenbroek (*expr) -> op = expr_funcall;
4391*83ee113eSDavid van Moolenbroek (*expr) -> data.funcall.name = cptr;
4392*83ee113eSDavid van Moolenbroek
4393*83ee113eSDavid van Moolenbroek /* Now parse the argument list. */
4394*83ee113eSDavid van Moolenbroek ep = &(*expr) -> data.funcall.arglist;
4395*83ee113eSDavid van Moolenbroek do {
4396*83ee113eSDavid van Moolenbroek if (!expression_allocate (ep, MDL))
4397*83ee113eSDavid van Moolenbroek log_fatal ("can't allocate expression");
4398*83ee113eSDavid van Moolenbroek (*ep) -> op = expr_arg;
4399*83ee113eSDavid van Moolenbroek if (!parse_expression (&(*ep) -> data.arg.val,
4400*83ee113eSDavid van Moolenbroek cfile, lose, context_any,
4401*83ee113eSDavid van Moolenbroek (struct expression **)0,
4402*83ee113eSDavid van Moolenbroek expr_none)) {
4403*83ee113eSDavid van Moolenbroek if (!*lose) {
4404*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4405*83ee113eSDavid van Moolenbroek "expecting expression.");
4406*83ee113eSDavid van Moolenbroek *lose = 1;
4407*83ee113eSDavid van Moolenbroek }
4408*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4409*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4410*83ee113eSDavid van Moolenbroek return 0;
4411*83ee113eSDavid van Moolenbroek }
4412*83ee113eSDavid van Moolenbroek ep = &((*ep) -> data.arg.next);
4413*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
4414*83ee113eSDavid van Moolenbroek } while (token == COMMA);
4415*83ee113eSDavid van Moolenbroek if (token != RPAREN) {
4416*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Right parenthesis expected.");
4417*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4418*83ee113eSDavid van Moolenbroek *lose = 1;
4419*83ee113eSDavid van Moolenbroek expression_dereference (expr, MDL);
4420*83ee113eSDavid van Moolenbroek return 0;
4421*83ee113eSDavid van Moolenbroek }
4422*83ee113eSDavid van Moolenbroek break;
4423*83ee113eSDavid van Moolenbroek }
4424*83ee113eSDavid van Moolenbroek return 1;
4425*83ee113eSDavid van Moolenbroek }
4426*83ee113eSDavid van Moolenbroek
4427*83ee113eSDavid van Moolenbroek /* Parse an expression. */
4428*83ee113eSDavid van Moolenbroek
parse_expression(expr,cfile,lose,context,plhs,binop)4429*83ee113eSDavid van Moolenbroek int parse_expression (expr, cfile, lose, context, plhs, binop)
4430*83ee113eSDavid van Moolenbroek struct expression **expr;
4431*83ee113eSDavid van Moolenbroek struct parse *cfile;
4432*83ee113eSDavid van Moolenbroek int *lose;
4433*83ee113eSDavid van Moolenbroek enum expression_context context;
4434*83ee113eSDavid van Moolenbroek struct expression **plhs;
4435*83ee113eSDavid van Moolenbroek enum expr_op binop;
4436*83ee113eSDavid van Moolenbroek {
4437*83ee113eSDavid van Moolenbroek enum dhcp_token token;
4438*83ee113eSDavid van Moolenbroek const char *val;
4439*83ee113eSDavid van Moolenbroek struct expression *rhs = (struct expression *)0, *tmp;
4440*83ee113eSDavid van Moolenbroek struct expression *lhs = (struct expression *)0;
4441*83ee113eSDavid van Moolenbroek enum expr_op next_op;
4442*83ee113eSDavid van Moolenbroek enum expression_context
4443*83ee113eSDavid van Moolenbroek lhs_context = context_any,
4444*83ee113eSDavid van Moolenbroek rhs_context = context_any;
4445*83ee113eSDavid van Moolenbroek
4446*83ee113eSDavid van Moolenbroek /* Consume the left hand side we were passed. */
4447*83ee113eSDavid van Moolenbroek if (plhs) {
4448*83ee113eSDavid van Moolenbroek expression_reference (&lhs, *plhs, MDL);
4449*83ee113eSDavid van Moolenbroek expression_dereference (plhs, MDL);
4450*83ee113eSDavid van Moolenbroek }
4451*83ee113eSDavid van Moolenbroek
4452*83ee113eSDavid van Moolenbroek new_rhs:
4453*83ee113eSDavid van Moolenbroek if (!parse_non_binary (&rhs, cfile, lose, context)) {
4454*83ee113eSDavid van Moolenbroek /* If we already have a left-hand side, then it's not
4455*83ee113eSDavid van Moolenbroek okay for there not to be a right-hand side here, so
4456*83ee113eSDavid van Moolenbroek we need to flag it as an error. */
4457*83ee113eSDavid van Moolenbroek if (lhs) {
4458*83ee113eSDavid van Moolenbroek if (!*lose) {
4459*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4460*83ee113eSDavid van Moolenbroek "expecting right-hand side.");
4461*83ee113eSDavid van Moolenbroek *lose = 1;
4462*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4463*83ee113eSDavid van Moolenbroek }
4464*83ee113eSDavid van Moolenbroek expression_dereference (&lhs, MDL);
4465*83ee113eSDavid van Moolenbroek }
4466*83ee113eSDavid van Moolenbroek return 0;
4467*83ee113eSDavid van Moolenbroek }
4468*83ee113eSDavid van Moolenbroek
4469*83ee113eSDavid van Moolenbroek /* At this point, rhs contains either an entire subexpression,
4470*83ee113eSDavid van Moolenbroek or at least a left-hand-side. If we do not see a binary token
4471*83ee113eSDavid van Moolenbroek as the next token, we're done with the expression. */
4472*83ee113eSDavid van Moolenbroek
4473*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
4474*83ee113eSDavid van Moolenbroek switch (token) {
4475*83ee113eSDavid van Moolenbroek case BANG:
4476*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4477*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
4478*83ee113eSDavid van Moolenbroek if (token != EQUAL) {
4479*83ee113eSDavid van Moolenbroek parse_warn (cfile, "! in boolean context without =");
4480*83ee113eSDavid van Moolenbroek *lose = 1;
4481*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4482*83ee113eSDavid van Moolenbroek if (lhs)
4483*83ee113eSDavid van Moolenbroek expression_dereference (&lhs, MDL);
4484*83ee113eSDavid van Moolenbroek return 0;
4485*83ee113eSDavid van Moolenbroek }
4486*83ee113eSDavid van Moolenbroek next_op = expr_not_equal;
4487*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4488*83ee113eSDavid van Moolenbroek break;
4489*83ee113eSDavid van Moolenbroek
4490*83ee113eSDavid van Moolenbroek case EQUAL:
4491*83ee113eSDavid van Moolenbroek next_op = expr_equal;
4492*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4493*83ee113eSDavid van Moolenbroek break;
4494*83ee113eSDavid van Moolenbroek
4495*83ee113eSDavid van Moolenbroek case TILDE:
4496*83ee113eSDavid van Moolenbroek #ifdef HAVE_REGEX_H
4497*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
4498*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
4499*83ee113eSDavid van Moolenbroek
4500*83ee113eSDavid van Moolenbroek if (token == TILDE)
4501*83ee113eSDavid van Moolenbroek next_op = expr_iregex_match;
4502*83ee113eSDavid van Moolenbroek else if (token == EQUAL)
4503*83ee113eSDavid van Moolenbroek next_op = expr_regex_match;
4504*83ee113eSDavid van Moolenbroek else {
4505*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting ~= or ~~ operator");
4506*83ee113eSDavid van Moolenbroek *lose = 1;
4507*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
4508*83ee113eSDavid van Moolenbroek if (lhs)
4509*83ee113eSDavid van Moolenbroek expression_dereference(&lhs, MDL);
4510*83ee113eSDavid van Moolenbroek return 0;
4511*83ee113eSDavid van Moolenbroek }
4512*83ee113eSDavid van Moolenbroek
4513*83ee113eSDavid van Moolenbroek context = expression_context(rhs);
4514*83ee113eSDavid van Moolenbroek #else
4515*83ee113eSDavid van Moolenbroek parse_warn(cfile, "No support for regex operator.");
4516*83ee113eSDavid van Moolenbroek *lose = 1;
4517*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
4518*83ee113eSDavid van Moolenbroek if (lhs != NULL)
4519*83ee113eSDavid van Moolenbroek expression_dereference(&lhs, MDL);
4520*83ee113eSDavid van Moolenbroek return 0;
4521*83ee113eSDavid van Moolenbroek #endif
4522*83ee113eSDavid van Moolenbroek break;
4523*83ee113eSDavid van Moolenbroek
4524*83ee113eSDavid van Moolenbroek case AND:
4525*83ee113eSDavid van Moolenbroek next_op = expr_and;
4526*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4527*83ee113eSDavid van Moolenbroek break;
4528*83ee113eSDavid van Moolenbroek
4529*83ee113eSDavid van Moolenbroek case OR:
4530*83ee113eSDavid van Moolenbroek next_op = expr_or;
4531*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4532*83ee113eSDavid van Moolenbroek break;
4533*83ee113eSDavid van Moolenbroek
4534*83ee113eSDavid van Moolenbroek case PLUS:
4535*83ee113eSDavid van Moolenbroek next_op = expr_add;
4536*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4537*83ee113eSDavid van Moolenbroek break;
4538*83ee113eSDavid van Moolenbroek
4539*83ee113eSDavid van Moolenbroek case MINUS:
4540*83ee113eSDavid van Moolenbroek next_op = expr_subtract;
4541*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4542*83ee113eSDavid van Moolenbroek break;
4543*83ee113eSDavid van Moolenbroek
4544*83ee113eSDavid van Moolenbroek case SLASH:
4545*83ee113eSDavid van Moolenbroek next_op = expr_divide;
4546*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4547*83ee113eSDavid van Moolenbroek break;
4548*83ee113eSDavid van Moolenbroek
4549*83ee113eSDavid van Moolenbroek case ASTERISK:
4550*83ee113eSDavid van Moolenbroek next_op = expr_multiply;
4551*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4552*83ee113eSDavid van Moolenbroek break;
4553*83ee113eSDavid van Moolenbroek
4554*83ee113eSDavid van Moolenbroek case PERCENT:
4555*83ee113eSDavid van Moolenbroek next_op = expr_remainder;
4556*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4557*83ee113eSDavid van Moolenbroek break;
4558*83ee113eSDavid van Moolenbroek
4559*83ee113eSDavid van Moolenbroek case AMPERSAND:
4560*83ee113eSDavid van Moolenbroek next_op = expr_binary_and;
4561*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4562*83ee113eSDavid van Moolenbroek break;
4563*83ee113eSDavid van Moolenbroek
4564*83ee113eSDavid van Moolenbroek case PIPE:
4565*83ee113eSDavid van Moolenbroek next_op = expr_binary_or;
4566*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4567*83ee113eSDavid van Moolenbroek break;
4568*83ee113eSDavid van Moolenbroek
4569*83ee113eSDavid van Moolenbroek case CARET:
4570*83ee113eSDavid van Moolenbroek next_op = expr_binary_xor;
4571*83ee113eSDavid van Moolenbroek context = expression_context (rhs);
4572*83ee113eSDavid van Moolenbroek break;
4573*83ee113eSDavid van Moolenbroek
4574*83ee113eSDavid van Moolenbroek default:
4575*83ee113eSDavid van Moolenbroek next_op = expr_none;
4576*83ee113eSDavid van Moolenbroek }
4577*83ee113eSDavid van Moolenbroek
4578*83ee113eSDavid van Moolenbroek /* If we have no lhs yet, we just parsed it. */
4579*83ee113eSDavid van Moolenbroek if (!lhs) {
4580*83ee113eSDavid van Moolenbroek /* If there was no operator following what we just parsed,
4581*83ee113eSDavid van Moolenbroek then we're done - return it. */
4582*83ee113eSDavid van Moolenbroek if (next_op == expr_none) {
4583*83ee113eSDavid van Moolenbroek *expr = rhs;
4584*83ee113eSDavid van Moolenbroek return 1;
4585*83ee113eSDavid van Moolenbroek }
4586*83ee113eSDavid van Moolenbroek lhs = rhs;
4587*83ee113eSDavid van Moolenbroek rhs = (struct expression *)0;
4588*83ee113eSDavid van Moolenbroek binop = next_op;
4589*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4590*83ee113eSDavid van Moolenbroek goto new_rhs;
4591*83ee113eSDavid van Moolenbroek }
4592*83ee113eSDavid van Moolenbroek
4593*83ee113eSDavid van Moolenbroek /* If the next binary operator is of greater precedence than the
4594*83ee113eSDavid van Moolenbroek * current operator, then rhs we have parsed so far is actually
4595*83ee113eSDavid van Moolenbroek * the lhs of the next operator. To get this value, we have to
4596*83ee113eSDavid van Moolenbroek * recurse.
4597*83ee113eSDavid van Moolenbroek */
4598*83ee113eSDavid van Moolenbroek if (binop != expr_none && next_op != expr_none &&
4599*83ee113eSDavid van Moolenbroek op_precedence (binop, next_op) < 0) {
4600*83ee113eSDavid van Moolenbroek
4601*83ee113eSDavid van Moolenbroek /* Eat the subexpression operator token, which we pass to
4602*83ee113eSDavid van Moolenbroek * parse_expression...we only peek()'d earlier.
4603*83ee113eSDavid van Moolenbroek */
4604*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4605*83ee113eSDavid van Moolenbroek
4606*83ee113eSDavid van Moolenbroek /* Continue parsing of the right hand side with that token. */
4607*83ee113eSDavid van Moolenbroek tmp = rhs;
4608*83ee113eSDavid van Moolenbroek rhs = (struct expression *)0;
4609*83ee113eSDavid van Moolenbroek if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
4610*83ee113eSDavid van Moolenbroek &tmp, next_op)) {
4611*83ee113eSDavid van Moolenbroek if (!*lose) {
4612*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4613*83ee113eSDavid van Moolenbroek "expecting a subexpression");
4614*83ee113eSDavid van Moolenbroek *lose = 1;
4615*83ee113eSDavid van Moolenbroek }
4616*83ee113eSDavid van Moolenbroek return 0;
4617*83ee113eSDavid van Moolenbroek }
4618*83ee113eSDavid van Moolenbroek next_op = expr_none;
4619*83ee113eSDavid van Moolenbroek }
4620*83ee113eSDavid van Moolenbroek
4621*83ee113eSDavid van Moolenbroek if (binop != expr_none) {
4622*83ee113eSDavid van Moolenbroek rhs_context = expression_context(rhs);
4623*83ee113eSDavid van Moolenbroek lhs_context = expression_context(lhs);
4624*83ee113eSDavid van Moolenbroek
4625*83ee113eSDavid van Moolenbroek if ((rhs_context != context_any) && (lhs_context != context_any) &&
4626*83ee113eSDavid van Moolenbroek (rhs_context != lhs_context)) {
4627*83ee113eSDavid van Moolenbroek parse_warn (cfile, "illegal expression relating different types");
4628*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4629*83ee113eSDavid van Moolenbroek expression_dereference (&rhs, MDL);
4630*83ee113eSDavid van Moolenbroek expression_dereference (&lhs, MDL);
4631*83ee113eSDavid van Moolenbroek *lose = 1;
4632*83ee113eSDavid van Moolenbroek return 0;
4633*83ee113eSDavid van Moolenbroek }
4634*83ee113eSDavid van Moolenbroek
4635*83ee113eSDavid van Moolenbroek switch(binop) {
4636*83ee113eSDavid van Moolenbroek case expr_not_equal:
4637*83ee113eSDavid van Moolenbroek case expr_equal:
4638*83ee113eSDavid van Moolenbroek if ((rhs_context != context_data_or_numeric) &&
4639*83ee113eSDavid van Moolenbroek (rhs_context != context_data) &&
4640*83ee113eSDavid van Moolenbroek (rhs_context != context_numeric) &&
4641*83ee113eSDavid van Moolenbroek (rhs_context != context_any)) {
4642*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting data/numeric expression");
4643*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4644*83ee113eSDavid van Moolenbroek expression_dereference (&rhs, MDL);
4645*83ee113eSDavid van Moolenbroek *lose = 1;
4646*83ee113eSDavid van Moolenbroek return 0;
4647*83ee113eSDavid van Moolenbroek }
4648*83ee113eSDavid van Moolenbroek break;
4649*83ee113eSDavid van Moolenbroek
4650*83ee113eSDavid van Moolenbroek case expr_regex_match:
4651*83ee113eSDavid van Moolenbroek #ifdef HAVE_REGEX_H
4652*83ee113eSDavid van Moolenbroek if (expression_context(rhs) != context_data) {
4653*83ee113eSDavid van Moolenbroek parse_warn(cfile, "expecting data expression");
4654*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
4655*83ee113eSDavid van Moolenbroek expression_dereference(&rhs, MDL);
4656*83ee113eSDavid van Moolenbroek *lose = 1;
4657*83ee113eSDavid van Moolenbroek return 0;
4658*83ee113eSDavid van Moolenbroek }
4659*83ee113eSDavid van Moolenbroek #else
4660*83ee113eSDavid van Moolenbroek /* It should not be possible to attempt to parse the right
4661*83ee113eSDavid van Moolenbroek * hand side of an operator there is no support for.
4662*83ee113eSDavid van Moolenbroek */
4663*83ee113eSDavid van Moolenbroek log_fatal("Impossible condition at %s:%d.", MDL);
4664*83ee113eSDavid van Moolenbroek #endif
4665*83ee113eSDavid van Moolenbroek break;
4666*83ee113eSDavid van Moolenbroek
4667*83ee113eSDavid van Moolenbroek case expr_and:
4668*83ee113eSDavid van Moolenbroek case expr_or:
4669*83ee113eSDavid van Moolenbroek if ((rhs_context != context_boolean) &&
4670*83ee113eSDavid van Moolenbroek (rhs_context != context_any)) {
4671*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting boolean expressions");
4672*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4673*83ee113eSDavid van Moolenbroek expression_dereference (&rhs, MDL);
4674*83ee113eSDavid van Moolenbroek *lose = 1;
4675*83ee113eSDavid van Moolenbroek return 0;
4676*83ee113eSDavid van Moolenbroek }
4677*83ee113eSDavid van Moolenbroek break;
4678*83ee113eSDavid van Moolenbroek
4679*83ee113eSDavid van Moolenbroek case expr_add:
4680*83ee113eSDavid van Moolenbroek case expr_subtract:
4681*83ee113eSDavid van Moolenbroek case expr_divide:
4682*83ee113eSDavid van Moolenbroek case expr_multiply:
4683*83ee113eSDavid van Moolenbroek case expr_remainder:
4684*83ee113eSDavid van Moolenbroek case expr_binary_and:
4685*83ee113eSDavid van Moolenbroek case expr_binary_or:
4686*83ee113eSDavid van Moolenbroek case expr_binary_xor:
4687*83ee113eSDavid van Moolenbroek if ((rhs_context != context_numeric) &&
4688*83ee113eSDavid van Moolenbroek (rhs_context != context_any)) {
4689*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting numeric expressions");
4690*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4691*83ee113eSDavid van Moolenbroek expression_dereference (&rhs, MDL);
4692*83ee113eSDavid van Moolenbroek *lose = 1;
4693*83ee113eSDavid van Moolenbroek return 0;
4694*83ee113eSDavid van Moolenbroek }
4695*83ee113eSDavid van Moolenbroek break;
4696*83ee113eSDavid van Moolenbroek
4697*83ee113eSDavid van Moolenbroek default:
4698*83ee113eSDavid van Moolenbroek break;
4699*83ee113eSDavid van Moolenbroek }
4700*83ee113eSDavid van Moolenbroek }
4701*83ee113eSDavid van Moolenbroek
4702*83ee113eSDavid van Moolenbroek /* Now, if we didn't find a binary operator, we're done parsing
4703*83ee113eSDavid van Moolenbroek this subexpression, so combine it with the preceding binary
4704*83ee113eSDavid van Moolenbroek operator and return the result. */
4705*83ee113eSDavid van Moolenbroek if (next_op == expr_none) {
4706*83ee113eSDavid van Moolenbroek if (!expression_allocate (expr, MDL))
4707*83ee113eSDavid van Moolenbroek log_fatal ("Can't allocate expression!");
4708*83ee113eSDavid van Moolenbroek
4709*83ee113eSDavid van Moolenbroek (*expr) -> op = binop;
4710*83ee113eSDavid van Moolenbroek /* All the binary operators' data union members
4711*83ee113eSDavid van Moolenbroek are the same, so we'll cheat and use the member
4712*83ee113eSDavid van Moolenbroek for the equals operator. */
4713*83ee113eSDavid van Moolenbroek (*expr) -> data.equal [0] = lhs;
4714*83ee113eSDavid van Moolenbroek (*expr) -> data.equal [1] = rhs;
4715*83ee113eSDavid van Moolenbroek return 1;
4716*83ee113eSDavid van Moolenbroek }
4717*83ee113eSDavid van Moolenbroek
4718*83ee113eSDavid van Moolenbroek /* Eat the operator token - we now know it was a binary operator... */
4719*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4720*83ee113eSDavid van Moolenbroek
4721*83ee113eSDavid van Moolenbroek /* Now combine the LHS and the RHS using binop. */
4722*83ee113eSDavid van Moolenbroek tmp = (struct expression *)0;
4723*83ee113eSDavid van Moolenbroek if (!expression_allocate (&tmp, MDL))
4724*83ee113eSDavid van Moolenbroek log_fatal ("No memory for equal precedence combination.");
4725*83ee113eSDavid van Moolenbroek
4726*83ee113eSDavid van Moolenbroek /* Store the LHS and RHS. */
4727*83ee113eSDavid van Moolenbroek tmp -> data.equal [0] = lhs;
4728*83ee113eSDavid van Moolenbroek tmp -> data.equal [1] = rhs;
4729*83ee113eSDavid van Moolenbroek tmp -> op = binop;
4730*83ee113eSDavid van Moolenbroek
4731*83ee113eSDavid van Moolenbroek lhs = tmp;
4732*83ee113eSDavid van Moolenbroek tmp = (struct expression *)0;
4733*83ee113eSDavid van Moolenbroek rhs = (struct expression *)0;
4734*83ee113eSDavid van Moolenbroek
4735*83ee113eSDavid van Moolenbroek /* Recursions don't return until we have parsed the end of the
4736*83ee113eSDavid van Moolenbroek expression, so if we recursed earlier, we can now return what
4737*83ee113eSDavid van Moolenbroek we got. */
4738*83ee113eSDavid van Moolenbroek if (next_op == expr_none) {
4739*83ee113eSDavid van Moolenbroek *expr = lhs;
4740*83ee113eSDavid van Moolenbroek return 1;
4741*83ee113eSDavid van Moolenbroek }
4742*83ee113eSDavid van Moolenbroek
4743*83ee113eSDavid van Moolenbroek binop = next_op;
4744*83ee113eSDavid van Moolenbroek goto new_rhs;
4745*83ee113eSDavid van Moolenbroek }
4746*83ee113eSDavid van Moolenbroek
4747*83ee113eSDavid van Moolenbroek
parse_option_data(expr,cfile,lookups,option)4748*83ee113eSDavid van Moolenbroek int parse_option_data (expr, cfile, lookups, option)
4749*83ee113eSDavid van Moolenbroek struct expression **expr;
4750*83ee113eSDavid van Moolenbroek struct parse *cfile;
4751*83ee113eSDavid van Moolenbroek int lookups;
4752*83ee113eSDavid van Moolenbroek struct option *option;
4753*83ee113eSDavid van Moolenbroek {
4754*83ee113eSDavid van Moolenbroek const char *val;
4755*83ee113eSDavid van Moolenbroek const char *fmt = NULL;
4756*83ee113eSDavid van Moolenbroek struct expression *tmp;
4757*83ee113eSDavid van Moolenbroek enum dhcp_token token;
4758*83ee113eSDavid van Moolenbroek
4759*83ee113eSDavid van Moolenbroek do {
4760*83ee113eSDavid van Moolenbroek /*
4761*83ee113eSDavid van Moolenbroek * Set a flag if this is an array of a simple type (i.e.,
4762*83ee113eSDavid van Moolenbroek * not an array of pairs of IP addresses, or something like
4763*83ee113eSDavid van Moolenbroek * that.
4764*83ee113eSDavid van Moolenbroek */
4765*83ee113eSDavid van Moolenbroek int uniform = 0;
4766*83ee113eSDavid van Moolenbroek
4767*83ee113eSDavid van Moolenbroek and_again:
4768*83ee113eSDavid van Moolenbroek /* Set fmt to start of format for 'A' and one char back
4769*83ee113eSDavid van Moolenbroek * for 'a'.
4770*83ee113eSDavid van Moolenbroek */
4771*83ee113eSDavid van Moolenbroek if ((fmt != NULL) && (fmt != option->format) && (*fmt == 'a'))
4772*83ee113eSDavid van Moolenbroek fmt -= 1;
4773*83ee113eSDavid van Moolenbroek else if ((fmt == NULL) || (*fmt == 'A'))
4774*83ee113eSDavid van Moolenbroek fmt = option->format;
4775*83ee113eSDavid van Moolenbroek
4776*83ee113eSDavid van Moolenbroek /* 'a' means always uniform */
4777*83ee113eSDavid van Moolenbroek if ((fmt[0] != 'Z') && (tolower((unsigned char)fmt[1]) == 'a'))
4778*83ee113eSDavid van Moolenbroek uniform = 1;
4779*83ee113eSDavid van Moolenbroek
4780*83ee113eSDavid van Moolenbroek do {
4781*83ee113eSDavid van Moolenbroek if ((*fmt == 'A') || (*fmt == 'a'))
4782*83ee113eSDavid van Moolenbroek break;
4783*83ee113eSDavid van Moolenbroek if (*fmt == 'o') {
4784*83ee113eSDavid van Moolenbroek /* consume the optional flag */
4785*83ee113eSDavid van Moolenbroek fmt++;
4786*83ee113eSDavid van Moolenbroek continue;
4787*83ee113eSDavid van Moolenbroek }
4788*83ee113eSDavid van Moolenbroek
4789*83ee113eSDavid van Moolenbroek if (fmt[1] == 'o') {
4790*83ee113eSDavid van Moolenbroek /*
4791*83ee113eSDavid van Moolenbroek * A value for the current format is
4792*83ee113eSDavid van Moolenbroek * optional - check to see if the next
4793*83ee113eSDavid van Moolenbroek * token is a semi-colon if so we don't
4794*83ee113eSDavid van Moolenbroek * need to parse it and doing so would
4795*83ee113eSDavid van Moolenbroek * consume the semi-colon which our
4796*83ee113eSDavid van Moolenbroek * caller is expecting to parse
4797*83ee113eSDavid van Moolenbroek */
4798*83ee113eSDavid van Moolenbroek token = peek_token(&val, (unsigned *)0,
4799*83ee113eSDavid van Moolenbroek cfile);
4800*83ee113eSDavid van Moolenbroek if (token == SEMI) {
4801*83ee113eSDavid van Moolenbroek fmt++;
4802*83ee113eSDavid van Moolenbroek continue;
4803*83ee113eSDavid van Moolenbroek }
4804*83ee113eSDavid van Moolenbroek }
4805*83ee113eSDavid van Moolenbroek
4806*83ee113eSDavid van Moolenbroek tmp = *expr;
4807*83ee113eSDavid van Moolenbroek *expr = NULL;
4808*83ee113eSDavid van Moolenbroek
4809*83ee113eSDavid van Moolenbroek if (!parse_option_token(expr, cfile, &fmt, tmp,
4810*83ee113eSDavid van Moolenbroek uniform, lookups)) {
4811*83ee113eSDavid van Moolenbroek if (fmt [1] != 'o') {
4812*83ee113eSDavid van Moolenbroek if (tmp)
4813*83ee113eSDavid van Moolenbroek expression_dereference (&tmp,
4814*83ee113eSDavid van Moolenbroek MDL);
4815*83ee113eSDavid van Moolenbroek return 0;
4816*83ee113eSDavid van Moolenbroek }
4817*83ee113eSDavid van Moolenbroek *expr = tmp;
4818*83ee113eSDavid van Moolenbroek tmp = NULL;
4819*83ee113eSDavid van Moolenbroek }
4820*83ee113eSDavid van Moolenbroek if (tmp)
4821*83ee113eSDavid van Moolenbroek expression_dereference (&tmp, MDL);
4822*83ee113eSDavid van Moolenbroek
4823*83ee113eSDavid van Moolenbroek fmt++;
4824*83ee113eSDavid van Moolenbroek } while (*fmt != '\0');
4825*83ee113eSDavid van Moolenbroek
4826*83ee113eSDavid van Moolenbroek if ((*fmt == 'A') || (*fmt == 'a')) {
4827*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
4828*83ee113eSDavid van Moolenbroek /* Comma means: continue with next element in array */
4829*83ee113eSDavid van Moolenbroek if (token == COMMA) {
4830*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4831*83ee113eSDavid van Moolenbroek continue;
4832*83ee113eSDavid van Moolenbroek }
4833*83ee113eSDavid van Moolenbroek /* no comma: end of array.
4834*83ee113eSDavid van Moolenbroek 'A' or end of string means: leave the loop */
4835*83ee113eSDavid van Moolenbroek if ((*fmt == 'A') || (fmt[1] == '\0'))
4836*83ee113eSDavid van Moolenbroek break;
4837*83ee113eSDavid van Moolenbroek /* 'a' means: go on with next char */
4838*83ee113eSDavid van Moolenbroek if (*fmt == 'a') {
4839*83ee113eSDavid van Moolenbroek fmt++;
4840*83ee113eSDavid van Moolenbroek goto and_again;
4841*83ee113eSDavid van Moolenbroek }
4842*83ee113eSDavid van Moolenbroek }
4843*83ee113eSDavid van Moolenbroek } while ((*fmt == 'A') || (*fmt == 'a'));
4844*83ee113eSDavid van Moolenbroek
4845*83ee113eSDavid van Moolenbroek return 1;
4846*83ee113eSDavid van Moolenbroek }
4847*83ee113eSDavid van Moolenbroek
4848*83ee113eSDavid van Moolenbroek /* option-statement :== identifier DOT identifier <syntax> SEMI
4849*83ee113eSDavid van Moolenbroek | identifier <syntax> SEMI
4850*83ee113eSDavid van Moolenbroek
4851*83ee113eSDavid van Moolenbroek Option syntax is handled specially through format strings, so it
4852*83ee113eSDavid van Moolenbroek would be painful to come up with BNF for it. However, it always
4853*83ee113eSDavid van Moolenbroek starts as above and ends in a SEMI. */
4854*83ee113eSDavid van Moolenbroek
parse_option_statement(result,cfile,lookups,option,op)4855*83ee113eSDavid van Moolenbroek int parse_option_statement (result, cfile, lookups, option, op)
4856*83ee113eSDavid van Moolenbroek struct executable_statement **result;
4857*83ee113eSDavid van Moolenbroek struct parse *cfile;
4858*83ee113eSDavid van Moolenbroek int lookups;
4859*83ee113eSDavid van Moolenbroek struct option *option;
4860*83ee113eSDavid van Moolenbroek enum statement_op op;
4861*83ee113eSDavid van Moolenbroek {
4862*83ee113eSDavid van Moolenbroek const char *val;
4863*83ee113eSDavid van Moolenbroek enum dhcp_token token;
4864*83ee113eSDavid van Moolenbroek struct expression *expr = (struct expression *)0;
4865*83ee113eSDavid van Moolenbroek int lose;
4866*83ee113eSDavid van Moolenbroek
4867*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
4868*83ee113eSDavid van Moolenbroek if ((token == SEMI) && (option->format[0] != 'Z')) {
4869*83ee113eSDavid van Moolenbroek /* Eat the semicolon... */
4870*83ee113eSDavid van Moolenbroek /*
4871*83ee113eSDavid van Moolenbroek * XXXSK: I'm not sure why we should ever get here, but we
4872*83ee113eSDavid van Moolenbroek * do during our startup. This confuses things if
4873*83ee113eSDavid van Moolenbroek * we are parsing a zero-length option, so don't
4874*83ee113eSDavid van Moolenbroek * eat the semicolon token in that case.
4875*83ee113eSDavid van Moolenbroek */
4876*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4877*83ee113eSDavid van Moolenbroek } else if (token == EQUAL) {
4878*83ee113eSDavid van Moolenbroek /* Eat the equals sign. */
4879*83ee113eSDavid van Moolenbroek skip_token(&val, (unsigned *)0, cfile);
4880*83ee113eSDavid van Moolenbroek
4881*83ee113eSDavid van Moolenbroek /* Parse a data expression and use its value for the data. */
4882*83ee113eSDavid van Moolenbroek if (!parse_data_expression (&expr, cfile, &lose)) {
4883*83ee113eSDavid van Moolenbroek /* In this context, we must have an executable
4884*83ee113eSDavid van Moolenbroek statement, so if we found something else, it's
4885*83ee113eSDavid van Moolenbroek still an error. */
4886*83ee113eSDavid van Moolenbroek if (!lose) {
4887*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4888*83ee113eSDavid van Moolenbroek "expecting a data expression.");
4889*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4890*83ee113eSDavid van Moolenbroek }
4891*83ee113eSDavid van Moolenbroek return 0;
4892*83ee113eSDavid van Moolenbroek }
4893*83ee113eSDavid van Moolenbroek } else {
4894*83ee113eSDavid van Moolenbroek if (! parse_option_data(&expr, cfile, lookups, option))
4895*83ee113eSDavid van Moolenbroek return 0;
4896*83ee113eSDavid van Moolenbroek }
4897*83ee113eSDavid van Moolenbroek
4898*83ee113eSDavid van Moolenbroek if (!parse_semi (cfile))
4899*83ee113eSDavid van Moolenbroek return 0;
4900*83ee113eSDavid van Moolenbroek if (!executable_statement_allocate (result, MDL))
4901*83ee113eSDavid van Moolenbroek log_fatal ("no memory for option statement.");
4902*83ee113eSDavid van Moolenbroek
4903*83ee113eSDavid van Moolenbroek (*result)->op = op;
4904*83ee113eSDavid van Moolenbroek if (expr && !option_cache (&(*result)->data.option,
4905*83ee113eSDavid van Moolenbroek NULL, expr, option, MDL))
4906*83ee113eSDavid van Moolenbroek log_fatal ("no memory for option cache");
4907*83ee113eSDavid van Moolenbroek
4908*83ee113eSDavid van Moolenbroek if (expr)
4909*83ee113eSDavid van Moolenbroek expression_dereference (&expr, MDL);
4910*83ee113eSDavid van Moolenbroek
4911*83ee113eSDavid van Moolenbroek return 1;
4912*83ee113eSDavid van Moolenbroek }
4913*83ee113eSDavid van Moolenbroek
parse_option_token(rv,cfile,fmt,expr,uniform,lookups)4914*83ee113eSDavid van Moolenbroek int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
4915*83ee113eSDavid van Moolenbroek struct expression **rv;
4916*83ee113eSDavid van Moolenbroek struct parse *cfile;
4917*83ee113eSDavid van Moolenbroek const char **fmt;
4918*83ee113eSDavid van Moolenbroek struct expression *expr;
4919*83ee113eSDavid van Moolenbroek int uniform;
4920*83ee113eSDavid van Moolenbroek int lookups;
4921*83ee113eSDavid van Moolenbroek {
4922*83ee113eSDavid van Moolenbroek const char *val;
4923*83ee113eSDavid van Moolenbroek enum dhcp_token token;
4924*83ee113eSDavid van Moolenbroek struct expression *t = (struct expression *)0;
4925*83ee113eSDavid van Moolenbroek unsigned char buf [4];
4926*83ee113eSDavid van Moolenbroek unsigned len;
4927*83ee113eSDavid van Moolenbroek struct iaddr addr;
4928*83ee113eSDavid van Moolenbroek int compress;
4929*83ee113eSDavid van Moolenbroek isc_boolean_t freeval = ISC_FALSE;
4930*83ee113eSDavid van Moolenbroek const char *f, *g;
4931*83ee113eSDavid van Moolenbroek struct enumeration_value *e;
4932*83ee113eSDavid van Moolenbroek
4933*83ee113eSDavid van Moolenbroek switch (**fmt) {
4934*83ee113eSDavid van Moolenbroek case 'U':
4935*83ee113eSDavid van Moolenbroek token = next_token (&val, &len, cfile);
4936*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
4937*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o') {
4938*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting identifier.");
4939*83ee113eSDavid van Moolenbroek if (token != SEMI)
4940*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4941*83ee113eSDavid van Moolenbroek }
4942*83ee113eSDavid van Moolenbroek return 0;
4943*83ee113eSDavid van Moolenbroek }
4944*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, (const unsigned char *)val,
4945*83ee113eSDavid van Moolenbroek len, 1, 1, MDL))
4946*83ee113eSDavid van Moolenbroek log_fatal ("No memory for %s", val);
4947*83ee113eSDavid van Moolenbroek break;
4948*83ee113eSDavid van Moolenbroek
4949*83ee113eSDavid van Moolenbroek case 'E':
4950*83ee113eSDavid van Moolenbroek g = strchr (*fmt, '.');
4951*83ee113eSDavid van Moolenbroek if (!g) {
4952*83ee113eSDavid van Moolenbroek parse_warn (cfile,
4953*83ee113eSDavid van Moolenbroek "malformed encapsulation format (bug!)");
4954*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4955*83ee113eSDavid van Moolenbroek return 0;
4956*83ee113eSDavid van Moolenbroek }
4957*83ee113eSDavid van Moolenbroek *fmt = g;
4958*83ee113eSDavid van Moolenbroek /* FALL THROUGH */
4959*83ee113eSDavid van Moolenbroek /* to get string value for the option */
4960*83ee113eSDavid van Moolenbroek case 'X':
4961*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
4962*83ee113eSDavid van Moolenbroek if (token == NUMBER_OR_NAME || token == NUMBER) {
4963*83ee113eSDavid van Moolenbroek if (!expression_allocate (&t, MDL))
4964*83ee113eSDavid van Moolenbroek return 0;
4965*83ee113eSDavid van Moolenbroek if (!parse_cshl (&t -> data.const_data, cfile)) {
4966*83ee113eSDavid van Moolenbroek expression_dereference (&t, MDL);
4967*83ee113eSDavid van Moolenbroek return 0;
4968*83ee113eSDavid van Moolenbroek }
4969*83ee113eSDavid van Moolenbroek t -> op = expr_const_data;
4970*83ee113eSDavid van Moolenbroek } else {
4971*83ee113eSDavid van Moolenbroek token = next_token (&val, &len, cfile);
4972*83ee113eSDavid van Moolenbroek
4973*83ee113eSDavid van Moolenbroek if(token == STRING) {
4974*83ee113eSDavid van Moolenbroek if (!make_const_data (&t,
4975*83ee113eSDavid van Moolenbroek (const unsigned char *)val,
4976*83ee113eSDavid van Moolenbroek len, 1, 1, MDL))
4977*83ee113eSDavid van Moolenbroek log_fatal ("No memory for \"%s\"", val);
4978*83ee113eSDavid van Moolenbroek } else {
4979*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o') {
4980*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting string "
4981*83ee113eSDavid van Moolenbroek "or hexadecimal data.");
4982*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
4983*83ee113eSDavid van Moolenbroek }
4984*83ee113eSDavid van Moolenbroek return 0;
4985*83ee113eSDavid van Moolenbroek }
4986*83ee113eSDavid van Moolenbroek }
4987*83ee113eSDavid van Moolenbroek break;
4988*83ee113eSDavid van Moolenbroek
4989*83ee113eSDavid van Moolenbroek case 'D': /* Domain list... */
4990*83ee113eSDavid van Moolenbroek if ((*fmt)[1] == 'c') {
4991*83ee113eSDavid van Moolenbroek compress = 1;
4992*83ee113eSDavid van Moolenbroek /* Skip the compress-flag atom. */
4993*83ee113eSDavid van Moolenbroek (*fmt)++;
4994*83ee113eSDavid van Moolenbroek } else
4995*83ee113eSDavid van Moolenbroek compress = 0;
4996*83ee113eSDavid van Moolenbroek
4997*83ee113eSDavid van Moolenbroek t = parse_domain_list(cfile, compress);
4998*83ee113eSDavid van Moolenbroek
4999*83ee113eSDavid van Moolenbroek if (!t) {
5000*83ee113eSDavid van Moolenbroek if ((*fmt)[1] != 'o')
5001*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
5002*83ee113eSDavid van Moolenbroek return 0;
5003*83ee113eSDavid van Moolenbroek }
5004*83ee113eSDavid van Moolenbroek
5005*83ee113eSDavid van Moolenbroek break;
5006*83ee113eSDavid van Moolenbroek
5007*83ee113eSDavid van Moolenbroek case 'd': /* Domain name... */
5008*83ee113eSDavid van Moolenbroek val = parse_host_name (cfile);
5009*83ee113eSDavid van Moolenbroek if (!val) {
5010*83ee113eSDavid van Moolenbroek parse_warn (cfile, "not a valid domain name.");
5011*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5012*83ee113eSDavid van Moolenbroek return 0;
5013*83ee113eSDavid van Moolenbroek }
5014*83ee113eSDavid van Moolenbroek len = strlen (val);
5015*83ee113eSDavid van Moolenbroek freeval = ISC_TRUE;
5016*83ee113eSDavid van Moolenbroek goto make_string;
5017*83ee113eSDavid van Moolenbroek
5018*83ee113eSDavid van Moolenbroek case 't': /* Text string... */
5019*83ee113eSDavid van Moolenbroek token = next_token (&val, &len, cfile);
5020*83ee113eSDavid van Moolenbroek if (token != STRING && !is_identifier (token)) {
5021*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o') {
5022*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting string.");
5023*83ee113eSDavid van Moolenbroek if (token != SEMI)
5024*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5025*83ee113eSDavid van Moolenbroek }
5026*83ee113eSDavid van Moolenbroek return 0;
5027*83ee113eSDavid van Moolenbroek }
5028*83ee113eSDavid van Moolenbroek make_string:
5029*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, (const unsigned char *)val,
5030*83ee113eSDavid van Moolenbroek len, 1, 1, MDL))
5031*83ee113eSDavid van Moolenbroek log_fatal ("No memory for concatenation");
5032*83ee113eSDavid van Moolenbroek if (freeval == ISC_TRUE) {
5033*83ee113eSDavid van Moolenbroek dfree((char *)val, MDL);
5034*83ee113eSDavid van Moolenbroek freeval = ISC_FALSE;
5035*83ee113eSDavid van Moolenbroek POST(freeval);
5036*83ee113eSDavid van Moolenbroek }
5037*83ee113eSDavid van Moolenbroek break;
5038*83ee113eSDavid van Moolenbroek
5039*83ee113eSDavid van Moolenbroek case 'N':
5040*83ee113eSDavid van Moolenbroek f = (*fmt) + 1;
5041*83ee113eSDavid van Moolenbroek g = strchr (*fmt, '.');
5042*83ee113eSDavid van Moolenbroek if (!g) {
5043*83ee113eSDavid van Moolenbroek parse_warn (cfile, "malformed %s (bug!)",
5044*83ee113eSDavid van Moolenbroek "enumeration format");
5045*83ee113eSDavid van Moolenbroek foo:
5046*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5047*83ee113eSDavid van Moolenbroek return 0;
5048*83ee113eSDavid van Moolenbroek }
5049*83ee113eSDavid van Moolenbroek *fmt = g;
5050*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5051*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
5052*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5053*83ee113eSDavid van Moolenbroek "identifier expected");
5054*83ee113eSDavid van Moolenbroek goto foo;
5055*83ee113eSDavid van Moolenbroek }
5056*83ee113eSDavid van Moolenbroek e = find_enumeration_value (f, (*fmt) - f, &len, val);
5057*83ee113eSDavid van Moolenbroek if (!e) {
5058*83ee113eSDavid van Moolenbroek parse_warn (cfile, "unknown value");
5059*83ee113eSDavid van Moolenbroek goto foo;
5060*83ee113eSDavid van Moolenbroek }
5061*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, &e -> value, len, 0, 1, MDL))
5062*83ee113eSDavid van Moolenbroek return 0;
5063*83ee113eSDavid van Moolenbroek break;
5064*83ee113eSDavid van Moolenbroek
5065*83ee113eSDavid van Moolenbroek case 'I': /* IP address or hostname. */
5066*83ee113eSDavid van Moolenbroek if (lookups) {
5067*83ee113eSDavid van Moolenbroek if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
5068*83ee113eSDavid van Moolenbroek return 0;
5069*83ee113eSDavid van Moolenbroek } else {
5070*83ee113eSDavid van Moolenbroek if (!parse_ip_addr (cfile, &addr))
5071*83ee113eSDavid van Moolenbroek return 0;
5072*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, addr.iabuf, addr.len,
5073*83ee113eSDavid van Moolenbroek 0, 1, MDL))
5074*83ee113eSDavid van Moolenbroek return 0;
5075*83ee113eSDavid van Moolenbroek }
5076*83ee113eSDavid van Moolenbroek break;
5077*83ee113eSDavid van Moolenbroek
5078*83ee113eSDavid van Moolenbroek case '6': /* IPv6 address. */
5079*83ee113eSDavid van Moolenbroek if (!parse_ip6_addr(cfile, &addr)) {
5080*83ee113eSDavid van Moolenbroek return 0;
5081*83ee113eSDavid van Moolenbroek }
5082*83ee113eSDavid van Moolenbroek if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) {
5083*83ee113eSDavid van Moolenbroek return 0;
5084*83ee113eSDavid van Moolenbroek }
5085*83ee113eSDavid van Moolenbroek break;
5086*83ee113eSDavid van Moolenbroek
5087*83ee113eSDavid van Moolenbroek case 'T': /* Lease interval. */
5088*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5089*83ee113eSDavid van Moolenbroek if (token != INFINITE)
5090*83ee113eSDavid van Moolenbroek goto check_number;
5091*83ee113eSDavid van Moolenbroek putLong (buf, -1);
5092*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5093*83ee113eSDavid van Moolenbroek return 0;
5094*83ee113eSDavid van Moolenbroek break;
5095*83ee113eSDavid van Moolenbroek
5096*83ee113eSDavid van Moolenbroek case 'L': /* Unsigned 32-bit integer... */
5097*83ee113eSDavid van Moolenbroek case 'l': /* Signed 32-bit integer... */
5098*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5099*83ee113eSDavid van Moolenbroek check_number:
5100*83ee113eSDavid van Moolenbroek if ((token != NUMBER) && (token != NUMBER_OR_NAME)) {
5101*83ee113eSDavid van Moolenbroek need_number:
5102*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o') {
5103*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting number.");
5104*83ee113eSDavid van Moolenbroek if (token != SEMI)
5105*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5106*83ee113eSDavid van Moolenbroek }
5107*83ee113eSDavid van Moolenbroek return 0;
5108*83ee113eSDavid van Moolenbroek }
5109*83ee113eSDavid van Moolenbroek convert_num (cfile, buf, val, 0, 32);
5110*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5111*83ee113eSDavid van Moolenbroek return 0;
5112*83ee113eSDavid van Moolenbroek break;
5113*83ee113eSDavid van Moolenbroek
5114*83ee113eSDavid van Moolenbroek case 's': /* Signed 16-bit integer. */
5115*83ee113eSDavid van Moolenbroek case 'S': /* Unsigned 16-bit integer. */
5116*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5117*83ee113eSDavid van Moolenbroek if ((token != NUMBER) && (token != NUMBER_OR_NAME))
5118*83ee113eSDavid van Moolenbroek goto need_number;
5119*83ee113eSDavid van Moolenbroek convert_num (cfile, buf, val, 0, 16);
5120*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, buf, 2, 0, 1, MDL))
5121*83ee113eSDavid van Moolenbroek return 0;
5122*83ee113eSDavid van Moolenbroek break;
5123*83ee113eSDavid van Moolenbroek
5124*83ee113eSDavid van Moolenbroek case 'b': /* Signed 8-bit integer. */
5125*83ee113eSDavid van Moolenbroek case 'B': /* Unsigned 8-bit integer. */
5126*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5127*83ee113eSDavid van Moolenbroek if ((token != NUMBER) && (token != NUMBER_OR_NAME))
5128*83ee113eSDavid van Moolenbroek goto need_number;
5129*83ee113eSDavid van Moolenbroek convert_num (cfile, buf, val, 0, 8);
5130*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5131*83ee113eSDavid van Moolenbroek return 0;
5132*83ee113eSDavid van Moolenbroek break;
5133*83ee113eSDavid van Moolenbroek
5134*83ee113eSDavid van Moolenbroek case 'f': /* Boolean flag. */
5135*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5136*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
5137*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o')
5138*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting identifier.");
5139*83ee113eSDavid van Moolenbroek bad_flag:
5140*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o') {
5141*83ee113eSDavid van Moolenbroek if (token != SEMI)
5142*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5143*83ee113eSDavid van Moolenbroek }
5144*83ee113eSDavid van Moolenbroek return 0;
5145*83ee113eSDavid van Moolenbroek }
5146*83ee113eSDavid van Moolenbroek if (!strcasecmp (val, "true")
5147*83ee113eSDavid van Moolenbroek || !strcasecmp (val, "on"))
5148*83ee113eSDavid van Moolenbroek buf [0] = 1;
5149*83ee113eSDavid van Moolenbroek else if (!strcasecmp (val, "false")
5150*83ee113eSDavid van Moolenbroek || !strcasecmp (val, "off"))
5151*83ee113eSDavid van Moolenbroek buf [0] = 0;
5152*83ee113eSDavid van Moolenbroek else if (!strcasecmp (val, "ignore"))
5153*83ee113eSDavid van Moolenbroek buf [0] = 2;
5154*83ee113eSDavid van Moolenbroek else {
5155*83ee113eSDavid van Moolenbroek if ((*fmt) [1] != 'o')
5156*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting boolean.");
5157*83ee113eSDavid van Moolenbroek goto bad_flag;
5158*83ee113eSDavid van Moolenbroek }
5159*83ee113eSDavid van Moolenbroek if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5160*83ee113eSDavid van Moolenbroek return 0;
5161*83ee113eSDavid van Moolenbroek break;
5162*83ee113eSDavid van Moolenbroek
5163*83ee113eSDavid van Moolenbroek case 'Z': /* Zero-length option. */
5164*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
5165*83ee113eSDavid van Moolenbroek if (token != SEMI) {
5166*83ee113eSDavid van Moolenbroek parse_warn(cfile, "semicolon expected.");
5167*83ee113eSDavid van Moolenbroek skip_to_semi(cfile);
5168*83ee113eSDavid van Moolenbroek }
5169*83ee113eSDavid van Moolenbroek buf[0] = '\0';
5170*83ee113eSDavid van Moolenbroek if (!make_const_data(&t, /* expression */
5171*83ee113eSDavid van Moolenbroek buf, /* buffer */
5172*83ee113eSDavid van Moolenbroek 0, /* length */
5173*83ee113eSDavid van Moolenbroek 0, /* terminated */
5174*83ee113eSDavid van Moolenbroek 1, /* allocate */
5175*83ee113eSDavid van Moolenbroek MDL))
5176*83ee113eSDavid van Moolenbroek return 0;
5177*83ee113eSDavid van Moolenbroek break;
5178*83ee113eSDavid van Moolenbroek
5179*83ee113eSDavid van Moolenbroek default:
5180*83ee113eSDavid van Moolenbroek parse_warn (cfile, "Bad format '%c' in parse_option_token.",
5181*83ee113eSDavid van Moolenbroek **fmt);
5182*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5183*83ee113eSDavid van Moolenbroek return 0;
5184*83ee113eSDavid van Moolenbroek }
5185*83ee113eSDavid van Moolenbroek if (expr) {
5186*83ee113eSDavid van Moolenbroek if (!make_concat (rv, expr, t))
5187*83ee113eSDavid van Moolenbroek return 0;
5188*83ee113eSDavid van Moolenbroek } else
5189*83ee113eSDavid van Moolenbroek expression_reference (rv, t, MDL);
5190*83ee113eSDavid van Moolenbroek expression_dereference (&t, MDL);
5191*83ee113eSDavid van Moolenbroek return 1;
5192*83ee113eSDavid van Moolenbroek }
5193*83ee113eSDavid van Moolenbroek
parse_option_decl(oc,cfile)5194*83ee113eSDavid van Moolenbroek int parse_option_decl (oc, cfile)
5195*83ee113eSDavid van Moolenbroek struct option_cache **oc;
5196*83ee113eSDavid van Moolenbroek struct parse *cfile;
5197*83ee113eSDavid van Moolenbroek {
5198*83ee113eSDavid van Moolenbroek const char *val;
5199*83ee113eSDavid van Moolenbroek int token;
5200*83ee113eSDavid van Moolenbroek u_int8_t buf [4];
5201*83ee113eSDavid van Moolenbroek u_int8_t hunkbuf [1024];
5202*83ee113eSDavid van Moolenbroek unsigned hunkix = 0;
5203*83ee113eSDavid van Moolenbroek const char *fmt, *f;
5204*83ee113eSDavid van Moolenbroek struct option *option=NULL;
5205*83ee113eSDavid van Moolenbroek struct iaddr ip_addr;
5206*83ee113eSDavid van Moolenbroek u_int8_t *dp;
5207*83ee113eSDavid van Moolenbroek const u_int8_t *cdp;
5208*83ee113eSDavid van Moolenbroek unsigned len;
5209*83ee113eSDavid van Moolenbroek int nul_term = 0;
5210*83ee113eSDavid van Moolenbroek struct buffer *bp;
5211*83ee113eSDavid van Moolenbroek int known = 0;
5212*83ee113eSDavid van Moolenbroek int compress;
5213*83ee113eSDavid van Moolenbroek struct expression *express = NULL;
5214*83ee113eSDavid van Moolenbroek struct enumeration_value *e;
5215*83ee113eSDavid van Moolenbroek isc_result_t status;
5216*83ee113eSDavid van Moolenbroek
5217*83ee113eSDavid van Moolenbroek status = parse_option_name (cfile, 0, &known, &option);
5218*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS || option == NULL)
5219*83ee113eSDavid van Moolenbroek return 0;
5220*83ee113eSDavid van Moolenbroek
5221*83ee113eSDavid van Moolenbroek fmt = option->format;
5222*83ee113eSDavid van Moolenbroek
5223*83ee113eSDavid van Moolenbroek /* Parse the option data... */
5224*83ee113eSDavid van Moolenbroek do {
5225*83ee113eSDavid van Moolenbroek for (; *fmt; fmt++) {
5226*83ee113eSDavid van Moolenbroek if (*fmt == 'A') {
5227*83ee113eSDavid van Moolenbroek /* 'A' is an array of records, start at
5228*83ee113eSDavid van Moolenbroek * the beginning
5229*83ee113eSDavid van Moolenbroek */
5230*83ee113eSDavid van Moolenbroek fmt = option->format;
5231*83ee113eSDavid van Moolenbroek break;
5232*83ee113eSDavid van Moolenbroek }
5233*83ee113eSDavid van Moolenbroek
5234*83ee113eSDavid van Moolenbroek if (*fmt == 'a') {
5235*83ee113eSDavid van Moolenbroek /* 'a' is an array of the last field,
5236*83ee113eSDavid van Moolenbroek * back up one format character
5237*83ee113eSDavid van Moolenbroek */
5238*83ee113eSDavid van Moolenbroek fmt--;
5239*83ee113eSDavid van Moolenbroek break;
5240*83ee113eSDavid van Moolenbroek }
5241*83ee113eSDavid van Moolenbroek if (*fmt == 'o' && fmt != option -> format)
5242*83ee113eSDavid van Moolenbroek continue;
5243*83ee113eSDavid van Moolenbroek switch (*fmt) {
5244*83ee113eSDavid van Moolenbroek case 'E':
5245*83ee113eSDavid van Moolenbroek fmt = strchr (fmt, '.');
5246*83ee113eSDavid van Moolenbroek if (!fmt) {
5247*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5248*83ee113eSDavid van Moolenbroek "malformed %s (bug!)",
5249*83ee113eSDavid van Moolenbroek "encapsulation format");
5250*83ee113eSDavid van Moolenbroek goto parse_exit;
5251*83ee113eSDavid van Moolenbroek }
5252*83ee113eSDavid van Moolenbroek /* FALL THROUGH */
5253*83ee113eSDavid van Moolenbroek /* to get string value for the option */
5254*83ee113eSDavid van Moolenbroek case 'X':
5255*83ee113eSDavid van Moolenbroek len = parse_X (cfile, &hunkbuf [hunkix],
5256*83ee113eSDavid van Moolenbroek sizeof hunkbuf - hunkix);
5257*83ee113eSDavid van Moolenbroek hunkix += len;
5258*83ee113eSDavid van Moolenbroek break;
5259*83ee113eSDavid van Moolenbroek
5260*83ee113eSDavid van Moolenbroek case 't': /* Text string... */
5261*83ee113eSDavid van Moolenbroek token = peek_token (&val,
5262*83ee113eSDavid van Moolenbroek &len, cfile);
5263*83ee113eSDavid van Moolenbroek if (token == SEMI && fmt[1] == 'o') {
5264*83ee113eSDavid van Moolenbroek fmt++;
5265*83ee113eSDavid van Moolenbroek break;
5266*83ee113eSDavid van Moolenbroek }
5267*83ee113eSDavid van Moolenbroek token = next_token (&val,
5268*83ee113eSDavid van Moolenbroek &len, cfile);
5269*83ee113eSDavid van Moolenbroek if (token != STRING) {
5270*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5271*83ee113eSDavid van Moolenbroek "expecting string.");
5272*83ee113eSDavid van Moolenbroek goto parse_exit;
5273*83ee113eSDavid van Moolenbroek }
5274*83ee113eSDavid van Moolenbroek if (hunkix + len + 1 > sizeof hunkbuf) {
5275*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5276*83ee113eSDavid van Moolenbroek "option data buffer %s",
5277*83ee113eSDavid van Moolenbroek "overflow");
5278*83ee113eSDavid van Moolenbroek goto parse_exit;
5279*83ee113eSDavid van Moolenbroek }
5280*83ee113eSDavid van Moolenbroek memcpy (&hunkbuf [hunkix], val, len + 1);
5281*83ee113eSDavid van Moolenbroek nul_term = 1;
5282*83ee113eSDavid van Moolenbroek hunkix += len;
5283*83ee113eSDavid van Moolenbroek break;
5284*83ee113eSDavid van Moolenbroek
5285*83ee113eSDavid van Moolenbroek case 'D':
5286*83ee113eSDavid van Moolenbroek if (fmt[1] == 'c') {
5287*83ee113eSDavid van Moolenbroek compress = 1;
5288*83ee113eSDavid van Moolenbroek fmt++;
5289*83ee113eSDavid van Moolenbroek } else
5290*83ee113eSDavid van Moolenbroek compress = 0;
5291*83ee113eSDavid van Moolenbroek
5292*83ee113eSDavid van Moolenbroek express = parse_domain_list(cfile, compress);
5293*83ee113eSDavid van Moolenbroek
5294*83ee113eSDavid van Moolenbroek if (express == NULL)
5295*83ee113eSDavid van Moolenbroek goto exit;
5296*83ee113eSDavid van Moolenbroek
5297*83ee113eSDavid van Moolenbroek if (express->op != expr_const_data) {
5298*83ee113eSDavid van Moolenbroek parse_warn(cfile, "unexpected "
5299*83ee113eSDavid van Moolenbroek "expression");
5300*83ee113eSDavid van Moolenbroek goto parse_exit;
5301*83ee113eSDavid van Moolenbroek }
5302*83ee113eSDavid van Moolenbroek
5303*83ee113eSDavid van Moolenbroek len = express->data.const_data.len;
5304*83ee113eSDavid van Moolenbroek cdp = express->data.const_data.data;
5305*83ee113eSDavid van Moolenbroek
5306*83ee113eSDavid van Moolenbroek if ((hunkix + len) > sizeof(hunkbuf)) {
5307*83ee113eSDavid van Moolenbroek parse_warn(cfile, "option data buffer "
5308*83ee113eSDavid van Moolenbroek "overflow");
5309*83ee113eSDavid van Moolenbroek goto parse_exit;
5310*83ee113eSDavid van Moolenbroek }
5311*83ee113eSDavid van Moolenbroek memcpy(&hunkbuf[hunkix], cdp, len);
5312*83ee113eSDavid van Moolenbroek hunkix += len;
5313*83ee113eSDavid van Moolenbroek
5314*83ee113eSDavid van Moolenbroek expression_dereference(&express, MDL);
5315*83ee113eSDavid van Moolenbroek break;
5316*83ee113eSDavid van Moolenbroek
5317*83ee113eSDavid van Moolenbroek case 'N':
5318*83ee113eSDavid van Moolenbroek f = fmt + 1;
5319*83ee113eSDavid van Moolenbroek fmt = strchr (fmt, '.');
5320*83ee113eSDavid van Moolenbroek if (!fmt) {
5321*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5322*83ee113eSDavid van Moolenbroek "malformed %s (bug!)",
5323*83ee113eSDavid van Moolenbroek "enumeration format");
5324*83ee113eSDavid van Moolenbroek goto parse_exit;
5325*83ee113eSDavid van Moolenbroek }
5326*83ee113eSDavid van Moolenbroek token = next_token (&val,
5327*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
5328*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
5329*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5330*83ee113eSDavid van Moolenbroek "identifier expected");
5331*83ee113eSDavid van Moolenbroek goto parse_exit;
5332*83ee113eSDavid van Moolenbroek }
5333*83ee113eSDavid van Moolenbroek e = find_enumeration_value (f, fmt - f,
5334*83ee113eSDavid van Moolenbroek &len, val);
5335*83ee113eSDavid van Moolenbroek if (!e) {
5336*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5337*83ee113eSDavid van Moolenbroek "unknown value");
5338*83ee113eSDavid van Moolenbroek goto parse_exit;
5339*83ee113eSDavid van Moolenbroek }
5340*83ee113eSDavid van Moolenbroek dp = &e -> value;
5341*83ee113eSDavid van Moolenbroek goto alloc;
5342*83ee113eSDavid van Moolenbroek
5343*83ee113eSDavid van Moolenbroek case '6':
5344*83ee113eSDavid van Moolenbroek if (!parse_ip6_addr(cfile, &ip_addr))
5345*83ee113eSDavid van Moolenbroek goto exit;
5346*83ee113eSDavid van Moolenbroek len = ip_addr.len;
5347*83ee113eSDavid van Moolenbroek dp = ip_addr.iabuf;
5348*83ee113eSDavid van Moolenbroek goto alloc;
5349*83ee113eSDavid van Moolenbroek
5350*83ee113eSDavid van Moolenbroek case 'I': /* IP address. */
5351*83ee113eSDavid van Moolenbroek if (!parse_ip_addr (cfile, &ip_addr))
5352*83ee113eSDavid van Moolenbroek goto exit;
5353*83ee113eSDavid van Moolenbroek len = ip_addr.len;
5354*83ee113eSDavid van Moolenbroek dp = ip_addr.iabuf;
5355*83ee113eSDavid van Moolenbroek
5356*83ee113eSDavid van Moolenbroek alloc:
5357*83ee113eSDavid van Moolenbroek if (hunkix + len > sizeof hunkbuf) {
5358*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5359*83ee113eSDavid van Moolenbroek "option data buffer %s",
5360*83ee113eSDavid van Moolenbroek "overflow");
5361*83ee113eSDavid van Moolenbroek goto parse_exit;
5362*83ee113eSDavid van Moolenbroek }
5363*83ee113eSDavid van Moolenbroek memcpy (&hunkbuf [hunkix], dp, len);
5364*83ee113eSDavid van Moolenbroek hunkix += len;
5365*83ee113eSDavid van Moolenbroek break;
5366*83ee113eSDavid van Moolenbroek
5367*83ee113eSDavid van Moolenbroek case 'L': /* Unsigned 32-bit integer... */
5368*83ee113eSDavid van Moolenbroek case 'l': /* Signed 32-bit integer... */
5369*83ee113eSDavid van Moolenbroek token = next_token (&val,
5370*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
5371*83ee113eSDavid van Moolenbroek if ((token != NUMBER) &&
5372*83ee113eSDavid van Moolenbroek (token != NUMBER_OR_NAME)) {
5373*83ee113eSDavid van Moolenbroek need_number:
5374*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5375*83ee113eSDavid van Moolenbroek "expecting number.");
5376*83ee113eSDavid van Moolenbroek if (token != SEMI)
5377*83ee113eSDavid van Moolenbroek goto parse_exit;
5378*83ee113eSDavid van Moolenbroek else
5379*83ee113eSDavid van Moolenbroek goto exit;
5380*83ee113eSDavid van Moolenbroek }
5381*83ee113eSDavid van Moolenbroek convert_num (cfile, buf, val, 0, 32);
5382*83ee113eSDavid van Moolenbroek len = 4;
5383*83ee113eSDavid van Moolenbroek dp = buf;
5384*83ee113eSDavid van Moolenbroek goto alloc;
5385*83ee113eSDavid van Moolenbroek
5386*83ee113eSDavid van Moolenbroek case 's': /* Signed 16-bit integer. */
5387*83ee113eSDavid van Moolenbroek case 'S': /* Unsigned 16-bit integer. */
5388*83ee113eSDavid van Moolenbroek token = next_token (&val,
5389*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
5390*83ee113eSDavid van Moolenbroek if ((token != NUMBER) &&
5391*83ee113eSDavid van Moolenbroek (token != NUMBER_OR_NAME))
5392*83ee113eSDavid van Moolenbroek goto need_number;
5393*83ee113eSDavid van Moolenbroek convert_num (cfile, buf, val, 0, 16);
5394*83ee113eSDavid van Moolenbroek len = 2;
5395*83ee113eSDavid van Moolenbroek dp = buf;
5396*83ee113eSDavid van Moolenbroek goto alloc;
5397*83ee113eSDavid van Moolenbroek
5398*83ee113eSDavid van Moolenbroek case 'b': /* Signed 8-bit integer. */
5399*83ee113eSDavid van Moolenbroek case 'B': /* Unsigned 8-bit integer. */
5400*83ee113eSDavid van Moolenbroek token = next_token (&val,
5401*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
5402*83ee113eSDavid van Moolenbroek if ((token != NUMBER) &&
5403*83ee113eSDavid van Moolenbroek (token != NUMBER_OR_NAME))
5404*83ee113eSDavid van Moolenbroek goto need_number;
5405*83ee113eSDavid van Moolenbroek convert_num (cfile, buf, val, 0, 8);
5406*83ee113eSDavid van Moolenbroek len = 1;
5407*83ee113eSDavid van Moolenbroek dp = buf;
5408*83ee113eSDavid van Moolenbroek goto alloc;
5409*83ee113eSDavid van Moolenbroek
5410*83ee113eSDavid van Moolenbroek case 'f': /* Boolean flag. */
5411*83ee113eSDavid van Moolenbroek token = next_token (&val,
5412*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
5413*83ee113eSDavid van Moolenbroek if (!is_identifier (token)) {
5414*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5415*83ee113eSDavid van Moolenbroek "expecting identifier.");
5416*83ee113eSDavid van Moolenbroek bad_flag:
5417*83ee113eSDavid van Moolenbroek if (token != SEMI)
5418*83ee113eSDavid van Moolenbroek goto parse_exit;
5419*83ee113eSDavid van Moolenbroek else
5420*83ee113eSDavid van Moolenbroek goto exit;
5421*83ee113eSDavid van Moolenbroek }
5422*83ee113eSDavid van Moolenbroek if (!strcasecmp (val, "true")
5423*83ee113eSDavid van Moolenbroek || !strcasecmp (val, "on"))
5424*83ee113eSDavid van Moolenbroek buf [0] = 1;
5425*83ee113eSDavid van Moolenbroek else if (!strcasecmp (val, "false")
5426*83ee113eSDavid van Moolenbroek || !strcasecmp (val, "off"))
5427*83ee113eSDavid van Moolenbroek buf [0] = 0;
5428*83ee113eSDavid van Moolenbroek else {
5429*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5430*83ee113eSDavid van Moolenbroek "expecting boolean.");
5431*83ee113eSDavid van Moolenbroek goto bad_flag;
5432*83ee113eSDavid van Moolenbroek }
5433*83ee113eSDavid van Moolenbroek len = 1;
5434*83ee113eSDavid van Moolenbroek dp = buf;
5435*83ee113eSDavid van Moolenbroek goto alloc;
5436*83ee113eSDavid van Moolenbroek
5437*83ee113eSDavid van Moolenbroek case 'Z': /* Zero-length option */
5438*83ee113eSDavid van Moolenbroek token = peek_token(&val, (unsigned *)0, cfile);
5439*83ee113eSDavid van Moolenbroek if (token != SEMI) {
5440*83ee113eSDavid van Moolenbroek parse_warn(cfile,
5441*83ee113eSDavid van Moolenbroek "semicolon expected.");
5442*83ee113eSDavid van Moolenbroek goto parse_exit;
5443*83ee113eSDavid van Moolenbroek }
5444*83ee113eSDavid van Moolenbroek len = 0;
5445*83ee113eSDavid van Moolenbroek buf[0] = '\0';
5446*83ee113eSDavid van Moolenbroek break;
5447*83ee113eSDavid van Moolenbroek
5448*83ee113eSDavid van Moolenbroek default:
5449*83ee113eSDavid van Moolenbroek log_error ("parse_option_param: Bad format %c",
5450*83ee113eSDavid van Moolenbroek *fmt);
5451*83ee113eSDavid van Moolenbroek goto parse_exit;
5452*83ee113eSDavid van Moolenbroek }
5453*83ee113eSDavid van Moolenbroek }
5454*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5455*83ee113eSDavid van Moolenbroek } while (*fmt && token == COMMA);
5456*83ee113eSDavid van Moolenbroek
5457*83ee113eSDavid van Moolenbroek if (token != SEMI) {
5458*83ee113eSDavid van Moolenbroek parse_warn (cfile, "semicolon expected.");
5459*83ee113eSDavid van Moolenbroek goto parse_exit;
5460*83ee113eSDavid van Moolenbroek }
5461*83ee113eSDavid van Moolenbroek
5462*83ee113eSDavid van Moolenbroek bp = (struct buffer *)0;
5463*83ee113eSDavid van Moolenbroek if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
5464*83ee113eSDavid van Moolenbroek log_fatal ("no memory to store option declaration.");
5465*83ee113eSDavid van Moolenbroek memcpy (bp -> data, hunkbuf, hunkix + nul_term);
5466*83ee113eSDavid van Moolenbroek
5467*83ee113eSDavid van Moolenbroek if (!option_cache_allocate (oc, MDL))
5468*83ee113eSDavid van Moolenbroek log_fatal ("out of memory allocating option cache.");
5469*83ee113eSDavid van Moolenbroek
5470*83ee113eSDavid van Moolenbroek (*oc) -> data.buffer = bp;
5471*83ee113eSDavid van Moolenbroek (*oc) -> data.data = &bp -> data [0];
5472*83ee113eSDavid van Moolenbroek (*oc) -> data.terminated = nul_term;
5473*83ee113eSDavid van Moolenbroek (*oc) -> data.len = hunkix;
5474*83ee113eSDavid van Moolenbroek option_reference(&(*oc)->option, option, MDL);
5475*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
5476*83ee113eSDavid van Moolenbroek return 1;
5477*83ee113eSDavid van Moolenbroek
5478*83ee113eSDavid van Moolenbroek parse_exit:
5479*83ee113eSDavid van Moolenbroek if (express != NULL)
5480*83ee113eSDavid van Moolenbroek expression_dereference(&express, MDL);
5481*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5482*83ee113eSDavid van Moolenbroek exit:
5483*83ee113eSDavid van Moolenbroek option_dereference(&option, MDL);
5484*83ee113eSDavid van Moolenbroek
5485*83ee113eSDavid van Moolenbroek return 0;
5486*83ee113eSDavid van Moolenbroek }
5487*83ee113eSDavid van Moolenbroek
5488*83ee113eSDavid van Moolenbroek /* Consider merging parse_cshl into this. */
5489*83ee113eSDavid van Moolenbroek
parse_X(cfile,buf,max)5490*83ee113eSDavid van Moolenbroek int parse_X (cfile, buf, max)
5491*83ee113eSDavid van Moolenbroek struct parse *cfile;
5492*83ee113eSDavid van Moolenbroek u_int8_t *buf;
5493*83ee113eSDavid van Moolenbroek unsigned max;
5494*83ee113eSDavid van Moolenbroek {
5495*83ee113eSDavid van Moolenbroek int token;
5496*83ee113eSDavid van Moolenbroek const char *val;
5497*83ee113eSDavid van Moolenbroek unsigned len;
5498*83ee113eSDavid van Moolenbroek
5499*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
5500*83ee113eSDavid van Moolenbroek if (token == NUMBER_OR_NAME || token == NUMBER) {
5501*83ee113eSDavid van Moolenbroek len = 0;
5502*83ee113eSDavid van Moolenbroek do {
5503*83ee113eSDavid van Moolenbroek token = next_token (&val, (unsigned *)0, cfile);
5504*83ee113eSDavid van Moolenbroek if (token != NUMBER && token != NUMBER_OR_NAME) {
5505*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5506*83ee113eSDavid van Moolenbroek "expecting hexadecimal constant.");
5507*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5508*83ee113eSDavid van Moolenbroek return 0;
5509*83ee113eSDavid van Moolenbroek }
5510*83ee113eSDavid van Moolenbroek convert_num (cfile, &buf [len], val, 16, 8);
5511*83ee113eSDavid van Moolenbroek if (len++ > max) {
5512*83ee113eSDavid van Moolenbroek parse_warn (cfile,
5513*83ee113eSDavid van Moolenbroek "hexadecimal constant too long.");
5514*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5515*83ee113eSDavid van Moolenbroek return 0;
5516*83ee113eSDavid van Moolenbroek }
5517*83ee113eSDavid van Moolenbroek token = peek_token (&val, (unsigned *)0, cfile);
5518*83ee113eSDavid van Moolenbroek if (token == COLON)
5519*83ee113eSDavid van Moolenbroek token = next_token (&val,
5520*83ee113eSDavid van Moolenbroek (unsigned *)0, cfile);
5521*83ee113eSDavid van Moolenbroek } while (token == COLON);
5522*83ee113eSDavid van Moolenbroek val = (char *)buf;
5523*83ee113eSDavid van Moolenbroek } else if (token == STRING) {
5524*83ee113eSDavid van Moolenbroek skip_token(&val, &len, cfile);
5525*83ee113eSDavid van Moolenbroek if (len + 1 > max) {
5526*83ee113eSDavid van Moolenbroek parse_warn (cfile, "string constant too long.");
5527*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5528*83ee113eSDavid van Moolenbroek return 0;
5529*83ee113eSDavid van Moolenbroek }
5530*83ee113eSDavid van Moolenbroek memcpy (buf, val, len + 1);
5531*83ee113eSDavid van Moolenbroek } else {
5532*83ee113eSDavid van Moolenbroek parse_warn (cfile, "expecting string or hexadecimal data");
5533*83ee113eSDavid van Moolenbroek skip_to_semi (cfile);
5534*83ee113eSDavid van Moolenbroek return 0;
5535*83ee113eSDavid van Moolenbroek }
5536*83ee113eSDavid van Moolenbroek return len;
5537*83ee113eSDavid van Moolenbroek }
5538*83ee113eSDavid van Moolenbroek
parse_warn(struct parse * cfile,const char * fmt,...)5539*83ee113eSDavid van Moolenbroek int parse_warn (struct parse *cfile, const char *fmt, ...)
5540*83ee113eSDavid van Moolenbroek {
5541*83ee113eSDavid van Moolenbroek va_list list;
5542*83ee113eSDavid van Moolenbroek char lexbuf [256];
5543*83ee113eSDavid van Moolenbroek char mbuf [1024];
5544*83ee113eSDavid van Moolenbroek char fbuf [1024];
5545*83ee113eSDavid van Moolenbroek unsigned i, lix;
5546*83ee113eSDavid van Moolenbroek
5547*83ee113eSDavid van Moolenbroek do_percentm (mbuf, fmt);
5548*83ee113eSDavid van Moolenbroek /* %Audit% This is log output. %2004.06.17,Safe%
5549*83ee113eSDavid van Moolenbroek * If we truncate we hope the user can get a hint from the log.
5550*83ee113eSDavid van Moolenbroek */
5551*83ee113eSDavid van Moolenbroek snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
5552*83ee113eSDavid van Moolenbroek cfile -> tlname, cfile -> lexline, mbuf);
5553*83ee113eSDavid van Moolenbroek
5554*83ee113eSDavid van Moolenbroek va_start (list, fmt);
5555*83ee113eSDavid van Moolenbroek vsnprintf (mbuf, sizeof mbuf, fbuf, list);
5556*83ee113eSDavid van Moolenbroek va_end (list);
5557*83ee113eSDavid van Moolenbroek
5558*83ee113eSDavid van Moolenbroek lix = 0;
5559*83ee113eSDavid van Moolenbroek for (i = 0;
5560*83ee113eSDavid van Moolenbroek cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
5561*83ee113eSDavid van Moolenbroek if (lix < (sizeof lexbuf) - 1)
5562*83ee113eSDavid van Moolenbroek lexbuf [lix++] = ' ';
5563*83ee113eSDavid van Moolenbroek if (cfile -> token_line [i] == '\t') {
5564*83ee113eSDavid van Moolenbroek for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
5565*83ee113eSDavid van Moolenbroek lexbuf [lix] = ' ';
5566*83ee113eSDavid van Moolenbroek }
5567*83ee113eSDavid van Moolenbroek }
5568*83ee113eSDavid van Moolenbroek lexbuf [lix] = 0;
5569*83ee113eSDavid van Moolenbroek
5570*83ee113eSDavid van Moolenbroek #ifndef DEBUG
5571*83ee113eSDavid van Moolenbroek syslog (log_priority | LOG_ERR, "%s", mbuf);
5572*83ee113eSDavid van Moolenbroek syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
5573*83ee113eSDavid van Moolenbroek if (cfile -> lexchar < 81)
5574*83ee113eSDavid van Moolenbroek syslog (log_priority | LOG_ERR, "%s^", lexbuf);
5575*83ee113eSDavid van Moolenbroek #endif
5576*83ee113eSDavid van Moolenbroek
5577*83ee113eSDavid van Moolenbroek if (log_perror) {
5578*83ee113eSDavid van Moolenbroek IGNORE_RET (write (STDERR_FILENO, mbuf, strlen (mbuf)));
5579*83ee113eSDavid van Moolenbroek IGNORE_RET (write (STDERR_FILENO, "\n", 1));
5580*83ee113eSDavid van Moolenbroek IGNORE_RET (write (STDERR_FILENO, cfile -> token_line,
5581*83ee113eSDavid van Moolenbroek strlen (cfile -> token_line)));
5582*83ee113eSDavid van Moolenbroek IGNORE_RET (write (STDERR_FILENO, "\n", 1));
5583*83ee113eSDavid van Moolenbroek if (cfile -> lexchar < 81)
5584*83ee113eSDavid van Moolenbroek IGNORE_RET (write (STDERR_FILENO, lexbuf, lix));
5585*83ee113eSDavid van Moolenbroek IGNORE_RET (write (STDERR_FILENO, "^\n", 2));
5586*83ee113eSDavid van Moolenbroek }
5587*83ee113eSDavid van Moolenbroek
5588*83ee113eSDavid van Moolenbroek cfile -> warnings_occurred = 1;
5589*83ee113eSDavid van Moolenbroek
5590*83ee113eSDavid van Moolenbroek return 0;
5591*83ee113eSDavid van Moolenbroek }
5592*83ee113eSDavid van Moolenbroek
5593*83ee113eSDavid van Moolenbroek struct expression *
parse_domain_list(struct parse * cfile,int compress)5594*83ee113eSDavid van Moolenbroek parse_domain_list(struct parse *cfile, int compress)
5595*83ee113eSDavid van Moolenbroek {
5596*83ee113eSDavid van Moolenbroek const char *val;
5597*83ee113eSDavid van Moolenbroek enum dhcp_token token = SEMI;
5598*83ee113eSDavid van Moolenbroek struct expression *t = NULL;
5599*83ee113eSDavid van Moolenbroek unsigned len, clen = 0;
5600*83ee113eSDavid van Moolenbroek int result;
5601*83ee113eSDavid van Moolenbroek unsigned char compbuf[256 * NS_MAXCDNAME];
5602*83ee113eSDavid van Moolenbroek const unsigned char *dnptrs[256], **lastdnptr;
5603*83ee113eSDavid van Moolenbroek
5604*83ee113eSDavid van Moolenbroek memset(compbuf, 0, sizeof(compbuf));
5605*83ee113eSDavid van Moolenbroek memset(dnptrs, 0, sizeof(dnptrs));
5606*83ee113eSDavid van Moolenbroek dnptrs[0] = compbuf;
5607*83ee113eSDavid van Moolenbroek lastdnptr = &dnptrs[255];
5608*83ee113eSDavid van Moolenbroek
5609*83ee113eSDavid van Moolenbroek do {
5610*83ee113eSDavid van Moolenbroek /* Consume the COMMA token if peeked. */
5611*83ee113eSDavid van Moolenbroek if (token == COMMA)
5612*83ee113eSDavid van Moolenbroek skip_token(&val, NULL, cfile);
5613*83ee113eSDavid van Moolenbroek
5614*83ee113eSDavid van Moolenbroek /* Get next (or first) value. */
5615*83ee113eSDavid van Moolenbroek token = next_token(&val, &len, cfile);
5616*83ee113eSDavid van Moolenbroek
5617*83ee113eSDavid van Moolenbroek if (token != STRING) {
5618*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Expecting a domain string.");
5619*83ee113eSDavid van Moolenbroek return NULL;
5620*83ee113eSDavid van Moolenbroek }
5621*83ee113eSDavid van Moolenbroek
5622*83ee113eSDavid van Moolenbroek /* If compression pointers are enabled, compress. If not,
5623*83ee113eSDavid van Moolenbroek * just pack the names in series into the buffer.
5624*83ee113eSDavid van Moolenbroek */
5625*83ee113eSDavid van Moolenbroek if (compress) {
5626*83ee113eSDavid van Moolenbroek result = MRns_name_compress(val, compbuf + clen,
5627*83ee113eSDavid van Moolenbroek sizeof(compbuf) - clen,
5628*83ee113eSDavid van Moolenbroek dnptrs, lastdnptr);
5629*83ee113eSDavid van Moolenbroek
5630*83ee113eSDavid van Moolenbroek if (result < 0) {
5631*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Error compressing domain "
5632*83ee113eSDavid van Moolenbroek "list: %m");
5633*83ee113eSDavid van Moolenbroek return NULL;
5634*83ee113eSDavid van Moolenbroek }
5635*83ee113eSDavid van Moolenbroek
5636*83ee113eSDavid van Moolenbroek clen += result;
5637*83ee113eSDavid van Moolenbroek } else {
5638*83ee113eSDavid van Moolenbroek result = MRns_name_pton(val, compbuf + clen,
5639*83ee113eSDavid van Moolenbroek sizeof(compbuf) - clen);
5640*83ee113eSDavid van Moolenbroek
5641*83ee113eSDavid van Moolenbroek /* result == 1 means the input was fully qualified.
5642*83ee113eSDavid van Moolenbroek * result == 0 means the input wasn't.
5643*83ee113eSDavid van Moolenbroek * result == -1 means bad things.
5644*83ee113eSDavid van Moolenbroek */
5645*83ee113eSDavid van Moolenbroek if (result < 0) {
5646*83ee113eSDavid van Moolenbroek parse_warn(cfile, "Error assembling domain "
5647*83ee113eSDavid van Moolenbroek "list: %m");
5648*83ee113eSDavid van Moolenbroek return NULL;
5649*83ee113eSDavid van Moolenbroek }
5650*83ee113eSDavid van Moolenbroek
5651*83ee113eSDavid van Moolenbroek /*
5652*83ee113eSDavid van Moolenbroek * We need to figure out how many bytes to increment
5653*83ee113eSDavid van Moolenbroek * our buffer pointer since pton doesn't tell us.
5654*83ee113eSDavid van Moolenbroek */
5655*83ee113eSDavid van Moolenbroek while (compbuf[clen] != 0)
5656*83ee113eSDavid van Moolenbroek clen += compbuf[clen] + 1;
5657*83ee113eSDavid van Moolenbroek
5658*83ee113eSDavid van Moolenbroek /* Count the last label (0). */
5659*83ee113eSDavid van Moolenbroek clen++;
5660*83ee113eSDavid van Moolenbroek }
5661*83ee113eSDavid van Moolenbroek
5662*83ee113eSDavid van Moolenbroek if (clen > sizeof(compbuf))
5663*83ee113eSDavid van Moolenbroek log_fatal("Impossible error at %s:%d", MDL);
5664*83ee113eSDavid van Moolenbroek
5665*83ee113eSDavid van Moolenbroek token = peek_token(&val, NULL, cfile);
5666*83ee113eSDavid van Moolenbroek } while (token == COMMA);
5667*83ee113eSDavid van Moolenbroek
5668*83ee113eSDavid van Moolenbroek if (!make_const_data(&t, compbuf, clen, 1, 1, MDL))
5669*83ee113eSDavid van Moolenbroek log_fatal("No memory for domain list object.");
5670*83ee113eSDavid van Moolenbroek
5671*83ee113eSDavid van Moolenbroek return t;
5672*83ee113eSDavid van Moolenbroek }
5673*83ee113eSDavid van Moolenbroek
5674