confpars.c
来自「open source dhcp server client etc...」· C语言 代码 · 共 2,454 行 · 第 1/5 页
C
2,454 行
/* confpars.c Parser for dhcpd config file... *//* * Copyright (c) 1995-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of The Internet Software Consortium nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This software has been written for the Internet Software Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about the Internet Software Consortium, see * ``http://www.isc.org/''. To learn more about Vixie Enterprises, * see ``http://www.vix.com''. To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#ifndef lintstatic char copyright[] ="$Id: confpars.c,v 1.143.2.8 2001/10/04 22:08:35 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"static TIME parsed_time;#if defined (TRACING)trace_type_t *trace_readconf_type;trace_type_t *trace_readleases_type;void parse_trace_setup (){ trace_readconf_type = trace_type_register ("readconf", (void *)0, trace_conf_input, trace_conf_stop, MDL); trace_readleases_type = trace_type_register ("readleases", (void *)0, trace_conf_input, trace_conf_stop, MDL);}#endif/* conf-file :== parameters declarations END_OF_FILE parameters :== <nil> | parameter | parameters parameter declarations :== <nil> | declaration | declarations declaration */isc_result_t readconf (){ return read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);}isc_result_t read_conf_file (const char *filename, struct group *group, int group_type, int leasep){ int file; struct parse *cfile; isc_result_t status;#if defined (TRACING) char *fbuf, *dbuf; off_t flen; int result; unsigned tflen, ulen; trace_type_t *ttype; if (leasep) ttype = trace_readleases_type; else ttype = trace_readconf_type; /* If we're in playback, we need to snarf the contents of the named file out of the playback file rather than trying to open and read it. */ if (trace_playback ()) { dbuf = (char *)0; tflen = 0; status = trace_get_file (ttype, filename, &tflen, &dbuf); if (status != ISC_R_SUCCESS) return status; ulen = tflen; /* What we get back is filename\0contents, where contents is terminated just by the length. So we figure out the length of the filename, and subtract that and the NUL from the total length to get the length of the contents of the file. We make fbuf a pointer to the contents of the file, and leave dbuf as it is so we can free it later. */ tflen = strlen (dbuf); ulen = ulen - tflen - 1; fbuf = dbuf + tflen + 1; goto memfile; }#endif if ((file = open (filename, O_RDONLY)) < 0) { if (leasep) { log_error ("Can't open lease database %s: %m --", path_dhcpd_db); log_error (" check for failed database %s!", "rewrite attempt"); log_error ("Please read the dhcpd.leases manual%s", " page if you"); log_fatal ("don't know what to do about this."); } else { log_fatal ("Can't open %s: %m", filename); } } cfile = (struct parse *)0;#if defined (TRACING) flen = lseek (file, (off_t)0, SEEK_END); if (flen < 0) { boom: log_fatal ("Can't lseek on %s: %m", filename); } if (lseek (file, (off_t)0, SEEK_SET) < 0) goto boom; /* Can't handle files greater than 2^31-1. */ if (flen > 0x7FFFFFFFUL) log_fatal ("%s: file is too long to buffer.", filename); ulen = flen; /* Allocate a buffer that will be what's written to the tracefile, and also will be what we parse from. */ tflen = strlen (filename); dbuf = dmalloc (ulen + tflen + 1, MDL); if (!dbuf) log_fatal ("No memory for %s (%d bytes)", filename, ulen); /* Copy the name into the beginning, nul-terminated. */ strcpy (dbuf, filename); /* Load the file in after the NUL. */ fbuf = dbuf + tflen + 1; result = read (file, fbuf, ulen); if (result < 0) log_fatal ("Can't read in %s: %m", filename); if (result != ulen) log_fatal ("%s: short read of %d bytes instead of %d.", filename, ulen, result); memfile: /* If we're recording, write out the filename and file contents. */ if (trace_record ()) trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL); new_parse (&cfile, -1, fbuf, ulen, filename, 0); /* XXX */#else new_parse (&cfile, file, (char *)0, 0, filename, 0);#endif if (leasep) status = lease_file_subparse (cfile); else status = conf_file_subparse (cfile, group, group_type); end_parse (&cfile);#if defined (TRACING) dfree (dbuf, MDL);#endif close (file); return status;}#if defined (TRACING)void trace_conf_input (trace_type_t *ttype, unsigned len, char *data){ char *fbuf; unsigned flen; unsigned tflen; struct parse *cfile = (struct parse *)0; static int postconf_initialized; static int leaseconf_initialized; /* Do what's done above, except that we don't have to read in the data, because it's already been read for us. */ tflen = strlen (data); flen = len - tflen - 1; fbuf = data + tflen + 1; /* If we're recording, write out the filename and file contents. */ if (trace_record ()) trace_write_packet (ttype, len, data, MDL); new_parse (&cfile, -1, fbuf, flen, data, 0); if (ttype == trace_readleases_type) lease_file_subparse (cfile); else conf_file_subparse (cfile, root_group, ROOT_GROUP); end_parse (&cfile); /* Postconfiguration needs to be done after the config file has been loaded. */ if (!postconf_initialized && ttype == trace_readconf_type) { postconf_initialization (0); postconf_initialized = 1; } if (!leaseconf_initialized && ttype == trace_readleases_type) { db_startup (0); leaseconf_initialized = 1; postdb_startup (); }}void trace_conf_stop (trace_type_t *ttype) { }#endif/* conf-file :== parameters declarations END_OF_FILE parameters :== <nil> | parameter | parameters parameter declarations :== <nil> | declaration | declarations declaration */isc_result_t conf_file_subparse (struct parse *cfile, struct group *group, int group_type){ const char *val; enum dhcp_token token; int declaration = 0; int status; do { token = peek_token (&val, (unsigned *)0, cfile); if (token == END_OF_FILE) break; declaration = parse_statement (cfile, group, group_type, (struct host_decl *)0, declaration); } while (1); token = next_token (&val, (unsigned *)0, cfile); status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS; return status;}/* lease-file :== lease-declarations END_OF_FILE lease-statments :== <nil> | lease-declaration | lease-declarations lease-declaration */isc_result_t lease_file_subparse (struct parse *cfile){ const char *val; enum dhcp_token token; isc_result_t status; do { token = next_token (&val, (unsigned *)0, cfile); if (token == END_OF_FILE) break; if (token == LEASE) { struct lease *lease = (struct lease *)0; if (parse_lease_declaration (&lease, cfile)) { enter_lease (lease); lease_dereference (&lease, MDL); } else 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);#if defined (FAILOVER_PROTOCOL) } else if (token == FAILOVER) { parse_failover_state_declaration (cfile, (dhcp_failover_state_t *)0);#endif } 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; return status;}/* statement :== parameter | declaration parameter :== timestamp | DEFAULT_LEASE_TIME lease_time | MAX_LEASE_TIME lease_time | DYNAMIC_BOOTP_LEASE_CUTOFF date | DYNAMIC_BOOTP_LEASE_LENGTH lease_time | BOOT_UNKNOWN_CLIENTS boolean | ONE_LEASE_PER_CLIENT boolean | GET_LEASE_HOSTNAMES boolean | USE_HOST_DECL_NAME boolean | NEXT_SERVER ip-addr-or-hostname SEMI | option_parameter | SERVER-IDENTIFIER ip-addr-or-hostname SEMI | FILENAME string-parameter | SERVER_NAME string-parameter | hardware-parameter | fixed-address-parameter | ALLOW allow-deny-keyword | DENY allow-deny-keyword | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean | AUTHORITATIVE | NOT AUTHORITATIVE declaration :== host-declaration | group-declaration | shared-network-declaration | subnet-declaration | VENDOR_CLASS class-declaration | USER_CLASS class-declaration | RANGE address-range-declaration */int parse_statement (cfile, group, type, host_decl, declaration) struct parse *cfile; struct group *group; int type; struct host_decl *host_decl; int declaration;{ enum dhcp_token token; const char *val; struct shared_network *share; char *t, *n; struct expression *expr; struct data_string data; struct hardware hardware; struct executable_statement *et, *ep; struct option *option; struct option_cache *cache; int lose; struct data_string key_id; int known; isc_result_t status; token = peek_token (&val, (unsigned *)0, cfile); switch (token) { case INCLUDE: next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "filename string expected."); skip_to_semi (cfile); } else { status = read_conf_file (val, group, type, 0); if (status != ISC_R_SUCCESS) parse_warn (cfile, "%s: bad parse.", val); parse_semi (cfile); } return 1; case HOST: next_token (&val, (unsigned *)0, cfile); if (type != HOST_DECL && type != CLASS_DECL) parse_host_declaration (cfile, group); else { parse_warn (cfile, "host declarations not allowed here."); skip_to_semi (cfile); } return 1; case GROUP: next_token (&val, (unsigned *)0, cfile); if (type != HOST_DECL && type != CLASS_DECL) parse_group_declaration (cfile, group); else { parse_warn (cfile, "group declarations not allowed here."); skip_to_semi (cfile); } return 1; case TIMESTAMP: next_token (&val, (unsigned *)0, cfile); parsed_time = parse_timestamp (cfile); break; case SHARED_NETWORK: next_token (&val, (unsigned *)0, cfile); if (type == SHARED_NET_DECL || type == HOST_DECL || type == SUBNET_DECL || type == CLASS_DECL) { parse_warn (cfile, "shared-network parameters not %s.", "allowed here"); skip_to_semi (cfile); break; } parse_shared_net_declaration (cfile, group); return 1; case SUBNET: next_token (&val, (unsigned *)0, cfile); if (type == HOST_DECL || type == SUBNET_DECL || type == CLASS_DECL) { parse_warn (cfile, "subnet declarations not allowed here."); skip_to_semi (cfile); return 1; } /* If we're in a subnet declaration, just do the parse. */ if (group -> shared_network) { parse_subnet_declaration (cfile, group -> shared_network); break; } /* Otherwise, cons up a fake shared network structure and populate it with the lone subnet... */ share = (struct shared_network *)0; status = shared_network_allocate (&share, MDL); if (status != ISC_R_SUCCESS) log_fatal ("Can't allocate shared subnet: %s", isc_result_totext (status)); if (!clone_group (&share -> group, group, MDL)) log_fatal ("Can't allocate group for shared net"); shared_network_reference (&share -> group -> shared_network, share, MDL); parse_subnet_declaration (cfile, share); /* share -> subnets is the subnet we just parsed. */ if (share -> subnets) { interface_reference (&share -> interface, share -> subnets -> interface, MDL); /* Make the shared network name from network number. */ n = piaddrmask (share -> subnets -> net, share -> subnets -> netmask, MDL); share -> name = n; /* Copy the authoritative parameter from the subnet, since there is no opportunity to declare it here. */ share -> group -> authoritative = share -> subnets -> group -> authoritative; enter_shared_network (share); } shared_network_dereference (&share, MDL); return 1; case VENDOR_CLASS: next_token (&val, (unsigned *)0, cfile); if (type == CLASS_DECL) { parse_warn (cfile, "class declarations not allowed here."); skip_to_semi (cfile); break; } parse_class_declaration ((struct class **)0, cfile, group, 0); return 1; case USER_CLASS: next_token (&val, (unsigned *)0, cfile); if (type == CLASS_DECL) { parse_warn (cfile, "class declarations not allowed here."); skip_to_semi (cfile); break; } parse_class_declaration ((struct class **)0, cfile, group, 1); return 1; case CLASS: next_token (&val, (unsigned *)0, cfile); if (type == CLASS_DECL) { parse_warn (cfile, "class declarations not allowed here."); skip_to_semi (cfile); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?