2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-31 06:15:55 +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
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 */
#include "dhcpd.h"
@@ -94,6 +94,8 @@ int read_client_conf ()
if (!ip -> client)
error ("no memory for client state.");
memset (ip -> client, 0, sizeof *(ip -> client));
}
if (!ip -> client -> config) {
if (!config) {
config = (struct client_config *)
malloc (sizeof (struct client_config));
@@ -134,7 +136,7 @@ void read_client_leases ()
skip_to_semi (cfile);
break;
} else
parse_client_lease_statement (cfile);
parse_client_lease_statement (cfile, 0);
} while (1);
}
@@ -160,7 +162,7 @@ void parse_client_statement (cfile, ip, config)
int token;
char *val;
char *t, *n;
struct hardware hardware;
u_int8_t buf [1024];
switch (next_token (&val, cfile)) {
case HOSTNAME:
@@ -168,8 +170,14 @@ void parse_client_statement (cfile, ip, config)
return;
case CLIENT_IDENTIFIER:
config -> cid_len = parse_X (cfile,
&config -> client_identifier);
config -> cid_len = parse_X (cfile, buf, sizeof buf);
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;
case HARDWARE:
@@ -216,7 +224,7 @@ void parse_client_statement (cfile, ip, config)
return;
case LEASE:
parse_client_lease_statement (cfile);
parse_client_lease_statement (cfile, 1);
return;
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;
u_int8_t **p;
u_int8_t *buf;
int max;
{
int token;
char *val;
unsigned char buf [1024];
int buflen;
unsigned char *s;
int 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 ("expecting hexadecimal constant.");
skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0;
}
convert_num (&buf [buflen], val, 16, 8);
if (buflen++ > sizeof buf) {
convert_num (&buf [len], val, 16, 8);
if (len++ > max) {
parse_warn ("hexadecimal constant too long.");
skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0;
}
token = peek_token (&val, cfile);
@@ -265,18 +272,19 @@ int parse_X (cfile, p)
val = buf;
} else if (token == STRING) {
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 {
parse_warn ("expecting string or hexadecimal data");
skip_to_semi (cfile);
*p = (u_int8_t *)0;
return 0;
}
*p = malloc (buflen);
if (!*p)
error ("out of memory allocating client id.\n");
memcpy (*p, val, buflen);
return buflen;
return len;
}
/* option-list :== option_name |
@@ -344,38 +352,13 @@ void parse_interface_declaration (cfile, outer_config)
return;
}
/* Find the interface (if any) that matches the name. */
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, val))
break;
}
ip = interface_or_dummy (val);
/* If we didn't find an interface, put up a dummy interface so
that we have some place to parse the bogus data. Otherwise,
allocate a client state and client config structure for the
interface. */
if (!ip) {
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);
if (!ip -> client)
make_client_state (ip);
if (!ip -> client -> config)
make_client_config (ip, outer_config);
token = next_token (&val, cfile);
if (token != LBRACE) {
@@ -397,6 +380,64 @@ void parse_interface_declaration (cfile, outer_config)
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 :==
LEASE RBRACE client-lease-declarations LBRACE
@@ -406,8 +447,9 @@ void parse_interface_declaration (cfile, outer_config)
client-lease-declarations client-lease-declaration */
void parse_client_lease_statement (cfile)
void parse_client_lease_statement (cfile, is_static)
FILE *cfile;
int is_static;
{
struct client_lease *lease, *lp, *pl;
struct interface_info *ip;
@@ -425,6 +467,7 @@ void parse_client_lease_statement (cfile)
if (!lease)
error ("no memory for lease.\n");
memset (lease, 0, sizeof *lease);
lease -> is_static = is_static;
ip = (struct interface_info *)0;
@@ -447,6 +490,10 @@ void parse_client_lease_statement (cfile)
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 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
@@ -523,10 +570,7 @@ void parse_client_lease_declaration (cfile, lease, ipp)
skip_to_semi (cfile);
break;
}
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, val))
break;
}
ip = interface_or_dummy (val);
*ipp = ip;
break;
@@ -588,7 +632,9 @@ void parse_option_decl (cfile, options)
{
char *val;
int token;
unsigned char buf [4];
u_int8_t buf [4];
u_int8_t hunkbuf [1024];
int hunkix = 0;
char *vendor;
char *fmt;
struct universe *universe;
@@ -596,6 +642,7 @@ void parse_option_decl (cfile, options)
struct iaddr ip_addr;
char *dp;
int len;
int nul_term = 0;
token = next_token (&val, cfile);
if (!is_identifier (token)) {
@@ -669,17 +716,28 @@ void parse_option_decl (cfile, options)
break;
switch (*fmt) {
case 'X':
options [option -> code].len =
parse_X (cfile,
(&options
[option -> code].data));
len = parse_X (cfile, &hunkbuf [hunkix],
sizeof hunkbuf - hunkix);
hunkix += len;
break;
case 't': /* Text string... */
options [option -> code].data =
parse_string (cfile);
options [option -> code].len =
strlen (options [option -> code].data);
token = next_token (&val, cfile);
if (token != STRING) {
parse_warn ("expecting string.");
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;
case 'I': /* IP address. */
@@ -688,12 +746,14 @@ void parse_option_decl (cfile, options)
dp = ip_addr.iabuf;
alloc:
options [option -> code].data = malloc (len);
if (!options [option -> code].data)
error ("no memory for option data.");
memcpy (options [option -> code].data,
dp, len);
options [option -> code].len = len;
if (hunkix + len > sizeof hunkbuf) {
parse_warn ("option data buffer %s",
"overflow");
skip_to_semi (cfile);
return;
}
memcpy (&hunkbuf [hunkix], dp, len);
hunkix += len;
break;
case 'L': /* Unsigned 32-bit integer... */
@@ -761,21 +821,18 @@ void parse_option_decl (cfile, options)
return;
}
}
if (*fmt == 'A') {
token = peek_token (&val, cfile);
if (token == COMMA) {
token = next_token (&val, cfile);
continue;
}
break;
}
} while (*fmt == 'A');
token = next_token (&val, cfile);
} while (*fmt == 'A' && token == COMMA);
token = next_token (&val, cfile);
if (token != SEMI) {
parse_warn ("semicolon expected.");
skip_to_semi (cfile);
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;
}