#ifndef lint
static char copyright[] =
-"$Id: confpars.c,v 1.84 1999/09/28 23:55:55 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+"$Id: confpars.c,v 1.85 1999/10/01 03:37:29 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
-#include "dhctoken.h"
static TIME parsed_time;
parameters :== <nil> | parameter | parameters parameter
declarations :== <nil> | declaration | declarations declaration */
-int readconf ()
+isc_result_t readconf ()
{
- FILE *cfile;
+ int file;
+ struct parse *cfile;
char *val;
enum dhcp_token token;
int declaration = 0;
-
- new_parse (path_dhcpd_conf);
+ int status;
/* Set up the initial dhcp option universe. */
initialize_universes ();
root_group.authoritative = 0;
- if ((cfile = fopen (path_dhcpd_conf, "r")) == NULL)
+ if ((file = open (path_dhcpd_conf, O_RDONLY)) < 0)
log_fatal ("Can't open %s: %m", path_dhcpd_conf);
+
+ cfile = (struct parse *)0;
+ new_parse (&cfile, file, (char *)0, 0, path_dhcpd_conf);
+
do {
token = peek_token (&val, cfile);
if (token == EOF)
} while (1);
token = next_token (&val, cfile); /* Clear the peek buffer */
- return !warnings_occurred;
+ status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS;
+
+ end_parse (&cfile);
+ close (file);
+ return status;
}
/* lease-file :== lease-declarations EOF
| lease-declaration
| lease-declarations lease-declaration */
-void read_leases ()
+isc_result_t read_leases ()
{
- FILE *cfile;
+ struct parse *cfile;
+ int file;
char *val;
enum dhcp_token token;
-
- new_parse (path_dhcpd_db);
+ isc_result_t status;
/* Open the lease file. If we can't open it, fail. The reason
for this is that although on initial startup, the absence of
human has corrected the database problem, then we are left
thinking that no leases have been assigned to anybody, which
could create severe network chaos. */
- if ((cfile = fopen (path_dhcpd_db, "r")) == NULL) {
+ if ((file = open (path_dhcpd_db, O_RDONLY)) < 0) {
log_error ("Can't open lease database %s: %m -- %s",
path_dhcpd_db,
"check for failed database rewrite attempt!");
log_fatal ("don't know what to do about this.");
}
+ cfile = (struct parse *)0;
+ new_parse (&cfile, file, (char *)0, 0, path_dhcpd_db);
+
do {
token = next_token (&val, cfile);
if (token == EOF)
(&lease -> on_release,
"read_leases");
} else
- parse_warn ("possibly corrupt lease file");
+ parse_warn (cfile,
+ "possibly corrupt lease file");
} else if (token == HOST) {
parse_host_declaration (cfile, &root_group);
+ } else if (token == GROUP) {
+ parse_group_declaration (cfile, &root_group);
} else {
log_error ("Corrupt lease file - possible data loss!");
skip_to_semi (cfile);
}
} while (1);
+
+ status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS;
+
+ end_parse (&cfile);
+ close (file);
+
+ return status;
}
/* statement :== parameter | declaration
| RANGE address-range-declaration */
int parse_statement (cfile, group, type, host_decl, declaration)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
int type;
struct host_decl *host_decl;
if (type != HOST_DECL && type != CLASS_DECL)
parse_host_declaration (cfile, group);
else {
- parse_warn ("host declarations not allowed here.");
+ parse_warn (cfile,
+ "host declarations not allowed here.");
skip_to_semi (cfile);
}
return 1;
if (type != HOST_DECL && type != CLASS_DECL)
parse_group_declaration (cfile, group);
else {
- parse_warn ("group declarations not allowed here.");
+ parse_warn (cfile,
+ "group declarations not allowed here.");
skip_to_semi (cfile);
}
return 1;
type == HOST_DECL ||
type == SUBNET_DECL ||
type == CLASS_DECL) {
- parse_warn ("shared-network parameters not %s.",
+ parse_warn (cfile, "shared-network parameters not %s.",
"allowed here");
skip_to_semi (cfile);
break;
next_token (&val, cfile);
if (type == HOST_DECL || type == SUBNET_DECL ||
type == CLASS_DECL) {
- parse_warn ("subnet declarations not allowed here.");
+ parse_warn (cfile,
+ "subnet declarations not allowed here.");
skip_to_semi (cfile);
return 1;
}
case VENDOR_CLASS:
next_token (&val, cfile);
if (type == CLASS_DECL) {
- parse_warn ("class declarations not allowed here.");
+ parse_warn (cfile,
+ "class declarations not allowed here.");
skip_to_semi (cfile);
break;
}
case USER_CLASS:
next_token (&val, cfile);
if (type == CLASS_DECL) {
- parse_warn ("class declarations not allowed here.");
+ parse_warn (cfile,
+ "class declarations not allowed here.");
skip_to_semi (cfile);
break;
}
case CLASS:
next_token (&val, cfile);
if (type == CLASS_DECL) {
- parse_warn ("class declarations not allowed here.");
+ parse_warn (cfile,
+ "class declarations not allowed here.");
skip_to_semi (cfile);
break;
}
case SUBCLASS:
next_token (&val, cfile);
if (type == CLASS_DECL) {
- parse_warn ("class declarations not allowed here.");
+ parse_warn (cfile,
+ "class declarations not allowed here.");
skip_to_semi (cfile);
break;
}
if (host_decl)
host_decl -> interface = hardware;
else
- parse_warn ("hardware address parameter %s",
+ parse_warn (cfile, "hardware address parameter %s",
"not allowed here.");
break;
if (host_decl)
host_decl -> fixed_addr = cache;
else {
- parse_warn ("fixed-address parameter not %s",
+ parse_warn (cfile, "fixed-address parameter not %s",
"allowed here.");
option_cache_dereference (&cache, "parse_statement");
}
case POOL:
next_token (&val, cfile);
if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
- parse_warn ("pool declared outside of network");
+ parse_warn (cfile, "pool declared outside of network");
}
if (type == POOL_DECL) {
- parse_warn ("pool declared within pool.");
+ parse_warn (cfile, "pool declared within pool.");
}
parse_pool_statement (cfile, group, type);
return declaration;
case RANGE:
next_token (&val, cfile);
if (type != SUBNET_DECL || !group -> subnet) {
- parse_warn ("range declaration not allowed here.");
+ parse_warn (cfile,
+ "range declaration not allowed here.");
skip_to_semi (cfile);
return declaration;
}
group -> authoritative = 0;
goto authoritative;
default:
- parse_warn ("expecting assertion");
+ parse_warn (cfile, "expecting assertion");
skip_to_semi (cfile);
break;
}
group -> authoritative = 1;
authoritative:
if (type == HOST_DECL)
- parse_warn ("authority makes no sense here.");
+ parse_warn (cfile, "authority makes no sense here.");
parse_semi (cfile);
break;
token = peek_token (&val, cfile);
if (token == SPACE) {
if (type != ROOT_GROUP) {
- parse_warn ("option space definitions %s",
+ parse_warn (cfile,
+ "option space definitions %s",
" may not be scoped.");
skip_to_semi (cfile);
free_option (option, "parse_statement");
token = peek_token (&val, cfile);
if (token == CODE) {
if (type != ROOT_GROUP) {
- parse_warn ("option definitions%s%s",
+ parse_warn (cfile,
+ "option definitions%s%s",
" may not be scoped.");
skip_to_semi (cfile);
free_option (option,
/* If this wasn't an option code definition, don't
allow an unknown option. */
if (option -> code == -1) {
- parse_warn ("unknown option %s.%s",
+ parse_warn (cfile, "unknown option %s.%s",
option -> universe -> name,
option -> name);
skip_to_semi (cfile);
lose = 0;
if (!parse_executable_statement (&et, cfile, &lose)) {
if (!lose) {
- if (declaration)
- parse_warn ("expecting a %s.",
- "declaration");
- else
- parse_warn ("expecting a%s%s.",
- " parameter",
- " or declaration");
+ if (declaration)
+ parse_warn (cfile,
+ "expecting a declaration");
+ else
+ parse_warn (cfile,
+ "expecting a parameter %s"
+ "or declaration");
skip_to_semi (cfile);
}
return declaration;
}
}
if (!et) {
- parse_warn ("expecting a %sdeclaration",
+ parse_warn (cfile, "expecting a %sdeclaration",
declaration ? "" : "parameter or ");
return declaration;
}
}
if (declaration) {
- parse_warn ("parameters not allowed after first declaration.");
+ parse_warn (cfile,
+ "parameters not allowed after first declaration.");
return 1;
}
#if defined (FAILOVER_PROTOCOL)
void parse_failover_peer (cfile, group, type)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
int type;
{
char *name;
if (type != SHARED_NET_DECL && type != ROOT_GROUP) {
- parse_warn ("failover peer statements not in shared-network%s"
+ parse_warn (cfile,
+ "failover peer statements not in shared-network%s"
" declaration or at top level.");
skip_to_semi (cfile);
return;
token = next_token (&val, cfile);
if (token != PEER) {
- parse_warn ("expecting peer keyword");
+ parse_warn (cfile, "expecting peer keyword");
skip_to_semi (cfile);
return;
}
if (!peer -> name)
log_fatal ("no memory for peer name %s", name);
} else {
- parse_warn ("expecting identifier or left brace");
+ parse_warn (cfile, "expecting identifier or left brace");
skip_to_semi (cfile);
return;
}
if (token == SEMI) {
dfree (name, "peer name");
if (type != SHARED_NET_DECL)
- parse_warn ("failover peer reference not %s",
+ parse_warn (cfile, "failover peer reference not %s",
"in shared-network declaration");
else {
if (!peer) {
- parse_warn ("reference to unknown%s%s",
+ parse_warn (cfile, "reference to unknown%s%s",
" failover peer ", name);
return;
}
return;
} else if (token == MY || token == PARTNER) {
if (!peer) {
- parse_warn ("reference to unknown%s%s",
+ parse_warn (cfile, "reference to unknown%s%s",
" failover peer ", name);
return;
}
parse_semi (cfile);
return;
} else if (token != LBRACE) {
- parse_warn ("expecting left brace");
+ parse_warn (cfile, "expecting left brace");
skip_to_semi (cfile);
}
/* Make sure this isn't a redeclaration. */
if (peer) {
- parse_warn ("redeclaration of failover peer %s", name);
+ parse_warn (cfile, "redeclaration of failover peer %s", name);
skip_to_rbrace (cfile, 1);
return;
}
case PORT:
token = next_token (&val, cfile);
if (token != NUMBER) {
- parse_warn ("expecting number");
+ parse_warn (cfile, "expecting number");
skip_to_rbrace (cfile, 1);
}
peer -> port = atoi (val);
parse_idle:
token = next_token (&val, cfile);
if (token != NUMBER) {
- parse_warn ("expecting number.");
+ parse_warn (cfile, "expecting number.");
skip_to_rbrace (cfile, 1);
return;
}
*tp = atoi (val);
default:
- parse_warn ("invalid statement in peer declaration");
+ parse_warn (cfile,
+ "invalid statement in peer declaration");
skip_to_rbrace (cfile, 1);
return;
}
}
enum failover_state parse_failover_state (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
enum dhcp_token token;
char *val;
case RECOVER:
return recover;
default:
- parse_warn ("unknown failover state");
+ parse_warn (cfile, "unknown failover state");
break;
}
return invalid_state;
#endif /* defined (FAILOVER_PROTOCOL) */
void parse_pool_statement (cfile, group, type)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
int type;
{
permit -> type = permit_unknown_clients;
get_clients:
if (next_token (&val, cfile) != CLIENTS) {
- parse_warn ("expecting \"clients\"");
+ parse_warn (cfile,
+ "expecting \"clients\"");
skip_to_semi (cfile);
free_permit (permit,
"parse_pool_statement");
case DYNAMIC:
permit -> type = permit_dynamic_bootp_clients;
if (next_token (&val, cfile) != BOOTP) {
- parse_warn ("expecting \"bootp\"");
+ parse_warn (cfile,
+ "expecting \"bootp\"");
skip_to_semi (cfile);
free_permit (permit,
"parse_pool_statement");
case MEMBERS:
if (next_token (&val, cfile) != OF) {
- parse_warn ("expecting \"of\"");
+ parse_warn (cfile, "expecting \"of\"");
skip_to_semi (cfile);
free_permit (permit,
"parse_pool_statement");
continue;
}
if (next_token (&val, cfile) != STRING) {
- parse_warn ("expecting class name.");
+ parse_warn (cfile,
+ "expecting class name.");
skip_to_semi (cfile);
free_permit (permit,
"parse_pool_statement");
permit -> type = permit_class;
permit -> class = find_class (val);
if (!permit -> class)
- parse_warn ("no such class: %s", val);
+ parse_warn (cfile,
+ "no such class: %s", val);
break;
default:
- parse_warn ("expecting permit type.");
+ parse_warn (cfile, "expecting permit type.");
skip_to_semi (cfile);
break;
}
/* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
int parse_boolean (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
enum dhcp_token token;
char *val;
|| !strcasecmp (val, "off"))
rv = 0;
else {
- parse_warn ("boolean value (true/false/on/off) expected");
+ parse_warn (cfile,
+ "boolean value (true/false/on/off) expected");
skip_to_semi (cfile);
return 0;
}
statement and return zero; otherwise, return 1. */
int parse_lbrace (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
enum dhcp_token token;
char *val;
token = next_token (&val, cfile);
if (token != LBRACE) {
- parse_warn ("expecting left brace.");
+ parse_warn (cfile, "expecting left brace.");
skip_to_semi (cfile);
return 0;
}
/* host-declaration :== hostname RBRACE parameters declarations LBRACE */
void parse_host_declaration (cfile, group)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
{
char *val;
}
if (token == EOF) {
token = next_token (&val, cfile);
- parse_warn ("unexpected end of file");
+ parse_warn (cfile, "unexpected end of file");
break;
}
/* If the host declaration was created by the server,
token = next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != STRING && !is_identifier (token)) {
- parse_warn ("expecting string or identifier.");
+ parse_warn (cfile,
+ "expecting string or identifier.");
skip_to_rbrace (cfile, 1);
break;
}
hash_lookup (group_name_hash,
val, strlen (val)));
if (!go) {
- parse_warn
- ("unknown group %s in host %s",
- val, host -> name);
+ parse_warn (cfile, "unknown group %s in host %s",
+ val, host -> name);
} else {
if (host -> named_group)
omapi_object_dereference
(cfile,
(unsigned char *)0, &len, ':', 16, 8);
if (!t) {
- parse_warn ("expecting hex list.");
+ parse_warn (cfile,
+ "expecting hex list.");
skip_to_semi (cfile);
}
s = (char *)t;
status = enter_host (host, dynamicp, 0);
if (status != ISC_R_SUCCESS)
- parse_warn ("host %s: %s", isc_result_totext (status));
+ parse_warn (cfile,
+ "host %s: %s", isc_result_totext (status));
}
}
*/
struct class *parse_class_declaration (cfile, group, type)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
int type;
{
token = next_token (&val, cfile);
if (token != STRING) {
- parse_warn ("Expecting class name");
+ parse_warn (cfile, "Expecting class name");
skip_to_semi (cfile);
return (struct class *)0;
}
/* If this _is_ a subclass, there _must_ be a class with the
same name. */
if (!pc && (type == 0 || type == 1 || type == 3)) {
- parse_warn ("no class named %s", val);
+ parse_warn (cfile, "no class named %s", val);
skip_to_semi (cfile);
return (struct class *)0;
}
if (!parse_cshl (&data, cfile))
return (struct class *)0;
} else {
- parse_warn ("Expecting string or hex list.");
+ parse_warn (cfile, "Expecting string or hex list.");
return (struct class *)0;
}
}
break;
} else if (token == EOF) {
token = next_token (&val, cfile);
- parse_warn ("unexpected end of file");
+ parse_warn (cfile, "unexpected end of file");
break;
} else if (token == MATCH) {
if (pc) {
- parse_warn ("invalid match in subclass.");
+ parse_warn (cfile,
+ "invalid match in subclass.");
skip_to_semi (cfile);
break;
}
if (class -> expr) {
- parse_warn ("can't override match.");
+ parse_warn (cfile, "can't override match.");
skip_to_semi (cfile);
break;
}
parse_semi (cfile);
} else if (token == SPAWN) {
if (pc) {
- parse_warn ("invalid spawn in subclass.");
+ parse_warn (cfile,
+ "invalid spawn in subclass.");
skip_to_semi (cfile);
break;
}
token = next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != WITH) {
- parse_warn ("expecting with after spawn");
+ parse_warn (cfile,
+ "expecting with after spawn");
skip_to_semi (cfile);
break;
}
class -> spawning = 1;
submatch:
if (class -> submatch) {
- parse_warn ("can't override existing %s.",
+ parse_warn (cfile,
+ "can't override existing %s.",
"submatch/spawn");
skip_to_semi (cfile);
break;
next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != LIMIT) {
- parse_warn ("expecting \"limit\"");
+ parse_warn (cfile, "expecting \"limit\"");
if (token != SEMI)
skip_to_semi (cfile);
break;
}
token = next_token (&val, cfile);
if (token != NUMBER) {
- parse_warn ("expecting a number");
+ parse_warn (cfile, "expecting a number");
if (token != SEMI)
skip_to_semi (cfile);
break;
hostname LBRACE declarations parameters RBRACE */
void parse_shared_net_declaration (cfile, group)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
{
char *val;
token = next_token (&val, cfile);
if (val [0] == 0) {
- parse_warn ("zero-length shared network name");
+ parse_warn (cfile, "zero-length shared network name");
val = "<no-name-given>";
}
name = malloc (strlen (val) + 1);
if (token == RBRACE) {
token = next_token (&val, cfile);
if (!share -> subnets) {
- parse_warn ("empty shared-network decl");
+ parse_warn (cfile,
+ "empty shared-network decl");
return;
}
enter_shared_network (share);
return;
} else if (token == EOF) {
token = next_token (&val, cfile);
- parse_warn ("unexpected end of file");
+ parse_warn (cfile, "unexpected end of file");
break;
}
net NETMASK netmask RBRACE parameters declarations LBRACE */
void parse_subnet_declaration (cfile, share)
- FILE *cfile;
+ struct parse *cfile;
struct shared_network *share;
{
char *val;
token = next_token (&val, cfile);
if (token != NETMASK) {
- parse_warn ("Expecting netmask");
+ parse_warn (cfile, "Expecting netmask");
skip_to_semi (cfile);
return;
}
break;
} else if (token == EOF) {
token = next_token (&val, cfile);
- parse_warn ("unexpected end of file");
+ parse_warn (cfile, "unexpected end of file");
break;
}
declaration = parse_statement (cfile, subnet -> group,
/* group-declaration :== RBRACE parameters declarations LBRACE */
void parse_group_declaration (cfile, group)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
{
char *val;
break;
} else if (token == EOF) {
token = next_token (&val, cfile);
- parse_warn ("unexpected end of file");
+ parse_warn (cfile, "unexpected end of file");
break;
} else if (token == DELETED) {
token = next_token (&val, cfile);
int parse_fixed_addr_param (oc, cfile)
struct option_cache **oc;
- FILE *cfile;
+ struct parse *cfile;
{
char *val;
enum dhcp_token token;
they're not even used there yet). */
TIME parse_timestamp (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
TIME rv;
| DYNAMIC_BOOTP SEMI */
struct lease *parse_lease_declaration (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
char *val;
enum dhcp_token token;
if (token == RBRACE)
break;
else if (token == EOF) {
- parse_warn ("unexpected end of file");
+ parse_warn (cfile, "unexpected end of file");
break;
}
strncpy (tbuf, val, sizeof tbuf);
}
if (lease.uid_len == 0) {
lease.uid = (unsigned char *)0;
- parse_warn ("zero-length uid");
+ parse_warn (cfile,
+ "zero-length uid");
seenbit = 0;
break;
}
if (token == CLASS) {
token = next_token (&val, cfile);
if (token != STRING) {
- parse_warn
- ("expecting string");
- if (token != SEMI)
- skip_to_semi (cfile);
- token = BILLING;
- break;
+ parse_warn (cfile,
+ "expecting string");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ token = BILLING;
+ break;
}
lease.billing_class = find_class (val);
if (!lease.billing_class)
- parse_warn ("unknown class %s",
+ parse_warn (cfile,
+ "unknown class %s",
val);
parse_semi (cfile);
} else if (token == SUBCLASS) {
parse_class_declaration
(cfile, (struct group *)0, 3);
} else {
- parse_warn ("expecting \"class\"");
+ parse_warn (cfile,
+ "expecting \"class\"");
if (token != SEMI)
skip_to_semi (cfile);
}
&& token != BILLING && token != ON) {
token = next_token (&val, cfile);
if (token != SEMI) {
- parse_warn ("semicolon expected.");
+ parse_warn (cfile,
+ "semicolon expected.");
skip_to_semi (cfile);
return (struct lease *)0;
}
}
}
if (seenmask & seenbit) {
- parse_warn ("Too many %s parameters in lease %s\n",
+ parse_warn (cfile,
+ "Too many %s parameters in lease %s\n",
tbuf, piaddr (lease.ip_addr));
} else
seenmask |= seenbit;
| DYNAMIC_BOOTP ip-address ip-address SEMI */
void parse_address_range (cfile, group, type, pool)
- FILE *cfile;
+ struct parse *cfile;
struct group *group;
int type;
struct pool *pool;
token = next_token (&val, cfile);
if (token != SEMI) {
- parse_warn ("semicolon expected.");
+ parse_warn (cfile, "semicolon expected.");
skip_to_semi (cfile);
return;
}
break;
}
if (!subnet) {
- parse_warn ("address range not on network %s",
+ parse_warn (cfile, "address range not on network %s",
group -> shared_network -> name);
log_error ("Be sure to place pool statement after %s",
"related subnet declarations.");