2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-01 14:55:30 +00:00

Parse arrays correctly; modify parse_X behaviour to facilitate this

This commit is contained in:
Ted Lemon
1997-02-19 10:53:16 +00:00
parent 41fb155b61
commit bf70e81904
2 changed files with 282 additions and 168 deletions

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: clparse.c,v 1.1 1997/02/18 14:27:53 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: clparse.c,v 1.2 1997/02/19 10:53:16 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -94,6 +94,8 @@ int read_client_conf ()
if (!ip -> client) if (!ip -> client)
error ("no memory for client state."); error ("no memory for client state.");
memset (ip -> client, 0, sizeof *(ip -> client)); memset (ip -> client, 0, sizeof *(ip -> client));
}
if (!ip -> client -> config) {
if (!config) { if (!config) {
config = (struct client_config *) config = (struct client_config *)
malloc (sizeof (struct client_config)); malloc (sizeof (struct client_config));
@@ -134,7 +136,7 @@ void read_client_leases ()
skip_to_semi (cfile); skip_to_semi (cfile);
break; break;
} else } else
parse_client_lease_statement (cfile); parse_client_lease_statement (cfile, 0);
} while (1); } while (1);
} }
@@ -160,7 +162,7 @@ void parse_client_statement (cfile, ip, config)
int token; int token;
char *val; char *val;
char *t, *n; char *t, *n;
struct hardware hardware; u_int8_t buf [1024];
switch (next_token (&val, cfile)) { switch (next_token (&val, cfile)) {
case HOSTNAME: case HOSTNAME:
@@ -168,8 +170,14 @@ void parse_client_statement (cfile, ip, config)
return; return;
case CLIENT_IDENTIFIER: case CLIENT_IDENTIFIER:
config -> cid_len = parse_X (cfile, config -> cid_len = parse_X (cfile, buf, sizeof buf);
&config -> client_identifier); if (config -> cid_len == 0)
break;
config -> client_identifier = malloc (config -> cid_len + 1);
if (!config -> client_identifier)
error ("no memory for client identifier.");
memcpy (config -> client_identifier, buf, config -> cid_len);
config -> client_identifier [config -> cid_len] = 0;
break; break;
case HARDWARE: case HARDWARE:
@@ -216,7 +224,7 @@ void parse_client_statement (cfile, ip, config)
return; return;
case LEASE: case LEASE:
parse_client_lease_statement (cfile); parse_client_lease_statement (cfile, 1);
return; return;
default: default:
@@ -231,31 +239,30 @@ void parse_client_statement (cfile, ip, config)
} }
} }
int parse_X (cfile, p) int parse_X (cfile, buf, max)
FILE *cfile; FILE *cfile;
u_int8_t **p; u_int8_t *buf;
int max;
{ {
int token; int token;
char *val; char *val;
unsigned char buf [1024]; int len;
int buflen; u_int8_t *s;
unsigned char *s;
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
if (token == NUMBER_OR_NAME || token == NUMBER) { if (token == NUMBER_OR_NAME || token == NUMBER) {
len = 0;
do { do {
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != NUMBER && token != NUMBER_OR_NAME) { if (token != NUMBER && token != NUMBER_OR_NAME) {
parse_warn ("expecting hexadecimal constant."); parse_warn ("expecting hexadecimal constant.");
skip_to_semi (cfile); skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0; return 0;
} }
convert_num (&buf [buflen], val, 16, 8); convert_num (&buf [len], val, 16, 8);
if (buflen++ > sizeof buf) { if (len++ > max) {
parse_warn ("hexadecimal constant too long."); parse_warn ("hexadecimal constant too long.");
skip_to_semi (cfile); skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0; return 0;
} }
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
@@ -265,18 +272,19 @@ int parse_X (cfile, p)
val = buf; val = buf;
} else if (token == STRING) { } else if (token == STRING) {
token = next_token (&val, cfile); token = next_token (&val, cfile);
buflen = strlen (val) + 1; len = strlen (val);
if (len + 1 > max) {
parse_warn ("string constant too long.");
skip_to_semi (cfile);
return 0;
}
memcpy (buf, val, len + 1);
} else { } else {
parse_warn ("expecting string or hexadecimal data"); parse_warn ("expecting string or hexadecimal data");
skip_to_semi (cfile); skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0; return 0;
} }
*p = malloc (buflen); return len;
if (!*p)
error ("out of memory allocating client id.\n");
memcpy (*p, val, buflen);
return buflen;
} }
/* option-list :== option_name | /* option-list :== option_name |
@@ -344,38 +352,13 @@ void parse_interface_declaration (cfile, outer_config)
return; return;
} }
/* Find the interface (if any) that matches the name. */ ip = interface_or_dummy (val);
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, val))
break;
}
/* If we didn't find an interface, put up a dummy interface so if (!ip -> client)
that we have some place to parse the bogus data. Otherwise, make_client_state (ip);
allocate a client state and client config structure for the
interface. */ if (!ip -> client -> config)
if (!ip) { make_client_config (ip, outer_config);
parse_warn ("interface %s not found.", val);
ip = &dummy_interface;
memset (ip, 0, sizeof dummy_interface);
ip -> client = &dummy_state;
memset (ip -> client, 0, sizeof dummy_state);
ip -> client -> config = &dummy_config;
} else {
ip -> client = ((struct client_state *)
malloc (sizeof (struct client_state)));
if (!ip -> client)
error ("no memory for state for %s\n", val);
memset (ip -> client, 0, sizeof *(ip -> client));
ip -> client -> config =
((struct client_config *)
malloc (sizeof (struct client_config)));
if (!ip -> client -> config)
error ("no memory for config for %s\n", val);
memset (ip -> client -> config, 0,
sizeof *(ip -> client -> config));
}
memcpy (ip -> client -> config, outer_config, sizeof *outer_config);
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != LBRACE) { if (token != LBRACE) {
@@ -397,6 +380,64 @@ void parse_interface_declaration (cfile, outer_config)
token = next_token (&val, cfile); token = next_token (&val, cfile);
} }
struct interface_info *interface_or_dummy (name)
char *name;
{
struct interface_info *ip;
/* Find the interface (if any) that matches the name. */
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name))
break;
}
/* If it's not a real interface, see if it's on the dummy list. */
if (!ip) {
for (ip = dummy_interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name))
break;
}
}
/* If we didn't find an interface, make a dummy interface as
a placeholder. */
if (!ip) {
ip = ((struct interface_info *)malloc (sizeof *ip));
if (!ip)
error ("Insufficient memory to record interface %s",
name);
memset (ip, 0, sizeof *ip);
strcpy (ip -> name, name);
ip -> next = dummy_interfaces;
dummy_interfaces = ip;
}
return ip;
}
void make_client_state (ip)
struct interface_info *ip;
{
ip -> client =
((struct client_state *)malloc (sizeof *(ip -> client)));
if (!ip -> client)
error ("no memory for state on %s\n", ip -> name);
memset (ip -> client, 0, sizeof *(ip -> client));
}
void make_client_config (ip, config)
struct interface_info *ip;
struct client_config *config;
{
ip -> client -> config =
((struct client_config *)
malloc (sizeof (struct client_config)));
if (!ip -> client -> config)
error ("no memory for config for %s\n", ip -> name);
memset (ip -> client -> config, 0,
sizeof *(ip -> client -> config));
memcpy (ip -> client -> config, config, sizeof *config);
}
/* client-lease-statement :== /* client-lease-statement :==
LEASE RBRACE client-lease-declarations LBRACE LEASE RBRACE client-lease-declarations LBRACE
@@ -406,8 +447,9 @@ void parse_interface_declaration (cfile, outer_config)
client-lease-declarations client-lease-declaration */ client-lease-declarations client-lease-declaration */
void parse_client_lease_statement (cfile) void parse_client_lease_statement (cfile, is_static)
FILE *cfile; FILE *cfile;
int is_static;
{ {
struct client_lease *lease, *lp, *pl; struct client_lease *lease, *lp, *pl;
struct interface_info *ip; struct interface_info *ip;
@@ -425,6 +467,7 @@ void parse_client_lease_statement (cfile)
if (!lease) if (!lease)
error ("no memory for lease.\n"); error ("no memory for lease.\n");
memset (lease, 0, sizeof *lease); memset (lease, 0, sizeof *lease);
lease -> is_static = is_static;
ip = (struct interface_info *)0; ip = (struct interface_info *)0;
@@ -447,6 +490,10 @@ void parse_client_lease_statement (cfile)
return; return;
} }
/* Make sure there's a client state structure... */
if (!ip -> client)
make_client_state (ip);
/* The last lease in the lease file on a particular interface is /* The last lease in the lease file on a particular interface is
the active lease for that interface. Of course, we don't know the active lease for that interface. Of course, we don't know
what the last lease in the file is until we've parsed the whole what the last lease in the file is until we've parsed the whole
@@ -523,10 +570,7 @@ void parse_client_lease_declaration (cfile, lease, ipp)
skip_to_semi (cfile); skip_to_semi (cfile);
break; break;
} }
for (ip = interfaces; ip; ip = ip -> next) { ip = interface_or_dummy (val);
if (!strcmp (ip -> name, val))
break;
}
*ipp = ip; *ipp = ip;
break; break;
@@ -588,7 +632,9 @@ void parse_option_decl (cfile, options)
{ {
char *val; char *val;
int token; int token;
unsigned char buf [4]; u_int8_t buf [4];
u_int8_t hunkbuf [1024];
int hunkix = 0;
char *vendor; char *vendor;
char *fmt; char *fmt;
struct universe *universe; struct universe *universe;
@@ -596,6 +642,7 @@ void parse_option_decl (cfile, options)
struct iaddr ip_addr; struct iaddr ip_addr;
char *dp; char *dp;
int len; int len;
int nul_term = 0;
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (!is_identifier (token)) { if (!is_identifier (token)) {
@@ -669,17 +716,28 @@ void parse_option_decl (cfile, options)
break; break;
switch (*fmt) { switch (*fmt) {
case 'X': case 'X':
options [option -> code].len = len = parse_X (cfile, &hunkbuf [hunkix],
parse_X (cfile, sizeof hunkbuf - hunkix);
(&options hunkix += len;
[option -> code].data));
break; break;
case 't': /* Text string... */ case 't': /* Text string... */
options [option -> code].data = token = next_token (&val, cfile);
parse_string (cfile); if (token != STRING) {
options [option -> code].len = parse_warn ("expecting string.");
strlen (options [option -> code].data); skip_to_semi (cfile);
return;
}
len = strlen (val);
if (hunkix + len + 1 > sizeof hunkbuf) {
parse_warn ("option data buffer %s",
"overflow");
skip_to_semi (cfile);
return;
}
memcpy (&hunkbuf [hunkix], val, len + 1);
nul_term = 1;
hunkix += len;
break; break;
case 'I': /* IP address. */ case 'I': /* IP address. */
@@ -688,12 +746,14 @@ void parse_option_decl (cfile, options)
dp = ip_addr.iabuf; dp = ip_addr.iabuf;
alloc: alloc:
options [option -> code].data = malloc (len); if (hunkix + len > sizeof hunkbuf) {
if (!options [option -> code].data) parse_warn ("option data buffer %s",
error ("no memory for option data."); "overflow");
memcpy (options [option -> code].data, skip_to_semi (cfile);
dp, len); return;
options [option -> code].len = len; }
memcpy (&hunkbuf [hunkix], dp, len);
hunkix += len;
break; break;
case 'L': /* Unsigned 32-bit integer... */ case 'L': /* Unsigned 32-bit integer... */
@@ -761,21 +821,18 @@ void parse_option_decl (cfile, options)
return; return;
} }
} }
if (*fmt == 'A') { token = next_token (&val, cfile);
token = peek_token (&val, cfile); } while (*fmt == 'A' && token == COMMA);
if (token == COMMA) {
token = next_token (&val, cfile);
continue;
}
break;
}
} while (*fmt == 'A');
token = next_token (&val, cfile);
if (token != SEMI) { if (token != SEMI) {
parse_warn ("semicolon expected."); parse_warn ("semicolon expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
return; return;
} }
}
options [option -> code].data = malloc (hunkix + nul_term);
if (!options [option -> code].data)
error ("out of memory allocating option data.");
memcpy (options [option -> code].data, hunkbuf, hunkix + nul_term);
options [option -> code].len = hunkix;
}

225
clparse.c
View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: clparse.c,v 1.1 1997/02/18 14:27:53 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: clparse.c,v 1.2 1997/02/19 10:53:16 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -94,6 +94,8 @@ int read_client_conf ()
if (!ip -> client) if (!ip -> client)
error ("no memory for client state."); error ("no memory for client state.");
memset (ip -> client, 0, sizeof *(ip -> client)); memset (ip -> client, 0, sizeof *(ip -> client));
}
if (!ip -> client -> config) {
if (!config) { if (!config) {
config = (struct client_config *) config = (struct client_config *)
malloc (sizeof (struct client_config)); malloc (sizeof (struct client_config));
@@ -134,7 +136,7 @@ void read_client_leases ()
skip_to_semi (cfile); skip_to_semi (cfile);
break; break;
} else } else
parse_client_lease_statement (cfile); parse_client_lease_statement (cfile, 0);
} while (1); } while (1);
} }
@@ -160,7 +162,7 @@ void parse_client_statement (cfile, ip, config)
int token; int token;
char *val; char *val;
char *t, *n; char *t, *n;
struct hardware hardware; u_int8_t buf [1024];
switch (next_token (&val, cfile)) { switch (next_token (&val, cfile)) {
case HOSTNAME: case HOSTNAME:
@@ -168,8 +170,14 @@ void parse_client_statement (cfile, ip, config)
return; return;
case CLIENT_IDENTIFIER: case CLIENT_IDENTIFIER:
config -> cid_len = parse_X (cfile, config -> cid_len = parse_X (cfile, buf, sizeof buf);
&config -> client_identifier); if (config -> cid_len == 0)
break;
config -> client_identifier = malloc (config -> cid_len + 1);
if (!config -> client_identifier)
error ("no memory for client identifier.");
memcpy (config -> client_identifier, buf, config -> cid_len);
config -> client_identifier [config -> cid_len] = 0;
break; break;
case HARDWARE: case HARDWARE:
@@ -216,7 +224,7 @@ void parse_client_statement (cfile, ip, config)
return; return;
case LEASE: case LEASE:
parse_client_lease_statement (cfile); parse_client_lease_statement (cfile, 1);
return; return;
default: default:
@@ -231,31 +239,30 @@ void parse_client_statement (cfile, ip, config)
} }
} }
int parse_X (cfile, p) int parse_X (cfile, buf, max)
FILE *cfile; FILE *cfile;
u_int8_t **p; u_int8_t *buf;
int max;
{ {
int token; int token;
char *val; char *val;
unsigned char buf [1024]; int len;
int buflen; u_int8_t *s;
unsigned char *s;
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
if (token == NUMBER_OR_NAME || token == NUMBER) { if (token == NUMBER_OR_NAME || token == NUMBER) {
len = 0;
do { do {
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != NUMBER && token != NUMBER_OR_NAME) { if (token != NUMBER && token != NUMBER_OR_NAME) {
parse_warn ("expecting hexadecimal constant."); parse_warn ("expecting hexadecimal constant.");
skip_to_semi (cfile); skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0; return 0;
} }
convert_num (&buf [buflen], val, 16, 8); convert_num (&buf [len], val, 16, 8);
if (buflen++ > sizeof buf) { if (len++ > max) {
parse_warn ("hexadecimal constant too long."); parse_warn ("hexadecimal constant too long.");
skip_to_semi (cfile); skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0; return 0;
} }
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
@@ -265,18 +272,19 @@ int parse_X (cfile, p)
val = buf; val = buf;
} else if (token == STRING) { } else if (token == STRING) {
token = next_token (&val, cfile); token = next_token (&val, cfile);
buflen = strlen (val) + 1; len = strlen (val);
if (len + 1 > max) {
parse_warn ("string constant too long.");
skip_to_semi (cfile);
return 0;
}
memcpy (buf, val, len + 1);
} else { } else {
parse_warn ("expecting string or hexadecimal data"); parse_warn ("expecting string or hexadecimal data");
skip_to_semi (cfile); skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0; return 0;
} }
*p = malloc (buflen); return len;
if (!*p)
error ("out of memory allocating client id.\n");
memcpy (*p, val, buflen);
return buflen;
} }
/* option-list :== option_name | /* option-list :== option_name |
@@ -344,38 +352,13 @@ void parse_interface_declaration (cfile, outer_config)
return; return;
} }
/* Find the interface (if any) that matches the name. */ ip = interface_or_dummy (val);
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, val))
break;
}
/* If we didn't find an interface, put up a dummy interface so if (!ip -> client)
that we have some place to parse the bogus data. Otherwise, make_client_state (ip);
allocate a client state and client config structure for the
interface. */ if (!ip -> client -> config)
if (!ip) { make_client_config (ip, outer_config);
parse_warn ("interface %s not found.", val);
ip = &dummy_interface;
memset (ip, 0, sizeof dummy_interface);
ip -> client = &dummy_state;
memset (ip -> client, 0, sizeof dummy_state);
ip -> client -> config = &dummy_config;
} else {
ip -> client = ((struct client_state *)
malloc (sizeof (struct client_state)));
if (!ip -> client)
error ("no memory for state for %s\n", val);
memset (ip -> client, 0, sizeof *(ip -> client));
ip -> client -> config =
((struct client_config *)
malloc (sizeof (struct client_config)));
if (!ip -> client -> config)
error ("no memory for config for %s\n", val);
memset (ip -> client -> config, 0,
sizeof *(ip -> client -> config));
}
memcpy (ip -> client -> config, outer_config, sizeof *outer_config);
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != LBRACE) { if (token != LBRACE) {
@@ -397,6 +380,64 @@ void parse_interface_declaration (cfile, outer_config)
token = next_token (&val, cfile); token = next_token (&val, cfile);
} }
struct interface_info *interface_or_dummy (name)
char *name;
{
struct interface_info *ip;
/* Find the interface (if any) that matches the name. */
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name))
break;
}
/* If it's not a real interface, see if it's on the dummy list. */
if (!ip) {
for (ip = dummy_interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name))
break;
}
}
/* If we didn't find an interface, make a dummy interface as
a placeholder. */
if (!ip) {
ip = ((struct interface_info *)malloc (sizeof *ip));
if (!ip)
error ("Insufficient memory to record interface %s",
name);
memset (ip, 0, sizeof *ip);
strcpy (ip -> name, name);
ip -> next = dummy_interfaces;
dummy_interfaces = ip;
}
return ip;
}
void make_client_state (ip)
struct interface_info *ip;
{
ip -> client =
((struct client_state *)malloc (sizeof *(ip -> client)));
if (!ip -> client)
error ("no memory for state on %s\n", ip -> name);
memset (ip -> client, 0, sizeof *(ip -> client));
}
void make_client_config (ip, config)
struct interface_info *ip;
struct client_config *config;
{
ip -> client -> config =
((struct client_config *)
malloc (sizeof (struct client_config)));
if (!ip -> client -> config)
error ("no memory for config for %s\n", ip -> name);
memset (ip -> client -> config, 0,
sizeof *(ip -> client -> config));
memcpy (ip -> client -> config, config, sizeof *config);
}
/* client-lease-statement :== /* client-lease-statement :==
LEASE RBRACE client-lease-declarations LBRACE LEASE RBRACE client-lease-declarations LBRACE
@@ -406,8 +447,9 @@ void parse_interface_declaration (cfile, outer_config)
client-lease-declarations client-lease-declaration */ client-lease-declarations client-lease-declaration */
void parse_client_lease_statement (cfile) void parse_client_lease_statement (cfile, is_static)
FILE *cfile; FILE *cfile;
int is_static;
{ {
struct client_lease *lease, *lp, *pl; struct client_lease *lease, *lp, *pl;
struct interface_info *ip; struct interface_info *ip;
@@ -425,6 +467,7 @@ void parse_client_lease_statement (cfile)
if (!lease) if (!lease)
error ("no memory for lease.\n"); error ("no memory for lease.\n");
memset (lease, 0, sizeof *lease); memset (lease, 0, sizeof *lease);
lease -> is_static = is_static;
ip = (struct interface_info *)0; ip = (struct interface_info *)0;
@@ -447,6 +490,10 @@ void parse_client_lease_statement (cfile)
return; return;
} }
/* Make sure there's a client state structure... */
if (!ip -> client)
make_client_state (ip);
/* The last lease in the lease file on a particular interface is /* The last lease in the lease file on a particular interface is
the active lease for that interface. Of course, we don't know the active lease for that interface. Of course, we don't know
what the last lease in the file is until we've parsed the whole what the last lease in the file is until we've parsed the whole
@@ -523,10 +570,7 @@ void parse_client_lease_declaration (cfile, lease, ipp)
skip_to_semi (cfile); skip_to_semi (cfile);
break; break;
} }
for (ip = interfaces; ip; ip = ip -> next) { ip = interface_or_dummy (val);
if (!strcmp (ip -> name, val))
break;
}
*ipp = ip; *ipp = ip;
break; break;
@@ -588,7 +632,9 @@ void parse_option_decl (cfile, options)
{ {
char *val; char *val;
int token; int token;
unsigned char buf [4]; u_int8_t buf [4];
u_int8_t hunkbuf [1024];
int hunkix = 0;
char *vendor; char *vendor;
char *fmt; char *fmt;
struct universe *universe; struct universe *universe;
@@ -596,6 +642,7 @@ void parse_option_decl (cfile, options)
struct iaddr ip_addr; struct iaddr ip_addr;
char *dp; char *dp;
int len; int len;
int nul_term = 0;
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (!is_identifier (token)) { if (!is_identifier (token)) {
@@ -669,17 +716,28 @@ void parse_option_decl (cfile, options)
break; break;
switch (*fmt) { switch (*fmt) {
case 'X': case 'X':
options [option -> code].len = len = parse_X (cfile, &hunkbuf [hunkix],
parse_X (cfile, sizeof hunkbuf - hunkix);
(&options hunkix += len;
[option -> code].data));
break; break;
case 't': /* Text string... */ case 't': /* Text string... */
options [option -> code].data = token = next_token (&val, cfile);
parse_string (cfile); if (token != STRING) {
options [option -> code].len = parse_warn ("expecting string.");
strlen (options [option -> code].data); skip_to_semi (cfile);
return;
}
len = strlen (val);
if (hunkix + len + 1 > sizeof hunkbuf) {
parse_warn ("option data buffer %s",
"overflow");
skip_to_semi (cfile);
return;
}
memcpy (&hunkbuf [hunkix], val, len + 1);
nul_term = 1;
hunkix += len;
break; break;
case 'I': /* IP address. */ case 'I': /* IP address. */
@@ -688,12 +746,14 @@ void parse_option_decl (cfile, options)
dp = ip_addr.iabuf; dp = ip_addr.iabuf;
alloc: alloc:
options [option -> code].data = malloc (len); if (hunkix + len > sizeof hunkbuf) {
if (!options [option -> code].data) parse_warn ("option data buffer %s",
error ("no memory for option data."); "overflow");
memcpy (options [option -> code].data, skip_to_semi (cfile);
dp, len); return;
options [option -> code].len = len; }
memcpy (&hunkbuf [hunkix], dp, len);
hunkix += len;
break; break;
case 'L': /* Unsigned 32-bit integer... */ case 'L': /* Unsigned 32-bit integer... */
@@ -761,21 +821,18 @@ void parse_option_decl (cfile, options)
return; return;
} }
} }
if (*fmt == 'A') { token = next_token (&val, cfile);
token = peek_token (&val, cfile); } while (*fmt == 'A' && token == COMMA);
if (token == COMMA) {
token = next_token (&val, cfile);
continue;
}
break;
}
} while (*fmt == 'A');
token = next_token (&val, cfile);
if (token != SEMI) { if (token != SEMI) {
parse_warn ("semicolon expected."); parse_warn ("semicolon expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
return; return;
} }
}
options [option -> code].data = malloc (hunkix + nul_term);
if (!options [option -> code].data)
error ("out of memory allocating option data.");
memcpy (options [option -> code].data, hunkbuf, hunkix + nul_term);
options [option -> code].len = hunkix;
}