#ifndef lint
static char copyright[] =
-"$Id: clparse.c,v 1.51 2000/11/24 03:38:18 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
+"$Id: clparse.c,v 1.52 2000/11/28 22:07:09 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
parse_semi (cfile);
}
-int parse_X (cfile, buf, max)
- struct parse *cfile;
- u_int8_t *buf;
- unsigned max;
-{
- int token;
- const char *val;
- unsigned len;
- u_int8_t *s;
-
- token = peek_token (&val, cfile);
- if (token == NUMBER_OR_NAME || token == NUMBER) {
- len = 0;
- do {
- token = next_token (&val, cfile);
- if (token != NUMBER && token != NUMBER_OR_NAME) {
- parse_warn (cfile,
- "expecting hexadecimal constant.");
- skip_to_semi (cfile);
- return 0;
- }
- convert_num (cfile, &buf [len], val, 16, 8);
- if (len++ > max) {
- parse_warn (cfile,
- "hexadecimal constant too long.");
- skip_to_semi (cfile);
- return 0;
- }
- token = peek_token (&val, cfile);
- if (token == COLON)
- token = next_token (&val, cfile);
- } while (token == COLON);
- val = (char *)buf;
- } else if (token == STRING) {
- token = next_token (&val, cfile);
- len = strlen (val);
- if (len + 1 > max) {
- parse_warn (cfile, "string constant too long.");
- skip_to_semi (cfile);
- return 0;
- }
- memcpy (buf, val, len + 1);
- } else {
- parse_warn (cfile, "expecting string or hexadecimal data");
- skip_to_semi (cfile);
- return 0;
- }
- return len;
-}
-
/* option-list :== option_name |
option_list COMMA option_name */
}
}
-int parse_option_decl (oc, cfile)
- struct option_cache **oc;
- struct parse *cfile;
-{
- const char *val;
- int token;
- u_int8_t buf [4];
- u_int8_t hunkbuf [1024];
- unsigned hunkix = 0;
- const char *fmt;
- struct option *option;
- struct iaddr ip_addr;
- u_int8_t *dp;
- unsigned len;
- int nul_term = 0;
- struct buffer *bp;
- int known = 0;
-
- option = parse_option_name (cfile, 0, &known);
- if (!option)
- return 0;
-
- /* Parse the option data... */
- do {
- /* Set a flag if this is an array of a simple type (i.e.,
- not an array of pairs of IP addresses, or something
- like that. */
- int uniform = option -> format [1] == 'A';
-
- for (fmt = option -> format; *fmt; fmt++) {
- if (*fmt == 'A')
- break;
- switch (*fmt) {
- case 'E':
- fmt = strchr (fmt, '.');
- if (!fmt) {
- parse_warn (cfile,
- "malformed %s (bug!)",
- "encapsulation format");
- skip_to_semi (cfile);
- return 0;
- }
- case 'X':
- len = parse_X (cfile, &hunkbuf [hunkix],
- sizeof hunkbuf - hunkix);
- hunkix += len;
- break;
-
- case 't': /* Text string... */
- token = next_token (&val, cfile);
- if (token != STRING) {
- parse_warn (cfile,
- "expecting string.");
- skip_to_semi (cfile);
- return 0;
- }
- len = strlen (val);
- if (hunkix + len + 1 > sizeof hunkbuf) {
- parse_warn (cfile,
- "option data buffer %s",
- "overflow");
- skip_to_semi (cfile);
- return 0;
- }
- memcpy (&hunkbuf [hunkix], val, len + 1);
- nul_term = 1;
- hunkix += len;
- break;
-
- case 'I': /* IP address. */
- if (!parse_ip_addr (cfile, &ip_addr))
- return 0;
- len = ip_addr.len;
- dp = ip_addr.iabuf;
-
- alloc:
- if (hunkix + len > sizeof hunkbuf) {
- parse_warn (cfile,
- "option data buffer %s",
- "overflow");
- skip_to_semi (cfile);
- return 0;
- }
- memcpy (&hunkbuf [hunkix], dp, len);
- hunkix += len;
- break;
-
- case 'L': /* Unsigned 32-bit integer... */
- case 'l': /* Signed 32-bit integer... */
- token = next_token (&val, cfile);
- if (token != NUMBER) {
- need_number:
- parse_warn (cfile,
- "expecting number.");
- if (token != SEMI)
- skip_to_semi (cfile);
- return 0;
- }
- convert_num (cfile, buf, val, 0, 32);
- len = 4;
- dp = buf;
- goto alloc;
-
- case 's': /* Signed 16-bit integer. */
- case 'S': /* Unsigned 16-bit integer. */
- token = next_token (&val, cfile);
- if (token != NUMBER)
- goto need_number;
- convert_num (cfile, buf, val, 0, 16);
- len = 2;
- dp = buf;
- goto alloc;
-
- case 'b': /* Signed 8-bit integer. */
- case 'B': /* Unsigned 8-bit integer. */
- token = next_token (&val, cfile);
- if (token != NUMBER)
- goto need_number;
- convert_num (cfile, buf, val, 0, 8);
- len = 1;
- dp = buf;
- goto alloc;
-
- case 'f': /* Boolean flag. */
- token = next_token (&val, cfile);
- if (!is_identifier (token)) {
- parse_warn (cfile,
- "expecting identifier.");
- bad_flag:
- if (token != SEMI)
- skip_to_semi (cfile);
- return 0;
- }
- if (!strcasecmp (val, "true")
- || !strcasecmp (val, "on"))
- buf [0] = 1;
- else if (!strcasecmp (val, "false")
- || !strcasecmp (val, "off"))
- buf [0] = 0;
- else {
- parse_warn (cfile,
- "expecting boolean.");
- goto bad_flag;
- }
- len = 1;
- dp = buf;
- goto alloc;
-
- default:
- log_error ("parse_option_param: Bad format %c",
- *fmt);
- skip_to_semi (cfile);
- return 0;
- }
- }
- token = next_token (&val, cfile);
- } while (*fmt == 'A' && token == COMMA);
-
- if (token != SEMI) {
- parse_warn (cfile, "semicolon expected.");
- skip_to_semi (cfile);
- return 0;
- }
-
- bp = (struct buffer *)0;
- if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
- log_fatal ("no memory to store option declaration.");
- if (!bp -> data)
- log_fatal ("out of memory allocating option data.");
- memcpy (bp -> data, hunkbuf, hunkix + nul_term);
-
- if (!option_cache_allocate (oc, MDL))
- log_fatal ("out of memory allocating option cache.");
-
- (*oc) -> data.buffer = bp;
- (*oc) -> data.data = &bp -> data [0];
- (*oc) -> data.terminated = nul_term;
- (*oc) -> data.len = hunkix;
- (*oc) -> option = option;
- return 1;
-}
-
void parse_string_list (cfile, lp, multiple)
struct parse *cfile;
struct string_list **lp;