mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-30 05:47:45 +00:00
shared network support; dynamic bootp support; BOOTP sname support; add warning on lease file syntax error; can't warn on duplicate option code anymore
This commit is contained in:
parent
f1c1b29607
commit
1f814ff24f
351
confpars.c
351
confpars.c
@ -98,6 +98,8 @@ void read_leases ()
|
||||
lease = parse_lease_statement (cfile,
|
||||
jref (bc));
|
||||
enter_lease (lease);
|
||||
} else {
|
||||
parse_warn ("possibly corrupt lease file");
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +111,7 @@ void read_leases ()
|
||||
void parse_statement (cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
int token;
|
||||
char *val;
|
||||
jmp_buf bc;
|
||||
|
||||
@ -134,9 +137,40 @@ void parse_statement (cfile)
|
||||
parsed_time = parse_timestamp (cfile, jref (bc));
|
||||
}
|
||||
break;
|
||||
case SHARED_NETWORK:
|
||||
if (!setjmp (bc)) {
|
||||
parse_shared_net_statement (cfile, jref (bc));
|
||||
}
|
||||
break;
|
||||
case SUBNET:
|
||||
if (!setjmp (bc)) {
|
||||
parse_subnet_statement (cfile, jref (bc));
|
||||
struct shared_network *share;
|
||||
struct subnet *subnet;
|
||||
char *t, *n;
|
||||
|
||||
share = new_shared_network ("parse_statement");
|
||||
if (!share)
|
||||
error ("No memory for shared subnet");
|
||||
share -> leases = (struct lease *)0;
|
||||
share -> last_lease = (struct lease *)0;
|
||||
share -> insertion_point = (struct lease *)0;
|
||||
share -> next = (struct shared_network *)0;
|
||||
share -> default_lease_time = default_lease_time;
|
||||
share -> max_lease_time = max_lease_time;
|
||||
memcpy (share -> options,
|
||||
global_options, sizeof global_options);
|
||||
|
||||
subnet = parse_subnet_statement (cfile, jref (bc),
|
||||
share);
|
||||
share -> subnets = subnet;
|
||||
n = piaddr (subnet -> net);
|
||||
t = dmalloc (strlen (n) + 1, "parse_statement");
|
||||
if (!t)
|
||||
error ("no memory for subnet name");
|
||||
strcpy (t, n);
|
||||
share -> name = t;
|
||||
enter_shared_network (share);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
case VENDOR_CLASS:
|
||||
@ -149,11 +183,59 @@ void parse_statement (cfile)
|
||||
parse_class_statement (cfile, jref (bc), 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
if (!setjmp (bc)) {
|
||||
parse_lease_time (cfile, jref (bc),
|
||||
&default_lease_time);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
if (!setjmp (bc)) {
|
||||
parse_lease_time (cfile, jref (bc), &max_lease_time);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION:
|
||||
if (!setjmp (bc)) {
|
||||
parse_option_decl (cfile, jref (bc), global_options);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVER_IDENTIFIER:
|
||||
if (!setjmp (bc)) {
|
||||
struct tree_cache *server_id =
|
||||
tree_cache (parse_ip_addr_or_hostname
|
||||
(cfile, jref (bc), 0));
|
||||
if (!tree_evaluate (server_id))
|
||||
error ("server identifier is not known");
|
||||
if (server_id -> len > 4)
|
||||
warn ("server identifier evaluates to more %s"
|
||||
"than one IP address");
|
||||
server_identifier.len = 4;
|
||||
memcpy (server_identifier.iabuf,
|
||||
server_id -> value, server_identifier.len);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
parse_warn ("expecting a declaration.");
|
||||
skip_to_semi (cfile);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
need_semi:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != SEMI) {
|
||||
parse_warn ("semicolon expected");
|
||||
skip_to_semi (cfile);
|
||||
}
|
||||
}
|
||||
|
||||
void skip_to_semi (cfile)
|
||||
@ -317,13 +399,122 @@ void parse_class_decl (cfile, bc, class)
|
||||
}
|
||||
}
|
||||
|
||||
/* subnet_statement :== SUBNET net NETMASK netmask declarations SEMI
|
||||
/* lease_time :== NUMBER */
|
||||
|
||||
void parse_lease_time (cfile, bc, timep)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
TIME *timep;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
convert_num ((unsigned char *)timep, val, 10, 32);
|
||||
/* Unswap the number - convert_num returns stuff in NBO. */
|
||||
*timep = ntohl (*timep); /* XXX */
|
||||
}
|
||||
|
||||
/* shared_network_statement :== SHARED_NETWORK subnet_statements SEMI
|
||||
subnet_statements :== subnet_statement |
|
||||
subnet_statements subnet_statement */
|
||||
|
||||
void parse_shared_net_statement (cfile, bc)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
struct shared_network *share;
|
||||
struct subnet *first_net = (struct subnet *)0;
|
||||
struct subnet *last_net = (struct subnet *)0;
|
||||
struct subnet *next_net;
|
||||
char *name;
|
||||
|
||||
share = new_shared_network ("parse_shared_net_statement");
|
||||
if (!share)
|
||||
error ("No memory for shared subnet");
|
||||
share -> leases = (struct lease *)0;
|
||||
share -> last_lease = (struct lease *)0;
|
||||
share -> insertion_point = (struct lease *)0;
|
||||
share -> next = (struct shared_network *)0;
|
||||
share -> default_lease_time = default_lease_time;
|
||||
share -> max_lease_time = max_lease_time;
|
||||
memcpy (share -> options, global_options, sizeof global_options);
|
||||
|
||||
/* Get the name of the shared network... */
|
||||
token = next_token (&val, cfile);
|
||||
if (!is_identifier (token) && token != STRING) {
|
||||
skip_to_semi (cfile);
|
||||
parse_warn ("expecting shared network name");
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
if (val [0] == 0) {
|
||||
parse_warn ("zero-length shared network name");
|
||||
val = "<no-name-given>";
|
||||
}
|
||||
name = dmalloc (strlen (val), "parse_shared_net_statement");
|
||||
if (!name)
|
||||
error ("no memory for shared network name");
|
||||
strcpy (name, val);
|
||||
share -> name = name;
|
||||
|
||||
do {
|
||||
token = next_token (&val, cfile);
|
||||
switch (token) {
|
||||
case SEMI:
|
||||
if (!first_net) {
|
||||
parse_warn ("empty shared-network decl");
|
||||
return;
|
||||
}
|
||||
share -> subnets = first_net;
|
||||
enter_shared_network (share);
|
||||
return;
|
||||
|
||||
case SUBNET:
|
||||
next_net = parse_subnet_statement (cfile, bc, share);
|
||||
if (!first_net)
|
||||
first_net = next_net;
|
||||
if (last_net)
|
||||
last_net -> next_sibling = next_net;
|
||||
last_net = next_net;
|
||||
break;
|
||||
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, share -> options);
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&share -> default_lease_time);
|
||||
break;
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&share -> max_lease_time);
|
||||
break;
|
||||
|
||||
default:
|
||||
parse_warn ("expecting subnet declaration");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* subnet_statement :== SUBNET net NETMASK netmask declarations
|
||||
host_declarations :== <nil> | host_declaration
|
||||
| host_declarations host_declaration SEMI */
|
||||
|
||||
struct subnet *parse_subnet_statement (cfile, bc)
|
||||
struct subnet *parse_subnet_statement (cfile, bc, share)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
struct shared_network *share;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
@ -335,11 +526,11 @@ struct subnet *parse_subnet_statement (cfile, bc)
|
||||
subnet = new_subnet ("parse_subnet_statement");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
subnet -> leases = (struct lease *)0;
|
||||
subnet -> last_lease = (struct lease *)0;
|
||||
subnet -> next = (struct subnet *)0;
|
||||
subnet -> default_lease_time = default_lease_time;
|
||||
subnet -> max_lease_time = max_lease_time;
|
||||
subnet -> next_subnet = subnet -> next_sibling = (struct subnet *)0;
|
||||
subnet -> shared_network = share;
|
||||
subnet -> default_lease_time = share -> default_lease_time;
|
||||
subnet -> max_lease_time = share -> max_lease_time;
|
||||
memcpy (subnet -> options, share -> options, sizeof subnet -> options);
|
||||
|
||||
/* Get the network number... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
@ -364,12 +555,15 @@ struct subnet *parse_subnet_statement (cfile, bc)
|
||||
|
||||
do {
|
||||
token = peek_token (&val, cfile);
|
||||
if (token == SEMI) {
|
||||
token = next_token (&val, cfile);
|
||||
if (token == SEMI || token == SUBNET)
|
||||
break;
|
||||
}
|
||||
parse_subnet_decl (cfile, bc, subnet);
|
||||
} while (1);
|
||||
|
||||
/* If this subnet supports dynamic bootp, flag it so in the
|
||||
shared_network containing it. */
|
||||
if (subnet -> dynamic_bootp)
|
||||
share -> dynamic_bootp = 1;
|
||||
return subnet;
|
||||
}
|
||||
|
||||
@ -395,31 +589,13 @@ void parse_subnet_decl (cfile, bc, decl)
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric default lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> default_lease_time,
|
||||
val, 10, 32);
|
||||
/* Unswap the number - convert_num returns stuff in NBO. */
|
||||
decl -> default_lease_time =
|
||||
ntohl (decl -> default_lease_time);
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> default_lease_time);
|
||||
break;
|
||||
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric max lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> max_lease_time,
|
||||
val, 10, 32);
|
||||
/* Unswap the number - convert_num returns stuff in NBO. */
|
||||
decl -> max_lease_time =
|
||||
ntohl (decl -> max_lease_time);
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> max_lease_time);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -431,7 +607,8 @@ void parse_subnet_decl (cfile, bc, decl)
|
||||
}
|
||||
|
||||
/* host_declaration :== hardware_declaration | filename_declaration
|
||||
| fixed_addr_declaration | option_declaration */
|
||||
| fixed_addr_declaration | option_declaration
|
||||
| max_lease_declaration | default_lease_declaration */
|
||||
|
||||
void parse_host_decl (cfile, bc, decl)
|
||||
FILE *cfile;
|
||||
@ -449,12 +626,23 @@ void parse_host_decl (cfile, bc, decl)
|
||||
case FILENAME:
|
||||
decl -> filename = parse_filename_decl (cfile, bc);
|
||||
break;
|
||||
case SERVER_NAME:
|
||||
decl -> server_name = parse_servername_decl (cfile, bc);
|
||||
break;
|
||||
case FIXED_ADDR:
|
||||
parse_fixed_addr_decl (cfile, bc, decl);
|
||||
break;
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, decl -> options);
|
||||
break;
|
||||
case DEFAULT_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> default_lease_time);
|
||||
break;
|
||||
case MAX_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> max_lease_time);
|
||||
break;
|
||||
case CIADDR:
|
||||
decl -> ciaddr =
|
||||
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
|
||||
@ -493,25 +681,10 @@ void parse_hardware_decl (cfile, bc, decl)
|
||||
|
||||
hw = parse_hardware_addr (cfile, bc);
|
||||
|
||||
/* Find space for the new interface... */
|
||||
if (decl -> interfaces) {
|
||||
decl -> interfaces =
|
||||
(struct hardware *)realloc (decl -> interfaces,
|
||||
++decl -> interface_count *
|
||||
sizeof (struct hardware));
|
||||
} else {
|
||||
decl -> interfaces =
|
||||
(struct hardware *)malloc (sizeof (struct hardware));
|
||||
decl -> interface_count = 1;
|
||||
}
|
||||
if (!decl -> interfaces)
|
||||
error ("no memory for hardware interface info.");
|
||||
|
||||
/* Copy out the information... */
|
||||
decl -> interfaces [decl -> interface_count - 1].htype = hw.htype;
|
||||
decl -> interfaces [decl -> interface_count - 1].hlen = hw.hlen;
|
||||
memcpy (decl -> interfaces [decl -> interface_count - 1].haddr,
|
||||
&hw.haddr [0], hw.hlen);
|
||||
decl -> interface.htype = hw.htype;
|
||||
decl -> interface.hlen = hw.hlen;
|
||||
memcpy (decl -> interface.haddr, &hw.haddr [0], hw.hlen);
|
||||
}
|
||||
|
||||
struct hardware parse_hardware_addr (cfile, bc)
|
||||
@ -564,6 +737,29 @@ char *parse_filename_decl (cfile, bc)
|
||||
return s;
|
||||
}
|
||||
|
||||
/* servername_decl :== SERVER_NAME STRING */
|
||||
|
||||
char *parse_servername_decl (cfile, bc)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
char *s;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
if (token != STRING) {
|
||||
parse_warn ("server name must be a string");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
s = (char *)malloc (strlen (val));
|
||||
if (!s)
|
||||
error ("no memory for server name.");
|
||||
strcpy (s, val);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ip_addr_or_hostname :== ip_address | hostname
|
||||
ip_address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
|
||||
|
||||
@ -602,15 +798,33 @@ struct tree *parse_ip_addr_or_hostname (cfile, bc, uniform)
|
||||
}
|
||||
|
||||
|
||||
/* fixed_addr_declaration :== FIXED_ADDR ip_addr_or_hostname */
|
||||
/* fixed_addr_clause :==
|
||||
FIXED_ADDR fixed_addr_decls
|
||||
|
||||
fixed_addr_decls :== ip_addr_or_hostname |
|
||||
fixed_addr_decls ip_addr_or_hostname */
|
||||
|
||||
void parse_fixed_addr_decl (cfile, bc, decl)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
struct host_decl *decl;
|
||||
{
|
||||
decl -> fixed_addr =
|
||||
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
|
||||
char *val;
|
||||
int token;
|
||||
struct tree *tree = (struct tree *)0;
|
||||
struct tree *tmp;
|
||||
|
||||
do {
|
||||
tmp = parse_ip_addr_or_hostname (cfile, bc, 0);
|
||||
if (tree)
|
||||
tree = tree_concat (tree, tmp);
|
||||
else
|
||||
tree = tmp;
|
||||
token = peek_token (&val, cfile);
|
||||
if (token == COMMA)
|
||||
token = next_token (&val, cfile);
|
||||
} while (token == COMMA);
|
||||
decl -> fixed_addr = tree_cache (tree);
|
||||
}
|
||||
|
||||
/* option_declaration :== OPTION identifier DOT identifier <syntax> |
|
||||
@ -790,10 +1004,6 @@ void parse_option_decl (cfile, bc, options)
|
||||
}
|
||||
} while (*fmt == 'A');
|
||||
|
||||
if (options [option -> code]) {
|
||||
parse_warn ("duplicate option code %d (%s).",
|
||||
option -> code, option -> name);
|
||||
}
|
||||
options [option -> code] = tree_cache (tree);
|
||||
}
|
||||
|
||||
@ -829,7 +1039,8 @@ TIME parse_timestamp (cfile, bc)
|
||||
| UID hex_numbers
|
||||
| HOST identifier
|
||||
| CLASS identifier
|
||||
| TIMESTAMP number */
|
||||
| TIMESTAMP number
|
||||
| DYNAMIC_BOOTP */
|
||||
|
||||
struct lease *parse_lease_statement (cfile, bc)
|
||||
FILE *cfile;
|
||||
@ -912,6 +1123,7 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
memcpy (lease.uid, s, lease.uid_len);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case HOST:
|
||||
seenbit = 16;
|
||||
token = next_token (&val, cfile);
|
||||
@ -927,6 +1139,7 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
val,
|
||||
"no longer known.");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CLASS:
|
||||
seenbit = 32;
|
||||
@ -945,6 +1158,11 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
= parse_hardware_addr (cfile, bc);
|
||||
break;
|
||||
|
||||
case DYNAMIC_BOOTP:
|
||||
seenbit = 128;
|
||||
lease.flags |= BOOTP_LEASE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (token != SEMI)
|
||||
skip_to_semi (cfile);
|
||||
@ -960,7 +1178,8 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
return &lease;
|
||||
}
|
||||
|
||||
/* address_range :== RANGE ip_address ip_address */
|
||||
/* address_range :== RANGE ip_address ip_address |
|
||||
RANGE dynamic_bootp_statement ip_address ip_address */
|
||||
|
||||
void parse_address_range (cfile, bc, subnet)
|
||||
FILE *cfile;
|
||||
@ -972,6 +1191,12 @@ void parse_address_range (cfile, bc, subnet)
|
||||
int len = sizeof addr;
|
||||
int token;
|
||||
char *val;
|
||||
int dynamic = 0;
|
||||
|
||||
if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) {
|
||||
token = next_token (&val, cfile);
|
||||
subnet -> dynamic_bootp = dynamic = 1;
|
||||
}
|
||||
|
||||
/* Get the bottom address in the range... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
@ -984,7 +1209,7 @@ void parse_address_range (cfile, bc, subnet)
|
||||
high.len = len;
|
||||
|
||||
/* Create the new address range... */
|
||||
new_address_range (low, high, subnet);
|
||||
new_address_range (low, high, subnet, dynamic);
|
||||
}
|
||||
|
||||
/* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER
|
||||
|
@ -98,6 +98,8 @@ void read_leases ()
|
||||
lease = parse_lease_statement (cfile,
|
||||
jref (bc));
|
||||
enter_lease (lease);
|
||||
} else {
|
||||
parse_warn ("possibly corrupt lease file");
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +111,7 @@ void read_leases ()
|
||||
void parse_statement (cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
int token;
|
||||
char *val;
|
||||
jmp_buf bc;
|
||||
|
||||
@ -134,9 +137,40 @@ void parse_statement (cfile)
|
||||
parsed_time = parse_timestamp (cfile, jref (bc));
|
||||
}
|
||||
break;
|
||||
case SHARED_NETWORK:
|
||||
if (!setjmp (bc)) {
|
||||
parse_shared_net_statement (cfile, jref (bc));
|
||||
}
|
||||
break;
|
||||
case SUBNET:
|
||||
if (!setjmp (bc)) {
|
||||
parse_subnet_statement (cfile, jref (bc));
|
||||
struct shared_network *share;
|
||||
struct subnet *subnet;
|
||||
char *t, *n;
|
||||
|
||||
share = new_shared_network ("parse_statement");
|
||||
if (!share)
|
||||
error ("No memory for shared subnet");
|
||||
share -> leases = (struct lease *)0;
|
||||
share -> last_lease = (struct lease *)0;
|
||||
share -> insertion_point = (struct lease *)0;
|
||||
share -> next = (struct shared_network *)0;
|
||||
share -> default_lease_time = default_lease_time;
|
||||
share -> max_lease_time = max_lease_time;
|
||||
memcpy (share -> options,
|
||||
global_options, sizeof global_options);
|
||||
|
||||
subnet = parse_subnet_statement (cfile, jref (bc),
|
||||
share);
|
||||
share -> subnets = subnet;
|
||||
n = piaddr (subnet -> net);
|
||||
t = dmalloc (strlen (n) + 1, "parse_statement");
|
||||
if (!t)
|
||||
error ("no memory for subnet name");
|
||||
strcpy (t, n);
|
||||
share -> name = t;
|
||||
enter_shared_network (share);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
case VENDOR_CLASS:
|
||||
@ -149,11 +183,59 @@ void parse_statement (cfile)
|
||||
parse_class_statement (cfile, jref (bc), 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
if (!setjmp (bc)) {
|
||||
parse_lease_time (cfile, jref (bc),
|
||||
&default_lease_time);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
if (!setjmp (bc)) {
|
||||
parse_lease_time (cfile, jref (bc), &max_lease_time);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION:
|
||||
if (!setjmp (bc)) {
|
||||
parse_option_decl (cfile, jref (bc), global_options);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVER_IDENTIFIER:
|
||||
if (!setjmp (bc)) {
|
||||
struct tree_cache *server_id =
|
||||
tree_cache (parse_ip_addr_or_hostname
|
||||
(cfile, jref (bc), 0));
|
||||
if (!tree_evaluate (server_id))
|
||||
error ("server identifier is not known");
|
||||
if (server_id -> len > 4)
|
||||
warn ("server identifier evaluates to more %s"
|
||||
"than one IP address");
|
||||
server_identifier.len = 4;
|
||||
memcpy (server_identifier.iabuf,
|
||||
server_id -> value, server_identifier.len);
|
||||
goto need_semi;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
parse_warn ("expecting a declaration.");
|
||||
skip_to_semi (cfile);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
need_semi:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != SEMI) {
|
||||
parse_warn ("semicolon expected");
|
||||
skip_to_semi (cfile);
|
||||
}
|
||||
}
|
||||
|
||||
void skip_to_semi (cfile)
|
||||
@ -317,13 +399,122 @@ void parse_class_decl (cfile, bc, class)
|
||||
}
|
||||
}
|
||||
|
||||
/* subnet_statement :== SUBNET net NETMASK netmask declarations SEMI
|
||||
/* lease_time :== NUMBER */
|
||||
|
||||
void parse_lease_time (cfile, bc, timep)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
TIME *timep;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
convert_num ((unsigned char *)timep, val, 10, 32);
|
||||
/* Unswap the number - convert_num returns stuff in NBO. */
|
||||
*timep = ntohl (*timep); /* XXX */
|
||||
}
|
||||
|
||||
/* shared_network_statement :== SHARED_NETWORK subnet_statements SEMI
|
||||
subnet_statements :== subnet_statement |
|
||||
subnet_statements subnet_statement */
|
||||
|
||||
void parse_shared_net_statement (cfile, bc)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
struct shared_network *share;
|
||||
struct subnet *first_net = (struct subnet *)0;
|
||||
struct subnet *last_net = (struct subnet *)0;
|
||||
struct subnet *next_net;
|
||||
char *name;
|
||||
|
||||
share = new_shared_network ("parse_shared_net_statement");
|
||||
if (!share)
|
||||
error ("No memory for shared subnet");
|
||||
share -> leases = (struct lease *)0;
|
||||
share -> last_lease = (struct lease *)0;
|
||||
share -> insertion_point = (struct lease *)0;
|
||||
share -> next = (struct shared_network *)0;
|
||||
share -> default_lease_time = default_lease_time;
|
||||
share -> max_lease_time = max_lease_time;
|
||||
memcpy (share -> options, global_options, sizeof global_options);
|
||||
|
||||
/* Get the name of the shared network... */
|
||||
token = next_token (&val, cfile);
|
||||
if (!is_identifier (token) && token != STRING) {
|
||||
skip_to_semi (cfile);
|
||||
parse_warn ("expecting shared network name");
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
if (val [0] == 0) {
|
||||
parse_warn ("zero-length shared network name");
|
||||
val = "<no-name-given>";
|
||||
}
|
||||
name = dmalloc (strlen (val), "parse_shared_net_statement");
|
||||
if (!name)
|
||||
error ("no memory for shared network name");
|
||||
strcpy (name, val);
|
||||
share -> name = name;
|
||||
|
||||
do {
|
||||
token = next_token (&val, cfile);
|
||||
switch (token) {
|
||||
case SEMI:
|
||||
if (!first_net) {
|
||||
parse_warn ("empty shared-network decl");
|
||||
return;
|
||||
}
|
||||
share -> subnets = first_net;
|
||||
enter_shared_network (share);
|
||||
return;
|
||||
|
||||
case SUBNET:
|
||||
next_net = parse_subnet_statement (cfile, bc, share);
|
||||
if (!first_net)
|
||||
first_net = next_net;
|
||||
if (last_net)
|
||||
last_net -> next_sibling = next_net;
|
||||
last_net = next_net;
|
||||
break;
|
||||
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, share -> options);
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&share -> default_lease_time);
|
||||
break;
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&share -> max_lease_time);
|
||||
break;
|
||||
|
||||
default:
|
||||
parse_warn ("expecting subnet declaration");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* subnet_statement :== SUBNET net NETMASK netmask declarations
|
||||
host_declarations :== <nil> | host_declaration
|
||||
| host_declarations host_declaration SEMI */
|
||||
|
||||
struct subnet *parse_subnet_statement (cfile, bc)
|
||||
struct subnet *parse_subnet_statement (cfile, bc, share)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
struct shared_network *share;
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
@ -335,11 +526,11 @@ struct subnet *parse_subnet_statement (cfile, bc)
|
||||
subnet = new_subnet ("parse_subnet_statement");
|
||||
if (!subnet)
|
||||
error ("No memory for new subnet");
|
||||
subnet -> leases = (struct lease *)0;
|
||||
subnet -> last_lease = (struct lease *)0;
|
||||
subnet -> next = (struct subnet *)0;
|
||||
subnet -> default_lease_time = default_lease_time;
|
||||
subnet -> max_lease_time = max_lease_time;
|
||||
subnet -> next_subnet = subnet -> next_sibling = (struct subnet *)0;
|
||||
subnet -> shared_network = share;
|
||||
subnet -> default_lease_time = share -> default_lease_time;
|
||||
subnet -> max_lease_time = share -> max_lease_time;
|
||||
memcpy (subnet -> options, share -> options, sizeof subnet -> options);
|
||||
|
||||
/* Get the network number... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
@ -364,12 +555,15 @@ struct subnet *parse_subnet_statement (cfile, bc)
|
||||
|
||||
do {
|
||||
token = peek_token (&val, cfile);
|
||||
if (token == SEMI) {
|
||||
token = next_token (&val, cfile);
|
||||
if (token == SEMI || token == SUBNET)
|
||||
break;
|
||||
}
|
||||
parse_subnet_decl (cfile, bc, subnet);
|
||||
} while (1);
|
||||
|
||||
/* If this subnet supports dynamic bootp, flag it so in the
|
||||
shared_network containing it. */
|
||||
if (subnet -> dynamic_bootp)
|
||||
share -> dynamic_bootp = 1;
|
||||
return subnet;
|
||||
}
|
||||
|
||||
@ -395,31 +589,13 @@ void parse_subnet_decl (cfile, bc, decl)
|
||||
break;
|
||||
|
||||
case DEFAULT_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric default lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> default_lease_time,
|
||||
val, 10, 32);
|
||||
/* Unswap the number - convert_num returns stuff in NBO. */
|
||||
decl -> default_lease_time =
|
||||
ntohl (decl -> default_lease_time);
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> default_lease_time);
|
||||
break;
|
||||
|
||||
|
||||
case MAX_LEASE_TIME:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn ("Expecting numeric max lease time");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
convert_num ((unsigned char *)&decl -> max_lease_time,
|
||||
val, 10, 32);
|
||||
/* Unswap the number - convert_num returns stuff in NBO. */
|
||||
decl -> max_lease_time =
|
||||
ntohl (decl -> max_lease_time);
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> max_lease_time);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -431,7 +607,8 @@ void parse_subnet_decl (cfile, bc, decl)
|
||||
}
|
||||
|
||||
/* host_declaration :== hardware_declaration | filename_declaration
|
||||
| fixed_addr_declaration | option_declaration */
|
||||
| fixed_addr_declaration | option_declaration
|
||||
| max_lease_declaration | default_lease_declaration */
|
||||
|
||||
void parse_host_decl (cfile, bc, decl)
|
||||
FILE *cfile;
|
||||
@ -449,12 +626,23 @@ void parse_host_decl (cfile, bc, decl)
|
||||
case FILENAME:
|
||||
decl -> filename = parse_filename_decl (cfile, bc);
|
||||
break;
|
||||
case SERVER_NAME:
|
||||
decl -> server_name = parse_servername_decl (cfile, bc);
|
||||
break;
|
||||
case FIXED_ADDR:
|
||||
parse_fixed_addr_decl (cfile, bc, decl);
|
||||
break;
|
||||
case OPTION:
|
||||
parse_option_decl (cfile, bc, decl -> options);
|
||||
break;
|
||||
case DEFAULT_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> default_lease_time);
|
||||
break;
|
||||
case MAX_LEASE_TIME:
|
||||
parse_lease_time (cfile, bc,
|
||||
&decl -> max_lease_time);
|
||||
break;
|
||||
case CIADDR:
|
||||
decl -> ciaddr =
|
||||
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
|
||||
@ -493,25 +681,10 @@ void parse_hardware_decl (cfile, bc, decl)
|
||||
|
||||
hw = parse_hardware_addr (cfile, bc);
|
||||
|
||||
/* Find space for the new interface... */
|
||||
if (decl -> interfaces) {
|
||||
decl -> interfaces =
|
||||
(struct hardware *)realloc (decl -> interfaces,
|
||||
++decl -> interface_count *
|
||||
sizeof (struct hardware));
|
||||
} else {
|
||||
decl -> interfaces =
|
||||
(struct hardware *)malloc (sizeof (struct hardware));
|
||||
decl -> interface_count = 1;
|
||||
}
|
||||
if (!decl -> interfaces)
|
||||
error ("no memory for hardware interface info.");
|
||||
|
||||
/* Copy out the information... */
|
||||
decl -> interfaces [decl -> interface_count - 1].htype = hw.htype;
|
||||
decl -> interfaces [decl -> interface_count - 1].hlen = hw.hlen;
|
||||
memcpy (decl -> interfaces [decl -> interface_count - 1].haddr,
|
||||
&hw.haddr [0], hw.hlen);
|
||||
decl -> interface.htype = hw.htype;
|
||||
decl -> interface.hlen = hw.hlen;
|
||||
memcpy (decl -> interface.haddr, &hw.haddr [0], hw.hlen);
|
||||
}
|
||||
|
||||
struct hardware parse_hardware_addr (cfile, bc)
|
||||
@ -564,6 +737,29 @@ char *parse_filename_decl (cfile, bc)
|
||||
return s;
|
||||
}
|
||||
|
||||
/* servername_decl :== SERVER_NAME STRING */
|
||||
|
||||
char *parse_servername_decl (cfile, bc)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
{
|
||||
char *val;
|
||||
int token;
|
||||
char *s;
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
if (token != STRING) {
|
||||
parse_warn ("server name must be a string");
|
||||
skip_to_semi (cfile);
|
||||
longjmp (jdref (bc), 1);
|
||||
}
|
||||
s = (char *)malloc (strlen (val));
|
||||
if (!s)
|
||||
error ("no memory for server name.");
|
||||
strcpy (s, val);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ip_addr_or_hostname :== ip_address | hostname
|
||||
ip_address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
|
||||
|
||||
@ -602,15 +798,33 @@ struct tree *parse_ip_addr_or_hostname (cfile, bc, uniform)
|
||||
}
|
||||
|
||||
|
||||
/* fixed_addr_declaration :== FIXED_ADDR ip_addr_or_hostname */
|
||||
/* fixed_addr_clause :==
|
||||
FIXED_ADDR fixed_addr_decls
|
||||
|
||||
fixed_addr_decls :== ip_addr_or_hostname |
|
||||
fixed_addr_decls ip_addr_or_hostname */
|
||||
|
||||
void parse_fixed_addr_decl (cfile, bc, decl)
|
||||
FILE *cfile;
|
||||
jbp_decl (bc);
|
||||
struct host_decl *decl;
|
||||
{
|
||||
decl -> fixed_addr =
|
||||
tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
|
||||
char *val;
|
||||
int token;
|
||||
struct tree *tree = (struct tree *)0;
|
||||
struct tree *tmp;
|
||||
|
||||
do {
|
||||
tmp = parse_ip_addr_or_hostname (cfile, bc, 0);
|
||||
if (tree)
|
||||
tree = tree_concat (tree, tmp);
|
||||
else
|
||||
tree = tmp;
|
||||
token = peek_token (&val, cfile);
|
||||
if (token == COMMA)
|
||||
token = next_token (&val, cfile);
|
||||
} while (token == COMMA);
|
||||
decl -> fixed_addr = tree_cache (tree);
|
||||
}
|
||||
|
||||
/* option_declaration :== OPTION identifier DOT identifier <syntax> |
|
||||
@ -790,10 +1004,6 @@ void parse_option_decl (cfile, bc, options)
|
||||
}
|
||||
} while (*fmt == 'A');
|
||||
|
||||
if (options [option -> code]) {
|
||||
parse_warn ("duplicate option code %d (%s).",
|
||||
option -> code, option -> name);
|
||||
}
|
||||
options [option -> code] = tree_cache (tree);
|
||||
}
|
||||
|
||||
@ -829,7 +1039,8 @@ TIME parse_timestamp (cfile, bc)
|
||||
| UID hex_numbers
|
||||
| HOST identifier
|
||||
| CLASS identifier
|
||||
| TIMESTAMP number */
|
||||
| TIMESTAMP number
|
||||
| DYNAMIC_BOOTP */
|
||||
|
||||
struct lease *parse_lease_statement (cfile, bc)
|
||||
FILE *cfile;
|
||||
@ -912,6 +1123,7 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
memcpy (lease.uid, s, lease.uid_len);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case HOST:
|
||||
seenbit = 16;
|
||||
token = next_token (&val, cfile);
|
||||
@ -927,6 +1139,7 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
val,
|
||||
"no longer known.");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CLASS:
|
||||
seenbit = 32;
|
||||
@ -945,6 +1158,11 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
= parse_hardware_addr (cfile, bc);
|
||||
break;
|
||||
|
||||
case DYNAMIC_BOOTP:
|
||||
seenbit = 128;
|
||||
lease.flags |= BOOTP_LEASE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (token != SEMI)
|
||||
skip_to_semi (cfile);
|
||||
@ -960,7 +1178,8 @@ struct lease *parse_lease_statement (cfile, bc)
|
||||
return &lease;
|
||||
}
|
||||
|
||||
/* address_range :== RANGE ip_address ip_address */
|
||||
/* address_range :== RANGE ip_address ip_address |
|
||||
RANGE dynamic_bootp_statement ip_address ip_address */
|
||||
|
||||
void parse_address_range (cfile, bc, subnet)
|
||||
FILE *cfile;
|
||||
@ -972,6 +1191,12 @@ void parse_address_range (cfile, bc, subnet)
|
||||
int len = sizeof addr;
|
||||
int token;
|
||||
char *val;
|
||||
int dynamic = 0;
|
||||
|
||||
if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) {
|
||||
token = next_token (&val, cfile);
|
||||
subnet -> dynamic_bootp = dynamic = 1;
|
||||
}
|
||||
|
||||
/* Get the bottom address in the range... */
|
||||
parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
|
||||
@ -984,7 +1209,7 @@ void parse_address_range (cfile, bc, subnet)
|
||||
high.len = len;
|
||||
|
||||
/* Create the new address range... */
|
||||
new_address_range (low, high, subnet);
|
||||
new_address_range (low, high, subnet, dynamic);
|
||||
}
|
||||
|
||||
/* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER
|
||||
|
Loading…
x
Reference in New Issue
Block a user