diff options
author | brooks <brooks@FreeBSD.org> | 2005-06-29 01:46:40 +0000 |
---|---|---|
committer | brooks <brooks@FreeBSD.org> | 2005-06-29 01:46:40 +0000 |
commit | bd7fc02cf00f7446a4fc2151d3367d5e935dacae (patch) | |
tree | c334ad76a77de064f9dde5e545e004461813e6a5 /contrib/isc-dhcp/common | |
parent | 37efc775b590475026ff6366785a1b78bcb697f5 (diff) | |
download | FreeBSD-src-bd7fc02cf00f7446a4fc2151d3367d5e935dacae.zip FreeBSD-src-bd7fc02cf00f7446a4fc2151d3367d5e935dacae.tar.gz |
Remove isc-dhcp files from HEAD now that we're using the OpenBSD
dhclient.
Reminded by: ru
Approved by: re (blanket dhclient)
Diffstat (limited to 'contrib/isc-dhcp/common')
32 files changed, 0 insertions, 28863 deletions
diff --git a/contrib/isc-dhcp/common/Makefile.dist b/contrib/isc-dhcp/common/Makefile.dist deleted file mode 100644 index 8d4e043..0000000 --- a/contrib/isc-dhcp/common/Makefile.dist +++ /dev/null @@ -1,95 +0,0 @@ -# Makefile.dist -# -# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# Internet Systems Consortium, Inc. -# 950 Charter Street -# Redwood City, CA 94063 -# <info@isc.org> -# http://www.isc.org/ - -CATMANPAGES = dhcp-options.cat5 dhcp-eval.cat5 -SEDMANPAGES = dhcp-options.man5 dhcp-eval.man5 -SRC = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \ - lpf.c dlpi.c packet.c tr.c ethernet.c iscprint.c memory.c print.c \ - options.c inet.c tree.c tables.c alloc.c fddi.c ctrace.c dns.c \ - resolv.c execute.c discover.c comapi.c -OBJ = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \ - lpf.o dlpi.o packet.o tr.o ethernet.o iscprint.o memory.o print.o \ - options.o inet.o tree.o tables.o alloc.o fddi.o ctrace.o dns.o \ - resolv.o execute.o discover.o comapi.o -MAN = dhcp-options.5 dhcp-eval.5 - -INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes -CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) - -all: libdhcp.a $(CATMANPAGES) - -libdhcp.a: $(OBJ) - rm -f libdhcp.a - ar cruv libdhcp.a $(OBJ) - $(RANLIB) libdhcp.a - -install: all - for dir in $(FFMANDIR); do \ - foo=""; \ - for bar in `echo $(DESTDIR)$${dir} |tr / ' '`; do \ - foo=$${foo}/$$bar; \ - if [ ! -d $$foo ]; then \ - mkdir $$foo; \ - chmod 755 $$foo; \ - fi; \ - done; \ - done - $(MANINSTALL) $(MANFROM) dhcp-options.$(MANCAT)5 $(MANTO) \ - $(DESTDIR)$(FFMANDIR)/dhcp-options$(FFMANEXT) - $(MANINSTALL) $(MANFROM) dhcp-eval.$(MANCAT)5 $(MANTO) \ - $(DESTDIR)$(FFMANDIR)/dhcp-eval$(FFMANEXT) - -depend: - $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC) - -clean: - -rm -f $(OBJ) - -realclean: clean - -rm -f libdhcp.a $(CATMANPAGES) $(SEDMANPAGES) *~ #* - -distclean: realclean - -rm -f Makefile - -links: - @for foo in $(SRC) $(MAN); do \ - if [ ! -b $$foo ]; then \ - rm -f $$foo; \ - fi; \ - ln -s $(TOP)/common/$$foo $$foo; \ - done - -dhcp-options.cat5: dhcp-options.man5 - nroff -man dhcp-options.man5 >dhcp-options.cat5 - -dhcp-options.man5: dhcp-options.5 - sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ - -e "s#RUNDIR#$(VARRUN)#g" < dhcp-options.5 >dhcp-options.man5 - -dhcp-eval.cat5: dhcp-eval.man5 - nroff -man dhcp-eval.man5 >dhcp-eval.cat5 - -dhcp-eval.man5: dhcp-eval.5 - sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ - -e "s#RUNDIR#$(VARRUN)#g" < dhcp-eval.5 >dhcp-eval.man5 - -# Dependencies (semi-automatically-generated) diff --git a/contrib/isc-dhcp/common/alloc.c b/contrib/isc-dhcp/common/alloc.c deleted file mode 100644 index 39edd81..0000000 --- a/contrib/isc-dhcp/common/alloc.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* alloc.c - - Memory allocation... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: alloc.c,v 1.53.2.10 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include <omapip/omapip_p.h> - -struct dhcp_packet *dhcp_free_list; -struct packet *packet_free_list; - -int option_chain_head_allocate (ptr, file, line) - struct option_chain_head **ptr; - const char *file; - int line; -{ - int size; - struct option_chain_head *h; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct option_chain_head *)0; -#endif - } - - h = dmalloc (sizeof *h, file, line); - if (h) { - memset (h, 0, sizeof *h); - return option_chain_head_reference (ptr, h, file, line); - } - return 0; -} - -int option_chain_head_reference (ptr, bp, file, line) - struct option_chain_head **ptr; - struct option_chain_head *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct option_chain_head *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int option_chain_head_dereference (ptr, file, line) - struct option_chain_head **ptr; - const char *file; - int line; -{ - int i; - struct option_chain_head *option_chain_head; - pair car, cdr; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - option_chain_head = *ptr; - *ptr = (struct option_chain_head *)0; - --option_chain_head -> refcnt; - rc_register (file, line, ptr, option_chain_head, - option_chain_head -> refcnt, 1, RC_MISC); - if (option_chain_head -> refcnt > 0) - return 1; - - if (option_chain_head -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (option_chain_head); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - /* If there are any options on this head, free them. */ - for (car = option_chain_head -> first; car; car = cdr) { - cdr = car -> cdr; - if (car -> car) - option_cache_dereference ((struct option_cache **) - (&car -> car), MDL); - dfree (car, MDL); - car = cdr; - } - - dfree (option_chain_head, file, line); - return 1; -} - -int group_allocate (ptr, file, line) - struct group **ptr; - const char *file; - int line; -{ - int size; - struct group *g; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct group *)0; -#endif - } - - g = dmalloc (sizeof *g, file, line); - if (g) { - memset (g, 0, sizeof *g); - return group_reference (ptr, g, file, line); - } - return 0; -} - -int group_reference (ptr, bp, file, line) - struct group **ptr; - struct group *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct group *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int group_dereference (ptr, file, line) - struct group **ptr; - const char *file; - int line; -{ - int i; - struct group *group; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - group = *ptr; - *ptr = (struct group *)0; - --group -> refcnt; - rc_register (file, line, ptr, group, group -> refcnt, 1, RC_MISC); - if (group -> refcnt > 0) - return 1; - - if (group -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (group); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (group -> object) - group_object_dereference (&group -> object, file, line); - if (group -> subnet) - subnet_dereference (&group -> subnet, file, line); - if (group -> shared_network) - shared_network_dereference (&group -> shared_network, - file, line); - if (group -> statements) - executable_statement_dereference (&group -> statements, - file, line); - if (group -> next) - group_dereference (&group -> next, file, line); - dfree (group, file, line); - return 1; -} - -struct dhcp_packet *new_dhcp_packet (file, line) - const char *file; - int line; -{ - struct dhcp_packet *rval; - rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet), - file, line); - return rval; -} - -struct protocol *new_protocol (file, line) - const char *file; - int line; -{ - struct protocol *rval = dmalloc (sizeof (struct protocol), file, line); - return rval; -} - -struct domain_search_list *new_domain_search_list (file, line) - const char *file; - int line; -{ - struct domain_search_list *rval = - dmalloc (sizeof (struct domain_search_list), file, line); - return rval; -} - -struct name_server *new_name_server (file, line) - const char *file; - int line; -{ - struct name_server *rval = - dmalloc (sizeof (struct name_server), file, line); - return rval; -} - -void free_name_server (ptr, file, line) - struct name_server *ptr; - const char *file; - int line; -{ - dfree ((VOIDPTR)ptr, file, line); -} - -struct option *new_option (file, line) - const char *file; - int line; -{ - struct option *rval = - dmalloc (sizeof (struct option), file, line); - if (rval) - memset (rval, 0, sizeof *rval); - return rval; -} - -void free_option (ptr, file, line) - struct option *ptr; - const char *file; - int line; -{ -/* XXX have to put all options on heap before this is possible. */ -#if 0 - if (ptr -> name) - dfree ((VOIDPTR)option -> name, file, line); - dfree ((VOIDPTR)ptr, file, line); -#endif -} - -struct universe *new_universe (file, line) - const char *file; - int line; -{ - struct universe *rval = - dmalloc (sizeof (struct universe), file, line); - return rval; -} - -void free_universe (ptr, file, line) - struct universe *ptr; - const char *file; - int line; -{ - dfree ((VOIDPTR)ptr, file, line); -} - -void free_domain_search_list (ptr, file, line) - struct domain_search_list *ptr; - const char *file; - int line; -{ - dfree ((VOIDPTR)ptr, file, line); -} - -void free_protocol (ptr, file, line) - struct protocol *ptr; - const char *file; - int line; -{ - dfree ((VOIDPTR)ptr, file, line); -} - -void free_dhcp_packet (ptr, file, line) - struct dhcp_packet *ptr; - const char *file; - int line; -{ - dfree ((VOIDPTR)ptr, file, line); -} - -struct client_lease *new_client_lease (file, line) - const char *file; - int line; -{ - return (struct client_lease *)dmalloc (sizeof (struct client_lease), - file, line); -} - -void free_client_lease (lease, file, line) - struct client_lease *lease; - const char *file; - int line; -{ - dfree (lease, file, line); -} - -pair free_pairs; - -pair new_pair (file, line) - const char *file; - int line; -{ - pair foo; - - if (free_pairs) { - foo = free_pairs; - free_pairs = foo -> cdr; - memset (foo, 0, sizeof *foo); - dmalloc_reuse (foo, file, line, 0); - return foo; - } - - foo = dmalloc (sizeof *foo, file, line); - if (!foo) - return foo; - memset (foo, 0, sizeof *foo); - return foo; -} - -void free_pair (foo, file, line) - pair foo; - const char *file; - int line; -{ - foo -> cdr = free_pairs; - free_pairs = foo; - dmalloc_reuse (free_pairs, (char *)0, 0, 0); -} - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -void relinquish_free_pairs () -{ - pair pf, pc; - - for (pf = free_pairs; pf; pf = pc) { - pc = pf -> cdr; - dfree (pf, MDL); - } - free_pairs = (pair)0; -} -#endif - -struct expression *free_expressions; - -int expression_allocate (cptr, file, line) - struct expression **cptr; - const char *file; - int line; -{ - struct expression *rval; - - if (free_expressions) { - rval = free_expressions; - free_expressions = rval -> data.not; - dmalloc_reuse (rval, file, line, 1); - } else { - rval = dmalloc (sizeof (struct expression), file, line); - if (!rval) - return 0; - } - memset (rval, 0, sizeof *rval); - return expression_reference (cptr, rval, file, line); -} - -int expression_reference (ptr, src, file, line) - struct expression **ptr; - struct expression *src; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct expression *)0; -#endif - } - *ptr = src; - src -> refcnt++; - rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); - return 1; -} - -void free_expression (expr, file, line) - struct expression *expr; - const char *file; - int line; -{ - expr -> data.not = free_expressions; - free_expressions = expr; - dmalloc_reuse (free_expressions, (char *)0, 0, 0); -} - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -void relinquish_free_expressions () -{ - struct expression *e, *n; - - for (e = free_expressions; e; e = n) { - n = e -> data.not; - dfree (e, MDL); - } - free_expressions = (struct expression *)0; -} -#endif - -struct binding_value *free_binding_values; - -int binding_value_allocate (cptr, file, line) - struct binding_value **cptr; - const char *file; - int line; -{ - struct binding_value *rval; - - if (free_binding_values) { - rval = free_binding_values; - free_binding_values = rval -> value.bv; - dmalloc_reuse (rval, file, line, 1); - } else { - rval = dmalloc (sizeof (struct binding_value), file, line); - if (!rval) - return 0; - } - memset (rval, 0, sizeof *rval); - return binding_value_reference (cptr, rval, file, line); -} - -int binding_value_reference (ptr, src, file, line) - struct binding_value **ptr; - struct binding_value *src; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct binding_value *)0; -#endif - } - *ptr = src; - src -> refcnt++; - rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); - return 1; -} - -void free_binding_value (bv, file, line) - struct binding_value *bv; - const char *file; - int line; -{ - bv -> value.bv = free_binding_values; - free_binding_values = bv; - dmalloc_reuse (free_binding_values, (char *)0, 0, 0); -} - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -void relinquish_free_binding_values () -{ - struct binding_value *b, *n; - - for (b = free_binding_values; b; b = n) { - n = b -> value.bv; - dfree (b, MDL); - } - free_binding_values = (struct binding_value *)0; -} -#endif - -int fundef_allocate (cptr, file, line) - struct fundef **cptr; - const char *file; - int line; -{ - struct fundef *rval; - - rval = dmalloc (sizeof (struct fundef), file, line); - if (!rval) - return 0; - memset (rval, 0, sizeof *rval); - return fundef_reference (cptr, rval, file, line); -} - -int fundef_reference (ptr, src, file, line) - struct fundef **ptr; - struct fundef *src; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct fundef *)0; -#endif - } - *ptr = src; - src -> refcnt++; - rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); - return 1; -} - -struct option_cache *free_option_caches; - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -void relinquish_free_option_caches () -{ - struct option_cache *o, *n; - - for (o = free_option_caches; o; o = n) { - n = (struct option_cache *)(o -> expression); - dfree (o, MDL); - } - free_option_caches = (struct option_cache *)0; -} -#endif - -int option_cache_allocate (cptr, file, line) - struct option_cache **cptr; - const char *file; - int line; -{ - struct option_cache *rval; - - if (free_option_caches) { - rval = free_option_caches; - free_option_caches = - (struct option_cache *)(rval -> expression); - dmalloc_reuse (rval, file, line, 0); - } else { - rval = dmalloc (sizeof (struct option_cache), file, line); - if (!rval) - return 0; - } - memset (rval, 0, sizeof *rval); - return option_cache_reference (cptr, rval, file, line); -} - -int option_cache_reference (ptr, src, file, line) - struct option_cache **ptr; - struct option_cache *src; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct option_cache *)0; -#endif - } - *ptr = src; - src -> refcnt++; - rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); - return 1; -} - -int buffer_allocate (ptr, len, file, line) - struct buffer **ptr; - unsigned len; - const char *file; - int line; -{ - struct buffer *bp; - - bp = dmalloc (len + sizeof *bp, file, line); - if (!bp) - return 0; - memset (bp, 0, sizeof *bp); - bp -> refcnt = 0; - return buffer_reference (ptr, bp, file, line); -} - -int buffer_reference (ptr, bp, file, line) - struct buffer **ptr; - struct buffer *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct buffer *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int buffer_dereference (ptr, file, line) - struct buffer **ptr; - const char *file; - int line; -{ - struct buffer *bp; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (!*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - (*ptr) -> refcnt--; - rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC); - if (!(*ptr) -> refcnt) { - dfree ((*ptr), file, line); - } else if ((*ptr) -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (*ptr); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - *ptr = (struct buffer *)0; - return 1; -} - -int dns_host_entry_allocate (ptr, hostname, file, line) - struct dns_host_entry **ptr; - const char *hostname; - const char *file; - int line; -{ - struct dns_host_entry *bp; - - bp = dmalloc (strlen (hostname) + sizeof *bp, file, line); - if (!bp) - return 0; - memset (bp, 0, sizeof *bp); - bp -> refcnt = 0; - strcpy (bp -> hostname, hostname); - return dns_host_entry_reference (ptr, bp, file, line); -} - -int dns_host_entry_reference (ptr, bp, file, line) - struct dns_host_entry **ptr; - struct dns_host_entry *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct dns_host_entry *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int dns_host_entry_dereference (ptr, file, line) - struct dns_host_entry **ptr; - const char *file; - int line; -{ - struct dns_host_entry *bp; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - (*ptr) -> refcnt--; - rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC); - if (!(*ptr) -> refcnt) - dfree ((*ptr), file, line); - if ((*ptr) -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (*ptr); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - *ptr = (struct dns_host_entry *)0; - return 1; -} - -int option_state_allocate (ptr, file, line) - struct option_state **ptr; - const char *file; - int line; -{ - unsigned size; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct option_state *)0; -#endif - } - - size = sizeof **ptr + (universe_count - 1) * sizeof (VOIDPTR); - *ptr = dmalloc (size, file, line); - if (*ptr) { - memset (*ptr, 0, size); - (*ptr) -> universe_count = universe_count; - (*ptr) -> refcnt = 1; - rc_register (file, line, - ptr, *ptr, (*ptr) -> refcnt, 0, RC_MISC); - return 1; - } - return 0; -} - -int option_state_reference (ptr, bp, file, line) - struct option_state **ptr; - struct option_state *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct option_state *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int option_state_dereference (ptr, file, line) - struct option_state **ptr; - const char *file; - int line; -{ - int i; - struct option_state *options; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - options = *ptr; - *ptr = (struct option_state *)0; - --options -> refcnt; - rc_register (file, line, ptr, options, options -> refcnt, 1, RC_MISC); - if (options -> refcnt > 0) - return 1; - - if (options -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (options); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - /* Loop through the per-universe state. */ - for (i = 0; i < options -> universe_count; i++) - if (options -> universes [i] && - universes [i] -> option_state_dereference) - ((*(universes [i] -> option_state_dereference)) - (universes [i], options, file, line)); - dfree (options, file, line); - return 1; -} - -int executable_statement_allocate (ptr, file, line) - struct executable_statement **ptr; - const char *file; - int line; -{ - struct executable_statement *bp; - - bp = dmalloc (sizeof *bp, file, line); - if (!bp) - return 0; - memset (bp, 0, sizeof *bp); - return executable_statement_reference (ptr, bp, file, line); -} - -int executable_statement_reference (ptr, bp, file, line) - struct executable_statement **ptr; - struct executable_statement *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct executable_statement *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -static struct packet *free_packets; - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -void relinquish_free_packets () -{ - struct packet *p, *n; - for (p = free_packets; p; p = n) { - n = (struct packet *)(p -> raw); - dfree (p, MDL); - } - free_packets = (struct packet *)0; -} -#endif - -int packet_allocate (ptr, file, line) - struct packet **ptr; - const char *file; - int line; -{ - int size; - struct packet *p; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct packet *)0; -#endif - } - - if (free_packets) { - p = free_packets; - free_packets = (struct packet *)(p -> raw); - dmalloc_reuse (p, file, line, 1); - } else { - p = dmalloc (sizeof *p, file, line); - } - if (p) { - memset (p, 0, sizeof *p); - return packet_reference (ptr, p, file, line); - } - return 0; -} - -int packet_reference (ptr, bp, file, line) - struct packet **ptr; - struct packet *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct packet *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int packet_dereference (ptr, file, line) - struct packet **ptr; - const char *file; - int line; -{ - int i; - struct packet *packet; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - packet = *ptr; - *ptr = (struct packet *)0; - --packet -> refcnt; - rc_register (file, line, ptr, packet, packet -> refcnt, 1, RC_MISC); - if (packet -> refcnt > 0) - return 1; - - if (packet -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (packet); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (packet -> options) - option_state_dereference (&packet -> options, file, line); - if (packet -> interface) - interface_dereference (&packet -> interface, MDL); - if (packet -> shared_network) - shared_network_dereference (&packet -> shared_network, MDL); - for (i = 0; i < packet -> class_count && i < PACKET_MAX_CLASSES; i++) { - if (packet -> classes [i]) - omapi_object_dereference ((omapi_object_t **) - &packet -> classes [i], MDL); - } - packet -> raw = (struct dhcp_packet *)free_packets; - free_packets = packet; - dmalloc_reuse (free_packets, (char *)0, 0, 0); - return 1; -} - -int dns_zone_allocate (ptr, file, line) - struct dns_zone **ptr; - const char *file; - int line; -{ - int size; - struct dns_zone *d; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct dns_zone *)0; -#endif - } - - d = dmalloc (sizeof *d, file, line); - if (d) { - memset (d, 0, sizeof *d); - return dns_zone_reference (ptr, d, file, line); - } - return 0; -} - -int dns_zone_reference (ptr, bp, file, line) - struct dns_zone **ptr; - struct dns_zone *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct dns_zone *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -int binding_scope_allocate (ptr, file, line) - struct binding_scope **ptr; - const char *file; - int line; -{ - struct binding_scope *bp; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - bp = dmalloc (sizeof *bp, file, line); - if (!bp) - return 0; - memset (bp, 0, sizeof *bp); - binding_scope_reference (ptr, bp, file, line); - return 1; -} - -int binding_scope_reference (ptr, bp, file, line) - struct binding_scope **ptr; - struct binding_scope *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct binding_scope *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); - return 1; -} - -/* Make a copy of the data in data_string, upping the buffer reference - count if there's a buffer. */ - -void data_string_copy (dest, src, file, line) - struct data_string *dest; - struct data_string *src; - const char *file; - int line; -{ - if (src -> buffer) - buffer_reference (&dest -> buffer, src -> buffer, file, line); - dest -> data = src -> data; - dest -> terminated = src -> terminated; - dest -> len = src -> len; -} - -/* Release the reference count to a data string's buffer (if any) and - zero out the other information, yielding the null data string. */ - -void data_string_forget (data, file, line) - struct data_string *data; - const char *file; - int line; -{ - if (data -> buffer) - buffer_dereference (&data -> buffer, file, line); - memset (data, 0, sizeof *data); -} - -/* Make a copy of the data in data_string, upping the buffer reference - count if there's a buffer. */ - -void data_string_truncate (dp, len) - struct data_string *dp; - int len; -{ - if (len < dp -> len) { - dp -> terminated = 0; - dp -> len = len; - } -} diff --git a/contrib/isc-dhcp/common/bpf.c b/contrib/isc-dhcp/common/bpf.c deleted file mode 100644 index 9c32153..0000000 --- a/contrib/isc-dhcp/common/bpf.c +++ /dev/null @@ -1,548 +0,0 @@ -/* bpf.c - - BPF socket interface code, originally contributed by Archie Cobbs. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software was contributed to Internet Systems Consortium - * by Archie Cobbs. - * - * Patches for FDDI support on Digital Unix were written by Bill - * Stapleton, and maintained for a while by Mike Meredith before he - * managed to get me to integrate them. - */ - -#ifndef lint -static char copyright[] = -"$Id: bpf.c,v 1.48.2.6 2004/06/17 20:54:38 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \ - || defined (USE_LPF_RECEIVE) -# if defined (USE_LPF_RECEIVE) -# include <asm/types.h> -# include <linux/filter.h> -# define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */ -# else -# include <sys/ioctl.h> -# include <sys/uio.h> -# include <net/bpf.h> -# if defined (NEED_OSF_PFILT_HACKS) -# include <net/pfilt.h> -# endif -# endif - -#include <netinet/in_systm.h> -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" -#endif - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#ifdef USE_BPF_SEND -void if_reinitialize_send (info) - struct interface_info *info; -{ -} -#endif - -#ifdef USE_BPF_RECEIVE -void if_reinitialize_receive (info) - struct interface_info *info; -{ -} -#endif - -/* Called by get_interface_list for each interface that's discovered. - Opens a packet filter for each interface and adds it to the select - mask. */ - -#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) -int if_register_bpf (info) - struct interface_info *info; -{ - int sock; - char filename[50]; - int b; - - /* Open a BPF device */ - for (b = 0; 1; b++) { - /* %Audit% 31 bytes max. %2004.06.17,Safe% */ - sprintf(filename, BPF_FORMAT, b); - sock = open (filename, O_RDWR, 0); - if (sock < 0) { - if (errno == EBUSY) { - continue; - } else { - if (!b) - log_fatal ("No bpf devices.%s%s%s", - " Please read the README", - " section for your operating", - " system."); - log_fatal ("Can't find free bpf: %m"); - } - } else { - break; - } - } - - /* Set the BPF device to point at this interface. */ - if (ioctl (sock, BIOCSETIF, info -> ifp) < 0) - log_fatal ("Can't attach interface %s to bpf device %s: %m", - info -> name, filename); - - return sock; -} -#endif /* USE_BPF_SEND || USE_BPF_RECEIVE */ - -#ifdef USE_BPF_SEND -void if_register_send (info) - struct interface_info *info; -{ - /* If we're using the bpf API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_BPF_RECEIVE - info -> wfdesc = if_register_bpf (info, interface); -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - log_info ("Sending on BPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_send (info) - struct interface_info *info; -{ - /* If we're using the bpf API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_BPF_RECEIVE - close (info -> wfdesc); -#endif - info -> wfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling output on BPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_BPF_SEND */ - -#if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE) -/* Packet filter program... - XXX Changes to the filter program may require changes to the constant - offsets used in if_register_send to patch the BPF program! XXX */ - -struct bpf_insn dhcp_bpf_filter [] = { - /* Make sure this is an IP packet... */ - BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12), - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), - - /* Make sure it's a UDP packet... */ - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23), - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), - - /* Make sure this isn't a fragment... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), - BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), - - /* Get the IP header length... */ - BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), - - /* Make sure it's to the right port... */ - BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ - - /* If we passed all the tests, ask for the whole packet. */ - BPF_STMT(BPF_RET+BPF_K, (u_int)-1), - - /* Otherwise, drop it. */ - BPF_STMT(BPF_RET+BPF_K, 0), -}; - -#if defined (DEC_FDDI) -struct bpf_insn *bpf_fddi_filter; -#endif - -int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn); -#if defined (HAVE_TR_SUPPORT) -struct bpf_insn dhcp_bpf_tr_filter [] = { - /* accept all token ring packets due to variable length header */ - /* if we want to get clever, insert the program here */ - - /* If we passed all the tests, ask for the whole packet. */ - BPF_STMT(BPF_RET+BPF_K, (u_int)-1), - - /* Otherwise, drop it. */ - BPF_STMT(BPF_RET+BPF_K, 0), -}; - -int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter / - sizeof (struct bpf_insn)); -#endif /* HAVE_TR_SUPPORT */ -#endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */ - -#if defined (USE_BPF_RECEIVE) -void if_register_receive (info) - struct interface_info *info; -{ - int flag = 1; - struct bpf_version v; - u_int32_t addr; - struct bpf_program p; - u_int32_t bits; -#ifdef DEC_FDDI - int link_layer; -#endif /* DEC_FDDI */ - - /* Open a BPF device and hang it on this interface... */ - info -> rfdesc = if_register_bpf (info); - - /* Make sure the BPF version is in range... */ - if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0) - log_fatal ("Can't get BPF version: %m"); - - if (v.bv_major != BPF_MAJOR_VERSION || - v.bv_minor < BPF_MINOR_VERSION) - log_fatal ("BPF version mismatch - recompile DHCP!"); - - /* Set immediate mode so that reads return as soon as a packet - comes in, rather than waiting for the input buffer to fill with - packets. */ - if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0) - log_fatal ("Can't set immediate mode on bpf device: %m"); - -#ifdef NEED_OSF_PFILT_HACKS - /* Allow the copyall flag to be set... */ - if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0) - log_fatal ("Can't set ALLOWCOPYALL: %m"); - - /* Clear all the packet filter mode bits first... */ - bits = 0; - if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) - log_fatal ("Can't clear pfilt bits: %m"); - - /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */ - bits = ENBATCH | ENCOPYALL | ENBPFHDR; - if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) - log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m"); -#endif - /* Get the required BPF buffer length from the kernel. */ - if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0) - log_fatal ("Can't get bpf buffer length: %m"); - info -> rbuf = dmalloc (info -> rbuf_max, MDL); - if (!info -> rbuf) - log_fatal ("Can't allocate %ld bytes for bpf input buffer.", - (long)(info -> rbuf_max)); - info -> rbuf_offset = 0; - info -> rbuf_len = 0; - - /* Set up the bpf filter program structure. */ - p.bf_len = dhcp_bpf_filter_len; - -#ifdef DEC_FDDI - /* See if this is an FDDI interface, flag it for later. */ - if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 && - link_layer == DLT_FDDI) { - if (!bpf_fddi_filter) { - bpf_fddi_filter = dmalloc (sizeof bpf_fddi_filter, - MDL); - if (!bpf_fddi_filter) - log_fatal ("No memory for FDDI filter."); - memcpy (bpf_fddi_filter, - dhcp_bpf_filter, sizeof dhcp_bpf_filter); - /* Patch the BPF program to account for the difference - in length between ethernet headers (14), FDDI and - 802.2 headers (16 +8=24, +10). - XXX changes to filter program may require changes to - XXX the insn number(s) used below! */ - bpf_fddi_filter[0].k += 10; - bpf_fddi_filter[2].k += 10; - bpf_fddi_filter[4].k += 10; - bpf_fddi_filter[6].k += 10; - bpf_fddi_filter[7].k += 10; - } - p.bf_insns = bpf_fddi_filter; - } else -#endif /* DEC_FDDI */ - p.bf_insns = dhcp_bpf_filter; - - /* Patch the server port into the BPF program... - XXX changes to filter program may require changes - to the insn number(s) used below! XXX */ - dhcp_bpf_filter [8].k = ntohs (local_port); - - if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0) - log_fatal ("Can't install packet filter program: %m"); - if (!quiet_interface_discovery) - log_info ("Listening on BPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_receive (info) - struct interface_info *info; -{ - close (info -> rfdesc); - info -> rfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling input on BPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_BPF_RECEIVE */ - -#ifdef USE_BPF_SEND -ssize_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - unsigned hbufp = 0, ibufp = 0; - double hw [4]; - double ip [32]; - struct iovec iov [3]; - int result; - int fudge; - - if (!strcmp (interface -> name, "fallback")) - return send_fallback (interface, packet, raw, - len, from, to, hto); - - /* Assemble the headers... */ - assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto); - assemble_udp_ip_header (interface, - (unsigned char *)ip, &ibufp, from.s_addr, - to -> sin_addr.s_addr, to -> sin_port, - (unsigned char *)raw, len); - - /* Fire it off */ - iov [0].iov_base = ((char *)hw); - iov [0].iov_len = hbufp; - iov [1].iov_base = ((char *)ip); - iov [1].iov_len = ibufp; - iov [2].iov_base = (char *)raw; - iov [2].iov_len = len; - - result = writev(interface -> wfdesc, iov, 3); - if (result < 0) - log_error ("send_packet: %m"); - return result; -} -#endif /* USE_BPF_SEND */ - -#ifdef USE_BPF_RECEIVE -ssize_t receive_packet (interface, buf, len, from, hfrom) - struct interface_info *interface; - unsigned char *buf; - size_t len; - struct sockaddr_in *from; - struct hardware *hfrom; -{ - int length = 0; - int offset = 0; - struct bpf_hdr hdr; - - /* All this complexity is because BPF doesn't guarantee - that only one packet will be returned at a time. We're - getting what we deserve, though - this is a terrible abuse - of the BPF interface. Sigh. */ - - /* Process packets until we get one we can return or until we've - done a read and gotten nothing we can return... */ - - do { - /* If the buffer is empty, fill it. */ - if (interface -> rbuf_offset == interface -> rbuf_len) { - length = read (interface -> rfdesc, - interface -> rbuf, - (size_t)interface -> rbuf_max); - if (length <= 0) { -#ifdef __FreeBSD__ - if (errno == ENXIO) { -#else - if (errno == EIO) { -#endif - dhcp_interface_remove - ((omapi_object_t *)interface, - (omapi_object_t *)0); - } - return length; - } - interface -> rbuf_offset = 0; - interface -> rbuf_len = BPF_WORDALIGN (length); - } - - /* If there isn't room for a whole bpf header, something went - wrong, but we'll ignore it and hope it goes away... XXX */ - if (interface -> rbuf_len - - interface -> rbuf_offset < sizeof hdr) { - interface -> rbuf_offset = interface -> rbuf_len; - continue; - } - - /* Copy out a bpf header... */ - memcpy (&hdr, &interface -> rbuf [interface -> rbuf_offset], - sizeof hdr); - - /* If the bpf header plus data doesn't fit in what's left - of the buffer, stick head in sand yet again... */ - if (interface -> rbuf_offset + - hdr.bh_hdrlen + hdr.bh_caplen > interface -> rbuf_len) { - interface -> rbuf_offset = interface -> rbuf_len; - continue; - } - - /* If the captured data wasn't the whole packet, or if - the packet won't fit in the input buffer, all we - can do is drop it. */ - if (hdr.bh_caplen != hdr.bh_datalen) { - interface -> rbuf_offset = - BPF_WORDALIGN (interface -> rbuf_offset + - hdr.bh_hdrlen + hdr.bh_caplen); - continue; - } - - /* Skip over the BPF header... */ - interface -> rbuf_offset += hdr.bh_hdrlen; - - /* Decode the physical header... */ - offset = decode_hw_header (interface, - interface -> rbuf, - interface -> rbuf_offset, - hfrom); - - /* If a physical layer checksum failed (dunno of any - physical layer that supports this, but WTH), skip this - packet. */ - if (offset < 0) { - interface -> rbuf_offset = - BPF_WORDALIGN (interface -> rbuf_offset + - hdr.bh_caplen); - continue; - } - interface -> rbuf_offset += offset; - hdr.bh_caplen -= offset; - - /* Decode the IP and UDP headers... */ - offset = decode_udp_ip_header (interface, - interface -> rbuf, - interface -> rbuf_offset, - from, - (unsigned char *)0, - hdr.bh_caplen); - - /* If the IP or UDP checksum was bad, skip the packet... */ - if (offset < 0) { - interface -> rbuf_offset = - BPF_WORDALIGN (interface -> rbuf_offset + - hdr.bh_caplen); - continue; - } - interface -> rbuf_offset = interface -> rbuf_offset + offset; - hdr.bh_caplen -= offset; - - /* If there's not enough room to stash the packet data, - we have to skip it (this shouldn't happen in real - life, though). */ - if (hdr.bh_caplen > len) { - interface -> rbuf_offset = - BPF_WORDALIGN (interface -> rbuf_offset + - hdr.bh_caplen); - continue; - } - - /* Copy out the data in the packet... */ - memcpy (buf, interface -> rbuf + interface -> rbuf_offset, - hdr.bh_caplen); - interface -> rbuf_offset = - BPF_WORDALIGN (interface -> rbuf_offset + - hdr.bh_caplen); - return hdr.bh_caplen; - } while (!length); - return 0; -} - -int can_unicast_without_arp (ip) - struct interface_info *ip; -{ - return 1; -} - -int can_receive_unicast_unconfigured (ip) - struct interface_info *ip; -{ - return 1; -} - -int supports_multiple_interfaces (ip) - struct interface_info *ip; -{ - return 1; -} - -void maybe_setup_fallback () -{ - isc_result_t status; - struct interface_info *fbi = (struct interface_info *)0; - if (setup_fallback (&fbi, MDL)) { - if_register_fallback (fbi); - status = omapi_register_io_object ((omapi_object_t *)fbi, - if_readsocket, 0, - fallback_discard, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - fbi -> name, isc_result_totext (status)); - interface_dereference (&fbi, MDL); - } -} -#endif diff --git a/contrib/isc-dhcp/common/comapi.c b/contrib/isc-dhcp/common/comapi.c deleted file mode 100644 index 9f0b965..0000000 --- a/contrib/isc-dhcp/common/comapi.c +++ /dev/null @@ -1,949 +0,0 @@ -/* omapi.c - - OMAPI object interfaces for the DHCP server. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1999-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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''. - */ - -/* Many, many thanks to Brian Murrell and BCtel for this code - BCtel - provided the funding that resulted in this code and the entire - OMAPI support library being written, and Brian helped brainstorm - and refine the requirements. To the extent that this code is - useful, you have Brian and BCtel to thank. Any limitations in the - code are a result of mistakes on my part. -- Ted Lemon */ - -#ifndef lint -static char copyright[] = -"$Id: comapi.c,v 1.9.2.7 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include <omapip/omapip_p.h> - -OMAPI_OBJECT_ALLOC (subnet, struct subnet, dhcp_type_subnet) -OMAPI_OBJECT_ALLOC (shared_network, struct shared_network, - dhcp_type_shared_network) -OMAPI_OBJECT_ALLOC (group_object, struct group_object, dhcp_type_group) -OMAPI_OBJECT_ALLOC (dhcp_control, dhcp_control_object_t, dhcp_type_control) - -omapi_object_type_t *dhcp_type_interface; -omapi_object_type_t *dhcp_type_group; -omapi_object_type_t *dhcp_type_shared_network; -omapi_object_type_t *dhcp_type_subnet; -omapi_object_type_t *dhcp_type_control; -dhcp_control_object_t *dhcp_control_object; - -void dhcp_common_objects_setup () -{ - isc_result_t status; - - status = omapi_object_type_register (&dhcp_type_control, - "control", - dhcp_control_set_value, - dhcp_control_get_value, - dhcp_control_destroy, - dhcp_control_signal_handler, - dhcp_control_stuff_values, - dhcp_control_lookup, - dhcp_control_create, - dhcp_control_remove, 0, 0, 0, - sizeof (dhcp_control_object_t), - 0, RC_MISC); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register control object type: %s", - isc_result_totext (status)); - status = dhcp_control_allocate (&dhcp_control_object, MDL); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't make initial control object: %s", - isc_result_totext (status)); - dhcp_control_object -> state = server_startup; - - status = omapi_object_type_register (&dhcp_type_group, - "group", - dhcp_group_set_value, - dhcp_group_get_value, - dhcp_group_destroy, - dhcp_group_signal_handler, - dhcp_group_stuff_values, - dhcp_group_lookup, - dhcp_group_create, - dhcp_group_remove, 0, 0, 0, - sizeof (struct group_object), 0, - RC_MISC); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register group object type: %s", - isc_result_totext (status)); - - status = omapi_object_type_register (&dhcp_type_subnet, - "subnet", - dhcp_subnet_set_value, - dhcp_subnet_get_value, - dhcp_subnet_destroy, - dhcp_subnet_signal_handler, - dhcp_subnet_stuff_values, - dhcp_subnet_lookup, - dhcp_subnet_create, - dhcp_subnet_remove, 0, 0, 0, - sizeof (struct subnet), 0, - RC_MISC); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register subnet object type: %s", - isc_result_totext (status)); - - status = omapi_object_type_register - (&dhcp_type_shared_network, - "shared-network", - dhcp_shared_network_set_value, - dhcp_shared_network_get_value, - dhcp_shared_network_destroy, - dhcp_shared_network_signal_handler, - dhcp_shared_network_stuff_values, - dhcp_shared_network_lookup, - dhcp_shared_network_create, - dhcp_shared_network_remove, 0, 0, 0, - sizeof (struct shared_network), 0, RC_MISC); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register shared network object type: %s", - isc_result_totext (status)); - - interface_setup (); -} - -isc_result_t dhcp_group_set_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_typed_data_t *value) -{ - struct group_object *group; - isc_result_t status; - int foo; - - if (h -> type != dhcp_type_group) - return ISC_R_INVALIDARG; - group = (struct group_object *)h; - - /* XXX For now, we can only set these values on new group objects. - XXX Soon, we need to be able to update group objects. */ - if (!omapi_ds_strcmp (name, "name")) { - if (group -> name) - return ISC_R_EXISTS; - if (value -> type == omapi_datatype_data || - value -> type == omapi_datatype_string) { - group -> name = dmalloc (value -> u.buffer.len + 1, - MDL); - if (!group -> name) - return ISC_R_NOMEMORY; - memcpy (group -> name, - value -> u.buffer.value, - value -> u.buffer.len); - group -> name [value -> u.buffer.len] = 0; - } else - return ISC_R_INVALIDARG; - return ISC_R_SUCCESS; - } - - if (!omapi_ds_strcmp (name, "statements")) { - if (group -> group && group -> group -> statements) - return ISC_R_EXISTS; - if (!group -> group) { - if (!clone_group (&group -> group, root_group, MDL)) - return ISC_R_NOMEMORY; - } - if (value -> type == omapi_datatype_data || - value -> type == omapi_datatype_string) { - struct parse *parse; - int lose = 0; - parse = (struct parse *)0; - status = new_parse (&parse, -1, - (char *)value -> u.buffer.value, - value -> u.buffer.len, - "network client", 0); - if (status != ISC_R_SUCCESS) - return status; - if (!(parse_executable_statements - (&group -> group -> statements, parse, &lose, - context_any))) { - end_parse (&parse); - return ISC_R_BADPARSE; - } - end_parse (&parse); - return ISC_R_SUCCESS; - } else - return ISC_R_INVALIDARG; - } - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> set_value) { - status = ((*(h -> inner -> type -> set_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED) - return status; - } - - return ISC_R_NOTFOUND; -} - - -isc_result_t dhcp_group_get_value (omapi_object_t *h, omapi_object_t *id, - omapi_data_string_t *name, - omapi_value_t **value) -{ - struct group_object *group; - isc_result_t status; - struct data_string ip_addrs; - - if (h -> type != dhcp_type_group) - return ISC_R_INVALIDARG; - group = (struct group_object *)h; - - if (!omapi_ds_strcmp (name, "name")) - return omapi_make_string_value (value, - name, group -> name, MDL); - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> get_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_group_destroy (omapi_object_t *h, const char *file, int line) -{ - struct group_object *group, *t; - isc_result_t status; - - if (h -> type != dhcp_type_group) - return ISC_R_INVALIDARG; - group = (struct group_object *)h; - - if (group -> name) { - if (group_name_hash) { - t = (struct group_object *)0; - if (group_hash_lookup (&t, group_name_hash, - group -> name, - strlen (group -> name), MDL)) { - group_hash_delete (group_name_hash, - group -> name, - strlen (group -> name), - MDL); - group_object_dereference (&t, MDL); - } - } - dfree (group -> name, file, line); - group -> name = (char *)0; - } - if (group -> group) - group_dereference (&group -> group, MDL); - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_group_signal_handler (omapi_object_t *h, - const char *name, va_list ap) -{ - struct group_object *group, *t; - isc_result_t status; - int updatep = 0; - - if (h -> type != dhcp_type_group) - return ISC_R_INVALIDARG; - group = (struct group_object *)h; - - if (!strcmp (name, "updated")) { - /* A group object isn't valid if a subgroup hasn't yet been - associated with it. */ - if (!group -> group) - return ISC_R_INVALIDARG; - - /* Group objects always have to have names. */ - if (!group -> name) { - char hnbuf [64]; - sprintf (hnbuf, "ng%08lx%08lx", - (unsigned long)cur_time, - (unsigned long)group); - group -> name = dmalloc (strlen (hnbuf) + 1, MDL); - if (!group -> name) - return ISC_R_NOMEMORY; - strcpy (group -> name, hnbuf); - } - - supersede_group (group, 1); - updatep = 1; - } - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> signal_handler)) - (h -> inner, name, ap)); - if (status == ISC_R_SUCCESS) - return status; - } - if (updatep) - return ISC_R_SUCCESS; - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_group_stuff_values (omapi_object_t *c, - omapi_object_t *id, - omapi_object_t *h) -{ - struct group_object *group; - isc_result_t status; - - if (h -> type != dhcp_type_group) - return ISC_R_INVALIDARG; - group = (struct group_object *)h; - - /* Write out all the values. */ - if (group -> name) { - status = omapi_connection_put_name (c, "name"); - if (status != ISC_R_SUCCESS) - return status; - status = omapi_connection_put_string (c, group -> name); - if (status != ISC_R_SUCCESS) - return status; - } - - /* Write out the inner object, if any. */ - if (h -> inner && h -> inner -> type -> stuff_values) { - status = ((*(h -> inner -> type -> stuff_values)) - (c, id, h -> inner)); - if (status == ISC_R_SUCCESS) - return status; - } - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_group_lookup (omapi_object_t **lp, - omapi_object_t *id, omapi_object_t *ref) -{ - omapi_value_t *tv = (omapi_value_t *)0; - isc_result_t status; - struct group_object *group; - - if (!ref) - return ISC_R_NOKEYS; - - /* First see if we were sent a handle. */ - status = omapi_get_value_str (ref, id, "handle", &tv); - if (status == ISC_R_SUCCESS) { - status = omapi_handle_td_lookup (lp, tv -> value); - - omapi_value_dereference (&tv, MDL); - if (status != ISC_R_SUCCESS) - return status; - - /* Don't return the object if the type is wrong. */ - if ((*lp) -> type != dhcp_type_group) { - omapi_object_dereference (lp, MDL); - return ISC_R_INVALIDARG; - } - } - - /* Now look for a name. */ - status = omapi_get_value_str (ref, id, "name", &tv); - if (status == ISC_R_SUCCESS) { - group = (struct group_object *)0; - if (group_name_hash && - group_hash_lookup (&group, group_name_hash, - (const char *) - tv -> value -> u.buffer.value, - tv -> value -> u.buffer.len, MDL)) { - omapi_value_dereference (&tv, MDL); - - if (*lp && *lp != (omapi_object_t *)group) { - group_object_dereference (&group, MDL); - omapi_object_dereference (lp, MDL); - return ISC_R_KEYCONFLICT; - } else if (!*lp) { - /* XXX fix so that hash lookup itself creates - XXX the reference. */ - omapi_object_reference (lp, - (omapi_object_t *)group, - MDL); - group_object_dereference (&group, MDL); - } - } else if (!*lp) - return ISC_R_NOTFOUND; - } - - /* If we get to here without finding a group, no valid key was - specified. */ - if (!*lp) - return ISC_R_NOKEYS; - - if (((struct group_object *)(*lp)) -> flags & GROUP_OBJECT_DELETED) { - omapi_object_dereference (lp, MDL); - return ISC_R_NOTFOUND; - } - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_group_create (omapi_object_t **lp, - omapi_object_t *id) -{ - struct group_object *group; - isc_result_t status; - group = (struct group_object *)0; - - status = group_object_allocate (&group, MDL); - if (status != ISC_R_SUCCESS) - return status; - group -> flags = GROUP_OBJECT_DYNAMIC; - status = omapi_object_reference (lp, (omapi_object_t *)group, MDL); - group_object_dereference (&group, MDL); - return status; -} - -isc_result_t dhcp_group_remove (omapi_object_t *lp, - omapi_object_t *id) -{ - struct group_object *group; - isc_result_t status; - if (lp -> type != dhcp_type_group) - return ISC_R_INVALIDARG; - group = (struct group_object *)lp; - - group -> flags |= GROUP_OBJECT_DELETED; - if (group_write_hook) { - if (!(*group_write_hook) (group)) - return ISC_R_IOERROR; - } - - status = dhcp_group_destroy ((omapi_object_t *)group, MDL); - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_control_set_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_typed_data_t *value) -{ - dhcp_control_object_t *control; - isc_result_t status; - int foo; - unsigned long newstate; - - if (h -> type != dhcp_type_control) - return ISC_R_INVALIDARG; - control = (dhcp_control_object_t *)h; - - if (!omapi_ds_strcmp (name, "state")) { - status = omapi_get_int_value (&newstate, value); - if (status != ISC_R_SUCCESS) - return status; - status = dhcp_set_control_state (control -> state, newstate); - if (status == ISC_R_SUCCESS) - control -> state = value -> u.integer; - return status; - } - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> set_value) { - status = ((*(h -> inner -> type -> set_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED) - return status; - } - - return ISC_R_NOTFOUND; -} - - -isc_result_t dhcp_control_get_value (omapi_object_t *h, omapi_object_t *id, - omapi_data_string_t *name, - omapi_value_t **value) -{ - dhcp_control_object_t *control; - isc_result_t status; - struct data_string ip_addrs; - - if (h -> type != dhcp_type_control) - return ISC_R_INVALIDARG; - control = (dhcp_control_object_t *)h; - - if (!omapi_ds_strcmp (name, "state")) - return omapi_make_int_value (value, - name, (int)control -> state, MDL); - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> get_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_control_destroy (omapi_object_t *h, - const char *file, int line) -{ - dhcp_control_object_t *control, *t; - isc_result_t status; - - if (h -> type != dhcp_type_control) - return ISC_R_INVALIDARG; - - /* Can't destroy the control object. */ - return ISC_R_NOPERM; -} - -isc_result_t dhcp_control_signal_handler (omapi_object_t *h, - const char *name, va_list ap) -{ - dhcp_control_object_t *control, *t; - isc_result_t status; - int updatep = 0; - - if (h -> type != dhcp_type_control) - return ISC_R_INVALIDARG; - control = (dhcp_control_object_t *)h; - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> signal_handler)) - (h -> inner, name, ap)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_control_stuff_values (omapi_object_t *c, - omapi_object_t *id, - omapi_object_t *h) -{ - dhcp_control_object_t *control; - isc_result_t status; - - if (h -> type != dhcp_type_control) - return ISC_R_INVALIDARG; - control = (dhcp_control_object_t *)h; - - /* Write out all the values. */ - status = omapi_connection_put_name (c, "state"); - if (status != ISC_R_SUCCESS) - return status; - status = omapi_connection_put_uint32 (c, sizeof (u_int32_t)); - if (status != ISC_R_SUCCESS) - return status; - status = omapi_connection_put_uint32 (c, control -> state); - if (status != ISC_R_SUCCESS) - return status; - - /* Write out the inner object, if any. */ - if (h -> inner && h -> inner -> type -> stuff_values) { - status = ((*(h -> inner -> type -> stuff_values)) - (c, id, h -> inner)); - if (status == ISC_R_SUCCESS) - return status; - } - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_control_lookup (omapi_object_t **lp, - omapi_object_t *id, omapi_object_t *ref) -{ - omapi_value_t *tv = (omapi_value_t *)0; - isc_result_t status; - dhcp_control_object_t *control; - - /* First see if we were sent a handle. */ - if (ref) { - status = omapi_get_value_str (ref, id, "handle", &tv); - if (status == ISC_R_SUCCESS) { - status = omapi_handle_td_lookup (lp, tv -> value); - - omapi_value_dereference (&tv, MDL); - if (status != ISC_R_SUCCESS) - return status; - - /* Don't return the object if the type is wrong. */ - if ((*lp) -> type != dhcp_type_control) { - omapi_object_dereference (lp, MDL); - return ISC_R_INVALIDARG; - } - } - } - - /* Otherwise, stop playing coy - there's only one control object, - so we can just return it. */ - dhcp_control_reference ((dhcp_control_object_t **)lp, - dhcp_control_object, MDL); - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_control_create (omapi_object_t **lp, - omapi_object_t *id) -{ - /* Can't create a control object - there can be only one. */ - return ISC_R_NOPERM; -} - -isc_result_t dhcp_control_remove (omapi_object_t *lp, - omapi_object_t *id) -{ - /* Form is emptiness; emptiness form. The control object - cannot go out of existance. */ - return ISC_R_NOPERM; -} - -isc_result_t dhcp_subnet_set_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_typed_data_t *value) -{ - struct subnet *subnet; - isc_result_t status; - int foo; - - if (h -> type != dhcp_type_subnet) - return ISC_R_INVALIDARG; - subnet = (struct subnet *)h; - - /* No values to set yet. */ - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> set_value) { - status = ((*(h -> inner -> type -> set_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED) - return status; - } - - return ISC_R_NOTFOUND; -} - - -isc_result_t dhcp_subnet_get_value (omapi_object_t *h, omapi_object_t *id, - omapi_data_string_t *name, - omapi_value_t **value) -{ - struct subnet *subnet; - isc_result_t status; - - if (h -> type != dhcp_type_subnet) - return ISC_R_INVALIDARG; - subnet = (struct subnet *)h; - - /* No values to get yet. */ - - /* Try to find some inner object that can provide the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> get_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_subnet_destroy (omapi_object_t *h, const char *file, int line) -{ - struct subnet *subnet; - isc_result_t status; - - if (h -> type != dhcp_type_subnet) - return ISC_R_INVALIDARG; - subnet = (struct subnet *)h; - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) - if (subnet -> next_subnet) - subnet_dereference (&subnet -> next_subnet, file, line); - if (subnet -> next_sibling) - subnet_dereference (&subnet -> next_sibling, file, line); - if (subnet -> shared_network) - shared_network_dereference (&subnet -> shared_network, - file, line); - if (subnet -> interface) - interface_dereference (&subnet -> interface, file, line); - if (subnet -> group) - group_dereference (&subnet -> group, file, line); -#endif - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_subnet_signal_handler (omapi_object_t *h, - const char *name, va_list ap) -{ - struct subnet *subnet; - isc_result_t status; - int updatep = 0; - - if (h -> type != dhcp_type_subnet) - return ISC_R_INVALIDARG; - subnet = (struct subnet *)h; - - /* Can't write subnets yet. */ - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> signal_handler)) - (h -> inner, name, ap)); - if (status == ISC_R_SUCCESS) - return status; - } - if (updatep) - return ISC_R_SUCCESS; - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_subnet_stuff_values (omapi_object_t *c, - omapi_object_t *id, - omapi_object_t *h) -{ - struct subnet *subnet; - isc_result_t status; - - if (h -> type != dhcp_type_subnet) - return ISC_R_INVALIDARG; - subnet = (struct subnet *)h; - - /* Can't stuff subnet values yet. */ - - /* Write out the inner object, if any. */ - if (h -> inner && h -> inner -> type -> stuff_values) { - status = ((*(h -> inner -> type -> stuff_values)) - (c, id, h -> inner)); - if (status == ISC_R_SUCCESS) - return status; - } - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_subnet_lookup (omapi_object_t **lp, - omapi_object_t *id, - omapi_object_t *ref) -{ - omapi_value_t *tv = (omapi_value_t *)0; - isc_result_t status; - struct subnet *subnet; - - /* Can't look up subnets yet. */ - - /* If we get to here without finding a subnet, no valid key was - specified. */ - if (!*lp) - return ISC_R_NOKEYS; - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_subnet_create (omapi_object_t **lp, - omapi_object_t *id) -{ - return ISC_R_NOTIMPLEMENTED; -} - -isc_result_t dhcp_subnet_remove (omapi_object_t *lp, - omapi_object_t *id) -{ - return ISC_R_NOTIMPLEMENTED; -} - -isc_result_t dhcp_shared_network_set_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_typed_data_t *value) -{ - struct shared_network *shared_network; - isc_result_t status; - int foo; - - if (h -> type != dhcp_type_shared_network) - return ISC_R_INVALIDARG; - shared_network = (struct shared_network *)h; - - /* No values to set yet. */ - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> set_value) { - status = ((*(h -> inner -> type -> set_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED) - return status; - } - - return ISC_R_NOTFOUND; -} - - -isc_result_t dhcp_shared_network_get_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_value_t **value) -{ - struct shared_network *shared_network; - isc_result_t status; - - if (h -> type != dhcp_type_shared_network) - return ISC_R_INVALIDARG; - shared_network = (struct shared_network *)h; - - /* No values to get yet. */ - - /* Try to find some inner object that can provide the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> get_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_shared_network_destroy (omapi_object_t *h, - const char *file, int line) -{ - struct shared_network *shared_network; - isc_result_t status; - - if (h -> type != dhcp_type_shared_network) - return ISC_R_INVALIDARG; - shared_network = (struct shared_network *)h; - -#if defined (DEBUG_MEMORY_LEAKAGE) || \ - defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) - if (shared_network -> next) - shared_network_dereference (&shared_network -> next, - file, line); - if (shared_network -> name) { - dfree (shared_network -> name, file, line); - shared_network -> name = 0; - } - if (shared_network -> subnets) - subnet_dereference (&shared_network -> subnets, file, line); - if (shared_network -> interface) - interface_dereference (&shared_network -> interface, - file, line); - if (shared_network -> pools) - omapi_object_dereference ((omapi_object_t **) - &shared_network -> pools, file, line); - if (shared_network -> group) - group_dereference (&shared_network -> group, file, line); -#if defined (FAILOVER_PROTOCOL) - if (shared_network -> failover_peer) - omapi_object_dereference ((omapi_object_t **) - &shared_network -> failover_peer, - file, line); -#endif -#endif /* DEBUG_MEMORY_LEAKAGE */ - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *h, - const char *name, - va_list ap) -{ - struct shared_network *shared_network; - isc_result_t status; - int updatep = 0; - - if (h -> type != dhcp_type_shared_network) - return ISC_R_INVALIDARG; - shared_network = (struct shared_network *)h; - - /* Can't write shared_networks yet. */ - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> signal_handler)) - (h -> inner, name, ap)); - if (status == ISC_R_SUCCESS) - return status; - } - if (updatep) - return ISC_R_SUCCESS; - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *c, - omapi_object_t *id, - omapi_object_t *h) -{ - struct shared_network *shared_network; - isc_result_t status; - - if (h -> type != dhcp_type_shared_network) - return ISC_R_INVALIDARG; - shared_network = (struct shared_network *)h; - - /* Can't stuff shared_network values yet. */ - - /* Write out the inner object, if any. */ - if (h -> inner && h -> inner -> type -> stuff_values) { - status = ((*(h -> inner -> type -> stuff_values)) - (c, id, h -> inner)); - if (status == ISC_R_SUCCESS) - return status; - } - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_shared_network_lookup (omapi_object_t **lp, - omapi_object_t *id, - omapi_object_t *ref) -{ - omapi_value_t *tv = (omapi_value_t *)0; - isc_result_t status; - struct shared_network *shared_network; - - /* Can't look up shared_networks yet. */ - - /* If we get to here without finding a shared_network, no valid key was - specified. */ - if (!*lp) - return ISC_R_NOKEYS; - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_shared_network_create (omapi_object_t **lp, - omapi_object_t *id) -{ - return ISC_R_NOTIMPLEMENTED; -} - -isc_result_t dhcp_shared_network_remove (omapi_object_t *lp, - omapi_object_t *id) -{ - return ISC_R_NOTIMPLEMENTED; -} - diff --git a/contrib/isc-dhcp/common/conflex.c b/contrib/isc-dhcp/common/conflex.c deleted file mode 100644 index a8a5039..0000000 --- a/contrib/isc-dhcp/common/conflex.c +++ /dev/null @@ -1,1073 +0,0 @@ -/* conflex.c - - Lexical scanner for dhcpd config file... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: conflex.c,v 1.92.2.7 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include <ctype.h> - -static int get_char PROTO ((struct parse *)); -static enum dhcp_token get_token PROTO ((struct parse *)); -static void skip_to_eol PROTO ((struct parse *)); -static enum dhcp_token read_string PROTO ((struct parse *)); -static enum dhcp_token read_number PROTO ((int, struct parse *)); -static enum dhcp_token read_num_or_name PROTO ((int, struct parse *)); -static enum dhcp_token intern PROTO ((char *, enum dhcp_token)); - -isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp) - struct parse **cfile; - int file; - char *inbuf; - unsigned buflen; - const char *name; - int eolp; -{ - struct parse *tmp; - - tmp = dmalloc (sizeof (struct parse), MDL); - if (!tmp) - return ISC_R_NOMEMORY; - memset (tmp, 0, sizeof *tmp); - - tmp -> token = 0; - tmp -> tlname = name; - tmp -> lpos = tmp -> line = 1; - tmp -> cur_line = tmp -> line1; - tmp -> prev_line = tmp -> line2; - tmp -> token_line = tmp -> cur_line; - tmp -> cur_line [0] = tmp -> prev_line [0] = 0; - tmp -> warnings_occurred = 0; - tmp -> file = file; - tmp -> eol_token = eolp; - - tmp -> bufix = 0; - tmp -> buflen = buflen; - if (inbuf) { - tmp -> bufsiz = 0; - tmp -> inbuf = inbuf; - } else { - tmp -> inbuf = dmalloc (8192, MDL); - if (!tmp -> inbuf) { - dfree (tmp, MDL); - return ISC_R_NOMEMORY; - } - tmp -> bufsiz = 8192; - } - - *cfile = tmp; - return ISC_R_SUCCESS; -} - -isc_result_t end_parse (cfile) - struct parse **cfile; -{ - if ((*cfile) -> bufsiz) - dfree ((*cfile) -> inbuf, MDL); - dfree (*cfile, MDL); - *cfile = (struct parse *)0; - return ISC_R_SUCCESS; -} - -static int get_char (cfile) - struct parse *cfile; -{ - /* My kingdom for WITH... */ - int c; - - if (cfile -> bufix == cfile -> buflen) { - if (cfile -> file != -1) { - cfile -> buflen = - read (cfile -> file, - cfile -> inbuf, cfile -> bufsiz); - if (cfile -> buflen == 0) { - c = EOF; - cfile -> bufix = 0; - } else if (cfile -> buflen < 0) { - c = EOF; - cfile -> bufix = cfile -> buflen = 0; - } else { - c = cfile -> inbuf [0]; - cfile -> bufix = 1; - } - } else - c = EOF; - } else { - c = cfile -> inbuf [cfile -> bufix]; - cfile -> bufix++; - } - - if (!cfile -> ugflag) { - if (c == EOL) { - if (cfile -> cur_line == cfile -> line1) { - cfile -> cur_line = cfile -> line2; - cfile -> prev_line = cfile -> line1; - } else { - cfile -> cur_line = cfile -> line1; - cfile -> prev_line = cfile -> line2; - } - cfile -> line++; - cfile -> lpos = 1; - cfile -> cur_line [0] = 0; - } else if (c != EOF) { - if (cfile -> lpos <= 80) { - cfile -> cur_line [cfile -> lpos - 1] = c; - cfile -> cur_line [cfile -> lpos] = 0; - } - cfile -> lpos++; - } - } else - cfile -> ugflag = 0; - return c; -} - -static enum dhcp_token get_token (cfile) - struct parse *cfile; -{ - int c; - enum dhcp_token ttok; - static char tb [2]; - int l, p, u; - - do { - l = cfile -> line; - p = cfile -> lpos; - u = cfile -> ugflag; - - c = get_char (cfile); -#ifdef OLD_LEXER - if (c == '\n' && p == 1 && !u - && cfile -> comment_index < sizeof cfile -> comments) - cfile -> comments [cfile -> comment_index++] = '\n'; -#endif - - if (!(c == '\n' && cfile -> eol_token) - && isascii (c) && isspace (c)) - continue; - if (c == '#') { -#ifdef OLD_LEXER - if (cfile -> comment_index < sizeof cfile -> comments) - cfile -> comments [cfile -> comment_index++] = '#'; -#endif - skip_to_eol (cfile); - continue; - } - if (c == '"') { - cfile -> lexline = l; - cfile -> lexchar = p; - ttok = read_string (cfile); - break; - } - if ((isascii (c) && isdigit (c)) || c == '-') { - cfile -> lexline = l; - cfile -> lexchar = p; - ttok = read_number (c, cfile); - break; - } else if (isascii (c) && isalpha (c)) { - cfile -> lexline = l; - cfile -> lexchar = p; - ttok = read_num_or_name (c, cfile); - break; - } else if (c == EOF) { - ttok = END_OF_FILE; - cfile -> tlen = 0; - break; - } else { - cfile -> lexline = l; - cfile -> lexchar = p; - tb [0] = c; - tb [1] = 0; - cfile -> tval = tb; - cfile -> tlen = 1; - ttok = c; - break; - } - } while (1); - return ttok; -} - -enum dhcp_token next_token (rval, rlen, cfile) - const char **rval; - unsigned *rlen; - struct parse *cfile; -{ - int rv; - - if (cfile -> token) { - if (cfile -> lexline != cfile -> tline) - cfile -> token_line = cfile -> cur_line; - cfile -> lexchar = cfile -> tlpos; - cfile -> lexline = cfile -> tline; - rv = cfile -> token; - cfile -> token = 0; - } else { - rv = get_token (cfile); - cfile -> token_line = cfile -> cur_line; - } - if (rval) - *rval = cfile -> tval; - if (rlen) - *rlen = cfile -> tlen; -#ifdef DEBUG_TOKENS - fprintf (stderr, "%s:%d ", cfile -> tval, rv); -#endif - return rv; -} - -enum dhcp_token peek_token (rval, rlen, cfile) - const char **rval; - unsigned int *rlen; - struct parse *cfile; -{ - int x; - - if (!cfile -> token) { - cfile -> tlpos = cfile -> lexchar; - cfile -> tline = cfile -> lexline; - cfile -> token = get_token (cfile); - if (cfile -> lexline != cfile -> tline) - cfile -> token_line = cfile -> prev_line; - - x = cfile -> lexchar; - cfile -> lexchar = cfile -> tlpos; - cfile -> tlpos = x; - - x = cfile -> lexline; - cfile -> lexline = cfile -> tline; - cfile -> tline = x; - } - if (rval) - *rval = cfile -> tval; - if (rlen) - *rlen = cfile -> tlen; -#ifdef DEBUG_TOKENS - fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token); -#endif - return cfile -> token; -} - -static void skip_to_eol (cfile) - struct parse *cfile; -{ - int c; - do { - c = get_char (cfile); - if (c == EOF) - return; -#ifdef OLD_LEXER - if (cfile -> comment_index < sizeof (cfile -> comments)) - comments [cfile -> comment_index++] = c; -#endif - if (c == EOL) { - return; - } - } while (1); -} - -static enum dhcp_token read_string (cfile) - struct parse *cfile; -{ - int i; - int bs = 0; - int c; - int value; - int hex; - - for (i = 0; i < sizeof cfile -> tokbuf; i++) { - again: - c = get_char (cfile); - if (c == EOF) { - parse_warn (cfile, "eof in string constant"); - break; - } - if (bs == 1) { - switch (c) { - case 't': - cfile -> tokbuf [i] = '\t'; - break; - case 'r': - cfile -> tokbuf [i] = '\r'; - break; - case 'n': - cfile -> tokbuf [i] = '\n'; - break; - case 'b': - cfile -> tokbuf [i] = '\b'; - break; - case '0': - case '1': - case '2': - case '3': - hex = 0; - value = c - '0'; - ++bs; - goto again; - case 'x': - hex = 1; - value = 0; - ++bs; - goto again; - default: - cfile -> tokbuf [i] = c; - bs = 0; - break; - } - bs = 0; - } else if (bs > 1) { - if (hex) { - if (c >= '0' && c <= '9') { - value = value * 16 + (c - '0'); - } else if (c >= 'a' && c <= 'f') { - value = value * 16 + (c - 'a' + 10); - } else if (c >= 'A' && c <= 'F') { - value = value * 16 + (c - 'A' + 10); - } else { - parse_warn (cfile, - "invalid hex digit: %x", - c); - bs = 0; - continue; - } - if (++bs == 4) { - cfile -> tokbuf [i] = value; - bs = 0; - } else - goto again; - } else { - if (c >= '0' && c <= '9') { - value = value * 8 + (c - '0'); - } else { - if (value != 0) { - parse_warn (cfile, - "invalid octal digit %x", - c); - continue; - } else - cfile -> tokbuf [i] = 0; - bs = 0; - } - if (++bs == 4) { - cfile -> tokbuf [i] = value; - bs = 0; - } else - goto again; - } - } else if (c == '\\') { - bs = 1; - goto again; - } else if (c == '"') - break; - else - cfile -> tokbuf [i] = c; - } - /* Normally, I'd feel guilty about this, but we're talking about - strings that'll fit in a DHCP packet here... */ - if (i == sizeof cfile -> tokbuf) { - parse_warn (cfile, - "string constant larger than internal buffer"); - --i; - } - cfile -> tokbuf [i] = 0; - cfile -> tlen = i; - cfile -> tval = cfile -> tokbuf; - return STRING; -} - -static enum dhcp_token read_number (c, cfile) - int c; - struct parse *cfile; -{ - int seenx = 0; - int i = 0; - int token = NUMBER; - - cfile -> tokbuf [i++] = c; - for (; i < sizeof cfile -> tokbuf; i++) { - c = get_char (cfile); - if (!seenx && c == 'x') { - seenx = 1; -#ifndef OLD_LEXER - } else if (isascii (c) && !isxdigit (c) && - (c == '-' || c == '_' || isalpha (c))) { - token = NAME; - } else if (isascii (c) && !isdigit (c) && isxdigit (c)) { - token = NUMBER_OR_NAME; -#endif - } else if (!isascii (c) || !isxdigit (c)) { - if (c != EOF) { - cfile -> bufix--; - cfile -> ugflag = 1; - } - break; - } - cfile -> tokbuf [i] = c; - } - if (i == sizeof cfile -> tokbuf) { - parse_warn (cfile, - "numeric token larger than internal buffer"); - --i; - } - cfile -> tokbuf [i] = 0; - cfile -> tlen = i; - cfile -> tval = cfile -> tokbuf; - return token; -} - -static enum dhcp_token read_num_or_name (c, cfile) - int c; - struct parse *cfile; -{ - int i = 0; - enum dhcp_token rv = NUMBER_OR_NAME; - cfile -> tokbuf [i++] = c; - for (; i < sizeof cfile -> tokbuf; i++) { - c = get_char (cfile); - if (!isascii (c) || - (c != '-' && c != '_' && !isalnum (c))) { - if (c != EOF) { - cfile -> bufix--; - cfile -> ugflag = 1; - } - break; - } - if (!isxdigit (c)) - rv = NAME; - cfile -> tokbuf [i] = c; - } - if (i == sizeof cfile -> tokbuf) { - parse_warn (cfile, "token larger than internal buffer"); - --i; - } - cfile -> tokbuf [i] = 0; - cfile -> tlen = i; - cfile -> tval = cfile -> tokbuf; - return intern (cfile -> tval, rv); -} - -static enum dhcp_token intern (atom, dfv) - char *atom; - enum dhcp_token dfv; -{ - if (!isascii (atom [0])) - return dfv; - - switch (tolower (atom [0])) { - case '-': - if (atom [1] == 0) - return MINUS; - break; - - case 'a': - if (!strncasecmp (atom + 1, "uth", 3)) { - if (!strncasecmp (atom + 3, "uthenticat", 10)) { - if (!strcasecmp (atom + 13, "ed")) - return AUTHENTICATED; - if (!strcasecmp (atom + 13, "ion")) - return AUTHENTICATION; - break; - } - if (!strcasecmp (atom + 1, "uthoritative")) - return AUTHORITATIVE; - break; - } - if (!strcasecmp (atom + 1, "nd")) - return AND; - if (!strcasecmp (atom + 1, "ppend")) - return APPEND; - if (!strcasecmp (atom + 1, "llow")) - return ALLOW; - if (!strcasecmp (atom + 1, "lias")) - return ALIAS; - if (!strcasecmp (atom + 1, "lgorithm")) - return ALGORITHM; - if (!strcasecmp (atom + 1, "bandoned")) - return TOKEN_ABANDONED; - if (!strcasecmp (atom + 1, "dd")) - return TOKEN_ADD; - if (!strcasecmp (atom + 1, "ll")) - return ALL; - if (!strcasecmp (atom + 1, "t")) - return AT; - if (!strcasecmp (atom + 1, "rray")) - return ARRAY; - if (!strcasecmp (atom + 1, "ddress")) - return ADDRESS; - if (!strcasecmp (atom + 1, "ctive")) - return TOKEN_ACTIVE; - break; - case 'b': - if (!strcasecmp (atom + 1, "ackup")) - return TOKEN_BACKUP; - if (!strcasecmp (atom + 1, "ootp")) - return TOKEN_BOOTP; - if (!strcasecmp (atom + 1, "inding")) - return BINDING; - if (!strcasecmp (atom + 1, "inary-to-ascii")) - return BINARY_TO_ASCII; - if (!strcasecmp (atom + 1, "ackoff-cutoff")) - return BACKOFF_CUTOFF; - if (!strcasecmp (atom + 1, "ooting")) - return BOOTING; - if (!strcasecmp (atom + 1, "oot-unknown-clients")) - return BOOT_UNKNOWN_CLIENTS; - if (!strcasecmp (atom + 1, "reak")) - return BREAK; - if (!strcasecmp (atom + 1, "illing")) - return BILLING; - if (!strcasecmp (atom + 1, "oolean")) - return BOOLEAN; - if (!strcasecmp (atom + 1, "alance")) - return BALANCE; - if (!strcasecmp (atom + 1, "ound")) - return BOUND; - break; - case 'c': - if (!strcasecmp (atom + 1, "ase")) - return CASE; - if (!strcasecmp (atom + 1, "ommit")) - return COMMIT; - if (!strcasecmp (atom + 1, "ode")) - return CODE; - if (!strcasecmp (atom + 1, "onfig-option")) - return CONFIG_OPTION; - if (!strcasecmp (atom + 1, "heck")) - return CHECK; - if (!strcasecmp (atom + 1, "lass")) - return CLASS; - if (!strcasecmp (atom + 1, "lose")) - return TOKEN_CLOSE; - if (!strcasecmp (atom + 1, "reate")) - return TOKEN_CREATE; - if (!strcasecmp (atom + 1, "iaddr")) - return CIADDR; - if (!strncasecmp (atom + 1, "lient", 5)) { - if (!strcasecmp (atom + 6, "-identifier")) - return CLIENT_IDENTIFIER; - if (!strcasecmp (atom + 6, "-hostname")) - return CLIENT_HOSTNAME; - if (!strcasecmp (atom + 6, "-state")) - return CLIENT_STATE; - if (!strcasecmp (atom + 6, "-updates")) - return CLIENT_UPDATES; - if (!strcasecmp (atom + 6, "s")) - return CLIENTS; - } - if (!strcasecmp (atom + 1, "oncat")) - return CONCAT; - if (!strcasecmp (atom + 1, "onnect")) - return CONNECT; - if (!strcasecmp (atom + 1, "ommunications-interrupted")) - return COMMUNICATIONS_INTERRUPTED; - if (!strcasecmp (atom + 1, "ltt")) - return CLTT; - break; - case 'd': - if (!strcasecmp (atom + 1, "ns-update")) - return DNS_UPDATE; - if (!strcasecmp (atom + 1, "ns-delete")) - return DNS_DELETE; - if (!strcasecmp (atom + 1, "omain")) - return DOMAIN; - if (!strcasecmp (atom + 1, "omain-name")) - return DOMAIN_NAME; - if (!strcasecmp (atom + 1, "o-forward-update")) - return DO_FORWARD_UPDATE; - if (!strcasecmp (atom + 1, "ebug")) - return TOKEN_DEBUG; - if (!strcasecmp (atom + 1, "eny")) - return DENY; - if (!strcasecmp (atom + 1, "eleted")) - return TOKEN_DELETED; - if (!strcasecmp (atom + 1, "elete")) - return TOKEN_DELETE; - if (!strncasecmp (atom + 1, "efault", 6)) { - if (!atom [7]) - return DEFAULT; - if (!strcasecmp (atom + 7, "-lease-time")) - return DEFAULT_LEASE_TIME; - break; - } - if (!strncasecmp (atom + 1, "ynamic", 6)) { - if (!atom [7]) - return DYNAMIC; - if (!strncasecmp (atom + 7, "-bootp", 6)) { - if (!atom [13]) - return DYNAMIC_BOOTP; - if (!strcasecmp (atom + 13, "-lease-cutoff")) - return DYNAMIC_BOOTP_LEASE_CUTOFF; - if (!strcasecmp (atom + 13, "-lease-length")) - return DYNAMIC_BOOTP_LEASE_LENGTH; - break; - } - } - if (!strcasecmp (atom + 1, "uplicates")) - return DUPLICATES; - if (!strcasecmp (atom + 1, "eclines")) - return DECLINES; - if (!strncasecmp (atom + 1, "efine", 5)) { - if (!strcasecmp (atom + 6, "d")) - return DEFINED; - if (!atom [6]) - return DEFINE; - } - break; - case 'e': - if (isascii (atom [1]) && tolower (atom [1]) == 'x') { - if (!strcasecmp (atom + 2, "tract-int")) - return EXTRACT_INT; - if (!strcasecmp (atom + 2, "ists")) - return EXISTS; - if (!strcasecmp (atom + 2, "piry")) - return EXPIRY; - if (!strcasecmp (atom + 2, "pire")) - return EXPIRE; - if (!strcasecmp (atom + 2, "pired")) - return TOKEN_EXPIRED; - } - if (!strcasecmp (atom + 1, "ncode-int")) - return ENCODE_INT; - if (!strcasecmp (atom + 1, "thernet")) - return ETHERNET; - if (!strcasecmp (atom + 1, "nds")) - return ENDS; - if (!strncasecmp (atom + 1, "ls", 2)) { - if (!strcasecmp (atom + 3, "e")) - return ELSE; - if (!strcasecmp (atom + 3, "if")) - return ELSIF; - break; - } - if (!strcasecmp (atom + 1, "rror")) - return ERROR; - if (!strcasecmp (atom + 1, "val")) - return EVAL; - if (!strcasecmp (atom + 1, "ncapsulate")) - return ENCAPSULATE; - break; - case 'f': - if (!strcasecmp (atom + 1, "atal")) - return FATAL; - if (!strcasecmp (atom + 1, "ilename")) - return FILENAME; - if (!strcasecmp (atom + 1, "ixed-address")) - return FIXED_ADDR; - if (!strcasecmp (atom + 1, "ddi")) - return FDDI; - if (!strcasecmp (atom + 1, "ormerr")) - return NS_FORMERR; - if (!strcasecmp (atom + 1, "unction")) - return FUNCTION; - if (!strcasecmp (atom + 1, "ailover")) - return FAILOVER; - if (!strcasecmp (atom + 1, "ree")) - return TOKEN_FREE; - break; - case 'g': - if (!strcasecmp (atom + 1, "iaddr")) - return GIADDR; - if (!strcasecmp (atom + 1, "roup")) - return GROUP; - if (!strcasecmp (atom + 1, "et-lease-hostnames")) - return GET_LEASE_HOSTNAMES; - break; - case 'h': - if (!strcasecmp (atom + 1, "ba")) - return HBA; - if (!strcasecmp (atom + 1, "ost")) - return HOST; - if (!strcasecmp (atom + 1, "ost-decl-name")) - return HOST_DECL_NAME; - if (!strcasecmp (atom + 1, "ardware")) - return HARDWARE; - if (!strcasecmp (atom + 1, "ostname")) - return HOSTNAME; - if (!strcasecmp (atom + 1, "elp")) - return TOKEN_HELP; - break; - case 'i': - if (!strcasecmp (atom + 1, "nclude")) - return INCLUDE; - if (!strcasecmp (atom + 1, "nteger")) - return INTEGER; - if (!strcasecmp (atom + 1, "nfinite")) - return INFINITE; - if (!strcasecmp (atom + 1, "nfo")) - return INFO; - if (!strcasecmp (atom + 1, "p-address")) - return IP_ADDRESS; - if (!strcasecmp (atom + 1, "nitial-interval")) - return INITIAL_INTERVAL; - if (!strcasecmp (atom + 1, "nterface")) - return INTERFACE; - if (!strcasecmp (atom + 1, "dentifier")) - return IDENTIFIER; - if (!strcasecmp (atom + 1, "f")) - return IF; - if (!strcasecmp (atom + 1, "s")) - return IS; - if (!strcasecmp (atom + 1, "gnore")) - return IGNORE; - break; - case 'k': - if (!strcasecmp (atom + 1, "nown")) - return KNOWN; - if (!strcasecmp (atom + 1, "ey")) - return KEY; - break; - case 'l': - if (!strcasecmp (atom + 1, "ease")) - return LEASE; - if (!strcasecmp (atom + 1, "eased-address")) - return LEASED_ADDRESS; - if (!strcasecmp (atom + 1, "ease-time")) - return LEASE_TIME; - if (!strcasecmp (atom + 1, "imit")) - return LIMIT; - if (!strcasecmp (atom + 1, "et")) - return LET; - if (!strcasecmp (atom + 1, "oad")) - return LOAD; - if (!strcasecmp (atom + 1, "og")) - return LOG; - break; - case 'm': - if (!strncasecmp (atom + 1, "ax", 2)) { - if (!atom [3]) - return TOKEN_MAX; - if (!strcasecmp (atom + 3, "-lease-time")) - return MAX_LEASE_TIME; - if (!strcasecmp (atom + 3, "-transmit-idle")) - return MAX_TRANSMIT_IDLE; - if (!strcasecmp (atom + 3, "-response-delay")) - return MAX_RESPONSE_DELAY; - if (!strcasecmp (atom + 3, "-unacked-updates")) - return MAX_UNACKED_UPDATES; - } - if (!strncasecmp (atom + 1, "in-", 3)) { - if (!strcasecmp (atom + 4, "lease-time")) - return MIN_LEASE_TIME; - if (!strcasecmp (atom + 4, "secs")) - return MIN_SECS; - break; - } - if (!strncasecmp (atom + 1, "edi", 3)) { - if (!strcasecmp (atom + 4, "a")) - return MEDIA; - if (!strcasecmp (atom + 4, "um")) - return MEDIUM; - break; - } - if (!strcasecmp (atom + 1, "atch")) - return MATCH; - if (!strcasecmp (atom + 1, "embers")) - return MEMBERS; - if (!strcasecmp (atom + 1, "y")) - return MY; - if (!strcasecmp (atom + 1, "clt")) - return MCLT; - break; - case 'n': - if (!strcasecmp (atom + 1, "ormal")) - return NORMAL; - if (!strcasecmp (atom + 1, "ameserver")) - return NAMESERVER; - if (!strcasecmp (atom + 1, "etmask")) - return NETMASK; - if (!strcasecmp (atom + 1, "ever")) - return NEVER; - if (!strcasecmp (atom + 1, "ext-server")) - return NEXT_SERVER; - if (!strcasecmp (atom + 1, "ot")) - return TOKEN_NOT; - if (!strcasecmp (atom + 1, "o")) - return NO; - if (!strcasecmp (atom + 1, "s-update")) - return NS_UPDATE; - if (!strcasecmp (atom + 1, "oerror")) - return NS_NOERROR; - if (!strcasecmp (atom + 1, "otauth")) - return NS_NOTAUTH; - if (!strcasecmp (atom + 1, "otimp")) - return NS_NOTIMP; - if (!strcasecmp (atom + 1, "otzone")) - return NS_NOTZONE; - if (!strcasecmp (atom + 1, "xdomain")) - return NS_NXDOMAIN; - if (!strcasecmp (atom + 1, "xrrset")) - return NS_NXRRSET; - if (!strcasecmp (atom + 1, "ull")) - return TOKEN_NULL; - if (!strcasecmp (atom + 1, "ext")) - return TOKEN_NEXT; - if (!strcasecmp (atom + 1, "ew")) - return TOKEN_NEW; - break; - case 'o': - if (!strcasecmp (atom + 1, "mapi")) - return OMAPI; - if (!strcasecmp (atom + 1, "r")) - return OR; - if (!strcasecmp (atom + 1, "n")) - return ON; - if (!strcasecmp (atom + 1, "pen")) - return TOKEN_OPEN; - if (!strcasecmp (atom + 1, "ption")) - return OPTION; - if (!strcasecmp (atom + 1, "ne-lease-per-client")) - return ONE_LEASE_PER_CLIENT; - if (!strcasecmp (atom + 1, "f")) - return OF; - if (!strcasecmp (atom + 1, "wner")) - return OWNER; - break; - case 'p': - if (!strcasecmp (atom + 1, "repend")) - return PREPEND; - if (!strcasecmp (atom + 1, "acket")) - return PACKET; - if (!strcasecmp (atom + 1, "ool")) - return POOL; - if (!strcasecmp (atom + 1, "seudo")) - return PSEUDO; - if (!strcasecmp (atom + 1, "eer")) - return PEER; - if (!strcasecmp (atom + 1, "rimary")) - return PRIMARY; - if (!strncasecmp (atom + 1, "artner", 6)) { - if (!atom [7]) - return PARTNER; - if (!strcasecmp (atom + 7, "-down")) - return PARTNER_DOWN; - } - if (!strcasecmp (atom + 1, "ort")) - return PORT; - if (!strcasecmp (atom + 1, "otential-conflict")) - return POTENTIAL_CONFLICT; - if (!strcasecmp (atom + 1, "ick-first-value") || - !strcasecmp (atom + 1, "ick")) - return PICK; - if (!strcasecmp (atom + 1, "aused")) - return PAUSED; - break; - case 'r': - if (!strcasecmp (atom + 1, "esolution-interrupted")) - return RESOLUTION_INTERRUPTED; - if (!strcasecmp (atom + 1, "ange")) - return RANGE; - if (!strcasecmp (atom + 1, "ecover")) - return RECOVER; - if (!strcasecmp (atom + 1, "ecover-done")) - return RECOVER_DONE; - if (!strcasecmp (atom + 1, "ecover-wait")) - return RECOVER_WAIT; - if (!strcasecmp (atom + 1, "econtact-interval")) - return RECONTACT_INTERVAL; - if (!strcasecmp (atom + 1, "equest")) - return REQUEST; - if (!strcasecmp (atom + 1, "equire")) - return REQUIRE; - if (!strcasecmp (atom + 1, "equire")) - return REQUIRE; - if (!strcasecmp (atom + 1, "etry")) - return RETRY; - if (!strcasecmp (atom + 1, "eturn")) - return RETURN; - if (!strcasecmp (atom + 1, "enew")) - return RENEW; - if (!strcasecmp (atom + 1, "ebind")) - return REBIND; - if (!strcasecmp (atom + 1, "eboot")) - return REBOOT; - if (!strcasecmp (atom + 1, "eject")) - return REJECT; - if (!strcasecmp (atom + 1, "everse")) - return REVERSE; - if (!strcasecmp (atom + 1, "elease")) - return RELEASE; - if (!strcasecmp (atom + 1, "efused")) - return NS_REFUSED; - if (!strcasecmp (atom + 1, "eleased")) - return TOKEN_RELEASED; - if (!strcasecmp (atom + 1, "eset")) - return TOKEN_RESET; - if (!strcasecmp (atom + 1, "eserved")) - return TOKEN_RESERVED; - if (!strcasecmp (atom + 1, "emove")) - return REMOVE; - if (!strcasecmp (atom + 1, "efresh")) - return REFRESH; - break; - case 's': - if (!strcasecmp (atom + 1, "tate")) - return STATE; - if (!strcasecmp (atom + 1, "ecret")) - return SECRET; - if (!strcasecmp (atom + 1, "ervfail")) - return NS_SERVFAIL; - if (!strcasecmp (atom + 1, "witch")) - return SWITCH; - if (!strcasecmp (atom + 1, "igned")) - return SIGNED; - if (!strcasecmp (atom + 1, "tring")) - return STRING_TOKEN; - if (!strcasecmp (atom + 1, "uffix")) - return SUFFIX; - if (!strcasecmp (atom + 1, "earch")) - return SEARCH; - if (!strcasecmp (atom + 1, "tarts")) - return STARTS; - if (!strcasecmp (atom + 1, "iaddr")) - return SIADDR; - if (!strcasecmp (atom + 1, "hared-network")) - return SHARED_NETWORK; - if (!strcasecmp (atom + 1, "econdary")) - return SECONDARY; - if (!strcasecmp (atom + 1, "erver-name")) - return SERVER_NAME; - if (!strcasecmp (atom + 1, "erver-identifier")) - return SERVER_IDENTIFIER; - if (!strcasecmp (atom + 1, "erver")) - return SERVER; - if (!strcasecmp (atom + 1, "elect-timeout")) - return SELECT_TIMEOUT; - if (!strcasecmp (atom + 1, "elect")) - return SELECT; - if (!strcasecmp (atom + 1, "end")) - return SEND; - if (!strcasecmp (atom + 1, "cript")) - return SCRIPT; - if (!strcasecmp (atom + 1, "upersede")) - return SUPERSEDE; - if (!strncasecmp (atom + 1, "ub", 2)) { - if (!strcasecmp (atom + 3, "string")) - return SUBSTRING; - if (!strcasecmp (atom + 3, "net")) - return SUBNET; - if (!strcasecmp (atom + 3, "class")) - return SUBCLASS; - break; - } - if (!strcasecmp (atom + 1, "pawn")) - return SPAWN; - if (!strcasecmp (atom + 1, "pace")) - return SPACE; - if (!strcasecmp (atom + 1, "tatic")) - return STATIC; - if (!strcasecmp (atom + 1, "plit")) - return SPLIT; - if (!strcasecmp (atom + 1, "et")) - return TOKEN_SET; - if (!strcasecmp (atom + 1, "econds")) - return SECONDS; - if (!strcasecmp (atom + 1, "hutdown")) - return SHUTDOWN; - if (!strcasecmp (atom + 1, "tartup")) - return STARTUP; - break; - case 't': - if (!strcasecmp (atom + 1, "imestamp")) - return TIMESTAMP; - if (!strcasecmp (atom + 1, "imeout")) - return TIMEOUT; - if (!strcasecmp (atom + 1, "oken-ring")) - return TOKEN_RING; - if (!strcasecmp (atom + 1, "ext")) - return TEXT; - if (!strcasecmp (atom + 1, "stp")) - return TSTP; - if (!strcasecmp (atom + 1, "sfp")) - return TSFP; - if (!strcasecmp (atom + 1, "ransmission")) - return TRANSMISSION; - break; - case 'u': - if (!strcasecmp (atom + 1, "nset")) - return UNSET; - if (!strcasecmp (atom + 1, "nsigned")) - return UNSIGNED; - if (!strcasecmp (atom + 1, "id")) - return UID; - if (!strncasecmp (atom + 1, "se", 2)) { - if (!strcasecmp (atom + 3, "r-class")) - return USER_CLASS; - if (!strcasecmp (atom + 3, "-host-decl-names")) - return USE_HOST_DECL_NAMES; - if (!strcasecmp (atom + 3, - "-lease-addr-for-default-route")) - return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE; - break; - } - if (!strncasecmp (atom + 1, "nknown", 6)) { - if (!strcasecmp (atom + 7, "-clients")) - return UNKNOWN_CLIENTS; - if (!strcasecmp (atom + 7, "-state")) - return UNKNOWN_STATE; - if (!atom [7]) - return UNKNOWN; - break; - } - if (!strcasecmp (atom + 1, "nauthenticated")) - return AUTHENTICATED; - if (!strcasecmp (atom + 1, "pdated-dns-rr")) - return UPDATED_DNS_RR; - if (!strcasecmp (atom + 1, "pdate")) - return UPDATE; - break; - case 'v': - if (!strcasecmp (atom + 1, "endor-class")) - return VENDOR_CLASS; - if (!strcasecmp (atom + 1, "endor")) - return VENDOR; - break; - case 'w': - if (!strcasecmp (atom + 1, "ith")) - return WITH; - break; - case 'y': - if (!strcasecmp (atom + 1, "iaddr")) - return YIADDR; - if (!strcasecmp (atom + 1, "xdomain")) - return NS_YXDOMAIN; - if (!strcasecmp (atom + 1, "xrrset")) - return NS_YXRRSET; - break; - case 'z': - if (!strcasecmp (atom + 1, "one")) - return ZONE; - break; - } - return dfv; -} diff --git a/contrib/isc-dhcp/common/ctrace.c b/contrib/isc-dhcp/common/ctrace.c deleted file mode 100644 index 790a365..0000000 --- a/contrib/isc-dhcp/common/ctrace.c +++ /dev/null @@ -1,293 +0,0 @@ -/* trace.c - - Subroutines that support dhcp tracing... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 2001-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon, as part of a project for Nominum, Inc. To learn more - * about Internet Systems Consortium, see http://www.isc.org/. To - * learn more about Nominum, Inc., see ``http://www.nominum.com''. - */ - -#ifndef lint -static char copyright[] = -"$Id: ctrace.c,v 1.3.2.2 2004/06/10 17:59:15 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (TRACING) -void trace_interface_register (trace_type_t *ttype, struct interface_info *ip) -{ - trace_interface_packet_t tipkt; - - if (trace_record ()) { - memset (&tipkt, 0, sizeof tipkt); - memcpy (&tipkt.hw_address, - &ip -> hw_address, sizeof ip -> hw_address); - memcpy (&tipkt.primary_address, - &ip -> primary_address, sizeof ip -> primary_address); - memcpy (tipkt.name, ip -> name, sizeof ip -> name); - tipkt.index = htonl (ip -> index); - - trace_write_packet (ttype, sizeof tipkt, (char *)&tipkt, MDL); - } -} - -void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf) -{ - trace_interface_packet_t *tipkt; - struct interface_info *ip; - struct sockaddr_in *sin; - struct iaddr addr; - isc_result_t status; - - if (len != sizeof *tipkt) { - log_error ("trace interface packet size mismatch: %ld != %d", - (long)(sizeof *tipkt), len); - return; - } - tipkt = (trace_interface_packet_t *)buf; - - ip = (struct interface_info *)0; - status = interface_allocate (&ip, MDL); - if (status != ISC_R_SUCCESS) { - foo: - log_error ("trace_interface_input: %s.", - isc_result_totext (status)); - return; - } - ip -> ifp = dmalloc (sizeof *(ip -> ifp), MDL); - if (!ip -> ifp) { - interface_dereference (&ip, MDL); - status = ISC_R_NOMEMORY; - goto foo; - } - - memcpy (&ip -> hw_address, &tipkt -> hw_address, - sizeof ip -> hw_address); - memcpy (&ip -> primary_address, &tipkt -> primary_address, - sizeof ip -> primary_address); - memcpy (ip -> name, tipkt -> name, sizeof ip -> name); - ip -> index = ntohl (tipkt -> index); - - interface_snorf (ip, 0); - if (dhcp_interface_discovery_hook) - (*dhcp_interface_discovery_hook) (ip); - - /* Fake up an ifp. */ - memcpy (ip -> ifp -> ifr_name, ip -> name, sizeof ip -> name); -#ifdef HAVE_SA_LEN - ip -> ifp -> ifr_addr.sa_len = sizeof (struct sockaddr_in); -#endif - sin = (struct sockaddr_in *)&ip -> ifp -> ifr_addr; - sin -> sin_addr = ip -> primary_address; - - addr.len = 4; - memcpy (addr.iabuf, &sin -> sin_addr.s_addr, addr.len); - if (dhcp_interface_setup_hook) - (*dhcp_interface_setup_hook) (ip, &addr); - interface_stash (ip); - - if (!quiet_interface_discovery) { - log_info ("Listening on Trace/%s/%s%s%s", - ip -> name, - print_hw_addr (ip -> hw_address.hbuf [0], - ip -> hw_address.hlen - 1, - &ip -> hw_address.hbuf [1]), - (ip -> shared_network ? "/" : ""), - (ip -> shared_network ? - ip -> shared_network -> name : "")); - if (strcmp (ip -> name, "fallback")) { - log_info ("Sending on Trace/%s/%s%s%s", - ip -> name, - print_hw_addr (ip -> hw_address.hbuf [0], - ip -> hw_address.hlen - 1, - &ip -> hw_address.hbuf [1]), - (ip -> shared_network ? "/" : ""), - (ip -> shared_network ? - ip -> shared_network -> name : "")); - } - } - interface_dereference (&ip, MDL); -} - -void trace_interface_stop (trace_type_t *ttype) { - /* XXX */ -} - -void trace_inpacket_stash (struct interface_info *interface, - struct dhcp_packet *packet, - unsigned len, - unsigned int from_port, - struct iaddr from, - struct hardware *hfrom) -{ - trace_inpacket_t tip; - trace_iov_t iov [2]; - - if (!trace_record ()) - return; - tip.from_port = from_port; - tip.from = from; - if (hfrom) { - tip.hfrom = *hfrom; - tip.havehfrom = 1; - } else { - memset (&tip.hfrom, 0, sizeof tip.hfrom); - tip.havehfrom = 0; - } - tip.index = htonl (interface -> index); - - iov [0].buf = (char *)&tip; - iov [0].len = sizeof tip; - iov [1].buf = (char *)packet; - iov [1].len = len; - trace_write_packet_iov (inpacket_trace, 2, iov, MDL); -} - -void trace_inpacket_input (trace_type_t *ttype, unsigned len, char *buf) -{ - trace_inpacket_t *tip; - int index; - - if (len < sizeof *tip) { - log_error ("trace_input_packet: too short - %d", len); - return; - } - tip = (trace_inpacket_t *)buf; - index = ntohl (tip -> index); - - if (index > interface_count || - index < 0 || - !interface_vector [index]) { - log_error ("trace_input_packet: unknown interface index %d", - index); - return; - } - - if (!bootp_packet_handler) { - log_error ("trace_input_packet: no bootp packet handler."); - return; - } - - (*bootp_packet_handler) (interface_vector [index], - (struct dhcp_packet *)(tip + 1), - len - sizeof *tip, - tip -> from_port, - tip -> from, - (tip -> havehfrom ? - &tip -> hfrom - : (struct hardware *)0)); -} - -void trace_inpacket_stop (trace_type_t *ttype) { } - -ssize_t trace_packet_send (struct interface_info *interface, - struct packet *packet, - struct dhcp_packet *raw, - size_t len, - struct in_addr from, - struct sockaddr_in *to, - struct hardware *hto) -{ - trace_outpacket_t tip; - trace_iov_t iov [2]; - - if (trace_record ()) { - if (hto) { - tip.hto = *hto; - tip.havehto = 1; - } else { - memset (&tip.hto, 0, sizeof tip.hto); - tip.havehto = 0; - } - tip.from.len = 4; - memcpy (tip.from.iabuf, &from, 4); - tip.to.len = 4; - memcpy (tip.to.iabuf, &to -> sin_addr, 4); - tip.to_port = to -> sin_port; - tip.index = htonl (interface -> index); - - iov [0].buf = (char *)&tip; - iov [0].len = sizeof tip; - iov [1].buf = (char *)raw; - iov [1].len = len; - trace_write_packet_iov (outpacket_trace, 2, iov, MDL); - } - if (!trace_playback ()) { - return send_packet (interface, packet, raw, len, - from, to, hto); - } - return len; -} - -void trace_outpacket_input (trace_type_t *ttype, unsigned len, char *buf) -{ - trace_outpacket_t *tip; - int index; - - if (len < sizeof *tip) { - log_error ("trace_input_packet: too short - %d", len); - return; - } - tip = (trace_outpacket_t *)buf; - index = ntohl (tip -> index); - - if (index > interface_count || - index < 0 || - !interface_vector [index]) { - log_error ("trace_input_packet: unknown interface index %d", - index); - return; - } - - /* XXX would be nice to somehow take notice of these. */ -} - -void trace_outpacket_stop (trace_type_t *ttype) { } - -void trace_seed_stash (trace_type_t *ttype, unsigned seed) -{ - u_int32_t outseed; - if (!trace_record ()) - return; - outseed = htonl (seed); - trace_write_packet (ttype, sizeof outseed, (char *)&outseed, MDL); - return; -} - -void trace_seed_input (trace_type_t *ttype, unsigned length, char *buf) -{ - u_int32_t *seed; - - if (length != sizeof seed) { - log_error ("trace_seed_input: wrong size (%d)", length); - } - seed = (u_int32_t *)buf; - srandom (ntohl (*seed)); -} - -void trace_seed_stop (trace_type_t *ttype) { } -#endif /* TRACING */ diff --git a/contrib/isc-dhcp/common/dhcp-eval.5 b/contrib/isc-dhcp/common/dhcp-eval.5 deleted file mode 100644 index 48ee31b..0000000 --- a/contrib/isc-dhcp/common/dhcp-eval.5 +++ /dev/null @@ -1,477 +0,0 @@ -.\" $Id: dhcp-eval.5,v 1.17.2.7 2004/06/10 17:59:15 dhankins Exp $ -.\" -.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") -.\" Copyright (c) 1996-2003 by Internet Software Consortium -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Internet Systems Consortium, Inc. -.\" 950 Charter Street -.\" Redwood City, CA 94063 -.\" <info@isc.org> -.\" http://www.isc.org/ -.\" -.\" This software has been written for Internet Systems Consortium -.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about Internet Systems 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''. -.TH dhcp-eval 5 -.SH NAME -dhcp-eval - ISC DHCP conditional evaluation -.SH DESCRIPTION -The Internet Systems Consortium DHCP client and server both provide -the ability to perform conditional behavior depending on the contents -of packets they receive. The syntax for specifying this conditional -behaviour is documented here. -.SH REFERENCE: CONDITIONAL BEHAVIOUR -Conditional behaviour is specified using the if statement and the else -or elsif statements. A conditional statement can appear anywhere -that a regular statement (e.g., an option statement) can appear, and -can enclose one or more such statements. A typical conditional -statement in a server might be: -.PP -.nf -if option dhcp-user-class = "accounting" { - max-lease-time 17600; - option domain-name "accounting.example.org"; - option domain-name-servers ns1.accounting.example.org, - ns2.accounting.example.org; -} elsif option dhcp-user-class = "sales" { - max-lease-time 17600; - option domain-name "sales.example.org"; - option domain-name-servers ns1.sales.example.org, - ns2.sales.example.org; -} elsif option dhcp-user-class = "engineering" { - max-lease-time 17600; - option domain-name "engineering.example.org"; - option domain-name-servers ns1.engineering.example.org, - ns2.engineering.example.org; -} else { - max-lease-time 600; - option domain-name "misc.example.org"; - option domain-name-servers ns1.misc.example.org, - ns2.misc.example.org; -} -.fi -.PP -On the client side, an example of conditional evaluation might be: -.PP -.nf -# example.org filters DNS at its firewall, so we have to use their DNS -# servers when we connect to their network. If we are not at -# example.org, prefer our own DNS server. -if not option domain-name = "example.org" { - prepend domain-name-servers 127.0.0.1; -} -.fi -.PP -The -.B if -statement and the -.B elsif -continuation statement both take boolean expressions as their -arguments. That is, they take expressions that, when evaluated, -produce a boolean result. If the expression evaluates to true, then -the statements enclosed in braces following the -.B if -statement are executed, and all subsequent -.B elsif -and -.B else -clauses are skipped. Otherwise, each subsequent -.B elsif -clause's expression is checked, until an elsif clause is encountered -whose test evaluates to true. If such a clause is found, the -statements in braces following it are executed, and then any -subsequent -.B elsif -and -.B else -clauses are skipped. If all the -.B if -and -.B elsif -clauses are checked but none -of their expressions evaluate true, then if there is an -.B else -clause, the statements enclosed in braces following the -.B else -are evaluated. Boolean expressions that evaluate to null are -treated as false in conditionals. -.SH BOOLEAN EXPRESSIONS -The following is the current list of boolean expressions that are -supported by the DHCP distribution. -.PP -.I data-expression-1 \fB=\fI data-expression-2\fR -.RS 0.25i -.PP -The \fB=\fR operator compares the values of two data expressions, -returning true if they are the same, false if they are not. If -either the left-hand side or the right-hand side are null, the -result is also null. -.RE -.PP -.I boolean-expression-1 \fBand\fI boolean-expression-2\fR -.PP -.RS 0.25i -The \fBand\fR operator evaluates to true if the boolean expression on -the left-hand side and the boolean expression on the right-hand side -both evaluate to true. Otherwise, it evaluates to false. If either -the expression on the left-hand side or the expression on the -right-hand side are null, the result is null. -.RE -.PP -.I boolean-expression-1 \fBor\fI boolean-expression-2\fR -.PP -.RS 0.25i -The \fBor\fR operator evaluates to true if either the boolean -expression on the left-hand side or the boolean expression on the -right-hand side evaluate to true. Otherwise, it evaluates to false. -If either the expression on the left-hand side or the expression on -the right-hand side are null, the result is null. -.RE -.PP -.B not \fIboolean-expression -.PP -.RS 0.25i -The \fBnot\fR operator evaluates to true if \fIboolean-expression\fR -evaluates to false, and returns false if \fIboolean-expression\fR evaluates -to true. If \fIboolean-expression\fR evaluates to null, the result -is also null. -.RE -.PP -.B exists \fIoption-name\fR -.PP -.RS 0.25i -The \fBexists\fR expression returns true if the specified option -exists in the incoming DHCP packet being processed. -.RE -.B known -.PP -.RS 0.25i -The \fBknown\fR expression returns true if the client whose request is -currently being processed is known - that is, if there's a host -declaration for it. -.RE -.B static -.PP -.RS 0.25i -The \fBstatic\fR expression returns true if the lease assigned to the -client whose request is currently being processed is derived from a static -address assignment. -.RE -.SH DATA EXPRESSIONS -Several of the boolean expressions above depend on the results of -evaluating data expressions. A list of these expressions is provided -here. -.PP -.B substring (\fIdata-expr\fB, \fIoffset\fB, \fIlength\fB)\fR -.PP -.RS 0.25i -The \fBsubstring\fR operator evaluates the data expression and returns -the substring of the result of that evaluation that starts -\fIoffset\fR bytes from the beginning, continuing for \fIlength\fR -bytes. \fIOffset\fR and \fIlength\fR are both numeric expressions. -If \fIdata-expr\fR, \fIoffset\fR or \fIlength\fR evaluate to null, -then the result is also null. If \fIoffset\fR is greater than or -equal to the length of the evaluated data, then a zero-length data -string is returned. If \fIlength\fI is greater then the remaining -length of the evaluated data after \fIoffset\fR, then a data string -containing all data from \fIoffset\fR to the end of the evaluated data -is returned. -.RE -.PP -.B suffix (\fIdata-expr\fB, \fIlength\fB)\fR -.PP -.RS 0.25i -The \fBsuffix\fR operator evaluates \fIdata-expr\fR and returns the -last \fIlength\fR bytes of the result of that evaluation. \fILength\fR -is a numeric expression. If \fIdata-expr\fR or \fIlength\fR evaluate -to null, then the result is also null. If \fIsuffix\fR evaluates to a -number greater than the length of the evaluated data, then the -evaluated data is returned. -.RE -.PP -.B option \fIoption-name\fR -.PP -.RS 0.25i -The \fBoption\fR operator returns the contents of the specified option in -the packet to which the server is responding. -.RE -.PP -.B config-option \fIoption-name\fR -.PP -.RS 0.25i -The \fBconfig-option\fR operator returns the value for the specified option -that the DHCP client or server has been configured to send. -.RE -.PP -.B hardware -.PP -.RS 0.25i -The \fBhardware\fR operator returns a data string whose first element -is the type of network interface indicated in packet being considered, -and whose subsequent elements are client's link-layer address. If -there is no packet, or if the RFC2131 \fIhlen\fR field is invalid, -then the result is null. Hardware types include ethernet (1), -token-ring (6), and fddi (8). Hardware types are specified by the -IETF, and details on how the type numbers are defined can be found in -RFC2131 (in the ISC DHCP distribution, this is included in the doc/ -subdirectory). -.RE -.PP -.B packet (\fIoffset\fB, \fIlength\fB)\fR -.PP -.RS 0.25i -The \fBpacket\fR operator returns the specified portion of the packet -being considered, or null in contexts where no packet is being -considered. \fIOffset\fR and \fIlength\fR are applied to the -contents packet as in the \fBsubstring\fR operator. -.RE -.PP -.I string -.PP -.RS 0.25i -A string, enclosed in quotes, may be specified as a data expression, -and returns the text between the quotes, encoded in ASCII. The -backslash ('\\') character is treated specially, as in C programming: -'\\t' means TAB, '\\r' means carriage return, '\\n' means newline, and -'\\b' means bell. Any octal value can be specified with '\\nnn', -where nnn is any positive octal number less than 0400. Any -hexadecimal value can be specified with '\xnn', where nn is any -positive hexadecimal number less than 0xff. -.RE -.PP -.I colon-separated hexadecimal list -.PP -.RS 0.25i -A list of hexadecimal octet values, separated by colons, may be -specified as a data expression. -.RE -.PP -.B concat (\fIdata-expr1\fB, ..., \fIdata-exprN\fB)\fR -.RS 0.25i -The expressions are evaluated, and the results of each evaluation are -concatenated in the sequence that the subexpressions are listed. If -any subexpression evaluates to null, the result of the concatenation -is null. -.RE -.PP -.B reverse (\fInumeric-expr1\fB, \fIdata-expr2\fB)\fR -.RS 0.25i -The two expressions are evaluated, and then the result of evaluating -the data expression is reversed in place, using hunks of the size -specified in the numeric expression. For example, if the numeric -expression evaluates to four, and the data expression evaluates to -twelve bytes of data, then the reverse expression will evaluate to -twelve bytes of data, consisting of the last four bytes of the the -input data, followed by the middle four bytes, followed by the first -four bytes. -.RE -.PP -.B leased-address -.RS 0.25i -In any context where the client whose request is being processed has -been assigned an IP address, this data expression returns that IP -address. -.RE -.PP -.B binary-to-ascii (\fInumeric-expr1\fB, \fInumeric-expr2\fB, -.B \fIdata-expr1\fB,\fR \fIdata-expr2\fB)\fR -.RS 0.25i -Converts the result of evaluating data-expr2 into a text string -containing one number for each element of the result of evaluating -data-expr2. Each number is separated from the other by the result of -evaluating data-expr1. The result of evaluating numeric-expr1 -specifies the base (2 through 16) into which the numbers should be -converted. The result of evaluating numeric-expr2 specifies the -width in bits of each number, which may be either 8, 16 or 32. -.PP -As an example of the preceding three types of expressions, to produce -the name of a PTR record for the IP address being assigned to a -client, one could write the following expression: -.RE -.PP -.nf - concat (binary-to-ascii (10, 8, ".", - reverse (1, leased-address)), - ".in-addr.arpa."); - -.fi -.PP -.B encode-int (\fInumeric-expr\fB, \fIwidth\fB)\fR -.RS 0.25i -Numeric-expr is evaluated and encoded as a data string of the -specified width, in network byte order (most significant byte first). -If the numeric expression evaluates to the null value, the result is -also null. -.PP -.B pick-first-value (\fIdata-expr1\fR [ ... \fIexpr\fRn ] \fB)\fR -.RS 0.25i -The pick-first-value function takes any number of data expressions as -its arguments. Each expression is evaluated, starting with the first -in the list, until an expression is found that does not evaluate to a -null value. That expression is returned, and none of the subsequent -expressions are evaluated. If all expressions evaluate to a null -value, the null value is returned. -.RE -.PP -.B host-decl-name -.RS 0.25i -The host-decl-name function returns the name of the host declaration -that matched the client whose request is currently being processed, if -any. If no host declaration matched, the result is the null value. -.RE -.SH NUMERIC EXPRESSIONS -Numeric expressions are expressions that evaluate to an integer. In -general, the maximum size of such an integer should not be assumed to -be representable in fewer than 32 bits, but the precision of such -integers may be more than 32 bits. -.PP -.B extract-int (\fIdata-expr\fB, \fIwidth\fB)\fR -.PP -.RS 0.25i -The \fBextract-int\fR operator extracts an integer value in network -byte order from the result of evaluating the specified data -expression. Width is the width in bits of the integer to extract. -Currently, the only supported widths are 8, 16 and 32. If the -evaluation of the data expression doesn't provide sufficient bits to -extract an integer of the specified size, the null value is returned. -.RE -.PP -.B lease-time -.PP -.RS 0.25i -The duration of the current lease - that is, the difference between -the current time and the time that the lease expires. -.RE -.PP -.I number -.PP -.RS 0.25i -Any number between zero and the maximum representable size may be -specified as a numeric expression. -.RE -.PP -.B client-state -.PP -.RS 0.25i -The current state of the client instance being processed. This is -only useful in DHCP client configuration files. Possible values are: -.TP 2 -.I \(bu -Booting - DHCP client is in the INIT state, and does not yet have an -IP address. The next message transmitted will be a DHCPDISCOVER, -which will be broadcast. -.TP -.I \(bu -Reboot - DHCP client is in the INIT-REBOOT state. It has an IP -address, but is not yet using it. The next message to be transmitted -will be a DHCPREQUEST, which will be broadcast. If no response is -heard, the client will bind to its address and move to the BOUND state. -.TP -.I \(bu -Select - DHCP client is in the SELECTING state - it has received at -least one DHCPOFFER message, but is waiting to see if it may receive -other DHCPOFFER messages from other servers. No messages are sent in -the SELECTING state. -.TP -.I \(bu -Request - DHCP client is in the REQUESTING state - it has received at -least one DHCPOFFER message, and has chosen which one it will -request. The next message to be sent will be a DHCPREQUEST message, -which will be broadcast. -.TP -.I \(bu -Bound - DHCP client is in the BOUND state - it has an IP address. No -messages are transmitted in this state. -.TP -.I \(bu -Renew - DHCP client is in the RENEWING state - it has an IP address, -and is trying to contact the server to renew it. The next message to -be sent will be a DHCPREQUEST message, which will be unicast directly -to the server. -.TP -.I \(bu -Rebind - DHCP client is in the REBINDING state - it has an IP address, -and is trying to contact any server to renew it. The next message to -be sent will be a DHCPREQUEST, which will be broadcast. -.RE -.SH REFERENCE: LOGGING -Logging statements may be used to send information to the standard logging -channels. A logging statement includes an optional priority (\fBfatal\fR, -\fBerror\fR, \fBinfo\fR, or \fBdebug\fR), and a data expression. -.PP -.B log (\fIpriority\fB, \fIdata-expr\fB)\fR -.PP -Logging statements take only a single data expression argument, so if you -want to output multiple data values, you will need to use the \fBconcat\fR -operator to concatenate them. -.RE -.SH REFERENCE: DYNAMIC DNS UPDATES -.PP -The DHCP client and server have the ability to dynamically update the -Domain Name System. Within the configuration files, you can define -how you want the Domain Name System to be updated. These updates are -RFC 2136 compliant so any DNS server supporting RFC 2136 should be -able to accept updates from the DHCP server. -.SH SECURITY -Support for TSIG and DNSSEC is not yet available. When you set your -DNS server up to allow updates from the DHCP server or client, you may -be exposing it to unauthorized updates. To avoid this, the best you -can do right now is to use IP address-based packet filtering to -prevent unauthorized hosts from submitting update requests. -Obviously, there is currently no way to provide security for client -updates - this will require TSIG or DNSSEC, neither of which is yet -available in the DHCP distribution. -.PP -Dynamic DNS (DDNS) updates are performed by using the \fBdns-update\fR -expression. The \fBdns-update\fR expression is a boolean expression -that takes four parameters. If the update succeeds, the result is -true. If it fails, the result is false. The four parameters that the -are the resource record type (RR), the left hand side of the RR, the -right hand side of the RR and the ttl that should be applied to the -record. The simplest example of the use of the function can be found -in the reference section of the dhcpd.conf file, where events are -described. In this example several statements are being used to make -the arguments to the \fBdns-update\f\R. -.PP -In the example, the first argument to the first \f\Bdns-update\fR -expression is a data expression that evaluates to the A RR type. The -second argument is constructed by concatenating the DHCP host-name -option with a text string containing the local domain, in this case -"ssd.example.net". The third argument is constructed by converting -the address the client has been assigned from a 32-bit number into an -ascii string with each byte separated by a ".". The fourth argument, -the TTL, specifies the amount of time remaining in the lease (note -that this isn't really correct, since the DNS server will pass this -TTL out whenever a request comes in, even if that is only a few -seconds before the lease expires). -.PP -If the first \fBdns-update\fR statement succeeds, it is followed up -with a second update to install a PTR RR. The installation of a PTR -record is similar to installing an A RR except that the left hand side -of the record is the leased address, reversed, with ".in-addr.arpa" -concatenated. The right hand side is the fully qualified domain name -of the client to which the address is being leased. -.SH SEE ALSO -dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcp-eval(5), dhcpd(8), -dhclient(8), RFC2132, RFC2131. -.SH AUTHOR -The Internet Systems Consortium DHCP Distribution was written by Ted -Lemon under a contract with Vixie Labs. Funding for -this project was provided through Internet Systems Consortium. -Information about Internet Systems Consortium can be found at -.B http://www.isc.org. diff --git a/contrib/isc-dhcp/common/dhcp-options.5 b/contrib/isc-dhcp/common/dhcp-options.5 deleted file mode 100644 index 9bb7f94..0000000 --- a/contrib/isc-dhcp/common/dhcp-options.5 +++ /dev/null @@ -1,1523 +0,0 @@ -.\" $Id: dhcp-options.5,v 1.19.2.11 2004/06/10 17:59:15 dhankins Exp $ -.\" -.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") -.\" Copyright (c) 1996-2003 by Internet Software Consortium -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Internet Systems Consortium, Inc. -.\" 950 Charter Street -.\" Redwood City, CA 94063 -.\" <info@isc.org> -.\" http://www.isc.org/ -.\" -.\" This software has been written for Internet Systems Consortium -.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about Internet Systems 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''. -.\" -.\" $Id: dhcp-options.5,v 1.19.2.10 2003/02/23 03:27:42 dhankins Exp $ -.\" $FreeBSD$ -.\" -.TH dhcpd-options 5 -.SH NAME -dhcp-options - Dynamic Host Configuration Protocol options -.SH DESCRIPTION -The Dynamic Host Configuration protocol allows the client to receive -.B options -from the DHCP server describing the network configuration and various -services that are available on the network. When configuring -.B dhcpd(8) -or -.B dhclient(8) , -options must often be declared. The syntax for declaring options, -and the names and formats of the options that can be declared, are -documented here. -.SH REFERENCE: OPTION STATEMENTS -.PP -DHCP \fIoption\fR statements always start with the \fIoption\fR -keyword, followed by an option name, followed by option data. The -option names and data formats are described below. It is not -necessary to exhaustively specify all DHCP options - only those -options which are needed by clients must be specified. -.PP -Option data comes in a variety of formats, as defined below: -.PP -The -.B ip-address -data type can be entered either as an explicit IP -address (e.g., 239.254.197.10) or as a domain name (e.g., -haagen.isc.org). When entering a domain name, be sure that that -domain name resolves to a single IP address. -.PP -The -.B int32 -data type specifies a signed 32-bit integer. The -.B uint32 -data type specifies an unsigned 32-bit integer. The -.B int16 -and -.B uint16 -data types specify signed and unsigned 16-bit integers. The -.B int8 -and -.B uint8 -data types specify signed and unsigned 8-bit integers. -Unsigned 8-bit integers are also sometimes referred to as octets. -.PP -The -.B text -data type specifies an NVT ASCII string, which must be -enclosed in double quotes - for example, to specify a root-path -option, the syntax would be -.nf -.sp 1 -option root-path "10.0.1.4:/var/tmp/rootfs"; -.fi -.PP -The -.B domain-name -data type specifies a domain name, which must not -enclosed in double quotes. This data type is not used for any -existing DHCP options. The domain name is stored just as if it were -a text option. -.PP -The -.B flag -data type specifies a boolean value. Booleans can be either true or -false (or on or off, if that makes more sense to you). -.PP -The -.B string -data type specifies either an NVT ASCII string -enclosed in double quotes, or a series of octets specified in -hexadecimal, separated by colons. For example: -.nf -.sp 1 - option dhcp-client-identifier "CLIENT-FOO"; -or - option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f; -.fi -.SH SETTING OPTION VALUES USING EXPRESSIONS -Sometimes it's helpful to be able to set the value of a DHCP option -based on some value that the client has sent. To do this, you can -use expression evaluation. The -.B dhcp-eval(5) -manual page describes how to write expressions. To assign the result -of an evaluation to an option, define the option as follows: -.nf -.sp 1 - \fBoption \fImy-option \fB= \fIexpression \fB;\fR -.fi -.PP -For example: -.nf -.sp 1 - option hostname = binary-to-ascii (16, 8, "-", - substring (hardware, 1, 6)); -.fi -.SH STANDARD DHCP OPTIONS -The documentation for the various options mentioned below is taken -from the latest IETF draft document on DHCP options. Options not -listed below may not yet be implemented, but it is possible to use -such options by defining them in the configuration file. Please see -the DEFINING NEW OPTIONS heading later in this document for more -information. -.PP -Some of the options documented here are automatically generated by -the DHCP server or by clients, and cannot be configured by the user. -The value of such an option can be used in the configuration file of -the receiving DHCP protocol agent (server or client), for example in -conditional expressions. However, the value of the option cannot be -used in the configuration file of the sending agent, because the value -is determined only \fIafter\fR the configuration file has been -processed. In the following documentation, such options will be shown -as "not user configurable" -.PP -The standard options are: -.PP -.B option \fBall-subnets-local\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client may assume that all -subnets of the IP network to which the client is connected use the -same MTU as the subnet of that network to which the client is -directly connected. A value of true indicates that all subnets share -the same MTU. A value of false means that the client should assume that -some subnets of the directly connected network may have smaller MTUs. -.RE -.PP -.B option \fBarp-cache-timeout\fR \fIuint32\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the timeout in seconds for ARP cache entries. -.RE -.PP -.B option \fBbootfile-name\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option is used to identify a bootstrap file. If supported by the -client, it should have the same effect as the \fBfilename\fR -declaration. BOOTP clients are unlikely to support this option. Some -DHCP clients will support it, and others actually require it. -.RE -.PP -.B option \fBboot-size\fR \fIuint16\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the length in 512-octet blocks of the default -boot image for the client. -.RE -.PP -.B option \fBbroadcast-address\fR \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the broadcast address in use on the client's -subnet. Legal values for broadcast addresses are specified in -section 3.2.1.3 of STD 3 (RFC1122). -.RE -.PP -.B option \fBcookie-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The cookie server option specifies a list of RFC 865 cookie -servers available to the client. Servers should be listed in order -of preference. -.RE -.PP -.B option \fBdefault-ip-ttl\fR \fIuint8;\fR -.RS 0.25i -.PP -This option specifies the default time-to-live that the client should -use on outgoing datagrams. -.RE -.PP -.B option \fBdefault-tcp-ttl\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the default TTL that the client should use when -sending TCP segments. The minimum value is 1. -.RE -.PP -.B option \fBdhcp-client-identifier\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -This option can be used to specify a DHCP client identifier in a -host declaration, so that dhcpd can find the host record by matching -against the client identifier. -.PP -Please be aware that some DHCP clients, when configured with client -identifiers that are ASCII text, will prepend a zero to the ASCII -text. So you may need to write: -.nf - - option dhcp-client-identifier "\\0foo"; - -rather than: - - option dhcp-client-identifier "foo"; -.fi -.RE -.PP -.B option \fBdhcp-lease-time\fR \fIuint32\fR\fB;\fR -.RS 0.25i -.PP -This option is used in a client request (DHCPDISCOVER or DHCPREQUEST) -to allow the client to request a lease time for the IP address. In a -server reply (DHCPOFFER), a DHCP server uses this option to specify -the lease time it is willing to offer. -.PP -This option is not directly user configurable in the server; refer to the -\fImax-lease-time\fR and \fIdefault-lease-time\fR server options in -.B dhcpd.conf(5). -.RE -.PP -.B option \fBdhcp-max-message-size\fR \fIuint16\fR\fB;\fR -.RS 0.25i -.PP -This option, when sent by the client, specifies the maximum size of -any response that the server sends to the client. When specified on -the server, if the client did not send a dhcp-max-message-size option, -the size specified on the server is used. This works for BOOTP as -well as DHCP responses. -.RE -.PP -.B option \fBdhcp-message\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option is used by a DHCP server to provide an error message to a -DHCP client in a DHCPNAK message in the event of a failure. A client -may use this option in a DHCPDECLINE message to indicate why the -client declined the offered parameters. -.PP -This option is not user configurable. -.RE -.PP -.B option \fBdhcp-message-type\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -This option, sent by both client and server, specifies the type of DHCP -message contained in the DHCP packet. Possible values (taken directly from -RFC2132) are: -.PP -.nf - 1 DHCPDISCOVER - 2 DHCPOFFER - 3 DHCPREQUEST - 4 DHCPDECLINE - 5 DHCPACK - 6 DHCPNAK - 7 DHCPRELEASE - 8 DHCPINFORM -.fi -.PP -This option is not user configurable. -.PP -.RE -.B option \fBdhcp-option-overload\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -This option is used to indicate that the DHCP 'sname' or 'file' -fields are being overloaded by using them to carry DHCP options. A -DHCP server inserts this option if the returned parameters will -exceed the usual space allotted for options. -.PP -If this option is present, the client interprets the specified -additional fields after it concludes interpretation of the standard -option fields. -.PP -Legal values for this option are: -.PP -.nf - 1 the 'file' field is used to hold options - 2 the 'sname' field is used to hold options - 3 both fields are used to hold options -.fi -.PP -This option is not user configurable. -.PP -.RE -.PP -.B option \fBdhcp-parameter-request-list\fR \fIuint16\fR\fB;\fR -.RS 0.25i -.PP -This option, when sent by the client, specifies which options the -client wishes the server to return. Normally, in the ISC DHCP -client, this is done using the \fIrequest\fR statement. If this -option is not specified by the client, the DHCP server will normally -return every option that is valid in scope and that fits into the -reply. When this option is specified on the server, the server -returns the specified options. This can be used to force a client to -take options that it hasn't requested, and it can also be used to -tailor the response of the DHCP server for clients that may need a -more limited set of options than those the server would normally -return. -.RE -.PP -.B option \fBdhcp-rebinding-time\fR \fIuint32\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the number of seconds from the time a client gets -an address until the client transitions to the REBINDING state. -.PP -This option is not user configurable. -.PP -.RE -.PP -.B option \fBdhcp-renewal-time\fR \fIuint32\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the number of seconds from the time a client gets -an address until the client transitions to the RENEWING state. -.PP -This option is not user configurable. -.PP -.RE -.PP -.B option \fBdhcp-requested-address\fR \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -This option is used by the client in a DHCPDISCOVER to -request that a particular IP address be assigned. -.PP -This option is not user configurable. -.PP -.RE -.PP -.B option \fBdhcp-server-identifier\fR \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -This option is used in DHCPOFFER and DHCPREQUEST messages, and may -optionally be included in the DHCPACK and DHCPNAK messages. DHCP -servers include this option in the DHCPOFFER in order to allow the -client to distinguish between lease offers. DHCP clients use the -contents of the 'server identifier' field as the destination address -for any DHCP messages unicast to the DHCP server. DHCP clients also -indicate which of several lease offers is being accepted by including -this option in a DHCPREQUEST message. -.PP -The value of this option is the IP address of the server. -.PP -This option is not directly user configurable. See the -\fIserver-identifier\fR server option in -.B \fIdhcpd.conf(5). -.PP -.RE -.PP -.B option \fBdomain-name\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the domain name that client should use when -resolving hostnames via the Domain Name System. -.RE -.PP -.B option \fBdomain-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The domain-name-servers option specifies a list of Domain Name System -(STD 13, RFC 1035) name servers available to the client. Servers -should be listed in order of preference. -.RE -.PP -.B option \fBextensions-path\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the name of a file containing additional options -to be interpreted according to the DHCP option format as specified in -RFC2132. -.RE -.PP -.B option \fBfinger-server\fR \fIip-address\fR [\fB,\fR -\fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The Finger server option specifies a list of Finger servers available -to the client. Servers should be listed in order of preference. -.RE -.PP -.B option \fBfont-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -This option specifies a list of X Window System Font servers available -to the client. Servers should be listed in order of preference. -.RE -.PP -.B option \fBhost-name\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the name of the client. The name may or may -not be qualified with the local domain name (it is preferable to use -the domain-name option to specify the domain name). See RFC 1035 for -character set restrictions. This option is only honored by -.B dhclient-script(8) -if the hostname for the client machine is not set (i.e., set to the empty -string in -.B rc.conf(5) -). -.RE -.PP -.B option \fBieee802-3-encapsulation\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client should use Ethernet -Version 2 (RFC 894) or IEEE 802.3 (RFC 1042) encapsulation if the -interface is an Ethernet. A value of false indicates that the client -should use RFC 894 encapsulation. A value of true means that the client -should use RFC 1042 encapsulation. -.RE -.PP -.B option \fBien116-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]; -.RS 0.25i -.PP -The ien116-name-servers option specifies a list of IEN 116 name servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option \fBimpress-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The impress-server option specifies a list of Imagen Impress servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option \fBinterface-mtu\fR \fIuint16\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the MTU to use on this interface. The minimum -legal value for the MTU is 68. -.RE -.PP -.B option \fBip-forwarding\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether the client should configure its IP -layer for packet forwarding. A value of false means disable IP -forwarding, and a value of true means enable IP forwarding. -.RE -.PP -.B option \fBirc-server\fR \fIip-address\fR [\fB,\fR -\fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The IRC server option specifies a list of IRC servers available -to the client. Servers should be listed in order of preference. -.RE -.PP -.B option \fBlog-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The log-server option specifies a list of MIT-LCS UDP log servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The LPR server option specifies a list of RFC 1179 line printer -servers available to the client. Servers should be listed in order -of preference. -.RE -.PP -.B option \fBmask-supplier\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client should respond to -subnet mask requests using ICMP. A value of false indicates that the -client should not respond. A value of true means that the client should -respond. -.RE -.PP -.B option \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the maximum size datagram that the client -should be prepared to reassemble. The minimum legal value is -576. -.RE -.PP -.B option \fBmerit-dump\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the path-name of a file to which the client's -core image should be dumped in the event the client crashes. The -path is formatted as a character string consisting of characters from -the NVT ASCII character set. -.RE -.PP -.B option \fBmobile-ip-home-agent\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -This option specifies a list of IP addresses indicating mobile IP -home agents available to the client. Agents should be listed in -order of preference, although normally there will be only one such -agent. -.RE -.PP -.B option \fBnds-context\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The nds-context option specifies the name of the initial Netware -Directory Service for an NDS client. -.RE -.PP -.B option \fBnds-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The nds-servers option specifies a list of IP addresses of NDS servers. -.RE -.PP -.B option \fBnds-tree-name\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The nds-context option specifies NDS tree name that the NDS client -should use. -.RE -.PP -.B option \fBnetbios-dd-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The NetBIOS datagram distribution server (NBDD) option specifies a -list of RFC 1001/1002 NBDD servers listed in order of preference. -.RE -.PP -.B option \fBnetbios-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...]\fB;\fR -.RS 0.25i -.PP -The NetBIOS name server (NBNS) option specifies a list of RFC -1001/1002 NBNS name servers listed in order of preference. NetBIOS -Name Service is currently more commonly referred to as WINS. WINS -servers can be specified using the netbios-name-servers option. -.RE -.PP -.B option \fBnetbios-node-type\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -The NetBIOS node type option allows NetBIOS over TCP/IP clients which -are configurable to be configured as described in RFC 1001/1002. The -value is specified as a single octet which identifies the client type. -.PP -Possible node types are: -.PP -.TP 5 -.I 1 -B-node: Broadcast - no WINS -.TP -.I 2 -P-node: Peer - WINS only -.TP -.I 4 -M-node: Mixed - broadcast, then WINS -.TP -.I 8 -H-node: Hybrid - WINS, then broadcast -.RE -.PP -.B option \fBnetbios-scope\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The NetBIOS scope option specifies the NetBIOS over TCP/IP scope -parameter for the client as specified in RFC 1001/1002. See RFC1001, -RFC1002, and RFC1035 for character-set restrictions. -.RE -.PP -.B option \fBnis-domain\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the name of the client's NIS (Sun Network -Information Services) domain. The domain is formatted as a character -string consisting of characters from the NVT ASCII character set. -.RE -.PP -.B option \fBnis-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -This option specifies a list of IP addresses indicating NIS servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option \fBnisplus-domain\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the name of the client's NIS+ domain. The -domain is formatted as a character string consisting of characters -from the NVT ASCII character set. -.RE -.PP -.B option \fBnisplus-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -This option specifies a list of IP addresses indicating NIS+ servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option \fBnntp-server\fR \fIip-address\fR [\fB,\fR -\fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The NNTP server option specifies a list of NNTP servesr available -to the client. Servers should be listed in order of preference. -.RE -.PP -.B option \fBnon-local-source-routing\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether the client should configure its IP -layer to allow forwarding of datagrams with non-local source routes -(see Section 3.3.5 of [4] for a discussion of this topic). A value -of 0 means disallow forwarding of such datagrams, and a value of true -means allow forwarding. -.RE -.PP -.B option \fBntp-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -This option specifies a list of IP addresses indicating NTP (RFC 1035) -servers available to the client. Servers should be listed in order -of preference. -.RE -.PP -.B option \fBnwip-domain\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The name of the NetWare/IP domain that a NetWare/IP client should -use. -.RE -.PP -.B option \fBnwip-suboptions\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -A sequence of suboptions for NetWare/IP clients - see RFC2242 for -details. Normally this option is set by specifying specific -NetWare/IP suboptions - see the NETWARE/IP SUBOPTIONS section for more -information. -.RE -.PP -.B option \fBpath-mtu-aging-timeout\fR \fIuint32\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the timeout (in seconds) to use when aging Path -MTU values discovered by the mechanism defined in RFC 1191. -.RE -.PP -.B option \fBpath-mtu-plateau-table\fR \fIuint16\fR [\fB,\fR \fIuint16\fR... -]\fB;\fR -.RS 0.25i -.PP -This option specifies a table of MTU sizes to use when performing -Path MTU Discovery as defined in RFC 1191. The table is formatted as -a list of 16-bit unsigned integers, ordered from smallest to largest. -The minimum MTU value cannot be smaller than 68. -.RE -.PP -.B option \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client should perform subnet -mask discovery using ICMP. A value of false indicates that the client -should not perform mask discovery. A value of true means that the -client should perform mask discovery. -.RE -.PP -.nf -.B option \fBpolicy-filter\fR \fIip-address ip-address\fR - [\fB,\fR \fIip-address ip-address\fR...]\fB;\fR -.RE -.fi -.RS 0.25i -.PP -This option specifies policy filters for non-local source routing. -The filters consist of a list of IP addresses and masks which specify -destination/mask pairs with which to filter incoming source routes. -.PP -Any source routed datagram whose next-hop address does not match one -of the filters should be discarded by the client. -.PP -See STD 3 (RFC1122) for further information. -.RE -.PP -.B option \fBpop-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The POP3 server option specifies a list of POP3 servers available -to the client. Servers should be listed in order of preference. -.RE -.PP -.B option \fBresource-location-servers\fR \fIip-address\fR - [\fB, \fR\fIip-address\fR...]\fB;\fR -.fi -.RS 0.25i -.PP -This option specifies a list of RFC 887 Resource Location -servers available to the client. Servers should be listed in order -of preference. -.RE -.PP -.B option \fBroot-path\fR \fItext\fB;\fR\fR -.RS 0.25i -.PP -This option specifies the path-name that contains the client's root -disk. The path is formatted as a character string consisting of -characters from the NVT ASCII character set. -.RE -.PP -.B option \fBrouter-discovery\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client should solicit -routers using the Router Discovery mechanism defined in RFC 1256. -A value of false indicates that the client should not perform -router discovery. A value of true means that the client should perform -router discovery. -.RE -.PP -.B option \fBrouter-solicitation-address\fR \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the address to which the client should transmit -router solicitation requests. -.RE -.PP -.B option routers \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The routers option specifies a list of IP addresses for routers on the -client's subnet. Routers should be listed in order of preference. -.RE -.PP -.B option slp-directory-agent \fIboolean ip-address -[\fB,\fR \fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -This option specifies two things: the IP addresses of one or more -Service Location Protocol Directory Agents, and whether the use of -these addresses is mandatory. If the initial boolean value is true, -the SLP agent should just use the IP addresses given. If the value -is false, the SLP agent may additionally do active or passive -multicast discovery of SLP agents (see RFC2165 for details). -.PP -Please note that in this option and the slp-service-scope option, the -term "SLP Agent" is being used to refer to a Service Location Protocol -agent running on a machine that is being configured using the DHCP -protocol. -.PP -Also, please be aware that some companies may refer to SLP as NDS. -If you have an NDS directory agent whose address you need to -configure, the slp-directory-agent option should work. -.RE -.PP -.B option slp-service-scope \fIboolean text\fR\fB;\fR -.RS 0.25i -.PP -The Service Location Protocol Service Scope Option specifies two -things: a list of service scopes for SLP, and whether the use of this -list is mandatory. If the initial boolean value is true, the SLP -agent should only use the list of scopes provided in this option; -otherwise, it may use its own static configuration in preference to -the list provided in this option. -.PP -The text string should be a comma-separated list of scopes that the -SLP agent should use. It may be omitted, in which case the SLP Agent -will use the aggregated list of scopes of all directory agents known -to the SLP agent. -.RE -.PP -.B option \fBsmtp-server\fR \fIip-address\fR [\fB,\fR -\fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The SMTP server option specifies a list of SMTP servers available to -the client. Servers should be listed in order of preference. -.RE -.PP -.nf -.B option \fBstatic-routes\fR \fIip-address ip-address\fR - [\fB,\fR \fIip-address ip-address\fR...]\fB;\fR -.fi -.RS 0.25i -.PP -This option specifies a list of static routes that the client should -install in its routing cache. If multiple routes to the same -destination are specified, they are listed in descending order of -priority. -.PP -The routes consist of a list of IP address pairs. The first address -is the destination address, and the second address is the router for -the destination. -.PP -The default route (0.0.0.0) is an illegal destination for a static -route. To specify the default route, use the -.B routers -option. Also, please note that this option is not intended for -classless IP routing - it does not include a subnet mask. Since -classless IP routing is now the most widely deployed routing standard, -this option is virtually useless, and is not implemented by any of the -popular DHCP clients, for example the Microsoft DHCP client. -.RE -.PP -.nf -.B option \fBstreettalk-directory-assistance-server\fR \fIip-address\fR - [\fB,\fR \fIip-address\fR...]\fB;\fR -.fi -.RS 0.25i -.PP -The StreetTalk Directory Assistance (STDA) server option specifies a -list of STDA servers available to the client. Servers should be -listed in order of preference. -.RE -.PP -.B option \fBstreettalk-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The StreetTalk server option specifies a list of StreetTalk servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option subnet-mask \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -The subnet mask option specifies the client's subnet mask as per RFC -950. If no subnet mask option is provided anywhere in scope, as a -last resort dhcpd will use the subnet mask from the subnet declaration -for the network on which an address is being assigned. However, -.I any -subnet-mask option declaration that is in scope for the address being -assigned will override the subnet mask specified in the subnet -declaration. -.RE -.PP -.B option \fBsubnet-selection\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -Sent by the client if an address is required in a subnet other than the one -that would normally be selected (based on the relaying address of the -connected subnet the request is obtained from). See RFC3011. Note that the -option number used by this server is 118; this has not always been the -defined number, and some clients may use a different value. Use of this -option should be regarded as slightly experimental! -.RE -.PP -This option is not user configurable in the server. -.PP -.PP -.B option \fBswap-server\fR \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -This specifies the IP address of the client's swap server. -.RE -.PP -.B option \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client should send TCP -keepalive messages with an octet of garbage for compatibility with -older implementations. A value of false indicates that a garbage octet -should not be sent. A value of true indicates that a garbage octet -should be sent. -.RE -.PP -.B option \fBtcp-keepalive-interval\fR \fIuint32\fR\fB;\fR -.RS 0.25i -.PP -This option specifies the interval (in seconds) that the client TCP -should wait before sending a keepalive message on a TCP connection. -The time is specified as a 32-bit unsigned integer. A value of zero -indicates that the client should not generate keepalive messages on -connections unless specifically requested by an application. -.RE -.PP -.B option \fBtftp-server-name\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option is used to identify a TFTP server and, if supported by the -client, should have the same effect as the \fBserver-name\fR -declaration. BOOTP clients are unlikely to support this option. -Some DHCP clients will support it, and others actually require it. -.RE -.PP -.B option time-offset \fIint32\fR\fB;\fR -.RS 0.25i -.PP -The time-offset option specifies the offset of the client's subnet in -seconds from Coordinated Universal Time (UTC). -.RE -.PP -.B option time-servers \fIip-address\fR [, \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -The time-server option specifies a list of RFC 868 time servers -available to the client. Servers should be listed in order of -preference. -.RE -.PP -.B option \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -This option specifies whether or not the client should negotiate the -use of trailers (RFC 893 [14]) when using the ARP protocol. A value -of 0 indicates that the client should not attempt to use trailers. A -value of true means that the client should attempt to use trailers. -.RE -.PP -.B option \fBuap-servers\fR \fItext\fR\fB;\fR -.RS 0.25i -.PP -This option specifies a list of URLs, each pointing to a user -authentication service that is capable of processing authentication -requests encapsulated in the User Authentication Protocol (UAP). UAP -servers can accept either HTTP 1.1 or SSLv3 connections. If the list -includes a URL that does not contain a port component, the normal -default port is assumed (i.e., port 80 for http and port 443 for -https). If the list includes a URL that does not contain a path -component, the path /uap is assumed. If more than one URL is -specified in this list, the URLs are separated by spaces. -.RE -.PP -.B option \fBuser-class\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -This option is used by some DHCP clients as a way for users to -specify identifying information to the client. This can be used in a -similar way to the vendor-class-identifier option, but the value of -the option is specified by the user, not the vendor. Most recent -DHCP clients have a way in the user interface to specify the value for -this identifier, usually as a text string. -.PP -.B option \fBvendor-class-identifier\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -This option is used by some DHCP clients to identify the vendor -type and possibly the configuration of a DHCP client. The information -is a string of bytes whose contents are specific to the vendor and are -not specified in a standard. To see what vendor class identifier a -clients are sending, you can write the following in your DHCP server -configuration file: -.nf -.PP -set vendor-class option vendor-class-identifier; -.fi -.PP -This will result in all entries in the DHCP server lease database file -for clients that sent vendor-class-identifier options having a set -statement that looks something like this: -.nf -.PP -set vendor-class "SUNW.Ultra-5_10"; -.fi -.PP -The vendor-class-identifier option is normally used by the DHCP server -to determine the options that are returned in the -.B vendor-encapsulated-options -option. Please see the VENDOR ENCAPSULATED OPTIONS section of the -dhcpd.conf manual page for further information. -.RE -.PP -.B option \fBvendor-encapsulated-options\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The \fBvendor-encapsulated-options\fR option can contain either a -single vendor-specific value or one or more vendor-specific -suboptions. This option is not normally specified in the DHCP server -configuration file - instead, a vendor class is defined for each -vendor, vendor class suboptions are defined, values for those -suboptions are defined, and the DHCP server makes up a response on -that basis. -.PP -Some default behaviours for well-known DHCP client vendors (currently, -the Microsoft Windows 2000 DHCP client) are configured automatically, -but otherwise this must be configured manually - see the VENDOR -ENCAPSULATED OPTIONS section of the \fIdhcpd.conf\fI manual page for -details. -.RE -.PP -.B option \fBwww-server\fR \fIip-address\fR [\fB,\fR -\fIip-address\fR... ]\fB;\fR -.RS 0.25i -.PP -The WWW server option specifies a list of WWW servers available -to the client. Servers should be listed in order of preference. -.RE -.PP -.B option \fBx-display-manager\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... -]\fB;\fR -.RS 0.25i -.PP -This option specifies a list of systems that are running the X Window -System Display Manager and are available to the client. Addresses -should be listed in order of preference. -.RE -.SH RELAY AGENT INFORMATION OPTION -An IETF draft, draft-ietf-dhc-agent-options-11.txt, defines a series -of encapsulated options that a relay agent can add to a DHCP packet -when relaying it to the DHCP server. The server can then make -address allocation decisions (or whatever other decisions it wants) -based on these options. The server also returns these options in any -replies it sends through the relay agent, so that the relay agent can -use the information in these options for delivery or accounting -purposes. -.PP -The current draft defines two options. To reference -these options in the dhcp server, specify the option space name, -"agent", followed by a period, followed by the option name. It is -not normally useful to define values for these options in the server, -although it is permissible. These options are not supported in the -client. -.PP -.B option \fBagent.circuit-id\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The circuit-id suboption encodes an agent-local identifier of the -circuit from which a DHCP client-to-server packet was received. It is -intended for use by agents in relaying DHCP responses back to the -proper circuit. The format of this option is currently defined to be -vendor-dependent, and will probably remain that way, although the -current draft allows for for the possibility of standardizing the -format in the future. -.RE -.PP -.B option \fBagent.remote-id\fR \fIstring\fR\fB;\fR -.RS 0.25i -.PP -The remote-id suboption encodes information about the remote host end -of a circuit. Examples of what it might contain include caller ID -information, username information, remote ATM address, cable modem ID, -and similar things. In principal, the meaning is not well-specified, -and it should generally be assumed to be an opaque object that is -administratively guaranteed to be unique to a particular remote end of -a circuit. -.RE -.SH THE CLIENT FQDN SUBOPTIONS -The Client FQDN option, currently defined in the Internet Draft -draft-ietf-dhc-fqdn-option-00.txt is not a standard yet, but is in -sufficiently wide use already that we have implemented it. Due to -the complexity of the option format, we have implemented it as a -suboption space rather than a single option. In general this -option should not be configured by the user - instead it should be -used as part of an automatic DNS update system. -.PP -.B option fqdn.no-client-update \fIflag\fB; -.RS 0.25i -.PP -When the client sends this, if it is true, it means the client will not -attempt to update its A record. When sent by the server to the client, -it means that the client \fIshould not\fR update its own A record. -.RE -.PP -.B option fqdn.server-update \fIflag\fB; -.RS 0.25i -.PP -When the client sends this to the server, it is requesting that the server -update its A record. When sent by the server, it means that the server -has updated (or is about to update) the client's A record. -.RE -.PP -.B option fqdn.encoded \fIflag\fB; -.RS 0.25i -.PP -If true, this indicates that the domain name included in the option is -encoded in DNS wire format, rather than as plain ASCII text. The client -normally sets this to false if it doesn't support DNS wire format in the -FQDN option. The server should always send back the same value that the -client sent. When this value is set on the configuration side, it controls -the format in which the \fIfqdn.fqdn\fR suboption is encoded. -.RE -.PP -.B option fqdn.rcode1 \fIflag\fB; -.PP -.B option fqdn.rcode1 \fIflag\fB; -.RS 0.25i -.PP -These options specify the result of the updates of the A and PTR records, -respectively, and are only sent by the DHCP server to the DHCP client. -The values of these fields are those defined in the DNS protocol specification. -.RE -.PP -.B option fqdn.fqdn \fItext\fB; -.RS 0.25i -.PP -Specifies the domain name that the client wishes to use. This can be a -fully-qualified domain name, or a single label. If there is no trailing -'.' character in the name, it is not fully-qualified, and the server will -generally update that name in some locally-defined domain. -.RE -.PP -.B option fqdn.hostname \fI--never set--\fB; -.RS 0.25i -.PP -This option should never be set, but it can be read back using the \fBoption\fR -and \fBconfig-option\fR operators in an expression, in which case it returns -the first label in the \fBfqdn.fqdn\fR suboption - for example, if -the value of \fBfqdn.fqdn\fR is "foo.example.com.", then \fBfqdn.hostname\fR -will be "foo". -.RE -.PP -.B option fqdn.domainname \fI--never set--\fB; -.RS 0.25i -.PP -This option should never be set, but it can be read back using the \fBoption\fR -and \fBconfig-option\fR operators in an expression, in which case it returns -all labels after the first label in the \fBfqdn.fqdn\fR suboption - for -example, if the value of \fBfqdn.fqdn\fR is "foo.example.com.", -then \fBfqdn.hostname\fR will be "example.com.". If this suboption value -is not set, it means that an unqualified name was sent in the fqdn option, -or that no fqdn option was sent at all. -.RE -.PP -If you wish to use any of these suboptions, we strongly recommend that you -refer to the Client FQDN option draft (or standard, when it becomes a -standard) - the documentation here is sketchy and incomplete in comparison, -and is just intended for reference by people who already understand the -Client FQDN option specification. -.SH THE NETWARE/IP SUBOPTIONS -RFC2242 defines a set of encapsulated options for Novell NetWare/IP -clients. To use these options in the dhcp server, specify the option -space name, "nwip", followed by a period, followed by the option name. -The following options can be specified: -.PP -.B option \fBnwip.nsq-broadcast\fR \fIflag\fR\fB;\fR -.RS 0.25i -.PP -If true, the client should use the NetWare Nearest Server Query to -locate a NetWare/IP server. The behaviour of the Novell client if -this suboption is false, or is not present, is not specified. -.PP -.RE -.B option \fBnwip.preferred-dss\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fR\fB;\fR -.RS 0.25i -.PP -This suboption specifies a list of up to five IP addresses, each of -which should be the IP address of a NetWare Domain SAP/RIP server -(DSS). -.RE -.PP -.B option \fBnwip.nearest-nwip-server\fR \fI\fIip-address\fR - [\fB,\fR \fIip-address\fR...]\fR\fB;\fR -.RS 0.25i -.PP -This suboption specifies a list of up to five IP addresses, each of -which should be the IP address of a Nearest NetWare IP server. -.RE -.PP -.B option \fBnwip.autoretries\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -Specifies the number of times that a NetWare/IP client should attempt -to communicate with a given DSS server at startup. -.RE -.PP -.B option \fBnwip.autoretry-secs\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -Specifies the number of seconds that a Netware/IP client should wait -between retries when attempting to establish communications with a DSS -server at startup. -.RE -.PP -.B option \fBnwip.nwip-1-1\fR \fIuint8\fR\fB;\fR -.RS 0.25i -.PP -If true, the NetWare/IP client should support NetWare/IP version 1.1 -compatibility. This is only needed if the client will be contacting -Netware/IP version 1.1 servers. -.RE -.PP -.B option \fBnwip.primary-dss\fR \fIip-address\fR\fB;\fR -.RS 0.25i -.PP -Specifies the IP address of the Primary Domain SAP/RIP Service server -(DSS) for this NetWare/IP domain. The NetWare/IP administration -utility uses this value as Primary DSS server when configuring a -secondary DSS server. -.RE -.SH DEFINING NEW OPTIONS -The Internet Systems Consortium DHCP client and server provide the -capability to define new options. Each DHCP option has a name, a -code, and a structure. The name is used by you to refer to the -option. The code is a number, used by the DHCP server and client to -refer to an option. The structure describes what the contents of an -option looks like. -.PP -To define a new option, you need to choose a name for it that is not -in use for some other option - for example, you can't use "host-name" -because the DHCP protocol already defines a host-name option, which is -documented earlier in this manual page. If an option name doesn't -appear in this manual page, you can use it, but it's probably a good -idea to put some kind of unique string at the beginning so you can be -sure that future options don't take your name. For example, you -might define an option, "local-host-name", feeling some confidence -that no official DHCP option name will ever start with "local". -.PP -Once you have chosen a name, you must choose a code. For site-local -options, all codes between 128 and 254 are reserved for DHCP options, -so you can pick any one of these. In practice, some vendors have -interpreted the protocol rather loosely and have used option code -values greater than 128 themselves. There's no real way to avoid -this problem, but it's not likely to cause too much trouble in -practice. -.PP -The structure of an option is simply the format in which the option -data appears. The ISC DHCP server currently supports a few simple -types, like integers, booleans, strings and IP addresses, and it also -supports the ability to define arrays of single types or arrays of -fixed sequences of types. -.PP -New options are declared as follows: -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.I definition -.B ; -.PP -The values of -.I new-name -and -.I new-code -should be the name you have chosen for the new option and the code you -have chosen. The -.I definition -should be the definition of the structure of the option. -.PP -The following simple option type definitions are supported: -.PP -.B BOOLEAN -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.B boolean -.B ; -.PP -An option of type boolean is a flag with a value of either on or off -(or true or false). So an example use of the boolean type would be: -.nf - -option use-zephyr code 180 = boolean; -option use-zephyr on; - -.fi -.B INTEGER -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.I sign -.B integer -.I width -.B ; -.PP -The \fIsign\fR token should either be blank, \fIunsigned\fR -or \fIsigned\fR. The width can be either 8, 16 or 32, and refers to -the number of bits in the integer. So for example, the following two -lines show a definition of the sql-connection-max option and its use: -.nf - -option sql-connection-max code 192 = unsigned integer 16; -option sql-connection-max 1536; - -.fi -.B IP-ADDRESS -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.B ip-address -.B ; -.PP -An option whose structure is an IP address can be expressed either as -a domain name or as a dotted quad. So the following is an example use -of the ip-address type: -.nf - -option sql-server-address code 193 = ip-address; -option sql-server-address sql.example.com; - -.fi -.PP -.B TEXT -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.B text -.B ; -.PP -An option whose type is text will encode an ASCII text string. For -example: -.nf - -option sql-default-connection-name code 194 = text; -option sql-default-connection-name "PRODZA"; - -.fi -.PP -.B DATA STRING -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.B string -.B ; -.PP -An option whose type is a data string is essentially just a collection -of bytes, and can be specified either as quoted text, like the text -type, or as a list of hexadecimal contents separated by colons whose -values must be between 0 and FF. For example: -.nf - -option sql-identification-token code 195 = string; -option sql-identification-token 17:23:19:a6:42:ea:99:7c:22; - -.fi -.PP -.B ENCAPSULATION -.PP -.B option -.I new-name -.B code -.I new-code -.B = -.B encapsulate -.I identifier -.B ; -.PP -An option whose type is \fBencapsulate\fR will encapsulate the -contents of the option space specified in \fIidentifier\fR. Examples -of encapsulated options in the DHCP protocol as it currently exists -include the vendor-encapsulated-options option, the netware-suboptions -option and the relay-agent-information option. -.nf - -option space local; -option local.demo code 1 = text; -option local-encapsulation code 197 = encapsulate local; -option local.demo "demo"; - -.fi -.PP -.B ARRAYS -.PP -Options can contain arrays of any of the above types except for the -text and data string types, which aren't currently supported in -arrays. An example of an array definition is as follows: -.nf - -option kerberos-servers code 200 = array of ip-address; -option kerberos-servers 10.20.10.1, 10.20.11.1; - -.fi -.B RECORDS -.PP -Options can also contain data structures consisting of a sequence of -data types, which is sometimes called a record type. For example: -.nf - -option contrived-001 code 201 = { boolean, integer 32, text }; -option contrived-001 on 1772 "contrivance"; - -.fi -It's also possible to have options that are arrays of records, for -example: -.nf - -option new-static-routes code 201 = array of { - ip-address, ip-address, ip-address, integer 8 }; -option static-routes - 10.0.0.0 255.255.255.0 net-0-rtr.example.com 1, - 10.0.1.0 255.255.255.0 net-1-rtr.example.com 1, - 10.2.0.0 255.255.224.0 net-2-0-rtr.example.com 3; - -.fi -.SH VENDOR ENCAPSULATED OPTIONS -The DHCP protocol defines the \fB vendor-encapsulated-options\fR -option, which allows vendors to define their own options that will be -sent encapsulated in a standard DHCP option. The format of the -.B vendor-encapsulated-options -option is either a series of bytes whose format is not specified, or -a sequence of options, each of which consists of a single-byte -vendor-specific option code, followed by a single-byte length, -followed by as many bytes of data as are specified in the length (the -length does not include itself or the option code). -.PP -The value of this option can be set in one of two ways. The first -way is to simply specify the data directly, using a text string or a -colon-separated list of hexadecimal values. For example: -.PP -.nf -option vendor-encapsulated-options - 2:4:AC:11:41:1: - 3:12:73:75:6e:64:68:63:70:2d:73:65:72:76:65:72:31:37:2d:31: - 4:12:2f:65:78:70:6f:72:74:2f:72:6f:6f:74:2f:69:38:36:70:63; -.fi -.PP -The second way of setting the value of this option is to have the DHCP -server generate a vendor-specific option buffer. To do this, you -must do four things: define an option space, define some options in -that option space, provide values for them, and specify that that -option space should be used to generate the -.B vendor-encapsulated-options -option. -.PP -To define a new option space in which vendor options can be stored, -use the \fRoption space\fP statement: -.PP -.B option -.B space -.I name -.B ; -.PP -The name can then be used in option definitions, as described earlier in -this document. For example: -.nf - -option space SUNW; -option SUNW.server-address code 2 = ip-address; -option SUNW.server-name code 3 = text; -option SUNW.root-path code 4 = text; - -.fi -Once you have defined an option space and the format of some options, -you can set up scopes that define values for those options, and you -can say when to use them. For example, suppose you want to handle -two different classes of clients. Using the option space definition -shown in the previous example, you can send different option values to -different clients based on the vendor-class-identifier option that the -clients send, as follows: -.PP -.nf -class "vendor-classes" { - match option vendor-class-identifier; -} - -option SUNW.server-address 172.17.65.1; -option SUNW.server-name "sundhcp-server17-1"; - -subclass "vendor-classes" "SUNW.Ultra-5_10" { - vendor-option-space SUNW; - option SUNW.root-path "/export/root/sparc"; -} - -subclass "vendor-classes" "SUNW.i86pc" { - vendor-option-space SUNW; - option SUNW.root-path "/export/root/i86pc"; -} -.fi -.PP -As you can see in the preceding example, regular scoping rules apply, -so you can define values that are global in the global scope, and only -define values that are specific to a particular class in the local -scope. The \fBvendor-option-space\fR declaration tells the DHCP -server to use options in the SUNW option space to construct the -.B vendor-encapsulated-options -option. -.SH SEE ALSO -dhclient.conf(5), dhcp-eval(5), -dhclient(8), RFC2132, RFC2131. -.SH AUTHOR -The Internet Systems Consortium DHCP Distribution was written by Ted -Lemon under a contract with Vixie Labs. Funding for -this project was provided through Internet Systems Consortium. -Information about Internet Systems Consortium can be found at -.B http://www.isc.org. diff --git a/contrib/isc-dhcp/common/discover.c b/contrib/isc-dhcp/common/discover.c deleted file mode 100644 index c2f9d47..0000000 --- a/contrib/isc-dhcp/common/discover.c +++ /dev/null @@ -1,1138 +0,0 @@ -/* dispatch.c - - Network input dispatcher... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: discover.c,v 1.42.2.15 2004/06/10 17:59:16 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include <sys/ioctl.h> - -struct interface_info *interfaces, *dummy_interfaces, *fallback_interface; -int interfaces_invalidated; -int quiet_interface_discovery; -u_int16_t local_port; -u_int16_t remote_port; -int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *); -int (*dhcp_interface_discovery_hook) (struct interface_info *); -isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *); -int (*dhcp_interface_shutdown_hook) (struct interface_info *); - -struct in_addr limited_broadcast; -struct in_addr local_address; - -void (*bootp_packet_handler) PROTO ((struct interface_info *, - struct dhcp_packet *, unsigned, - unsigned int, - struct iaddr, struct hardware *)); - -omapi_object_type_t *dhcp_type_interface; -#if defined (TRACING) -trace_type_t *interface_trace; -trace_type_t *inpacket_trace; -trace_type_t *outpacket_trace; -#endif -struct interface_info **interface_vector; -int interface_count; -int interface_max; - -OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface) - -isc_result_t interface_setup () -{ - isc_result_t status; - status = omapi_object_type_register (&dhcp_type_interface, - "interface", - dhcp_interface_set_value, - dhcp_interface_get_value, - dhcp_interface_destroy, - dhcp_interface_signal_handler, - dhcp_interface_stuff_values, - dhcp_interface_lookup, - dhcp_interface_create, - dhcp_interface_remove, - 0, 0, 0, - sizeof (struct interface_info), - interface_initialize, RC_MISC); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register interface object type: %s", - isc_result_totext (status)); - - return status; -} - -#if defined (TRACING) -void interface_trace_setup () -{ - interface_trace = trace_type_register ("interface", (void *)0, - trace_interface_input, - trace_interface_stop, MDL); - inpacket_trace = trace_type_register ("inpacket", (void *)0, - trace_inpacket_input, - trace_inpacket_stop, MDL); - outpacket_trace = trace_type_register ("outpacket", (void *)0, - trace_outpacket_input, - trace_outpacket_stop, MDL); -} -#endif - -isc_result_t interface_initialize (omapi_object_t *ipo, - const char *file, int line) -{ - struct interface_info *ip = (struct interface_info *)ipo; - ip -> rfdesc = ip -> wfdesc = -1; - return ISC_R_SUCCESS; -} - -/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces. - For each interface that's of type INET and not the loopback interface, - register that interface with the network I/O software, figure out what - subnet it's on, and add it to the list of interfaces. */ - -void discover_interfaces (state) - int state; -{ - struct interface_info *tmp, *ip; - struct interface_info *last, *next; - char buf [2048]; - struct ifconf ic; - struct ifreq ifr; - int i; - int sock; - int address_count = 0; - struct subnet *subnet; - struct shared_network *share; - struct sockaddr_in foo; - int ir; - struct ifreq *tif; -#ifdef ALIAS_NAMES_PERMUTED - char *s; -#endif - isc_result_t status; - static int setup_fallback = 0; - int wifcount = 0; - - /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */ - if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - log_fatal ("Can't create addrlist socket"); - - /* Get the interface configuration information... */ - -#ifdef SIOCGIFCONF_ZERO_PROBE - /* linux will only tell us how long a buffer it wants if we give it - * a null buffer first. So, do a dry run to figure out the length. - * - * XXX this code is duplicated from below because trying to fold - * the logic into the if statement and goto resulted in excesssive - * obfuscation. The intent is that unless you run Linux you shouldn't - * have to deal with this. */ - - ic.ifc_len = 0; - ic.ifc_ifcu.ifcu_buf = (caddr_t)NULL; -#else - /* otherwise, we just feed it a starting size, and it'll tell us if - * it needs more */ - - ic.ifc_len = sizeof buf; - ic.ifc_ifcu.ifcu_buf = (caddr_t)buf; -#endif - - gifconf_again: - i = ioctl(sock, SIOCGIFCONF, &ic); - - if (i < 0) - log_fatal ("ioctl: SIOCGIFCONF: %m"); - -#ifdef SIOCGIFCONF_ZERO_PROBE - /* Workaround for SIOCGIFCONF bug on some Linux versions. */ - if (ic.ifc_ifcu.ifcu_buf == 0 && ic.ifc_len == 0) { - ic.ifc_len = sizeof buf; - ic.ifc_ifcu.ifcu_buf = (caddr_t)buf; - goto gifconf_again; - } -#endif - - /* If the SIOCGIFCONF resulted in more data than would fit in - a buffer, allocate a bigger buffer. */ - if ((ic.ifc_ifcu.ifcu_buf == buf -#ifdef SIOCGIFCONF_ZERO_PROBE - || ic.ifc_ifcu.ifcu_buf == 0 -#endif - ) && ic.ifc_len > sizeof buf) { - ic.ifc_ifcu.ifcu_buf = dmalloc ((size_t)ic.ifc_len, MDL); - if (!ic.ifc_ifcu.ifcu_buf) - log_fatal ("Can't allocate SIOCGIFCONF buffer."); - goto gifconf_again; -#ifdef SIOCGIFCONF_ZERO_PROBE - } else if (ic.ifc_ifcu.ifcu_buf == 0) { - ic.ifc_ifcu.ifcu_buf = (caddr_t)buf; - ic.ifc_len = sizeof buf; - goto gifconf_again; -#endif - } - - - /* If we already have a list of interfaces, and we're running as - a DHCP server, the interfaces were requested. */ - if (interfaces && (state == DISCOVER_SERVER || - state == DISCOVER_RELAY || - state == DISCOVER_REQUESTED)) - ir = 0; - else if (state == DISCOVER_UNCONFIGURED) - ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC; - else - ir = INTERFACE_REQUESTED; - - /* Cycle through the list of interfaces looking for IP addresses. */ - for (i = 0; i < ic.ifc_len;) { - struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i); -#ifdef HAVE_SA_LEN - if (ifp -> ifr_addr.sa_len > sizeof (struct sockaddr)) - i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len; - else -#endif - i += sizeof *ifp; - -#ifdef ALIAS_NAMES_PERMUTED - if ((s = strrchr (ifp -> ifr_name, ':'))) { - *s = 0; - } -#endif - -#ifdef SKIP_DUMMY_INTERFACES - if (!strncmp (ifp -> ifr_name, "dummy", 5)) - continue; -#endif - - - /* See if this is the sort of interface we want to - deal with. */ - strcpy (ifr.ifr_name, ifp -> ifr_name); - if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) - log_fatal ("Can't get interface flags for %s: %m", - ifr.ifr_name); - - /* See if we've seen an interface that matches this one. */ - for (tmp = interfaces; tmp; tmp = tmp -> next) - if (!strcmp (tmp -> name, ifp -> ifr_name)) - break; - - /* Skip non broadcast interfaces (plus loopback and - point-to-point in case an OS incorrectly marks them - as broadcast). Also skip down interfaces unless we're - trying to get a list of configurable interfaces. */ - if (((!(ifr.ifr_flags & IFF_BROADCAST) || - ifr.ifr_flags & IFF_LOOPBACK || - ifr.ifr_flags & IFF_POINTOPOINT) && !tmp) || - (!(ifr.ifr_flags & IFF_UP) && - state != DISCOVER_UNCONFIGURED)) - continue; - - /* If there isn't already an interface by this name, - allocate one. */ - if (!tmp) { - tmp = (struct interface_info *)0; - status = interface_allocate (&tmp, MDL); - if (status != ISC_R_SUCCESS) - log_fatal ("Error allocating interface %s: %s", - ifp -> ifr_name, - isc_result_totext (status)); - strcpy (tmp -> name, ifp -> ifr_name); - interface_snorf (tmp, ir); - interface_dereference (&tmp, MDL); - tmp = interfaces; /* XXX */ - } - - if (dhcp_interface_discovery_hook) - (*dhcp_interface_discovery_hook) (tmp); - - /* If we have the capability, extract link information - and record it in a linked list. */ -#ifdef HAVE_AF_LINK - if (ifp -> ifr_addr.sa_family == AF_LINK) { - struct sockaddr_dl *foo = ((struct sockaddr_dl *) - (&ifp -> ifr_addr)); -#if defined (HAVE_SIN_LEN) - tmp -> hw_address.hlen = foo -> sdl_alen; -#else - tmp -> hw_address.hlen = 6; /* XXX!!! */ -#endif - tmp -> hw_address.hbuf [0] = HTYPE_ETHER; /* XXX */ - memcpy (&tmp -> hw_address.hbuf [1], - LLADDR (foo), tmp -> hw_address.hlen); - tmp -> hw_address.hlen++; /* for type. */ - } else -#endif /* AF_LINK */ - - if (ifp -> ifr_addr.sa_family == AF_INET) { - struct iaddr addr; - - /* Get a pointer to the address... */ - memcpy (&foo, &ifp -> ifr_addr, - sizeof ifp -> ifr_addr); - - /* We don't want the loopback interface. */ - if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK) && - ((tmp -> flags & INTERFACE_AUTOMATIC) && - state == DISCOVER_SERVER)) - continue; - - - /* If this is the first real IP address we've - found, keep a pointer to ifreq structure in - which we found it. */ - if (!tmp -> ifp) { -#ifdef HAVE_SA_LEN - unsigned len = ((sizeof ifp -> ifr_name) + - ifp -> ifr_addr.sa_len); -#else - unsigned len = sizeof *ifp; -#endif - tif = (struct ifreq *)dmalloc (len, MDL); - if (!tif) - log_fatal ("no space for ifp."); - memcpy (tif, ifp, len); - tmp -> ifp = tif; - tmp -> primary_address = foo.sin_addr; - } - - /* Grab the address... */ - addr.len = 4; - memcpy (addr.iabuf, &foo.sin_addr.s_addr, - addr.len); - if (dhcp_interface_setup_hook) - (*dhcp_interface_setup_hook) (tmp, &addr); - } - } - - /* If we allocated a buffer, free it. */ - if (ic.ifc_ifcu.ifcu_buf != buf) - dfree (ic.ifc_ifcu.ifcu_buf, MDL); - -#if defined (LINUX_SLASHPROC_DISCOVERY) - /* On Linux, interfaces that don't have IP addresses don't - show up in the SIOCGIFCONF syscall. This only matters for - the DHCP client, of course - the relay agent and server - should only care about interfaces that are configured with - IP addresses anyway. - - The PROCDEV_DEVICE (/proc/net/dev) is a kernel-supplied file - that, when read, prints a human readable network status. We - extract the names of the network devices by skipping the first - two lines (which are header) and then parsing off everything - up to the colon in each subsequent line - these lines start - with the interface name, then a colon, then a bunch of - statistics. */ - - if (state == DISCOVER_UNCONFIGURED) { - FILE *proc_dev; - char buffer [256]; - int skip = 2; - - proc_dev = fopen (PROCDEV_DEVICE, "r"); - if (!proc_dev) - log_fatal ("%s: %m", PROCDEV_DEVICE); - - while (fgets (buffer, sizeof buffer, proc_dev)) { - char *name = buffer; - char *sep; - - /* Skip the first two blocks, which are header - lines. */ - if (skip) { - --skip; - continue; - } - - sep = strrchr (buffer, ':'); - if (sep) - *sep = '\0'; - while (*name == ' ') - name++; - - /* See if we've seen an interface that matches - this one. */ - for (tmp = interfaces; tmp; tmp = tmp -> next) - if (!strcmp (tmp -> name, name)) - break; - - /* If we found one, nothing more to do.. */ - if (tmp) - continue; - - /* Otherwise, allocate one. */ - tmp = (struct interface_info *)0; - status = interface_allocate (&tmp, MDL); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't allocate interface %s: %s", - name, isc_result_totext (status)); - tmp -> flags = ir; - strncpy (tmp -> name, name, IFNAMSIZ); - if (interfaces) { - interface_reference (&tmp -> next, - interfaces, MDL); - interface_dereference (&interfaces, MDL); - } - interface_reference (&interfaces, tmp, MDL); - interface_dereference (&tmp, MDL); - tmp = interfaces; - - if (dhcp_interface_discovery_hook) - (*dhcp_interface_discovery_hook) (tmp); - - } - fclose (proc_dev); - } -#endif - - /* Now cycle through all the interfaces we found, looking for - hardware addresses. */ -#if defined (HAVE_SIOCGIFHWADDR) && !defined (HAVE_AF_LINK) - for (tmp = interfaces; tmp; tmp = tmp -> next) { - struct ifreq ifr; - struct sockaddr sa; - int b, sk; - - if (!tmp -> ifp) { - /* Make up an ifreq structure. */ - tif = (struct ifreq *)dmalloc (sizeof (struct ifreq), - MDL); - if (!tif) - log_fatal ("no space to remember ifp."); - memset (tif, 0, sizeof (struct ifreq)); - strcpy (tif -> ifr_name, tmp -> name); - tmp -> ifp = tif; - } - - /* Read the hardware address from this interface. */ - ifr = *tmp -> ifp; - if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0) - continue; - - sa = *(struct sockaddr *)&ifr.ifr_hwaddr; - - switch (sa.sa_family) { -#ifdef HAVE_ARPHRD_TUNNEL - case ARPHRD_TUNNEL: - /* ignore tunnel interfaces. */ -#endif -#ifdef HAVE_ARPHRD_ROSE - case ARPHRD_ROSE: -#endif -#ifdef HAVE_ARPHRD_LOOPBACK - case ARPHRD_LOOPBACK: - /* ignore loopback interface */ - break; -#endif - - case ARPHRD_ETHER: - tmp -> hw_address.hlen = 7; - tmp -> hw_address.hbuf [0] = ARPHRD_ETHER; - memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); - break; - -#ifndef HAVE_ARPHRD_IEEE802 -# define ARPHRD_IEEE802 HTYPE_IEEE802 -#endif -#if defined (HAVE_ARPHRD_IEEE802_TR) - case ARPHRD_IEEE802_TR: -#endif - case ARPHRD_IEEE802: - tmp -> hw_address.hlen = 7; - tmp -> hw_address.hbuf [0] = ARPHRD_IEEE802; - memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); - break; - -#ifndef HAVE_ARPHRD_FDDI -# define ARPHRD_FDDI HTYPE_FDDI -#endif - case ARPHRD_FDDI: - tmp -> hw_address.hlen = 17; - tmp -> hw_address.hbuf [0] = HTYPE_FDDI; /* XXX */ - memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 16); - break; - -#ifdef HAVE_ARPHRD_METRICOM - case ARPHRD_METRICOM: - tmp -> hw_address.hlen = 7; - tmp -> hw_address.hbuf [0] = ARPHRD_METRICOM; - memcpy (&tmp -> hw_address.hbuf [0], sa.sa_data, 6); - break; -#endif - -#ifdef HAVE_ARPHRD_AX25 - case ARPHRD_AX25: - tmp -> hw_address.hlen = 7; - tmp -> hw_address.hbuf [0] = ARPHRD_AX25; - memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); - break; -#endif - -#ifdef HAVE_ARPHRD_NETROM - case ARPHRD_NETROM: - tmp -> hw_address.hlen = 7; - tmp -> hw_address.hbuf [0] = ARPHRD_NETROM; - memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); - break; -#endif - - default: - log_error ("%s: unknown hardware address type %d", - ifr.ifr_name, sa.sa_family); - break; - } - } -#endif /* defined (HAVE_SIOCGIFHWADDR) && !defined (HAVE_AF_LINK) */ - - /* If we're just trying to get a list of interfaces that we might - be able to configure, we can quit now. */ - if (state == DISCOVER_UNCONFIGURED) { - close (sock); - return; - } - - /* Weed out the interfaces that did not have IP addresses. */ - tmp = last = next = (struct interface_info *)0; - if (interfaces) - interface_reference (&tmp, interfaces, MDL); - while (tmp) { - if (next) - interface_dereference (&next, MDL); - if (tmp -> next) - interface_reference (&next, tmp -> next, MDL); - /* skip interfaces that are running already */ - if (tmp -> flags & INTERFACE_RUNNING) { - interface_dereference(&tmp, MDL); - if(next) - interface_reference(&tmp, next, MDL); - continue; - } - if ((tmp -> flags & INTERFACE_AUTOMATIC) && - state == DISCOVER_REQUESTED) - tmp -> flags &= ~(INTERFACE_AUTOMATIC | - INTERFACE_REQUESTED); - if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) { - if ((tmp -> flags & INTERFACE_REQUESTED) != ir) - log_fatal ("%s: not found", tmp -> name); - if (!last) { - if (interfaces) - interface_dereference (&interfaces, - MDL); - if (next) - interface_reference (&interfaces, next, MDL); - } else { - interface_dereference (&last -> next, MDL); - if (next) - interface_reference (&last -> next, - next, MDL); - } - if (tmp -> next) - interface_dereference (&tmp -> next, MDL); - - /* Remember the interface in case we need to know - about it later. */ - if (dummy_interfaces) { - interface_reference (&tmp -> next, - dummy_interfaces, MDL); - interface_dereference (&dummy_interfaces, MDL); - } - interface_reference (&dummy_interfaces, tmp, MDL); - interface_dereference (&tmp, MDL); - if (next) - interface_reference (&tmp, next, MDL); - continue; - } - last = tmp; - - memcpy (&foo, &tmp -> ifp -> ifr_addr, - sizeof tmp -> ifp -> ifr_addr); - - /* We must have a subnet declaration for each interface. */ - if (!tmp -> shared_network && (state == DISCOVER_SERVER)) { - log_error ("%s", ""); - log_error ("No subnet declaration for %s (%s).", - tmp -> name, inet_ntoa (foo.sin_addr)); - if (supports_multiple_interfaces (tmp)) { - log_error ("** Ignoring requests on %s. %s", - tmp -> name, "If this is not what"); - log_error (" you want, please write %s", - "a subnet declaration"); - log_error (" in your dhcpd.conf file %s", - "for the network segment"); - log_error (" to %s %s %s", - "which interface", - tmp -> name, "is attached. **"); - log_error ("%s", ""); - goto next; - } else { - log_error ("You must write a subnet %s", - " declaration for this"); - log_error ("subnet. You cannot prevent %s", - "the DHCP server"); - log_error ("from listening on this subnet %s", - "because your"); - log_fatal ("operating system does not %s.", - "support this capability"); - } - } - - /* Find subnets that don't have valid interface - addresses... */ - for (subnet = (tmp -> shared_network - ? tmp -> shared_network -> subnets - : (struct subnet *)0); - subnet; subnet = subnet -> next_sibling) { - if (!subnet -> interface_address.len) { - /* Set the interface address for this subnet - to the first address we found. */ - subnet -> interface_address.len = 4; - memcpy (subnet -> interface_address.iabuf, - &foo.sin_addr.s_addr, 4); - } - } - - /* Flag the index as not having been set, so that the - interface registerer can set it or not as it chooses. */ - tmp -> index = -1; - - /* Register the interface... */ - if_register_receive (tmp); - if_register_send (tmp); - - interface_stash (tmp); - wifcount++; -#if defined (HAVE_SETFD) - if (fcntl (tmp -> rfdesc, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on %s: %m", - tmp -> name); - if (tmp -> rfdesc != tmp -> wfdesc) { - if (fcntl (tmp -> wfdesc, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on %s: %m", - tmp -> name); - } -#endif - next: - interface_dereference (&tmp, MDL); - if (next) - interface_reference (&tmp, next, MDL); - } - - /* Now register all the remaining interfaces as protocols. */ - for (tmp = interfaces; tmp; tmp = tmp -> next) { - /* not if it's been registered before */ - if (tmp -> flags & INTERFACE_RUNNING) - continue; - if (tmp -> rfdesc == -1) - continue; - status = omapi_register_io_object ((omapi_object_t *)tmp, - if_readsocket, 0, - got_one, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - tmp -> name, isc_result_totext (status)); - } - - close (sock); - - if (state == DISCOVER_SERVER && wifcount == 0) { - log_info ("%s", ""); - log_fatal ("Not configured to listen on any interfaces!"); - } - - if (!setup_fallback) { - setup_fallback = 1; - maybe_setup_fallback (); - } - -#if defined (HAVE_SETFD) - if (fallback_interface) { - if (fcntl (fallback_interface -> rfdesc, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on fallback: %m"); - if (fallback_interface -> rfdesc != fallback_interface -> wfdesc) { - if (fcntl (fallback_interface -> wfdesc, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on fallback: %m"); - } - } -#endif -} - -int if_readsocket (h) - omapi_object_t *h; -{ - struct interface_info *ip; - - if (h -> type != dhcp_type_interface) - return -1; - ip = (struct interface_info *)h; - return ip -> rfdesc; -} - -int setup_fallback (struct interface_info **fp, const char *file, int line) -{ - isc_result_t status; - - status = interface_allocate (&fallback_interface, file, line); - if (status != ISC_R_SUCCESS) - log_fatal ("Error allocating fallback interface: %s", - isc_result_totext (status)); - strcpy (fallback_interface -> name, "fallback"); - if (dhcp_interface_setup_hook) - (*dhcp_interface_setup_hook) (fallback_interface, - (struct iaddr *)0); - status = interface_reference (fp, fallback_interface, file, line); - - fallback_interface -> index = -1; - interface_stash (fallback_interface); - return status == ISC_R_SUCCESS; -} - -void reinitialize_interfaces () -{ - struct interface_info *ip; - - for (ip = interfaces; ip; ip = ip -> next) { - if_reinitialize_receive (ip); - if_reinitialize_send (ip); - } - - if (fallback_interface) - if_reinitialize_send (fallback_interface); - - interfaces_invalidated = 1; -} - -isc_result_t got_one (h) - omapi_object_t *h; -{ - struct sockaddr_in from; - struct hardware hfrom; - struct iaddr ifrom; - int result; - union { - unsigned char packbuf [4095]; /* Packet input buffer. - Must be as large as largest - possible MTU. */ - struct dhcp_packet packet; - } u; - struct interface_info *ip; - - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - ip = (struct interface_info *)h; - - again: - if ((result = - receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) { - log_error ("receive_packet failed on %s: %m", ip -> name); - return ISC_R_UNEXPECTED; - } - if (result == 0) - return ISC_R_UNEXPECTED; - - /* If we didn't at least get the fixed portion of the BOOTP - packet, drop the packet. We're allowing packets with no - sname or filename, because we're aware of at least one - client that sends such packets, but this definitely falls - into the category of being forgiving. */ - if (result < DHCP_FIXED_NON_UDP - DHCP_SNAME_LEN - DHCP_FILE_LEN) - return ISC_R_UNEXPECTED; - - if (bootp_packet_handler) { - ifrom.len = 4; - memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); - - (*bootp_packet_handler) (ip, &u.packet, (unsigned)result, - from.sin_port, ifrom, &hfrom); - } - - /* If there is buffered data, read again. This is for, e.g., - bpf, which may return two packets at once. */ - if (ip -> rbuf_offset != ip -> rbuf_len) - goto again; - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_interface_set_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_typed_data_t *value) -{ - struct interface_info *interface; - isc_result_t status; - int foo; - - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - interface = (struct interface_info *)h; - - if (!omapi_ds_strcmp (name, "name")) { - if ((value -> type == omapi_datatype_data || - value -> type == omapi_datatype_string) && - value -> u.buffer.len < sizeof interface -> name) { - memcpy (interface -> name, - value -> u.buffer.value, - value -> u.buffer.len); - interface -> name [value -> u.buffer.len] = 0; - } else - return ISC_R_INVALIDARG; - return ISC_R_SUCCESS; - } - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> set_value) { - status = ((*(h -> inner -> type -> set_value)) - (h -> inner, id, name, value)); - if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED) - return status; - } - - return ISC_R_NOTFOUND; -} - - -isc_result_t dhcp_interface_get_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_value_t **value) -{ - return ISC_R_NOTIMPLEMENTED; -} - -isc_result_t dhcp_interface_destroy (omapi_object_t *h, - const char *file, int line) -{ - struct interface_info *interface; - isc_result_t status; - - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - interface = (struct interface_info *)h; - - if (interface -> ifp) { - dfree (interface -> ifp, file, line); - interface -> ifp = 0; - } - if (interface -> next) - interface_dereference (&interface -> next, file, line); - if (interface -> rbuf) { - dfree (interface -> rbuf, file, line); - interface -> rbuf = (unsigned char *)0; - } - if (interface -> client) - interface -> client = (struct client_state *)0; - - if (interface -> shared_network) - omapi_object_dereference ((omapi_object_t **) - &interface -> shared_network, MDL); - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_interface_signal_handler (omapi_object_t *h, - const char *name, va_list ap) -{ - struct interface_info *ip, *interface; - struct client_config *config; - struct client_state *client; - isc_result_t status; - - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - interface = (struct interface_info *)h; - - /* If it's an update signal, see if the interface is dead right - now, or isn't known at all, and if that's the case, revive it. */ - if (!strcmp (name, "update")) { - for (ip = dummy_interfaces; ip; ip = ip -> next) - if (ip == interface) - break; - if (ip && dhcp_interface_startup_hook) - return (*dhcp_interface_startup_hook) (ip); - - for (ip = interfaces; ip; ip = ip -> next) - if (ip == interface) - break; - if (!ip && dhcp_interface_startup_hook) - return (*dhcp_interface_startup_hook) (ip); - } - - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> signal_handler)) - (h -> inner, name, ap)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_interface_stuff_values (omapi_object_t *c, - omapi_object_t *id, - omapi_object_t *h) -{ - struct interface_info *interface; - isc_result_t status; - - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - interface = (struct interface_info *)h; - - /* Write out all the values. */ - - status = omapi_connection_put_name (c, "state"); - if (status != ISC_R_SUCCESS) - return status; - if (interface -> flags && INTERFACE_REQUESTED) - status = omapi_connection_put_string (c, "up"); - else - status = omapi_connection_put_string (c, "down"); - if (status != ISC_R_SUCCESS) - return status; - - /* Write out the inner object, if any. */ - if (h -> inner && h -> inner -> type -> stuff_values) { - status = ((*(h -> inner -> type -> stuff_values)) - (c, id, h -> inner)); - if (status == ISC_R_SUCCESS) - return status; - } - - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_interface_lookup (omapi_object_t **ip, - omapi_object_t *id, - omapi_object_t *ref) -{ - omapi_value_t *tv = (omapi_value_t *)0; - isc_result_t status; - struct interface_info *interface; - - if (!ref) - return ISC_R_NOKEYS; - - /* First see if we were sent a handle. */ - status = omapi_get_value_str (ref, id, "handle", &tv); - if (status == ISC_R_SUCCESS) { - status = omapi_handle_td_lookup (ip, tv -> value); - - omapi_value_dereference (&tv, MDL); - if (status != ISC_R_SUCCESS) - return status; - - /* Don't return the object if the type is wrong. */ - if ((*ip) -> type != dhcp_type_interface) { - omapi_object_dereference (ip, MDL); - return ISC_R_INVALIDARG; - } - } - - /* Now look for an interface name. */ - status = omapi_get_value_str (ref, id, "name", &tv); - if (status == ISC_R_SUCCESS) { - char *s; - unsigned len; - for (interface = interfaces; interface; - interface = interface -> next) { - s = memchr (interface -> name, 0, IFNAMSIZ); - if (s) - len = s - &interface -> name [0]; - else - len = IFNAMSIZ; - if ((tv -> value -> u.buffer.len == len && - !memcmp (interface -> name, - (char *)tv -> value -> u.buffer.value, - len))) - break; - } - if (!interface) { - for (interface = dummy_interfaces; - interface; interface = interface -> next) { - s = memchr (interface -> name, 0, IFNAMSIZ); - if (s) - len = s - &interface -> name [0]; - else - len = IFNAMSIZ; - if ((tv -> value -> u.buffer.len == len && - !memcmp (interface -> name, - (char *) - tv -> value -> u.buffer.value, - len))) - break; - } - } - - omapi_value_dereference (&tv, MDL); - if (*ip && *ip != (omapi_object_t *)interface) { - omapi_object_dereference (ip, MDL); - return ISC_R_KEYCONFLICT; - } else if (!interface) { - if (*ip) - omapi_object_dereference (ip, MDL); - return ISC_R_NOTFOUND; - } else if (!*ip) - omapi_object_reference (ip, - (omapi_object_t *)interface, - MDL); - } - - /* If we get to here without finding an interface, no valid key was - specified. */ - if (!*ip) - return ISC_R_NOKEYS; - return ISC_R_SUCCESS; -} - -/* actually just go discover the interface */ -isc_result_t dhcp_interface_create (omapi_object_t **lp, - omapi_object_t *id) -{ - struct interface_info *hp; - isc_result_t status; - - hp = (struct interface_info *)0; - status = interface_allocate (&hp, MDL); - if (status != ISC_R_SUCCESS) - return status; - hp -> flags = INTERFACE_REQUESTED; - status = interface_reference ((struct interface_info **)lp, hp, MDL); - interface_dereference (&hp, MDL); - return status; -} - -isc_result_t dhcp_interface_remove (omapi_object_t *lp, - omapi_object_t *id) -{ - struct interface_info *interface, *ip, *last; - - interface = (struct interface_info *)lp; - - /* remove from interfaces */ - last = 0; - for (ip = interfaces; ip; ip = ip -> next) { - if (ip == interface) { - if (last) { - interface_dereference (&last -> next, MDL); - if (ip -> next) - interface_reference (&last -> next, - ip -> next, MDL); - } else { - interface_dereference (&interfaces, MDL); - if (ip -> next) - interface_reference (&interfaces, - ip -> next, MDL); - } - if (ip -> next) - interface_dereference (&ip -> next, MDL); - break; - } - last = ip; - } - if (!ip) - return ISC_R_NOTFOUND; - - /* add the interface to the dummy_interface list */ - if (dummy_interfaces) { - interface_reference (&interface -> next, - dummy_interfaces, MDL); - interface_dereference (&dummy_interfaces, MDL); - } - interface_reference (&dummy_interfaces, interface, MDL); - - /* do a DHCPRELEASE */ - if (dhcp_interface_shutdown_hook) - (*dhcp_interface_shutdown_hook) (interface); - - /* remove the io object */ - omapi_unregister_io_object ((omapi_object_t *)interface); - - if_deregister_send (interface); - if_deregister_receive (interface); - - return ISC_R_SUCCESS; -} - -void interface_stash (struct interface_info *tptr) -{ - struct interface_info **vec; - int delta; - - /* If the registerer didn't assign an index, assign one now. */ - if (tptr -> index == -1) { - tptr -> index = interface_count++; - while (tptr -> index < interface_max && - interface_vector [tptr -> index]) - tptr -> index = interface_count++; - } - - if (interface_max <= tptr -> index) { - delta = tptr -> index - interface_max + 10; - vec = dmalloc ((interface_max + delta) * - sizeof (struct interface_info *), MDL); - if (!vec) - return; - memset (&vec [interface_max], 0, - (sizeof (struct interface_info *)) * delta); - interface_max += delta; - if (interface_vector) { - memcpy (vec, interface_vector, - (interface_count * - sizeof (struct interface_info *))); - dfree (interface_vector, MDL); - } - interface_vector = vec; - } - interface_reference (&interface_vector [tptr -> index], tptr, MDL); - if (tptr -> index >= interface_count) - interface_count = tptr -> index + 1; -#if defined (TRACING) - trace_interface_register (interface_trace, tptr); -#endif -} - -void interface_snorf (struct interface_info *tmp, int ir) -{ - tmp -> circuit_id = (u_int8_t *)tmp -> name; - tmp -> circuit_id_len = strlen (tmp -> name); - tmp -> remote_id = 0; - tmp -> remote_id_len = 0; - tmp -> flags = ir; - if (interfaces) { - interface_reference (&tmp -> next, - interfaces, MDL); - interface_dereference (&interfaces, MDL); - } - interface_reference (&interfaces, tmp, MDL); -} diff --git a/contrib/isc-dhcp/common/dispatch.c b/contrib/isc-dhcp/common/dispatch.c deleted file mode 100644 index 326ed1f..0000000 --- a/contrib/isc-dhcp/common/dispatch.c +++ /dev/null @@ -1,238 +0,0 @@ -/* dispatch.c - - Network input dispatcher... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: dispatch.c,v 1.63.2.4 2004/06/10 17:59:16 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n" -"$FreeBSD$\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -struct timeout *timeouts; -static struct timeout *free_timeouts; - -#ifdef ENABLE_POLLING_MODE -extern int polling_interval; -#endif - -void set_time (TIME t) -{ - /* Do any outstanding timeouts. */ - if (cur_time != t) { - cur_time = t; - process_outstanding_timeouts ((struct timeval *)0); - } -} - -struct timeval *process_outstanding_timeouts (struct timeval *tvp) -{ - /* Call any expired timeouts, and then if there's - still a timeout registered, time out the select - call then. */ - another: - if (timeouts) { - struct timeout *t; - if (timeouts -> when <= cur_time) { - t = timeouts; - timeouts = timeouts -> next; - (*(t -> func)) (t -> what); - if (t -> unref) - (*t -> unref) (&t -> what, MDL); - t -> next = free_timeouts; - free_timeouts = t; - goto another; - } - if (tvp) { - tvp -> tv_sec = timeouts -> when; - tvp -> tv_usec = 0; - } - return tvp; - } else - return (struct timeval *)0; -} - -/* Wait for packets to come in using select(). When one does, call - receive_packet to receive the packet and possibly strip hardware - addressing information from it, and then call through the - bootp_packet_handler hook to try to do something with it. */ - -void dispatch () -{ - struct timeval tv, *tvp; -#ifdef ENABLE_POLLING_MODE - struct timeval *tvp_new; -#endif - isc_result_t status; - - tvp = NULL; -#ifdef ENABLE_POLLING_MODE - tvp_new = NULL; -#endif - /* Wait for a packet or a timeout... XXX */ - do { - tvp = process_outstanding_timeouts (&tv); -#ifdef ENABLE_POLLING_MODE - GET_TIME (&cur_time); - add_timeout(cur_time + polling_interval, state_polling, 0, 0, 0); - tvp_new = process_outstanding_timeouts(&tv); - if (tvp != NULL && (tvp -> tv_sec > tvp_new -> tv_sec)) - tvp = tvp_new; -#endif /* ENABLE_POLLING_MODE */ - status = omapi_one_dispatch (0, tvp); - } while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS); - log_fatal ("omapi_one_dispatch failed: %s -- exiting.", - isc_result_totext (status)); -} - -void add_timeout (when, where, what, ref, unref) - TIME when; - void (*where) PROTO ((void *)); - void *what; - tvref_t ref; - tvunref_t unref; -{ - struct timeout *t, *q; - - /* See if this timeout supersedes an existing timeout. */ - t = (struct timeout *)0; - for (q = timeouts; q; q = q -> next) { - if ((where == NULL || q -> func == where) && - q -> what == what) { - if (t) - t -> next = q -> next; - else - timeouts = q -> next; - break; - } - t = q; - } - - /* If we didn't supersede a timeout, allocate a timeout - structure now. */ - if (!q) { - if (free_timeouts) { - q = free_timeouts; - free_timeouts = q -> next; - } else { - q = ((struct timeout *) - dmalloc (sizeof (struct timeout), MDL)); - if (!q) - log_fatal ("add_timeout: no memory!"); - } - memset (q, 0, sizeof *q); - q -> func = where; - q -> ref = ref; - q -> unref = unref; - if (q -> ref) - (*q -> ref)(&q -> what, what, MDL); - else - q -> what = what; - } - - q -> when = when; - - /* Now sort this timeout into the timeout list. */ - - /* Beginning of list? */ - if (!timeouts || timeouts -> when > q -> when) { - q -> next = timeouts; - timeouts = q; - return; - } - - /* Middle of list? */ - for (t = timeouts; t -> next; t = t -> next) { - if (t -> next -> when > q -> when) { - q -> next = t -> next; - t -> next = q; - return; - } - } - - /* End of list. */ - t -> next = q; - q -> next = (struct timeout *)0; -} - -void cancel_timeout (where, what) - void (*where) PROTO ((void *)); - void *what; -{ - struct timeout *t, *q; - - /* Look for this timeout on the list, and unlink it if we find it. */ - t = (struct timeout *)0; - for (q = timeouts; q; q = q -> next) { - if (q -> func == where && q -> what == what) { - if (t) - t -> next = q -> next; - else - timeouts = q -> next; - break; - } - t = q; - } - - /* If we found the timeout, put it on the free list. */ - if (q) { - if (q -> unref) - (*q -> unref) (&q -> what, MDL); - q -> next = free_timeouts; - free_timeouts = q; - } -} - -#if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -void cancel_all_timeouts () -{ - struct timeout *t, *n; - for (t = timeouts; t; t = n) { - n = t -> next; - if (t -> unref && t -> what) - (*t -> unref) (&t -> what, MDL); - t -> next = free_timeouts; - free_timeouts = t; - } -} - -void relinquish_timeouts () -{ - struct timeout *t, *n; - for (t = free_timeouts; t; t = n) { - n = t -> next; - dfree (t, MDL); - } -} -#endif diff --git a/contrib/isc-dhcp/common/dlpi.c b/contrib/isc-dhcp/common/dlpi.c deleted file mode 100644 index 08e9764..0000000 --- a/contrib/isc-dhcp/common/dlpi.c +++ /dev/null @@ -1,1336 +0,0 @@ -/* dlpi.c - - Data Link Provider Interface (DLPI) network interface code. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software was written for Internet Systems Consortium - * by Eric James Negaard, <lmdejn@lmd.ericsson.se>. To learn more about - * Internet Systems Consortium, see ``http://www.isc.org''. - * - * Joost Mulders has also done considerable work in debugging the DLPI API - * support on Solaris and getting this code to work properly on a variety - * of different Solaris platforms. - */ - -/* - * Based largely in part to the existing NIT code in nit.c. - * - * This code has been developed and tested on sparc-based machines running - * SunOS 5.5.1, with le and hme network interfaces. It should be pretty - * generic, though. - */ - -/* - * Implementation notes: - * - * I first tried to write this code to the "vanilla" DLPI 2.0 API. - * It worked on a Sun Ultra-1 with a hme interface, but didn't work - * on Sun SparcStation 5's with "le" interfaces (the packets sent out - * via dlpiunitdatareq contained an Ethernet type of 0x0000 instead - * of the expected 0x0800). - * - * Therefore I added the "DLPI_RAW" code which is a Sun extension to - * the DLPI standard. This code works on both of the above machines. - * This is configurable in the OS-dependent include file by defining - * USE_DLPI_RAW. - * - * It quickly became apparant that I should also use the "pfmod" - * STREAMS module to cut down on the amount of user level packet - * processing. I don't know how widely available "pfmod" is, so it's - * use is conditionally included. This is configurable in the - * OS-dependent include file by defining USE_DLPI_PFMOD. - * - * A major quirk on the Sun's at least, is that no packets seem to get - * sent out the interface until six seconds after the interface is - * first "attached" to [per system reboot] (it's actually from when - * the interface is attached, not when it is plumbed, so putting a - * sleep into the dhclient-script at PREINIT time doesn't help). I - * HAVE tried, without success to poll the fd to see when it is ready - * for writing. This doesn't help at all. If the sleeps are not done, - * the initial DHCPREQUEST or DHCPDISCOVER never gets sent out, so - * I've put them here, when register_send and register_receive are - * called (split up into two three-second sleeps between the notices, - * so that it doesn't seem like so long when you're watching :-). The - * amount of time to sleep is configurable in the OS-dependent include - * file by defining DLPI_FIRST_SEND_WAIT to be the number of seconds - * to sleep. - */ - -#ifndef lint -static char copyright[] = -"$Id: dlpi.c,v 1.28.2.2 2004/06/10 17:59:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) - -# include <sys/ioctl.h> -# include <sys/time.h> -# include <sys/dlpi.h> -# include <stropts.h> -# ifdef USE_DLPI_PFMOD -# include <sys/pfmod.h> -# endif -# ifdef USE_POLL -# include <poll.h> -# endif - -# include <netinet/in_systm.h> -# include "includes/netinet/ip.h" -# include "includes/netinet/udp.h" -# include "includes/netinet/if_ether.h" - -# ifdef USE_DLPI_PFMOD -# ifdef USE_DLPI_RAW -# define DLPI_MODNAME "DLPI+RAW+PFMOD" -# else -# define DLPI_MODNAME "DLPI+PFMOD" -# endif -# else -# ifdef USE_DLPI_RAW -# define DLPI_MODNAME "DLPI+RAW" -# else -# define DLPI_MODNAME "DLPI" -# endif -# endif - -# ifndef ABS -# define ABS(x) ((x) >= 0 ? (x) : 0-(x)) -# endif - -static int strioctl PROTO ((int fd, int cmd, int timeout, int len, char *dp)); - -#define DLPI_MAXDLBUF 8192 /* Buffer size */ -#define DLPI_MAXDLADDR 1024 /* Max address size */ -#define DLPI_DEVDIR "/dev/" /* Device directory */ - -static int dlpiopen PROTO ((char *ifname)); -static int dlpiunit PROTO ((char *ifname)); -static int dlpiinforeq PROTO ((int fd)); -static int dlpiphysaddrreq PROTO ((int fd, unsigned long addrtype)); -static int dlpiattachreq PROTO ((int fd, unsigned long ppa)); -static int dlpibindreq PROTO ((int fd, unsigned long sap, unsigned long max_conind, - unsigned long service_mode, unsigned long conn_mgmt, - unsigned long xidtest)); -static int dlpidetachreq PROTO ((int fd)); -static int dlpiunbindreq PROTO ((int fd)); -static int dlpiokack PROTO ((int fd, char *bufp)); -static int dlpiinfoack PROTO ((int fd, char *bufp)); -static int dlpiphysaddrack PROTO ((int fd, char *bufp)); -static int dlpibindack PROTO ((int fd, char *bufp)); -static int dlpiunitdatareq PROTO ((int fd, unsigned char *addr, - int addrlen, unsigned long minpri, - unsigned long maxpri, unsigned char *data, - int datalen)); -static int dlpiunitdataind PROTO ((int fd, - unsigned char *dstaddr, - unsigned long *dstaddrlen, - unsigned char *srcaddr, - unsigned long *srcaddrlen, - unsigned long *grpaddr, - unsigned char *data, - int datalen)); - -# ifndef USE_POLL -static void sigalrm PROTO ((int sig)); -# endif -static int expected PROTO ((unsigned long prim, union DL_primitives *dlp, - int msgflags)); -static int strgetmsg PROTO ((int fd, struct strbuf *ctlp, - struct strbuf *datap, int *flagsp, - char *caller)); - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#ifdef USE_DLPI_SEND -void if_reinitialize_send (info) - struct interface_info *info; -{ -} -#endif - -#ifdef USE_DLPI_RECEIVE -void if_reinitialize_receive (info) - struct interface_info *info; -{ -} -#endif - -/* Called by get_interface_list for each interface that's discovered. - Opens a packet filter for each interface and adds it to the select - mask. */ - -int if_register_dlpi (info) - struct interface_info *info; -{ - int sock; - int unit; - long buf [DLPI_MAXDLBUF]; - union DL_primitives *dlp; - - dlp = (union DL_primitives *)buf; - - /* Open a DLPI device */ - if ((sock = dlpiopen (info -> name)) < 0) { - log_fatal ("Can't open DLPI device for %s: %m", info -> name); - } - - - /* - * Submit a DL_INFO_REQ request, to find the dl_mac_type and - * dl_provider_style - */ - if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) { - log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name); - } else { - switch (dlp -> info_ack.dl_mac_type) { - case DL_CSMACD: /* IEEE 802.3 */ - case DL_ETHER: - info -> hw_address.hbuf [0] = HTYPE_ETHER; - break; - /* adding token ring 5/1999 - mayer@ping.at */ - case DL_TPR: - info -> hw_address.hbuf [0] = HTYPE_IEEE802; - break; - case DL_FDDI: - info -> hw_address.hbuf [0] = HTYPE_FDDI; - break; - default: - log_fatal ("%s: unsupported DLPI MAC type %ld", - info -> name, dlp -> info_ack.dl_mac_type); - break; - } - /* - * copy the sap length and broadcast address of this interface - * to interface_info. This fixes nothing but seemed nicer than to - * assume -2 and ffffff. - */ - info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length; - info -> dlpi_broadcast_addr.hlen = - dlp -> info_ack.dl_brdcst_addr_length; - memcpy (info -> dlpi_broadcast_addr.hbuf, - (char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset, - dlp -> info_ack.dl_brdcst_addr_length); - } - - if (dlp -> info_ack.dl_provider_style == DL_STYLE2) { - /* - * Attach to the device. If this fails, the device - * does not exist. - */ - unit = dlpiunit (info -> name); - - if (dlpiattachreq (sock, unit) < 0 - || dlpiokack (sock, (char *)buf) < 0) { - log_fatal ("Can't attach DLPI device for %s: %m", info -> name); - } - } - - /* - * Bind to the IP service access point (SAP), connectionless (CLDLS). - */ - if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0 - || dlpibindack (sock, (char *)buf) < 0) { - log_fatal ("Can't bind DLPI device for %s: %m", info -> name); - } - - /* - * Submit a DL_PHYS_ADDR_REQ request, to find - * the hardware address - */ - if (dlpiphysaddrreq (sock, DL_CURR_PHYS_ADDR) < 0 - || dlpiphysaddrack (sock, (char *)buf) < 0) { - log_fatal ("Can't get DLPI hardware address for %s: %m", - info -> name); - } - - info -> hw_address.hlen = dlp -> physaddr_ack.dl_addr_length + 1; - memcpy (&info -> hw_address.hbuf [1], - (char *)buf + dlp -> physaddr_ack.dl_addr_offset, - dlp -> physaddr_ack.dl_addr_length); - -#ifdef USE_DLPI_RAW - if (strioctl (sock, DLIOCRAW, INFTIM, 0, 0) < 0) { - log_fatal ("Can't set DLPI RAW mode for %s: %m", - info -> name); - } -#endif - -#ifdef USE_DLPI_PFMOD - if (ioctl (sock, I_PUSH, "pfmod") < 0) { - log_fatal ("Can't push packet filter onto DLPI for %s: %m", - info -> name); - } -#endif - - return sock; -} - -static int -strioctl (fd, cmd, timeout, len, dp) -int fd; -int cmd; -int timeout; -int len; -char *dp; -{ - struct strioctl sio; - int rslt; - - sio.ic_cmd = cmd; - sio.ic_timout = timeout; - sio.ic_len = len; - sio.ic_dp = dp; - - if ((rslt = ioctl (fd, I_STR, &sio)) < 0) { - return rslt; - } else { - return sio.ic_len; - } -} - -#ifdef USE_DLPI_SEND -void if_register_send (info) - struct interface_info *info; -{ - /* If we're using the DLPI API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_DLPI_RECEIVE -# ifdef USE_DLPI_PFMOD - struct packetfilt pf; -# endif - - info -> wfdesc = if_register_dlpi (info); - -# ifdef USE_DLPI_PFMOD - /* Set up an PFMOD filter that rejects everything... */ - pf.Pf_Priority = 0; - pf.Pf_FilterLen = 1; - pf.Pf_Filter [0] = ENF_PUSHZERO; - - /* Install the filter */ - if (strioctl (info -> wfdesc, PFIOCSETF, INFTIM, - sizeof (pf), (char *)&pf) < 0) { - log_fatal ("Can't set PFMOD send filter on %s: %m", info -> name); - } - -# endif /* USE_DLPI_PFMOD */ -#else /* !defined (USE_DLPI_RECEIVE) */ - /* - * If using DLPI for both send and receive, simply re-use - * the read file descriptor that was set up earlier. - */ - info -> wfdesc = info -> rfdesc; -#endif - - if (!quiet_interface_discovery) - log_info ("Sending on DLPI/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); - -#ifdef DLPI_FIRST_SEND_WAIT -/* See the implementation notes at the beginning of this file */ -# ifdef USE_DLPI_RECEIVE - sleep (DLPI_FIRST_SEND_WAIT - (DLPI_FIRST_SEND_WAIT / 2)); -# else - sleep (DLPI_FIRST_SEND_WAIT); -# endif -#endif -} - -void if_deregister_send (info) - struct interface_info *info; -{ - /* If we're using the DLPI API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_DLPI_RECEIVE - close (info -> wfdesc); -#endif - info -> wfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling output on DLPI/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_DLPI_SEND */ - -#ifdef USE_DLPI_RECEIVE -/* Packet filter program... - XXX Changes to the filter program may require changes to the constant - offsets used in if_register_send to patch the NIT program! XXX */ - -void if_register_receive (info) - struct interface_info *info; -{ -#ifdef USE_DLPI_PFMOD - struct packetfilt pf; - struct ip iphdr; - u_int16_t offset; -#endif - - /* Open a DLPI device and hang it on this interface... */ - info -> rfdesc = if_register_dlpi (info); - -#ifdef USE_DLPI_PFMOD - /* Set up the PFMOD filter program. */ - /* XXX Unlike the BPF filter program, this one won't work if the - XXX IP packet is fragmented or if there are options on the IP - XXX header. */ - pf.Pf_Priority = 0; - pf.Pf_FilterLen = 0; - -#if defined (USE_DLPI_RAW) -# define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */ - /* - * ethertype == ETHERTYPE_IP - */ - offset = 12; - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND; - pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP); -# else -# define ETHER_H_PREFIX (0) -# endif /* USE_DLPI_RAW */ - /* - * The packets that will be received on this file descriptor - * will be IP packets (due to the SAP that was specified in - * the dlbind call). There will be no ethernet header. - * Therefore, setup the packet filter to check the protocol - * field for UDP, and the destination port number equal - * to the local port. All offsets are relative to the start - * of an IP packet. - */ - - /* - * BOOTPS destination port - */ - offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND; - pf.Pf_Filter [pf.Pf_FilterLen++] = local_port; - - /* - * protocol should be udp. this is a byte compare, test for - * endianess. - */ - offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND; - pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND; - pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP); - - /* Install the filter... */ - if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM, - sizeof (pf), (char *)&pf) < 0) { - log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name); - } -#endif /* USE_DLPI_PFMOD */ - - if (!quiet_interface_discovery) - log_info ("Listening on DLPI/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); - -#ifdef DLPI_FIRST_SEND_WAIT -/* See the implementation notes at the beginning of this file */ -# ifdef USE_DLPI_SEND - sleep (DLPI_FIRST_SEND_WAIT / 2); -# else - sleep (DLPI_FIRST_SEND_WAIT); -# endif -#endif -} - -void if_deregister_receive (info) - struct interface_info *info; -{ - /* If we're using the DLPI API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_DLPI_SEND - close (info -> rfdesc); -#endif - info -> rfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling input on DLPI/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_DLPI_RECEIVE */ - -#ifdef USE_DLPI_SEND -ssize_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - unsigned hbufp = 0; - double hh [32]; - double ih [1536 / sizeof (double)]; - unsigned char *dbuf = (unsigned char *)ih; - unsigned dbuflen; - unsigned char dstaddr [DLPI_MAXDLADDR]; - unsigned addrlen; - int result; - int fudge; - - if (!strcmp (interface -> name, "fallback")) - return send_fallback (interface, packet, raw, - len, from, to, hto); - - dbuflen = 0; - - /* Assemble the headers... */ -#ifdef USE_DLPI_RAW - assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto); - if (dbuflen > sizeof hh) - log_fatal ("send_packet: hh buffer too small.\n"); - fudge = dbuflen % 4; /* IP header must be word-aligned. */ - memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen); - dbuflen += fudge; -#else - fudge = 0; -#endif - assemble_udp_ip_header (interface, dbuf, &dbuflen, from.s_addr, - to -> sin_addr.s_addr, to -> sin_port, - (unsigned char *)raw, len); - - /* Copy the data into the buffer (yuk). */ - memcpy (dbuf + dbuflen, raw, len); - dbuflen += len; - -#ifdef USE_DLPI_RAW - result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge); -#else - - /* - * Setup the destination address (DLSAP) in dstaddr - * - * If sap_length < 0 we must deliver the DLSAP as phys+sap. - * If sap_length > 0 we must deliver the DLSAP as sap+phys. - * - * sap = Service Access Point == ETHERTYPE_IP - * sap + datalink address is called DLSAP in dlpi speak. - */ - { /* ENCODE DLSAP */ - unsigned char phys [DLPI_MAXDLADDR]; - unsigned char sap [4]; - int sap_len = interface -> dlpi_sap_length; - int phys_len = interface -> hw_address.hlen - 1; - - /* sap = htons (ETHERTYPE_IP) kludge */ - memset (sap, 0, sizeof (sap)); -# if (BYTE_ORDER == LITTLE_ENDIAN) - sap [0] = 0x00; - sap [1] = 0x08; -# else - sap [0] = 0x08; - sap [1] = 0x00; -# endif - - if (hto && hto -> hlen == interface -> hw_address.hlen) - memcpy ( phys, (char *) &hto -> hbuf [1], phys_len); - else - memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf, - interface -> dlpi_broadcast_addr.hlen); - - if (sap_len < 0) { - memcpy ( dstaddr, phys, phys_len); - memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len)); - } - else { - memcpy ( dstaddr, (void *) sap, sap_len); - memcpy ( (char *) &dstaddr [sap_len], phys, phys_len); - } - addrlen = phys_len + ABS (sap_len); - } /* ENCODE DLSAP */ - - result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen, - 0, 0, dbuf, dbuflen); -#endif /* USE_DLPI_RAW */ - if (result < 0) - log_error ("send_packet: %m"); - return result; -} -#endif /* USE_DLPI_SEND */ - -#ifdef USE_DLPI_RECEIVE -ssize_t receive_packet (interface, buf, len, from, hfrom) - struct interface_info *interface; - unsigned char *buf; - size_t len; - struct sockaddr_in *from; - struct hardware *hfrom; -{ - unsigned char dbuf [1536]; - unsigned char srcaddr [DLPI_MAXDLADDR]; - unsigned long srcaddrlen; - int flags = 0; - int length = 0; - int offset = 0; - int rslt; - int bufix = 0; - -#ifdef USE_DLPI_RAW - length = read (interface -> rfdesc, dbuf, sizeof (dbuf)); -#else - length = dlpiunitdataind (interface -> rfdesc, (unsigned char *)NULL, - (unsigned long *)NULL, srcaddr, &srcaddrlen, - (unsigned long *)NULL, dbuf, sizeof (dbuf)); -#endif - - if (length <= 0) { - return length; - } - -# if !defined (USE_DLPI_RAW) - /* - * Copy the sender's hw address into hfrom - * If sap_len < 0 the DLSAP is as phys+sap. - * If sap_len > 0 the DLSAP is as sap+phys. - * - * sap is discarded here. - */ - { /* DECODE DLSAP */ - int sap_len = interface -> dlpi_sap_length; - int phys_len = interface -> hw_address.hlen - 1; - - if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) { - hfrom -> hbuf [0] = interface -> hw_address.hbuf [0]; - hfrom -> hlen = interface -> hw_address.hlen; - - if (sap_len < 0) { - memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len); - } - else { - memcpy ((char *) &hfrom -> hbuf [1], (char *) &srcaddr [phys_len], - phys_len); - } - } - else if (hfrom) { - memset (hfrom, '\0', sizeof *hfrom); - } - } /* DECODE_DLSAP */ - -# endif /* !defined (USE_DLPI_RAW) */ - - /* Decode the IP and UDP headers... */ - bufix = 0; -#ifdef USE_DLPI_RAW - /* Decode the physical header... */ - offset = decode_hw_header (interface, dbuf, bufix, hfrom); - - /* If a physical layer checksum failed (dunno of any - physical layer that supports this, but WTH), skip this - packet. */ - if (offset < 0) { - return 0; - } - bufix += offset; - length -= offset; -#endif - offset = decode_udp_ip_header (interface, dbuf, bufix, - from, (unsigned char *)0, length); - - /* If the IP or UDP checksum was bad, skip the packet... */ - if (offset < 0) { - return 0; - } - - bufix += offset; - length -= offset; - - /* Copy out the data in the packet... */ - memcpy (buf, &dbuf [bufix], length); - return length; -} -#endif - -/* Common DLPI routines ... - * - * Written by Eric James Negaard, <lmdejn@lmd.ericsson.se> - * - * Based largely in part to the example code contained in the document - * "How to Use the STREAMS Data Link Provider Interface (DLPI)", written - * by Neal Nuckolls of SunSoft Internet Engineering. - * - * This code has been developed and tested on sparc-based machines running - * SunOS 5.5.1, with le and hme network interfaces. It should be pretty - * generic, though. - * - * The usual disclaimers apply. This code works for me. Don't blame me - * if it makes your machine or network go down in flames. That taken - * into consideration, use this code as you wish. If you make usefull - * modifications I'd appreciate hearing about it. - */ - -#define DLPI_MAXWAIT 15 /* Max timeout */ - - -/* - * Parse an interface name and extract the unit number - */ - -static int dlpiunit (ifname) - char *ifname; -{ - int fd; - char *cp, *dp, *ep; - int unit; - - if (!ifname) { - return 0; - } - - /* Advance to the end of the name */ - cp = ifname; - while (*cp) cp++; - /* Back up to the start of the first digit */ - while ((*(cp-1) >= '0' && *(cp-1) <= '9') || *(cp - 1) == ':') cp--; - - /* Convert the unit number */ - unit = 0; - while (*cp >= '0' && *cp <= '9') { - unit *= 10; - unit += (*cp++ - '0'); - } - - return unit; -} - -/* - * dlpiopen - open the DLPI device for a given interface name - */ -static int dlpiopen (ifname) - char *ifname; -{ - char devname [50]; - char *cp, *dp, *ep; - - if (!ifname) { - return -1; - } - - /* Open a DLPI device */ - if (*ifname == '/') { - dp = devname; - } else { - /* Prepend the device directory */ - memcpy (devname, DLPI_DEVDIR, strlen (DLPI_DEVDIR)); - dp = &devname [strlen (DLPI_DEVDIR)]; - } - - /* Find the end of the interface name */ - ep = cp = ifname; - while (*ep) - ep++; - /* And back up to the first digit (unit number) */ - while ((*(ep - 1) >= '0' && *(ep - 1) <= '9') || *(ep - 1) == ':') - ep--; - - /* Copy everything up to the unit number */ - while (cp < ep) { - *dp++ = *cp++; - } - *dp = '\0'; - - return open (devname, O_RDWR, 0); -} - -/* - * dlpiinforeq - request information about the data link provider. - */ - -static int dlpiinforeq (fd) - int fd; -{ - dl_info_req_t info_req; - struct strbuf ctl; - int flags; - - info_req.dl_primitive = DL_INFO_REQ; - - ctl.maxlen = 0; - ctl.len = sizeof (info_req); - ctl.buf = (char *)&info_req; - - flags = RS_HIPRI; - - return putmsg (fd, &ctl, (struct strbuf *)NULL, flags); -} - -/* - * dlpiphysaddrreq - request the current physical address. - */ -static int dlpiphysaddrreq (fd, addrtype) - int fd; - unsigned long addrtype; -{ - dl_phys_addr_req_t physaddr_req; - struct strbuf ctl; - int flags; - - physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; - physaddr_req.dl_addr_type = addrtype; - - ctl.maxlen = 0; - ctl.len = sizeof (physaddr_req); - ctl.buf = (char *)&physaddr_req; - - flags = RS_HIPRI; - - return putmsg (fd, &ctl, (struct strbuf *)NULL, flags); -} - -/* - * dlpiattachreq - send a request to attach to a specific unit. - */ -static int dlpiattachreq (fd, ppa) - unsigned long ppa; - int fd; -{ - dl_attach_req_t attach_req; - struct strbuf ctl; - int flags; - - attach_req.dl_primitive = DL_ATTACH_REQ; - attach_req.dl_ppa = ppa; - - ctl.maxlen = 0; - ctl.len = sizeof (attach_req); - ctl.buf = (char *)&attach_req; - - flags = 0; - - return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); -} - -/* - * dlpibindreq - send a request to bind to a specific SAP address. - */ -static int dlpibindreq (fd, sap, max_conind, service_mode, conn_mgmt, xidtest) - unsigned long sap; - unsigned long max_conind; - unsigned long service_mode; - unsigned long conn_mgmt; - unsigned long xidtest; - int fd; -{ - dl_bind_req_t bind_req; - struct strbuf ctl; - int flags; - - bind_req.dl_primitive = DL_BIND_REQ; - bind_req.dl_sap = sap; - bind_req.dl_max_conind = max_conind; - bind_req.dl_service_mode = service_mode; - bind_req.dl_conn_mgmt = conn_mgmt; - bind_req.dl_xidtest_flg = xidtest; - - ctl.maxlen = 0; - ctl.len = sizeof (bind_req); - ctl.buf = (char *)&bind_req; - - flags = 0; - - return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); -} - -/* - * dlpiunbindreq - send a request to unbind. - */ -static int dlpiunbindreq (fd) - int fd; -{ - dl_unbind_req_t unbind_req; - struct strbuf ctl; - int flags; - - unbind_req.dl_primitive = DL_UNBIND_REQ; - - ctl.maxlen = 0; - ctl.len = sizeof (unbind_req); - ctl.buf = (char *)&unbind_req; - - flags = 0; - - return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); -} - - -/* - * dlpidetachreq - send a request to detach. - */ -static int dlpidetachreq (fd) - int fd; -{ - dl_detach_req_t detach_req; - struct strbuf ctl; - int flags; - - detach_req.dl_primitive = DL_DETACH_REQ; - - ctl.maxlen = 0; - ctl.len = sizeof (detach_req); - ctl.buf = (char *)&detach_req; - - flags = 0; - - return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); -} - - -/* - * dlpibindack - receive an ack to a dlbindreq. - */ -static int dlpibindack (fd, bufp) - char *bufp; - int fd; -{ - union DL_primitives *dlp; - struct strbuf ctl; - int flags; - - ctl.maxlen = DLPI_MAXDLBUF; - ctl.len = 0; - ctl.buf = bufp; - - if (strgetmsg (fd, &ctl, - (struct strbuf*)NULL, &flags, "dlpibindack") < 0) { - return -1; - } - - dlp = (union DL_primitives *)ctl.buf; - - if (!expected (DL_BIND_ACK, dlp, flags) < 0) { - return -1; - } - - if (ctl.len < sizeof (dl_bind_ack_t)) { - /* Returned structure is too short */ - return -1; - } - - return 0; -} - -/* - * dlpiokack - general acknowledgement reception. - */ -static int dlpiokack (fd, bufp) - char *bufp; - int fd; -{ - union DL_primitives *dlp; - struct strbuf ctl; - int flags; - - ctl.maxlen = DLPI_MAXDLBUF; - ctl.len = 0; - ctl.buf = bufp; - - if (strgetmsg (fd, &ctl, - (struct strbuf*)NULL, &flags, "dlpiokack") < 0) { - return -1; - } - - dlp = (union DL_primitives *)ctl.buf; - - if (!expected (DL_OK_ACK, dlp, flags) < 0) { - return -1; - } - - if (ctl.len < sizeof (dl_ok_ack_t)) { - /* Returned structure is too short */ - return -1; - } - - return 0; -} - -/* - * dlpiinfoack - receive an ack to a dlinforeq. - */ -static int dlpiinfoack (fd, bufp) - char *bufp; - int fd; -{ - union DL_primitives *dlp; - struct strbuf ctl; - int flags; - - ctl.maxlen = DLPI_MAXDLBUF; - ctl.len = 0; - ctl.buf = bufp; - - if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags, - "dlpiinfoack") < 0) { - return -1; - } - - dlp = (union DL_primitives *) ctl.buf; - - if (!expected (DL_INFO_ACK, dlp, flags) < 0) { - return -1; - } - - if (ctl.len < sizeof (dl_info_ack_t)) { - /* Returned structure is too short */ - return -1; - } - - return 0; -} - -/* - * dlpiphysaddrack - receive an ack to a dlpiphysaddrreq. - */ -int dlpiphysaddrack (fd, bufp) - char *bufp; - int fd; -{ - union DL_primitives *dlp; - struct strbuf ctl; - int flags; - - ctl.maxlen = DLPI_MAXDLBUF; - ctl.len = 0; - ctl.buf = bufp; - - if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags, - "dlpiphysaddrack") < 0) { - return -1; - } - - dlp = (union DL_primitives *)ctl.buf; - - if (!expected (DL_PHYS_ADDR_ACK, dlp, flags) < 0) { - return -1; - } - - if (ctl.len < sizeof (dl_phys_addr_ack_t)) { - /* Returned structure is too short */ - return -1; - } - - return 0; -} - -int dlpiunitdatareq (fd, addr, addrlen, minpri, maxpri, dbuf, dbuflen) - int fd; - unsigned char *addr; - int addrlen; - unsigned long minpri; - unsigned long maxpri; - unsigned char *dbuf; - int dbuflen; -{ - long buf [DLPI_MAXDLBUF]; - union DL_primitives *dlp; - struct strbuf ctl, data; - - /* Set up the control information... */ - dlp = (union DL_primitives *)buf; - dlp -> unitdata_req.dl_primitive = DL_UNITDATA_REQ; - dlp -> unitdata_req.dl_dest_addr_length = addrlen; - dlp -> unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); - dlp -> unitdata_req.dl_priority.dl_min = minpri; - dlp -> unitdata_req.dl_priority.dl_max = maxpri; - - /* Append the destination address */ - memcpy ((char *)buf + dlp -> unitdata_req.dl_dest_addr_offset, - addr, addrlen); - - ctl.maxlen = 0; - ctl.len = dlp -> unitdata_req.dl_dest_addr_offset + addrlen; - ctl.buf = (char *)buf; - - data.maxlen = 0; - data.buf = (char *)dbuf; - data.len = dbuflen; - - /* Send the packet down the wire... */ - return putmsg (fd, &ctl, &data, 0); -} - -static int dlpiunitdataind (fd, daddr, daddrlen, - saddr, saddrlen, grpaddr, dbuf, dlen) - int fd; - unsigned char *daddr; - unsigned long *daddrlen; - unsigned char *saddr; - unsigned long *saddrlen; - unsigned long *grpaddr; - unsigned char *dbuf; - int dlen; -{ - long buf [DLPI_MAXDLBUF]; - union DL_primitives *dlp; - struct strbuf ctl, data; - int flags = 0; - int result; - - /* Set up the msg_buf structure... */ - dlp = (union DL_primitives *)buf; - dlp -> unitdata_ind.dl_primitive = DL_UNITDATA_IND; - - ctl.maxlen = DLPI_MAXDLBUF; - ctl.len = 0; - ctl.buf = (char *)buf; - - data.maxlen = dlen; - data.len = 0; - data.buf = (char *)dbuf; - - result = getmsg (fd, &ctl, &data, &flags); - - if (result != 0) { - return -1; - } - - if (ctl.len < sizeof (dl_unitdata_ind_t) || - dlp -> unitdata_ind.dl_primitive != DL_UNITDATA_IND) { - return -1; - } - - if (data.len <= 0) { - return data.len; - } - - /* Copy sender info */ - if (saddr) { - memcpy (saddr, - (char *)buf + dlp -> unitdata_ind.dl_src_addr_offset, - dlp -> unitdata_ind.dl_src_addr_length); - } - if (saddrlen) { - *saddrlen = dlp -> unitdata_ind.dl_src_addr_length; - } - - /* Copy destination info */ - if (daddr) { - memcpy (daddr, - (char *)buf + dlp -> unitdata_ind.dl_dest_addr_offset, - dlp -> unitdata_ind.dl_dest_addr_length); - } - if (daddrlen) { - *daddrlen = dlp -> unitdata_ind.dl_dest_addr_length; - } - - if (grpaddr) { - *grpaddr = dlp -> unitdata_ind.dl_group_address; - } - - return data.len; -} - -/* - * expected - see if we got what we wanted. - */ -static int expected (prim, dlp, msgflags) - unsigned long prim; - union DL_primitives *dlp; - int msgflags; -{ - if (msgflags != RS_HIPRI) { - /* Message was not M_PCPROTO */ - return 0; - } - - if (dlp -> dl_primitive != prim) { - /* Incorrect/unexpected return message */ - return 0; - } - - return 1; -} - -/* - * strgetmsg - get a message from a stream, with timeout. - */ -static int strgetmsg (fd, ctlp, datap, flagsp, caller) - struct strbuf *ctlp, *datap; - char *caller; - int *flagsp; - int fd; -{ - int result; -#ifdef USE_POLL - struct pollfd pfd; - int count; - time_t now; - time_t starttime; - int to_msec; -#endif - -#ifdef USE_POLL - pfd.fd = fd; - pfd.events = POLLPRI; /* We're only interested in knowing - * when we can receive the next high - * priority message. - */ - pfd.revents = 0; - - now = time (&starttime); - while (now <= starttime + DLPI_MAXWAIT) { - to_msec = ((starttime + DLPI_MAXWAIT) - now) * 1000; - count = poll (&pfd, 1, to_msec); - - if (count == 0) { - /* log_fatal ("strgetmsg: timeout"); */ - return -1; - } else if (count < 0) { - if (errno == EAGAIN || errno == EINTR) { - time (&now); - continue; - } else { - /* log_fatal ("poll: %m"); */ - return -1; - } - } else { - break; - } - } -#else /* defined (USE_POLL) */ - /* - * Start timer. Can't use select, since it might return true if there - * were non High-Priority data available on the stream. - */ - (void) sigset (SIGALRM, sigalrm); - - if (alarm (DLPI_MAXWAIT) < 0) { - /* log_fatal ("alarm: %m"); */ - return -1; - } -#endif /* !defined (USE_POLL) */ - - /* - * Set flags argument and issue getmsg (). - */ - *flagsp = 0; - if ((result = getmsg (fd, ctlp, datap, flagsp)) < 0) { - return result; - } - -#ifndef USE_POLL - /* - * Stop timer. - */ - if (alarm (0) < 0) { - /* log_fatal ("alarm: %m"); */ - return -1; - } -#endif - - /* - * Check for MOREDATA and/or MORECTL. - */ - if (result & (MORECTL|MOREDATA)) { - return -1; - } - - /* - * Check for at least sizeof (long) control data portion. - */ - if (ctlp -> len < sizeof (long)) { - return -1; - } - - return 0; -} - -#ifndef USE_POLL -/* - * sigalrm - handle alarms. - */ -static void sigalrm (sig) - int sig; -{ - fprintf (stderr, "strgetmsg: timeout"); - exit (1); -} -#endif /* !defined (USE_POLL) */ - -int can_unicast_without_arp (ip) - struct interface_info *ip; -{ - return 1; -} - -int can_receive_unicast_unconfigured (ip) - struct interface_info *ip; -{ - return 1; -} - -int supports_multiple_interfaces (ip) - struct interface_info *ip; -{ - return 1; -} - -void maybe_setup_fallback () -{ - isc_result_t status; - struct interface_info *fbi = (struct interface_info *)0; - if (setup_fallback (&fbi, MDL)) { - if_register_fallback (fbi); - status = omapi_register_io_object ((omapi_object_t *)fbi, - if_readsocket, 0, - fallback_discard, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - fbi -> name, isc_result_totext (status)); - interface_dereference (&fbi, MDL); - } -} -#endif /* USE_DLPI */ diff --git a/contrib/isc-dhcp/common/dns.c b/contrib/isc-dhcp/common/dns.c deleted file mode 100644 index e80df9a..0000000 --- a/contrib/isc-dhcp/common/dns.c +++ /dev/null @@ -1,953 +0,0 @@ -/* dns.c - - Domain Name Service subroutines. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 2001-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Nominum, Inc. - * To learn more about Internet Systems Consortium, see - * ``http://www.isc.org/''. To learn more about Nominum, Inc., see - * ``http://www.nominum.com''. - */ - -#ifndef lint -static char copyright[] = -"$Id: dns.c,v 1.35.2.16 2004/06/17 20:54:38 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include "arpa/nameser.h" -#include "dst/md5.h" - -/* This file is kind of a crutch for the BIND 8 nsupdate code, which has - * itself been cruelly hacked from its original state. What this code - * does is twofold: first, it maintains a database of zone cuts that can - * be used to figure out which server should be contacted to update any - * given domain name. Secondly, it maintains a set of named TSIG keys, - * and associates those keys with zones. When an update is requested for - * a particular zone, the key associated with that zone is used for the - * update. - * - * The way this works is that you define the domain name to which an - * SOA corresponds, and the addresses of some primaries for that domain name: - * - * zone FOO.COM { - * primary 10.0.17.1; - * secondary 10.0.22.1, 10.0.23.1; - * key "FOO.COM Key"; - * } - * - * If an update is requested for GAZANGA.TOPANGA.FOO.COM, then the name - * server looks in its database for a zone record for "GAZANGA.TOPANGA.FOO.COM", - * doesn't find it, looks for one for "TOPANGA.FOO.COM", doesn't find *that*, - * looks for "FOO.COM", finds it. So it - * attempts the update to the primary for FOO.COM. If that times out, it - * tries the secondaries. You can list multiple primaries if you have some - * kind of magic name server that supports that. You shouldn't list - * secondaries that don't know how to forward updates (e.g., BIND 8 doesn't - * support update forwarding, AFAIK). If no TSIG key is listed, the update - * is attempted without TSIG. - * - * The DHCP server tries to find an existing zone for any given name by - * trying to look up a local zone structure for each domain containing - * that name, all the way up to '.'. If it finds one cached, it tries - * to use that one to do the update. That's why it tries to update - * "FOO.COM" above, even though theoretically it should try GAZANGA... - * and TOPANGA... first. - * - * If the update fails with a predefined or cached zone (we'll get to - * those in a second), then it tries to find a more specific zone. This - * is done by looking first for an SOA for GAZANGA.TOPANGA.FOO.COM. Then - * an SOA for TOPANGA.FOO.COM is sought. If during this search a predefined - * or cached zone is found, the update fails - there's something wrong - * somewhere. - * - * If a more specific zone _is_ found, that zone is cached for the length of - * its TTL in the same database as that described above. TSIG updates are - * never done for cached zones - if you want TSIG updates you _must_ - * write a zone definition linking the key to the zone. In cases where you - * know for sure what the key is but do not want to hardcode the IP addresses - * of the primary or secondaries, a zone declaration can be made that doesn't - * include any primary or secondary declarations. When the DHCP server - * encounters this while hunting up a matching zone for a name, it looks up - * the SOA, fills in the IP addresses, and uses that record for the update. - * If the SOA lookup returns NXRRSET, a warning is printed and the zone is - * discarded, TSIG key and all. The search for the zone then continues as if - * the zone record hadn't been found. Zones without IP addresses don't - * match when initially hunting for a predefined or cached zone to update. - * - * When an update is attempted and no predefined or cached zone is found - * that matches any enclosing domain of the domain being updated, the DHCP - * server goes through the same process that is done when the update to a - * predefined or cached zone fails - starting with the most specific domain - * name (GAZANGA.TOPANGA.FOO.COM) and moving to the least specific (the root), - * it tries to look up an SOA record. When it finds one, it creates a cached - * zone and attempts an update, and gives up if the update fails. - * - * TSIG keys are defined like this: - * - * key "FOO.COM Key" { - * algorithm HMAC-MD5.SIG-ALG.REG.INT; - * secret <Base64>; - * } - * - * <Base64> is a number expressed in base64 that represents the key. - * It's also permissible to use a quoted string here - this will be - * translated as the ASCII bytes making up the string, and will not - * include any NUL termination. The key name can be any text string, - * and the key type must be one of the key types defined in the draft - * or by the IANA. Currently only the HMAC-MD5... key type is - * supported. - */ - -dns_zone_hash_t *dns_zone_hash; - -#if defined (NSUPDATE) -isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname, - struct dns_zone *zone) -{ - isc_result_t status; - ns_tsig_key *tkey; - - if (!zone) - return ISC_R_NOTFOUND; - - if (!zone -> key) { - return ISC_R_KEY_UNKNOWN; - } - - if ((!zone -> key -> name || - strlen (zone -> key -> name) > NS_MAXDNAME) || - (!zone -> key -> algorithm || - strlen (zone -> key -> algorithm) > NS_MAXDNAME) || - (!zone -> key) || - (!zone -> key -> key) || - (zone -> key -> key -> len == 0)) { - return ISC_R_INVALIDKEY; - } - tkey = dmalloc (sizeof *tkey, MDL); - if (!tkey) { - nomem: - return ISC_R_NOMEMORY; - } - memset (tkey, 0, sizeof *tkey); - tkey -> data = dmalloc (zone -> key -> key -> len, MDL); - if (!tkey -> data) { - dfree (tkey, MDL); - goto nomem; - } - strcpy (tkey -> name, zone -> key -> name); - strcpy (tkey -> alg, zone -> key -> algorithm); - memcpy (tkey -> data, - zone -> key -> key -> value, zone -> key -> key -> len); - tkey -> len = zone -> key -> key -> len; - *key = tkey; - return ISC_R_SUCCESS; -} - -void tkey_free (ns_tsig_key **key) -{ - if ((*key) -> data) - dfree ((*key) -> data, MDL); - dfree ((*key), MDL); - *key = (ns_tsig_key *)0; -} -#endif - -isc_result_t enter_dns_zone (struct dns_zone *zone) -{ - struct dns_zone *tz = (struct dns_zone *)0; - - if (dns_zone_hash) { - dns_zone_hash_lookup (&tz, - dns_zone_hash, zone -> name, 0, MDL); - if (tz == zone) { - dns_zone_dereference (&tz, MDL); - return ISC_R_SUCCESS; - } - if (tz) { - dns_zone_hash_delete (dns_zone_hash, - zone -> name, 0, MDL); - dns_zone_dereference (&tz, MDL); - } - } else { - if (!dns_zone_new_hash (&dns_zone_hash, 1, MDL)) - return ISC_R_NOMEMORY; - } - dns_zone_hash_add (dns_zone_hash, zone -> name, 0, zone, MDL); - return ISC_R_SUCCESS; -} - -isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name) -{ - struct dns_zone *tz = (struct dns_zone *)0; - int len; - char *tname = (char *)0; - isc_result_t status; - - if (!dns_zone_hash) - return ISC_R_NOTFOUND; - - len = strlen (name); - if (name [len - 1] != '.') { - tname = dmalloc ((unsigned)len + 2, MDL); - if (!tname) - return ISC_R_NOMEMORY;; - strcpy (tname, name); - tname [len] = '.'; - tname [len + 1] = 0; - name = tname; - } - if (!dns_zone_hash_lookup (zone, dns_zone_hash, name, 0, MDL)) - status = ISC_R_NOTFOUND; - else - status = ISC_R_SUCCESS; - - if (tname) - dfree (tname, MDL); - return status; -} - -int dns_zone_dereference (ptr, file, line) - struct dns_zone **ptr; - const char *file; - int line; -{ - int i; - struct dns_zone *dns_zone; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - dns_zone = *ptr; - *ptr = (struct dns_zone *)0; - --dns_zone -> refcnt; - rc_register (file, line, ptr, dns_zone, dns_zone -> refcnt, 1, RC_MISC); - if (dns_zone -> refcnt > 0) - return 1; - - if (dns_zone -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (dns_zone); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (dns_zone -> name) - dfree (dns_zone -> name, file, line); - if (dns_zone -> key) - omapi_auth_key_dereference (&dns_zone -> key, file, line); - if (dns_zone -> primary) - option_cache_dereference (&dns_zone -> primary, file, line); - if (dns_zone -> secondary) - option_cache_dereference (&dns_zone -> secondary, file, line); - dfree (dns_zone, file, line); - return 1; -} - -#if defined (NSUPDATE) -isc_result_t find_cached_zone (const char *dname, ns_class class, - char *zname, size_t zsize, - struct in_addr *addrs, - int naddrs, int *naddrout, - struct dns_zone **zcookie) -{ - isc_result_t status = ISC_R_NOTFOUND; - const char *np; - struct dns_zone *zone = (struct dns_zone *)0; - struct data_string nsaddrs; - int ix; - - /* The absence of the zcookie pointer indicates that we - succeeded previously, but the update itself failed, meaning - that we shouldn't use the cached zone. */ - if (!zcookie) - return ISC_R_NOTFOUND; - - /* We can't look up a null zone. */ - if (!dname || !*dname) - return ISC_R_INVALIDARG; - - /* For each subzone, try to find a cached zone. */ - for (np = dname; np; np = strchr (np, '.')) { - np++; - status = dns_zone_lookup (&zone, np); - if (status == ISC_R_SUCCESS) - break; - } - - if (status != ISC_R_SUCCESS) - return status; - - /* Make sure the zone is valid. */ - if (zone -> timeout && zone -> timeout < cur_time) { - dns_zone_dereference (&zone, MDL); - return ISC_R_CANCELED; - } - - /* Make sure the zone name will fit. */ - if (strlen (zone -> name) > zsize) { - dns_zone_dereference (&zone, MDL); - return ISC_R_NOSPACE; - } - strcpy (zname, zone -> name); - - memset (&nsaddrs, 0, sizeof nsaddrs); - ix = 0; - - if (zone -> primary) { - if (evaluate_option_cache (&nsaddrs, (struct packet *)0, - (struct lease *)0, - (struct client_state *)0, - (struct option_state *)0, - (struct option_state *)0, - &global_scope, - zone -> primary, MDL)) { - int ip = 0; - while (ix < naddrs) { - if (ip + 4 > nsaddrs.len) - break; - memcpy (&addrs [ix], &nsaddrs.data [ip], 4); - ip += 4; - ix++; - } - data_string_forget (&nsaddrs, MDL); - } - } - if (zone -> secondary) { - if (evaluate_option_cache (&nsaddrs, (struct packet *)0, - (struct lease *)0, - (struct client_state *)0, - (struct option_state *)0, - (struct option_state *)0, - &global_scope, - zone -> secondary, MDL)) { - int ip = 0; - while (ix < naddrs) { - if (ip + 4 > nsaddrs.len) - break; - memcpy (&addrs [ix], &nsaddrs.data [ip], 4); - ip += 4; - ix++; - } - data_string_forget (&nsaddrs, MDL); - } - } - - /* It's not an error for zcookie to have a value here - actually, - it's quite likely, because res_nupdate cycles through all the - names in the update looking for their zones. */ - if (!*zcookie) - dns_zone_reference (zcookie, zone, MDL); - dns_zone_dereference (&zone, MDL); - if (naddrout) - *naddrout = ix; - return ISC_R_SUCCESS; -} - -void forget_zone (struct dns_zone **zone) -{ - dns_zone_dereference (zone, MDL); -} - -void repudiate_zone (struct dns_zone **zone) -{ - /* XXX Currently we're not differentiating between a cached - XXX zone and a zone that's been repudiated, which means - XXX that if we reap cached zones, we blow away repudiated - XXX zones. This isn't a big problem since we're not yet - XXX caching zones... :'} */ - - (*zone) -> timeout = cur_time - 1; - dns_zone_dereference (zone, MDL); -} - -void cache_found_zone (ns_class class, - char *zname, struct in_addr *addrs, int naddrs) -{ - isc_result_t status = ISC_R_NOTFOUND; - struct dns_zone *zone = (struct dns_zone *)0; - struct data_string nsaddrs; - int ix = strlen (zname); - - if (zname [ix - 1] == '.') - ix = 0; - - /* See if there's already such a zone. */ - if (dns_zone_lookup (&zone, zname) == ISC_R_SUCCESS) { - /* If it's not a dynamic zone, leave it alone. */ - if (!zone -> timeout) - return; - /* Address may have changed, so just blow it away. */ - if (zone -> primary) - option_cache_dereference (&zone -> primary, MDL); - if (zone -> secondary) - option_cache_dereference (&zone -> secondary, MDL); - } else if (!dns_zone_allocate (&zone, MDL)) - return; - - if (!zone -> name) { - zone -> name = - dmalloc (strlen (zname) + 1 + (ix != 0), MDL); - if (!zone -> name) { - dns_zone_dereference (&zone, MDL); - return; - } - strcpy (zone -> name, zname); - /* Add a trailing '.' if it was missing. */ - if (ix) { - zone -> name [ix] = '.'; - zone -> name [ix + 1] = 0; - } - } - - /* XXX Need to get the lower-level code to push the actual zone - XXX TTL up to us. */ - zone -> timeout = cur_time + 1800; - - if (!option_cache_allocate (&zone -> primary, MDL)) { - dns_zone_dereference (&zone, MDL); - return; - } - if (!buffer_allocate (&zone -> primary -> data.buffer, - naddrs * sizeof (struct in_addr), MDL)) { - dns_zone_dereference (&zone, MDL); - return; - } - memcpy (zone -> primary -> data.buffer -> data, - addrs, naddrs * sizeof *addrs); - zone -> primary -> data.data = - &zone -> primary -> data.buffer -> data [0]; - zone -> primary -> data.len = naddrs * sizeof *addrs; - - enter_dns_zone (zone); -} - -/* Have to use TXT records for now. */ -#define T_DHCID T_TXT - -int get_dhcid (struct data_string *id, - int type, const u_int8_t *data, unsigned len) -{ - unsigned char buf[MD5_DIGEST_LENGTH]; - MD5_CTX md5; - int i; - - /* Types can only be 0..(2^16)-1. */ - if (type < 0 || type > 65535) - return 0; - - /* Hexadecimal MD5 digest plus two byte type and NUL. */ - if (!buffer_allocate (&id -> buffer, - (MD5_DIGEST_LENGTH * 2) + 3, MDL)) - return 0; - id -> data = id -> buffer -> data; - - /* - * DHCP clients and servers should use the following forms of client - * identification, starting with the most preferable, and finishing - * with the least preferable. If the client does not send any of these - * forms of identification, the DHCP/DDNS interaction is not defined by - * this specification. The most preferable form of identification is - * the Globally Unique Identifier Option [TBD]. Next is the DHCP - * Client Identifier option. Last is the client's link-layer address, - * as conveyed in its DHCPREQUEST message. Implementors should note - * that the link-layer address cannot be used if there are no - * significant bytes in the chaddr field of the DHCP client's request, - * because this does not constitute a unique identifier. - * -- "Interaction between DHCP and DNS" - * <draft-ietf-dhc-dhcp-dns-12.txt> - * M. Stapp, Y. Rekhter - */ - - /* Put the type in the first two bytes. */ - id -> buffer -> data [0] = "0123456789abcdef" [type >> 4]; - id -> buffer -> data [1] = "0123456789abcdef" [type % 15]; - - /* Mash together an MD5 hash of the identifier. */ - MD5_Init (&md5); - MD5_Update (&md5, data, len); - MD5_Final (buf, &md5); - - /* Convert into ASCII. */ - for (i = 0; i < MD5_DIGEST_LENGTH; i++) { - id -> buffer -> data [i * 2 + 2] = - "0123456789abcdef" [(buf [i] >> 4) & 0xf]; - id -> buffer -> data [i * 2 + 3] = - "0123456789abcdef" [buf [i] & 0xf]; - } - id -> len = MD5_DIGEST_LENGTH * 2 + 2; - id -> buffer -> data [id -> len] = 0; - id -> terminated = 1; - - return 1; -} - -/* Now for the DDNS update code that is shared between client and - server... */ - -isc_result_t ddns_update_a (struct data_string *ddns_fwd_name, - struct iaddr ddns_addr, - struct data_string *ddns_dhcid, - unsigned long ttl, int rrsetp) -{ - ns_updque updqueue; - ns_updrec *updrec; - isc_result_t result; - char ddns_address [16]; - - if (ddns_addr.len != 4) - return ISC_R_INVALIDARG; - - /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */ - sprintf (ddns_address, "%u.%u.%u.%u", - ddns_addr.iabuf[0], ddns_addr.iabuf[1], - ddns_addr.iabuf[2], ddns_addr.iabuf[3]); - - /* - * When a DHCP client or server intends to update an A RR, it first - * prepares a DNS UPDATE query which includes as a prerequisite the - * assertion that the name does not exist. The update section of the - * query attempts to add the new name and its IP address mapping (an A - * RR), and the DHCID RR with its unique client-identity. - * -- "Interaction between DHCP and DNS" - */ - - ISC_LIST_INIT (updqueue); - - /* - * A RR does not exist. - */ - updrec = minires_mkupdrec (S_PREREQ, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)0; - updrec -> r_size = 0; - updrec -> r_opcode = rrsetp ? NXRRSET : NXDOMAIN; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Add A RR. - */ - updrec = minires_mkupdrec (S_UPDATE, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, ttl); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)ddns_address; - updrec -> r_size = strlen (ddns_address); - updrec -> r_opcode = ADD; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Add DHCID RR. - */ - updrec = minires_mkupdrec (S_UPDATE, - (const char *)ddns_fwd_name -> data, - C_IN, T_DHCID, ttl); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = ddns_dhcid -> data; - updrec -> r_size = ddns_dhcid -> len; - updrec -> r_opcode = ADD; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Attempt to perform the update. - */ - result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); - -#ifdef DEBUG_DNS_UPDATES - print_dns_status ((int)result, &updqueue); -#endif - - /* - * If this update operation succeeds, the updater can conclude that it - * has added a new name whose only RRs are the A and DHCID RR records. - * The A RR update is now complete (and a client updater is finished, - * while a server might proceed to perform a PTR RR update). - * -- "Interaction between DHCP and DNS" - */ - - if (result == ISC_R_SUCCESS) { - log_info ("Added new forward map from %.*s to %s", - (int)ddns_fwd_name -> len, - (const char *)ddns_fwd_name -> data, ddns_address); - goto error; - } - - - /* - * If the first update operation fails with YXDOMAIN, the updater can - * conclude that the intended name is in use. The updater then - * attempts to confirm that the DNS name is not being used by some - * other host. The updater prepares a second UPDATE query in which the - * prerequisite is that the desired name has attached to it a DHCID RR - * whose contents match the client identity. The update section of - * this query deletes the existing A records on the name, and adds the - * A record that matches the DHCP binding and the DHCID RR with the - * client identity. - * -- "Interaction between DHCP and DNS" - */ - - if (result != (rrsetp ? ISC_R_YXRRSET : ISC_R_YXDOMAIN)) { - log_error ("Unable to add forward map from %.*s to %s: %s", - (int)ddns_fwd_name -> len, - (const char *)ddns_fwd_name -> data, ddns_address, - isc_result_totext (result)); - goto error; - } - - while (!ISC_LIST_EMPTY (updqueue)) { - updrec = ISC_LIST_HEAD (updqueue); - ISC_LIST_UNLINK (updqueue, updrec, r_link); - minires_freeupdrec (updrec); - } - - /* - * DHCID RR exists, and matches client identity. - */ - updrec = minires_mkupdrec (S_PREREQ, - (const char *)ddns_fwd_name -> data, - C_IN, T_DHCID, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = ddns_dhcid -> data; - updrec -> r_size = ddns_dhcid -> len; - updrec -> r_opcode = YXRRSET; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Delete A RRset. - */ - updrec = minires_mkupdrec (S_UPDATE, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)0; - updrec -> r_size = 0; - updrec -> r_opcode = DELETE; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Add A RR. - */ - updrec = minires_mkupdrec (S_UPDATE, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, ttl); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)ddns_address; - updrec -> r_size = strlen (ddns_address); - updrec -> r_opcode = ADD; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Attempt to perform the update. - */ - result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); - - if (result != ISC_R_SUCCESS) { - if (result == YXRRSET || result == YXDOMAIN || - result == NXRRSET || result == NXDOMAIN) - log_error ("Forward map from %.*s to %s already in use", - (int)ddns_fwd_name -> len, - (const char *)ddns_fwd_name -> data, - ddns_address); - else - log_error ("Can't update forward map %.*s to %s: %s", - (int)ddns_fwd_name -> len, - (const char *)ddns_fwd_name -> data, - ddns_address, isc_result_totext (result)); - - } else { - log_info ("Added new forward map from %.*s to %s", - (int)ddns_fwd_name -> len, - (const char *)ddns_fwd_name -> data, ddns_address); - } -#if defined (DEBUG_DNS_UPDATES) - print_dns_status ((int)result, &updqueue); -#endif - - /* - * If this query succeeds, the updater can conclude that the current - * client was the last client associated with the domain name, and that - * the name now contains the updated A RR. The A RR update is now - * complete (and a client updater is finished, while a server would - * then proceed to perform a PTR RR update). - * -- "Interaction between DHCP and DNS" - */ - - /* - * If the second query fails with NXRRSET, the updater must conclude - * that the client's desired name is in use by another host. At this - * juncture, the updater can decide (based on some administrative - * configuration outside of the scope of this document) whether to let - * the existing owner of the name keep that name, and to (possibly) - * perform some name disambiguation operation on behalf of the current - * client, or to replace the RRs on the name with RRs that represent - * the current client. If the configured policy allows replacement of - * existing records, the updater submits a query that deletes the - * existing A RR and the existing DHCID RR, adding A and DHCID RRs that - * represent the IP address and client-identity of the new client. - * -- "Interaction between DHCP and DNS" - */ - - error: - while (!ISC_LIST_EMPTY (updqueue)) { - updrec = ISC_LIST_HEAD (updqueue); - ISC_LIST_UNLINK (updqueue, updrec, r_link); - minires_freeupdrec (updrec); - } - - return result; -} - -isc_result_t ddns_remove_a (struct data_string *ddns_fwd_name, - struct iaddr ddns_addr, - struct data_string *ddns_dhcid) -{ - ns_updque updqueue; - ns_updrec *updrec; - isc_result_t result = SERVFAIL; - char ddns_address [16]; - - if (ddns_addr.len != 4) - return ISC_R_INVALIDARG; - - /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */ - sprintf (ddns_address, "%u.%u.%u.%u", - ddns_addr.iabuf[0], ddns_addr.iabuf[1], - ddns_addr.iabuf[2], ddns_addr.iabuf[3]); - - /* - * The entity chosen to handle the A record for this client (either the - * client or the server) SHOULD delete the A record that was added when - * the lease was made to the client. - * - * In order to perform this delete, the updater prepares an UPDATE - * query which contains two prerequisites. The first prerequisite - * asserts that the DHCID RR exists whose data is the client identity - * described in Section 4.3. The second prerequisite asserts that the - * data in the A RR contains the IP address of the lease that has - * expired or been released. - * -- "Interaction between DHCP and DNS" - */ - - ISC_LIST_INIT (updqueue); - - /* - * DHCID RR exists, and matches client identity. - */ - updrec = minires_mkupdrec (S_PREREQ, - (const char *)ddns_fwd_name -> data, - C_IN, T_DHCID,0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = ddns_dhcid -> data; - updrec -> r_size = ddns_dhcid -> len; - updrec -> r_opcode = YXRRSET; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * A RR matches the expiring lease. - */ - updrec = minires_mkupdrec (S_PREREQ, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)ddns_address; - updrec -> r_size = strlen (ddns_address); - updrec -> r_opcode = YXRRSET; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - - /* - * Delete appropriate A RR. - */ - updrec = minires_mkupdrec (S_UPDATE, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)ddns_address; - updrec -> r_size = strlen (ddns_address); - updrec -> r_opcode = DELETE; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - /* - * Attempt to perform the update. - */ - result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); - print_dns_status ((int)result, &updqueue); - - /* - * If the query fails, the updater MUST NOT delete the DNS name. It - * may be that the host whose lease on the server has expired has moved - * to another network and obtained a lease from a different server, - * which has caused the client's A RR to be replaced. It may also be - * that some other client has been configured with a name that matches - * the name of the DHCP client, and the policy was that the last client - * to specify the name would get the name. In this case, the DHCID RR - * will no longer match the updater's notion of the client-identity of - * the host pointed to by the DNS name. - * -- "Interaction between DHCP and DNS" - */ - - if (result != ISC_R_SUCCESS) { - /* If the rrset isn't there, we didn't need to do the - delete, which is success. */ - if (result == ISC_R_NXRRSET || result == ISC_R_NXDOMAIN) - result = ISC_R_SUCCESS; - goto error; - } - - while (!ISC_LIST_EMPTY (updqueue)) { - updrec = ISC_LIST_HEAD (updqueue); - ISC_LIST_UNLINK (updqueue, updrec, r_link); - minires_freeupdrec (updrec); - } - - /* If the deletion of the A succeeded, and there are no A records - left for this domain, then we can blow away the DHCID record - as well. We can't blow away the DHCID record above because - it's possible that more than one A has been added to this - domain name. */ - ISC_LIST_INIT (updqueue); - - /* - * A RR does not exist. - */ - updrec = minires_mkupdrec (S_PREREQ, - (const char *)ddns_fwd_name -> data, - C_IN, T_A, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = (unsigned char *)0; - updrec -> r_size = 0; - updrec -> r_opcode = NXRRSET; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - /* - * Delete appropriate DHCID RR. - */ - updrec = minires_mkupdrec (S_UPDATE, - (const char *)ddns_fwd_name -> data, - C_IN, T_DHCID, 0); - if (!updrec) { - result = ISC_R_NOMEMORY; - goto error; - } - - updrec -> r_data = ddns_dhcid -> data; - updrec -> r_size = ddns_dhcid -> len; - updrec -> r_opcode = DELETE; - - ISC_LIST_APPEND (updqueue, updrec, r_link); - - /* - * Attempt to perform the update. - */ - result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); - print_dns_status ((int)result, &updqueue); - - /* Fall through. */ - error: - - while (!ISC_LIST_EMPTY (updqueue)) { - updrec = ISC_LIST_HEAD (updqueue); - ISC_LIST_UNLINK (updqueue, updrec, r_link); - minires_freeupdrec (updrec); - } - - return result; -} - - -#endif /* NSUPDATE */ - -HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone, dns_zone_hash_t, - dns_zone_reference, dns_zone_dereference) diff --git a/contrib/isc-dhcp/common/ethernet.c b/contrib/isc-dhcp/common/ethernet.c deleted file mode 100644 index dd7af2b..0000000 --- a/contrib/isc-dhcp/common/ethernet.c +++ /dev/null @@ -1,98 +0,0 @@ -/* ethernet.c - - Packet assembly code, originally contributed by Archie Cobbs. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: ethernet.c,v 1.6.2.3 2004/06/10 17:59:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING) -#include "includes/netinet/if_ether.h" -#endif /* PACKET_ASSEMBLY || PACKET_DECODING */ - -#if defined (PACKET_ASSEMBLY) -/* Assemble an hardware header... */ - -void assemble_ethernet_header (interface, buf, bufix, to) - struct interface_info *interface; - unsigned char *buf; - unsigned *bufix; - struct hardware *to; -{ - struct isc_ether_header eh; - - if (to && to -> hlen == 7) /* XXX */ - memcpy (eh.ether_dhost, &to -> hbuf [1], - sizeof eh.ether_dhost); - else - memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost)); - if (interface -> hw_address.hlen - 1 == sizeof (eh.ether_shost)) - memcpy (eh.ether_shost, &interface -> hw_address.hbuf [1], - sizeof (eh.ether_shost)); - else - memset (eh.ether_shost, 0x00, sizeof (eh.ether_shost)); - - eh.ether_type = htons (ETHERTYPE_IP); - - memcpy (&buf [*bufix], &eh, ETHER_HEADER_SIZE); - *bufix += ETHER_HEADER_SIZE; -} -#endif /* PACKET_ASSEMBLY */ - -#ifdef PACKET_DECODING -/* Decode a hardware header... */ - -ssize_t decode_ethernet_header (interface, buf, bufix, from) - struct interface_info *interface; - unsigned char *buf; - unsigned bufix; - struct hardware *from; -{ - struct isc_ether_header eh; - - memcpy (&eh, buf + bufix, ETHER_HEADER_SIZE); - -#ifdef USERLAND_FILTER - if (ntohs (eh.ether_type) != ETHERTYPE_IP) - return -1; -#endif - memcpy (&from -> hbuf [1], eh.ether_shost, sizeof (eh.ether_shost)); - from -> hbuf [0] = ARPHRD_ETHER; - from -> hlen = (sizeof eh.ether_shost) + 1; - - return ETHER_HEADER_SIZE; -} -#endif /* PACKET_DECODING */ diff --git a/contrib/isc-dhcp/common/execute.c b/contrib/isc-dhcp/common/execute.c deleted file mode 100644 index 46b2580..0000000 --- a/contrib/isc-dhcp/common/execute.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* execute.c - - Support for executable statements. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1998-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: execute.c,v 1.44.2.10 2004/06/10 17:59:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include <omapip/omapip_p.h> - -int execute_statements (result, packet, lease, client_state, - in_options, out_options, scope, statements) - struct binding_value **result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *out_options; - struct binding_scope **scope; - struct executable_statement *statements; -{ - struct executable_statement *r, *e, *next; - int rc; - int status; - unsigned long num; - struct binding_scope *outer; - struct binding *binding; - struct data_string ds; - struct binding_scope *ns; - - if (!statements) - return 1; - - r = (struct executable_statement *)0; - next = (struct executable_statement *)0; - e = (struct executable_statement *)0; - executable_statement_reference (&r, statements, MDL); - while (r && !(result && *result)) { - if (r -> next) - executable_statement_reference (&next, r -> next, MDL); - switch (r -> op) { - case statements_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: statements"); -#endif - status = execute_statements (result, packet, lease, - client_state, in_options, - out_options, scope, - r -> data.statements); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: statements returns %d", status); -#endif - if (!status) - return 0; - break; - - case on_statement: - if (lease) { - if (r -> data.on.evtypes & ON_EXPIRY) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: on expiry"); -#endif - if (lease -> on_expiry) - executable_statement_dereference - (&lease -> on_expiry, MDL); - if (r -> data.on.statements) - executable_statement_reference - (&lease -> on_expiry, - r -> data.on.statements, MDL); - } - if (r -> data.on.evtypes & ON_RELEASE) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: on release"); -#endif - if (lease -> on_release) - executable_statement_dereference - (&lease -> on_release, MDL); - if (r -> data.on.statements) - executable_statement_reference - (&lease -> on_release, - r -> data.on.statements, MDL); - } - if (r -> data.on.evtypes & ON_COMMIT) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: on commit"); -#endif - if (lease -> on_commit) - executable_statement_dereference - (&lease -> on_commit, MDL); - if (r -> data.on.statements) - executable_statement_reference - (&lease -> on_commit, - r -> data.on.statements, MDL); - } - } - break; - - case switch_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: switch"); -#endif - status = (find_matching_case - (&e, packet, lease, client_state, - in_options, out_options, scope, - r -> data.s_switch.expr, - r -> data.s_switch.statements)); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: switch: case %lx", (unsigned long)e); -#endif - if (status) { - if (!(execute_statements - (result, packet, lease, client_state, - in_options, out_options, scope, e))) { - executable_statement_dereference - (&e, MDL); - return 0; - } - executable_statement_dereference (&e, MDL); - } - break; - - /* These have no effect when executed. */ - case case_statement: - case default_statement: - break; - - case if_statement: - status = (evaluate_boolean_expression - (&rc, packet, - lease, client_state, in_options, - out_options, scope, r -> data.ie.expr)); - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: if %s", (status - ? (rc ? "true" : "false") - : "NULL")); -#endif - /* XXX Treat NULL as false */ - if (!status) - rc = 0; - if (!execute_statements - (result, packet, lease, client_state, - in_options, out_options, scope, - rc ? r -> data.ie.tc : r -> data.ie.fc)) - return 0; - break; - - case eval_statement: - status = evaluate_expression - ((struct binding_value **)0, - packet, lease, client_state, in_options, - out_options, scope, r -> data.eval, MDL); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: evaluate: %s", - (status ? "succeeded" : "failed")); -#endif - break; - - case return_statement: - status = evaluate_expression - (result, packet, - lease, client_state, in_options, - out_options, scope, r -> data.retval, MDL); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: return: %s", - (status ? "succeeded" : "failed")); -#endif - break; - - case add_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: add %s", (r -> data.add -> name - ? r -> data.add -> name - : "<unnamed class>")); -#endif - classify (packet, r -> data.add); - break; - - case break_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: break"); -#endif - return 1; - - case supersede_option_statement: - case send_option_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: %s option %s.%s", - (r -> op == supersede_option_statement - ? "supersede" : "send"), - r -> data.option -> option -> universe -> name, - r -> data.option -> option -> name); - goto option_statement; -#endif - case default_option_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: default option %s.%s", - r -> data.option -> option -> universe -> name, - r -> data.option -> option -> name); - goto option_statement; -#endif - case append_option_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: append option %s.%s", - r -> data.option -> option -> universe -> name, - r -> data.option -> option -> name); - goto option_statement; -#endif - case prepend_option_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: prepend option %s.%s", - r -> data.option -> option -> universe -> name, - r -> data.option -> option -> name); - option_statement: -#endif - set_option (r -> data.option -> option -> universe, - out_options, r -> data.option, r -> op); - break; - - case set_statement: - case define_statement: - if (!scope) { - log_error ("set %s: no scope", - r -> data.set.name); - status = 0; - break; - } - if (!*scope) { - if (!binding_scope_allocate (scope, MDL)) { - log_error ("set %s: can't allocate scope", - r -> data.set.name); - status = 0; - break; - } - } - binding = find_binding (*scope, r -> data.set.name); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: set %s", r -> data.set.name); -#endif - if (!binding) { - binding = dmalloc (sizeof *binding, MDL); - if (binding) { - memset (binding, 0, sizeof *binding); - binding -> name = - dmalloc (strlen - (r -> data.set.name) + 1, - MDL); - if (binding -> name) { - strcpy (binding -> name, - r -> data.set.name); - binding -> next = (*scope) -> bindings; - (*scope) -> bindings = binding; - } else { - badalloc: - dfree (binding, MDL); - binding = (struct binding *)0; - } - } - } - if (binding) { - if (binding -> value) - binding_value_dereference - (&binding -> value, MDL); - if (r -> op == set_statement) { - status = (evaluate_expression - (&binding -> value, packet, - lease, client_state, - in_options, out_options, - scope, r -> data.set.expr, - MDL)); - } else { - if (!(binding_value_allocate - (&binding -> value, MDL))) { - dfree (binding, MDL); - binding = (struct binding *)0; - } - if (binding -> value) { - binding -> value -> type = - binding_function; - (fundef_reference - (&binding -> value -> value.fundef, - r -> data.set.expr -> data.func, - MDL)); - } - } - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: set %s%s", r -> data.set.name, - (binding && status ? "" : " (failed)")); -#endif - break; - - case unset_statement: - if (!scope || !*scope) { - status = 0; - break; - } - binding = find_binding (*scope, r -> data.unset); - if (binding) { - if (binding -> value) - binding_value_dereference - (&binding -> value, MDL); - status = 1; - } else - status = 0; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: unset %s: %s", r -> data.unset, - (status ? "found" : "not found")); -#endif - break; - - case let_statement: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: let %s", r -> data.let.name); -#endif - ns = (struct binding_scope *)0; - binding_scope_allocate (&ns, MDL); - e = r; - - next_let: - if (ns) { - binding = dmalloc (sizeof *binding, MDL); - memset (binding, 0, sizeof *binding); - if (!binding) { - blb: - binding_scope_dereference (&ns, MDL); - } else { - binding -> name = - dmalloc (strlen - (e -> data.let.name + 1), - MDL); - if (binding -> name) - strcpy (binding -> name, - e -> data.let.name); - else { - dfree (binding, MDL); - binding = (struct binding *)0; - goto blb; - } - } - } - if (ns && binding) { - status = (evaluate_expression - (&binding -> value, packet, lease, - client_state, - in_options, out_options, - scope, e -> data.set.expr, MDL)); - binding -> next = ns -> bindings; - ns -> bindings = binding; - } - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: let %s%s", e -> data.let.name, - (binding && status ? "" : "failed")); -#endif - if (!e -> data.let.statements) { - } else if (e -> data.let.statements -> op == - let_statement) { - e = e -> data.let.statements; - goto next_let; - } else if (ns) { - if (scope && *scope) - binding_scope_reference (&ns -> outer, - *scope, MDL); - execute_statements - (result, packet, lease, - client_state, - in_options, out_options, - &ns, e -> data.let.statements); - } - if (ns) - binding_scope_dereference (&ns, MDL); - break; - - case log_statement: - memset (&ds, 0, sizeof ds); - status = (evaluate_data_expression - (&ds, packet, - lease, client_state, in_options, - out_options, scope, r -> data.log.expr, - MDL)); - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("exec: log"); -#endif - - if (status) { - switch (r -> data.log.priority) { - case log_priority_fatal: - log_fatal ("%.*s", (int)ds.len, - ds.buffer -> data); - break; - case log_priority_error: - log_error ("%.*s", (int)ds.len, - ds.buffer -> data); - break; - case log_priority_debug: - log_debug ("%.*s", (int)ds.len, - ds.buffer -> data); - break; - case log_priority_info: - log_info ("%.*s", (int)ds.len, - ds.buffer -> data); - break; - } - data_string_forget (&ds, MDL); - } - - break; - - default: - log_error ("bogus statement type %d", r -> op); - break; - } - executable_statement_dereference (&r, MDL); - if (next) { - executable_statement_reference (&r, next, MDL); - executable_statement_dereference (&next, MDL); - } - } - - return 1; -} - -/* Execute all the statements in a particular scope, and all statements in - scopes outer from that scope, but if a particular limiting scope is - reached, do not execute statements in that scope or in scopes outer - from it. More specific scopes need to take precedence over less - specific scopes, so we recursively traverse the scope list, executing - the most outer scope first. */ - -void execute_statements_in_scope (result, packet, - lease, client_state, in_options, out_options, - scope, group, limiting_group) - struct binding_value **result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *out_options; - struct binding_scope **scope; - struct group *group; - struct group *limiting_group; -{ - struct group *limit; - - /* If we've recursed as far as we can, return. */ - if (!group) - return; - - /* As soon as we get to a scope that is outer than the limiting - scope, we are done. This is so that if somebody does something - like this, it does the expected thing: - - domain-name "fugue.com"; - shared-network FOO { - host bar { - domain-name "othello.fugue.com"; - fixed-address 10.20.30.40; - } - subnet 10.20.30.0 netmask 255.255.255.0 { - domain-name "manhattan.fugue.com"; - } - } - - The problem with the above arrangement is that the host's - group nesting will be host -> shared-network -> top-level, - and the limiting scope when we evaluate the host's scope - will be the subnet -> shared-network -> top-level, so we need - to know when we evaluate the host's scope to stop before we - evaluate the shared-networks scope, because it's outer than - the limiting scope, which means we've already evaluated it. */ - - for (limit = limiting_group; limit; limit = limit -> next) { - if (group == limit) - return; - } - - if (group -> next) - execute_statements_in_scope (result, packet, - lease, client_state, - in_options, out_options, scope, - group -> next, limiting_group); - execute_statements (result, packet, lease, client_state, in_options, - out_options, scope, group -> statements); -} - -/* Dereference or free any subexpressions of a statement being freed. */ - -int executable_statement_dereference (ptr, file, line) - struct executable_statement **ptr; - const char *file; - int line; -{ - struct executable_statement *bp; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - (*ptr) -> refcnt--; - rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC); - if ((*ptr) -> refcnt > 0) { - *ptr = (struct executable_statement *)0; - return 1; - } - - if ((*ptr) -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (*ptr); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if ((*ptr) -> next) - executable_statement_dereference (&(*ptr) -> next, file, line); - - switch ((*ptr) -> op) { - case statements_statement: - if ((*ptr) -> data.statements) - executable_statement_dereference - (&(*ptr) -> data.statements, file, line); - break; - - case on_statement: - if ((*ptr) -> data.on.statements) - executable_statement_dereference - (&(*ptr) -> data.on.statements, file, line); - break; - - case switch_statement: - if ((*ptr) -> data.s_switch.statements) - executable_statement_dereference - (&(*ptr) -> data.on.statements, file, line); - if ((*ptr) -> data.s_switch.expr) - expression_dereference (&(*ptr) -> data.s_switch.expr, - file, line); - break; - - case case_statement: - if ((*ptr) -> data.s_switch.expr) - expression_dereference (&(*ptr) -> data.c_case, - file, line); - break; - - case if_statement: - if ((*ptr) -> data.ie.expr) - expression_dereference (&(*ptr) -> data.ie.expr, - file, line); - if ((*ptr) -> data.ie.tc) - executable_statement_dereference - (&(*ptr) -> data.ie.tc, file, line); - if ((*ptr) -> data.ie.fc) - executable_statement_dereference - (&(*ptr) -> data.ie.fc, file, line); - break; - - case eval_statement: - if ((*ptr) -> data.eval) - expression_dereference (&(*ptr) -> data.eval, - file, line); - break; - - case return_statement: - if ((*ptr) -> data.eval) - expression_dereference (&(*ptr) -> data.eval, - file, line); - break; - - case set_statement: - if ((*ptr)->data.set.name) - dfree ((*ptr)->data.set.name, file, line); - if ((*ptr)->data.set.expr) - expression_dereference (&(*ptr) -> data.set.expr, - file, line); - break; - - case unset_statement: - if ((*ptr)->data.unset) - dfree ((*ptr)->data.unset, file, line); - break; - - case supersede_option_statement: - case send_option_statement: - case default_option_statement: - case append_option_statement: - case prepend_option_statement: - if ((*ptr) -> data.option) - option_cache_dereference (&(*ptr) -> data.option, - file, line); - break; - - default: - /* Nothing to do. */ - break; - } - - dfree ((*ptr), file, line); - *ptr = (struct executable_statement *)0; - return 1; -} - -void write_statements (file, statements, indent) - FILE *file; - struct executable_statement *statements; - int indent; -{ - struct executable_statement *r, *x; - int result; - int status; - const char *s, *t, *dot; - int col; - - if (!statements) - return; - - for (r = statements; r; r = r -> next) { - switch (r -> op) { - case statements_statement: - write_statements (file, r -> data.statements, indent); - break; - - case on_statement: - indent_spaces (file, indent); - fprintf (file, "on "); - s = ""; - if (r -> data.on.evtypes & ON_EXPIRY) { - fprintf (file, "%sexpiry", s); - s = " or "; - } - if (r -> data.on.evtypes & ON_COMMIT) { - fprintf (file, "%scommit", s); - s = "or"; - } - if (r -> data.on.evtypes & ON_RELEASE) { - fprintf (file, "%srelease", s); - s = "or"; - } - if (r -> data.on.statements) { - fprintf (file, " {"); - write_statements (file, - r -> data.on.statements, - indent + 2); - indent_spaces (file, indent); - fprintf (file, "}"); - } else { - fprintf (file, ";"); - } - break; - - case switch_statement: - indent_spaces (file, indent); - fprintf (file, "switch ("); - col = write_expression (file, - r -> data.s_switch.expr, - indent + 7, indent + 7, 1); - col = token_print_indent (file, col, indent + 7, - "", "", ")"); - token_print_indent (file, - col, indent, " ", "", "{"); - write_statements (file, r -> data.s_switch.statements, - indent + 2); - indent_spaces (file, indent); - fprintf (file, "}"); - break; - - case case_statement: - indent_spaces (file, indent - 1); - fprintf (file, "case "); - col = write_expression (file, - r -> data.s_switch.expr, - indent + 5, indent + 5, 1); - token_print_indent (file, col, indent + 5, - "", "", ":"); - break; - - case default_statement: - indent_spaces (file, indent - 1); - fprintf (file, "default: "); - break; - - case if_statement: - indent_spaces (file, indent); - fprintf (file, "if "); - x = r; - col = write_expression (file, - x -> data.ie.expr, - indent + 3, indent + 3, 1); - else_if: - token_print_indent (file, col, indent, " ", "", "{"); - write_statements (file, x -> data.ie.tc, indent + 2); - if (x -> data.ie.fc && - x -> data.ie.fc -> op == if_statement && - !x -> data.ie.fc -> next) { - indent_spaces (file, indent); - fprintf (file, "} elsif "); - x = x -> data.ie.fc; - col = write_expression (file, - x -> data.ie.expr, - indent + 6, - indent + 6, 1); - goto else_if; - } - if (x -> data.ie.fc) { - indent_spaces (file, indent); - fprintf (file, "} else {"); - write_statements (file, x -> data.ie.fc, - indent + 2); - } - indent_spaces (file, indent); - fprintf (file, "}"); - break; - - case eval_statement: - indent_spaces (file, indent); - fprintf (file, "eval "); - col = write_expression (file, r -> data.eval, - indent + 5, indent + 5, 1); - fprintf (file, ";"); - break; - - case return_statement: - indent_spaces (file, indent); - fprintf (file, "return;"); - break; - - case add_statement: - indent_spaces (file, indent); - fprintf (file, "add \"%s\"", r -> data.add -> name); - break; - - case break_statement: - indent_spaces (file, indent); - fprintf (file, "break;"); - break; - - case supersede_option_statement: - case send_option_statement: - s = "supersede"; - goto option_statement; - - case default_option_statement: - s = "default"; - goto option_statement; - - case append_option_statement: - s = "append"; - goto option_statement; - - case prepend_option_statement: - s = "prepend"; - option_statement: - /* Note: the reason we don't try to pretty print - the option here is that the format of the option - may change in dhcpd.conf, and then when this - statement was read back, it would cause a syntax - error. */ - if (r -> data.option -> option -> universe == - &dhcp_universe) { - t = ""; - dot = ""; - } else { - t = (r -> data.option -> option -> - universe -> name); - dot = "."; - } - indent_spaces (file, indent); - fprintf (file, "%s %s%s%s = ", s, t, dot, - r -> data.option -> option -> name); - col = (indent + strlen (s) + strlen (t) + - strlen (dot) + strlen (r -> data.option -> - option -> name) + 4); - if (r -> data.option -> expression) - write_expression - (file, - r -> data.option -> expression, - col, indent + 8, 1); - else - token_indent_data_string - (file, col, indent + 8, "", "", - &r -> data.option -> data); - - fprintf (file, ";"); /* XXX */ - break; - - case set_statement: - indent_spaces (file, indent); - fprintf (file, "set "); - col = token_print_indent (file, indent + 4, indent + 4, - "", "", r -> data.set.name); - col = token_print_indent (file, col, indent + 4, - " ", " ", "="); - col = write_expression (file, r -> data.set.expr, - indent + 3, indent + 3, 0); - col = token_print_indent (file, col, indent + 4, - " ", "", ";"); - break; - - case unset_statement: - indent_spaces (file, indent); - fprintf (file, "unset "); - col = token_print_indent (file, indent + 6, indent + 6, - "", "", r -> data.set.name); - col = token_print_indent (file, col, indent + 6, - " ", "", ";"); - break; - - case log_statement: - indent_spaces (file, indent); - fprintf (file, "log "); - col = token_print_indent (file, col, indent + 4, - "", "", "("); - switch (r -> data.log.priority) { - case log_priority_fatal: - col = token_print_indent - (file, col, indent + 4, "", - " ", "fatal,"); - break; - case log_priority_error: - col = token_print_indent - (file, col, indent + 4, "", - " ", "error,"); - break; - case log_priority_debug: - col = token_print_indent - (file, col, indent + 4, "", - " ", "debug,"); - break; - case log_priority_info: - col = token_print_indent - (file, col, indent + 4, "", - " ", "info,"); - break; - } - col = write_expression (file, r -> data.log.expr, - indent + 4, indent + 4, 0); - col = token_print_indent (file, col, indent + 4, - "", "", ");"); - - break; - - default: - log_fatal ("bogus statement type %d\n", r -> op); - } - } -} - -/* Find a case statement in the sequence of executable statements that - matches the expression, and if found, return the following statement. - If no case statement matches, try to find a default statement and - return that (the default statement can precede all the case statements). - Otherwise, return the null statement. */ - -int find_matching_case (struct executable_statement **ep, - struct packet *packet, struct lease *lease, - struct client_state *client_state, - struct option_state *in_options, - struct option_state *out_options, - struct binding_scope **scope, - struct expression *expr, - struct executable_statement *stmt) -{ - int status, sub; - struct executable_statement *s; - unsigned long foo; - - if (is_data_expression (expr)) { - struct executable_statement *e; - struct data_string cd, ds; - memset (&ds, 0, sizeof ds); - memset (&cd, 0, sizeof cd); - - status = (evaluate_data_expression (&ds, packet, lease, - client_state, in_options, - out_options, scope, expr, - MDL)); - if (status) { - for (s = stmt; s; s = s -> next) { - if (s -> op == case_statement) { - sub = (evaluate_data_expression - (&cd, packet, lease, client_state, - in_options, out_options, - scope, s -> data.c_case, MDL)); - if (sub && cd.len == ds.len && - !memcmp (cd.data, ds.data, cd.len)) - { - data_string_forget (&cd, MDL); - data_string_forget (&ds, MDL); - executable_statement_reference - (ep, s -> next, MDL); - return 1; - } - data_string_forget (&cd, MDL); - } - } - data_string_forget (&ds, MDL); - } - } else { - unsigned long n, c; - status = evaluate_numeric_expression (&n, packet, lease, - client_state, - in_options, out_options, - scope, expr); - - if (status) { - for (s = stmt; s; s = s -> next) { - if (s -> op == case_statement) { - sub = (evaluate_numeric_expression - (&c, packet, lease, client_state, - in_options, out_options, - scope, s -> data.c_case)); - if (sub && n == c) { - executable_statement_reference - (ep, s -> next, MDL); - return 1; - } - } - } - } - } - - /* If we didn't find a matching case statement, look for a default - statement and return the statement following it. */ - for (s = stmt; s; s = s -> next) - if (s -> op == default_statement) - break; - if (s) { - executable_statement_reference (ep, s -> next, MDL); - return 1; - } - return 0; -} - -int executable_statement_foreach (struct executable_statement *stmt, - int (*callback) (struct - executable_statement *, - void *, int), - void *vp, int condp) -{ - struct executable_statement *foo; - int ok = 0; - int result; - - for (foo = stmt; foo; foo = foo -> next) { - if ((*callback) (foo, vp, condp) != 0) - ok = 1; - switch (foo -> op) { - case null_statement: - break; - case if_statement: - if (executable_statement_foreach (foo -> data.ie.tc, - callback, vp, 1)) - ok = 1; - if (executable_statement_foreach (foo -> data.ie.fc, - callback, vp, 1)) - ok = 1; - break; - case add_statement: - break; - case eval_statement: - break; - case break_statement: - break; - case default_option_statement: - break; - case supersede_option_statement: - break; - case append_option_statement: - break; - case prepend_option_statement: - break; - case send_option_statement: - break; - case statements_statement: - if ((executable_statement_foreach - (foo -> data.statements, callback, vp, condp))) - ok = 1; - break; - case on_statement: - if ((executable_statement_foreach - (foo -> data.on.statements, callback, vp, 1))) - ok = 1; - break; - case switch_statement: - if ((executable_statement_foreach - (foo -> data.s_switch.statements, callback, vp, 1))) - ok = 1; - break; - case case_statement: - break; - case default_statement: - break; - case set_statement: - break; - case unset_statement: - break; - case let_statement: - if ((executable_statement_foreach - (foo -> data.let.statements, callback, vp, 0))) - ok = 1; - break; - case define_statement: - break; - case log_statement: - case return_statement: - break; - } - } - return ok; -} diff --git a/contrib/isc-dhcp/common/fddi.c b/contrib/isc-dhcp/common/fddi.c deleted file mode 100644 index 9fdbb94..0000000 --- a/contrib/isc-dhcp/common/fddi.c +++ /dev/null @@ -1,97 +0,0 @@ -/* fddi.c - - Packet assembly code, originally contributed by Archie Cobbs. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: fddi.c,v 1.3.2.2 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (DEC_FDDI) -#include <netinet/if_fddi.h> -#include <net/if_llc.h> - -#if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING) -#include "includes/netinet/if_ether.h" -#endif /* PACKET_ASSEMBLY || PACKET_DECODING */ - -#if defined (PACKET_ASSEMBLY) -/* Assemble an hardware header... */ - -void assemble_fddi_header (interface, buf, bufix, to) - struct interface_info *interface; - unsigned char *buf; - unsigned *bufix; - struct hardware *to; -{ - struct fddi_header fh; - struct llc lh; - - if (to && to -> hlen == 7) - memcpy (fh.fddi_dhost, &to -> hbuf [1], - sizeof (fh.fddi_dhost)); - memcpy (fh.fddi_shost, - &interface -> hw_address.hbuf [1], sizeof (fh.fddi_shost)); - fh.fddi_fc = FDDIFC_LLC_ASYNC; - memcpy (&buf [*bufix], &fh, sizeof fh); - *bufix += sizeof fh; - - lh.llc_dsap = LLC_SNAP_LSAP; - lh.llc_ssap = LLC_SNAP_LSAP; - lh.llc_un.type_snap.control = LLC_UI; - lh.llc_un.type_snap.ether_type = htons (ETHERTYPE_IP); - memcpy (&buf [*bufix], &lh, LLC_SNAP_LEN); - *bufix += LLC_SNAP_LEN; -} -#endif /* PACKET_ASSEMBLY */ - -#ifdef PACKET_DECODING -/* Decode a hardware header... */ - -ssize_t decode_fddi_header (interface, buf, bufix, from) - struct interface_info *interface; - unsigned char *buf; - unsigned bufix; - struct hardware *from; -{ - struct fddi_header fh; - struct llc lh; - - from -> hbuf [0] = HTYPE_FDDI; - memcpy (&from -> hbuf [1], fh.fddi_shost, sizeof fh.fddi_shost); - return FDDI_HEADER_SIZE + LLC_SNAP_LEN; -} -#endif /* PACKET_DECODING */ -#endif /* DEC_FDDI */ diff --git a/contrib/isc-dhcp/common/icmp.c b/contrib/isc-dhcp/common/icmp.c deleted file mode 100644 index 8ef2283..0000000 --- a/contrib/isc-dhcp/common/icmp.c +++ /dev/null @@ -1,317 +0,0 @@ -/* dhcp.c - - ICMP Protocol engine - for sending out pings and receiving - responses. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: icmp.c,v 1.30.2.6 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include "netinet/ip.h" -#include "netinet/ip_icmp.h" - -struct icmp_state *icmp_state; -static omapi_object_type_t *dhcp_type_icmp; -static int no_icmp; - -OMAPI_OBJECT_ALLOC (icmp_state, struct icmp_state, dhcp_type_icmp) - -#if defined (TRACING) -trace_type_t *trace_icmp_input; -trace_type_t *trace_icmp_output; -#endif - -/* Initialize the ICMP protocol. */ - -void icmp_startup (routep, handler) - int routep; - void (*handler) PROTO ((struct iaddr, u_int8_t *, int)); -{ - struct protoent *proto; - int protocol = 1; - struct sockaddr_in from; - int fd; - int state; - struct icmp_state *new; - omapi_object_t *h; - isc_result_t result; - - /* Only initialize icmp once. */ - if (dhcp_type_icmp) - log_fatal ("attempted to reinitialize icmp protocol"); - - result = omapi_object_type_register (&dhcp_type_icmp, "icmp", - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - sizeof (struct icmp_state), - 0, RC_MISC); - - if (result != ISC_R_SUCCESS) - log_fatal ("Can't register icmp object type: %s", - isc_result_totext (result)); - - icmp_state_allocate (&icmp_state, MDL); - icmp_state -> icmp_handler = handler; - -#if defined (TRACING) - trace_icmp_input = trace_type_register ("icmp-input", (void *)0, - trace_icmp_input_input, - trace_icmp_input_stop, MDL); - trace_icmp_output = trace_type_register ("icmp-output", (void *)0, - trace_icmp_output_input, - trace_icmp_output_stop, MDL); - - /* If we're playing back a trace file, don't create the socket - or set up the callback. */ - if (!trace_playback ()) { -#endif - /* Get the protocol number (should be 1). */ - proto = getprotobyname ("icmp"); - if (proto) - protocol = proto -> p_proto; - - /* Get a raw socket for the ICMP protocol. */ - icmp_state -> socket = socket (AF_INET, SOCK_RAW, protocol); - if (icmp_state -> socket < 0) { - no_icmp = 1; - log_error ("unable to create icmp socket: %m"); - return; - } - -#if defined (HAVE_SETFD) - if (fcntl (icmp_state -> socket, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on icmp: %m"); -#endif - - /* Make sure it does routing... */ - state = 0; - if (setsockopt (icmp_state -> socket, SOL_SOCKET, SO_DONTROUTE, - (char *)&state, sizeof state) < 0) - log_fatal ("Can't disable SO_DONTROUTE on ICMP: %m"); - - result = (omapi_register_io_object - ((omapi_object_t *)icmp_state, - icmp_readsocket, 0, icmp_echoreply, 0, 0)); - if (result != ISC_R_SUCCESS) - log_fatal ("Can't register icmp handle: %s", - isc_result_totext (result)); -#if defined (TRACING) - } -#endif -} - -int icmp_readsocket (h) - omapi_object_t *h; -{ - struct icmp_state *state; - - state = (struct icmp_state *)h; - return state -> socket; -} - -int icmp_echorequest (addr) - struct iaddr *addr; -{ - struct sockaddr_in to; - struct icmp icmp; - int status; -#if defined (TRACING) - trace_iov_t iov [2]; -#endif - - if (no_icmp) - return 1; - if (!icmp_state) - log_fatal ("ICMP protocol used before initialization."); - - memset (&to, 0, sizeof(to)); -#ifdef HAVE_SA_LEN - to.sin_len = sizeof to; -#endif - to.sin_family = AF_INET; - to.sin_port = 0; /* unused. */ - memcpy (&to.sin_addr, addr -> iabuf, sizeof to.sin_addr); /* XXX */ - - icmp.icmp_type = ICMP_ECHO; - icmp.icmp_code = 0; - icmp.icmp_cksum = 0; - icmp.icmp_seq = 0; -#ifdef PTRSIZE_64BIT - icmp.icmp_id = (((u_int32_t)(u_int64_t)addr) ^ - (u_int32_t)(((u_int64_t)addr) >> 32)); -#else - icmp.icmp_id = (u_int32_t)addr; -#endif - memset (&icmp.icmp_dun, 0, sizeof icmp.icmp_dun); - - icmp.icmp_cksum = wrapsum (checksum ((unsigned char *)&icmp, - sizeof icmp, 0)); - -#if defined (TRACING) - if (trace_playback ()) { - char *buf = (char *)0; - unsigned buflen = 0; - - /* Consume the ICMP event. */ - status = trace_get_packet (&trace_icmp_output, &buflen, &buf); - if (status != ISC_R_SUCCESS) - log_error ("icmp_echorequest: %s", - isc_result_totext (status)); - if (buf) - dfree (buf, MDL); - } else { - if (trace_record ()) { - iov [0].buf = (char *)addr; - iov [0].len = sizeof *addr; - iov [1].buf = (char *)&icmp; - iov [1].len = sizeof icmp; - trace_write_packet_iov (trace_icmp_output, - 2, iov, MDL); - } -#endif - /* Send the ICMP packet... */ - status = sendto (icmp_state -> socket, - (char *)&icmp, sizeof icmp, 0, - (struct sockaddr *)&to, sizeof to); - if (status < 0) - log_error ("icmp_echorequest %s: %m", - inet_ntoa(to.sin_addr)); - - if (status != sizeof icmp) - return 0; -#if defined (TRACING) - } -#endif - return 1; -} - -isc_result_t icmp_echoreply (h) - omapi_object_t *h; -{ - struct icmp *icfrom; - struct ip *ip; - struct sockaddr_in from; - u_int8_t icbuf [1500]; - int status; - SOCKLEN_T sl; - int hlen, len; - struct iaddr ia; - struct icmp_state *state; -#if defined (TRACING) - trace_iov_t iov [2]; -#endif - - state = (struct icmp_state *)h; - - sl = sizeof from; - status = recvfrom (state -> socket, (char *)icbuf, sizeof icbuf, 0, - (struct sockaddr *)&from, &sl); - if (status < 0) { - log_error ("icmp_echoreply: %m"); - return ISC_R_UNEXPECTED; - } - - /* Find the IP header length... */ - ip = (struct ip *)icbuf; - hlen = IP_HL (ip); - - /* Short packet? */ - if (status < hlen + (sizeof *icfrom)) { - return ISC_R_SUCCESS; - } - - len = status - hlen; - icfrom = (struct icmp *)(icbuf + hlen); - - /* Silently discard ICMP packets that aren't echoreplies. */ - if (icfrom -> icmp_type != ICMP_ECHOREPLY) { - return ISC_R_SUCCESS; - } - - /* If we were given a second-stage handler, call it. */ - if (state -> icmp_handler) { - memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr); - ia.len = sizeof from.sin_addr; - -#if defined (TRACING) - if (trace_record ()) { - ia.len = htonl(ia.len); - iov [0].buf = (char *)&ia; - iov [0].len = sizeof ia; - iov [1].buf = (char *)icbuf; - iov [1].len = len; - trace_write_packet_iov (trace_icmp_input, 2, iov, MDL); - ia.len = ntohl(ia.len); - } -#endif - (*state -> icmp_handler) (ia, icbuf, len); - } - return ISC_R_SUCCESS; -} - -#if defined (TRACING) -void trace_icmp_input_input (trace_type_t *ttype, unsigned length, char *buf) -{ - struct iaddr *ia; - unsigned len; - u_int8_t *icbuf; - ia = (struct iaddr *)buf; - ia->len = ntohl(ia->len); - icbuf = (u_int8_t *)(ia + 1); - if (icmp_state -> icmp_handler) - (*icmp_state -> icmp_handler) (*ia, icbuf, - (int)(length - sizeof ia)); -} - -void trace_icmp_input_stop (trace_type_t *ttype) { } - -void trace_icmp_output_input (trace_type_t *ttype, unsigned length, char *buf) -{ - struct icmp *icmp; - struct iaddr ia; - - if (length != (sizeof (*icmp) + (sizeof ia))) { - log_error ("trace_icmp_output_input: data size mismatch %d:%d", - length, (int)((sizeof (*icmp)) + (sizeof ia))); - return; - } - ia.len = 4; - memcpy (ia.iabuf, buf, 4); - icmp = (struct icmp *)(buf + 1); - - log_error ("trace_icmp_output_input: unsent ping to %s", piaddr (ia)); -} - -void trace_icmp_output_stop (trace_type_t *ttype) { } -#endif /* TRACING */ diff --git a/contrib/isc-dhcp/common/inet.c b/contrib/isc-dhcp/common/inet.c deleted file mode 100644 index 53f5869..0000000 --- a/contrib/isc-dhcp/common/inet.c +++ /dev/null @@ -1,233 +0,0 @@ -/* inet.c - - Subroutines to manipulate internet addresses in a safely portable - way... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: inet.c,v 1.8.2.5 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -/* Return just the network number of an internet address... */ - -struct iaddr subnet_number (addr, mask) - struct iaddr addr; - struct iaddr mask; -{ - int i; - struct iaddr rv; - - rv.len = 0; - - /* Both addresses must have the same length... */ - if (addr.len != mask.len) - return rv; - - rv.len = addr.len; - for (i = 0; i < rv.len; i++) - rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i]; - return rv; -} - -/* Combine a network number and a integer to produce an internet address. - This won't work for subnets with more than 32 bits of host address, but - maybe this isn't a problem. */ - -struct iaddr ip_addr (subnet, mask, host_address) - struct iaddr subnet; - struct iaddr mask; - u_int32_t host_address; -{ - int i, j, k; - u_int32_t swaddr; - struct iaddr rv; - unsigned char habuf [sizeof swaddr]; - - swaddr = htonl (host_address); - memcpy (habuf, &swaddr, sizeof swaddr); - - /* Combine the subnet address and the host address. If - the host address is bigger than can fit in the subnet, - return a zero-length iaddr structure. */ - rv = subnet; - j = rv.len - sizeof habuf; - for (i = sizeof habuf - 1; i >= 0; i--) { - if (mask.iabuf [i + j]) { - if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) { - rv.len = 0; - return rv; - } - for (k = i - 1; k >= 0; k--) { - if (habuf [k]) { - rv.len = 0; - return rv; - } - } - rv.iabuf [i + j] |= habuf [i]; - break; - } else - rv.iabuf [i + j] = habuf [i]; - } - - return rv; -} - -/* Given a subnet number and netmask, return the address on that subnet - for which the host portion of the address is all ones (the standard - broadcast address). */ - -struct iaddr broadcast_addr (subnet, mask) - struct iaddr subnet; - struct iaddr mask; -{ - int i, j, k; - struct iaddr rv; - - if (subnet.len != mask.len) { - rv.len = 0; - return rv; - } - - for (i = 0; i < subnet.len; i++) { - rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255); - } - rv.len = subnet.len; - - return rv; -} - -u_int32_t host_addr (addr, mask) - struct iaddr addr; - struct iaddr mask; -{ - int i; - u_int32_t swaddr; - struct iaddr rv; - - rv.len = 0; - - /* Mask out the network bits... */ - rv.len = addr.len; - for (i = 0; i < rv.len; i++) - rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i]; - - /* Copy out up to 32 bits... */ - memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr); - - /* Swap it and return it. */ - return ntohl (swaddr); -} - -int addr_eq (addr1, addr2) - struct iaddr addr1, addr2; -{ - if (addr1.len != addr2.len) - return 0; - return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0; -} - -char *piaddr (addr) - struct iaddr addr; -{ - static char pbuf [4 * 16]; - char *s = pbuf; - int i; - - if (addr.len == 0) { - strcpy (s, "<null address>"); - } - for (i = 0; i < addr.len; i++) { - sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]); - s += strlen (s); - } - return pbuf; -} - -char *piaddr1 (addr) - struct iaddr addr; -{ - static char pbuf [4 * 16]; - char *s = pbuf; - int i; - - if (addr.len == 0) { - strcpy (s, "<null address>"); - } - for (i = 0; i < addr.len; i++) { - sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]); - s += strlen (s); - } - return pbuf; -} - -char *piaddrmask (struct iaddr addr, struct iaddr mask, - const char *file, int line) -{ - char *s, *t; - int i, mw; - unsigned len; - - for (i = 0; i < 32; i++) { - if (!mask.iabuf [3 - i / 8]) - i += 7; - else if (mask.iabuf [3 - i / 8] & (1 << (i % 8))) - break; - } - mw = 32 - i; - len = mw > 9 ? 2 : 1; - len += 4; /* three dots and a slash. */ - for (i = 0; i < (mw / 8) + 1; i++) { - if (addr.iabuf [i] > 99) - len += 3; - else if (addr.iabuf [i] > 9) - len += 2; - else - len++; - } - s = dmalloc (len + 1, file, line); - if (!s) - return s; - t = s; - sprintf (t, "%d", addr.iabuf [0]); - t += strlen (t); - for (i = 1; i < (mw / 8) + 1; i++) { - sprintf (t, ".%d", addr.iabuf [i]); - t += strlen (t); - } - *t++ = '/'; - sprintf (t, "%d", mw); - return s; -} - diff --git a/contrib/isc-dhcp/common/iscprint.c b/contrib/isc-dhcp/common/iscprint.c deleted file mode 100644 index d26896e..0000000 --- a/contrib/isc-dhcp/common/iscprint.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001, 2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: iscprint.c,v 1.1.2.1 2004/06/14 21:09:22 dhankins Exp $ */ - -#include "dhcpd.h" - -#ifdef NO_SNPRINTF - -#ifndef LINT -static char copyright[] = -"$Id: iscprint.c,v 1.1.2.1 2004/06/14 21:09:22 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium, Inc. All rights reserved."; -#endif - -#define INSIST(cond) REQUIRE(cond) -#define REQUIRE(cond) if (!(cond)) { return 0; } - -/* - * Return length of string that would have been written if not truncated. - */ - -int -isc_print_snprintf(char *str, size_t size, const char *format, ...) { - va_list ap; - int ret; - - va_start(ap, format); - ret = vsnprintf(str, size, format, ap); - va_end(ap); - return (ret); -} - -/* - * Return length of string that would have been written if not truncated. - */ - -int -isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { - int h; - int l; - int q; - int alt; - int zero; - int left; - int plus; - int space; - int neg; - isc_int64_t tmpi; - isc_uint64_t tmpui; - unsigned long width; - unsigned long precision; - unsigned int length; - char buf[1024]; - char c; - void *v; - char *save = str; - const char *cp; - const char *head; - int count = 0; - int pad; - int zeropad; - int dot; - double dbl; -#ifdef HAVE_LONG_DOUBLE - long double ldbl; -#endif - char fmt[32]; - - INSIST(str != NULL); - INSIST(format != NULL); - - while (*format != '\0') { - if (*format != '%') { - if (size > 1) { - *str++ = *format; - size--; - } - count++; - format++; - continue; - } - format++; - - /* - * Reset flags. - */ - dot = neg = space = plus = left = zero = alt = h = l = q = 0; - width = precision = 0; - head = ""; - length = pad = zeropad = 0; - - do { - if (*format == '#') { - alt = 1; - format++; - } else if (*format == '-') { - left = 1; - zero = 0; - format++; - } else if (*format == ' ') { - if (!plus) - space = 1; - format++; - } else if (*format == '+') { - plus = 1; - space = 0; - format++; - } else if (*format == '0') { - if (!left) - zero = 1; - format++; - } else - break; - } while (1); - - /* - * Width. - */ - if (*format == '*') { - width = va_arg(ap, int); - format++; - } else if (isdigit((unsigned char)*format)) { - char *e; - width = strtoul(format, &e, 10); - format = e; - } - - /* - * Precision. - */ - if (*format == '.') { - format++; - dot = 1; - if (*format == '*') { - precision = va_arg(ap, int); - format++; - } else if (isdigit((unsigned char)*format)) { - char *e; - precision = strtoul(format, &e, 10); - format = e; - } - } - - switch (*format) { - case '\0': - continue; - case '%': - if (size > 1) { - *str++ = *format; - size--; - } - count++; - break; - case 'q': - q = 1; - format++; - goto doint; - case 'h': - h = 1; - format++; - goto doint; - case 'l': - l = 1; - format++; - if (*format == 'l') { - q = 1; - format++; - } - goto doint; - case 'n': - case 'i': - case 'd': - case 'o': - case 'u': - case 'x': - case 'X': - doint: - if (precision != 0) - zero = 0; - switch (*format) { - case 'n': - if (h) { - short int *p; - p = va_arg(ap, short *); - REQUIRE(p != NULL); - *p = str - save; - } else if (l) { - long int *p; - p = va_arg(ap, long *); - REQUIRE(p != NULL); - *p = str - save; - } else { - int *p; - p = va_arg(ap, int *); - REQUIRE(p != NULL); - *p = str - save; - } - break; - case 'i': - case 'd': - if (q) - tmpi = va_arg(ap, isc_int64_t); - else if (l) - tmpi = va_arg(ap, long int); - else - tmpi = va_arg(ap, int); - if (tmpi < 0) { - head = "-"; - tmpui = -tmpi; - } else { - if (plus) - head = "+"; - else if (space) - head = " "; - else - head = ""; - tmpui = tmpi; - } - sprintf(buf, "%u", tmpui); - goto printint; - case 'o': - if (q) - tmpui = va_arg(ap, isc_uint64_t); - else if (l) - tmpui = va_arg(ap, long int); - else - tmpui = va_arg(ap, int); - sprintf(buf, alt ? "%#o" - : "%o", tmpui); - goto printint; - case 'u': - if (q) - tmpui = va_arg(ap, isc_uint64_t); - else if (l) - tmpui = va_arg(ap, unsigned long int); - else - tmpui = va_arg(ap, unsigned int); - sprintf(buf, "%u", tmpui); - goto printint; - case 'x': - if (q) - tmpui = va_arg(ap, isc_uint64_t); - else if (l) - tmpui = va_arg(ap, unsigned long int); - else - tmpui = va_arg(ap, unsigned int); - if (alt) { - head = "0x"; - if (precision > 2) - precision -= 2; - } - sprintf(buf, "%x", tmpui); - goto printint; - case 'X': - if (q) - tmpui = va_arg(ap, isc_uint64_t); - else if (l) - tmpui = va_arg(ap, unsigned long int); - else - tmpui = va_arg(ap, unsigned int); - if (alt) { - head = "0X"; - if (precision > 2) - precision -= 2; - } - sprintf(buf, "%X", tmpui); - goto printint; - printint: - if (precision != 0 || width != 0) { - length = strlen(buf); - if (length < precision) - zeropad = precision - length; - else if (length < width && zero) - zeropad = width - length; - if (width != 0) { - pad = width - length - - zeropad - strlen(head); - if (pad < 0) - pad = 0; - } - } - count += strlen(head) + strlen(buf) + pad + - zeropad; - if (!left) { - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - } - cp = head; - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (zeropad > 0 && size > 1) { - *str++ = '0'; - size--; - zeropad--; - } - cp = buf; - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - break; - default: - break; - } - break; - case 's': - cp = va_arg(ap, char *); - REQUIRE(cp != NULL); - - if (precision != 0) { - /* - * cp need not be NULL terminated. - */ - const char *tp; - unsigned long n; - - n = precision; - tp = cp; - while (n != 0 && *tp != '\0') - n--, tp++; - length = precision - n; - } else { - length = strlen(cp); - } - if (width != 0) { - pad = width - length; - if (pad < 0) - pad = 0; - } - count += pad + length; - if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - if (precision != 0) - while (precision > 0 && *cp != '\0' && - size > 1) { - *str++ = *cp++; - size--; - precision--; - } - else - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - break; - case 'c': - c = va_arg(ap, int); - if (width > 0) { - count += width; - width--; - if (left) { - *str++ = c; - size--; - } - while (width-- > 0 && size > 1) { - *str++ = ' '; - size--; - } - if (!left && size > 1) { - *str++ = c; - size--; - } - } else { - count++; - if (size > 1) { - *str++ = c; - size--; - } - } - break; - case 'p': - v = va_arg(ap, void *); - sprintf(buf, "%p", v); - length = strlen(buf); - if (precision > length) - zeropad = precision - length; - if (width > 0) { - pad = width - length - zeropad; - if (pad < 0) - pad = 0; - } - count += length + pad + zeropad; - if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - cp = buf; - if (zeropad > 0 && buf[0] == '0' && - (buf[1] == 'x' || buf[1] == 'X')) { - if (size > 1) { - *str++ = *cp++; - size--; - } - if (size > 1) { - *str++ = *cp++; - size--; - } - while (zeropad > 0 && size > 1) { - *str++ = '0'; - size--; - zeropad--; - } - } - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - break; - case 'D': /*deprecated*/ - INSIST("use %ld instead of %D" == NULL); - case 'O': /*deprecated*/ - INSIST("use %lo instead of %O" == NULL); - case 'U': /*deprecated*/ - INSIST("use %lu instead of %U" == NULL); - - case 'L': -#ifdef HAVE_LONG_DOUBLE - l = 1; -#else - INSIST("long doubles are not supported" == NULL); -#endif - /*FALLTHROUGH*/ - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - if (!dot) - precision = 6; - /* - * IEEE floating point. - * MIN 2.2250738585072014E-308 - * MAX 1.7976931348623157E+308 - * VAX floating point has a smaller range than IEEE. - * - * precisions > 324 don't make much sense. - * if we cap the precision at 512 we will not - * overflow buf. - */ - if (precision > 512) - precision = 512; - sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "", - plus ? "+" : space ? " " : "", - precision, l ? "L" : "", *format); - switch (*format) { - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': -#ifdef HAVE_LONG_DOUBLE - if (l) { - ldbl = va_arg(ap, long double); - sprintf(buf, fmt, ldbl); - } else -#endif - { - dbl = va_arg(ap, double); - sprintf(buf, fmt, dbl); - } - length = strlen(buf); - if (width > 0) { - pad = width - length; - if (pad < 0) - pad = 0; - } - count += length + pad; - if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - cp = buf; - while (*cp != ' ' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; - pad--; - } - break; - default: - continue; - } - break; - default: - continue; - } - format++; - } - if (size > 0) - *str = '\0'; - return (count); -} - -#endif diff --git a/contrib/isc-dhcp/common/lpf.c b/contrib/isc-dhcp/common/lpf.c deleted file mode 100644 index 87ba8fe..0000000 --- a/contrib/isc-dhcp/common/lpf.c +++ /dev/null @@ -1,410 +0,0 @@ -/* lpf.c - - Linux packet filter code, contributed by Brian Murrel at Interlinx - Support Services in Vancouver, B.C. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - */ - -#ifndef lint -static char copyright[] = -"$Id: lpf.c,v 1.29.2.2 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) -#include <sys/ioctl.h> -#include <sys/uio.h> - -#include <asm/types.h> -#include <linux/filter.h> -#include <linux/if_ether.h> -#include <netinet/in_systm.h> -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#ifdef USE_LPF_SEND -void if_reinitialize_send (info) - struct interface_info *info; -{ -} -#endif - -#ifdef USE_LPF_RECEIVE -void if_reinitialize_receive (info) - struct interface_info *info; -{ -} -#endif - -/* Called by get_interface_list for each interface that's discovered. - Opens a packet filter for each interface and adds it to the select - mask. */ - -int if_register_lpf (info) - struct interface_info *info; -{ - int sock; - char filename[50]; - int b; - struct sockaddr sa; - - /* Make an LPF socket. */ - if ((sock = socket(PF_PACKET, SOCK_PACKET, - htons((short)ETH_P_ALL))) < 0) { - if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || - errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || - errno == EAFNOSUPPORT || errno == EINVAL) { - log_error ("socket: %m - make sure"); - log_error ("CONFIG_PACKET (Packet socket) %s", - "and CONFIG_FILTER"); - log_error ("(Socket Filtering) are enabled %s", - "in your kernel"); - log_fatal ("configuration!"); - } - log_fatal ("Open a socket for LPF: %m"); - } - - /* Bind to the interface name */ - memset (&sa, 0, sizeof sa); - sa.sa_family = AF_PACKET; - strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data); - if (bind (sock, &sa, sizeof sa)) { - if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || - errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || - errno == EAFNOSUPPORT || errno == EINVAL) { - log_error ("socket: %m - make sure"); - log_error ("CONFIG_PACKET (Packet socket) %s", - "and CONFIG_FILTER"); - log_error ("(Socket Filtering) are enabled %s", - "in your kernel"); - log_fatal ("configuration!"); - } - log_fatal ("Bind socket to interface: %m"); - } - - return sock; -} -#endif /* USE_LPF_SEND || USE_LPF_RECEIVE */ - -#ifdef USE_LPF_SEND -void if_register_send (info) - struct interface_info *info; -{ - /* If we're using the lpf API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_LPF_RECEIVE - info -> wfdesc = if_register_lpf (info); -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - log_info ("Sending on LPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_send (info) - struct interface_info *info; -{ - /* don't need to close twice if we are using lpf for sending and - receiving */ -#ifndef USE_LPF_RECEIVE - /* for LPF this is simple, packet filters are removed when sockets - are closed */ - close (info -> wfdesc); -#endif - info -> wfdesc = -1; - if (!quiet_interface_discovery) - log_info ("Disabling output on LPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_LPF_SEND */ - -#ifdef USE_LPF_RECEIVE -/* Defined in bpf.c. We can't extern these in dhcpd.h without pulling - in bpf includes... */ -extern struct sock_filter dhcp_bpf_filter []; -extern int dhcp_bpf_filter_len; - -#if defined (HAVE_TR_SUPPORT) -extern struct sock_filter dhcp_bpf_tr_filter []; -extern int dhcp_bpf_tr_filter_len; -static void lpf_tr_filter_setup (struct interface_info *); -#endif - -static void lpf_gen_filter_setup (struct interface_info *); - -void if_register_receive (info) - struct interface_info *info; -{ - /* Open a LPF device and hang it on this interface... */ - info -> rfdesc = if_register_lpf (info); - -#if defined (HAVE_TR_SUPPORT) - if (info -> hw_address.hbuf [0] == HTYPE_IEEE802) - lpf_tr_filter_setup (info); - else -#endif - lpf_gen_filter_setup (info); - - if (!quiet_interface_discovery) - log_info ("Listening on LPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_receive (info) - struct interface_info *info; -{ - /* for LPF this is simple, packet filters are removed when sockets - are closed */ - close (info -> rfdesc); - info -> rfdesc = -1; - if (!quiet_interface_discovery) - log_info ("Disabling input on LPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -static void lpf_gen_filter_setup (info) - struct interface_info *info; -{ - struct sock_fprog p; - - /* Set up the bpf filter program structure. This is defined in - bpf.c */ - p.len = dhcp_bpf_filter_len; - p.filter = dhcp_bpf_filter; - - /* Patch the server port into the LPF program... - XXX changes to filter program may require changes - to the insn number(s) used below! XXX */ - dhcp_bpf_filter [8].k = ntohs ((short)local_port); - - if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, - sizeof p) < 0) { - if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || - errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || - errno == EAFNOSUPPORT) { - log_error ("socket: %m - make sure"); - log_error ("CONFIG_PACKET (Packet socket) %s", - "and CONFIG_FILTER"); - log_error ("(Socket Filtering) are enabled %s", - "in your kernel"); - log_fatal ("configuration!"); - } - log_fatal ("Can't install packet filter program: %m"); - } -} - -#if defined (HAVE_TR_SUPPORT) -static void lpf_tr_filter_setup (info) - struct interface_info *info; -{ - struct sock_fprog p; - - /* Set up the bpf filter program structure. This is defined in - bpf.c */ - p.len = dhcp_bpf_tr_filter_len; - p.filter = dhcp_bpf_tr_filter; - - /* Patch the server port into the LPF program... - XXX changes to filter program may require changes - XXX to the insn number(s) used below! - XXX Token ring filter is null - when/if we have a filter - XXX that's not, we'll need this code. - XXX dhcp_bpf_filter [?].k = ntohs (local_port); */ - - if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, - sizeof p) < 0) { - if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || - errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || - errno == EAFNOSUPPORT) { - log_error ("socket: %m - make sure"); - log_error ("CONFIG_PACKET (Packet socket) %s", - "and CONFIG_FILTER"); - log_error ("(Socket Filtering) are enabled %s", - "in your kernel"); - log_fatal ("configuration!"); - } - log_fatal ("Can't install packet filter program: %m"); - } -} -#endif /* HAVE_TR_SUPPORT */ -#endif /* USE_LPF_RECEIVE */ - -#ifdef USE_LPF_SEND -ssize_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - unsigned hbufp = 0, ibufp = 0; - double hh [16]; - double ih [1536 / sizeof (double)]; - unsigned char *buf = (unsigned char *)ih; - struct sockaddr sa; - int result; - int fudge; - - if (!strcmp (interface -> name, "fallback")) - return send_fallback (interface, packet, raw, - len, from, to, hto); - - /* Assemble the headers... */ - assemble_hw_header (interface, (unsigned char *)hh, &hbufp, hto); - fudge = hbufp % 4; /* IP header must be word-aligned. */ - memcpy (buf + fudge, (unsigned char *)hh, hbufp); - ibufp = hbufp + fudge; - assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr, - to -> sin_addr.s_addr, to -> sin_port, - (unsigned char *)raw, len); - memcpy (buf + ibufp, raw, len); - - /* For some reason, SOCK_PACKET sockets can't be connected, - so we have to do a sentdo every time. */ - memset (&sa, 0, sizeof sa); - sa.sa_family = AF_PACKET; - strncpy (sa.sa_data, - (const char *)interface -> ifp, sizeof sa.sa_data); - - result = sendto (interface -> wfdesc, - buf + fudge, ibufp + len - fudge, 0, &sa, sizeof sa); - if (result < 0) - log_error ("send_packet: %m"); - return result; -} -#endif /* USE_LPF_SEND */ - -#ifdef USE_LPF_RECEIVE -ssize_t receive_packet (interface, buf, len, from, hfrom) - struct interface_info *interface; - unsigned char *buf; - size_t len; - struct sockaddr_in *from; - struct hardware *hfrom; -{ - int nread; - int length = 0; - int offset = 0; - unsigned char ibuf [1536]; - unsigned bufix = 0; - - length = read (interface -> rfdesc, ibuf, sizeof ibuf); - if (length <= 0) - return length; - - bufix = 0; - /* Decode the physical header... */ - offset = decode_hw_header (interface, ibuf, bufix, hfrom); - - /* If a physical layer checksum failed (dunno of any - physical layer that supports this, but WTH), skip this - packet. */ - if (offset < 0) { - return 0; - } - - bufix += offset; - length -= offset; - - /* Decode the IP and UDP headers... */ - offset = decode_udp_ip_header (interface, ibuf, bufix, from, - (unsigned char *)0, (unsigned)length); - - /* If the IP or UDP checksum was bad, skip the packet... */ - if (offset < 0) - return 0; - - bufix += offset; - length -= offset; - - /* Copy out the data in the packet... */ - memcpy (buf, &ibuf [bufix], length); - return length; -} - -int can_unicast_without_arp (ip) - struct interface_info *ip; -{ - return 1; -} - -int can_receive_unicast_unconfigured (ip) - struct interface_info *ip; -{ - return 1; -} - -int supports_multiple_interfaces (ip) - struct interface_info *ip; -{ - return 1; -} - -void maybe_setup_fallback () -{ - isc_result_t status; - struct interface_info *fbi = (struct interface_info *)0; - if (setup_fallback (&fbi, MDL)) { - if_register_fallback (fbi); - status = omapi_register_io_object ((omapi_object_t *)fbi, - if_readsocket, 0, - fallback_discard, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - fbi -> name, isc_result_totext (status)); - interface_dereference (&fbi, MDL); - } -} -#endif diff --git a/contrib/isc-dhcp/common/memory.c b/contrib/isc-dhcp/common/memory.c deleted file mode 100644 index 4a444e2..0000000 --- a/contrib/isc-dhcp/common/memory.c +++ /dev/null @@ -1,161 +0,0 @@ -/* memory.c - - Memory-resident database... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: memory.c,v 1.66.2.5 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -struct group *root_group; -group_hash_t *group_name_hash; -int (*group_write_hook) (struct group_object *); - -isc_result_t delete_group (struct group_object *group, int writep) -{ - struct group_object *d; - - /* The group should exist and be hashed - if not, it's invalid. */ - if (group_name_hash) { - d = (struct group_object *)0; - group_hash_lookup (&d, group_name_hash, group -> name, - strlen (group -> name), MDL); - } else - return ISC_R_INVALIDARG; - if (!d) - return ISC_R_INVALIDARG; - - /* Also not okay to delete a group that's not the one in - the hash table. */ - if (d != group) - return ISC_R_INVALIDARG; - - /* If it's dynamic, and we're deleting it, we can just blow away the - hash table entry. */ - if ((group -> flags & GROUP_OBJECT_DYNAMIC) && - !(group -> flags & GROUP_OBJECT_STATIC)) { - group_hash_delete (group_name_hash, - group -> name, strlen (group -> name), MDL); - } else { - group -> flags |= GROUP_OBJECT_DELETED; - if (group -> group) - group_dereference (&group -> group, MDL); - } - - /* Store the group declaration in the lease file. */ - if (writep && group_write_hook) { - if (!(*group_write_hook) (group)) - return ISC_R_IOERROR; - } - return ISC_R_SUCCESS; -} - -isc_result_t supersede_group (struct group_object *group, int writep) -{ - struct group_object *t, *u; - isc_result_t status; - - /* Register the group in the group name hash table, - so we can look it up later. */ - if (group_name_hash) { - t = (struct group_object *)0; - group_hash_lookup (&t, group_name_hash, - group -> name, - strlen (group -> name), MDL); - if (t && t != group) { - /* If this isn't a dynamic entry, then we need to flag - the replacement as not dynamic either - otherwise, - if the dynamic entry is deleted later, the static - entry will come back next time the server is stopped - and restarted. */ - if (!(t -> flags & GROUP_OBJECT_DYNAMIC)) - group -> flags |= GROUP_OBJECT_STATIC; - - /* Delete the old object if it hasn't already been - deleted. If it has already been deleted, get rid of - the hash table entry. This is a legitimate - situation - a deleted static object needs to be kept - around so we remember it's deleted. */ - if (!(t -> flags & GROUP_OBJECT_DELETED)) - delete_group (t, 0); - else { - group_hash_delete (group_name_hash, - group -> name, - strlen (group -> name), - MDL); - group_object_dereference (&t, MDL); - } - } - } else { - group_new_hash (&group_name_hash, 0, MDL); - t = (struct group_object *)0; - } - - /* Add the group to the group name hash if it's not - already there, and also thread it into the list of - dynamic groups if appropriate. */ - if (!t) { - group_hash_add (group_name_hash, group -> name, - strlen (group -> name), group, MDL); - } - - /* Store the group declaration in the lease file. */ - if (writep && group_write_hook) { - if (!(*group_write_hook) (group)) - return ISC_R_IOERROR; - } - return ISC_R_SUCCESS; -} - -int clone_group (struct group **gp, struct group *group, - const char *file, int line) -{ - isc_result_t status; - struct group *g = (struct group *)0; - - /* Normally gp should contain the null pointer, but for convenience - it's permissible to clone a group into itself. */ - if (*gp && *gp != group) - return 0; - if (!group_allocate (&g, file, line)) - return 0; - if (group == *gp) - *gp = (struct group *)0; - group_reference (gp, g, file, line); - g -> authoritative = group -> authoritative; - group_reference (&g -> next, group, file, line); - group_dereference (&g, file, line); - return 1; -} diff --git a/contrib/isc-dhcp/common/nit.c b/contrib/isc-dhcp/common/nit.c deleted file mode 100644 index ea1f5dc..0000000 --- a/contrib/isc-dhcp/common/nit.c +++ /dev/null @@ -1,420 +0,0 @@ -/* nit.c - - Network Interface Tap (NIT) network interface code, by Ted Lemon - with one crucial tidbit of help from Stu Grossmen. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: nit.c,v 1.34.2.2 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE) -#include <sys/ioctl.h> -#include <sys/uio.h> - -#include <sys/time.h> -#include <net/nit.h> -#include <net/nit_if.h> -#include <net/nit_pf.h> -#include <net/nit_buf.h> -#include <sys/stropts.h> -#include <net/packetfilt.h> - -#include <netinet/in_systm.h> -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#ifdef USE_NIT_SEND -void if_reinitialize_send (info) - struct interface_info *info; -{ -} -#endif - -#ifdef USE_NIT_RECEIVE -void if_reinitialize_receive (info) - struct interface_info *info; -{ -} -#endif - -/* Called by get_interface_list for each interface that's discovered. - Opens a packet filter for each interface and adds it to the select - mask. */ - -int if_register_nit (info) - struct interface_info *info; -{ - int sock; - char filename[50]; - struct ifreq ifr; - struct strioctl sio; - - /* Open a NIT device */ - sock = open ("/dev/nit", O_RDWR); - if (sock < 0) - log_fatal ("Can't open NIT device for %s: %m", info -> name); - - /* Set the NIT device to point at this interface. */ - sio.ic_cmd = NIOCBIND; - sio.ic_len = sizeof *(info -> ifp); - sio.ic_dp = (char *)(info -> ifp); - sio.ic_timout = INFTIM; - if (ioctl (sock, I_STR, &sio) < 0) - log_fatal ("Can't attach interface %s to nit device: %m", - info -> name); - - /* Get the low-level address... */ - sio.ic_cmd = SIOCGIFADDR; - sio.ic_len = sizeof ifr; - sio.ic_dp = (char *)𝔦 - sio.ic_timout = INFTIM; - if (ioctl (sock, I_STR, &sio) < 0) - log_fatal ("Can't get physical layer address for %s: %m", - info -> name); - - /* XXX code below assumes ethernet interface! */ - info -> hw_address.hlen = 7; - info -> hw_address.hbuf [0] = ARPHRD_ETHER; - memcpy (&info -> hw_address.hbuf [1], - ifr.ifr_ifru.ifru_addr.sa_data, 6); - - if (ioctl (sock, I_PUSH, "pf") < 0) - log_fatal ("Can't push packet filter onto NIT for %s: %m", - info -> name); - - return sock; -} -#endif /* USE_NIT_SEND || USE_NIT_RECEIVE */ - -#ifdef USE_NIT_SEND -void if_register_send (info) - struct interface_info *info; -{ - /* If we're using the nit API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_NIT_RECEIVE - struct packetfilt pf; - struct strioctl sio; - - info -> wfdesc = if_register_nit (info); - - pf.Pf_Priority = 0; - pf.Pf_FilterLen = 1; - pf.Pf_Filter [0] = ENF_PUSHZERO; - - /* Set up an NIT filter that rejects everything... */ - sio.ic_cmd = NIOCSETF; - sio.ic_len = sizeof pf; - sio.ic_dp = (char *)&pf; - sio.ic_timout = INFTIM; - if (ioctl (info -> wfdesc, I_STR, &sio) < 0) - log_fatal ("Can't set NIT filter: %m"); -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - log_info ("Sending on NIT/%s%s%s", - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_send (info) - struct interface_info *info; -{ - /* If we're using the nit API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_NIT_RECEIVE - close (info -> wfdesc); -#endif - info -> wfdesc = -1; - if (!quiet_interface_discovery) - log_info ("Disabling output on NIT/%s%s%s", - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_NIT_SEND */ - -#ifdef USE_NIT_RECEIVE -/* Packet filter program... - XXX Changes to the filter program may require changes to the constant - offsets used in if_register_send to patch the NIT program! XXX */ - -void if_register_receive (info) - struct interface_info *info; -{ - int flag = 1; - u_int32_t x; - struct packetfilt pf; - struct strioctl sio; - u_int16_t addr [2]; - struct timeval t; - - /* Open a NIT device and hang it on this interface... */ - info -> rfdesc = if_register_nit (info); - - /* Set the snap length to 0, which means always take the whole - packet. */ - x = 0; - if (ioctl (info -> rfdesc, NIOCSSNAP, &x) < 0) - log_fatal ("Can't set NIT snap length on %s: %m", info -> name); - - /* Set the stream to byte stream mode */ - if (ioctl (info -> rfdesc, I_SRDOPT, RMSGN) != 0) - log_info ("I_SRDOPT failed on %s: %m", info -> name); - -#if 0 - /* Push on the chunker... */ - if (ioctl (info -> rfdesc, I_PUSH, "nbuf") < 0) - log_fatal ("Can't push chunker onto NIT STREAM: %m"); - - /* Set the timeout to zero. */ - t.tv_sec = 0; - t.tv_usec = 0; - if (ioctl (info -> rfdesc, NIOCSTIME, &t) < 0) - log_fatal ("Can't set chunk timeout: %m"); -#endif - - /* Ask for no header... */ - x = 0; - if (ioctl (info -> rfdesc, NIOCSFLAGS, &x) < 0) - log_fatal ("Can't set NIT flags on %s: %m", info -> name); - - /* Set up the NIT filter program. */ - /* XXX Unlike the BPF filter program, this one won't work if the - XXX IP packet is fragmented or if there are options on the IP - XXX header. */ - pf.Pf_Priority = 0; - pf.Pf_FilterLen = 0; - - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 6; - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; - pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT; - pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 11; - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_AND; - pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0xFF); - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_CAND; - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 18; - pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; - pf.Pf_Filter [pf.Pf_FilterLen++] = local_port; - - /* Install the filter... */ - sio.ic_cmd = NIOCSETF; - sio.ic_len = sizeof pf; - sio.ic_dp = (char *)&pf; - sio.ic_timout = INFTIM; - if (ioctl (info -> rfdesc, I_STR, &sio) < 0) - log_fatal ("Can't set NIT filter on %s: %m", info -> name); - - if (!quiet_interface_discovery) - log_info ("Listening on NIT/%s%s%s", - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_receive (info) - struct interface_info *info; -{ - /* If we're using the nit API for sending and receiving, - we don't need to register this interface twice. */ - close (info -> rfdesc); - info -> rfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling input on NIT/%s%s%s", - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_NIT_RECEIVE */ - -#ifdef USE_NIT_SEND -ssize_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - unsigned hbufp, ibufp; - double hh [16]; - double ih [1536 / sizeof (double)]; - unsigned char *buf = (unsigned char *)ih; - struct sockaddr *junk; - struct strbuf ctl, data; - struct sockaddr_in foo; - int result; - - if (!strcmp (interface -> name, "fallback")) - return send_fallback (interface, packet, raw, - len, from, to, hto); - - /* Start with the sockaddr struct... */ - junk = (struct sockaddr *)&hh [0]; - hbufp = (((unsigned char *)&junk -> sa_data [0]) - - (unsigned char *)&hh[0]); - ibufp = 0; - - /* Assemble the headers... */ - assemble_hw_header (interface, (unsigned char *)junk, &hbufp, hto); - assemble_udp_ip_header (interface, buf, &ibufp, - from.s_addr, to -> sin_addr.s_addr, - to -> sin_port, (unsigned char *)raw, len); - - /* Copy the data into the buffer (yuk). */ - memcpy (buf + ibufp, raw, len); - - /* Set up the sockaddr structure... */ -#if USE_SIN_LEN - junk -> sa_len = hbufp - 2; /* XXX */ -#endif - junk -> sa_family = AF_UNSPEC; - - /* Set up the msg_buf structure... */ - ctl.buf = (char *)&hh [0]; - ctl.maxlen = ctl.len = hbufp; - data.buf = (char *)&ih [0]; - data.maxlen = data.len = ibufp + len; - - result = putmsg (interface -> wfdesc, &ctl, &data, 0); - if (result < 0) - log_error ("send_packet: %m"); - return result; -} -#endif /* USE_NIT_SEND */ - -#ifdef USE_NIT_RECEIVE -ssize_t receive_packet (interface, buf, len, from, hfrom) - struct interface_info *interface; - unsigned char *buf; - size_t len; - struct sockaddr_in *from; - struct hardware *hfrom; -{ - int nread; - int length = 0; - int offset = 0; - unsigned char ibuf [1536]; - int bufix = 0; - - length = read (interface -> rfdesc, ibuf, sizeof ibuf); - if (length <= 0) - return length; - - /* Decode the physical header... */ - offset = decode_hw_header (interface, ibuf, bufix, hfrom); - - /* If a physical layer checksum failed (dunno of any - physical layer that supports this, but WTH), skip this - packet. */ - if (offset < 0) { - return 0; - } - - bufix += offset; - length -= offset; - - /* Decode the IP and UDP headers... */ - offset = decode_udp_ip_header (interface, ibuf, bufix, - from, (unsigned char *)0, length); - - /* If the IP or UDP checksum was bad, skip the packet... */ - if (offset < 0) - return 0; - - bufix += offset; - length -= offset; - - /* Copy out the data in the packet... */ - memcpy (buf, &ibuf [bufix], length); - return length; -} - -int can_unicast_without_arp (ip) - struct interface_info *ip; -{ - return 1; -} - -int can_receive_unicast_unconfigured (ip) - struct interface_info *ip; -{ - return 1; -} - -int supports_multiple_interfaces (ip) - struct interface_info *ip; -{ - return 1; -} - -void maybe_setup_fallback () -{ - isc_result_t status; - struct interface_info *fbi = (struct interface_info *)0; - if (setup_fallback (&fbi, MDL)) { - if_register_fallback (fbi); - status = omapi_register_io_object ((omapi_object_t *)fbi, - if_readsocket, 0, - fallback_discard, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - fbi -> name, isc_result_totext (status)); - interface_dereference (&fbi, MDL); - } -} -#endif diff --git a/contrib/isc-dhcp/common/options.c b/contrib/isc-dhcp/common/options.c deleted file mode 100644 index 9b67b23..0000000 --- a/contrib/isc-dhcp/common/options.c +++ /dev/null @@ -1,2248 +0,0 @@ -/* options.c - - DHCP options parsing and reassembly. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: options.c,v 1.85.2.13 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#define DHCP_OPTION_DATA -#include "dhcpd.h" -#include <omapip/omapip_p.h> - -struct option *vendor_cfg_option; - -static void do_option_set PROTO ((pair *, - struct option_cache *, - enum statement_op)); - -/* Parse all available options out of the specified packet. */ - -int parse_options (packet) - struct packet *packet; -{ - int i; - struct option_cache *op = (struct option_cache *)0; - - /* Allocate a new option state. */ - if (!option_state_allocate (&packet -> options, MDL)) { - packet -> options_valid = 0; - return 0; - } - - /* If we don't see the magic cookie, there's nothing to parse. */ - if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) { - packet -> options_valid = 0; - return 1; - } - - /* Go through the options field, up to the end of the packet - or the End field. */ - if (!parse_option_buffer (packet -> options, - &packet -> raw -> options [4], - (packet -> packet_length - - DHCP_FIXED_NON_UDP - 4), - &dhcp_universe)) - return 0; - - /* If we parsed a DHCP Option Overload option, parse more - options out of the buffer(s) containing them. */ - if (packet -> options_valid && - (op = lookup_option (&dhcp_universe, packet -> options, - DHO_DHCP_OPTION_OVERLOAD))) { - if (op -> data.data [0] & 1) { - if (!parse_option_buffer - (packet -> options, - (unsigned char *)packet -> raw -> file, - sizeof packet -> raw -> file, - &dhcp_universe)) - return 0; - } - if (op -> data.data [0] & 2) { - if (!parse_option_buffer - (packet -> options, - (unsigned char *)packet -> raw -> sname, - sizeof packet -> raw -> sname, - &dhcp_universe)) - return 0; - } - } - packet -> options_valid = 1; - return 1; -} - -/* Parse options out of the specified buffer, storing addresses of option - values in packet -> options and setting packet -> options_valid if no - errors are encountered. */ - -int parse_option_buffer (options, buffer, length, universe) - struct option_state *options; - const unsigned char *buffer; - unsigned length; - struct universe *universe; -{ - unsigned char *t; - const unsigned char *end = buffer + length; - unsigned len, offset; - int code; - struct option_cache *op = (struct option_cache *)0; - struct buffer *bp = (struct buffer *)0; - - if (!buffer_allocate (&bp, length, MDL)) { - log_error ("no memory for option buffer."); - return 0; - } - memcpy (bp -> data, buffer, length); - - for (offset = 0; buffer [offset] != DHO_END && offset < length; ) { - code = buffer [offset]; - /* Pad options don't have a length - just skip them. */ - if (code == DHO_PAD) { - ++offset; - continue; - } - - /* Don't look for length if the buffer isn't that big. */ - if (offset + 2 > length) { - len = 65536; - goto bogus; - } - - /* All other fields (except end, see above) have a - one-byte length. */ - len = buffer [offset + 1]; - - /* If the length is outrageous, the options are bad. */ - if (offset + len + 2 > length) { - bogus: - log_error ("parse_option_buffer: option %s (%d) %s.", - dhcp_options [code].name, len, - "larger than buffer"); - buffer_dereference (&bp, MDL); - return 0; - } - - /* If the option contains an encapsulation, parse it. If - the parse fails, or the option isn't an encapsulation (by - far the most common case), or the option isn't entirely - an encapsulation, keep the raw data as well. */ - if (universe -> options [code] && - !((universe -> options [code] -> format [0] == 'e' || - universe -> options [code] -> format [0] == 'E') && - (parse_encapsulated_suboptions - (options, universe -> options [code], - buffer + offset + 2, len, - universe, (const char *)0)))) { - op = lookup_option (universe, options, code); - if (op) { - struct data_string new; - memset (&new, 0, sizeof new); - if (!buffer_allocate (&new.buffer, op -> data.len + len, - MDL)) { - log_error ("parse_option_buffer: No memory."); - return 0; - } - memcpy (new.buffer -> data, op -> data.data, - op -> data.len); - memcpy (&new.buffer -> data [op -> data.len], - &bp -> data [offset + 2], len); - new.len = op -> data.len + len; - new.data = new.buffer -> data; - data_string_forget (&op -> data, MDL); - data_string_copy (&op -> data, &new, MDL); - data_string_forget (&new, MDL); - } else { - save_option_buffer (universe, options, bp, - &bp -> data [offset + 2], len, - universe -> options [code], 1); - } - } - offset += len + 2; - } - buffer_dereference (&bp, MDL); - return 1; -} - -/* If an option in an option buffer turns out to be an encapsulation, - figure out what to do. If we don't know how to de-encapsulate it, - or it's not well-formed, return zero; otherwise, return 1, indicating - that we succeeded in de-encapsulating it. */ - -struct universe *find_option_universe (struct option *eopt, const char *uname) -{ - int i; - char *s, *t; - struct universe *universe = (struct universe *)0; - - /* Look for the E option in the option format. */ - s = strchr (eopt -> format, 'E'); - if (!s) { - log_error ("internal encapsulation format error 1."); - return 0; - } - /* Look for the universe name in the option format. */ - t = strchr (++s, '.'); - /* If there was no trailing '.', or there's something after the - trailing '.', the option is bogus and we can't use it. */ - if (!t || t [1]) { - log_error ("internal encapsulation format error 2."); - return 0; - } - if (t == s && uname) { - for (i = 0; i < universe_count; i++) { - if (!strcmp (universes [i] -> name, uname)) { - universe = universes [i]; - break; - } - } - } else if (t != s) { - for (i = 0; i < universe_count; i++) { - if (strlen (universes [i] -> name) == t - s && - !memcmp (universes [i] -> name, - s, (unsigned)(t - s))) { - universe = universes [i]; - break; - } - } - } - return universe; -} - -/* If an option in an option buffer turns out to be an encapsulation, - figure out what to do. If we don't know how to de-encapsulate it, - or it's not well-formed, return zero; otherwise, return 1, indicating - that we succeeded in de-encapsulating it. */ - -int parse_encapsulated_suboptions (struct option_state *options, - struct option *eopt, - const unsigned char *buffer, - unsigned len, struct universe *eu, - const char *uname) -{ - int i; - struct universe *universe = find_option_universe (eopt, uname); - - /* If we didn't find the universe, we can't do anything with it - right now (e.g., we can't decode vendor options until we've - decoded the packet and executed the scopes that it matches). */ - if (!universe) - return 0; - - /* If we don't have a decoding function for it, we can't decode - it. */ - if (!universe -> decode) - return 0; - - i = (*universe -> decode) (options, buffer, len, universe); - - /* If there is stuff before the suboptions, we have to keep it. */ - if (eopt -> format [0] != 'E') - return 0; - /* Otherwise, return the status of the decode function. */ - return i; -} - -int fqdn_universe_decode (struct option_state *options, - const unsigned char *buffer, - unsigned length, struct universe *u) -{ - char *name; - struct buffer *bp = (struct buffer *)0; - - /* FQDN options have to be at least four bytes long. */ - if (length < 3) - return 0; - - /* Save the contents of the option in a buffer. */ - if (!buffer_allocate (&bp, length + 4, MDL)) { - log_error ("no memory for option buffer."); - return 0; - } - memcpy (&bp -> data [3], buffer + 1, length - 1); - - if (buffer [0] & 4) /* encoded */ - bp -> data [0] = 1; - else - bp -> data [0] = 0; - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [0], 1, - &fqdn_options [FQDN_ENCODED], 0)) { - bad: - buffer_dereference (&bp, MDL); - return 0; - } - - if (buffer [0] & 1) /* server-update */ - bp -> data [2] = 1; - else - bp -> data [2] = 0; - if (buffer [0] & 2) /* no-client-update */ - bp -> data [1] = 1; - else - bp -> data [1] = 0; - - /* XXX Ideally we should store the name in DNS format, so if the - XXX label isn't in DNS format, we convert it to DNS format, - XXX rather than converting labels specified in DNS format to - XXX the plain ASCII representation. But that's hard, so - XXX not now. */ - - /* Not encoded using DNS format? */ - if (!bp -> data [0]) { - unsigned i; - - /* Some broken clients NUL-terminate this option. */ - if (buffer [length - 1] == 0) { - --length; - bp -> data [1] = 1; - } - - /* Determine the length of the hostname component of the - name. If the name contains no '.' character, it - represents a non-qualified label. */ - for (i = 3; i < length && buffer [i] != '.'; i++); - i -= 3; - - /* Note: If the client sends a FQDN, the first '.' will - be used as a NUL terminator for the hostname. */ - if (i) - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data[5], i, - &fqdn_options [FQDN_HOSTNAME], - 0)) - goto bad; - /* Note: If the client sends a single label, the - FQDN_DOMAINNAME option won't be set. */ - if (length > 4 + i && - !save_option_buffer (&fqdn_universe, options, bp, - &bp -> data[6 + i], length - 4 - i, - &fqdn_options [FQDN_DOMAINNAME], 1)) - goto bad; - /* Also save the whole name. */ - if (length > 3) - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [5], length - 3, - &fqdn_options [FQDN_FQDN], 1)) - goto bad; - } else { - unsigned len; - unsigned total_len = 0; - unsigned first_len = 0; - int terminated = 0; - unsigned char *s; - - s = &bp -> data[5]; - - while (s < &bp -> data[0] + length + 2) { - len = *s; - if (len > 63) { - log_info ("fancy bits in fqdn option"); - return 0; - } - if (len == 0) { - terminated = 1; - break; - } - if (s + len > &bp -> data [0] + length + 3) { - log_info ("fqdn tag longer than buffer"); - return 0; - } - - if (first_len == 0) { - first_len = len; - } - - *s = '.'; - s += len + 1; - total_len += len + 1; - } - - /* We wind up with a length that's one too many because - we shouldn't increment for the last label, but there's - no way to tell we're at the last label until we exit - the loop. :'*/ - if (total_len > 0) - total_len--; - - if (!terminated) { - first_len = total_len; - } - - if (first_len > 0 && - !save_option_buffer (&fqdn_universe, options, bp, - &bp -> data[6], first_len, - &fqdn_options [FQDN_HOSTNAME], 0)) - goto bad; - if (total_len > 0 && first_len != total_len) { - if (!save_option_buffer - (&fqdn_universe, options, bp, - &bp -> data[6 + first_len], total_len - first_len, - &fqdn_options [FQDN_DOMAINNAME], 1)) - goto bad; - } - if (total_len > 0) - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [6], total_len, - &fqdn_options [FQDN_FQDN], 1)) - goto bad; - } - - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [1], 1, - &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0)) - goto bad; - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [2], 1, - &fqdn_options [FQDN_SERVER_UPDATE], 0)) - goto bad; - - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [3], 1, - &fqdn_options [FQDN_RCODE1], 0)) - goto bad; - if (!save_option_buffer (&fqdn_universe, options, bp, - &bp -> data [4], 1, - &fqdn_options [FQDN_RCODE2], 0)) - goto bad; - - buffer_dereference (&bp, MDL); - return 1; -} - -/* cons options into a big buffer, and then split them out into the - three seperate buffers if needed. This allows us to cons up a set - of vendor options using the same routine. */ - -int cons_options (inpacket, outpacket, lease, client_state, - mms, in_options, cfg_options, - scope, overload, terminate, bootpp, prl, vuname) - struct packet *inpacket; - struct dhcp_packet *outpacket; - struct lease *lease; - struct client_state *client_state; - int mms; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - int overload; /* Overload flags that may be set. */ - int terminate; - int bootpp; - struct data_string *prl; - const char *vuname; -{ -#define PRIORITY_COUNT 300 - unsigned priority_list [PRIORITY_COUNT]; - int priority_len; - unsigned char buffer [4096]; /* Really big buffer... */ - unsigned main_buffer_size; - unsigned mainbufix, bufix, agentix; - unsigned option_size; - unsigned length; - int i; - struct option_cache *op; - struct data_string ds; - pair pp, *hash; - int need_endopt = 0; - int have_sso = 0; - - memset (&ds, 0, sizeof ds); - - /* If there's a Maximum Message Size option in the incoming packet - and no alternate maximum message size has been specified, take the - one in the packet. */ - - if (inpacket && - (op = lookup_option (&dhcp_universe, inpacket -> options, - DHO_DHCP_MAX_MESSAGE_SIZE))) { - evaluate_option_cache (&ds, inpacket, - lease, client_state, in_options, - cfg_options, scope, op, MDL); - if (ds.len >= sizeof (u_int16_t)) { - i = getUShort (ds.data); - - if(!mms || (i < mms)) - mms = i; - } - data_string_forget (&ds, MDL); - } - - /* If the client has provided a maximum DHCP message size, - use that; otherwise, if it's BOOTP, only 64 bytes; otherwise - use up to the minimum IP MTU size (576 bytes). */ - /* XXX if a BOOTP client specifies a max message size, we will - honor it. */ - - if (mms) { - main_buffer_size = mms - DHCP_FIXED_LEN; - - /* Enforce a minimum packet size... */ - if (main_buffer_size < (576 - DHCP_FIXED_LEN)) - main_buffer_size = 576 - DHCP_FIXED_LEN; - } else if (bootpp) { - if (inpacket) { - main_buffer_size = - inpacket -> packet_length - DHCP_FIXED_LEN; - if (main_buffer_size < 64) - main_buffer_size = 64; - } else - main_buffer_size = 64; - } else - main_buffer_size = 576 - DHCP_FIXED_LEN; - - /* Set a hard limit at the size of the output buffer. */ - if (main_buffer_size > sizeof buffer) - main_buffer_size = sizeof buffer; - - /* Preload the option priority list with mandatory options. */ - priority_len = 0; - priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE; - priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER; - priority_list [priority_len++] = DHO_DHCP_LEASE_TIME; - priority_list [priority_len++] = DHO_DHCP_MESSAGE; - priority_list [priority_len++] = DHO_DHCP_REQUESTED_ADDRESS; - priority_list [priority_len++] = DHO_FQDN; - - if (prl && prl -> len > 0) { - if ((op = lookup_option (&dhcp_universe, cfg_options, - DHO_SUBNET_SELECTION))) { - if (priority_len < PRIORITY_COUNT) - priority_list [priority_len++] = - DHO_SUBNET_SELECTION; - } - - data_string_truncate (prl, (PRIORITY_COUNT - priority_len)); - - for (i = 0; i < prl -> len; i++) { - /* Prevent client from changing order of delivery - of relay agent information option. */ - if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS) - priority_list [priority_len++] = - prl -> data [i]; - } - } else { - /* First, hardcode some more options that ought to be - sent first... */ - priority_list [priority_len++] = DHO_SUBNET_MASK; - priority_list [priority_len++] = DHO_ROUTERS; - priority_list [priority_len++] = DHO_DOMAIN_NAME_SERVERS; - priority_list [priority_len++] = DHO_HOST_NAME; - - /* Append a list of the standard DHCP options from the - standard DHCP option space. Actually, if a site - option space hasn't been specified, we wind up - treating the dhcp option space as the site option - space, and the first for loop is skipped, because - it's slightly more general to do it this way, - taking the 1Q99 DHCP futures work into account. */ - if (cfg_options -> site_code_min) { - for (i = 0; i < OPTION_HASH_SIZE; i++) { - hash = cfg_options -> universes [dhcp_universe.index]; - if (hash) { - for (pp = hash [i]; pp; pp = pp -> cdr) { - op = (struct option_cache *)(pp -> car); - if (op -> option -> code < - cfg_options -> site_code_min && - priority_len < PRIORITY_COUNT && - (op -> option -> code != - DHO_DHCP_AGENT_OPTIONS)) - priority_list [priority_len++] = - op -> option -> code; - } - } - } - } - - /* Now cycle through the site option space, or if there - is no site option space, we'll be cycling through the - dhcp option space. */ - for (i = 0; i < OPTION_HASH_SIZE; i++) { - hash = (cfg_options -> universes - [cfg_options -> site_universe]); - if (hash) - for (pp = hash [i]; pp; pp = pp -> cdr) { - op = (struct option_cache *)(pp -> car); - if (op -> option -> code >= - cfg_options -> site_code_min && - priority_len < PRIORITY_COUNT && - (op -> option -> code != - DHO_DHCP_AGENT_OPTIONS)) - priority_list [priority_len++] = - op -> option -> code; - } - } - - /* Now go through all the universes for which options - were set and see if there are encapsulations for - them; if there are, put the encapsulation options - on the priority list as well. */ - for (i = 0; i < cfg_options -> universe_count; i++) { - if (cfg_options -> universes [i] && - universes [i] -> enc_opt && - priority_len < PRIORITY_COUNT && - universes [i] -> enc_opt -> universe == &dhcp_universe) - { - if (universes [i] -> enc_opt -> code != - DHO_DHCP_AGENT_OPTIONS) - priority_list [priority_len++] = - universes [i] -> enc_opt -> code; - } - } - - /* The vendor option space can't stand on its own, so always - add it to the list. */ - if (priority_len < PRIORITY_COUNT) - priority_list [priority_len++] = - DHO_VENDOR_ENCAPSULATED_OPTIONS; - } - - /* Copy the options into the big buffer... */ - option_size = store_options (buffer, - (main_buffer_size - 7 + - ((overload & 1) ? DHCP_FILE_LEN : 0) + - ((overload & 2) ? DHCP_SNAME_LEN : 0)), - inpacket, lease, client_state, - in_options, cfg_options, scope, - priority_list, priority_len, - main_buffer_size, - (main_buffer_size + - ((overload & 1) ? DHCP_FILE_LEN : 0)), - terminate, vuname); - - /* Put the cookie up front... */ - memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4); - mainbufix = 4; - - /* If we're going to have to overload, store the overload - option at the beginning. If we can, though, just store the - whole thing in the packet's option buffer and leave it at - that. */ - if (option_size <= main_buffer_size - mainbufix) { - memcpy (&outpacket -> options [mainbufix], - buffer, option_size); - mainbufix += option_size; - agentix = mainbufix; - if (mainbufix < main_buffer_size) - need_endopt = 1; - length = DHCP_FIXED_NON_UDP + mainbufix; - } else { - outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD; - outpacket -> options [mainbufix++] = 1; - if (option_size > main_buffer_size - mainbufix + DHCP_FILE_LEN) - outpacket -> options [mainbufix++] = 3; - else - outpacket -> options [mainbufix++] = 1; - - memcpy (&outpacket -> options [mainbufix], - buffer, main_buffer_size - mainbufix); - length = DHCP_FIXED_NON_UDP + main_buffer_size; - agentix = main_buffer_size; - - bufix = main_buffer_size - mainbufix; - if (overload & 1) { - if (option_size - bufix <= DHCP_FILE_LEN) { - memcpy (outpacket -> file, - &buffer [bufix], option_size - bufix); - mainbufix = option_size - bufix; - if (mainbufix < DHCP_FILE_LEN) - outpacket -> file [mainbufix++] - = DHO_END; - while (mainbufix < DHCP_FILE_LEN) - outpacket -> file [mainbufix++] - = DHO_PAD; - } else { - memcpy (outpacket -> file, - &buffer [bufix], DHCP_FILE_LEN); - bufix += DHCP_FILE_LEN; - } - } - if ((overload & 2) && option_size < bufix) { - memcpy (outpacket -> sname, - &buffer [bufix], option_size - bufix); - - mainbufix = option_size - bufix; - if (mainbufix < DHCP_SNAME_LEN) - outpacket -> file [mainbufix++] - = DHO_END; - while (mainbufix < DHCP_SNAME_LEN) - outpacket -> file [mainbufix++] - = DHO_PAD; - } - } - - /* Now hack in the agent options if there are any. */ - priority_list [0] = DHO_DHCP_AGENT_OPTIONS; - priority_len = 1; - agentix += - store_options (&outpacket -> options [agentix], - 1500 - DHCP_FIXED_LEN - agentix, - inpacket, lease, client_state, - in_options, cfg_options, scope, - priority_list, priority_len, - 1500 - DHCP_FIXED_LEN - agentix, - 1500 - DHCP_FIXED_LEN - agentix, 0, (char *)0); - - /* Tack a DHO_END option onto the packet if we need to. */ - if (agentix < 1500 - DHCP_FIXED_LEN && need_endopt) - outpacket -> options [agentix++] = DHO_END; - - /* Figure out the length. */ - length = DHCP_FIXED_NON_UDP + agentix; - return length; -} - -/* Store all the requested options into the requested buffer. */ - -int store_options (buffer, buflen, packet, lease, client_state, - in_options, cfg_options, scope, priority_list, priority_len, - first_cutoff, second_cutoff, terminate, vuname) - unsigned char *buffer; - unsigned buflen; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - unsigned *priority_list; - int priority_len; - unsigned first_cutoff, second_cutoff; - int terminate; - const char *vuname; -{ - int bufix = 0; - int i; - int ix; - int tto; - struct data_string od; - struct option_cache *oc; - unsigned code; - int optstart; - - memset (&od, 0, sizeof od); - - /* Eliminate duplicate options in the parameter request list. - There's got to be some clever knuthian way to do this: - Eliminate all but the first occurance of a value in an array - of values without otherwise disturbing the order of the array. */ - for (i = 0; i < priority_len - 1; i++) { - tto = 0; - for (ix = i + 1; ix < priority_len + tto; ix++) { - if (tto) - priority_list [ix - tto] = - priority_list [ix]; - if (priority_list [i] == priority_list [ix]) { - tto++; - priority_len--; - } - } - } - - /* Copy out the options in the order that they appear in the - priority list... */ - for (i = 0; i < priority_len; i++) { - /* Number of bytes left to store (some may already - have been stored by a previous pass). */ - unsigned length; - int optstart; - struct universe *u; - int have_encapsulation = 0; - struct data_string encapsulation; - - memset (&encapsulation, 0, sizeof encapsulation); - - /* Code for next option to try to store. */ - code = priority_list [i]; - - /* Look up the option in the site option space if the code - is above the cutoff, otherwise in the DHCP option space. */ - if (code >= cfg_options -> site_code_min) - u = universes [cfg_options -> site_universe]; - else - u = &dhcp_universe; - - oc = lookup_option (u, cfg_options, code); - - /* It's an encapsulation, try to find the universe - to be encapsulated first, except that if it's a straight - encapsulation and the user has provided a value for the - encapsulation option, use the user-provided value. */ - if (u -> options [code] && - ((u -> options [code] -> format [0] == 'E' && !oc) || - u -> options [code] -> format [0] == 'e')) { - int uix; - static char *s, *t; - struct option_cache *tmp; - struct data_string name; - - s = strchr (u -> options [code] -> format, 'E'); - if (s) - t = strchr (++s, '.'); - if (s && t) { - memset (&name, 0, sizeof name); - - /* A zero-length universe name means the vendor - option space, if one is defined. */ - if (t == s) { - if (vendor_cfg_option) { - tmp = lookup_option (vendor_cfg_option -> universe, - cfg_options, - vendor_cfg_option -> code); - if (tmp) - evaluate_option_cache (&name, packet, lease, - client_state, - in_options, - cfg_options, - scope, tmp, MDL); - } else if (vuname) { - name.data = (unsigned char *)s; - name.len = strlen (s); - } - } else { - name.data = (unsigned char *)s; - name.len = t - s; - } - - /* If we found a universe, and there are options configured - for that universe, try to encapsulate it. */ - if (name.len) { - have_encapsulation = - (option_space_encapsulate - (&encapsulation, packet, lease, client_state, - in_options, cfg_options, scope, &name)); - data_string_forget (&name, MDL); - } - } - } - - /* In order to avoid memory leaks, we have to get to here - with any option cache that we allocated in tmp not being - referenced by tmp, and whatever option cache is referenced - by oc being an actual reference. lookup_option doesn't - generate a reference (this needs to be fixed), so the - preceding goop ensures that if we *didn't* generate a new - option cache, oc still winds up holding an actual reference. */ - - /* If no data is available for this option, skip it. */ - if (!oc && !have_encapsulation) { - continue; - } - - /* Find the value of the option... */ - if (oc) { - evaluate_option_cache (&od, packet, - lease, client_state, in_options, - cfg_options, scope, oc, MDL); - if (!od.len) { - data_string_forget (&encapsulation, MDL); - data_string_forget (&od, MDL); - have_encapsulation = 0; - continue; - } - } - - /* We should now have a constant length for the option. */ - length = od.len; - if (have_encapsulation) { - length += encapsulation.len; - if (!od.len) { - data_string_copy (&od, &encapsulation, MDL); - data_string_forget (&encapsulation, MDL); - } else { - struct buffer *bp = (struct buffer *)0; - if (!buffer_allocate (&bp, length, MDL)) { - option_cache_dereference (&oc, MDL); - data_string_forget (&od, MDL); - data_string_forget (&encapsulation, MDL); - continue; - } - memcpy (&bp -> data [0], od.data, od.len); - memcpy (&bp -> data [od.len], encapsulation.data, - encapsulation.len); - data_string_forget (&od, MDL); - data_string_forget (&encapsulation, MDL); - od.data = &bp -> data [0]; - buffer_reference (&od.buffer, bp, MDL); - buffer_dereference (&bp, MDL); - od.len = length; - od.terminated = 0; - } - } - - /* Do we add a NUL? */ - if (terminate && dhcp_options [code].format [0] == 't') { - length++; - tto = 1; - } else { - tto = 0; - } - - /* Try to store the option. */ - - /* If the option's length is more than 255, we must store it - in multiple hunks. Store 255-byte hunks first. However, - in any case, if the option data will cross a buffer - boundary, split it across that boundary. */ - - ix = 0; - optstart = bufix; - while (length) { - unsigned char incr = length > 255 ? 255 : length; - int consumed = 0; - - /* If this hunk of the buffer will cross a - boundary, only go up to the boundary in this - pass. */ - if (bufix < first_cutoff && - bufix + incr > first_cutoff) - incr = first_cutoff - bufix; - else if (bufix < second_cutoff && - bufix + incr > second_cutoff) - incr = second_cutoff - bufix; - - /* If this option is going to overflow the buffer, - skip it. */ - if (bufix + 2 + incr > buflen) { - bufix = optstart; - break; - } - - /* Everything looks good - copy it in! */ - buffer [bufix] = code; - buffer [bufix + 1] = incr; - if (tto && incr == length) { - memcpy (buffer + bufix + 2, - od.data + ix, (unsigned)(incr - 1)); - buffer [bufix + 2 + incr - 1] = 0; - } else { - memcpy (buffer + bufix + 2, - od.data + ix, (unsigned)incr); - } - length -= incr; - ix += incr; - bufix += 2 + incr; - } - data_string_forget (&od, MDL); - } - - return bufix; -} - -/* Format the specified option so that a human can easily read it. */ - -const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) - struct option *option; - const unsigned char *data; - unsigned len; - int emit_commas; - int emit_quotes; -{ - static char optbuf [32768]; /* XXX */ - int hunksize = 0; - int opthunk = 0; - int hunkinc = 0; - int numhunk = -1; - int numelem = 0; - char fmtbuf [32]; - struct enumeration *enumbuf [32]; - int i, j, k, l; - char *op = optbuf; - const unsigned char *dp = data; - struct in_addr foo; - char comma; - unsigned long tval; - - if (emit_commas) - comma = ','; - else - comma = ' '; - - memset (enumbuf, 0, sizeof enumbuf); - - /* Figure out the size of the data. */ - for (l = i = 0; option -> format [i]; i++, l++) { - if (!numhunk) { - log_error ("%s: Extra codes in format string: %s", - option -> name, - &(option -> format [i])); - break; - } - numelem++; - fmtbuf [l] = option -> format [i]; - switch (option -> format [i]) { - case 'a': - --numelem; - fmtbuf [l] = 0; - numhunk = 0; - break; - case 'A': - --numelem; - fmtbuf [l] = 0; - numhunk = 0; - break; - case 'E': - /* Skip the universe name. */ - while (option -> format [i] && - option -> format [i] != '.') - i++; - case 'X': - for (k = 0; k < len; k++) { - if (!isascii (data [k]) || - !isprint (data [k])) - break; - } - /* If we found no bogus characters, or the bogus - character we found is a trailing NUL, it's - okay to print this option as text. */ - if (k == len || (k + 1 == len && data [k] == 0)) { - fmtbuf [l] = 't'; - numhunk = -2; - } else { - fmtbuf [l] = 'x'; - hunksize++; - comma = ':'; - numhunk = 0; - } - fmtbuf [l + 1] = 0; - break; - case 'd': - case 't': - fmtbuf [l] = 't'; - fmtbuf [l + 1] = 0; - numhunk = -2; - break; - case 'N': - k = i; - while (option -> format [i] && - option -> format [i] != '.') - i++; - enumbuf [l] = - find_enumeration (&option -> format [k] + 1, - i - k - 1); - hunksize += 1; - hunkinc = 1; - break; - case 'I': - case 'l': - case 'L': - case 'T': - hunksize += 4; - hunkinc = 4; - break; - case 's': - case 'S': - hunksize += 2; - hunkinc = 2; - break; - case 'b': - case 'B': - case 'f': - hunksize++; - hunkinc = 1; - break; - case 'e': - break; - case 'o': - opthunk += hunkinc; - break; - default: - log_error ("%s: garbage in format string: %s", - option -> name, - &(option -> format [i])); - break; - } - } - - /* Check for too few bytes... */ - if (hunksize - opthunk > len) { - log_error ("%s: expecting at least %d bytes; got %d", - option -> name, - hunksize, len); - return "<error>"; - } - /* Check for too many bytes... */ - if (numhunk == -1 && hunksize < len) - log_error ("%s: %d extra bytes", - option -> name, - len - hunksize); - - /* If this is an array, compute its size. */ - if (!numhunk) - numhunk = len / hunksize; - /* See if we got an exact number of hunks. */ - if (numhunk > 0 && numhunk * hunksize < len) - log_error ("%s: %d extra bytes at end of array\n", - option -> name, - len - numhunk * hunksize); - - /* A one-hunk array prints the same as a single hunk. */ - if (numhunk < 0) - numhunk = 1; - - /* Cycle through the array (or hunk) printing the data. */ - for (i = 0; i < numhunk; i++) { - for (j = 0; j < numelem; j++) { - switch (fmtbuf [j]) { - case 't': - if (emit_quotes) - *op++ = '"'; - for (; dp < data + len; dp++) { - if (!isascii (*dp) || - !isprint (*dp)) { - /* Skip trailing NUL. */ - if (dp + 1 != data + len || - *dp != 0) { - sprintf (op, "\\%03o", - *dp); - op += 4; - } - } else if (*dp == '"' || - *dp == '\'' || - *dp == '$' || - *dp == '`' || - *dp == '\\') { - *op++ = '\\'; - *op++ = *dp; - } else - *op++ = *dp; - } - if (emit_quotes) - *op++ = '"'; - *op = 0; - break; - /* pretty-printing an array of enums is - going to get ugly. */ - case 'N': - if (!enumbuf [j]) - goto enum_as_num; - for (i = 0; ;i++) { - if (!enumbuf [j] -> values [i].name) - goto enum_as_num; - if (enumbuf [j] -> values [i].value == - *dp) - break; - } - strcpy (op, enumbuf [j] -> values [i].name); - op += strlen (op); - break; - case 'I': - foo.s_addr = htonl (getULong (dp)); - strcpy (op, inet_ntoa (foo)); - dp += 4; - break; - case 'l': - sprintf (op, "%ld", (long)getLong (dp)); - dp += 4; - break; - case 'T': - tval = getULong (dp); - if (tval == -1) - sprintf (op, "%s", "infinite"); - else - sprintf (op, "%ld", tval); - break; - case 'L': - sprintf (op, "%ld", - (unsigned long)getULong (dp)); - dp += 4; - break; - case 's': - sprintf (op, "%d", (int)getShort (dp)); - dp += 2; - break; - case 'S': - sprintf (op, "%d", (unsigned)getUShort (dp)); - dp += 2; - break; - case 'b': - sprintf (op, "%d", *(const char *)dp++); - break; - case 'B': - enum_as_num: - sprintf (op, "%d", *dp++); - break; - case 'x': - sprintf (op, "%x", *dp++); - break; - case 'f': - strcpy (op, *dp++ ? "true" : "false"); - break; - default: - log_error ("Unexpected format code %c", - fmtbuf [j]); - } - op += strlen (op); - if (dp == data + len) - break; - if (j + 1 < numelem && comma != ':') - *op++ = ' '; - } - if (i + 1 < numhunk) { - *op++ = comma; - } - if (dp == data + len) - break; - } - return optbuf; -} - -int get_option (result, universe, packet, lease, client_state, - in_options, cfg_options, options, scope, code, file, line) - struct data_string *result; - struct universe *universe; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct option_state *options; - struct binding_scope **scope; - unsigned code; - const char *file; - int line; -{ - struct option_cache *oc; - - if (!universe -> lookup_func) - return 0; - oc = ((*universe -> lookup_func) (universe, options, code)); - if (!oc) - return 0; - if (!evaluate_option_cache (result, packet, lease, client_state, - in_options, cfg_options, scope, oc, - file, line)) - return 0; - return 1; -} - -void set_option (universe, options, option, op) - struct universe *universe; - struct option_state *options; - struct option_cache *option; - enum statement_op op; -{ - struct option_cache *oc, *noc; - - switch (op) { - case if_statement: - case add_statement: - case eval_statement: - case break_statement: - default: - log_error ("bogus statement type in do_option_set."); - break; - - case default_option_statement: - oc = lookup_option (universe, options, - option -> option -> code); - if (oc) - break; - save_option (universe, options, option); - break; - - case supersede_option_statement: - case send_option_statement: - /* Install the option, replacing any existing version. */ - save_option (universe, options, option); - break; - - case append_option_statement: - case prepend_option_statement: - oc = lookup_option (universe, options, - option -> option -> code); - if (!oc) { - save_option (universe, options, option); - break; - } - /* If it's not an expression, make it into one. */ - if (!oc -> expression && oc -> data.len) { - if (!expression_allocate (&oc -> expression, MDL)) { - log_error ("Can't allocate const expression."); - break; - } - oc -> expression -> op = expr_const_data; - data_string_copy - (&oc -> expression -> data.const_data, - &oc -> data, MDL); - data_string_forget (&oc -> data, MDL); - } - noc = (struct option_cache *)0; - if (!option_cache_allocate (&noc, MDL)) - break; - if (op == append_option_statement) { - if (!make_concat (&noc -> expression, - oc -> expression, - option -> expression)) { - option_cache_dereference (&noc, MDL); - break; - } - } else { - if (!make_concat (&noc -> expression, - option -> expression, - oc -> expression)) { - option_cache_dereference (&noc, MDL); - break; - } - } - noc -> option = oc -> option; - save_option (universe, options, noc); - option_cache_dereference (&noc, MDL); - break; - } -} - -struct option_cache *lookup_option (universe, options, code) - struct universe *universe; - struct option_state *options; - unsigned code; -{ - if (!options) - return (struct option_cache *)0; - if (universe -> lookup_func) - return (*universe -> lookup_func) (universe, options, code); - else - log_error ("can't look up options in %s space.", - universe -> name); - return (struct option_cache *)0; -} - -struct option_cache *lookup_hashed_option (universe, options, code) - struct universe *universe; - struct option_state *options; - unsigned code; -{ - int hashix; - pair bptr; - pair *hash; - - /* Make sure there's a hash table. */ - if (universe -> index >= options -> universe_count || - !(options -> universes [universe -> index])) - return (struct option_cache *)0; - - hash = options -> universes [universe -> index]; - - hashix = compute_option_hash (code); - for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { - if (((struct option_cache *)(bptr -> car)) -> option -> code == - code) - return (struct option_cache *)(bptr -> car); - } - return (struct option_cache *)0; -} - -int save_option_buffer (struct universe *universe, - struct option_state *options, - struct buffer *bp, - unsigned char *buffer, unsigned length, - struct option *option, int tp) -{ - struct buffer *lbp = (struct buffer *)0; - struct option_cache *op = (struct option_cache *)0; - - if (!option_cache_allocate (&op, MDL)) { - log_error ("No memory for option %s.%s.", - universe -> name, - option -> name); - return 0; - } - - /* If we weren't passed a buffer in which the data are saved and - refcounted, allocate one now. */ - if (!bp) { - if (!buffer_allocate (&lbp, length, MDL)) { - log_error ("no memory for option buffer."); - - option_cache_dereference (&op, MDL); - return 0; - } - memcpy (lbp -> data, buffer, length + tp); - bp = lbp; - buffer = &bp -> data [0]; /* Refer to saved buffer. */ - } - - /* Reference buffer copy to option cache. */ - op -> data.buffer = (struct buffer *)0; - buffer_reference (&op -> data.buffer, bp, MDL); - - /* Point option cache into buffer. */ - op -> data.data = buffer; - op -> data.len = length; - - if (tp) { - /* NUL terminate (we can get away with this because we (or - the caller!) allocated one more than the buffer size, and - because the byte following the end of an option is always - the code of the next option, which the caller is getting - out of the *original* buffer. */ - buffer [length] = 0; - op -> data.terminated = 1; - } else - op -> data.terminated = 0; - - op -> option = option; - - /* Now store the option. */ - save_option (universe, options, op); - - /* And let go of our reference. */ - option_cache_dereference (&op, MDL); - - return 1; -} - -void save_option (struct universe *universe, - struct option_state *options, struct option_cache *oc) -{ - if (universe -> save_func) - (*universe -> save_func) (universe, options, oc); - else - log_error ("can't store options in %s space.", - universe -> name); -} - -void save_hashed_option (universe, options, oc) - struct universe *universe; - struct option_state *options; - struct option_cache *oc; -{ - int hashix; - pair bptr; - pair *hash = options -> universes [universe -> index]; - - if (oc -> refcnt == 0) - abort (); - - /* Compute the hash. */ - hashix = compute_option_hash (oc -> option -> code); - - /* If there's no hash table, make one. */ - if (!hash) { - hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL); - if (!hash) { - log_error ("no memory to store %s.%s", - universe -> name, oc -> option -> name); - return; - } - memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash); - options -> universes [universe -> index] = (VOIDPTR)hash; - } else { - /* Try to find an existing option matching the new one. */ - for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { - if (((struct option_cache *) - (bptr -> car)) -> option -> code == - oc -> option -> code) - break; - } - - /* If we find one, dereference it and put the new one - in its place. */ - if (bptr) { - option_cache_dereference - ((struct option_cache **)&bptr -> car, MDL); - option_cache_reference - ((struct option_cache **)&bptr -> car, - oc, MDL); - return; - } - } - - /* Otherwise, just put the new one at the head of the list. */ - bptr = new_pair (MDL); - if (!bptr) { - log_error ("No memory for option_cache reference."); - return; - } - bptr -> cdr = hash [hashix]; - bptr -> car = 0; - option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL); - hash [hashix] = bptr; -} - -void delete_option (universe, options, code) - struct universe *universe; - struct option_state *options; - int code; -{ - if (universe -> delete_func) - (*universe -> delete_func) (universe, options, code); - else - log_error ("can't delete options from %s space.", - universe -> name); -} - -void delete_hashed_option (universe, options, code) - struct universe *universe; - struct option_state *options; - int code; -{ - int hashix; - pair bptr, prev = (pair)0; - pair *hash = options -> universes [universe -> index]; - - /* There may not be any options in this space. */ - if (!hash) - return; - - /* Try to find an existing option matching the new one. */ - hashix = compute_option_hash (code); - for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { - if (((struct option_cache *)(bptr -> car)) -> option -> code - == code) - break; - prev = bptr; - } - /* If we found one, wipe it out... */ - if (bptr) { - if (prev) - prev -> cdr = bptr -> cdr; - else - hash [hashix] = bptr -> cdr; - option_cache_dereference - ((struct option_cache **)(&bptr -> car), MDL); - free_pair (bptr, MDL); - } -} - -extern struct option_cache *free_option_caches; /* XXX */ - -int option_cache_dereference (ptr, file, line) - struct option_cache **ptr; - const char *file; - int line; -{ - if (!ptr || !*ptr) { - log_error ("Null pointer in option_cache_dereference: %s(%d)", - file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - (*ptr) -> refcnt--; - rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC); - if (!(*ptr) -> refcnt) { - if ((*ptr) -> data.buffer) - data_string_forget (&(*ptr) -> data, file, line); - if ((*ptr) -> expression) - expression_dereference (&(*ptr) -> expression, - file, line); - if ((*ptr) -> next) - option_cache_dereference (&((*ptr) -> next), - file, line); - /* Put it back on the free list... */ - (*ptr) -> expression = (struct expression *)free_option_caches; - free_option_caches = *ptr; - dmalloc_reuse (free_option_caches, (char *)0, 0, 0); - } - if ((*ptr) -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (*ptr); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct option_cache *)0; - return 0; -#endif - } - *ptr = (struct option_cache *)0; - return 1; - -} - -int hashed_option_state_dereference (universe, state, file, line) - struct universe *universe; - struct option_state *state; - const char *file; - int line; -{ - pair *heads; - pair cp, next; - int i; - - /* Get the pointer to the array of hash table bucket heads. */ - heads = (pair *)(state -> universes [universe -> index]); - if (!heads) - return 0; - - /* For each non-null head, loop through all the buckets dereferencing - the attached option cache structures and freeing the buckets. */ - for (i = 0; i < OPTION_HASH_SIZE; i++) { - for (cp = heads [i]; cp; cp = next) { - next = cp -> cdr; - option_cache_dereference - ((struct option_cache **)&cp -> car, - file, line); - free_pair (cp, file, line); - } - } - - dfree (heads, file, line); - state -> universes [universe -> index] = (void *)0; - return 1; -} - -int store_option (result, universe, packet, lease, client_state, - in_options, cfg_options, scope, oc) - struct data_string *result; - struct universe *universe; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct option_cache *oc; -{ - struct data_string d1, d2; - - memset (&d1, 0, sizeof d1); - memset (&d2, 0, sizeof d2); - - if (evaluate_option_cache (&d2, packet, lease, client_state, - in_options, cfg_options, scope, oc, MDL)) { - if (!buffer_allocate (&d1.buffer, - (result -> len + - universe -> length_size + - universe -> tag_size + d2.len), MDL)) { - data_string_forget (result, MDL); - data_string_forget (&d2, MDL); - return 0; - } - d1.data = &d1.buffer -> data [0]; - if (result -> len) - memcpy (d1.buffer -> data, - result -> data, result -> len); - d1.len = result -> len; - (*universe -> store_tag) (&d1.buffer -> data [d1.len], - oc -> option -> code); - d1.len += universe -> tag_size; - (*universe -> store_length) (&d1.buffer -> data [d1.len], - d2.len); - d1.len += universe -> length_size; - memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len); - d1.len += d2.len; - data_string_forget (&d2, MDL); - data_string_forget (result, MDL); - data_string_copy (result, &d1, MDL); - data_string_forget (&d1, MDL); - return 1; - } - return 0; -} - -int option_space_encapsulate (result, packet, lease, client_state, - in_options, cfg_options, scope, name) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct data_string *name; -{ - struct universe *u; - - u = (struct universe *)0; - universe_hash_lookup (&u, universe_hash, - (const char *)name -> data, name -> len, MDL); - if (!u) - return 0; - - if (u -> encapsulate) - return (*u -> encapsulate) (result, packet, lease, - client_state, - in_options, cfg_options, scope, u); - log_error ("encapsulation requested for %s with no support.", - name -> data); - return 0; -} - -int hashed_option_space_encapsulate (result, packet, lease, client_state, - in_options, cfg_options, scope, universe) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct universe *universe; -{ - pair p, *hash; - int status; - int i; - - if (universe -> index >= cfg_options -> universe_count) - return 0; - - hash = cfg_options -> universes [universe -> index]; - if (!hash) - return 0; - - status = 0; - for (i = 0; i < OPTION_HASH_SIZE; i++) { - for (p = hash [i]; p; p = p -> cdr) { - if (store_option (result, universe, packet, - lease, client_state, in_options, - cfg_options, scope, - (struct option_cache *)p -> car)) - status = 1; - } - } - - return status; -} - -int nwip_option_space_encapsulate (result, packet, lease, client_state, - in_options, cfg_options, scope, universe) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct universe *universe; -{ - pair ocp; - int status; - int i; - static struct option_cache *no_nwip; - struct data_string ds; - struct option_chain_head *head; - - if (universe -> index >= cfg_options -> universe_count) - return 0; - head = ((struct option_chain_head *) - cfg_options -> universes [fqdn_universe.index]); - if (!head) - return 0; - - status = 0; - for (ocp = head -> first; ocp; ocp = ocp -> cdr) { - struct option_cache *oc = (struct option_cache *)(ocp -> car); - if (store_option (result, universe, packet, - lease, client_state, in_options, - cfg_options, scope, - (struct option_cache *)ocp -> car)) - status = 1; - } - - /* If there's no data, the nwip suboption is supposed to contain - a suboption saying there's no data. */ - if (!status) { - if (!no_nwip) { - static unsigned char nni [] = { 1, 0 }; - memset (&ds, 0, sizeof ds); - ds.data = nni; - ds.len = 2; - if (option_cache_allocate (&no_nwip, MDL)) - data_string_copy (&no_nwip -> data, &ds, MDL); - no_nwip -> option = nwip_universe.options [1]; - } - if (no_nwip) { - if (store_option (result, universe, packet, lease, - client_state, in_options, - cfg_options, scope, no_nwip)) - status = 1; - } - } else { - memset (&ds, 0, sizeof ds); - - /* If we have nwip options, the first one has to be the - nwip-exists-in-option-area option. */ - if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) { - data_string_forget (result, MDL); - return 0; - } - ds.data = &ds.buffer -> data [0]; - ds.buffer -> data [0] = 2; - ds.buffer -> data [1] = 0; - memcpy (&ds.buffer -> data [2], result -> data, result -> len); - data_string_forget (result, MDL); - data_string_copy (result, &ds, MDL); - data_string_forget (&ds, MDL); - } - - return status; -} - -int fqdn_option_space_encapsulate (result, packet, lease, client_state, - in_options, cfg_options, scope, universe) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct universe *universe; -{ - pair ocp; - struct data_string results [FQDN_SUBOPTION_COUNT + 1]; - unsigned i; - unsigned len; - struct buffer *bp = (struct buffer *)0; - struct option_chain_head *head; - - /* If there's no FQDN universe, don't encapsulate. */ - if (fqdn_universe.index >= cfg_options -> universe_count) - return 0; - head = ((struct option_chain_head *) - cfg_options -> universes [fqdn_universe.index]); - if (!head) - return 0; - - /* Figure out the values of all the suboptions. */ - memset (results, 0, sizeof results); - for (ocp = head -> first; ocp; ocp = ocp -> cdr) { - struct option_cache *oc = (struct option_cache *)(ocp -> car); - if (oc -> option -> code > FQDN_SUBOPTION_COUNT) - continue; - evaluate_option_cache (&results [oc -> option -> code], - packet, lease, client_state, in_options, - cfg_options, scope, oc, MDL); - } - len = 4 + results [FQDN_FQDN].len; - /* Save the contents of the option in a buffer. */ - if (!buffer_allocate (&bp, len, MDL)) { - log_error ("no memory for option buffer."); - return 0; - } - buffer_reference (&result -> buffer, bp, MDL); - result -> len = 3; - result -> data = &bp -> data [0]; - - memset (&bp -> data [0], 0, len); - if (results [FQDN_NO_CLIENT_UPDATE].len && - results [FQDN_NO_CLIENT_UPDATE].data [0]) - bp -> data [0] |= 2; - if (results [FQDN_SERVER_UPDATE].len && - results [FQDN_SERVER_UPDATE].data [0]) - bp -> data [0] |= 1; - if (results [FQDN_RCODE1].len) - bp -> data [1] = results [FQDN_RCODE1].data [0]; - if (results [FQDN_RCODE2].len) - bp -> data [2] = results [FQDN_RCODE2].data [0]; - - if (results [FQDN_ENCODED].len && - results [FQDN_ENCODED].data [0]) { - unsigned char *out; - int i; - bp -> data [0] |= 4; - out = &bp -> data [3]; - if (results [FQDN_FQDN].len) { - i = 0; - while (i < results [FQDN_FQDN].len) { - int j; - for (j = i; ('.' != - results [FQDN_FQDN].data [j]) && - j < results [FQDN_FQDN].len; j++) - ; - *out++ = j - i; - memcpy (out, &results [FQDN_FQDN].data [i], - (unsigned)(j - i)); - out += j - i; - i = j; - if (results [FQDN_FQDN].data [j] == '.') - i++; - } - if ((results [FQDN_FQDN].data - [results [FQDN_FQDN].len - 1] == '.')) - *out++ = 0; - result -> len = out - result -> data; - result -> terminated = 0; - } - } else { - if (results [FQDN_FQDN].len) { - memcpy (&bp -> data [3], results [FQDN_FQDN].data, - results [FQDN_FQDN].len); - result -> len += results [FQDN_FQDN].len; - result -> terminated = 0; - } - } - for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) { - if (results [i].len) - data_string_forget (&results [i], MDL); - } - buffer_dereference (&bp, MDL); - return 1; -} - -void option_space_foreach (struct packet *packet, struct lease *lease, - struct client_state *client_state, - struct option_state *in_options, - struct option_state *cfg_options, - struct binding_scope **scope, - struct universe *u, void *stuff, - void (*func) (struct option_cache *, - struct packet *, - struct lease *, struct client_state *, - struct option_state *, - struct option_state *, - struct binding_scope **, - struct universe *, void *)) -{ - if (u -> foreach) - (*u -> foreach) (packet, lease, client_state, in_options, - cfg_options, scope, u, stuff, func); -} - -void suboption_foreach (struct packet *packet, struct lease *lease, - struct client_state *client_state, - struct option_state *in_options, - struct option_state *cfg_options, - struct binding_scope **scope, - struct universe *u, void *stuff, - void (*func) (struct option_cache *, - struct packet *, - struct lease *, struct client_state *, - struct option_state *, - struct option_state *, - struct binding_scope **, - struct universe *, void *), - struct option_cache *oc, - const char *vsname) -{ - struct universe *universe = find_option_universe (oc -> option, - vsname); - int i; - - if (universe -> foreach) - (*universe -> foreach) (packet, lease, client_state, - in_options, cfg_options, - scope, universe, stuff, func); -} - -void hashed_option_space_foreach (struct packet *packet, struct lease *lease, - struct client_state *client_state, - struct option_state *in_options, - struct option_state *cfg_options, - struct binding_scope **scope, - struct universe *u, void *stuff, - void (*func) (struct option_cache *, - struct packet *, - struct lease *, - struct client_state *, - struct option_state *, - struct option_state *, - struct binding_scope **, - struct universe *, void *)) -{ - pair *hash; - int i; - struct option_cache *oc; - - if (cfg_options -> universe_count <= u -> index) - return; - - hash = cfg_options -> universes [u -> index]; - if (!hash) - return; - for (i = 0; i < OPTION_HASH_SIZE; i++) { - pair p; - /* XXX save _all_ options! XXX */ - for (p = hash [i]; p; p = p -> cdr) { - oc = (struct option_cache *)p -> car; - (*func) (oc, packet, lease, client_state, - in_options, cfg_options, scope, u, stuff); - } - } -} - -void save_linked_option (universe, options, oc) - struct universe *universe; - struct option_state *options; - struct option_cache *oc; -{ - pair *tail; - pair np = (pair )0; - struct option_chain_head *head; - - if (universe -> index >= options -> universe_count) - return; - head = ((struct option_chain_head *) - options -> universes [universe -> index]); - if (!head) { - if (!option_chain_head_allocate (((struct option_chain_head **) - &options -> universes - [universe -> index]), MDL)) - return; - head = ((struct option_chain_head *) - options -> universes [universe -> index]); - } - - /* Find the tail of the list. */ - for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) { - if (oc -> option == - ((struct option_cache *)((*tail) -> car)) -> option) { - option_cache_dereference ((struct option_cache **) - (&(*tail) -> car), MDL); - option_cache_reference ((struct option_cache **) - (&(*tail) -> car), oc, MDL); - return; - } - } - - *tail = cons (0, 0); - if (*tail) { - option_cache_reference ((struct option_cache **) - (&(*tail) -> car), oc, MDL); - } -} - -int linked_option_space_encapsulate (result, packet, lease, client_state, - in_options, cfg_options, scope, universe) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct universe *universe; -{ - int status; - pair oc; - struct option_chain_head *head; - - if (universe -> index >= cfg_options -> universe_count) - return 0; - head = ((struct option_chain_head *) - cfg_options -> universes [universe -> index]); - if (!head) - return 0; - - status = 0; - for (oc = head -> first; oc; oc = oc -> cdr) { - if (store_option (result, universe, packet, - lease, client_state, in_options, cfg_options, - scope, (struct option_cache *)(oc -> car))) - status = 1; - } - - return status; -} - -void delete_linked_option (universe, options, code) - struct universe *universe; - struct option_state *options; - int code; -{ - pair *tail, tmp = (pair)0; - struct option_chain_head *head; - - if (universe -> index >= options -> universe_count) - return; - head = ((struct option_chain_head *) - options -> universes [universe -> index]); - if (!head) - return; - - for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) { - if (code == - ((struct option_cache *)(*tail) -> car) -> option -> code) - { - tmp = (*tail) -> cdr; - option_cache_dereference ((struct option_cache **) - (&(*tail) -> car), MDL); - dfree (*tail, MDL); - (*tail) = tmp; - break; - } - } -} - -struct option_cache *lookup_linked_option (universe, options, code) - struct universe *universe; - struct option_state *options; - unsigned code; -{ - pair oc; - struct option_chain_head *head; - - if (universe -> index >= options -> universe_count) - return 0; - head = ((struct option_chain_head *) - options -> universes [universe -> index]); - if (!head) - return 0; - - for (oc = head -> first; oc; oc = oc -> cdr) { - if (code == - ((struct option_cache *)(oc -> car)) -> option -> code) { - return (struct option_cache *)(oc -> car); - } - } - - return (struct option_cache *)0; -} - -int linked_option_state_dereference (universe, state, file, line) - struct universe *universe; - struct option_state *state; - const char *file; - int line; -{ - return (option_chain_head_dereference - ((struct option_chain_head **) - (&state -> universes [universe -> index]), MDL)); -} - -void linked_option_space_foreach (struct packet *packet, struct lease *lease, - struct client_state *client_state, - struct option_state *in_options, - struct option_state *cfg_options, - struct binding_scope **scope, - struct universe *u, void *stuff, - void (*func) (struct option_cache *, - struct packet *, - struct lease *, - struct client_state *, - struct option_state *, - struct option_state *, - struct binding_scope **, - struct universe *, void *)) -{ - pair car; - struct option_chain_head *head; - - if (u -> index >= cfg_options -> universe_count) - return; - head = ((struct option_chain_head *) - cfg_options -> universes [u -> index]); - if (!head) - return; - for (car = head -> first; car; car = car -> cdr) { - (*func) ((struct option_cache *)(car -> car), - packet, lease, client_state, - in_options, cfg_options, scope, u, stuff); - } -} - -void do_packet (interface, packet, len, from_port, from, hfrom) - struct interface_info *interface; - struct dhcp_packet *packet; - unsigned len; - unsigned int from_port; - struct iaddr from; - struct hardware *hfrom; -{ - int i; - struct option_cache *op; - struct packet *decoded_packet; -#if defined (DEBUG_MEMORY_LEAKAGE) - unsigned long previous_outstanding = dmalloc_outstanding; -#endif - -#if defined (TRACING) - trace_inpacket_stash (interface, packet, len, from_port, from, hfrom); -#endif - - decoded_packet = (struct packet *)0; - if (!packet_allocate (&decoded_packet, MDL)) { - log_error ("do_packet: no memory for incoming packet!"); - return; - } - decoded_packet -> raw = packet; - decoded_packet -> packet_length = len; - decoded_packet -> client_port = from_port; - decoded_packet -> client_addr = from; - interface_reference (&decoded_packet -> interface, interface, MDL); - decoded_packet -> haddr = hfrom; - - if (packet -> hlen > sizeof packet -> chaddr) { - packet_dereference (&decoded_packet, MDL); - log_info ("Discarding packet with bogus hlen."); - return; - } - - /* If there's an option buffer, try to parse it. */ - if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) { - if (!parse_options (decoded_packet)) { - if (decoded_packet -> options) - option_state_dereference - (&decoded_packet -> options, MDL); - packet_dereference (&decoded_packet, MDL); - return; - } - - if (decoded_packet -> options_valid && - (op = lookup_option (&dhcp_universe, - decoded_packet -> options, - DHO_DHCP_MESSAGE_TYPE))) { - struct data_string dp; - memset (&dp, 0, sizeof dp); - evaluate_option_cache (&dp, decoded_packet, - (struct lease *)0, - (struct client_state *)0, - decoded_packet -> options, - (struct option_state *)0, - (struct binding_scope **)0, - op, MDL); - if (dp.len > 0) - decoded_packet -> packet_type = dp.data [0]; - else - decoded_packet -> packet_type = 0; - data_string_forget (&dp, MDL); - } - } - - if (decoded_packet -> packet_type) - dhcp (decoded_packet); - else - bootp (decoded_packet); - - /* If the caller kept the packet, they'll have upped the refcnt. */ - packet_dereference (&decoded_packet, MDL); - -#if defined (DEBUG_MEMORY_LEAKAGE) - log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term", - dmalloc_generation, - dmalloc_outstanding - previous_outstanding, - dmalloc_outstanding, dmalloc_longterm); -#endif -#if defined (DEBUG_MEMORY_LEAKAGE) - dmalloc_dump_outstanding (); -#endif -#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY) - dump_rc_history (0); -#endif -} - diff --git a/contrib/isc-dhcp/common/packet.c b/contrib/isc-dhcp/common/packet.c deleted file mode 100644 index 4038aec..0000000 --- a/contrib/isc-dhcp/common/packet.c +++ /dev/null @@ -1,339 +0,0 @@ -/* packet.c - - Packet assembly code, originally contributed by Archie Cobbs. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This code was originally contributed by Archie Cobbs, and is still - * very similar to that contribution, although the packet checksum code - * has been hacked significantly with the help of quite a few ISC DHCP - * users, without whose gracious and thorough help the checksum code would - * still be disabled. - */ - -#ifndef lint -static char copyright[] = -"$Id: packet.c,v 1.40.2.3 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING) -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" -#endif /* PACKET_ASSEMBLY || PACKET_DECODING */ - -/* Compute the easy part of the checksum on a range of bytes. */ - -u_int32_t checksum (buf, nbytes, sum) - unsigned char *buf; - unsigned nbytes; - u_int32_t sum; -{ - unsigned i; - -#ifdef DEBUG_CHECKSUM - log_debug ("checksum (%x %d %x)", buf, nbytes, sum); -#endif - - /* Checksum all the pairs of bytes first... */ - for (i = 0; i < (nbytes & ~1U); i += 2) { -#ifdef DEBUG_CHECKSUM_VERBOSE - log_debug ("sum = %x", sum); -#endif - sum += (u_int16_t) ntohs(*((u_int16_t *)(buf + i))); - /* Add carry. */ - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - - /* If there's a single byte left over, checksum it, too. Network - byte order is big-endian, so the remaining byte is the high byte. */ - if (i < nbytes) { -#ifdef DEBUG_CHECKSUM_VERBOSE - log_debug ("sum = %x", sum); -#endif - sum += buf [i] << 8; - /* Add carry. */ - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - - return sum; -} - -/* Finish computing the checksum, and then put it into network byte order. */ - -u_int32_t wrapsum (sum) - u_int32_t sum; -{ -#ifdef DEBUG_CHECKSUM - log_debug ("wrapsum (%x)", sum); -#endif - - sum = ~sum & 0xFFFF; -#ifdef DEBUG_CHECKSUM_VERBOSE - log_debug ("sum = %x", sum); -#endif - -#ifdef DEBUG_CHECKSUM - log_debug ("wrapsum returns %x", htons (sum)); -#endif - return htons(sum); -} - -#ifdef PACKET_ASSEMBLY -void assemble_hw_header (interface, buf, bufix, to) - struct interface_info *interface; - unsigned char *buf; - unsigned *bufix; - struct hardware *to; -{ -#if defined (HAVE_TR_SUPPORT) - if (interface -> hw_address.hbuf [0] == HTYPE_IEEE802) - assemble_tr_header (interface, buf, bufix, to); - else -#endif -#if defined (DEC_FDDI) - if (interface -> hw_address.hbuf [0] == HTYPE_FDDI) - assemble_fddi_header (interface, buf, bufix, to); - else -#endif - assemble_ethernet_header (interface, buf, bufix, to); - -} - -/* UDP header and IP header assembled together for convenience. */ - -void assemble_udp_ip_header (interface, buf, bufix, - from, to, port, data, len) - struct interface_info *interface; - unsigned char *buf; - unsigned *bufix; - u_int32_t from; - u_int32_t to; - u_int32_t port; - unsigned char *data; - unsigned len; -{ - struct ip ip; - struct udphdr udp; - - /* Fill out the IP header */ - IP_V_SET (&ip, 4); - IP_HL_SET (&ip, 20); - ip.ip_tos = IPTOS_LOWDELAY; - ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); - ip.ip_id = 0; - ip.ip_off = 0; - ip.ip_ttl = 16; - ip.ip_p = IPPROTO_UDP; - ip.ip_sum = 0; - ip.ip_src.s_addr = from; - ip.ip_dst.s_addr = to; - - /* Checksum the IP header... */ - ip.ip_sum = wrapsum (checksum ((unsigned char *)&ip, sizeof ip, 0)); - - /* Copy the ip header into the buffer... */ - memcpy (&buf [*bufix], &ip, sizeof ip); - *bufix += sizeof ip; - - /* Fill out the UDP header */ - udp.uh_sport = local_port; /* XXX */ - udp.uh_dport = port; /* XXX */ - udp.uh_ulen = htons(sizeof(udp) + len); - memset (&udp.uh_sum, 0, sizeof udp.uh_sum); - - /* Compute UDP checksums, including the ``pseudo-header'', the UDP - header and the data. */ - - udp.uh_sum = - wrapsum (checksum ((unsigned char *)&udp, sizeof udp, - checksum (data, len, - checksum ((unsigned char *) - &ip.ip_src, - 2 * sizeof ip.ip_src, - IPPROTO_UDP + - (u_int32_t) - ntohs (udp.uh_ulen))))); - - /* Copy the udp header into the buffer... */ - memcpy (&buf [*bufix], &udp, sizeof udp); - *bufix += sizeof udp; -} -#endif /* PACKET_ASSEMBLY */ - -#ifdef PACKET_DECODING -/* Decode a hardware header... */ -/* XXX currently only supports ethernet; doesn't check for other types. */ - -ssize_t decode_hw_header (interface, buf, bufix, from) - struct interface_info *interface; - unsigned char *buf; - unsigned bufix; - struct hardware *from; -{ -#if defined (HAVE_TR_SUPPORT) - if (interface -> hw_address.hbuf [0] == HTYPE_IEEE802) - return decode_tr_header (interface, buf, bufix, from); - else -#endif -#if defined (DEC_FDDI) - if (interface -> hw_address.hbuf [0] == HTYPE_FDDI) - return decode_fddi_header (interface, buf, bufix, from); - else -#endif - return decode_ethernet_header (interface, buf, bufix, from); -} - -/* UDP header and IP header decoded together for convenience. */ - -ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, buflen) - struct interface_info *interface; - unsigned char *buf; - unsigned bufix; - struct sockaddr_in *from; - unsigned char *data; - unsigned buflen; -{ - struct ip *ip; - struct udphdr *udp; - u_int32_t ip_len = (buf [bufix] & 0xf) << 2; - u_int32_t sum, usum; - static int ip_packets_seen; - static int ip_packets_bad_checksum; - static int udp_packets_seen; - static int udp_packets_bad_checksum; - static int udp_packets_length_checked; - static int udp_packets_length_overflow; - unsigned len; - unsigned ulen; - int ignore = 0; - - ip = (struct ip *)(buf + bufix); - udp = (struct udphdr *)(buf + bufix + ip_len); - -#ifdef USERLAND_FILTER - /* Is it a UDP packet? */ - if (ip -> ip_p != IPPROTO_UDP) - return -1; - - /* Is it to the port we're serving? */ - if (udp -> uh_dport != local_port) - return -1; -#endif /* USERLAND_FILTER */ - - ulen = ntohs (udp -> uh_ulen); - if (ulen < sizeof *udp || - ((unsigned char *)udp) + ulen > buf + bufix + buflen) { - log_info ("bogus UDP packet length: %d", ulen); - return -1; - } - - /* Check the IP header checksum - it should be zero. */ - ++ip_packets_seen; - if (wrapsum (checksum (buf + bufix, ip_len, 0))) { - ++ip_packets_bad_checksum; - if (ip_packets_seen > 4 && - (ip_packets_seen / ip_packets_bad_checksum) < 2) { - log_info ("%d bad IP checksums seen in %d packets", - ip_packets_bad_checksum, ip_packets_seen); - ip_packets_seen = ip_packets_bad_checksum = 0; - } - return -1; - } - - /* Check the IP packet length. */ - if (ntohs (ip -> ip_len) != buflen) { - if ((ntohs (ip -> ip_len + 2) & ~1) == buflen) - ignore = 1; - else - log_debug ("ip length %d disagrees with bytes received %d.", - ntohs (ip -> ip_len), buflen); - } - - /* Copy out the IP source address... */ - memcpy (&from -> sin_addr, &ip -> ip_src, 4); - - /* Compute UDP checksums, including the ``pseudo-header'', the UDP - header and the data. If the UDP checksum field is zero, we're - not supposed to do a checksum. */ - - if (!data) { - data = buf + bufix + ip_len + sizeof *udp; - len = ulen - sizeof *udp; - ++udp_packets_length_checked; - if (len + data > buf + bufix + buflen) { - ++udp_packets_length_overflow; - if (udp_packets_length_checked > 4 && - (udp_packets_length_checked / - udp_packets_length_overflow) < 2) { - log_info ("%d udp packets in %d too long - dropped", - udp_packets_length_overflow, - udp_packets_length_checked); - udp_packets_length_overflow = - udp_packets_length_checked = 0; - } - return -1; - } - if (len + data < buf + bufix + buflen && - len + data != buf + bufix + buflen && !ignore) - log_debug ("accepting packet with data after udp payload."); - if (len + data > buf + bufix + buflen) { - log_debug ("dropping packet with bogus uh_ulen %ld", - (long)(len + sizeof *udp)); - return -1; - } - } - - usum = udp -> uh_sum; - udp -> uh_sum = 0; - - sum = wrapsum (checksum ((unsigned char *)udp, sizeof *udp, - checksum (data, len, - checksum ((unsigned char *) - &ip -> ip_src, - 2 * sizeof ip -> ip_src, - IPPROTO_UDP + - (u_int32_t)ulen)))); - - udp_packets_seen++; - if (usum && usum != sum) { - udp_packets_bad_checksum++; - if (udp_packets_seen > 4 && - (udp_packets_seen / udp_packets_bad_checksum) < 2) { - log_info ("%d bad udp checksums in %d packets", - udp_packets_bad_checksum, udp_packets_seen); - udp_packets_seen = udp_packets_bad_checksum = 0; - } - return -1; - } - - /* Copy out the port... */ - memcpy (&from -> sin_port, &udp -> uh_sport, sizeof udp -> uh_sport); - - return ip_len + sizeof *udp; -} -#endif /* PACKET_DECODING */ diff --git a/contrib/isc-dhcp/common/parse.c b/contrib/isc-dhcp/common/parse.c deleted file mode 100644 index 90f01c3..0000000 --- a/contrib/isc-dhcp/common/parse.c +++ /dev/null @@ -1,4844 +0,0 @@ -/* parse.c - - Common parser code for dhcpd and dhclient. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: parse.c,v 1.104.2.17 2004/06/17 20:54:38 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n" -"$FreeBSD$"; -#endif /* not lint */ - -#include "dhcpd.h" - -/* Enumerations can be specified in option formats, and are used for - parsing, so we define the routines that manage them here. */ - -struct enumeration *enumerations; - -void add_enumeration (struct enumeration *enumeration) -{ - enumeration -> next = enumerations; - enumerations = enumeration; -} - -struct enumeration *find_enumeration (const char *name, int length) -{ - struct enumeration *e; - - for (e = enumerations; e; e = e -> next) - if (strlen (e -> name) == length && - !memcmp (e -> name, name, (unsigned)length)) - return e; - return (struct enumeration *)0; -} - -struct enumeration_value *find_enumeration_value (const char *name, - int length, - const char *value) -{ - struct enumeration *e; - int i; - - e = find_enumeration (name, length); - if (e) { - for (i = 0; e -> values [i].name; i++) { - if (!strcmp (value, e -> values [i].name)) - return &e -> values [i]; - } - } - return (struct enumeration_value *)0; -} - -/* Skip to the semicolon ending the current statement. If we encounter - braces, the matching closing brace terminates the statement. If we - encounter a right brace but haven't encountered a left brace, return - leaving the brace in the token buffer for the caller. If we see a - semicolon and haven't seen a left brace, return. This lets us skip - over: - - statement; - statement foo bar { } - statement foo bar { statement { } } - statement} - - ...et cetera. */ - -void skip_to_semi (cfile) - struct parse *cfile; -{ - skip_to_rbrace (cfile, 0); -} - -void skip_to_rbrace (cfile, brace_count) - struct parse *cfile; - int brace_count; -{ - enum dhcp_token token; - const char *val; - -#if defined (DEBUG_TOKEN) - log_error ("skip_to_rbrace: %d\n", brace_count); -#endif - do { - token = peek_token (&val, (unsigned *)0, cfile); - if (token == RBRACE) { - token = next_token (&val, (unsigned *)0, cfile); - if (brace_count) { - if (!--brace_count) - return; - } else - return; - } else if (token == LBRACE) { - brace_count++; - } else if (token == SEMI && !brace_count) { - token = next_token (&val, (unsigned *)0, cfile); - return; - } else if (token == EOL) { - /* EOL only happens when parsing /etc/resolv.conf, - and we treat it like a semicolon because the - resolv.conf file is line-oriented. */ - token = next_token (&val, (unsigned *)0, cfile); - return; - } - token = next_token (&val, (unsigned *)0, cfile); - } while (token != END_OF_FILE); -} - -int parse_semi (cfile) - struct parse *cfile; -{ - enum dhcp_token token; - const char *val; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != SEMI) { - parse_warn (cfile, "semicolon expected."); - skip_to_semi (cfile); - return 0; - } - return 1; -} - -/* string-parameter :== STRING SEMI */ - -int parse_string (cfile, sptr, lptr) - struct parse *cfile; - char **sptr; - unsigned *lptr; -{ - const char *val; - enum dhcp_token token; - char *s; - unsigned len; - - token = next_token (&val, &len, cfile); - if (token != STRING) { - parse_warn (cfile, "expecting a string"); - skip_to_semi (cfile); - return 0; - } - s = (char *)dmalloc (len + 1, MDL); - if (!s) - log_fatal ("no memory for string %s.", val); - memcpy (s, val, len + 1); - - if (!parse_semi (cfile)) { - dfree (s, MDL); - return 0; - } - if (sptr) - *sptr = s; - else - dfree (s, MDL); - if (lptr) - *lptr = len; - return 1; -} - -/* - * hostname :== IDENTIFIER - * | IDENTIFIER DOT - * | hostname DOT IDENTIFIER - */ - -char *parse_host_name (cfile) - struct parse *cfile; -{ - const char *val; - enum dhcp_token token; - unsigned len = 0; - char *s; - char *t; - pair c = (pair)0; - int ltid = 0; - - /* Read a dotted hostname... */ - do { - /* Read a token, which should be an identifier. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token) && token != NUMBER) - break; - token = next_token (&val, (unsigned *)0, cfile); - - /* Store this identifier... */ - if (!(s = (char *)dmalloc (strlen (val) + 1, MDL))) - log_fatal ("can't allocate temp space for hostname."); - strcpy (s, val); - c = cons ((caddr_t)s, c); - len += strlen (s) + 1; - /* Look for a dot; if it's there, keep going, otherwise - we're done. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token == DOT) { - token = next_token (&val, (unsigned *)0, cfile); - ltid = 1; - } else - ltid = 0; - } while (token == DOT); - - /* Should be at least one token. */ - if (!len) - return (char *)0; - - /* Assemble the hostname together into a string. */ - if (!(s = (char *)dmalloc (len + ltid, MDL))) - log_fatal ("can't allocate space for hostname."); - t = s + len + ltid; - *--t = 0; - if (ltid) - *--t = '.'; - while (c) { - pair cdr = c -> cdr; - unsigned l = strlen ((char *)(c -> car)); - t -= l; - memcpy (t, (char *)(c -> car), l); - /* Free up temp space. */ - dfree (c -> car, MDL); - dfree (c, MDL); - c = cdr; - if (t != s) - *--t = '.'; - } - return s; -} - -/* ip-addr-or-hostname :== ip-address | hostname - ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER - - Parse an ip address or a hostname. If uniform is zero, put in - an expr_substring node to limit hostnames that evaluate to more - than one IP address. */ - -int parse_ip_addr_or_hostname (expr, cfile, uniform) - struct expression **expr; - struct parse *cfile; - int uniform; -{ - const char *val; - enum dhcp_token token; - unsigned char addr [4]; - unsigned len = sizeof addr; - char *name; - struct expression *x = (struct expression *)0; - - token = peek_token (&val, (unsigned *)0, cfile); - if (is_identifier (token)) { - name = parse_host_name (cfile); - if (!name) - return 0; - if (!make_host_lookup (expr, name)) { - dfree(name, MDL); - return 0; - } - dfree(name, MDL); - if (!uniform) { - if (!make_limit (&x, *expr, 4)) - return 0; - expression_dereference (expr, MDL); - *expr = x; - } - } else if (token == NUMBER) { - if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) - return 0; - return make_const_data (expr, addr, len, 0, 1, MDL); - } else { - if (token != RBRACE && token != LBRACE) - token = next_token (&val, (unsigned *)0, cfile); - parse_warn (cfile, "%s (%d): expecting IP address or hostname", - val, token); - if (token != SEMI) - skip_to_semi (cfile); - return 0; - } - - return 1; -} - -/* - * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER - */ - -int parse_ip_addr (cfile, addr) - struct parse *cfile; - struct iaddr *addr; -{ - const char *val; - enum dhcp_token token; - - addr -> len = 4; - if (parse_numeric_aggregate (cfile, addr -> iabuf, - &addr -> len, DOT, 10, 8)) - return 1; - return 0; -} - -/* - * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI - * hardware-type :== ETHERNET | TOKEN_RING | FDDI - */ - -void parse_hardware_param (cfile, hardware) - struct parse *cfile; - struct hardware *hardware; -{ - const char *val; - enum dhcp_token token; - unsigned hlen; - unsigned char *t; - - token = next_token (&val, (unsigned *)0, cfile); - switch (token) { - case ETHERNET: - hardware -> hbuf [0] = HTYPE_ETHER; - break; - case TOKEN_RING: - hardware -> hbuf [0] = HTYPE_IEEE802; - break; - case FDDI: - hardware -> hbuf [0] = HTYPE_FDDI; - break; - default: - if (!strncmp (val, "unknown-", 8)) { - hardware -> hbuf [0] = atoi (&val [8]); - } else { - parse_warn (cfile, - "expecting a network hardware type"); - skip_to_semi (cfile); - - return; - } - } - - /* Parse the hardware address information. Technically, - it would make a lot of sense to restrict the length of the - data we'll accept here to the length of a particular hardware - address type. Unfortunately, there are some broken clients - out there that put bogus data in the chaddr buffer, and we accept - that data in the lease file rather than simply failing on such - clients. Yuck. */ - hlen = 0; - token = peek_token (&val, (unsigned *)0, cfile); - if (token == SEMI) { - hardware -> hlen = 1; - goto out; - } - t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen, - COLON, 16, 8); - if (!t) { - hardware -> hlen = 1; - return; - } - if (hlen + 1 > sizeof hardware -> hbuf) { - dfree (t, MDL); - parse_warn (cfile, "hardware address too long"); - } else { - hardware -> hlen = hlen + 1; - memcpy ((unsigned char *)&hardware -> hbuf [1], t, hlen); - if (hlen + 1 < sizeof hardware -> hbuf) - memset (&hardware -> hbuf [hlen + 1], 0, - (sizeof hardware -> hbuf) - hlen - 1); - dfree (t, MDL); - } - - out: - token = next_token (&val, (unsigned *)0, cfile); - if (token != SEMI) { - parse_warn (cfile, "expecting semicolon."); - skip_to_semi (cfile); - } -} - -/* lease-time :== NUMBER SEMI */ - -void parse_lease_time (cfile, timep) - struct parse *cfile; - TIME *timep; -{ - const char *val; - enum dhcp_token token; - int32_t num; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "Expecting numeric lease time"); - skip_to_semi (cfile); - return; - } - convert_num (cfile, (unsigned char *)&num, val, 10, 32); - /* Unswap the number - convert_num returns stuff in NBO. */ - *timep = ntohl (num); - - parse_semi (cfile); -} - -/* No BNF for numeric aggregates - that's defined by the caller. What - this function does is to parse a sequence of numbers seperated by - the token specified in seperator. If max is zero, any number of - numbers will be parsed; otherwise, exactly max numbers are - expected. Base and size tell us how to internalize the numbers - once they've been tokenized. */ - -unsigned char *parse_numeric_aggregate (cfile, buf, - max, seperator, base, size) - struct parse *cfile; - unsigned char *buf; - unsigned *max; - int seperator; - int base; - unsigned size; -{ - const char *val; - enum dhcp_token token; - unsigned char *bufp = buf, *s, *t; - unsigned count = 0; - pair c = (pair)0; - - if (!bufp && *max) { - bufp = (unsigned char *)dmalloc (*max * size / 8, MDL); - if (!bufp) - log_fatal ("no space for numeric aggregate"); - s = 0; - } else - s = bufp; - - do { - if (count) { - token = peek_token (&val, (unsigned *)0, cfile); - if (token != seperator) { - if (!*max) - break; - if (token != RBRACE && token != LBRACE) - token = next_token (&val, - (unsigned *)0, - cfile); - parse_warn (cfile, "too few numbers."); - if (token != SEMI) - skip_to_semi (cfile); - return (unsigned char *)0; - } - token = next_token (&val, (unsigned *)0, cfile); - } - token = next_token (&val, (unsigned *)0, cfile); - - if (token == END_OF_FILE) { - parse_warn (cfile, "unexpected end of file"); - break; - } - - /* Allow NUMBER_OR_NAME if base is 16. */ - if (token != NUMBER && - (base != 16 || token != NUMBER_OR_NAME)) { - parse_warn (cfile, "expecting numeric value."); - skip_to_semi (cfile); - return (unsigned char *)0; - } - /* If we can, convert the number now; otherwise, build - a linked list of all the numbers. */ - if (s) { - convert_num (cfile, s, val, base, size); - s += size / 8; - } else { - t = (unsigned char *)dmalloc (strlen (val) + 1, MDL); - if (!t) - log_fatal ("no temp space for number."); - strcpy ((char *)t, val); - c = cons ((caddr_t)t, c); - } - } while (++count != *max); - - /* If we had to cons up a list, convert it now. */ - if (c) { - bufp = (unsigned char *)dmalloc (count * size / 8, MDL); - if (!bufp) - log_fatal ("no space for numeric aggregate."); - s = bufp + count - size / 8; - *max = count; - } - while (c) { - pair cdr = c -> cdr; - convert_num (cfile, s, (char *)(c -> car), base, size); - s -= size / 8; - /* Free up temp space. */ - dfree (c -> car, MDL); - dfree (c, MDL); - c = cdr; - } - return bufp; -} - -void convert_num (cfile, buf, str, base, size) - struct parse *cfile; - unsigned char *buf; - const char *str; - int base; - unsigned size; -{ - const char *ptr = str; - int negative = 0; - u_int32_t val = 0; - int tval; - int max; - - if (*ptr == '-') { - negative = 1; - ++ptr; - } - - /* If base wasn't specified, figure it out from the data. */ - if (!base) { - if (ptr [0] == '0') { - if (ptr [1] == 'x') { - base = 16; - ptr += 2; - } else if (isascii (ptr [1]) && isdigit (ptr [1])) { - base = 8; - ptr += 1; - } else { - base = 10; - } - } else { - base = 10; - } - } - - do { - tval = *ptr++; - /* XXX assumes ASCII... */ - if (tval >= 'a') - tval = tval - 'a' + 10; - else if (tval >= 'A') - tval = tval - 'A' + 10; - else if (tval >= '0') - tval -= '0'; - else { - parse_warn (cfile, "Bogus number: %s.", str); - break; - } - if (tval >= base) { - parse_warn (cfile, - "Bogus number %s: digit %d not in base %d", - str, tval, base); - break; - } - val = val * base + tval; - } while (*ptr); - - if (negative) - max = (1 << (size - 1)); - else - max = (1 << (size - 1)) + ((1 << (size - 1)) - 1); - if (val > max) { - switch (base) { - case 8: - parse_warn (cfile, - "%s%lo exceeds max (%d) for precision.", - negative ? "-" : "", - (unsigned long)val, max); - break; - case 16: - parse_warn (cfile, - "%s%lx exceeds max (%d) for precision.", - negative ? "-" : "", - (unsigned long)val, max); - break; - default: - parse_warn (cfile, - "%s%lu exceeds max (%d) for precision.", - negative ? "-" : "", - (unsigned long)val, max); - break; - } - } - - if (negative) { - switch (size) { - case 8: - *buf = -(unsigned long)val; - break; - case 16: - putShort (buf, -(long)val); - break; - case 32: - putLong (buf, -(long)val); - break; - default: - parse_warn (cfile, - "Unexpected integer size: %d\n", size); - break; - } - } else { - switch (size) { - case 8: - *buf = (u_int8_t)val; - break; - case 16: - putUShort (buf, (u_int16_t)val); - break; - case 32: - putULong (buf, val); - break; - default: - parse_warn (cfile, - "Unexpected integer size: %d\n", size); - break; - } - } -} - -/* - * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER - * NUMBER COLON NUMBER COLON NUMBER SEMI | - * NUMBER NUMBER SLASH NUMBER SLASH NUMBER - * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI | - * NEVER - * - * Dates are stored in GMT or with a timezone offset; first number is day - * of week; next is year/month/day; next is hours:minutes:seconds on a - * 24-hour clock, followed by the timezone offset in seconds, which is - * optional. - */ - -TIME parse_date (cfile) - struct parse *cfile; -{ - struct tm tm; - int guess; - int tzoff, wday, year, mon, mday, hour, min, sec; - const char *val; - enum dhcp_token token; - static int months [11] = { 31, 59, 90, 120, 151, 181, - 212, 243, 273, 304, 334 }; - - /* Day of week, or "never"... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token == NEVER) { - if (!parse_semi (cfile)) - return 0; - return MAX_TIME; - } - - if (token != NUMBER) { - parse_warn (cfile, "numeric day of week expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - wday = atoi (val); - - /* Year... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "numeric year expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - - /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until - somebody invents a time machine, I think we can safely disregard - it. This actually works around a stupid Y2K bug that was present - in a very early beta release of dhcpd. */ - year = atoi (val); - if (year > 1900) - year -= 1900; - - /* Slash seperating year from month... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != SLASH) { - parse_warn (cfile, - "expected slash seperating year from month."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - - /* Month... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "numeric month expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - mon = atoi (val) - 1; - - /* Slash seperating month from day... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != SLASH) { - parse_warn (cfile, - "expected slash seperating month from day."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - - /* Month... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "numeric day of month expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - mday = atoi (val); - - /* Hour... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "numeric hour expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - hour = atoi (val); - - /* Colon seperating hour from minute... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != COLON) { - parse_warn (cfile, - "expected colon seperating hour from minute."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - - /* Minute... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "numeric minute expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - min = atoi (val); - - /* Colon seperating minute from second... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != COLON) { - parse_warn (cfile, - "expected colon seperating hour from minute."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - - /* Minute... */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "numeric minute expected."); - if (token != SEMI) - skip_to_semi (cfile); - return (TIME)0; - } - sec = atoi (val); - - token = peek_token (&val, (unsigned *)0, cfile); - if (token == NUMBER) { - token = next_token (&val, (unsigned *)0, cfile); - tzoff = atoi (val); - } else - tzoff = 0; - - /* Make sure the date ends in a semicolon... */ - if (!parse_semi (cfile)) - return 0; - - /* Guess the time value... */ - guess = ((((((365 * (year - 70) + /* Days in years since '70 */ - (year - 69) / 4 + /* Leap days since '70 */ - (mon /* Days in months this year */ - ? months [mon - 1] - : 0) + - (mon > 1 && /* Leap day this year */ - !((year - 72) & 3)) + - mday - 1) * 24) + /* Day of month */ - hour) * 60) + - min) * 60) + sec + tzoff; - - /* This guess could be wrong because of leap seconds or other - weirdness we don't know about that the system does. For - now, we're just going to accept the guess, but at some point - it might be nice to do a successive approximation here to - get an exact value. Even if the error is small, if the - server is restarted frequently (and thus the lease database - is reread), the error could accumulate into something - significant. */ - - return guess; -} - -/* - * option-name :== IDENTIFIER | - IDENTIFIER . IDENTIFIER - */ - -struct option *parse_option_name (cfile, allocate, known) - struct parse *cfile; - int allocate; - int *known; -{ - const char *val; - enum dhcp_token token; - char *uname; - struct universe *universe; - struct option *option; - - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, - "expecting identifier after option keyword."); - if (token != SEMI) - skip_to_semi (cfile); - return (struct option *)0; - } - uname = dmalloc (strlen (val) + 1, MDL); - if (!uname) - log_fatal ("no memory for uname information."); - strcpy (uname, val); - token = peek_token (&val, (unsigned *)0, cfile); - if (token == DOT) { - /* Go ahead and take the DOT token... */ - token = next_token (&val, (unsigned *)0, cfile); - - /* The next token should be an identifier... */ - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, "expecting identifier after '.'"); - if (token != SEMI) - skip_to_semi (cfile); - return (struct option *)0; - } - - /* Look up the option name hash table for the specified - uname. */ - universe = (struct universe *)0; - if (!universe_hash_lookup (&universe, universe_hash, - uname, 0, MDL)) { - parse_warn (cfile, "no option space named %s.", uname); - skip_to_semi (cfile); - return (struct option *)0; - } - } else { - /* Use the default hash table, which contains all the - standard dhcp option names. */ - val = uname; - universe = &dhcp_universe; - } - - /* Look up the actual option info... */ - option = (struct option *)0; - option_hash_lookup (&option, universe -> hash, val, 0, MDL); - - /* If we didn't get an option structure, it's an undefined option. */ - if (option) { - if (known) - *known = 1; - } else { - /* If we've been told to allocate, that means that this - (might) be an option code definition, so we'll create - an option structure just in case. */ - if (allocate) { - option = new_option (MDL); - if (val == uname) - option -> name = val; - else { - char *s; - dfree (uname, MDL); - s = dmalloc (strlen (val) + 1, MDL); - if (!s) - log_fatal ("no memory for option %s.%s", - universe -> name, val); - strcpy (s, val); - option -> name = s; - } - option -> universe = universe; - option -> code = 0; - return option; - } - if (val == uname) - parse_warn (cfile, "no option named %s", val); - else - parse_warn (cfile, "no option named %s in space %s", - val, uname); - skip_to_semi (cfile); - return (struct option *)0; - } - - /* Free the initial identifier token. */ - dfree (uname, MDL); - return option; -} - -/* IDENTIFIER SEMI */ - -void parse_option_space_decl (cfile) - struct parse *cfile; -{ - int token; - const char *val; - struct universe **ua, *nu; - char *s; - - next_token (&val, (unsigned *)0, cfile); /* Discard the SPACE token, - which was checked by the - caller. */ - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, "expecting identifier."); - skip_to_semi (cfile); - return; - } - nu = new_universe (MDL); - if (!nu) - log_fatal ("No memory for new option space."); - - /* Set up the server option universe... */ - s = dmalloc (strlen (val) + 1, MDL); - if (!s) - log_fatal ("No memory for new option space name."); - strcpy (s, val); - nu -> name = s; - nu -> lookup_func = lookup_hashed_option; - nu -> option_state_dereference = - hashed_option_state_dereference; - nu -> foreach = hashed_option_space_foreach; - nu -> save_func = save_hashed_option; - nu -> delete_func = delete_hashed_option; - nu -> encapsulate = hashed_option_space_encapsulate; - nu -> decode = parse_option_buffer; - nu -> length_size = 1; - nu -> tag_size = 1; - nu -> store_tag = putUChar; - nu -> store_length = putUChar; - nu -> index = universe_count++; - if (nu -> index >= universe_max) { - ua = dmalloc (universe_max * 2 * sizeof *ua, MDL); - if (!ua) - log_fatal ("No memory to expand option space array."); - memcpy (ua, universes, universe_max * sizeof *ua); - universe_max *= 2; - dfree (universes, MDL); - universes = ua; - } - universes [nu -> index] = nu; - option_new_hash (&nu -> hash, 1, MDL); - if (!nu -> hash) - log_fatal ("Can't allocate %s option hash table.", nu -> name); - universe_hash_add (universe_hash, nu -> name, 0, nu, MDL); - parse_semi (cfile); -} - -/* This is faked up to look good right now. Ideally, this should do a - recursive parse and allow arbitrary data structure definitions, but for - now it just allows you to specify a single type, an array of single types, - a sequence of types, or an array of sequences of types. - - ocd :== NUMBER EQUALS ocsd SEMI - - ocsd :== ocsd_type | - ocsd_type_sequence | - ARRAY OF ocsd_simple_type_sequence - - ocsd_type_sequence :== LBRACE ocsd_types RBRACE - - ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE - - ocsd_types :== ocsd_type | - ocsd_types ocsd_type - - ocsd_type :== ocsd_simple_type | - ARRAY OF ocsd_simple_type - - ocsd_simple_types :== ocsd_simple_type | - ocsd_simple_types ocsd_simple_type - - ocsd_simple_type :== BOOLEAN | - INTEGER NUMBER | - SIGNED INTEGER NUMBER | - UNSIGNED INTEGER NUMBER | - IP-ADDRESS | - TEXT | - STRING | - ENCAPSULATE identifier */ - -int parse_option_code_definition (cfile, option) - struct parse *cfile; - struct option *option; -{ - const char *val; - enum dhcp_token token; - unsigned arrayp = 0; - int recordp = 0; - int no_more_in_record = 0; - char tokbuf [128]; - unsigned tokix = 0; - char type; - int code; - int is_signed; - char *s; - int has_encapsulation = 0; - - /* Parse the option code. */ - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "expecting option code number."); - skip_to_semi (cfile); - return 0; - } - option -> code = atoi (val); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != EQUAL) { - parse_warn (cfile, "expecting \"=\""); - skip_to_semi (cfile); - return 0; - } - - /* See if this is an array. */ - token = next_token (&val, (unsigned *)0, cfile); - if (token == ARRAY) { - token = next_token (&val, (unsigned *)0, cfile); - if (token != OF) { - parse_warn (cfile, "expecting \"of\"."); - skip_to_semi (cfile); - return 0; - } - arrayp = 1; - token = next_token (&val, (unsigned *)0, cfile); - } - - if (token == LBRACE) { - recordp = 1; - token = next_token (&val, (unsigned *)0, cfile); - } - - /* At this point we're expecting a data type. */ - next_type: - if (has_encapsulation) { - parse_warn (cfile, - "encapsulate must always be the last item."); - skip_to_semi (cfile); - return 0; - } - - switch (token) { - case ARRAY: - if (arrayp) { - parse_warn (cfile, "no nested arrays."); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != OF) { - parse_warn (cfile, "expecting \"of\"."); - skip_to_semi (cfile); - return 0; - } - arrayp = recordp + 1; - token = next_token (&val, (unsigned *)0, cfile); - if ((recordp) && (token == LBRACE)) { - parse_warn (cfile, - "only uniform array inside record."); - skip_to_rbrace (cfile, recordp + 1); - skip_to_semi (cfile); - return 0; - } - goto next_type; - case BOOLEAN: - type = 'f'; - break; - case INTEGER: - is_signed = 1; - parse_integer: - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "expecting number."); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - switch (atoi (val)) { - case 8: - type = is_signed ? 'b' : 'B'; - break; - case 16: - type = is_signed ? 's' : 'S'; - break; - case 32: - type = is_signed ? 'l' : 'L'; - break; - default: - parse_warn (cfile, - "%s bit precision is not supported.", val); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - break; - case SIGNED: - is_signed = 1; - parse_signed: - token = next_token (&val, (unsigned *)0, cfile); - if (token != INTEGER) { - parse_warn (cfile, "expecting \"integer\" keyword."); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - goto parse_integer; - case UNSIGNED: - is_signed = 0; - goto parse_signed; - - case IP_ADDRESS: - type = 'I'; - break; - case DOMAIN_NAME: - type = 'd'; - goto no_arrays; - case TEXT: - type = 't'; - no_arrays: - if (arrayp) { - parse_warn (cfile, "arrays of text strings not %s", - "yet supported."); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - no_more_in_record = 1; - break; - case STRING_TOKEN: - type = 'X'; - goto no_arrays; - - case ENCAPSULATE: - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, - "expecting option space identifier"); - skip_to_semi (cfile); - return 0; - } - if (strlen (val) + tokix + 2 > sizeof (tokbuf)) - goto toobig; - tokbuf [tokix++] = 'E'; - strcpy (&tokbuf [tokix], val); - tokix += strlen (val); - type = '.'; - has_encapsulation = 1; - break; - - default: - parse_warn (cfile, "unknown data type %s", val); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - - if (tokix == sizeof tokbuf) { - toobig: - parse_warn (cfile, "too many types in record."); - skip_to_rbrace (cfile, recordp); - if (recordp) - skip_to_semi (cfile); - return 0; - } - tokbuf [tokix++] = type; - - if (recordp) { - token = next_token (&val, (unsigned *)0, cfile); - if (arrayp > recordp) { - if (tokix == sizeof tokbuf) { - parse_warn (cfile, - "too many types in record."); - skip_to_rbrace (cfile, 1); - skip_to_semi (cfile); - return 0; - } - arrayp = 0; - tokbuf[tokix++] = 'a'; - } - if (token == COMMA) { - if (no_more_in_record) { - parse_warn (cfile, - "%s must be at end of record.", - type == 't' ? "text" : "string"); - skip_to_rbrace (cfile, 1); - if (recordp) - skip_to_semi (cfile); - return 0; - } - token = next_token (&val, (unsigned *)0, cfile); - goto next_type; - } - if (token != RBRACE) { - parse_warn (cfile, "expecting right brace."); - skip_to_rbrace (cfile, 1); - if (recordp) - skip_to_semi (cfile); - return 0; - } - } - if (!parse_semi (cfile)) { - parse_warn (cfile, "semicolon expected."); - skip_to_semi (cfile); - if (recordp) - skip_to_semi (cfile); - return 0; - } - if (has_encapsulation && arrayp) { - parse_warn (cfile, - "Arrays of encapsulations don't make sense."); - return 0; - } - if (has_encapsulation && tokbuf [0] == 'E') - has_encapsulation = 0; - s = dmalloc (tokix + - (arrayp ? 1 : 0) + - (has_encapsulation ? 1 : 0) + 1, MDL); - if (!s) - log_fatal ("no memory for option format."); - if (has_encapsulation) - s [0] = 'e'; - memcpy (s + has_encapsulation, tokbuf, tokix); - tokix += has_encapsulation; - if (arrayp) - s [tokix++] = (arrayp > recordp) ? 'a' : 'A'; - s [tokix] = 0; - option -> format = s; - if (option -> universe -> options [option -> code]) { - /* XXX Free the option, but we can't do that now because they - XXX may start out static. */ - } - option -> universe -> options [option -> code] = option; - option_hash_add (option -> universe -> hash, - (const char *)option -> name, - 0, option, MDL); - return 1; -} - -/* - * base64 :== NUMBER_OR_STRING - */ - -int parse_base64 (data, cfile) - struct data_string *data; - struct parse *cfile; -{ - enum dhcp_token token; - const char *val; - int i, j, k; - unsigned acc = 0; - static unsigned char - from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */ - 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */ - 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */ - 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */ - 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */ - 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */ - 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */ - 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */ - 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */ - 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */ - 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */ - 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */ - struct string_list *bufs = (struct string_list *)0, - *last = (struct string_list *)0, - *t; - int cc = 0; - int terminated = 0; - - /* It's possible for a + or a / to cause a base64 quantity to be - tokenized into more than one token, so we have to parse them all - in before decoding. */ - do { - unsigned l; - - token = next_token (&val, &l, cfile); - t = dmalloc (l + sizeof *t, MDL); - if (!t) - log_fatal ("no memory for base64 buffer."); - memset (t, 0, (sizeof *t) - 1); - memcpy (t -> string, val, l + 1); - cc += l; - if (last) - last -> next = t; - else - bufs = t; - last = t; - token = peek_token (&val, (unsigned *)0, cfile); - } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL || - token == NUMBER || token == PLUS || token == SLASH || - token == STRING); - - data -> len = cc; - data -> len = (data -> len * 3) / 4; - if (!buffer_allocate (&data -> buffer, data -> len, MDL)) { - parse_warn (cfile, "can't allocate buffer for base64 data."); - data -> len = 0; - data -> data = (unsigned char *)0; - return 0; - } - - j = k = 0; - for (t = bufs; t; t = t -> next) { - for (i = 0; t -> string [i]; i++) { - unsigned foo = t -> string [i]; - if (terminated && foo != '=') { - parse_warn (cfile, - "stuff after base64 '=' terminator: %s.", - &t -> string [i]); - goto bad; - } - if (foo < ' ' || foo > 'z') { - bad64: - parse_warn (cfile, - "invalid base64 character %d.", - t -> string [i]); - bad: - data_string_forget (data, MDL); - goto out; - } - if (foo == '=') - terminated = 1; - else { - foo = from64 [foo - ' ']; - if (foo == 64) - goto bad64; - acc = (acc << 6) + foo; - switch (k % 4) { - case 0: - break; - case 1: - data -> buffer -> data [j++] = (acc >> 4); - acc = acc & 0x0f; - break; - - case 2: - data -> buffer -> data [j++] = (acc >> 2); - acc = acc & 0x03; - break; - case 3: - data -> buffer -> data [j++] = acc; - acc = 0; - break; - } - } - k++; - } - } - if (k % 4) { - if (acc) { - parse_warn (cfile, - "partial base64 value left over: %d.", - acc); - } - } - data -> len = j; - data -> data = data -> buffer -> data; - out: - for (t = bufs; t; t = last) { - last = t -> next; - dfree (t, MDL); - } - if (data -> len) - return 1; - else - return 0; -} - - -/* - * colon-seperated-hex-list :== NUMBER | - * NUMBER COLON colon-seperated-hex-list - */ - -int parse_cshl (data, cfile) - struct data_string *data; - struct parse *cfile; -{ - u_int8_t ibuf [128]; - unsigned ilen = 0; - unsigned tlen = 0; - struct option_tag *sl = (struct option_tag *)0; - struct option_tag *next, **last = &sl; - enum dhcp_token token; - const char *val; - unsigned char *rvp; - - do { - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER && token != NUMBER_OR_NAME) { - parse_warn (cfile, "expecting hexadecimal number."); - skip_to_semi (cfile); - for (; sl; sl = next) { - next = sl -> next; - dfree (sl, MDL); - } - return 0; - } - if (ilen == sizeof ibuf) { - next = (struct option_tag *) - dmalloc (ilen - 1 + - sizeof (struct option_tag), MDL); - if (!next) - log_fatal ("no memory for string list."); - memcpy (next -> data, ibuf, ilen); - *last = next; - last = &next -> next; - tlen += ilen; - ilen = 0; - } - convert_num (cfile, &ibuf [ilen++], val, 16, 8); - - token = peek_token (&val, (unsigned *)0, cfile); - if (token != COLON) - break; - token = next_token (&val, (unsigned *)0, cfile); - } while (1); - - if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL)) - log_fatal ("no memory to store octet data."); - data -> data = &data -> buffer -> data [0]; - data -> len = tlen + ilen; - data -> terminated = 0; - - rvp = &data -> buffer -> data [0]; - while (sl) { - next = sl -> next; - memcpy (rvp, sl -> data, sizeof ibuf); - rvp += sizeof ibuf; - dfree (sl, MDL); - sl = next; - } - - memcpy (rvp, ibuf, ilen); - return 1; -} - -/* - * executable-statements :== executable-statement executable-statements | - * executable-statement - * - * executable-statement :== - * IF if-statement | - * ADD class-name SEMI | - * BREAK SEMI | - * OPTION option-parameter SEMI | - * SUPERSEDE option-parameter SEMI | - * PREPEND option-parameter SEMI | - * APPEND option-parameter SEMI - */ - -int parse_executable_statements (statements, cfile, lose, case_context) - struct executable_statement **statements; - struct parse *cfile; - int *lose; - enum expression_context case_context; -{ - struct executable_statement **next; - - next = statements; - while (parse_executable_statement (next, cfile, lose, case_context)) - next = &((*next) -> next); - if (!*lose) - return 1; - return 0; -} - -int parse_executable_statement (result, cfile, lose, case_context) - struct executable_statement **result; - struct parse *cfile; - int *lose; - enum expression_context case_context; -{ - enum dhcp_token token; - const char *val; - struct executable_statement base; - struct class *cta; - struct option *option; - struct option_cache *cache; - int known; - int flag; - int i; - struct dns_zone *zone; - isc_result_t status; - char *s; - - token = peek_token (&val, (unsigned *)0, cfile); - switch (token) { - case IF: - next_token (&val, (unsigned *)0, cfile); - return parse_if_statement (result, cfile, lose); - - case TOKEN_ADD: - token = next_token (&val, (unsigned *)0, cfile); - token = next_token (&val, (unsigned *)0, cfile); - if (token != STRING) { - parse_warn (cfile, "expecting class name."); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - cta = (struct class *)0; - status = find_class (&cta, val, MDL); - if (status != ISC_R_SUCCESS) { - parse_warn (cfile, "class %s: %s", - val, isc_result_totext (status)); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - if (!parse_semi (cfile)) { - *lose = 1; - return 0; - } - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for new statement."); - (*result) -> op = add_statement; - (*result) -> data.add = cta; - break; - - case BREAK: - token = next_token (&val, (unsigned *)0, cfile); - if (!parse_semi (cfile)) { - *lose = 1; - return 0; - } - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for new statement."); - (*result) -> op = break_statement; - break; - - case SEND: - token = next_token (&val, (unsigned *)0, cfile); - known = 0; - option = parse_option_name (cfile, 0, &known); - if (!option) { - *lose = 1; - return 0; - } - return parse_option_statement (result, cfile, 1, option, - send_option_statement); - - case SUPERSEDE: - case OPTION: - token = next_token (&val, (unsigned *)0, cfile); - known = 0; - option = parse_option_name (cfile, 0, &known); - if (!option) { - *lose = 1; - return 0; - } - return parse_option_statement (result, cfile, 1, option, - supersede_option_statement); - - case ALLOW: - flag = 1; - goto pad; - case DENY: - flag = 0; - goto pad; - case IGNORE: - flag = 2; - pad: - token = next_token (&val, (unsigned *)0, cfile); - cache = (struct option_cache *)0; - if (!parse_allow_deny (&cache, cfile, flag)) - return 0; - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for new statement."); - (*result) -> op = supersede_option_statement; - (*result) -> data.option = cache; - break; - - case DEFAULT: - token = next_token (&val, (unsigned *)0, cfile); - token = peek_token (&val, (unsigned *)0, cfile); - if (token == COLON) - goto switch_default; - known = 0; - option = parse_option_name (cfile, 0, &known); - if (!option) { - *lose = 1; - return 0; - } - return parse_option_statement (result, cfile, 1, option, - default_option_statement); - - case PREPEND: - token = next_token (&val, (unsigned *)0, cfile); - known = 0; - option = parse_option_name (cfile, 0, &known); - if (!option) { - *lose = 1; - return 0; - } - return parse_option_statement (result, cfile, 1, option, - prepend_option_statement); - - case APPEND: - token = next_token (&val, (unsigned *)0, cfile); - known = 0; - option = parse_option_name (cfile, 0, &known); - if (!option) { - *lose = 1; - return 0; - } - return parse_option_statement (result, cfile, 1, option, - append_option_statement); - - case ON: - token = next_token (&val, (unsigned *)0, cfile); - return parse_on_statement (result, cfile, lose); - - case SWITCH: - token = next_token (&val, (unsigned *)0, cfile); - return parse_switch_statement (result, cfile, lose); - - case CASE: - token = next_token (&val, (unsigned *)0, cfile); - if (case_context == context_any) { - parse_warn (cfile, - "case statement in inappropriate scope."); - *lose = 1; - skip_to_semi (cfile); - return 0; - } - return parse_case_statement (result, - cfile, lose, case_context); - - switch_default: - token = next_token (&val, (unsigned *)0, cfile); - if (case_context == context_any) { - parse_warn (cfile, "switch default statement in %s", - "inappropriate scope."); - - *lose = 1; - return 0; - } else { - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for default statement."); - (*result) -> op = default_statement; - return 1; - } - - case DEFINE: - case TOKEN_SET: - token = next_token (&val, (unsigned *)0, cfile); - if (token == DEFINE) - flag = 1; - else - flag = 0; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != NAME && token != NUMBER_OR_NAME) { - parse_warn (cfile, - "%s can't be a variable name", val); - badset: - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for set statement."); - (*result) -> op = flag ? define_statement : set_statement; - (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL); - if (!(*result)->data.set.name) - log_fatal ("can't allocate variable name"); - strcpy ((*result) -> data.set.name, val); - token = next_token (&val, (unsigned *)0, cfile); - - if (token == LPAREN) { - struct string_list *head, *cur, *new; - struct expression *expr; - head = cur = (struct string_list *)0; - do { - token = next_token (&val, - (unsigned *)0, cfile); - if (token == RPAREN) - break; - if (token != NAME && token != NUMBER_OR_NAME) { - parse_warn (cfile, - "expecting argument name"); - skip_to_rbrace (cfile, 0); - *lose = 1; - executable_statement_dereference - (result, MDL); - return 0; - } - new = ((struct string_list *) - dmalloc (sizeof (struct string_list) + - strlen (val), MDL)); - if (!new) - log_fatal ("can't allocate string."); - memset (new, 0, sizeof *new); - strcpy (new -> string, val); - if (cur) { - cur -> next = new; - cur = new; - } else { - head = cur = new; - } - token = next_token (&val, - (unsigned *)0, cfile); - } while (token == COMMA); - - if (token != RPAREN) { - parse_warn (cfile, "expecting right paren."); - badx: - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LBRACE) { - parse_warn (cfile, "expecting left brace."); - goto badx; - } - - expr = (struct expression *)0; - if (!(expression_allocate (&expr, MDL))) - log_fatal ("can't allocate expression."); - expr -> op = expr_function; - if (!fundef_allocate (&expr -> data.func, MDL)) - log_fatal ("can't allocate fundef."); - expr -> data.func -> args = head; - (*result) -> data.set.expr = expr; - - if (!(parse_executable_statements - (&expr -> data.func -> statements, cfile, lose, - case_context))) { - if (*lose) - goto badx; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RBRACE) { - parse_warn (cfile, "expecting rigt brace."); - goto badx; - } - } else { - if (token != EQUAL) { - parse_warn (cfile, - "expecting '=' in %s statement.", - flag ? "define" : "set"); - goto badset; - } - - if (!parse_expression (&(*result) -> data.set.expr, - cfile, lose, context_any, - (struct expression **)0, - expr_none)) { - if (!*lose) - parse_warn (cfile, - "expecting expression."); - else - *lose = 1; - skip_to_semi (cfile); - executable_statement_dereference (result, MDL); - return 0; - } - if (!parse_semi (cfile)) { - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - } - break; - - case UNSET: - token = next_token (&val, (unsigned *)0, cfile); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != NAME && token != NUMBER_OR_NAME) { - parse_warn (cfile, - "%s can't be a variable name", val); - badunset: - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for set statement."); - (*result) -> op = unset_statement; - (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL); - if (!(*result)->data.unset) - log_fatal ("can't allocate variable name"); - strcpy ((*result) -> data.unset, val); - if (!parse_semi (cfile)) { - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - break; - - case EVAL: - token = next_token (&val, (unsigned *)0, cfile); - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for eval statement."); - (*result) -> op = eval_statement; - - if (!parse_expression (&(*result) -> data.eval, - cfile, lose, context_data, /* XXX */ - (struct expression **)0, expr_none)) { - if (!*lose) - parse_warn (cfile, - "expecting data expression."); - else - *lose = 1; - skip_to_semi (cfile); - executable_statement_dereference (result, MDL); - return 0; - } - if (!parse_semi (cfile)) { - *lose = 1; - executable_statement_dereference (result, MDL); - } - break; - - case RETURN: - token = next_token (&val, (unsigned *)0, cfile); - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for return statement."); - (*result) -> op = return_statement; - - if (!parse_expression (&(*result) -> data.retval, - cfile, lose, context_data, - (struct expression **)0, expr_none)) { - if (!*lose) - parse_warn (cfile, - "expecting data expression."); - else - *lose = 1; - skip_to_semi (cfile); - executable_statement_dereference (result, MDL); - return 0; - } - if (!parse_semi (cfile)) { - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - break; - - case LOG: - token = next_token (&val, (unsigned *)0, cfile); - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for log statement."); - (*result) -> op = log_statement; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) { - parse_warn (cfile, "left parenthesis expected."); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - token = peek_token (&val, (unsigned *)0, cfile); - i = 1; - if (token == FATAL) { - (*result) -> data.log.priority = log_priority_fatal; - } else if (token == ERROR) { - (*result) -> data.log.priority = log_priority_error; - } else if (token == TOKEN_DEBUG) { - (*result) -> data.log.priority = log_priority_debug; - } else if (token == INFO) { - (*result) -> data.log.priority = log_priority_info; - } else { - (*result) -> data.log.priority = log_priority_debug; - i = 0; - } - if (i) { - token = next_token (&val, (unsigned *)0, cfile); - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) { - parse_warn (cfile, "comma expected."); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - } - - if (!(parse_data_expression - (&(*result) -> data.log.expr, cfile, lose))) { - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - parse_warn (cfile, "right parenthesis expected."); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != SEMI) { - parse_warn (cfile, "semicolon expected."); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - break; - - /* Not really a statement, but we parse it here anyway - because it's appropriate for all DHCP agents with - parsers. */ - case ZONE: - token = next_token (&val, (unsigned *)0, cfile); - zone = (struct dns_zone *)0; - if (!dns_zone_allocate (&zone, MDL)) - log_fatal ("no memory for new zone."); - zone -> name = parse_host_name (cfile); - if (!zone -> name) { - parse_warn (cfile, "expecting hostname."); - badzone: - *lose = 1; - skip_to_semi (cfile); - dns_zone_dereference (&zone, MDL); - return 0; - } - i = strlen (zone -> name); - if (zone -> name [i - 1] != '.') { - s = dmalloc ((unsigned)i + 2, MDL); - if (!s) { - parse_warn (cfile, "no trailing '.' on zone"); - goto badzone; - } - strcpy (s, zone -> name); - s [i] = '.'; - s [i + 1] = 0; - dfree (zone -> name, MDL); - zone -> name = s; - } - if (!parse_zone (zone, cfile)) - goto badzone; - status = enter_dns_zone (zone); - if (status != ISC_R_SUCCESS) { - parse_warn (cfile, "dns zone key %s: %s", - zone -> name, isc_result_totext (status)); - dns_zone_dereference (&zone, MDL); - return 0; - } - dns_zone_dereference (&zone, MDL); - return 1; - - /* Also not really a statement, but same idea as above. */ - case KEY: - token = next_token (&val, (unsigned *)0, cfile); - if (!parse_key (cfile)) { - *lose = 1; - return 0; - } - return 1; - - default: - if (config_universe && is_identifier (token)) { - option = (struct option *)0; - option_hash_lookup (&option, config_universe -> hash, - val, 0, MDL); - if (option) { - token = next_token (&val, - (unsigned *)0, cfile); - return parse_option_statement - (result, cfile, 1, option, - supersede_option_statement); - } - } - - if (token == NUMBER_OR_NAME || token == NAME) { - /* This is rather ugly. Since function calls are - data expressions, fake up an eval statement. */ - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for eval statement."); - (*result) -> op = eval_statement; - - if (!parse_expression (&(*result) -> data.eval, - cfile, lose, context_data, - (struct expression **)0, - expr_none)) { - if (!*lose) - parse_warn (cfile, "expecting " - "function call."); - else - *lose = 1; - skip_to_semi (cfile); - executable_statement_dereference (result, MDL); - return 0; - } - if (!parse_semi (cfile)) { - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - break; - } - - *lose = 0; - return 0; - } - - return 1; -} - -/* zone-statements :== zone-statement | - zone-statement zone-statements - zone-statement :== - PRIMARY ip-addresses SEMI | - SECONDARY ip-addresses SEMI | - key-reference SEMI - ip-addresses :== ip-addr-or-hostname | - ip-addr-or-hostname COMMA ip-addresses - key-reference :== KEY STRING | - KEY identifier */ - -int parse_zone (struct dns_zone *zone, struct parse *cfile) -{ - int token; - const char *val; - char *key_name; - struct option_cache *oc; - int done = 0; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LBRACE) { - parse_warn (cfile, "expecting left brace"); - return 0; - } - - do { - token = peek_token (&val, (unsigned *)0, cfile); - switch (token) { - case PRIMARY: - if (zone -> primary) { - parse_warn (cfile, - "more than one primary."); - skip_to_semi (cfile); - return 0; - } - if (!option_cache_allocate (&zone -> primary, MDL)) - log_fatal ("can't allocate primary option cache."); - oc = zone -> primary; - goto consemup; - - case SECONDARY: - if (zone -> secondary) { - parse_warn (cfile, "more than one secondary."); - skip_to_semi (cfile); - return 0; - } - if (!option_cache_allocate (&zone -> secondary, MDL)) - log_fatal ("can't allocate secondary."); - oc = zone -> secondary; - consemup: - token = next_token (&val, (unsigned *)0, cfile); - do { - struct expression *expr = (struct expression *)0; - if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) { - parse_warn (cfile, - "expecting IP addr or hostname."); - skip_to_semi (cfile); - return 0; - } - if (oc -> expression) { - struct expression *old = - (struct expression *)0; - expression_reference (&old, - oc -> expression, - MDL); - expression_dereference (&oc -> expression, - MDL); - if (!make_concat (&oc -> expression, - old, expr)) - log_fatal ("no memory for concat."); - expression_dereference (&expr, MDL); - expression_dereference (&old, MDL); - } else { - expression_reference (&oc -> expression, - expr, MDL); - expression_dereference (&expr, MDL); - } - token = next_token (&val, (unsigned *)0, cfile); - } while (token == COMMA); - if (token != SEMI) { - parse_warn (cfile, "expecting semicolon."); - skip_to_semi (cfile); - return 0; - } - break; - - case KEY: - token = next_token (&val, (unsigned *)0, cfile); - token = peek_token (&val, (unsigned *)0, cfile); - if (token == STRING) { - token = next_token (&val, (unsigned *)0, cfile); - key_name = (char *)0; - } else { - key_name = parse_host_name (cfile); - if (!key_name) { - parse_warn (cfile, "expecting key name."); - skip_to_semi (cfile); - return 0; - } - val = key_name; - } - if (omapi_auth_key_lookup_name (&zone -> key, val) != - ISC_R_SUCCESS) - parse_warn (cfile, "unknown key %s", val); - if (key_name) - dfree (key_name, MDL); - if (!parse_semi (cfile)) - return 0; - break; - - default: - done = 1; - break; - } - } while (!done); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RBRACE) { - parse_warn (cfile, "expecting right brace."); - return 0; - } - return 1; -} - -/* key-statements :== key-statement | - key-statement key-statements - key-statement :== - ALGORITHM host-name SEMI | - secret-definition SEMI - secret-definition :== SECRET base64val | - SECRET STRING */ - -int parse_key (struct parse *cfile) -{ - int token; - const char *val; - int done = 0; - struct auth_key *key; - struct data_string ds; - isc_result_t status; - char *s; - - key = (struct auth_key *)0; - if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS) - log_fatal ("no memory for key"); - - token = peek_token (&val, (unsigned *)0, cfile); - if (token == STRING) { - token = next_token (&val, (unsigned *)0, cfile); - key -> name = dmalloc (strlen (val) + 1, MDL); - if (!key -> name) - log_fatal ("no memory for key name."); - strcpy (key -> name, val); - - } else { - key -> name = parse_host_name (cfile); - if (!key -> name) { - parse_warn (cfile, "expecting key name."); - skip_to_semi (cfile); - goto bad; - } - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LBRACE) { - parse_warn (cfile, "expecting left brace"); - goto bad; - } - - do { - token = next_token (&val, (unsigned *)0, cfile); - switch (token) { - case ALGORITHM: - if (key -> algorithm) { - parse_warn (cfile, - "key %s: too many algorithms", - key -> name); - goto rbad; - } - key -> algorithm = parse_host_name (cfile); - if (!key -> algorithm) { - parse_warn (cfile, - "expecting key algorithm name."); - goto rbad; - } - if (!parse_semi (cfile)) - goto rbad; - /* If the algorithm name isn't an FQDN, tack on - the .SIG-ALG.REG.NET. domain. */ - s = strrchr (key -> algorithm, '.'); - if (!s) { - static char add [] = ".SIG-ALG.REG.INT."; - s = dmalloc (strlen (key -> algorithm) + - sizeof (add), MDL); - if (!s) { - log_error ("no memory for key %s.", - "algorithm"); - goto rbad; - } - strcpy (s, key -> algorithm); - strcat (s, add); - dfree (key -> algorithm, MDL); - key -> algorithm = s; - } else if (s [1]) { - /* If there is no trailing '.', hack one in. */ - s = dmalloc (strlen (key -> algorithm) + 2, MDL); - if (!s) { - log_error ("no memory for key %s.", - key -> algorithm); - goto rbad; - } - strcpy (s, key -> algorithm); - strcat (s, "."); - dfree (key -> algorithm, MDL); - key -> algorithm = s; - } - break; - - case SECRET: - if (key -> key) { - parse_warn (cfile, "key %s: too many secrets", - key -> name); - goto rbad; - } - - memset (&ds, 0, sizeof(ds)); - if (!parse_base64 (&ds, cfile)) - goto rbad; - status = omapi_data_string_new (&key -> key, ds.len, - MDL); - if (status != ISC_R_SUCCESS) - goto rbad; - memcpy (key -> key -> value, - ds.buffer -> data, ds.len); - data_string_forget (&ds, MDL); - - if (!parse_semi (cfile)) - goto rbad; - break; - - default: - done = 1; - break; - } - } while (!done); - if (token != RBRACE) { - parse_warn (cfile, "expecting right brace."); - goto rbad; - } - /* Allow the BIND 8 syntax, which has a semicolon after each - closing brace. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token == SEMI) - token = next_token (&val, (unsigned *)0, cfile); - - /* Remember the key. */ - status = omapi_auth_key_enter (key); - if (status != ISC_R_SUCCESS) { - parse_warn (cfile, "tsig key %s: %s", - key -> name, isc_result_totext (status)); - goto bad; - } - omapi_auth_key_dereference (&key, MDL); - return 1; - - rbad: - skip_to_rbrace (cfile, 1); - bad: - omapi_auth_key_dereference (&key, MDL); - return 0; -} - -/* - * on-statement :== event-types LBRACE executable-statements RBRACE - * event-types :== event-type OR event-types | - * event-type - * event-type :== EXPIRY | COMMIT | RELEASE - */ - -int parse_on_statement (result, cfile, lose) - struct executable_statement **result; - struct parse *cfile; - int *lose; -{ - enum dhcp_token token; - const char *val; - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for new statement."); - (*result) -> op = on_statement; - - do { - token = next_token (&val, (unsigned *)0, cfile); - switch (token) { - case EXPIRY: - (*result) -> data.on.evtypes |= ON_EXPIRY; - break; - - case COMMIT: - (*result) -> data.on.evtypes |= ON_COMMIT; - break; - - case RELEASE: - (*result) -> data.on.evtypes |= ON_RELEASE; - break; - - case TRANSMISSION: - (*result) -> data.on.evtypes |= ON_TRANSMISSION; - break; - - default: - parse_warn (cfile, "expecting a lease event type"); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - token = next_token (&val, (unsigned *)0, cfile); - } while (token == OR); - - /* Semicolon means no statements. */ - if (token == SEMI) - return 1; - - if (token != LBRACE) { - parse_warn (cfile, "left brace expected."); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - if (!parse_executable_statements (&(*result) -> data.on.statements, - cfile, lose, context_any)) { - if (*lose) { - /* Try to even things up. */ - do { - token = next_token (&val, - (unsigned *)0, cfile); - } while (token != END_OF_FILE && token != RBRACE); - executable_statement_dereference (result, MDL); - return 0; - } - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != RBRACE) { - parse_warn (cfile, "right brace expected."); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - return 1; -} - -/* - * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE - * - */ - -int parse_switch_statement (result, cfile, lose) - struct executable_statement **result; - struct parse *cfile; - int *lose; -{ - enum dhcp_token token; - const char *val; - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for new statement."); - (*result) -> op = switch_statement; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) { - parse_warn (cfile, "expecting left brace."); - pfui: - *lose = 1; - skip_to_semi (cfile); - gnorf: - executable_statement_dereference (result, MDL); - return 0; - } - - if (!parse_expression (&(*result) -> data.s_switch.expr, - cfile, lose, context_data_or_numeric, - (struct expression **)0, expr_none)) { - if (!*lose) { - parse_warn (cfile, - "expecting data or numeric expression."); - goto pfui; - } - goto gnorf; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - parse_warn (cfile, "right paren expected."); - goto pfui; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LBRACE) { - parse_warn (cfile, "left brace expected."); - goto pfui; - } - if (!(parse_executable_statements - (&(*result) -> data.s_switch.statements, cfile, lose, - (is_data_expression ((*result) -> data.s_switch.expr) - ? context_data : context_numeric)))) { - if (*lose) { - skip_to_rbrace (cfile, 1); - executable_statement_dereference (result, MDL); - return 0; - } - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != RBRACE) { - parse_warn (cfile, "right brace expected."); - goto pfui; - } - return 1; -} - -/* - * case-statement :== CASE expr COLON - * - */ - -int parse_case_statement (result, cfile, lose, case_context) - struct executable_statement **result; - struct parse *cfile; - int *lose; - enum expression_context case_context; -{ - enum dhcp_token token; - const char *val; - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for new statement."); - (*result) -> op = case_statement; - - if (!parse_expression (&(*result) -> data.c_case, - cfile, lose, case_context, - (struct expression **)0, expr_none)) - { - if (!*lose) { - parse_warn (cfile, "expecting %s expression.", - (case_context == context_data - ? "data" : "numeric")); - } - pfui: - *lose = 1; - skip_to_semi (cfile); - executable_statement_dereference (result, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COLON) { - parse_warn (cfile, "colon expected."); - goto pfui; - } - return 1; -} - -/* - * if-statement :== boolean-expression LBRACE executable-statements RBRACE - * else-statement - * - * else-statement :== <null> | - * ELSE LBRACE executable-statements RBRACE | - * ELSE IF if-statement | - * ELSIF if-statement - */ - -int parse_if_statement (result, cfile, lose) - struct executable_statement **result; - struct parse *cfile; - int *lose; -{ - enum dhcp_token token; - const char *val; - int parenp; - - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for if statement."); - - (*result) -> op = if_statement; - - token = peek_token (&val, (unsigned *)0, cfile); - if (token == LPAREN) { - parenp = 1; - next_token (&val, (unsigned *)0, cfile); - } else - parenp = 0; - - - if (!parse_boolean_expression (&(*result) -> data.ie.expr, - cfile, lose)) { - if (!*lose) - parse_warn (cfile, "boolean expression expected."); - executable_statement_dereference (result, MDL); - *lose = 1; - return 0; - } -#if defined (DEBUG_EXPRESSION_PARSE) - print_expression ("if condition", (*result) -> data.ie.expr); -#endif - if (parenp) { - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - parse_warn (cfile, "expecting right paren."); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != LBRACE) { - parse_warn (cfile, "left brace expected."); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - if (!parse_executable_statements (&(*result) -> data.ie.tc, - cfile, lose, context_any)) { - if (*lose) { - /* Try to even things up. */ - do { - token = next_token (&val, - (unsigned *)0, cfile); - } while (token != END_OF_FILE && token != RBRACE); - executable_statement_dereference (result, MDL); - return 0; - } - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != RBRACE) { - parse_warn (cfile, "right brace expected."); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - token = peek_token (&val, (unsigned *)0, cfile); - if (token == ELSE) { - token = next_token (&val, (unsigned *)0, cfile); - token = peek_token (&val, (unsigned *)0, cfile); - if (token == IF) { - token = next_token (&val, (unsigned *)0, cfile); - if (!parse_if_statement (&(*result) -> data.ie.fc, - cfile, lose)) { - if (!*lose) - parse_warn (cfile, - "expecting if statement"); - executable_statement_dereference (result, MDL); - *lose = 1; - return 0; - } - } else if (token != LBRACE) { - parse_warn (cfile, "left brace or if expected."); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } else { - token = next_token (&val, (unsigned *)0, cfile); - if (!(parse_executable_statements - (&(*result) -> data.ie.fc, - cfile, lose, context_any))) { - executable_statement_dereference (result, MDL); - return 0; - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != RBRACE) { - parse_warn (cfile, "right brace expected."); - skip_to_semi (cfile); - *lose = 1; - executable_statement_dereference (result, MDL); - return 0; - } - } - } else if (token == ELSIF) { - token = next_token (&val, (unsigned *)0, cfile); - if (!parse_if_statement (&(*result) -> data.ie.fc, - cfile, lose)) { - if (!*lose) - parse_warn (cfile, - "expecting conditional."); - executable_statement_dereference (result, MDL); - *lose = 1; - return 0; - } - } else - (*result) -> data.ie.fc = (struct executable_statement *)0; - - return 1; -} - -/* - * boolean_expression :== CHECK STRING | - * NOT boolean-expression | - * data-expression EQUAL data-expression | - * data-expression BANG EQUAL data-expression | - * boolean-expression AND boolean-expression | - * boolean-expression OR boolean-expression - * EXISTS OPTION-NAME - */ - -int parse_boolean_expression (expr, cfile, lose) - struct expression **expr; - struct parse *cfile; - int *lose; -{ - /* Parse an expression... */ - if (!parse_expression (expr, cfile, lose, context_boolean, - (struct expression **)0, expr_none)) - return 0; - - if (!is_boolean_expression (*expr) && - (*expr) -> op != expr_variable_reference && - (*expr) -> op != expr_funcall) { - parse_warn (cfile, "Expecting a boolean expression."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - return 1; -} - -/* - * data_expression :== SUBSTRING LPAREN data-expression COMMA - * numeric-expression COMMA - * numeric-expression RPAREN | - * CONCAT LPAREN data-expression COMMA - data-expression RPAREN - * SUFFIX LPAREN data_expression COMMA - * numeric-expression RPAREN | - * OPTION option_name | - * HARDWARE | - * PACKET LPAREN numeric-expression COMMA - * numeric-expression RPAREN | - * STRING | - * colon_seperated_hex_list - */ - -int parse_data_expression (expr, cfile, lose) - struct expression **expr; - struct parse *cfile; - int *lose; -{ - /* Parse an expression... */ - if (!parse_expression (expr, cfile, lose, context_data, - (struct expression **)0, expr_none)) - return 0; - - if (!is_data_expression (*expr) && - (*expr) -> op != expr_variable_reference && - (*expr) -> op != expr_funcall) { - parse_warn (cfile, "Expecting a data expression."); - *lose = 1; - return 0; - } - return 1; -} - -/* - * numeric-expression :== EXTRACT_INT LPAREN data-expression - * COMMA number RPAREN | - * NUMBER - */ - -int parse_numeric_expression (expr, cfile, lose) - struct expression **expr; - struct parse *cfile; - int *lose; -{ - /* Parse an expression... */ - if (!parse_expression (expr, cfile, lose, context_numeric, - (struct expression **)0, expr_none)) - return 0; - - if (!is_numeric_expression (*expr) && - (*expr) -> op != expr_variable_reference && - (*expr) -> op != expr_funcall) { - parse_warn (cfile, "Expecting a numeric expression."); - *lose = 1; - return 0; - } - return 1; -} - -/* - * dns-expression :== - * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA - * data-expression COMMA numeric-expression RPAREN - * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA - * data-expression RPAREN - * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA - * data-expression RPAREN - * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA - * data-expression RPAREN - * ns-class :== IN | CHAOS | HS | NUMBER - * ns-type :== A | PTR | MX | TXT | NUMBER - */ - -int parse_dns_expression (expr, cfile, lose) - struct expression **expr; - struct parse *cfile; - int *lose; -{ - /* Parse an expression... */ - if (!parse_expression (expr, cfile, lose, context_dns, - (struct expression **)0, expr_none)) - return 0; - - if (!is_dns_expression (*expr) && - (*expr) -> op != expr_variable_reference && - (*expr) -> op != expr_funcall) { - parse_warn (cfile, "Expecting a dns update subexpression."); - *lose = 1; - return 0; - } - return 1; -} - -/* Parse a subexpression that does not contain a binary operator. */ - -int parse_non_binary (expr, cfile, lose, context) - struct expression **expr; - struct parse *cfile; - int *lose; - enum expression_context context; -{ - enum dhcp_token token; - const char *val; - struct collection *col; - struct option *option; - struct expression *nexp, **ep; - int known; - enum expr_op opcode; - const char *s; - char *cptr; - struct executable_statement *stmt; - int i; - unsigned long u; - isc_result_t status, code; - unsigned len; - - token = peek_token (&val, (unsigned *)0, cfile); - - /* Check for unary operators... */ - switch (token) { - case CHECK: - token = next_token (&val, (unsigned *)0, cfile); - token = next_token (&val, (unsigned *)0, cfile); - if (token != STRING) { - parse_warn (cfile, "string expected."); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - for (col = collections; col; col = col -> next) - if (!strcmp (col -> name, val)) - break; - if (!col) { - parse_warn (cfile, "unknown collection."); - *lose = 1; - return 0; - } - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_check; - (*expr) -> data.check = col; - break; - - case TOKEN_NOT: - token = next_token (&val, (unsigned *)0, cfile); - if (context == context_dns) { - token = peek_token (&val, (unsigned *)0, cfile); - goto not_exists; - } - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_not; - if (!parse_non_binary (&(*expr) -> data.not, - cfile, lose, context_boolean)) { - if (!*lose) { - parse_warn (cfile, "expression expected"); - skip_to_semi (cfile); - } - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - if (!is_boolean_expression ((*expr) -> data.not)) { - *lose = 1; - parse_warn (cfile, "boolean expression expected"); - skip_to_semi (cfile); - expression_dereference (expr, MDL); - return 0; - } - break; - - case LPAREN: - token = next_token (&val, (unsigned *)0, cfile); - if (!parse_expression (expr, cfile, lose, context, - (struct expression **)0, expr_none)) { - if (!*lose) { - parse_warn (cfile, "expression expected"); - skip_to_semi (cfile); - } - *lose = 1; - return 0; - } - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - *lose = 1; - parse_warn (cfile, "right paren expected"); - skip_to_semi (cfile); - return 0; - } - break; - - case EXISTS: - if (context == context_dns) - goto ns_exists; - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_exists; - known = 0; - (*expr) -> data.option = parse_option_name (cfile, 0, &known); - if (!(*expr) -> data.option) { - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - break; - - case STATIC: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_static; - break; - - case KNOWN: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_known; - break; - - case SUBSTRING: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_substring; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) { - nolparen: - expression_dereference (expr, MDL); - parse_warn (cfile, "left parenthesis expected."); - *lose = 1; - return 0; - } - - if (!parse_data_expression (&(*expr) -> data.substring.expr, - cfile, lose)) { - nodata: - expression_dereference (expr, MDL); - if (!*lose) { - parse_warn (cfile, - "expecting data expression."); - skip_to_semi (cfile); - *lose = 1; - } - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) { - nocomma: - expression_dereference (expr, MDL); - parse_warn (cfile, "comma expected."); - *lose = 1; - - return 0; - } - - if (!parse_numeric_expression - (&(*expr) -> data.substring.offset,cfile, lose)) { - nonum: - if (!*lose) { - parse_warn (cfile, - "expecting numeric expression."); - skip_to_semi (cfile); - *lose = 1; - } - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!parse_numeric_expression - (&(*expr) -> data.substring.len, cfile, lose)) - goto nonum; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - norparen: - parse_warn (cfile, "right parenthesis expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - break; - - case SUFFIX: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_suffix; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - if (!parse_data_expression (&(*expr) -> data.suffix.expr, - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!parse_numeric_expression (&(*expr) -> data.suffix.len, - cfile, lose)) - goto nonum; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - case CONCAT: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_concat; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - if (!parse_data_expression (&(*expr) -> data.concat [0], - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - concat_another: - if (!parse_data_expression (&(*expr) -> data.concat [1], - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - - if (token == COMMA) { - nexp = (struct expression *)0; - if (!expression_allocate (&nexp, MDL)) - log_fatal ("can't allocate at CONCAT2"); - nexp -> op = expr_concat; - expression_reference (&nexp -> data.concat [0], - *expr, MDL); - expression_dereference (expr, MDL); - expression_reference (expr, nexp, MDL); - expression_dereference (&nexp, MDL); - goto concat_another; - } - - if (token != RPAREN) - goto norparen; - break; - - case BINARY_TO_ASCII: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_binary_to_ascii; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - if (!parse_numeric_expression (&(*expr) -> data.b2a.base, - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!parse_numeric_expression (&(*expr) -> data.b2a.width, - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!parse_data_expression (&(*expr) -> data.b2a.seperator, - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!parse_data_expression (&(*expr) -> data.b2a.buffer, - cfile, lose)) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - case REVERSE: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_reverse; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - if (!(parse_numeric_expression - (&(*expr) -> data.reverse.width, cfile, lose))) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!(parse_data_expression - (&(*expr) -> data.reverse.buffer, cfile, lose))) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - case PICK: - /* pick (a, b, c) actually produces an internal representation - that looks like pick (a, pick (b, pick (c, nil))). */ - token = next_token (&val, (unsigned *)0, cfile); - if (!(expression_allocate (expr, MDL))) - log_fatal ("can't allocate expression"); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - nexp = (struct expression *)0; - expression_reference (&nexp, *expr, MDL); - do { - nexp -> op = expr_pick_first_value; - if (!(parse_data_expression - (&nexp -> data.pick_first_value.car, - cfile, lose))) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token == COMMA) { - struct expression *foo = (struct expression *)0; - if (!expression_allocate (&foo, MDL)) - log_fatal ("can't allocate expr"); - expression_reference - (&nexp -> data.pick_first_value.cdr, foo, MDL); - expression_dereference (&nexp, MDL); - expression_reference (&nexp, foo, MDL); - expression_dereference (&foo, MDL); - } - } while (token == COMMA); - expression_dereference (&nexp, MDL); - - if (token != RPAREN) - goto norparen; - break; - - /* dns-update and dns-delete are present for historical - purposes, but are deprecated in favor of ns-update - in combination with update, delete, exists and not - exists. */ - case DNS_UPDATE: - case DNS_DELETE: -#if !defined (NSUPDATE) - parse_warn (cfile, - "Please rebuild dhcpd with --with-nsupdate."); -#endif - token = next_token (&val, (unsigned *)0, cfile); - if (token == DNS_UPDATE) - opcode = expr_ns_add; - else - opcode = expr_ns_delete; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != STRING) { - parse_warn (cfile, - "parse_expression: expecting string."); - badnsupdate: - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - if (!strcasecmp (val, "a")) - u = T_A; - else if (!strcasecmp (val, "ptr")) - u = T_PTR; - else if (!strcasecmp (val, "mx")) - u = T_MX; - else if (!strcasecmp (val, "cname")) - u = T_CNAME; - else if (!strcasecmp (val, "TXT")) - u = T_TXT; - else { - parse_warn (cfile, "unexpected rrtype: %s", val); - goto badnsupdate; - } - - s = (opcode == expr_ns_add - ? "old-dns-update" - : "old-dns-delete"); - cptr = dmalloc (strlen (s) + 1, MDL); - if (!cptr) - log_fatal ("can't allocate name for %s", s); - strcpy (cptr, s); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_funcall; - (*expr) -> data.funcall.name = cptr; - - /* Fake up a function call. */ - ep = &(*expr) -> data.funcall.arglist; - if (!expression_allocate (ep, MDL)) - log_fatal ("can't allocate expression"); - (*ep) -> op = expr_arg; - if (!make_const_int (&(*ep) -> data.arg.val, u)) - log_fatal ("can't allocate rrtype value."); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - ep = &((*ep) -> data.arg.next); - if (!expression_allocate (ep, MDL)) - log_fatal ("can't allocate expression"); - (*ep) -> op = expr_arg; - if (!(parse_data_expression (&(*ep) -> data.arg.val, - cfile, lose))) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - ep = &((*ep) -> data.arg.next); - if (!expression_allocate (ep, MDL)) - log_fatal ("can't allocate expression"); - (*ep) -> op = expr_arg; - if (!(parse_data_expression (&(*ep) -> data.arg.val, - cfile, lose))) - goto nodata; - - if (opcode == expr_ns_add) { - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - ep = &((*ep) -> data.arg.next); - if (!expression_allocate (ep, MDL)) - log_fatal ("can't allocate expression"); - (*ep) -> op = expr_arg; - if (!(parse_numeric_expression (&(*ep) -> data.arg.val, - cfile, lose))) { - parse_warn (cfile, - "expecting numeric expression."); - goto badnsupdate; - } - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - case NS_UPDATE: -#if !defined (NSUPDATE) - parse_warn (cfile, - "Please rebuild dhcpd with --with-nsupdate."); -#endif - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - nexp = *expr; - do { - nexp -> op = expr_dns_transaction; - if (!(parse_dns_expression - (&nexp -> data.dns_transaction.car, - cfile, lose))) - { - if (!*lose) - parse_warn - (cfile, - "expecting dns expression."); - badnstrans: - expression_dereference (expr, MDL); - *lose = 1; - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - - if (token == COMMA) { - if (!(expression_allocate - (&nexp -> data.dns_transaction.cdr, - MDL))) - log_fatal - ("can't allocate expression"); - nexp = nexp -> data.dns_transaction.cdr; - } - } while (token == COMMA); - - if (token != RPAREN) - goto norparen; - break; - - /* NOT EXISTS is special cased above... */ - not_exists: - token = peek_token (&val, (unsigned *)0, cfile); - if (token != EXISTS) { - parse_warn (cfile, "expecting DNS prerequisite."); - *lose = 1; - return 0; - } - opcode = expr_ns_not_exists; - goto nsupdatecode; - case TOKEN_ADD: - opcode = expr_ns_add; - goto nsupdatecode; - case TOKEN_DELETE: - opcode = expr_ns_delete; - goto nsupdatecode; - ns_exists: - opcode = expr_ns_exists; - nsupdatecode: - token = next_token (&val, (unsigned *)0, cfile); - -#if !defined (NSUPDATE) - parse_warn (cfile, - "Please rebuild dhcpd with --with-nsupdate."); -#endif - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = opcode; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token) && token != NUMBER) { - parse_warn (cfile, "expecting identifier or number."); - badnsop: - expression_dereference (expr, MDL); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - if (token == NUMBER) - (*expr) -> data.ns_add.rrclass = atoi (val); - else if (!strcasecmp (val, "in")) - (*expr) -> data.ns_add.rrclass = C_IN; - else if (!strcasecmp (val, "chaos")) - (*expr) -> data.ns_add.rrclass = C_CHAOS; - else if (!strcasecmp (val, "hs")) - (*expr) -> data.ns_add.rrclass = C_HS; - else { - parse_warn (cfile, "unexpected rrclass: %s", val); - goto badnsop; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token) && token != NUMBER) { - parse_warn (cfile, "expecting identifier or number."); - goto badnsop; - } - - if (token == NUMBER) - (*expr) -> data.ns_add.rrtype = atoi (val); - else if (!strcasecmp (val, "a")) - (*expr) -> data.ns_add.rrtype = T_A; - else if (!strcasecmp (val, "ptr")) - (*expr) -> data.ns_add.rrtype = T_PTR; - else if (!strcasecmp (val, "mx")) - (*expr) -> data.ns_add.rrtype = T_MX; - else if (!strcasecmp (val, "cname")) - (*expr) -> data.ns_add.rrtype = T_CNAME; - else if (!strcasecmp (val, "TXT")) - (*expr) -> data.ns_add.rrtype = T_TXT; - else { - parse_warn (cfile, "unexpected rrtype: %s", val); - goto badnsop; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!(parse_data_expression - (&(*expr) -> data.ns_add.rrname, cfile, lose))) - goto nodata; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!(parse_data_expression - (&(*expr) -> data.ns_add.rrdata, cfile, lose))) - goto nodata; - - if (opcode == expr_ns_add) { - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!(parse_numeric_expression - (&(*expr) -> data.ns_add.ttl, cfile, - lose))) { - if (!*lose) - parse_warn (cfile, - "expecting numeric expression."); - goto badnsupdate; - } - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - case OPTION: - case CONFIG_OPTION: - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = (token == OPTION - ? expr_option - : expr_config_option); - token = next_token (&val, (unsigned *)0, cfile); - known = 0; - (*expr) -> data.option = parse_option_name (cfile, 0, &known); - if (!(*expr) -> data.option) { - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - break; - - case HARDWARE: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_hardware; - break; - - case LEASED_ADDRESS: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_leased_address; - break; - - case CLIENT_STATE: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_client_state; - break; - - case FILENAME: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_filename; - break; - - case SERVER_NAME: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_sname; - break; - - case LEASE_TIME: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_lease_time; - break; - - case TOKEN_NULL: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_null; - break; - - case HOST_DECL_NAME: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_host_decl_name; - break; - - case UPDATED_DNS_RR: - token = next_token (&val, (unsigned *)0, cfile); - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != STRING) { - parse_warn (cfile, "expecting string."); - bad_rrtype: - *lose = 1; - return 0; - } - if (!strcasecmp (val, "a")) - s = "ddns-fwd-name"; - else if (!strcasecmp (val, "ptr")) - s = "ddns-rev-name"; - else { - parse_warn (cfile, "invalid DNS rrtype: %s", val); - goto bad_rrtype; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_variable_reference; - (*expr) -> data.variable = - dmalloc (strlen (s) + 1, MDL); - if (!(*expr) -> data.variable) - log_fatal ("can't allocate variable name."); - strcpy ((*expr) -> data.variable, s); - break; - - case PACKET: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_packet; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - if (!parse_numeric_expression (&(*expr) -> data.packet.offset, - cfile, lose)) - goto nonum; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) - goto nocomma; - - if (!parse_numeric_expression (&(*expr) -> data.packet.len, - cfile, lose)) - goto nonum; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - case STRING: - token = next_token (&val, &len, cfile); - if (!make_const_data (expr, (const unsigned char *)val, - len, 1, 1, MDL)) - log_fatal ("can't make constant string expression."); - break; - - case EXTRACT_INT: - token = next_token (&val, (unsigned *)0, cfile); - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) { - parse_warn (cfile, "left parenthesis expected."); - *lose = 1; - return 0; - } - - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - - if (!parse_data_expression (&(*expr) -> data.extract_int, - cfile, lose)) { - if (!*lose) { - parse_warn (cfile, - "expecting data expression."); - skip_to_semi (cfile); - *lose = 1; - } - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) { - parse_warn (cfile, "comma expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "number expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - switch (atoi (val)) { - case 8: - (*expr) -> op = expr_extract_int8; - break; - - case 16: - (*expr) -> op = expr_extract_int16; - break; - - case 32: - (*expr) -> op = expr_extract_int32; - break; - - default: - parse_warn (cfile, - "unsupported integer size %d", atoi (val)); - *lose = 1; - skip_to_semi (cfile); - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - parse_warn (cfile, "right parenthesis expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - break; - - case ENCODE_INT: - token = next_token (&val, (unsigned *)0, cfile); - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) { - parse_warn (cfile, "left parenthesis expected."); - *lose = 1; - return 0; - } - - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - - if (!parse_numeric_expression (&(*expr) -> data.encode_int, - cfile, lose)) { - parse_warn (cfile, "expecting numeric expression."); - skip_to_semi (cfile); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != COMMA) { - parse_warn (cfile, "comma expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) { - parse_warn (cfile, "number expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - switch (atoi (val)) { - case 8: - (*expr) -> op = expr_encode_int8; - break; - - case 16: - (*expr) -> op = expr_encode_int16; - break; - - case 32: - (*expr) -> op = expr_encode_int32; - break; - - default: - parse_warn (cfile, - "unsupported integer size %d", atoi (val)); - *lose = 1; - skip_to_semi (cfile); - expression_dereference (expr, MDL); - return 0; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) { - parse_warn (cfile, "right parenthesis expected."); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - break; - - case NUMBER: - /* If we're in a numeric context, this should just be a - number, by itself. */ - if (context == context_numeric || - context == context_data_or_numeric) { - next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_const_int; - (*expr) -> data.const_int = atoi (val); - break; - } - - case NUMBER_OR_NAME: - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - - (*expr) -> op = expr_const_data; - if (!parse_cshl (&(*expr) -> data.const_data, cfile)) { - expression_dereference (expr, MDL); - return 0; - } - break; - - case NS_FORMERR: - known = FORMERR; - goto ns_const; - ns_const: - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_const_int; - (*expr) -> data.const_int = known; - break; - - case NS_NOERROR: - known = ISC_R_SUCCESS; - goto ns_const; - - case NS_NOTAUTH: - known = ISC_R_NOTAUTH; - goto ns_const; - - case NS_NOTIMP: - known = ISC_R_NOTIMPLEMENTED; - goto ns_const; - - case NS_NOTZONE: - known = ISC_R_NOTZONE; - goto ns_const; - - case NS_NXDOMAIN: - known = ISC_R_NXDOMAIN; - goto ns_const; - - case NS_NXRRSET: - known = ISC_R_NXRRSET; - goto ns_const; - - case NS_REFUSED: - known = ISC_R_REFUSED; - goto ns_const; - - case NS_SERVFAIL: - known = ISC_R_SERVFAIL; - goto ns_const; - - case NS_YXDOMAIN: - known = ISC_R_YXDOMAIN; - goto ns_const; - - case NS_YXRRSET: - known = ISC_R_YXRRSET; - goto ns_const; - - case BOOTING: - known = S_INIT; - goto ns_const; - - case REBOOT: - known = S_REBOOTING; - goto ns_const; - - case SELECT: - known = S_SELECTING; - goto ns_const; - - case REQUEST: - known = S_REQUESTING; - goto ns_const; - - case BOUND: - known = S_BOUND; - goto ns_const; - - case RENEW: - known = S_RENEWING; - goto ns_const; - - case REBIND: - known = S_REBINDING; - goto ns_const; - - case DEFINED: - token = next_token (&val, (unsigned *)0, cfile); - token = next_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) - goto nolparen; - - token = next_token (&val, (unsigned *)0, cfile); - if (token != NAME && token != NUMBER_OR_NAME) { - parse_warn (cfile, "%s can't be a variable name", val); - skip_to_semi (cfile); - *lose = 1; - return 0; - } - - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_variable_exists; - (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL); - if (!(*expr)->data.variable) - log_fatal ("can't allocate variable name"); - strcpy ((*expr) -> data.variable, val); - token = next_token (&val, (unsigned *)0, cfile); - if (token != RPAREN) - goto norparen; - break; - - /* Not a valid start to an expression... */ - default: - if (token != NAME && token != NUMBER_OR_NAME) - return 0; - - token = next_token (&val, (unsigned *)0, cfile); - - /* Save the name of the variable being referenced. */ - cptr = dmalloc (strlen (val) + 1, MDL); - if (!cptr) - log_fatal ("can't allocate variable name"); - strcpy (cptr, val); - - /* Simple variable reference, as far as we can tell. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token != LPAREN) { - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_variable_reference; - (*expr) -> data.variable = cptr; - break; - } - - token = next_token (&val, (unsigned *)0, cfile); - if (!expression_allocate (expr, MDL)) - log_fatal ("can't allocate expression"); - (*expr) -> op = expr_funcall; - (*expr) -> data.funcall.name = cptr; - - /* Now parse the argument list. */ - ep = &(*expr) -> data.funcall.arglist; - do { - if (!expression_allocate (ep, MDL)) - log_fatal ("can't allocate expression"); - (*ep) -> op = expr_arg; - if (!parse_expression (&(*ep) -> data.arg.val, - cfile, lose, context_any, - (struct expression **)0, - expr_none)) { - if (!*lose) { - parse_warn (cfile, - "expecting expression."); - *lose = 1; - } - skip_to_semi (cfile); - expression_dereference (expr, MDL); - return 0; - } - ep = &((*ep) -> data.arg.next); - token = next_token (&val, (unsigned *)0, cfile); - } while (token == COMMA); - if (token != RPAREN) { - parse_warn (cfile, "Right parenthesis expected."); - skip_to_semi (cfile); - *lose = 1; - expression_dereference (expr, MDL); - return 0; - } - break; - } - return 1; -} - -/* Parse an expression. */ - -int parse_expression (expr, cfile, lose, context, plhs, binop) - struct expression **expr; - struct parse *cfile; - int *lose; - enum expression_context context; - struct expression **plhs; - enum expr_op binop; -{ - enum dhcp_token token; - const char *val; - struct expression *rhs = (struct expression *)0, *tmp; - struct expression *lhs = (struct expression *)0; - enum expr_op next_op; - enum expression_context - lhs_context = context_any, - rhs_context = context_any; - - /* Consume the left hand side we were passed. */ - if (plhs) { - expression_reference (&lhs, *plhs, MDL); - expression_dereference (plhs, MDL); - } - - new_rhs: - if (!parse_non_binary (&rhs, cfile, lose, context)) { - /* If we already have a left-hand side, then it's not - okay for there not to be a right-hand side here, so - we need to flag it as an error. */ - if (lhs) { - if (!*lose) { - parse_warn (cfile, - "expecting right-hand side."); - *lose = 1; - skip_to_semi (cfile); - } - expression_dereference (&lhs, MDL); - } - return 0; - } - - /* At this point, rhs contains either an entire subexpression, - or at least a left-hand-side. If we do not see a binary token - as the next token, we're done with the expression. */ - - token = peek_token (&val, (unsigned *)0, cfile); - switch (token) { - case BANG: - token = next_token (&val, (unsigned *)0, cfile); - token = peek_token (&val, (unsigned *)0, cfile); - if (token != EQUAL) { - parse_warn (cfile, "! in boolean context without ="); - *lose = 1; - skip_to_semi (cfile); - if (lhs) - expression_dereference (&lhs, MDL); - return 0; - } - next_op = expr_not_equal; - context = expression_context (rhs); - break; - - case EQUAL: - next_op = expr_equal; - context = expression_context (rhs); - break; - - case AND: - next_op = expr_and; - context = expression_context (rhs); - break; - - case OR: - next_op = expr_or; - context = expression_context (rhs); - break; - - case PLUS: - next_op = expr_add; - context = expression_context (rhs); - break; - - case MINUS: - next_op = expr_subtract; - context = expression_context (rhs); - break; - - case SLASH: - next_op = expr_divide; - context = expression_context (rhs); - break; - - case ASTERISK: - next_op = expr_multiply; - context = expression_context (rhs); - break; - - case PERCENT: - next_op = expr_remainder; - context = expression_context (rhs); - break; - - case AMPERSAND: - next_op = expr_binary_and; - context = expression_context (rhs); - break; - - case PIPE: - next_op = expr_binary_or; - context = expression_context (rhs); - break; - - case CARET: - next_op = expr_binary_xor; - context = expression_context (rhs); - break; - - default: - next_op = expr_none; - } - - /* If we have no lhs yet, we just parsed it. */ - if (!lhs) { - /* If there was no operator following what we just parsed, - then we're done - return it. */ - if (next_op == expr_none) { - *expr = rhs; - return 1; - } - lhs = rhs; - rhs = (struct expression *)0; - binop = next_op; - next_token (&val, (unsigned *)0, cfile); - goto new_rhs; - } - - if (binop != expr_none) { - rhs_context = expression_context(rhs); - lhs_context = expression_context(lhs); - - if ((rhs_context != context_any) && (lhs_context != context_any) && - (rhs_context != lhs_context)) { - parse_warn (cfile, "illegal expression relating different types"); - skip_to_semi (cfile); - expression_dereference (&rhs, MDL); - expression_dereference (&lhs, MDL); - *lose = 1; - return 0; - } - - switch(binop) { - case expr_not_equal: - case expr_equal: - if ((rhs_context != context_data_or_numeric) && - (rhs_context != context_data) && - (rhs_context != context_numeric) && - (rhs_context != context_any)) { - parse_warn (cfile, "expecting data/numeric expression"); - skip_to_semi (cfile); - expression_dereference (&rhs, MDL); - *lose = 1; - return 0; - } - break; - - case expr_and: - case expr_or: - if ((rhs_context != context_boolean) && - (rhs_context != context_any)) { - parse_warn (cfile, "expecting boolean expressions"); - skip_to_semi (cfile); - expression_dereference (&rhs, MDL); - *lose = 1; - return 0; - } - break; - - case expr_add: - case expr_subtract: - case expr_divide: - case expr_multiply: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - if ((rhs_context != context_numeric) && - (rhs_context != context_any)) { - parse_warn (cfile, "expecting numeric expressions"); - skip_to_semi (cfile); - expression_dereference (&rhs, MDL); - *lose = 1; - return 0; - } - break; - - default: - break; - } - } - - /* Now, if we didn't find a binary operator, we're done parsing - this subexpression, so combine it with the preceding binary - operator and return the result. */ - if (next_op == expr_none) { - if (!expression_allocate (expr, MDL)) - log_fatal ("Can't allocate expression!"); - - (*expr) -> op = binop; - /* All the binary operators' data union members - are the same, so we'll cheat and use the member - for the equals operator. */ - (*expr) -> data.equal [0] = lhs; - (*expr) -> data.equal [1] = rhs; - return 1; - } - - /* Eat the operator token - we now know it was a binary operator... */ - token = next_token (&val, (unsigned *)0, cfile); - - /* If the binary operator we saw previously has a lower precedence - than the next operator, then the rhs we just parsed for that - operator is actually the lhs of the operator with the higher - precedence - to get the real rhs, we need to recurse on the - new operator. */ - if (binop != expr_none && - op_precedence (binop, next_op) < 0) { - tmp = rhs; - rhs = (struct expression *)0; - if (!parse_expression (&rhs, cfile, lose, op_context (next_op), - &tmp, next_op)) { - if (!*lose) { - parse_warn (cfile, - "expecting a subexpression"); - *lose = 1; - } - return 0; - } - next_op = expr_none; - } - - /* Now combine the LHS and the RHS using binop. */ - tmp = (struct expression *)0; - if (!expression_allocate (&tmp, MDL)) - log_fatal ("No memory for equal precedence combination."); - - /* Store the LHS and RHS. */ - tmp -> data.equal [0] = lhs; - tmp -> data.equal [1] = rhs; - tmp -> op = binop; - - lhs = tmp; - tmp = (struct expression *)0; - rhs = (struct expression *)0; - - /* Recursions don't return until we have parsed the end of the - expression, so if we recursed earlier, we can now return what - we got. */ - if (next_op == expr_none) { - *expr = lhs; - return 1; - } - - binop = next_op; - goto new_rhs; -} - -/* option-statement :== identifier DOT identifier <syntax> SEMI - | identifier <syntax> SEMI - - Option syntax is handled specially through format strings, so it - would be painful to come up with BNF for it. However, it always - starts as above and ends in a SEMI. */ - -int parse_option_statement (result, cfile, lookups, option, op) - struct executable_statement **result; - struct parse *cfile; - int lookups; - struct option *option; - enum statement_op op; -{ - const char *val; - enum dhcp_token token; - const char *fmt = NULL; - struct expression *expr = (struct expression *)0; - struct expression *tmp; - int lose; - struct executable_statement *stmt; - int ftt = 1; - - token = peek_token (&val, (unsigned *)0, cfile); - if (token == SEMI) { - /* Eat the semicolon... */ - token = next_token (&val, (unsigned *)0, cfile); - goto done; - } - - if (token == EQUAL) { - /* Eat the equals sign. */ - token = next_token (&val, (unsigned *)0, cfile); - - /* Parse a data expression and use its value for the data. */ - if (!parse_data_expression (&expr, cfile, &lose)) { - /* In this context, we must have an executable - statement, so if we found something else, it's - still an error. */ - if (!lose) { - parse_warn (cfile, - "expecting a data expression."); - skip_to_semi (cfile); - } - return 0; - } - - /* We got a valid expression, so use it. */ - goto done; - } - - /* Parse the option data... */ - do { - /* Set a flag if this is an array of a simple type (i.e., - not an array of pairs of IP addresses, or something - like that. */ - int uniform = option -> format [1] == 'A'; - - and_again: - /* Set fmt to start of format for 'A' and one char back - for 'a' */ - if ((fmt != NULL) && - (fmt != option -> format) && (*fmt == 'a')) - fmt -= 1; - else - fmt = ((fmt == NULL) || - (*fmt == 'A')) ? option -> format : fmt; - - /* 'a' means always uniform */ - uniform |= (fmt [1] == 'a'); - - for ( ; *fmt; fmt++) { - if ((*fmt == 'A') || (*fmt == 'a')) - break; - if (*fmt == 'o') - continue; - tmp = expr; - expr = (struct expression *)0; - if (!parse_option_token (&expr, cfile, &fmt, - tmp, uniform, lookups)) { - if (fmt [1] != 'o') { - if (tmp) - expression_dereference (&tmp, - MDL); - return 0; - } - expr = tmp; - tmp = (struct expression *)0; - } - if (tmp) - expression_dereference (&tmp, MDL); - } - if ((*fmt == 'A') || (*fmt == 'a')) { - token = peek_token (&val, (unsigned *)0, cfile); - /* Comma means: continue with next element in array */ - if (token == COMMA) { - token = next_token (&val, - (unsigned *)0, cfile); - continue; - } - /* no comma: end of array. - 'A' or end of string means: leave the loop */ - if ((*fmt == 'A') || (fmt[1] == '\0')) - break; - /* 'a' means: go on with next char */ - if (*fmt == 'a') { - fmt++; - goto and_again; - } - } - } while ((*fmt == 'A') || (*fmt == 'a')); - - done: - if (!parse_semi (cfile)) - return 0; - if (!executable_statement_allocate (result, MDL)) - log_fatal ("no memory for option statement."); - (*result) -> op = op; - if (expr && !option_cache (&(*result) -> data.option, - (struct data_string *)0, expr, option, MDL)) - log_fatal ("no memory for option cache"); - if (expr) - expression_dereference (&expr, MDL); - return 1; -} - -int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) - struct expression **rv; - struct parse *cfile; - const char **fmt; - struct expression *expr; - int uniform; - int lookups; -{ - const char *val; - enum dhcp_token token; - struct expression *t = (struct expression *)0; - unsigned char buf [4]; - unsigned len; - unsigned char *ob; - struct iaddr addr; - int num; - const char *f, *g; - struct enumeration_value *e; - - switch (**fmt) { - case 'U': - token = peek_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - if ((*fmt) [1] != 'o') { - parse_warn (cfile, "expecting identifier."); - skip_to_semi (cfile); - } - return 0; - } - token = next_token (&val, &len, cfile); - if (!make_const_data (&t, (const unsigned char *)val, - len, 1, 1, MDL)) - log_fatal ("No memory for %s", val); - break; - - case 'E': - g = strchr (*fmt, '.'); - if (!g) { - parse_warn (cfile, - "malformed encapsulation format (bug!)"); - skip_to_semi (cfile); - return 0; - } - *fmt = g; - case 'X': - token = peek_token (&val, (unsigned *)0, cfile); - if (token == NUMBER_OR_NAME || token == NUMBER) { - if (!expression_allocate (&t, MDL)) - return 0; - if (!parse_cshl (&t -> data.const_data, cfile)) { - expression_dereference (&t, MDL); - return 0; - } - t -> op = expr_const_data; - } else if (token == STRING) { - token = next_token (&val, &len, cfile); - if (!make_const_data (&t, (const unsigned char *)val, - len, 1, 1, MDL)) - log_fatal ("No memory for \"%s\"", val); - } else { - if ((*fmt) [1] != 'o') { - parse_warn (cfile, "expecting string %s.", - "or hexadecimal data"); - skip_to_semi (cfile); - } - return 0; - } - break; - - case 'd': /* Domain name... */ - val = parse_host_name (cfile); - if (!val) { - parse_warn (cfile, "not a valid domain name."); - skip_to_semi (cfile); - return 0; - } - len = strlen (val); - goto make_string; - - case 't': /* Text string... */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token != STRING && !is_identifier (token)) { - if ((*fmt) [1] != 'o') { - parse_warn (cfile, "expecting string."); - if (token != SEMI) - skip_to_semi (cfile); - } - return 0; - } - token = next_token (&val, &len, cfile); - make_string: - if (!make_const_data (&t, (const unsigned char *)val, - len, 1, 1, MDL)) - log_fatal ("No memory for concatenation"); - break; - - case 'N': - f = (*fmt) + 1; - g = strchr (*fmt, '.'); - if (!g) { - parse_warn (cfile, "malformed %s (bug!)", - "enumeration format"); - foo: - skip_to_semi (cfile); - return 0; - } - *fmt = g; - token = next_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, - "identifier expected"); - goto foo; - } - e = find_enumeration_value (f, (*fmt) - f, val); - if (!e) { - parse_warn (cfile, "unknown value"); - goto foo; - } - if (!make_const_data (&t, &e -> value, 1, 0, 1, MDL)) - return 0; - break; - - case 'I': /* IP address or hostname. */ - if (lookups) { - if (!parse_ip_addr_or_hostname (&t, cfile, uniform)) - return 0; - } else { - if (!parse_ip_addr (cfile, &addr)) - return 0; - if (!make_const_data (&t, addr.iabuf, addr.len, - 0, 1, MDL)) - return 0; - } - break; - - case 'T': /* Lease interval. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token != INFINITE) - goto check_number; - token = next_token (&val, (unsigned *)0, cfile); - putLong (buf, -1); - if (!make_const_data (&t, buf, 4, 0, 1, MDL)) - return 0; - break; - - case 'L': /* Unsigned 32-bit integer... */ - case 'l': /* Signed 32-bit integer... */ - token = peek_token (&val, (unsigned *)0, cfile); - check_number: - if (token != NUMBER) { - need_number: - if ((*fmt) [1] != 'o') { - parse_warn (cfile, "expecting number."); - if (token != SEMI) - skip_to_semi (cfile); - } - return 0; - } - token = next_token (&val, (unsigned *)0, cfile); - convert_num (cfile, buf, val, 0, 32); - if (!make_const_data (&t, buf, 4, 0, 1, MDL)) - return 0; - break; - - case 's': /* Signed 16-bit integer. */ - case 'S': /* Unsigned 16-bit integer. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) - goto need_number; - token = next_token (&val, (unsigned *)0, cfile); - convert_num (cfile, buf, val, 0, 16); - if (!make_const_data (&t, buf, 2, 0, 1, MDL)) - return 0; - break; - - case 'b': /* Signed 8-bit integer. */ - case 'B': /* Unsigned 8-bit integer. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (token != NUMBER) - goto need_number; - token = next_token (&val, (unsigned *)0, cfile); - convert_num (cfile, buf, val, 0, 8); - if (!make_const_data (&t, buf, 1, 0, 1, MDL)) - return 0; - break; - - case 'f': /* Boolean flag. */ - token = peek_token (&val, (unsigned *)0, cfile); - if (!is_identifier (token)) { - if ((*fmt) [1] != 'o') - parse_warn (cfile, "expecting identifier."); - bad_flag: - if ((*fmt) [1] != 'o') { - if (token != SEMI) - skip_to_semi (cfile); - } - return 0; - } - if (!strcasecmp (val, "true") - || !strcasecmp (val, "on")) - buf [0] = 1; - else if (!strcasecmp (val, "false") - || !strcasecmp (val, "off")) - buf [0] = 0; - else if (!strcasecmp (val, "ignore")) - buf [0] = 2; - else { - if ((*fmt) [1] != 'o') - parse_warn (cfile, "expecting boolean."); - goto bad_flag; - } - token = next_token (&val, (unsigned *)0, cfile); - if (!make_const_data (&t, buf, 1, 0, 1, MDL)) - return 0; - break; - - default: - parse_warn (cfile, "Bad format %c in parse_option_token.", - **fmt); - skip_to_semi (cfile); - return 0; - } - if (expr) { - if (!make_concat (rv, expr, t)) - return 0; - } else - expression_reference (rv, t, MDL); - expression_dereference (&t, MDL); - return 1; -} - -int parse_option_decl (oc, cfile) - struct option_cache **oc; - struct parse *cfile; -{ - const char *val; - int token; - u_int8_t buf [4]; - u_int8_t hunkbuf [1024]; - unsigned hunkix = 0; - const char *fmt, *f; - struct option *option; - struct iaddr ip_addr; - u_int8_t *dp; - unsigned len; - int nul_term = 0; - struct buffer *bp; - int known = 0; - struct enumeration_value *e; - - option = parse_option_name (cfile, 0, &known); - if (!option) - return 0; - - /* Parse the option data... */ - do { - /* Set a flag if this is an array of a simple type (i.e., - not an array of pairs of IP addresses, or something - like that. */ - int uniform = option -> format [1] == 'A'; - - for (fmt = option -> format; *fmt; fmt++) { - if (*fmt == 'A') - break; - switch (*fmt) { - case 'E': - fmt = strchr (fmt, '.'); - if (!fmt) { - parse_warn (cfile, - "malformed %s (bug!)", - "encapsulation format"); - skip_to_semi (cfile); - return 0; - } - case 'X': - len = parse_X (cfile, &hunkbuf [hunkix], - sizeof hunkbuf - hunkix); - hunkix += len; - break; - - case 't': /* Text string... */ - token = next_token (&val, - &len, cfile); - if (token != STRING) { - parse_warn (cfile, - "expecting string."); - skip_to_semi (cfile); - return 0; - } - if (hunkix + len + 1 > sizeof hunkbuf) { - parse_warn (cfile, - "option data buffer %s", - "overflow"); - skip_to_semi (cfile); - return 0; - } - memcpy (&hunkbuf [hunkix], val, len + 1); - nul_term = 1; - hunkix += len; - break; - - case 'N': - f = fmt; - fmt = strchr (fmt, '.'); - if (!fmt) { - parse_warn (cfile, - "malformed %s (bug!)", - "enumeration format"); - foo: - skip_to_semi (cfile); - return 0; - } - token = next_token (&val, - (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, - "identifier expected"); - goto foo; - } - e = find_enumeration_value (f, fmt - f, val); - if (!e) { - parse_warn (cfile, - "unknown value"); - goto foo; - } - len = 1; - dp = &e -> value; - goto alloc; - - case 'I': /* IP address. */ - if (!parse_ip_addr (cfile, &ip_addr)) - return 0; - len = ip_addr.len; - dp = ip_addr.iabuf; - - alloc: - if (hunkix + len > sizeof hunkbuf) { - parse_warn (cfile, - "option data buffer %s", - "overflow"); - skip_to_semi (cfile); - return 0; - } - memcpy (&hunkbuf [hunkix], dp, len); - hunkix += len; - break; - - case 'L': /* Unsigned 32-bit integer... */ - case 'l': /* Signed 32-bit integer... */ - token = next_token (&val, - (unsigned *)0, cfile); - if (token != NUMBER) { - need_number: - parse_warn (cfile, - "expecting number."); - if (token != SEMI) - skip_to_semi (cfile); - return 0; - } - convert_num (cfile, buf, val, 0, 32); - len = 4; - dp = buf; - goto alloc; - - case 's': /* Signed 16-bit integer. */ - case 'S': /* Unsigned 16-bit integer. */ - token = next_token (&val, - (unsigned *)0, cfile); - if (token != NUMBER) - goto need_number; - convert_num (cfile, buf, val, 0, 16); - len = 2; - dp = buf; - goto alloc; - - case 'b': /* Signed 8-bit integer. */ - case 'B': /* Unsigned 8-bit integer. */ - token = next_token (&val, - (unsigned *)0, cfile); - if (token != NUMBER) - goto need_number; - convert_num (cfile, buf, val, 0, 8); - len = 1; - dp = buf; - goto alloc; - - case 'f': /* Boolean flag. */ - token = next_token (&val, - (unsigned *)0, cfile); - if (!is_identifier (token)) { - parse_warn (cfile, - "expecting identifier."); - bad_flag: - if (token != SEMI) - skip_to_semi (cfile); - return 0; - } - if (!strcasecmp (val, "true") - || !strcasecmp (val, "on")) - buf [0] = 1; - else if (!strcasecmp (val, "false") - || !strcasecmp (val, "off")) - buf [0] = 0; - else { - parse_warn (cfile, - "expecting boolean."); - goto bad_flag; - } - len = 1; - dp = buf; - goto alloc; - - default: - log_error ("parse_option_param: Bad format %c", - *fmt); - skip_to_semi (cfile); - return 0; - } - } - token = next_token (&val, (unsigned *)0, cfile); - } while (*fmt == 'A' && token == COMMA); - - if (token != SEMI) { - parse_warn (cfile, "semicolon expected."); - skip_to_semi (cfile); - return 0; - } - - bp = (struct buffer *)0; - if (!buffer_allocate (&bp, hunkix + nul_term, MDL)) - log_fatal ("no memory to store option declaration."); - if (!bp -> data) - log_fatal ("out of memory allocating option data."); - memcpy (bp -> data, hunkbuf, hunkix + nul_term); - - if (!option_cache_allocate (oc, MDL)) - log_fatal ("out of memory allocating option cache."); - - (*oc) -> data.buffer = bp; - (*oc) -> data.data = &bp -> data [0]; - (*oc) -> data.terminated = nul_term; - (*oc) -> data.len = hunkix; - (*oc) -> option = option; - return 1; -} - -/* Consider merging parse_cshl into this. */ - -int parse_X (cfile, buf, max) - struct parse *cfile; - u_int8_t *buf; - unsigned max; -{ - int token; - const char *val; - unsigned len; - u_int8_t *s; - - token = peek_token (&val, (unsigned *)0, cfile); - if (token == NUMBER_OR_NAME || token == NUMBER) { - len = 0; - do { - token = next_token (&val, (unsigned *)0, cfile); - if (token != NUMBER && token != NUMBER_OR_NAME) { - parse_warn (cfile, - "expecting hexadecimal constant."); - skip_to_semi (cfile); - return 0; - } - convert_num (cfile, &buf [len], val, 16, 8); - if (len++ > max) { - parse_warn (cfile, - "hexadecimal constant too long."); - skip_to_semi (cfile); - return 0; - } - token = peek_token (&val, (unsigned *)0, cfile); - if (token == COLON) - token = next_token (&val, - (unsigned *)0, cfile); - } while (token == COLON); - val = (char *)buf; - } else if (token == STRING) { - token = next_token (&val, &len, cfile); - if (len + 1 > max) { - parse_warn (cfile, "string constant too long."); - skip_to_semi (cfile); - return 0; - } - memcpy (buf, val, len + 1); - } else { - parse_warn (cfile, "expecting string or hexadecimal data"); - skip_to_semi (cfile); - return 0; - } - return len; -} - -int parse_warn (struct parse *cfile, const char *fmt, ...) -{ - va_list list; - char lexbuf [256]; - char mbuf [1024]; - char fbuf [1024]; - unsigned i, lix; - - do_percentm (mbuf, fmt); - /* %Audit% This is log output. %2004.06.17,Safe% - * If we truncate we hope the user can get a hint from the log. - */ - snprintf (fbuf, sizeof fbuf, "%s line %d: %s", - cfile -> tlname, cfile -> lexline, mbuf); - - va_start (list, fmt); - vsnprintf (mbuf, sizeof mbuf, fbuf, list); - va_end (list); - - lix = 0; - for (i = 0; - cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) { - if (lix < (sizeof lexbuf) - 1) - lexbuf [lix++] = ' '; - if (cfile -> token_line [i] == '\t') { - for (lix; - lix < (sizeof lexbuf) - 1 && (lix & 7); lix++) - lexbuf [lix] = ' '; - } - } - lexbuf [lix] = 0; - -#ifndef DEBUG - syslog (log_priority | LOG_ERR, "%s", mbuf); - syslog (log_priority | LOG_ERR, "%s", cfile -> token_line); - if (cfile -> lexchar < 81) - syslog (log_priority | LOG_ERR, "%s^", lexbuf); -#endif - - if (log_perror) { - write (2, mbuf, strlen (mbuf)); - write (2, "\n", 1); - write (2, cfile -> token_line, strlen (cfile -> token_line)); - write (2, "\n", 1); - if (cfile -> lexchar < 81) - write (2, lexbuf, lix); - write (2, "^\n", 2); - } - - cfile -> warnings_occurred = 1; - - return 0; -} diff --git a/contrib/isc-dhcp/common/print.c b/contrib/isc-dhcp/common/print.c deleted file mode 100644 index dba1170..0000000 --- a/contrib/isc-dhcp/common/print.c +++ /dev/null @@ -1,1405 +0,0 @@ -/* print.c - - Turn data structures into printable text. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: print.c,v 1.53.2.11 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -char *quotify_string (const char *s, const char *file, int line) -{ - unsigned len = 0; - const char *sp; - char *buf, *nsp; - - for (sp = s; sp && *sp; sp++) { - if (*sp == ' ') - len++; - else if (!isascii (*sp) || !isprint (*sp)) - len += 4; - else if (*sp == '"' || *sp == '\\') - len += 2; - else - len++; - } - - buf = dmalloc (len + 1, file, line); - if (buf) { - nsp = buf; - for (sp = s; sp && *sp; sp++) { - if (*sp == ' ') - *nsp++ = ' '; - else if (!isascii (*sp) || !isprint (*sp)) { - sprintf (nsp, "\\%03o", - *(const unsigned char *)sp); - nsp += 4; - } else if (*sp == '"' || *sp == '\\') { - *nsp++ = '\\'; - *nsp++ = *sp; - } else - *nsp++ = *sp; - } - *nsp++ = 0; - } - return buf; -} - -char *quotify_buf (const unsigned char *s, unsigned len, - const char *file, int line) -{ - unsigned nulen = 0; - char *buf, *nsp; - int i; - - for (i = 0; i < len; i++) { - if (s [i] == ' ') - nulen++; - else if (!isascii (s [i]) || !isprint (s [i])) - nulen += 4; - else if (s [i] == '"' || s [i] == '\\') - nulen += 2; - else - nulen++; - } - - buf = dmalloc (nulen + 1, MDL); - if (buf) { - nsp = buf; - for (i = 0; i < len; i++) { - if (s [i] == ' ') - *nsp++ = ' '; - else if (!isascii (s [i]) || !isprint (s [i])) { - sprintf (nsp, "\\%03o", s [i]); - nsp += 4; - } else if (s [i] == '"' || s [i] == '\\') { - *nsp++ = '\\'; - *nsp++ = s [i]; - } else - *nsp++ = s [i]; - } - *nsp++ = 0; - } - return buf; -} - -char *print_base64 (const unsigned char *buf, unsigned len, - const char *file, int line) -{ - char *s, *b; - unsigned bl; - int i; - unsigned val, extra; - static char to64 [] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - bl = ((len * 4 + 2) / 3) + 1; - b = dmalloc (bl + 1, file, line); - if (!b) - return (char *)0; - - i = 0; - s = b; - while (i != len) { - val = buf [i++]; - extra = val & 3; - val = val >> 2; - *s++ = to64 [val]; - if (i == len) { - *s++ = to64 [extra << 4]; - *s++ = '='; - break; - } - val = (extra << 8) + buf [i++]; - extra = val & 15; - val = val >> 4; - *s++ = to64 [val]; - if (i == len) { - *s++ = to64 [extra << 2]; - *s++ = '='; - break; - } - val = (extra << 8) + buf [i++]; - extra = val & 0x3f; - val = val >> 6; - *s++ = to64 [val]; - *s++ = to64 [extra]; - } - if (!len) - *s++ = '='; - *s++ = 0; - if (s > b + bl + 1) - abort (); - return b; -} - -char *print_hw_addr (htype, hlen, data) - int htype; - int hlen; - unsigned char *data; -{ - static char habuf [49]; - char *s; - int i; - - if (hlen <= 0) - habuf [0] = 0; - else { - s = habuf; - for (i = 0; i < hlen; i++) { - sprintf (s, "%02x", data [i]); - s += strlen (s); - *s++ = ':'; - } - *--s = 0; - } - return habuf; -} - -void print_lease (lease) - struct lease *lease; -{ - struct tm *t; - char tbuf [32]; - - log_debug (" Lease %s", - piaddr (lease -> ip_addr)); - - t = gmtime (&lease -> starts); - strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); - log_debug (" start %s", tbuf); - - t = gmtime (&lease -> ends); - strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); - log_debug (" end %s", tbuf); - - if (lease -> hardware_addr.hlen) - log_debug (" hardware addr = %s", - print_hw_addr (lease -> hardware_addr.hbuf [0], - lease -> hardware_addr.hlen - 1, - &lease -> hardware_addr.hbuf [1])); - log_debug (" host %s ", - lease -> host ? lease -> host -> name : "<none>"); -} - -#if defined (DEBUG_PACKET) -void dump_packet_option (struct option_cache *oc, - struct packet *packet, - struct lease *lease, - struct client_state *client, - struct option_state *in_options, - struct option_state *cfg_options, - struct binding_scope **scope, - struct universe *u, void *foo) -{ - const char *name, *dot; - struct data_string ds; - memset (&ds, 0, sizeof ds); - - if (u != &dhcp_universe) { - name = u -> name; - dot = "."; - } else { - name = ""; - dot = ""; - } - if (evaluate_option_cache (&ds, packet, lease, client, - in_options, cfg_options, scope, oc, MDL)) { - log_debug (" option %s%s%s %s;\n", - name, dot, oc -> option -> name, - pretty_print_option (oc -> option, - ds.data, ds.len, 1, 1)); - data_string_forget (&ds, MDL); - } -} - -void dump_packet (tp) - struct packet *tp; -{ - struct dhcp_packet *tdp = tp -> raw; - - log_debug ("packet length %d", tp -> packet_length); - log_debug ("op = %d htype = %d hlen = %d hops = %d", - tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops); - log_debug ("xid = %x secs = %ld flags = %x", - tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags); - log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr)); - log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr)); - log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr)); - log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr)); - log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", - ((unsigned char *)(tdp -> chaddr)) [0], - ((unsigned char *)(tdp -> chaddr)) [1], - ((unsigned char *)(tdp -> chaddr)) [2], - ((unsigned char *)(tdp -> chaddr)) [3], - ((unsigned char *)(tdp -> chaddr)) [4], - ((unsigned char *)(tdp -> chaddr)) [5]); - log_debug ("filename = %s", tdp -> file); - log_debug ("server_name = %s", tdp -> sname); - if (tp -> options_valid) { - int i; - - for (i = 0; i < tp -> options -> universe_count; i++) { - if (tp -> options -> universes [i]) { - option_space_foreach (tp, (struct lease *)0, - (struct client_state *)0, - (struct option_state *)0, - tp -> options, - &global_scope, - universes [i], 0, - dump_packet_option); - } - } - } - log_debug ("%s", ""); -} -#endif - -void dump_raw (buf, len) - const unsigned char *buf; - unsigned len; -{ - int i; - char lbuf [80]; - int lbix = 0; - -/* - 1 2 3 4 5 6 7 -01234567890123456789012345678901234567890123456789012345678901234567890123 -280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................. -*/ - - memset(lbuf, ' ', 79); - lbuf [79] = 0; - - for (i = 0; i < len; i++) { - if ((i & 15) == 0) { - if (lbix) { - lbuf[53]=' '; - lbuf[54]=' '; - lbuf[55]=' '; - lbuf[73]='\0'; - log_info (lbuf); - } - memset(lbuf, ' ', 79); - lbuf [79] = 0; - sprintf (lbuf, "%03x:", i); - lbix = 4; - } else if ((i & 7) == 0) - lbuf [lbix++] = ' '; - - if(isprint(buf[i])) { - lbuf[56+(i%16)]=buf[i]; - } else { - lbuf[56+(i%16)]='.'; - } - - sprintf (&lbuf [lbix], " %02x", buf [i]); - lbix += 3; - lbuf[lbix]=' '; - - } - lbuf[53]=' '; - lbuf[54]=' '; - lbuf[55]=' '; - lbuf[73]='\0'; - log_info (lbuf); -} - -void hash_dump (table) - struct hash_table *table; -{ - int i; - struct hash_bucket *bp; - - if (!table) - return; - - for (i = 0; i < table -> hash_count; i++) { - if (!table -> buckets [i]) - continue; - log_info ("hash bucket %d:", i); - for (bp = table -> buckets [i]; bp; bp = bp -> next) { - if (bp -> len) - dump_raw (bp -> name, bp -> len); - else - log_info ("%s", (const char *)bp -> name); - } - } -} - -#define HBLEN 60 - -#define DECLARE_HEX_PRINTER(x) \ -char *print_hex##x (len, data, limit) \ - unsigned len; \ - const u_int8_t *data; \ - unsigned limit; \ -{ \ - \ - static char hex_buf##x [HBLEN + 1]; \ - unsigned i; \ - \ - if (limit > HBLEN) \ - limit = HBLEN; \ - \ - for (i = 0; i < (limit - 2) && i < len; i++) { \ - if (!isascii (data [i]) || !isprint (data [i])) { \ - for (i = 0; i < limit / 3 && i < len; i++) { \ - sprintf (&hex_buf##x [i * 3], \ - "%02x:", data [i]); \ - } \ - hex_buf##x [i * 3 - 1] = 0; \ - return hex_buf##x; \ - } \ - } \ - hex_buf##x [0] = '"'; \ - i = len; \ - if (i > limit - 2) \ - i = limit - 2; \ - memcpy (&hex_buf##x [1], data, i); \ - hex_buf##x [i + 1] = '"'; \ - hex_buf##x [i + 2] = 0; \ - return hex_buf##x; \ -} - -DECLARE_HEX_PRINTER (_1) -DECLARE_HEX_PRINTER (_2) -DECLARE_HEX_PRINTER (_3) - -#define DQLEN 80 - -char *print_dotted_quads (len, data) - unsigned len; - const u_int8_t *data; -{ - static char dq_buf [DQLEN + 1]; - int i; - char *s, *last; - - s = &dq_buf [0]; - last = s; - - i = 0; - - /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe% - * The sprintf can't exceed 18 bytes, and since the loop enforces - * 21 bytes of space per iteration at no time can we exit the - * loop without at least 3 bytes spare. - */ - do { - sprintf (s, "%u.%u.%u.%u, ", - data [i], data [i + 1], data [i + 2], data [i + 3]); - s += strlen (s); - i += 4; - } while ((s - &dq_buf [0] > DQLEN - 21) && - i + 3 < len); - if (i == len) - s [-2] = 0; - else - strcpy (s, "..."); - return dq_buf; -} - -char *print_dec_1 (val) - unsigned long val; -{ - static char vbuf [32]; - sprintf (vbuf, "%lu", val); - return vbuf; -} - -char *print_dec_2 (val) - unsigned long val; -{ - static char vbuf [32]; - sprintf (vbuf, "%lu", val); - return vbuf; -} - -static unsigned print_subexpression PROTO ((struct expression *, - char *, unsigned)); - -static unsigned print_subexpression (expr, buf, len) - struct expression *expr; - char *buf; - unsigned len; -{ - unsigned rv, left; - const char *s; - - switch (expr -> op) { - case expr_none: - if (len > 3) { - strcpy (buf, "nil"); - return 3; - } - break; - - case expr_match: - if (len > 7) { - strcpy (buf, "(match)"); - return 7; - } - break; - - case expr_check: - rv = 10 + strlen (expr -> data.check -> name); - if (len > rv) { - sprintf (buf, "(check %s)", - expr -> data.check -> name); - return rv; - } - break; - - case expr_equal: - if (len > 6) { - rv = 4; - strcpy (buf, "(eq "); - rv += print_subexpression (expr -> data.equal [0], - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.equal [1], - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_not_equal: - if (len > 7) { - rv = 5; - strcpy (buf, "(neq "); - rv += print_subexpression (expr -> data.equal [0], - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.equal [1], - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_substring: - if (len > 11) { - rv = 8; - strcpy (buf, "(substr "); - rv += print_subexpression (expr -> data.substring.expr, - buf + rv, len - rv - 3); - buf [rv++] = ' '; - rv += print_subexpression - (expr -> data.substring.offset, - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.substring.len, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_suffix: - if (len > 10) { - rv = 8; - strcpy (buf, "(suffix "); - rv += print_subexpression (expr -> data.suffix.expr, - buf + rv, len - rv - 2); - if (len > rv) - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.suffix.len, - buf + rv, len - rv - 1); - if (len > rv) - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_concat: - if (len > 10) { - rv = 8; - strcpy (buf, "(concat "); - rv += print_subexpression (expr -> data.concat [0], - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.concat [1], - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_pick_first_value: - if (len > 8) { - rv = 6; - strcpy (buf, "(pick1st "); - rv += print_subexpression - (expr -> data.pick_first_value.car, - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression - (expr -> data.pick_first_value.cdr, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_host_lookup: - rv = 15 + strlen (expr -> data.host_lookup -> hostname); - if (len > rv) { - sprintf (buf, "(dns-lookup %s)", - expr -> data.host_lookup -> hostname); - return rv; - } - break; - - case expr_and: - s = "and"; - binop: - rv = strlen (s); - if (len > rv + 4) { - buf [0] = '('; - strcpy (&buf [1], s); - rv += 1; - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.and [0], - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.and [1], - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_or: - s = "or"; - goto binop; - - case expr_add: - s = "+"; - goto binop; - - case expr_subtract: - s = "-"; - goto binop; - - case expr_multiply: - s = "*"; - goto binop; - - case expr_divide: - s = "/"; - goto binop; - - case expr_remainder: - s = "%"; - goto binop; - - case expr_binary_and: - s = "&"; - goto binop; - - case expr_binary_or: - s = "|"; - goto binop; - - case expr_binary_xor: - s = "^"; - goto binop; - - case expr_not: - if (len > 6) { - rv = 5; - strcpy (buf, "(not "); - rv += print_subexpression (expr -> data.not, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_config_option: - s = "cfg-option"; - goto dooption; - - case expr_option: - s = "option"; - dooption: - rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) + - strlen (expr -> data.option -> universe -> name)); - if (len > rv) { - sprintf (buf, "(option %s.%s)", - expr -> data.option -> universe -> name, - expr -> data.option -> name); - return rv; - } - break; - - case expr_hardware: - if (len > 10) { - strcpy (buf, "(hardware)"); - return 10; - } - break; - - case expr_packet: - if (len > 10) { - rv = 8; - strcpy (buf, "(substr "); - rv += print_subexpression (expr -> data.packet.offset, - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.packet.len, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_const_data: - s = print_hex_1 (expr -> data.const_data.len, - expr -> data.const_data.data, len); - rv = strlen (s); - if (rv >= len) - rv = len - 1; - strncpy (buf, s, rv); - buf [rv] = 0; - return rv; - - case expr_encapsulate: - rv = 13; - strcpy (buf, "(encapsulate "); - rv += expr -> data.encapsulate.len; - if (rv + 2 > len) - rv = len - 2; - strncpy (buf, - (const char *)expr -> data.encapsulate.data, rv - 13); - buf [rv++] = ')'; - buf [rv++] = 0; - break; - - case expr_extract_int8: - if (len > 7) { - rv = 6; - strcpy (buf, "(int8 "); - rv += print_subexpression (expr -> data.extract_int, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_extract_int16: - if (len > 8) { - rv = 7; - strcpy (buf, "(int16 "); - rv += print_subexpression (expr -> data.extract_int, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_extract_int32: - if (len > 8) { - rv = 7; - strcpy (buf, "(int32 "); - rv += print_subexpression (expr -> data.extract_int, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_encode_int8: - if (len > 7) { - rv = 6; - strcpy (buf, "(to-int8 "); - rv += print_subexpression (expr -> data.encode_int, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_encode_int16: - if (len > 8) { - rv = 7; - strcpy (buf, "(to-int16 "); - rv += print_subexpression (expr -> data.encode_int, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_encode_int32: - if (len > 8) { - rv = 7; - strcpy (buf, "(to-int32 "); - rv += print_subexpression (expr -> data.encode_int, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_const_int: - s = print_dec_1 (expr -> data.const_int); - rv = strlen (s); - if (len > rv) { - strcpy (buf, s); - return rv; - } - break; - - case expr_exists: - rv = 10 + (strlen (expr -> data.option -> name) + - strlen (expr -> data.option -> universe -> name)); - if (len > rv) { - sprintf (buf, "(exists %s.%s)", - expr -> data.option -> universe -> name, - expr -> data.option -> name); - return rv; - } - break; - - case expr_variable_exists: - rv = 10 + strlen (expr -> data.variable); - if (len > rv) { - sprintf (buf, "(defined %s)", expr -> data.variable); - return rv; - } - break; - - case expr_variable_reference: - rv = strlen (expr -> data.variable); - if (len > rv) { - sprintf (buf, "%s", expr -> data.variable); - return rv; - } - break; - - case expr_known: - s = "known"; - astring: - rv = strlen (s); - if (len > rv) { - strcpy (buf, s); - return rv; - } - break; - - case expr_leased_address: - s = "leased-address"; - goto astring; - - case expr_client_state: - s = "client-state"; - goto astring; - - case expr_host_decl_name: - s = "host-decl-name"; - goto astring; - - case expr_lease_time: - s = "lease-time"; - goto astring; - - case expr_static: - s = "static"; - goto astring; - - case expr_filename: - s = "filename"; - goto astring; - - case expr_sname: - s = "server-name"; - goto astring; - - case expr_reverse: - if (len > 11) { - rv = 13; - strcpy (buf, "(reverse "); - rv += print_subexpression (expr -> data.reverse.width, - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.reverse.buffer, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_binary_to_ascii: - if (len > 5) { - rv = 9; - strcpy (buf, "(b2a "); - rv += print_subexpression (expr -> data.b2a.base, - buf + rv, len - rv - 4); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.b2a.width, - buf + rv, len - rv - 3); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.b2a.seperator, - buf + rv, len - rv - 2); - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.b2a.buffer, - buf + rv, len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_dns_transaction: - rv = 10; - if (len < rv + 2) { - buf [0] = '('; - strcpy (&buf [1], "ns-update "); - while (len < rv + 2) { - rv += print_subexpression - (expr -> data.dns_transaction.car, - buf + rv, len - rv - 2); - buf [rv++] = ' '; - expr = expr -> data.dns_transaction.cdr; - } - buf [rv - 1] = ')'; - buf [rv] = 0; - return rv; - } - return 0; - - case expr_ns_delete: - s = "delete"; - left = 4; - goto dodnsupd; - case expr_ns_exists: - s = "exists"; - left = 4; - goto dodnsupd; - case expr_ns_not_exists: - s = "not_exists"; - left = 4; - goto dodnsupd; - case expr_ns_add: - s = "update"; - left = 5; - dodnsupd: - rv = strlen (s); - if (len > strlen (s) + 1) { - buf [0] = '('; - strcpy (buf + 1, s); - rv++; - buf [rv++] = ' '; - s = print_dec_1 (expr -> data.ns_add.rrclass); - if (len > rv + strlen (s) + left) { - strcpy (&buf [rv], s); - rv += strlen (&buf [rv]); - } - buf [rv++] = ' '; - left--; - s = print_dec_1 (expr -> data.ns_add.rrtype); - if (len > rv + strlen (s) + left) { - strcpy (&buf [rv], s); - rv += strlen (&buf [rv]); - } - buf [rv++] = ' '; - left--; - rv += print_subexpression - (expr -> data.ns_add.rrname, - buf + rv, len - rv - left); - buf [rv++] = ' '; - left--; - rv += print_subexpression - (expr -> data.ns_add.rrdata, - buf + rv, len - rv - left); - buf [rv++] = ' '; - left--; - rv += print_subexpression - (expr -> data.ns_add.ttl, - buf + rv, len - rv - left); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_null: - if (len > 6) { - strcpy (buf, "(null)"); - return 6; - } - break; - case expr_funcall: - rv = 12 + strlen (expr -> data.funcall.name); - if (len > rv + 1) { - strcpy (buf, "(funcall "); - strcpy (buf + 9, expr -> data.funcall.name); - buf [rv++] = ' '; - rv += print_subexpression - (expr -> data.funcall.arglist, buf + rv, - len - rv - 1); - buf [rv++] = ')'; - buf [rv] = 0; - return rv; - } - break; - - case expr_arg: - rv = print_subexpression (expr -> data.arg.val, buf, len); - if (expr -> data.arg.next && rv + 2 < len) { - buf [rv++] = ' '; - rv += print_subexpression (expr -> data.arg.next, - buf, len); - if (rv + 1 < len) - buf [rv++] = 0; - return rv; - } - break; - case expr_function: - rv = 9; - if (len > rv + 1) { - struct string_list *foo; - strcpy (buf, "(function"); - for (foo = expr -> data.func -> args; - foo; foo = foo -> next) { - if (len > rv + 2 + strlen (foo -> string)) { - buf [rv - 1] = ' '; - strcpy (&buf [rv], foo -> string); - rv += strlen (foo -> string); - } - } - buf [rv] = ')'; - buf [rv++] = 0; - return rv; - } - } - return 0; -} - -void print_expression (name, expr) - const char *name; - struct expression *expr; -{ - char buf [1024]; - - print_subexpression (expr, buf, sizeof buf); - log_info ("%s: %s", name, buf); -} - -int token_print_indent_concat (FILE *file, int col, int indent, - const char *prefix, - const char *suffix, ...) -{ - va_list list; - char *buf; - unsigned len; - char *s, *t, *u; - - va_start (list, suffix); - s = va_arg (list, char *); - len = 0; - while (s) { - len += strlen (s); - s = va_arg (list, char *); - } - va_end (list); - - t = dmalloc (len + 1, MDL); - if (!t) - log_fatal ("token_print_indent: no memory for copy buffer"); - - va_start (list, suffix); - s = va_arg (list, char *); - u = t; - while (s) { - len = strlen (s); - strcpy (u, s); - u += len; - } - va_end (list); - - len = token_print_indent (file, col, indent, - prefix, suffix, t); - dfree (t, MDL); - return col; -} - -int token_indent_data_string (FILE *file, int col, int indent, - const char *prefix, const char *suffix, - struct data_string *data) -{ - int i; - char *buf; - char obuf [3]; - - /* See if this is just ASCII. */ - for (i = 0; i < data -> len; i++) - if (!isascii (data -> data [i]) || - !isprint (data -> data [i])) - break; - - /* If we have a purely ASCII string, output it as text. */ - if (i == data -> len) { - char *buf = dmalloc (data -> len + 3, MDL); - if (buf) { - buf [0] = '"'; - memcpy (buf + 1, data -> data, data -> len); - buf [data -> len + 1] = '"'; - buf [data -> len + 2] = 0; - i = token_print_indent (file, col, indent, - prefix, suffix, buf); - dfree (buf, MDL); - return i; - } - } - - for (i = 0; i < data -> len; i++) { - sprintf (obuf, "%2.2x", data -> data [i]); - col = token_print_indent (file, col, indent, - i == 0 ? prefix : "", - (i + 1 == data -> len - ? suffix - : ""), obuf); - if (i + 1 != data -> len) - col = token_print_indent (file, col, indent, - prefix, suffix, ":"); - } - return col; -} - -int token_print_indent (FILE *file, int col, int indent, - const char *prefix, - const char *suffix, const char *buf) -{ - int len = strlen (buf) + strlen (prefix); - if (col + len > 79) { - if (indent + len < 79) { - indent_spaces (file, indent); - col = indent; - } else { - indent_spaces (file, col); - col = len > 79 ? 0 : 79 - len - 1; - } - } else if (prefix && *prefix) { - fputs (prefix, file); - col += strlen (prefix); - } - fputs (buf, file); - col += len; - if (suffix && *suffix) { - if (col + strlen (suffix) > 79) { - indent_spaces (file, indent); - col = indent; - } else { - fputs (suffix, file); - col += strlen (suffix); - } - } - return col; -} - -void indent_spaces (FILE *file, int indent) -{ - int i; - fputc ('\n', file); - for (i = 0; i < indent; i++) - fputc (' ', file); -} - -#if defined (NSUPDATE) -void print_dns_status (int status, ns_updque *uq) -{ - char obuf [1024]; - char *s = &obuf [0], *end = &obuf [1022]; - ns_updrec *u; - int position; - int ttlp; - const char *predicate = "if", *en, *op; - int errorp; - - for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) { - ttlp = 0; - - switch (u -> r_opcode) - { - case NXRRSET: - op = "rrset doesn't exist"; - position = 1; - break; - case YXRRSET: - op = "rrset exists"; - position = 1; - break; - case NXDOMAIN: - op = "domain doesn't exist"; - position = 1; - break; - case YXDOMAIN: - op = "domain exists"; - position = 1; - break; - case ADD: - op = "add"; - position = 0; - ttlp = 1; - break; - case DELETE: - op = "delete"; - position = 0; - break; - default: - op = "unknown"; - position = 0; - break; - } - if (!position) { - if (s != &obuf [0] && s + 1 < end) - *s++ = ' '; - if (s + strlen (op) < end) { - strcpy (s, op); - s += strlen (s); - } - } else { - if (s != &obuf [0] && s + 1 < end) - *s++ = ' '; - if (s + strlen (predicate) < end) { - strcpy (s, predicate); - s += strlen (s); - } - predicate = "and"; - } - if (u -> r_dname) { - if (s + 1 < end) - *s++ = ' '; - if (s + strlen (u -> r_dname) < end) { - strcpy (s, u -> r_dname); - s += strlen (s); - } - } - if (ttlp) { - if (s + 1 < end) - *s++ = ' '; - /* 27 is as big as a ttl can get. */ - if (s + 27 < end) { - sprintf (s, "%lu", - (unsigned long)(u -> r_ttl)); - s += strlen (s); - } - } - switch (u -> r_class) { - case C_IN: - en = "IN"; - break; - case C_CHAOS: - en = "CHAOS"; - break; - case C_HS: - en = "HS"; - break; - default: - en = "UNKNOWN"; - break; - } - if (s + strlen (en) < end) { - if (s + 1 < end) - *s++ = ' '; - strcpy (s, en); - s += strlen (en); - } - switch (u -> r_type) { - case T_A: - en = "A"; - break; - case T_PTR: - en = "PTR"; - break; - case T_MX: - en = "MX"; - break; - case T_TXT: - en = "TXT"; - break; - case T_KEY: - en = "KEY"; - break; - case T_CNAME: - en = "CNAME"; - break; - default: - en = "UNKNOWN"; - break; - } - if (s + strlen (en) < end) { - if (s + 1 < end) - *s++ = ' '; - strcpy (s, en); - s += strlen (en); - } - if (u -> r_data) { - if (s + 1 < end) - *s++ = ' '; - if (u -> r_type == T_TXT) { - if (s + 1 < end) - *s++ = '"'; - } - if(u->r_type == T_KEY) { - strcat(s, "<keydata>"); - s+=strlen("<keydata>"); - } - else { - if (s + u -> r_size < end) { - memcpy (s, u -> r_data, u -> r_size); - s += u -> r_size; - if (u -> r_type == T_TXT) { - if (s + 1 < end) - *s++ = '"'; - } - } - } - } - if (position) { - if (s + 1 < end) - *s++ = ' '; - if (s + strlen (op) < end) { - strcpy (s, op); - s += strlen (s); - } - } - if (u == ISC_LIST_TAIL (*uq)) - break; - } - if (s == &obuf [0]) { - strcpy (s, "empty update"); - s += strlen (s); - } - if (status == NOERROR) - errorp = 0; - else - errorp = 1; - en = isc_result_totext (status); -#if 0 - switch (status) { - case -1: - en = "resolver failed"; - break; - - case FORMERR: - en = "format error"; - break; - - case NOERROR: - en = "succeeded"; - errorp = 0; - break; - - case NOTAUTH: - en = "not authorized"; - break; - - case NOTIMP: - en = "not implemented"; - break; - - case NOTZONE: - en = "not a single valid zone"; - break; - - case NXDOMAIN: - en = "no such domain"; - break; - - case NXRRSET: - en = "no such record"; - break; - - case REFUSED: - en = "refused"; - break; - - case SERVFAIL: - en = "server failed"; - break; - - case YXDOMAIN: - en = "domain exists"; - break; - - case YXRRSET: - en = "record exists"; - break; - - default: - en = "unknown error"; - break; - } -#endif - - if (s + 2 < end) { - *s++ = ':'; - *s++ = ' '; - } - if (s + strlen (en) < end) { - strcpy (s, en); - s += strlen (en); - } - if (s + 1 < end) - *s++ = '.'; - *s++ = 0; - if (errorp) - log_error ("%s", obuf); - else - log_info ("%s", obuf); -} -#endif /* NSUPDATE */ diff --git a/contrib/isc-dhcp/common/raw.c b/contrib/isc-dhcp/common/raw.c deleted file mode 100644 index 1194ffc..0000000 --- a/contrib/isc-dhcp/common/raw.c +++ /dev/null @@ -1,144 +0,0 @@ -/* socket.c - - BSD raw socket interface code... */ - -/* XXX - - It's not clear how this should work, and that lack of clarity is - terribly detrimental to the NetBSD 1.1 kernel - it crashes and - burns. - - Using raw sockets ought to be a big win over using BPF or something - like it, because you don't need to deal with the complexities of - the physical layer, but it appears not to be possible with existing - raw socket implementations. This may be worth revisiting in the - future. For now, this code can probably be considered a curiosity. - Sigh. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: raw.c,v 1.17.2.2 2004/06/10 17:59:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (USE_RAW_SEND) -#include <sys/uio.h> - -/* Generic interface registration routine... */ -void if_register_send (info) - struct interface_info *info; -{ - struct sockaddr_in name; - int sock; - struct socklist *tmp; - int flag; - - /* Set up the address we're going to connect to. */ - name.sin_family = AF_INET; - name.sin_port = local_port; - name.sin_addr.s_addr = htonl (INADDR_BROADCAST); - memset (name.sin_zero, 0, sizeof (name.sin_zero)); - - /* List addresses on which we're listening. */ - if (!quiet_interface_discovery) - log_info ("Sending on %s, port %d", - piaddr (info -> address), htons (local_port)); - if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) - log_fatal ("Can't create dhcp socket: %m"); - - /* Set the BROADCAST option so that we can broadcast DHCP responses. */ - flag = 1; - if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, - &flag, sizeof flag) < 0) - log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m"); - - /* Set the IP_HDRINCL flag so that we can supply our own IP - headers... */ - if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &flag, sizeof flag) < 0) - log_fatal ("Can't set IP_HDRINCL flag: %m"); - - info -> wfdesc = sock; - if (!quiet_interface_discovery) - log_info ("Sending on Raw/%s%s%s", - info -> name, - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_send (info) - struct interface_info *info; -{ - close (info -> wfdesc); - info -> wfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling output on Raw/%s%s%s", - info -> name, - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -size_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - unsigned char buf [256]; - int bufp = 0; - struct iovec iov [2]; - int result; - - /* Assemble the headers... */ - assemble_udp_ip_header (interface, buf, &bufp, from.s_addr, - to -> sin_addr.s_addr, to -> sin_port, - (unsigned char *)raw, len); - - /* Fire it off */ - iov [0].iov_base = (char *)buf; - iov [0].iov_len = bufp; - iov [1].iov_base = (char *)raw; - iov [1].iov_len = len; - - result = writev(interface -> wfdesc, iov, 2); - if (result < 0) - log_error ("send_packet: %m"); - return result; -} -#endif /* USE_SOCKET_SEND */ diff --git a/contrib/isc-dhcp/common/resolv.c b/contrib/isc-dhcp/common/resolv.c deleted file mode 100644 index b84de02..0000000 --- a/contrib/isc-dhcp/common/resolv.c +++ /dev/null @@ -1,203 +0,0 @@ -/* resolv.c - - Parser for /etc/resolv.conf file. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: resolv.c,v 1.16.2.2 2004/06/10 17:59:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -struct name_server *name_servers; -struct domain_search_list *domains; -char path_resolv_conf [] = _PATH_RESOLV_CONF; - -void read_resolv_conf (parse_time) - TIME parse_time; -{ - int file; - struct parse *cfile; - const char *val; - int token; - int declaration = 0; - struct name_server *sp, *sl, *ns; - struct domain_search_list *dp, *dl, *nd; - struct iaddr *iaddr; - - if ((file = open (path_resolv_conf, O_RDONLY)) < 0) { - log_error ("Can't open %s: %m", path_resolv_conf); - return; - } - - cfile = (struct parse *)0; - new_parse (&cfile, file, (char *)0, 0, path_resolv_conf, 1); - - do { - token = next_token (&val, (unsigned *)0, cfile); - if (token == END_OF_FILE) - break; - else if (token == EOL) - continue; - else if (token == DOMAIN || token == SEARCH) { - do { - struct domain_search_list *nd, **dp; - char *dn; - - dn = parse_host_name (cfile); - if (!dn) - break; - - dp = &domains; - for (nd = domains; nd; nd = nd -> next) { - dp = &nd -> next; - if (!strcmp (nd -> domain, dn)) - break; - } - if (!nd) { - nd = new_domain_search_list (MDL); - if (!nd) - log_fatal ("No memory for %s", - dn); - nd -> next = - (struct domain_search_list *)0; - *dp = nd; - nd -> domain = dn; - dn = (char *)0; - } - nd -> rcdate = parse_time; - token = peek_token (&val, - (unsigned *)0, cfile); - } while (token != EOL); - if (token != EOL) { - parse_warn (cfile, - "junk after domain declaration"); - skip_to_semi (cfile); - } - token = next_token (&val, (unsigned *)0, cfile); - } else if (token == NAMESERVER) { - struct name_server *ns, **sp; - struct iaddr iaddr; - - parse_ip_addr (cfile, &iaddr); - - sp = &name_servers; - for (ns = name_servers; ns; ns = ns -> next) { - sp = &ns -> next; - if (!memcmp (&ns -> addr.sin_addr, - iaddr.iabuf, iaddr.len)) - break; - } - if (!ns) { - ns = new_name_server (MDL); - if (!ns) - log_fatal ("No memory for nameserver %s", - piaddr (iaddr)); - ns -> next = (struct name_server *)0; - *sp = ns; - memcpy (&ns -> addr.sin_addr, - iaddr.iabuf, iaddr.len); -#ifdef HAVE_SA_LEN - ns -> addr.sin_len = sizeof ns -> addr; -#endif - ns -> addr.sin_family = AF_INET; - ns -> addr.sin_port = htons (53); - memset (ns -> addr.sin_zero, 0, - sizeof ns -> addr.sin_zero); - } - ns -> rcdate = parse_time; - skip_to_semi (cfile); - } else - skip_to_semi (cfile); /* Ignore what we don't grok. */ - } while (1); - token = next_token (&val, (unsigned *)0, cfile); - - /* Lose servers that are no longer in /etc/resolv.conf. */ - sl = (struct name_server *)0; - for (sp = name_servers; sp; sp = ns) { - ns = sp -> next; - if (sp -> rcdate != parse_time) { - if (sl) - sl -> next = sp -> next; - else - name_servers = sp -> next; - /* We can't actually free the name server structure, - because somebody might be hanging on to it. If - your /etc/resolv.conf file changes a lot, this - could be a noticable memory leak. */ - } else - sl = sp; - } - - /* Lose domains that are no longer in /etc/resolv.conf. */ - dl = (struct domain_search_list *)0; - for (dp = domains; dp; dp = nd) { - nd = dp -> next; - if (dp -> rcdate != parse_time) { - if (dl) - dl -> next = dp -> next; - else - domains = dp -> next; - free_domain_search_list (dp, MDL); - } else - dl = dp; - } - close (file); - end_parse (&cfile); -} - -/* Pick a name server from the /etc/resolv.conf file. */ - -struct name_server *first_name_server () -{ - FILE *rc; - static TIME rcdate; - struct stat st; - - /* Check /etc/resolv.conf and reload it if it's changed. */ - if (cur_time > rcdate) { - if (stat (path_resolv_conf, &st) < 0) { - log_error ("Can't stat %s", path_resolv_conf); - return (struct name_server *)0; - } - if (st.st_mtime > rcdate) { - char rcbuf [512]; - char *s, *t, *u; - rcdate = cur_time + 1; - - read_resolv_conf (rcdate); - } - } - - return name_servers; -} diff --git a/contrib/isc-dhcp/common/socket.c b/contrib/isc-dhcp/common/socket.c deleted file mode 100644 index 6aa4507..0000000 --- a/contrib/isc-dhcp/common/socket.c +++ /dev/null @@ -1,371 +0,0 @@ -/* socket.c - - BSD socket interface code... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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''. - */ - -/* SO_BINDTODEVICE support added by Elliot Poger (poger@leland.stanford.edu). - * This sockopt allows a socket to be bound to a particular interface, - * thus enabling the use of DHCPD on a multihomed host. - * If SO_BINDTODEVICE is defined in your system header files, the use of - * this sockopt will be automatically enabled. - * I have implemented it under Linux; other systems should be doable also. - */ - -#ifndef lint -static char copyright[] = -"$Id: socket.c,v 1.55.2.4 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#ifdef USE_SOCKET_FALLBACK -# if !defined (USE_SOCKET_SEND) -# define if_register_send if_register_fallback -# define send_packet send_fallback -# define if_reinitialize_send if_reinitialize_fallback -# endif -#endif - -static int once = 0; - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) -void if_reinitialize_send (info) - struct interface_info *info; -{ -#if 0 -#ifndef USE_SOCKET_RECEIVE - once = 0; - close (info -> wfdesc); -#endif - if_register_send (info); -#endif -} -#endif - -#ifdef USE_SOCKET_RECEIVE -void if_reinitialize_receive (info) - struct interface_info *info; -{ -#if 0 - once = 0; - close (info -> rfdesc); - if_register_receive (info); -#endif -} -#endif - -#if defined (USE_SOCKET_SEND) || \ - defined (USE_SOCKET_RECEIVE) || \ - defined (USE_SOCKET_FALLBACK) -/* Generic interface registration routine... */ -int if_register_socket (info) - struct interface_info *info; -{ - struct sockaddr_in name; - int sock; - int flag; - -#if !defined (HAVE_SO_BINDTODEVICE) && !defined (USE_FALLBACK) - /* Make sure only one interface is registered. */ - if (once) - log_fatal ("The standard socket API can only support %s", - "hosts with a single network interface."); - once = 1; -#endif - - memset (&name, 0, sizeof (name)); - /* Set up the address we're going to bind to. */ - name.sin_family = AF_INET; - name.sin_port = local_port; - name.sin_addr = local_address; - - /* Make a socket... */ - if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - log_fatal ("Can't create dhcp socket: %m"); - - /* Set the REUSEADDR option so that we don't fail to start if - we're being restarted. */ - flag = 1; - if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, - (char *)&flag, sizeof flag) < 0) - log_fatal ("Can't set SO_REUSEADDR option on dhcp socket: %m"); - - /* Set the BROADCAST option so that we can broadcast DHCP responses. - We shouldn't do this for fallback devices, and we can detect that - a device is a fallback because it has no ifp structure. */ - if (info -> ifp && - (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, - (char *)&flag, sizeof flag) < 0)) - log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m"); - - /* Bind the socket to this interface's IP address. */ - if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) { - log_error ("Can't bind to dhcp address: %m"); - log_error ("Please make sure there is no other dhcp server"); - log_error ("running and that there's no entry for dhcp or"); - log_error ("bootp in /etc/inetd.conf. Also make sure you"); - log_error ("are not running HP JetAdmin software, which"); - log_fatal ("includes a bootp server."); - } - -#if defined (HAVE_SO_BINDTODEVICE) - /* Bind this socket to this interface. */ - if (info -> ifp && - setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE, - (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) { - log_fatal ("setsockopt: SO_BINDTODEVICE: %m"); - } -#endif - - return sock; -} -#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE || USE_SOCKET_FALLBACK */ - -#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) -void if_register_send (info) - struct interface_info *info; -{ -#ifndef USE_SOCKET_RECEIVE - info -> wfdesc = if_register_socket (info); -#if defined (USE_SOCKET_FALLBACK) - /* Fallback only registers for send, but may need to receive as - well. */ - info -> rfdesc = info -> wfdesc; -#endif -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - log_info ("Sending on Socket/%s%s%s", - info -> name, - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -#if defined (USE_SOCKET_SEND) -void if_deregister_send (info) - struct interface_info *info; -{ -#ifndef USE_SOCKET_RECEIVE - close (info -> wfdesc); -#endif - info -> wfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling output on Socket/%s%s%s", - info -> name, - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_SOCKET_SEND */ -#endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */ - -#ifdef USE_SOCKET_RECEIVE -void if_register_receive (info) - struct interface_info *info; -{ - /* If we're using the socket API for sending and receiving, - we don't need to register this interface twice. */ - info -> rfdesc = if_register_socket (info); - if (!quiet_interface_discovery) - log_info ("Listening on Socket/%s%s%s", - info -> name, - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_receive (info) - struct interface_info *info; -{ - close (info -> rfdesc); - info -> rfdesc = -1; - - if (!quiet_interface_discovery) - log_info ("Disabling input on Socket/%s%s%s", - info -> name, - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_SOCKET_RECEIVE */ - -#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) -ssize_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - int result; -#ifdef IGNORE_HOSTUNREACH - int retry = 0; - do { -#endif - result = sendto (interface -> wfdesc, (char *)raw, len, 0, - (struct sockaddr *)to, sizeof *to); -#ifdef IGNORE_HOSTUNREACH - } while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) && - result < 0 && - (errno == EHOSTUNREACH || - errno == ECONNREFUSED) && - retry++ < 10); -#endif - if (result < 0) { - log_error ("send_packet: %m"); - if (errno == ENETUNREACH) - log_error ("send_packet: please consult README file%s", - " regarding broadcast address."); - } - return result; -} -#endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */ - -#ifdef USE_SOCKET_RECEIVE -ssize_t receive_packet (interface, buf, len, from, hfrom) - struct interface_info *interface; - unsigned char *buf; - size_t len; - struct sockaddr_in *from; - struct hardware *hfrom; -{ - SOCKLEN_T flen = sizeof *from; - int result; - -#ifdef IGNORE_HOSTUNREACH - int retry = 0; - do { -#endif - result = recvfrom (interface -> rfdesc, (char *)buf, len, 0, - (struct sockaddr *)from, &flen); -#ifdef IGNORE_HOSTUNREACH - } while (result < 0 && - (errno == EHOSTUNREACH || - errno == ECONNREFUSED) && - retry++ < 10); -#endif - return result; -} -#endif /* USE_SOCKET_RECEIVE */ - -#if defined (USE_SOCKET_FALLBACK) -/* This just reads in a packet and silently discards it. */ - -isc_result_t fallback_discard (object) - omapi_object_t *object; -{ - char buf [1540]; - struct sockaddr_in from; - SOCKLEN_T flen = sizeof from; - int status; - struct interface_info *interface; - - if (object -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - interface = (struct interface_info *)object; - - status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0, - (struct sockaddr *)&from, &flen); -#if defined (DEBUG) - /* Only report fallback discard errors if we're debugging. */ - if (status < 0) { - log_error ("fallback_discard: %m"); - return ISC_R_UNEXPECTED; - } -#endif - return ISC_R_SUCCESS; -} -#endif /* USE_SOCKET_FALLBACK */ - -#if defined (USE_SOCKET_SEND) -int can_unicast_without_arp (ip) - struct interface_info *ip; -{ - return 0; -} - -int can_receive_unicast_unconfigured (ip) - struct interface_info *ip; -{ -#if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED) - return 1; -#else - return 0; -#endif -} - -int supports_multiple_interfaces (ip) - struct interface_info *ip; -{ -#if defined (SO_BINDTODEVICE) - return 1; -#else - return 0; -#endif -} - -/* If we have SO_BINDTODEVICE, set up a fallback interface; otherwise, - do not. */ - -void maybe_setup_fallback () -{ -#if defined (USE_SOCKET_FALLBACK) - isc_result_t status; - struct interface_info *fbi = (struct interface_info *)0; - if (setup_fallback (&fbi, MDL)) { - fbi -> wfdesc = if_register_socket (fbi); - fbi -> rfdesc = fbi -> wfdesc; - log_info ("Sending on Socket/%s%s%s", - fbi -> name, - (fbi -> shared_network ? "/" : ""), - (fbi -> shared_network ? - fbi -> shared_network -> name : "")); - - status = omapi_register_io_object ((omapi_object_t *)fbi, - if_readsocket, 0, - fallback_discard, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - fbi -> name, isc_result_totext (status)); - interface_dereference (&fbi, MDL); - } -#endif -} -#endif /* USE_SOCKET_SEND */ diff --git a/contrib/isc-dhcp/common/tables.c b/contrib/isc-dhcp/common/tables.c deleted file mode 100644 index 6de6d6f..0000000 --- a/contrib/isc-dhcp/common/tables.c +++ /dev/null @@ -1,1241 +0,0 @@ -/* tables.c - - Tables of information... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$FreeBSD$" -"$Id: tables.c,v 1.51.2.8 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -/* XXXDPN: Moved here from hash.c, when it moved to libomapi. Not sure - where these really belong. */ -HASH_FUNCTIONS (group, const char *, struct group_object, group_hash_t, - group_reference, group_dereference) -HASH_FUNCTIONS (universe, const char *, struct universe, universe_hash_t, 0, 0) -HASH_FUNCTIONS (option, const char *, struct option, option_hash_t, 0, 0) - -/* DHCP Option names, formats and codes, from RFC1533. - - Format codes: - - I - IP address - l - 32-bit signed integer - L - 32-bit unsigned integer - s - 16-bit signed integer - S - 16-bit unsigned integer - b - 8-bit signed integer - B - 8-bit unsigned integer - t - ASCII text - f - flag (true or false) - A - array of whatever precedes (e.g., IA means array of IP addresses) - a - array of the preceding character (e.g., IIa means two or more IP - addresses) - U - name of an option space (universe) - F - implicit flag - the presence of the option indicates that the - flag is true. - o - the preceding value is optional. - E - encapsulation, string or colon-seperated hex list (the latter - two for parsing). E is followed by a text string containing - the name of the option space to encapsulate, followed by a '.'. - If the E is immediately followed by '.', the applicable vendor - option space is used if one is defined. - e - If an encapsulation directive is not the first thing in the string, - the option scanner requires an efficient way to find the encapsulation. - This is done by placing a 'e' at the beginning of the option. The - 'e' has no other purpose, and is not required if 'E' is the first - thing in the option. - X - either an ASCII string or binary data. On output, the string is - scanned to see if it's printable ASCII and, if so, output as a - quoted string. If not, it's output as colon-seperated hex. On - input, the option can be specified either as a quoted string or as - a colon-seperated hex list. - N - enumeration. N is followed by a text string containing - the name of the set of enumeration values to parse or emit, - followed by a '.'. The width of the data is specified in the - named enumeration. Named enumerations are tracked in parse.c. - d - Domain name (i.e., FOO or FOO.BAR). -*/ - -struct universe dhcp_universe; -struct option dhcp_options [256] = { - { "pad", "", &dhcp_universe, 0 }, - { "subnet-mask", "I", &dhcp_universe, 1 }, - { "time-offset", "l", &dhcp_universe, 2 }, - { "routers", "IA", &dhcp_universe, 3 }, - { "time-servers", "IA", &dhcp_universe, 4 }, - { "ien116-name-servers", "IA", &dhcp_universe, 5 }, - { "domain-name-servers", "IA", &dhcp_universe, 6 }, - { "log-servers", "IA", &dhcp_universe, 7 }, - { "cookie-servers", "IA", &dhcp_universe, 8 }, - { "lpr-servers", "IA", &dhcp_universe, 9 }, - { "impress-servers", "IA", &dhcp_universe, 10 }, - { "resource-location-servers", "IA", &dhcp_universe, 11 }, - { "host-name", "X", &dhcp_universe, 12 }, - { "boot-size", "S", &dhcp_universe, 13 }, - { "merit-dump", "t", &dhcp_universe, 14 }, - { "domain-name", "t", &dhcp_universe, 15 }, - { "swap-server", "I", &dhcp_universe, 16 }, - { "root-path", "t", &dhcp_universe, 17 }, - { "extensions-path", "t", &dhcp_universe, 18 }, - { "ip-forwarding", "f", &dhcp_universe, 19 }, - { "non-local-source-routing", "f", &dhcp_universe, 20 }, - { "policy-filter", "IIA", &dhcp_universe, 21 }, - { "max-dgram-reassembly", "S", &dhcp_universe, 22 }, - { "default-ip-ttl", "B", &dhcp_universe, 23 }, - { "path-mtu-aging-timeout", "L", &dhcp_universe, 24 }, - { "path-mtu-plateau-table", "SA", &dhcp_universe, 25 }, - { "interface-mtu", "S", &dhcp_universe, 26 }, - { "all-subnets-local", "f", &dhcp_universe, 27 }, - { "broadcast-address", "I", &dhcp_universe, 28 }, - { "perform-mask-discovery", "f", &dhcp_universe, 29 }, - { "mask-supplier", "f", &dhcp_universe, 30 }, - { "router-discovery", "f", &dhcp_universe, 31 }, - { "router-solicitation-address", "I", &dhcp_universe, 32 }, - { "static-routes", "IIA", &dhcp_universe, 33 }, - { "trailer-encapsulation", "f", &dhcp_universe, 34 }, - { "arp-cache-timeout", "L", &dhcp_universe, 35 }, - { "ieee802-3-encapsulation", "f", &dhcp_universe, 36 }, - { "default-tcp-ttl", "B", &dhcp_universe, 37 }, - { "tcp-keepalive-interval", "L", &dhcp_universe, 38 }, - { "tcp-keepalive-garbage", "f", &dhcp_universe, 39 }, - { "nis-domain", "t", &dhcp_universe, 40 }, - { "nis-servers", "IA", &dhcp_universe, 41 }, - { "ntp-servers", "IA", &dhcp_universe, 42 }, - { "vendor-encapsulated-options", "E.", &dhcp_universe, 43 }, - { "netbios-name-servers", "IA", &dhcp_universe, 44 }, - { "netbios-dd-server", "IA", &dhcp_universe, 45 }, - { "netbios-node-type", "B", &dhcp_universe, 46 }, - { "netbios-scope", "t", &dhcp_universe, 47 }, - { "font-servers", "IA", &dhcp_universe, 48 }, - { "x-display-manager", "IA", &dhcp_universe, 49 }, - { "dhcp-requested-address", "I", &dhcp_universe, 50 }, - { "dhcp-lease-time", "L", &dhcp_universe, 51 }, - { "dhcp-option-overload", "B", &dhcp_universe, 52 }, - { "dhcp-message-type", "B", &dhcp_universe, 53 }, - { "dhcp-server-identifier", "I", &dhcp_universe, 54 }, - { "dhcp-parameter-request-list", "BA", &dhcp_universe, 55 }, - { "dhcp-message", "t", &dhcp_universe, 56 }, - { "dhcp-max-message-size", "S", &dhcp_universe, 57 }, - { "dhcp-renewal-time", "L", &dhcp_universe, 58 }, - { "dhcp-rebinding-time", "L", &dhcp_universe, 59 }, - { "vendor-class-identifier", "X", &dhcp_universe, 60 }, - { "dhcp-client-identifier", "X", &dhcp_universe, 61 }, - { "nwip-domain", "X", &dhcp_universe, 62 }, - { "nwip-suboptions", "Enwip.", &dhcp_universe, 63 }, - { "nisplus-domain", "t", &dhcp_universe, 64 }, - { "nisplus-servers", "IA", &dhcp_universe, 65 }, - { "tftp-server-name", "t", &dhcp_universe, 66 }, - { "bootfile-name", "t", &dhcp_universe, 67 }, - { "mobile-ip-home-agent", "IA", &dhcp_universe, 68 }, - { "smtp-server", "IA", &dhcp_universe, 69 }, - { "pop-server", "IA", &dhcp_universe, 70 }, - { "nntp-server", "IA", &dhcp_universe, 71 }, - { "www-server", "IA", &dhcp_universe, 72 }, - { "finger-server", "IA", &dhcp_universe, 73 }, - { "irc-server", "IA", &dhcp_universe, 74 }, - { "streettalk-server", "IA", &dhcp_universe, 75 }, - { "streettalk-directory-assistance-server", "IA", &dhcp_universe, 76 }, - { "user-class", "t", &dhcp_universe, 77 }, - { "slp-directory-agent", "fIa", &dhcp_universe, 78 }, - { "slp-service-scope", "fto", &dhcp_universe, 79 }, - { "unknown-80", "X", &dhcp_universe, 80 }, - { "fqdn", "Efqdn.", &dhcp_universe, 81 }, - { "relay-agent-information", "Eagent.", &dhcp_universe, 82 }, - { "unknown-83", "X", &dhcp_universe, 83 }, - { "unknown-84", "X", &dhcp_universe, 84 }, - { "nds-servers", "IA", &dhcp_universe, 85 }, - { "nds-tree-name", "X", &dhcp_universe, 86 }, - { "nds-context", "X", &dhcp_universe, 87 }, - { "unknown-88", "X", &dhcp_universe, 88 }, - { "unknown-89", "X", &dhcp_universe, 89 }, - { "unknown-90", "X", &dhcp_universe, 90 }, - { "unknown-91", "X", &dhcp_universe, 91 }, - { "unknown-92", "X", &dhcp_universe, 92 }, - { "unknown-93", "X", &dhcp_universe, 93 }, - { "unknown-94", "X", &dhcp_universe, 94 }, - { "unknown-95", "X", &dhcp_universe, 95 }, - { "unknown-96", "X", &dhcp_universe, 96 }, - { "unknown-97", "X", &dhcp_universe, 97 }, - { "uap-servers", "t", &dhcp_universe, 98 }, - { "unknown-99", "X", &dhcp_universe, 99 }, - { "unknown-100", "X", &dhcp_universe, 100 }, - { "unknown-101", "X", &dhcp_universe, 101 }, - { "unknown-102", "X", &dhcp_universe, 102 }, - { "unknown-103", "X", &dhcp_universe, 103 }, - { "unknown-104", "X", &dhcp_universe, 104 }, - { "unknown-105", "X", &dhcp_universe, 105 }, - { "unknown-106", "X", &dhcp_universe, 106 }, - { "unknown-107", "X", &dhcp_universe, 107 }, - { "unknown-108", "X", &dhcp_universe, 108 }, - { "unknown-109", "X", &dhcp_universe, 109 }, - { "unknown-110", "X", &dhcp_universe, 110 }, - { "unknown-111", "X", &dhcp_universe, 111 }, - { "unknown-112", "X", &dhcp_universe, 112 }, - { "unknown-113", "X", &dhcp_universe, 113 }, - { "unknown-114", "X", &dhcp_universe, 114 }, - { "unknown-115", "X", &dhcp_universe, 115 }, - { "unknown-116", "X", &dhcp_universe, 116 }, - { "unknown-117", "X", &dhcp_universe, 117 }, - { "subnet-selection", "X", &dhcp_universe, 118 }, - { "unknown-119", "X", &dhcp_universe, 119 }, - { "unknown-120", "X", &dhcp_universe, 120 }, - { "unknown-121", "X", &dhcp_universe, 121 }, - { "unknown-122", "X", &dhcp_universe, 122 }, - { "unknown-123", "X", &dhcp_universe, 123 }, - { "unknown-124", "X", &dhcp_universe, 124 }, - { "unknown-125", "X", &dhcp_universe, 125 }, - { "unknown-126", "X", &dhcp_universe, 126 }, - { "unknown-127", "X", &dhcp_universe, 127 }, - { "unknown-128", "X", &dhcp_universe, 128 }, - { "unknown-129", "X", &dhcp_universe, 129 }, - { "unknown-130", "X", &dhcp_universe, 130 }, - { "unknown-131", "X", &dhcp_universe, 131 }, - { "unknown-132", "X", &dhcp_universe, 132 }, - { "unknown-133", "X", &dhcp_universe, 133 }, - { "unknown-134", "X", &dhcp_universe, 134 }, - { "unknown-135", "X", &dhcp_universe, 135 }, - { "unknown-136", "X", &dhcp_universe, 136 }, - { "unknown-137", "X", &dhcp_universe, 137 }, - { "unknown-138", "X", &dhcp_universe, 138 }, - { "unknown-139", "X", &dhcp_universe, 139 }, - { "unknown-140", "X", &dhcp_universe, 140 }, - { "unknown-141", "X", &dhcp_universe, 141 }, - { "unknown-142", "X", &dhcp_universe, 142 }, - { "unknown-143", "X", &dhcp_universe, 143 }, - { "unknown-144", "X", &dhcp_universe, 144 }, - { "unknown-145", "X", &dhcp_universe, 145 }, - { "unknown-146", "X", &dhcp_universe, 146 }, - { "unknown-147", "X", &dhcp_universe, 147 }, - { "unknown-148", "X", &dhcp_universe, 148 }, - { "unknown-149", "X", &dhcp_universe, 149 }, - { "unknown-150", "X", &dhcp_universe, 150 }, - { "unknown-151", "X", &dhcp_universe, 151 }, - { "unknown-152", "X", &dhcp_universe, 152 }, - { "unknown-153", "X", &dhcp_universe, 153 }, - { "unknown-154", "X", &dhcp_universe, 154 }, - { "unknown-155", "X", &dhcp_universe, 155 }, - { "unknown-156", "X", &dhcp_universe, 156 }, - { "unknown-157", "X", &dhcp_universe, 157 }, - { "unknown-158", "X", &dhcp_universe, 158 }, - { "unknown-159", "X", &dhcp_universe, 159 }, - { "unknown-160", "X", &dhcp_universe, 160 }, - { "unknown-161", "X", &dhcp_universe, 161 }, - { "unknown-162", "X", &dhcp_universe, 162 }, - { "unknown-163", "X", &dhcp_universe, 163 }, - { "unknown-164", "X", &dhcp_universe, 164 }, - { "unknown-165", "X", &dhcp_universe, 165 }, - { "unknown-166", "X", &dhcp_universe, 166 }, - { "unknown-167", "X", &dhcp_universe, 167 }, - { "unknown-168", "X", &dhcp_universe, 168 }, - { "unknown-169", "X", &dhcp_universe, 169 }, - { "unknown-170", "X", &dhcp_universe, 170 }, - { "unknown-171", "X", &dhcp_universe, 171 }, - { "unknown-172", "X", &dhcp_universe, 172 }, - { "unknown-173", "X", &dhcp_universe, 173 }, - { "unknown-174", "X", &dhcp_universe, 174 }, - { "unknown-175", "X", &dhcp_universe, 175 }, - { "unknown-176", "X", &dhcp_universe, 176 }, - { "unknown-177", "X", &dhcp_universe, 177 }, - { "unknown-178", "X", &dhcp_universe, 178 }, - { "unknown-179", "X", &dhcp_universe, 179 }, - { "unknown-180", "X", &dhcp_universe, 180 }, - { "unknown-181", "X", &dhcp_universe, 181 }, - { "unknown-182", "X", &dhcp_universe, 182 }, - { "unknown-183", "X", &dhcp_universe, 183 }, - { "unknown-184", "X", &dhcp_universe, 184 }, - { "unknown-185", "X", &dhcp_universe, 185 }, - { "unknown-186", "X", &dhcp_universe, 186 }, - { "unknown-187", "X", &dhcp_universe, 187 }, - { "unknown-188", "X", &dhcp_universe, 188 }, - { "unknown-189", "X", &dhcp_universe, 189 }, - { "unknown-190", "X", &dhcp_universe, 190 }, - { "unknown-191", "X", &dhcp_universe, 191 }, - { "unknown-192", "X", &dhcp_universe, 192 }, - { "unknown-193", "X", &dhcp_universe, 193 }, - { "unknown-194", "X", &dhcp_universe, 194 }, - { "unknown-195", "X", &dhcp_universe, 195 }, - { "unknown-196", "X", &dhcp_universe, 196 }, - { "unknown-197", "X", &dhcp_universe, 197 }, - { "unknown-198", "X", &dhcp_universe, 198 }, - { "unknown-199", "X", &dhcp_universe, 199 }, - { "unknown-200", "X", &dhcp_universe, 200 }, - { "unknown-201", "X", &dhcp_universe, 201 }, - { "unknown-202", "X", &dhcp_universe, 202 }, - { "unknown-203", "X", &dhcp_universe, 203 }, - { "unknown-204", "X", &dhcp_universe, 204 }, - { "unknown-205", "X", &dhcp_universe, 205 }, - { "unknown-206", "X", &dhcp_universe, 206 }, - { "unknown-207", "X", &dhcp_universe, 207 }, - { "unknown-208", "X", &dhcp_universe, 208 }, - { "unknown-209", "X", &dhcp_universe, 209 }, - { "authenticate", "X", &dhcp_universe, 210 }, - { "unknown-211", "X", &dhcp_universe, 211 }, - { "unknown-212", "X", &dhcp_universe, 212 }, - { "unknown-213", "X", &dhcp_universe, 213 }, - { "unknown-214", "X", &dhcp_universe, 214 }, - { "unknown-215", "X", &dhcp_universe, 215 }, - { "unknown-216", "X", &dhcp_universe, 216 }, - { "unknown-217", "X", &dhcp_universe, 217 }, - { "unknown-218", "X", &dhcp_universe, 218 }, - { "unknown-219", "X", &dhcp_universe, 219 }, - { "unknown-220", "X", &dhcp_universe, 220 }, - { "unknown-221", "X", &dhcp_universe, 221 }, - { "unknown-222", "X", &dhcp_universe, 222 }, - { "unknown-223", "X", &dhcp_universe, 223 }, - { "unknown-224", "X", &dhcp_universe, 224 }, - { "unknown-225", "X", &dhcp_universe, 225 }, - { "unknown-226", "X", &dhcp_universe, 226 }, - { "unknown-227", "X", &dhcp_universe, 227 }, - { "unknown-228", "X", &dhcp_universe, 228 }, - { "unknown-229", "X", &dhcp_universe, 229 }, - { "unknown-230", "X", &dhcp_universe, 230 }, - { "unknown-231", "X", &dhcp_universe, 231 }, - { "unknown-232", "X", &dhcp_universe, 232 }, - { "unknown-233", "X", &dhcp_universe, 233 }, - { "unknown-234", "X", &dhcp_universe, 234 }, - { "unknown-235", "X", &dhcp_universe, 235 }, - { "unknown-236", "X", &dhcp_universe, 236 }, - { "unknown-237", "X", &dhcp_universe, 237 }, - { "unknown-238", "X", &dhcp_universe, 238 }, - { "unknown-239", "X", &dhcp_universe, 239 }, - { "unknown-240", "X", &dhcp_universe, 240 }, - { "unknown-241", "X", &dhcp_universe, 241 }, - { "unknown-242", "X", &dhcp_universe, 242 }, - { "unknown-243", "X", &dhcp_universe, 243 }, - { "unknown-244", "X", &dhcp_universe, 244 }, - { "unknown-245", "X", &dhcp_universe, 245 }, - { "unknown-246", "X", &dhcp_universe, 246 }, - { "unknown-247", "X", &dhcp_universe, 247 }, - { "unknown-248", "X", &dhcp_universe, 248 }, - { "unknown-249", "X", &dhcp_universe, 249 }, - { "unknown-250", "X", &dhcp_universe, 250 }, - { "unknown-251", "X", &dhcp_universe, 251 }, - { "unknown-252", "X", &dhcp_universe, 252 }, - { "unknown-253", "X", &dhcp_universe, 253 }, - { "unknown-254", "X", &dhcp_universe, 254 }, - { "option-end", "e", &dhcp_universe, 255 }, -}; - -struct universe nwip_universe; -struct option nwip_options [256] = { - { "pad", "", &nwip_universe, 0 }, - { "illegal-1", "", &nwip_universe, 1 }, - { "illegal-2", "", &nwip_universe, 2 }, - { "illegal-3", "", &nwip_universe, 3 }, - { "illegal-4", "", &nwip_universe, 4 }, - { "nsq-broadcast", "f", &nwip_universe, 5 }, - { "preferred-dss", "IA", &nwip_universe, 6 }, - { "nearest-nwip-server", "IA", &nwip_universe, 7 }, - { "autoretries", "B", &nwip_universe, 8 }, - { "autoretry-secs", "B", &nwip_universe, 9 }, - { "nwip-1-1", "f", &nwip_universe, 10 }, - { "primary-dss", "I", &nwip_universe, 11 }, - { "unknown-12", "X", &nwip_universe, 12 }, - { "unknown-13", "X", &nwip_universe, 13 }, - { "unknown-14", "X", &nwip_universe, 14 }, - { "unknown-15", "X", &nwip_universe, 15 }, - { "unknown-16", "X", &nwip_universe, 16 }, - { "unknown-17", "X", &nwip_universe, 17 }, - { "unknown-18", "X", &nwip_universe, 18 }, - { "unknown-19", "X", &nwip_universe, 19 }, - { "unknown-20", "X", &nwip_universe, 20 }, - { "unknown-21", "X", &nwip_universe, 21 }, - { "unknown-22", "X", &nwip_universe, 22 }, - { "unknown-23", "X", &nwip_universe, 23 }, - { "unknown-24", "X", &nwip_universe, 24 }, - { "unknown-25", "X", &nwip_universe, 25 }, - { "unknown-26", "X", &nwip_universe, 26 }, - { "unknown-27", "X", &nwip_universe, 27 }, - { "unknown-28", "X", &nwip_universe, 28 }, - { "unknown-29", "X", &nwip_universe, 29 }, - { "unknown-30", "X", &nwip_universe, 30 }, - { "unknown-31", "X", &nwip_universe, 31 }, - { "unknown-32", "X", &nwip_universe, 32 }, - { "unknown-33", "X", &nwip_universe, 33 }, - { "unknown-34", "X", &nwip_universe, 34 }, - { "unknown-35", "X", &nwip_universe, 35 }, - { "unknown-36", "X", &nwip_universe, 36 }, - { "unknown-37", "X", &nwip_universe, 37 }, - { "unknown-38", "X", &nwip_universe, 38 }, - { "unknown-39", "X", &nwip_universe, 39 }, - { "unknown-40", "X", &nwip_universe, 40 }, - { "unknown-41", "X", &nwip_universe, 41 }, - { "unknown-42", "X", &nwip_universe, 42 }, - { "unknown-43", "X", &nwip_universe, 43 }, - { "unknown-44", "X", &nwip_universe, 44 }, - { "unknown-45", "X", &nwip_universe, 45 }, - { "unknown-46", "X", &nwip_universe, 46 }, - { "unknown-47", "X", &nwip_universe, 47 }, - { "unknown-48", "X", &nwip_universe, 48 }, - { "unknown-49", "X", &nwip_universe, 49 }, - { "unknown-50", "X", &nwip_universe, 50 }, - { "unknown-51", "X", &nwip_universe, 51 }, - { "unknown-52", "X", &nwip_universe, 52 }, - { "unknown-53", "X", &nwip_universe, 53 }, - { "unknown-54", "X", &nwip_universe, 54 }, - { "unknown-55", "X", &nwip_universe, 55 }, - { "unknown-56", "X", &nwip_universe, 56 }, - { "unknown-57", "X", &nwip_universe, 57 }, - { "unknown-58", "X", &nwip_universe, 58 }, - { "unknown-59", "X", &nwip_universe, 59 }, - { "unknown-60", "X", &nwip_universe, 60 }, - { "unknown-61", "X", &nwip_universe, 61 }, - { "unknown-62", "X", &nwip_universe, 62 }, - { "unknown-63", "X", &nwip_universe, 63 }, - { "unknown-64", "X", &nwip_universe, 64 }, - { "unknown-65", "X", &nwip_universe, 65 }, - { "unknown-66", "X", &nwip_universe, 66 }, - { "unknown-67", "X", &nwip_universe, 67 }, - { "unknown-68", "X", &nwip_universe, 68 }, - { "unknown-69", "X", &nwip_universe, 69 }, - { "unknown-70", "X", &nwip_universe, 70 }, - { "unknown-71", "X", &nwip_universe, 71 }, - { "unknown-72", "X", &nwip_universe, 72 }, - { "unknown-73", "X", &nwip_universe, 73 }, - { "unknown-74", "X", &nwip_universe, 74 }, - { "unknown-75", "X", &nwip_universe, 75 }, - { "unknown-76", "X", &nwip_universe, 76 }, - { "unknown-77", "X", &nwip_universe, 77 }, - { "unknown-78", "X", &nwip_universe, 78 }, - { "unknown-79", "X", &nwip_universe, 79 }, - { "unknown-80", "X", &nwip_universe, 80 }, - { "unknown-81", "X", &nwip_universe, 81 }, - { "unknown-82", "X", &nwip_universe, 82 }, - { "unknown-83", "X", &nwip_universe, 83 }, - { "unknown-84", "X", &nwip_universe, 84 }, - { "unknown-85", "X", &nwip_universe, 85 }, - { "unknown-86", "X", &nwip_universe, 86 }, - { "unknown-87", "X", &nwip_universe, 87 }, - { "unknown-88", "X", &nwip_universe, 88 }, - { "unknown-89", "X", &nwip_universe, 89 }, - { "unknown-90", "X", &nwip_universe, 90 }, - { "unknown-91", "X", &nwip_universe, 91 }, - { "unknown-92", "X", &nwip_universe, 92 }, - { "unknown-93", "X", &nwip_universe, 93 }, - { "unknown-94", "X", &nwip_universe, 94 }, - { "unknown-95", "X", &nwip_universe, 95 }, - { "unknown-96", "X", &nwip_universe, 96 }, - { "unknown-97", "X", &nwip_universe, 97 }, - { "unknown-98", "X", &nwip_universe, 98 }, - { "unknown-99", "X", &nwip_universe, 99 }, - { "unknown-100", "X", &nwip_universe, 100 }, - { "unknown-101", "X", &nwip_universe, 101 }, - { "unknown-102", "X", &nwip_universe, 102 }, - { "unknown-103", "X", &nwip_universe, 103 }, - { "unknown-104", "X", &nwip_universe, 104 }, - { "unknown-105", "X", &nwip_universe, 105 }, - { "unknown-106", "X", &nwip_universe, 106 }, - { "unknown-107", "X", &nwip_universe, 107 }, - { "unknown-108", "X", &nwip_universe, 108 }, - { "unknown-109", "X", &nwip_universe, 109 }, - { "unknown-110", "X", &nwip_universe, 110 }, - { "unknown-111", "X", &nwip_universe, 111 }, - { "unknown-112", "X", &nwip_universe, 112 }, - { "unknown-113", "X", &nwip_universe, 113 }, - { "unknown-114", "X", &nwip_universe, 114 }, - { "unknown-115", "X", &nwip_universe, 115 }, - { "unknown-116", "X", &nwip_universe, 116 }, - { "unknown-117", "X", &nwip_universe, 117 }, - { "unknown-118", "X", &nwip_universe, 118 }, - { "unknown-119", "X", &nwip_universe, 119 }, - { "unknown-120", "X", &nwip_universe, 120 }, - { "unknown-121", "X", &nwip_universe, 121 }, - { "unknown-122", "X", &nwip_universe, 122 }, - { "unknown-123", "X", &nwip_universe, 123 }, - { "unknown-124", "X", &nwip_universe, 124 }, - { "unknown-125", "X", &nwip_universe, 125 }, - { "unknown-126", "X", &nwip_universe, 126 }, - { "unknown-127", "X", &nwip_universe, 127 }, - { "unknown-128", "X", &nwip_universe, 128 }, - { "unknown-129", "X", &nwip_universe, 129 }, - { "unknown-130", "X", &nwip_universe, 130 }, - { "unknown-131", "X", &nwip_universe, 131 }, - { "unknown-132", "X", &nwip_universe, 132 }, - { "unknown-133", "X", &nwip_universe, 133 }, - { "unknown-134", "X", &nwip_universe, 134 }, - { "unknown-135", "X", &nwip_universe, 135 }, - { "unknown-136", "X", &nwip_universe, 136 }, - { "unknown-137", "X", &nwip_universe, 137 }, - { "unknown-138", "X", &nwip_universe, 138 }, - { "unknown-139", "X", &nwip_universe, 139 }, - { "unknown-140", "X", &nwip_universe, 140 }, - { "unknown-141", "X", &nwip_universe, 141 }, - { "unknown-142", "X", &nwip_universe, 142 }, - { "unknown-143", "X", &nwip_universe, 143 }, - { "unknown-144", "X", &nwip_universe, 144 }, - { "unknown-145", "X", &nwip_universe, 145 }, - { "unknown-146", "X", &nwip_universe, 146 }, - { "unknown-147", "X", &nwip_universe, 147 }, - { "unknown-148", "X", &nwip_universe, 148 }, - { "unknown-149", "X", &nwip_universe, 149 }, - { "unknown-150", "X", &nwip_universe, 150 }, - { "unknown-151", "X", &nwip_universe, 151 }, - { "unknown-152", "X", &nwip_universe, 152 }, - { "unknown-153", "X", &nwip_universe, 153 }, - { "unknown-154", "X", &nwip_universe, 154 }, - { "unknown-155", "X", &nwip_universe, 155 }, - { "unknown-156", "X", &nwip_universe, 156 }, - { "unknown-157", "X", &nwip_universe, 157 }, - { "unknown-158", "X", &nwip_universe, 158 }, - { "unknown-159", "X", &nwip_universe, 159 }, - { "unknown-160", "X", &nwip_universe, 160 }, - { "unknown-161", "X", &nwip_universe, 161 }, - { "unknown-162", "X", &nwip_universe, 162 }, - { "unknown-163", "X", &nwip_universe, 163 }, - { "unknown-164", "X", &nwip_universe, 164 }, - { "unknown-165", "X", &nwip_universe, 165 }, - { "unknown-166", "X", &nwip_universe, 166 }, - { "unknown-167", "X", &nwip_universe, 167 }, - { "unknown-168", "X", &nwip_universe, 168 }, - { "unknown-169", "X", &nwip_universe, 169 }, - { "unknown-170", "X", &nwip_universe, 170 }, - { "unknown-171", "X", &nwip_universe, 171 }, - { "unknown-172", "X", &nwip_universe, 172 }, - { "unknown-173", "X", &nwip_universe, 173 }, - { "unknown-174", "X", &nwip_universe, 174 }, - { "unknown-175", "X", &nwip_universe, 175 }, - { "unknown-176", "X", &nwip_universe, 176 }, - { "unknown-177", "X", &nwip_universe, 177 }, - { "unknown-178", "X", &nwip_universe, 178 }, - { "unknown-179", "X", &nwip_universe, 179 }, - { "unknown-180", "X", &nwip_universe, 180 }, - { "unknown-181", "X", &nwip_universe, 181 }, - { "unknown-182", "X", &nwip_universe, 182 }, - { "unknown-183", "X", &nwip_universe, 183 }, - { "unknown-184", "X", &nwip_universe, 184 }, - { "unknown-185", "X", &nwip_universe, 185 }, - { "unknown-186", "X", &nwip_universe, 186 }, - { "unknown-187", "X", &nwip_universe, 187 }, - { "unknown-188", "X", &nwip_universe, 188 }, - { "unknown-189", "X", &nwip_universe, 189 }, - { "unknown-190", "X", &nwip_universe, 190 }, - { "unknown-191", "X", &nwip_universe, 191 }, - { "unknown-192", "X", &nwip_universe, 192 }, - { "unknown-193", "X", &nwip_universe, 193 }, - { "unknown-194", "X", &nwip_universe, 194 }, - { "unknown-195", "X", &nwip_universe, 195 }, - { "unknown-196", "X", &nwip_universe, 196 }, - { "unknown-197", "X", &nwip_universe, 197 }, - { "unknown-198", "X", &nwip_universe, 198 }, - { "unknown-199", "X", &nwip_universe, 199 }, - { "unknown-200", "X", &nwip_universe, 200 }, - { "unknown-201", "X", &nwip_universe, 201 }, - { "unknown-202", "X", &nwip_universe, 202 }, - { "unknown-203", "X", &nwip_universe, 203 }, - { "unknown-204", "X", &nwip_universe, 204 }, - { "unknown-205", "X", &nwip_universe, 205 }, - { "unknown-206", "X", &nwip_universe, 206 }, - { "unknown-207", "X", &nwip_universe, 207 }, - { "unknown-208", "X", &nwip_universe, 208 }, - { "unknown-209", "X", &nwip_universe, 209 }, - { "unknown-210", "X", &nwip_universe, 210 }, - { "unknown-211", "X", &nwip_universe, 211 }, - { "unknown-212", "X", &nwip_universe, 212 }, - { "unknown-213", "X", &nwip_universe, 213 }, - { "unknown-214", "X", &nwip_universe, 214 }, - { "unknown-215", "X", &nwip_universe, 215 }, - { "unknown-216", "X", &nwip_universe, 216 }, - { "unknown-217", "X", &nwip_universe, 217 }, - { "unknown-218", "X", &nwip_universe, 218 }, - { "unknown-219", "X", &nwip_universe, 219 }, - { "unknown-220", "X", &nwip_universe, 220 }, - { "unknown-221", "X", &nwip_universe, 221 }, - { "unknown-222", "X", &nwip_universe, 222 }, - { "unknown-223", "X", &nwip_universe, 223 }, - { "unknown-224", "X", &nwip_universe, 224 }, - { "unknown-225", "X", &nwip_universe, 225 }, - { "unknown-226", "X", &nwip_universe, 226 }, - { "unknown-227", "X", &nwip_universe, 227 }, - { "unknown-228", "X", &nwip_universe, 228 }, - { "unknown-229", "X", &nwip_universe, 229 }, - { "unknown-230", "X", &nwip_universe, 230 }, - { "unknown-231", "X", &nwip_universe, 231 }, - { "unknown-232", "X", &nwip_universe, 232 }, - { "unknown-233", "X", &nwip_universe, 233 }, - { "unknown-234", "X", &nwip_universe, 234 }, - { "unknown-235", "X", &nwip_universe, 235 }, - { "unknown-236", "X", &nwip_universe, 236 }, - { "unknown-237", "X", &nwip_universe, 237 }, - { "unknown-238", "X", &nwip_universe, 238 }, - { "unknown-239", "X", &nwip_universe, 239 }, - { "unknown-240", "X", &nwip_universe, 240 }, - { "unknown-241", "X", &nwip_universe, 241 }, - { "unknown-242", "X", &nwip_universe, 242 }, - { "unknown-243", "X", &nwip_universe, 243 }, - { "unknown-244", "X", &nwip_universe, 244 }, - { "unknown-245", "X", &nwip_universe, 245 }, - { "unknown-246", "X", &nwip_universe, 246 }, - { "unknown-247", "X", &nwip_universe, 247 }, - { "unknown-248", "X", &nwip_universe, 248 }, - { "unknown-249", "X", &nwip_universe, 249 }, - { "unknown-250", "X", &nwip_universe, 250 }, - { "unknown-251", "X", &nwip_universe, 251 }, - { "unknown-252", "X", &nwip_universe, 252 }, - { "unknown-253", "X", &nwip_universe, 253 }, - { "unknown-254", "X", &nwip_universe, 254 }, - { "unknown-end", "e", &nwip_universe, 255 }, -}; - -struct universe fqdn_universe; -struct option fqdn_options [256] = { - { "pad", "", &fqdn_universe, 0 }, - { "no-client-update", "f", &fqdn_universe, 1 }, - { "server-update", "f", &fqdn_universe, 2 }, - { "encoded", "f", &fqdn_universe, 3 }, - { "rcode1", "B", &fqdn_universe, 4 }, - { "rcode2", "B", &fqdn_universe, 5 }, - { "hostname", "t", &fqdn_universe, 6 }, - { "domainname", "t", &fqdn_universe, 7 }, - { "fqdn", "t", &fqdn_universe, 8 }, - { "unknown-9", "X", &fqdn_universe, 9 }, - { "unknown-10", "X", &fqdn_universe, 10 }, - { "unknown-11", "X", &fqdn_universe, 11 }, - { "unknown-12", "X", &fqdn_universe, 12 }, - { "unknown-13", "X", &fqdn_universe, 13 }, - { "unknown-14", "X", &fqdn_universe, 14 }, - { "unknown-15", "X", &fqdn_universe, 15 }, - { "unknown-16", "X", &fqdn_universe, 16 }, - { "unknown-17", "X", &fqdn_universe, 17 }, - { "unknown-18", "X", &fqdn_universe, 18 }, - { "unknown-19", "X", &fqdn_universe, 19 }, - { "unknown-20", "X", &fqdn_universe, 20 }, - { "unknown-21", "X", &fqdn_universe, 21 }, - { "unknown-22", "X", &fqdn_universe, 22 }, - { "unknown-23", "X", &fqdn_universe, 23 }, - { "unknown-24", "X", &fqdn_universe, 24 }, - { "unknown-25", "X", &fqdn_universe, 25 }, - { "unknown-26", "X", &fqdn_universe, 26 }, - { "unknown-27", "X", &fqdn_universe, 27 }, - { "unknown-28", "X", &fqdn_universe, 28 }, - { "unknown-29", "X", &fqdn_universe, 29 }, - { "unknown-30", "X", &fqdn_universe, 30 }, - { "unknown-31", "X", &fqdn_universe, 31 }, - { "unknown-32", "X", &fqdn_universe, 32 }, - { "unknown-33", "X", &fqdn_universe, 33 }, - { "unknown-34", "X", &fqdn_universe, 34 }, - { "unknown-35", "X", &fqdn_universe, 35 }, - { "unknown-36", "X", &fqdn_universe, 36 }, - { "unknown-37", "X", &fqdn_universe, 37 }, - { "unknown-38", "X", &fqdn_universe, 38 }, - { "unknown-39", "X", &fqdn_universe, 39 }, - { "unknown-40", "X", &fqdn_universe, 40 }, - { "unknown-41", "X", &fqdn_universe, 41 }, - { "unknown-42", "X", &fqdn_universe, 42 }, - { "unknown-43", "X", &fqdn_universe, 43 }, - { "unknown-44", "X", &fqdn_universe, 44 }, - { "unknown-45", "X", &fqdn_universe, 45 }, - { "unknown-46", "X", &fqdn_universe, 46 }, - { "unknown-47", "X", &fqdn_universe, 47 }, - { "unknown-48", "X", &fqdn_universe, 48 }, - { "unknown-49", "X", &fqdn_universe, 49 }, - { "unknown-50", "X", &fqdn_universe, 50 }, - { "unknown-51", "X", &fqdn_universe, 51 }, - { "unknown-52", "X", &fqdn_universe, 52 }, - { "unknown-53", "X", &fqdn_universe, 53 }, - { "unknown-54", "X", &fqdn_universe, 54 }, - { "unknown-55", "X", &fqdn_universe, 55 }, - { "unknown-56", "X", &fqdn_universe, 56 }, - { "unknown-57", "X", &fqdn_universe, 57 }, - { "unknown-58", "X", &fqdn_universe, 58 }, - { "unknown-59", "X", &fqdn_universe, 59 }, - { "unknown-60", "X", &fqdn_universe, 60 }, - { "unknown-61", "X", &fqdn_universe, 61 }, - { "unknown-62", "X", &fqdn_universe, 62 }, - { "unknown-63", "X", &fqdn_universe, 63 }, - { "unknown-64", "X", &fqdn_universe, 64 }, - { "unknown-65", "X", &fqdn_universe, 65 }, - { "unknown-66", "X", &fqdn_universe, 66 }, - { "unknown-67", "X", &fqdn_universe, 67 }, - { "unknown-68", "X", &fqdn_universe, 68 }, - { "unknown-69", "X", &fqdn_universe, 69 }, - { "unknown-70", "X", &fqdn_universe, 70 }, - { "unknown-71", "X", &fqdn_universe, 71 }, - { "unknown-72", "X", &fqdn_universe, 72 }, - { "unknown-73", "X", &fqdn_universe, 73 }, - { "unknown-74", "X", &fqdn_universe, 74 }, - { "unknown-75", "X", &fqdn_universe, 75 }, - { "unknown-76", "X", &fqdn_universe, 76 }, - { "unknown-77", "X", &fqdn_universe, 77 }, - { "unknown-78", "X", &fqdn_universe, 78 }, - { "unknown-79", "X", &fqdn_universe, 79 }, - { "unknown-80", "X", &fqdn_universe, 80 }, - { "unknown-81", "X", &fqdn_universe, 81 }, - { "unknown-82", "X", &fqdn_universe, 82 }, - { "unknown-83", "X", &fqdn_universe, 83 }, - { "unknown-84", "X", &fqdn_universe, 84 }, - { "unknown-85", "X", &fqdn_universe, 85 }, - { "unknown-86", "X", &fqdn_universe, 86 }, - { "unknown-87", "X", &fqdn_universe, 87 }, - { "unknown-88", "X", &fqdn_universe, 88 }, - { "unknown-89", "X", &fqdn_universe, 89 }, - { "unknown-90", "X", &fqdn_universe, 90 }, - { "unknown-91", "X", &fqdn_universe, 91 }, - { "unknown-92", "X", &fqdn_universe, 92 }, - { "unknown-93", "X", &fqdn_universe, 93 }, - { "unknown-94", "X", &fqdn_universe, 94 }, - { "unknown-95", "X", &fqdn_universe, 95 }, - { "unknown-96", "X", &fqdn_universe, 96 }, - { "unknown-97", "X", &fqdn_universe, 97 }, - { "unknown-98", "X", &fqdn_universe, 98 }, - { "unknown-99", "X", &fqdn_universe, 99 }, - { "unknown-100", "X", &fqdn_universe, 100 }, - { "unknown-101", "X", &fqdn_universe, 101 }, - { "unknown-102", "X", &fqdn_universe, 102 }, - { "unknown-103", "X", &fqdn_universe, 103 }, - { "unknown-104", "X", &fqdn_universe, 104 }, - { "unknown-105", "X", &fqdn_universe, 105 }, - { "unknown-106", "X", &fqdn_universe, 106 }, - { "unknown-107", "X", &fqdn_universe, 107 }, - { "unknown-108", "X", &fqdn_universe, 108 }, - { "unknown-109", "X", &fqdn_universe, 109 }, - { "unknown-110", "X", &fqdn_universe, 110 }, - { "unknown-111", "X", &fqdn_universe, 111 }, - { "unknown-112", "X", &fqdn_universe, 112 }, - { "unknown-113", "X", &fqdn_universe, 113 }, - { "unknown-114", "X", &fqdn_universe, 114 }, - { "unknown-115", "X", &fqdn_universe, 115 }, - { "unknown-116", "X", &fqdn_universe, 116 }, - { "unknown-117", "X", &fqdn_universe, 117 }, - { "unknown-118", "X", &fqdn_universe, 118 }, - { "unknown-119", "X", &fqdn_universe, 119 }, - { "unknown-120", "X", &fqdn_universe, 120 }, - { "unknown-121", "X", &fqdn_universe, 121 }, - { "unknown-122", "X", &fqdn_universe, 122 }, - { "unknown-123", "X", &fqdn_universe, 123 }, - { "unknown-124", "X", &fqdn_universe, 124 }, - { "unknown-125", "X", &fqdn_universe, 125 }, - { "unknown-126", "X", &fqdn_universe, 126 }, - { "unknown-127", "X", &fqdn_universe, 127 }, - { "unknown-128", "X", &fqdn_universe, 128 }, - { "unknown-129", "X", &fqdn_universe, 129 }, - { "unknown-130", "X", &fqdn_universe, 130 }, - { "unknown-131", "X", &fqdn_universe, 131 }, - { "unknown-132", "X", &fqdn_universe, 132 }, - { "unknown-133", "X", &fqdn_universe, 133 }, - { "unknown-134", "X", &fqdn_universe, 134 }, - { "unknown-135", "X", &fqdn_universe, 135 }, - { "unknown-136", "X", &fqdn_universe, 136 }, - { "unknown-137", "X", &fqdn_universe, 137 }, - { "unknown-138", "X", &fqdn_universe, 138 }, - { "unknown-139", "X", &fqdn_universe, 139 }, - { "unknown-140", "X", &fqdn_universe, 140 }, - { "unknown-141", "X", &fqdn_universe, 141 }, - { "unknown-142", "X", &fqdn_universe, 142 }, - { "unknown-143", "X", &fqdn_universe, 143 }, - { "unknown-144", "X", &fqdn_universe, 144 }, - { "unknown-145", "X", &fqdn_universe, 145 }, - { "unknown-146", "X", &fqdn_universe, 146 }, - { "unknown-147", "X", &fqdn_universe, 147 }, - { "unknown-148", "X", &fqdn_universe, 148 }, - { "unknown-149", "X", &fqdn_universe, 149 }, - { "unknown-150", "X", &fqdn_universe, 150 }, - { "unknown-151", "X", &fqdn_universe, 151 }, - { "unknown-152", "X", &fqdn_universe, 152 }, - { "unknown-153", "X", &fqdn_universe, 153 }, - { "unknown-154", "X", &fqdn_universe, 154 }, - { "unknown-155", "X", &fqdn_universe, 155 }, - { "unknown-156", "X", &fqdn_universe, 156 }, - { "unknown-157", "X", &fqdn_universe, 157 }, - { "unknown-158", "X", &fqdn_universe, 158 }, - { "unknown-159", "X", &fqdn_universe, 159 }, - { "unknown-160", "X", &fqdn_universe, 160 }, - { "unknown-161", "X", &fqdn_universe, 161 }, - { "unknown-162", "X", &fqdn_universe, 162 }, - { "unknown-163", "X", &fqdn_universe, 163 }, - { "unknown-164", "X", &fqdn_universe, 164 }, - { "unknown-165", "X", &fqdn_universe, 165 }, - { "unknown-166", "X", &fqdn_universe, 166 }, - { "unknown-167", "X", &fqdn_universe, 167 }, - { "unknown-168", "X", &fqdn_universe, 168 }, - { "unknown-169", "X", &fqdn_universe, 169 }, - { "unknown-170", "X", &fqdn_universe, 170 }, - { "unknown-171", "X", &fqdn_universe, 171 }, - { "unknown-172", "X", &fqdn_universe, 172 }, - { "unknown-173", "X", &fqdn_universe, 173 }, - { "unknown-174", "X", &fqdn_universe, 174 }, - { "unknown-175", "X", &fqdn_universe, 175 }, - { "unknown-176", "X", &fqdn_universe, 176 }, - { "unknown-177", "X", &fqdn_universe, 177 }, - { "unknown-178", "X", &fqdn_universe, 178 }, - { "unknown-179", "X", &fqdn_universe, 179 }, - { "unknown-180", "X", &fqdn_universe, 180 }, - { "unknown-181", "X", &fqdn_universe, 181 }, - { "unknown-182", "X", &fqdn_universe, 182 }, - { "unknown-183", "X", &fqdn_universe, 183 }, - { "unknown-184", "X", &fqdn_universe, 184 }, - { "unknown-185", "X", &fqdn_universe, 185 }, - { "unknown-186", "X", &fqdn_universe, 186 }, - { "unknown-187", "X", &fqdn_universe, 187 }, - { "unknown-188", "X", &fqdn_universe, 188 }, - { "unknown-189", "X", &fqdn_universe, 189 }, - { "unknown-190", "X", &fqdn_universe, 190 }, - { "unknown-191", "X", &fqdn_universe, 191 }, - { "unknown-192", "X", &fqdn_universe, 192 }, - { "unknown-193", "X", &fqdn_universe, 193 }, - { "unknown-194", "X", &fqdn_universe, 194 }, - { "unknown-195", "X", &fqdn_universe, 195 }, - { "unknown-196", "X", &fqdn_universe, 196 }, - { "unknown-197", "X", &fqdn_universe, 197 }, - { "unknown-198", "X", &fqdn_universe, 198 }, - { "unknown-199", "X", &fqdn_universe, 199 }, - { "unknown-200", "X", &fqdn_universe, 200 }, - { "unknown-201", "X", &fqdn_universe, 201 }, - { "unknown-202", "X", &fqdn_universe, 202 }, - { "unknown-203", "X", &fqdn_universe, 203 }, - { "unknown-204", "X", &fqdn_universe, 204 }, - { "unknown-205", "X", &fqdn_universe, 205 }, - { "unknown-206", "X", &fqdn_universe, 206 }, - { "unknown-207", "X", &fqdn_universe, 207 }, - { "unknown-208", "X", &fqdn_universe, 208 }, - { "unknown-209", "X", &fqdn_universe, 209 }, - { "unknown-210", "X", &fqdn_universe, 210 }, - { "unknown-211", "X", &fqdn_universe, 211 }, - { "unknown-212", "X", &fqdn_universe, 212 }, - { "unknown-213", "X", &fqdn_universe, 213 }, - { "unknown-214", "X", &fqdn_universe, 214 }, - { "unknown-215", "X", &fqdn_universe, 215 }, - { "unknown-216", "X", &fqdn_universe, 216 }, - { "unknown-217", "X", &fqdn_universe, 217 }, - { "unknown-218", "X", &fqdn_universe, 218 }, - { "unknown-219", "X", &fqdn_universe, 219 }, - { "unknown-220", "X", &fqdn_universe, 220 }, - { "unknown-221", "X", &fqdn_universe, 221 }, - { "unknown-222", "X", &fqdn_universe, 222 }, - { "unknown-223", "X", &fqdn_universe, 223 }, - { "unknown-224", "X", &fqdn_universe, 224 }, - { "unknown-225", "X", &fqdn_universe, 225 }, - { "unknown-226", "X", &fqdn_universe, 226 }, - { "unknown-227", "X", &fqdn_universe, 227 }, - { "unknown-228", "X", &fqdn_universe, 228 }, - { "unknown-229", "X", &fqdn_universe, 229 }, - { "unknown-230", "X", &fqdn_universe, 230 }, - { "unknown-231", "X", &fqdn_universe, 231 }, - { "unknown-232", "X", &fqdn_universe, 232 }, - { "unknown-233", "X", &fqdn_universe, 233 }, - { "unknown-234", "X", &fqdn_universe, 234 }, - { "unknown-235", "X", &fqdn_universe, 235 }, - { "unknown-236", "X", &fqdn_universe, 236 }, - { "unknown-237", "X", &fqdn_universe, 237 }, - { "unknown-238", "X", &fqdn_universe, 238 }, - { "unknown-239", "X", &fqdn_universe, 239 }, - { "unknown-240", "X", &fqdn_universe, 240 }, - { "unknown-241", "X", &fqdn_universe, 241 }, - { "unknown-242", "X", &fqdn_universe, 242 }, - { "unknown-243", "X", &fqdn_universe, 243 }, - { "unknown-244", "X", &fqdn_universe, 244 }, - { "unknown-245", "X", &fqdn_universe, 245 }, - { "unknown-246", "X", &fqdn_universe, 246 }, - { "unknown-247", "X", &fqdn_universe, 247 }, - { "unknown-248", "X", &fqdn_universe, 248 }, - { "unknown-249", "X", &fqdn_universe, 249 }, - { "unknown-250", "X", &fqdn_universe, 250 }, - { "unknown-251", "X", &fqdn_universe, 251 }, - { "unknown-252", "X", &fqdn_universe, 252 }, - { "unknown-253", "X", &fqdn_universe, 253 }, - { "unknown-254", "X", &fqdn_universe, 254 }, - { "unknown-end", "e", &fqdn_universe, 255 }, -}; - -const char *hardware_types [] = { - "unknown-0", - "ethernet", - "unknown-2", - "unknown-3", - "unknown-4", - "unknown-5", - "token-ring", - "unknown-7", - "fddi", - "unknown-9", - "unknown-10", - "unknown-11", - "unknown-12", - "unknown-13", - "unknown-14", - "unknown-15", - "unknown-16", - "unknown-17", - "unknown-18", - "unknown-19", - "unknown-20", - "unknown-21", - "unknown-22", - "unknown-23", - "unknown-24", - "unknown-25", - "unknown-26", - "unknown-27", - "unknown-28", - "unknown-29", - "unknown-30", - "unknown-31", - "unknown-32", - "unknown-33", - "unknown-34", - "unknown-35", - "unknown-36", - "unknown-37", - "unknown-38", - "unknown-39", - "unknown-40", - "unknown-41", - "unknown-42", - "unknown-43", - "unknown-44", - "unknown-45", - "unknown-46", - "unknown-47", - "unknown-48", - "unknown-49", - "unknown-50", - "unknown-51", - "unknown-52", - "unknown-53", - "unknown-54", - "unknown-55", - "unknown-56", - "unknown-57", - "unknown-58", - "unknown-59", - "unknown-60", - "unknown-61", - "unknown-62", - "unknown-63", - "unknown-64", - "unknown-65", - "unknown-66", - "unknown-67", - "unknown-68", - "unknown-69", - "unknown-70", - "unknown-71", - "unknown-72", - "unknown-73", - "unknown-74", - "unknown-75", - "unknown-76", - "unknown-77", - "unknown-78", - "unknown-79", - "unknown-80", - "unknown-81", - "unknown-82", - "unknown-83", - "unknown-84", - "unknown-85", - "unknown-86", - "unknown-87", - "unknown-88", - "unknown-89", - "unknown-90", - "unknown-91", - "unknown-92", - "unknown-93", - "unknown-94", - "unknown-95", - "unknown-96", - "unknown-97", - "unknown-98", - "unknown-99", - "unknown-100", - "unknown-101", - "unknown-102", - "unknown-103", - "unknown-104", - "unknown-105", - "unknown-106", - "unknown-107", - "unknown-108", - "unknown-109", - "unknown-110", - "unknown-111", - "unknown-112", - "unknown-113", - "unknown-114", - "unknown-115", - "unknown-116", - "unknown-117", - "unknown-118", - "unknown-119", - "unknown-120", - "unknown-121", - "unknown-122", - "unknown-123", - "unknown-124", - "unknown-125", - "unknown-126", - "unknown-127", - "unknown-128", - "unknown-129", - "unknown-130", - "unknown-131", - "unknown-132", - "unknown-133", - "unknown-134", - "unknown-135", - "unknown-136", - "unknown-137", - "unknown-138", - "unknown-139", - "unknown-140", - "unknown-141", - "unknown-142", - "unknown-143", - "unknown-144", - "unknown-145", - "unknown-146", - "unknown-147", - "unknown-148", - "unknown-149", - "unknown-150", - "unknown-151", - "unknown-152", - "unknown-153", - "unknown-154", - "unknown-155", - "unknown-156", - "unknown-157", - "unknown-158", - "unknown-159", - "unknown-160", - "unknown-161", - "unknown-162", - "unknown-163", - "unknown-164", - "unknown-165", - "unknown-166", - "unknown-167", - "unknown-168", - "unknown-169", - "unknown-170", - "unknown-171", - "unknown-172", - "unknown-173", - "unknown-174", - "unknown-175", - "unknown-176", - "unknown-177", - "unknown-178", - "unknown-179", - "unknown-180", - "unknown-181", - "unknown-182", - "unknown-183", - "unknown-184", - "unknown-185", - "unknown-186", - "unknown-187", - "unknown-188", - "unknown-189", - "unknown-190", - "unknown-191", - "unknown-192", - "unknown-193", - "unknown-194", - "unknown-195", - "unknown-196", - "unknown-197", - "unknown-198", - "unknown-199", - "unknown-200", - "unknown-201", - "unknown-202", - "unknown-203", - "unknown-204", - "unknown-205", - "unknown-206", - "unknown-207", - "unknown-208", - "unknown-209", - "unknown-210", - "unknown-211", - "unknown-212", - "unknown-213", - "unknown-214", - "unknown-215", - "unknown-216", - "unknown-217", - "unknown-218", - "unknown-219", - "unknown-220", - "unknown-221", - "unknown-222", - "unknown-223", - "unknown-224", - "unknown-225", - "unknown-226", - "unknown-227", - "unknown-228", - "unknown-229", - "unknown-230", - "unknown-231", - "unknown-232", - "unknown-233", - "unknown-234", - "unknown-235", - "unknown-236", - "unknown-237", - "unknown-238", - "unknown-239", - "unknown-240", - "unknown-241", - "unknown-242", - "unknown-243", - "unknown-244", - "unknown-245", - "unknown-246", - "unknown-247", - "unknown-248", - "unknown-249", - "unknown-250", - "unknown-251", - "unknown-252", - "unknown-253", - "unknown-254", - "unknown-255" }; - -universe_hash_t *universe_hash; -struct universe **universes; -int universe_count, universe_max; - -/* Universe containing names of configuration options, which, rather than - writing "option universe-name.option-name ...;", can be set by writing - "option-name ...;". */ - -struct universe *config_universe; - -void initialize_common_option_spaces() -{ - int i; - - universe_max = 10; - universes = ((struct universe **) - dmalloc (universe_max * sizeof (struct universe *), MDL)); - if (!universes) - log_fatal ("Can't allocate option space table."); - memset (universes, 0, universe_max * sizeof (struct universe *)); - - /* Set up the DHCP option universe... */ - dhcp_universe.name = "dhcp"; - dhcp_universe.lookup_func = lookup_hashed_option; - dhcp_universe.option_state_dereference = - hashed_option_state_dereference; - dhcp_universe.save_func = save_hashed_option; - dhcp_universe.delete_func = delete_hashed_option; - dhcp_universe.encapsulate = hashed_option_space_encapsulate; - dhcp_universe.foreach = hashed_option_space_foreach; - dhcp_universe.decode = parse_option_buffer; - dhcp_universe.length_size = 1; - dhcp_universe.tag_size = 1; - dhcp_universe.store_tag = putUChar; - dhcp_universe.store_length = putUChar; - dhcp_universe.index = universe_count++; - universes [dhcp_universe.index] = &dhcp_universe; - if (!option_new_hash (&dhcp_universe.hash, 1, MDL)) - log_fatal ("Can't allocate dhcp option hash table."); - for (i = 0; i < 256; i++) { - dhcp_universe.options [i] = &dhcp_options [i]; - option_hash_add (dhcp_universe.hash, - dhcp_options [i].name, 0, - &dhcp_options [i], MDL); - } - - /* Set up the Novell option universe (for option 63)... */ - nwip_universe.name = "nwip"; - nwip_universe.lookup_func = lookup_linked_option; - nwip_universe.option_state_dereference = - linked_option_state_dereference; - nwip_universe.save_func = save_linked_option; - nwip_universe.delete_func = delete_linked_option; - nwip_universe.encapsulate = nwip_option_space_encapsulate; - nwip_universe.foreach = linked_option_space_foreach; - nwip_universe.decode = parse_option_buffer; - nwip_universe.length_size = 1; - nwip_universe.tag_size = 1; - nwip_universe.store_tag = putUChar; - nwip_universe.store_length = putUChar; - nwip_universe.enc_opt = &dhcp_options [DHO_NWIP_SUBOPTIONS]; - nwip_universe.index = universe_count++; - universes [nwip_universe.index] = &nwip_universe; - option_new_hash (&nwip_universe.hash, 1, MDL); - if (!nwip_universe.hash) - log_fatal ("Can't allocate nwip option hash table."); - for (i = 0; i < 256; i++) { - nwip_universe.options [i] = &nwip_options [i]; - option_hash_add (nwip_universe.hash, - nwip_options [i].name, 0, - &nwip_options [i], MDL); - } - - /* Set up the FQDN option universe... */ - fqdn_universe.name = "fqdn"; - fqdn_universe.lookup_func = lookup_linked_option; - fqdn_universe.option_state_dereference = - linked_option_state_dereference; - fqdn_universe.save_func = save_linked_option; - fqdn_universe.delete_func = delete_linked_option; - fqdn_universe.encapsulate = fqdn_option_space_encapsulate; - fqdn_universe.foreach = linked_option_space_foreach; - fqdn_universe.decode = fqdn_universe_decode; - fqdn_universe.length_size = 1; - fqdn_universe.tag_size = 1; - fqdn_universe.store_tag = putUChar; - fqdn_universe.store_length = putUChar; - fqdn_universe.index = universe_count++; - fqdn_universe.enc_opt = &dhcp_options [DHO_FQDN]; - universes [fqdn_universe.index] = &fqdn_universe; - option_new_hash (&fqdn_universe.hash, 1, MDL); - if (!fqdn_universe.hash) - log_fatal ("Can't allocate fqdn option hash table."); - for (i = 0; i < 256; i++) { - fqdn_universe.options [i] = &fqdn_options [i]; - option_hash_add (fqdn_universe.hash, - fqdn_options [i].name, 0, - &fqdn_options [i], MDL); - } - - /* Set up the hash of universes. */ - universe_new_hash (&universe_hash, 1, MDL); - universe_hash_add (universe_hash, - dhcp_universe.name, 0, - &dhcp_universe, MDL); - universe_hash_add (universe_hash, - nwip_universe.name, 0, - &nwip_universe, MDL); - universe_hash_add (universe_hash, - fqdn_universe.name, 0, - &fqdn_universe, MDL); -} diff --git a/contrib/isc-dhcp/common/tr.c b/contrib/isc-dhcp/common/tr.c deleted file mode 100644 index c3f097b..0000000 --- a/contrib/isc-dhcp/common/tr.c +++ /dev/null @@ -1,335 +0,0 @@ -/* tr.c - - token ring interface support - Contributed in May of 1999 by Andrew Chittenden */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - */ - -#ifndef lint -static char copyright[] = -"$Id: tr.c,v 1.7.2.2 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (HAVE_TR_SUPPORT) && \ - (defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING)) -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" -#include "netinet/if_tr.h" -#include <sys/time.h> - -/* - * token ring device handling subroutines. These are required as token-ring - * does not have a simple on-the-wire header but requires the use of - * source routing - */ - -static int insert_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface)); -static void save_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface)); -static void expire_routes PROTO ((void)); - -/* - * As we keep a list of interesting routing information only, a singly - * linked list is all we need - */ -struct routing_entry { - struct routing_entry *next; - unsigned char addr[TR_ALEN]; - unsigned char iface[5]; - __u16 rcf; /* route control field */ - __u16 rseg[8]; /* routing registers */ - unsigned long access_time; /* time we last used this entry */ -}; - -static struct routing_entry *routing_info = NULL; - -static int routing_timeout = 10; -static struct timeval routing_timer; - -void assemble_tr_header (interface, buf, bufix, to) - struct interface_info *interface; - unsigned char *buf; - unsigned *bufix; - struct hardware *to; -{ - struct trh_hdr *trh; - int hdr_len; - struct trllc *llc; - - - /* set up the token header */ - trh = (struct trh_hdr *) &buf[*bufix]; - if (interface -> hw_address.hlen - 1 == sizeof (trh->saddr)) - memcpy (trh->saddr, &interface -> hw_address.hbuf [1], - sizeof (trh->saddr)); - else - memset (trh->saddr, 0x00, sizeof (trh->saddr)); - - if (to && to -> hlen == 7) /* XXX */ - memcpy (trh->daddr, &to -> hbuf [1], sizeof trh->daddr); - else - memset (trh->daddr, 0xff, sizeof (trh->daddr)); - - hdr_len = insert_source_routing (trh, interface); - - trh->ac = AC; - trh->fc = LLC_FRAME; - - /* set up the llc header for snap encoding after the tr header */ - llc = (struct trllc *)(buf + *bufix + hdr_len); - llc->dsap = EXTENDED_SAP; - llc->ssap = EXTENDED_SAP; - llc->llc = UI_CMD; - llc->protid[0] = 0; - llc->protid[1] = 0; - llc->protid[2] = 0; - llc->ethertype = htons(ETHERTYPE_IP); - - hdr_len += sizeof(struct trllc); - - *bufix += hdr_len; -} - - -static unsigned char tr_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -/* - * decoding the token header is a bit complex as you can see here. It is - * further complicated by the linux kernel stripping off some valuable - * information (see comment below) even though we've asked for the raw - * packets. - */ -ssize_t decode_tr_header (interface, buf, bufix, from) - struct interface_info *interface; - unsigned char *buf; - unsigned bufix; - struct hardware *from; -{ - struct trh_hdr *trh = (struct trh_hdr *) buf + bufix; - struct trllc *llc; - struct ip *ip; - struct udphdr *udp; - unsigned int route_len = 0; - ssize_t hdr_len; - struct timeval now; - - /* see whether any source routing information has expired */ - gettimeofday(&now, NULL); - - if (routing_timer.tv_sec == 0) - routing_timer.tv_sec = now.tv_sec + routing_timeout; - else if ((now.tv_sec - routing_timer.tv_sec) > 0) - expire_routes(); - - /* the kernel might have stripped off the source - * routing bit. We try a heuristic to determine whether - * this is the case and put it back on if so - */ - route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; - llc = (struct trllc *)(buf + bufix + sizeof(struct trh_hdr)-TR_MAXRIFLEN+route_len); - if (llc->dsap == EXTENDED_SAP - && llc->ssap == EXTENDED_SAP - && llc->llc == UI_CMD - && llc->protid[0] == 0 - && llc->protid[1] == 0 - && llc->protid[2] == 0) { - /* say there is source routing information present */ - trh->saddr[0] |= TR_RII; - } - - if (trh->saddr[0] & TR_RII) - route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; - else - route_len = 0; - - hdr_len = sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len; - - /* now filter out unwanted packets: this is based on the packet - * filter code in bpf.c */ - llc = (struct trllc *)(buf + bufix + hdr_len); - ip = (struct ip *) (llc + 1); - udp = (struct udphdr *) ((unsigned char*) ip + IP_HL (ip)); - - /* make sure it is a snap encoded, IP, UDP, unfragmented packet sent - * to our port */ - if (llc->dsap != EXTENDED_SAP - || ntohs(llc->ethertype) != ETHERTYPE_IP - || ip->ip_p != IPPROTO_UDP - || (ntohs (ip->ip_off) & IP_OFFMASK) != 0 - || udp->uh_dport != local_port) - return -1; - - /* only save source routing information for packets from valued hosts */ - save_source_routing(trh, interface); - - return hdr_len + sizeof (struct trllc); -} - -/* insert_source_routing inserts source route information into the token ring - * header - */ -static int insert_source_routing (trh, interface) - struct trh_hdr *trh; - struct interface_info* interface; -{ - struct routing_entry *rover; - struct timeval now; - unsigned int route_len = 0; - - gettimeofday(&now, NULL); - - /* single route broadcasts as per rfc 1042 */ - if (memcmp(trh->daddr, tr_broadcast,TR_ALEN) == 0) { - trh->saddr[0] |= TR_RII; - trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK; - trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); - trh->rcf = htons(trh->rcf); - } else { - /* look for a routing entry */ - for (rover = routing_info; rover != NULL; rover = rover->next) { - if (memcmp(rover->addr, trh->daddr, TR_ALEN) == 0) - break; - } - - if (rover != NULL) { - /* success: route that frame */ - if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) { - __u16 rcf = rover->rcf; - memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg)); - rcf ^= TR_RCF_DIR_BIT; - rcf &= ~TR_RCF_BROADCAST_MASK; - trh->rcf = htons(rcf); - trh->saddr[0] |= TR_RII; - } - rover->access_time = now.tv_sec; - } else { - /* we don't have any routing information so send a - * limited broadcast */ - trh->saddr[0] |= TR_RII; - trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK; - trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); - trh->rcf = htons(trh->rcf); - } - } - - /* return how much of the header we've actually used */ - if (trh->saddr[0] & TR_RII) - route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; - else - route_len = 0; - - return sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len; -} - -/* - * save any source routing information - */ -static void save_source_routing(trh, interface) - struct trh_hdr *trh; - struct interface_info *interface; -{ - struct routing_entry *rover; - struct timeval now; - unsigned char saddr[TR_ALEN]; - __u16 rcf = 0; - - gettimeofday(&now, NULL); - - memcpy(saddr, trh->saddr, sizeof(saddr)); - saddr[0] &= 0x7f; /* strip off source routing present flag */ - - /* scan our table to see if we've got it */ - for (rover = routing_info; rover != NULL; rover = rover->next) { - if (memcmp(&rover->addr[0], &saddr[0], TR_ALEN) == 0) - break; - } - - /* found an entry so update it with fresh information */ - if (rover != NULL) { - if ((trh->saddr[0] & TR_RII) && - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) { - rcf = ntohs(trh->rcf); - rcf &= ~TR_RCF_BROADCAST_MASK; - memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg)); - } - rover->rcf = rcf; - rover->access_time = now.tv_sec; - return; /* that's all folks */ - } - - /* no entry found, so create one */ - rover = dmalloc (sizeof (struct routing_entry), MDL); - if (rover == NULL) { - fprintf(stderr, - "%s: unable to save source routing information\n", - __FILE__); - return; - } - - memcpy(rover->addr, saddr, sizeof(rover->addr)); - memcpy(rover->iface, interface->name, 5); - rover->access_time = now.tv_sec; - if (trh->saddr[0] & TR_RII) { - if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) { - rcf = ntohs(trh->rcf); - rcf &= ~TR_RCF_BROADCAST_MASK; - memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg)); - } - rover->rcf = rcf; - } - - /* insert into list */ - rover->next = routing_info; - routing_info = rover; - - return; -} - -/* - * get rid of old routes - */ -static void expire_routes() -{ - struct routing_entry *rover; - struct routing_entry **prover = &routing_info; - struct timeval now; - - gettimeofday(&now, NULL); - - while((rover = *prover) != NULL) { - if ((now.tv_sec - rover->access_time) > routing_timeout) { - *prover = rover->next; - dfree (rover, MDL); - } else - prover = &rover->next; - } - - /* Reset the timer */ - routing_timer.tv_sec = now.tv_sec + routing_timeout; - routing_timer.tv_usec = now.tv_usec; -} - -#endif diff --git a/contrib/isc-dhcp/common/tree.c b/contrib/isc-dhcp/common/tree.c deleted file mode 100644 index ab357fb..0000000 --- a/contrib/isc-dhcp/common/tree.c +++ /dev/null @@ -1,4095 +0,0 @@ -/* tree.c - - Routines for manipulating parse trees... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: tree.c,v 1.101.2.9 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include <omapip/omapip_p.h> - -struct binding_scope *global_scope; - -static int do_host_lookup PROTO ((struct data_string *, - struct dns_host_entry *)); - -#ifdef NSUPDATE -struct __res_state resolver_state; -int resolver_inited = 0; -#endif - -pair cons (car, cdr) - caddr_t car; - pair cdr; -{ - pair foo = (pair)dmalloc (sizeof *foo, MDL); - if (!foo) - log_fatal ("no memory for cons."); - foo -> car = car; - foo -> cdr = cdr; - return foo; -} - -int make_const_option_cache (oc, buffer, data, len, option, file, line) - struct option_cache **oc; - struct buffer **buffer; - u_int8_t *data; - unsigned len; - struct option *option; - const char *file; - int line; -{ - struct buffer *bp; - - if (buffer) { - bp = *buffer; - *buffer = 0; - } else { - bp = (struct buffer *)0; - if (!buffer_allocate (&bp, len, file, line)) { - log_error ("%s(%d): can't allocate buffer.", - file, line); - return 0; - } - } - - if (!option_cache_allocate (oc, file, line)) { - log_error ("%s(%d): can't allocate option cache.", file, line); - buffer_dereference (&bp, file, line); - return 0; - } - - (*oc) -> data.len = len; - (*oc) -> data.buffer = bp; - (*oc) -> data.data = &bp -> data [0]; - (*oc) -> data.terminated = 0; - if (data) - memcpy (&bp -> data [0], data, len); - (*oc) -> option = option; - return 1; -} - -int make_host_lookup (expr, name) - struct expression **expr; - const char *name; -{ - if (!expression_allocate (expr, MDL)) { - log_error ("No memory for host lookup tree node."); - return 0; - } - (*expr) -> op = expr_host_lookup; - if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) { - expression_dereference (expr, MDL); - return 0; - } - return 1; -} - -int enter_dns_host (dh, name) - struct dns_host_entry **dh; - const char *name; -{ - /* XXX This should really keep a hash table of hostnames - XXX and just add a new reference to a hostname that - XXX already exists, if possible, rather than creating - XXX a new structure. */ - if (!dns_host_entry_allocate (dh, name, MDL)) { - log_error ("Can't allocate space for new host."); - return 0; - } - return 1; -} - -int make_const_data (struct expression **expr, const unsigned char *data, - unsigned len, int terminated, int allocate, - const char *file, int line) -{ - struct expression *nt; - - if (!expression_allocate (expr, file, line)) { - log_error ("No memory for make_const_data tree node."); - return 0; - } - nt = *expr; - - if (len) { - if (allocate) { - if (!buffer_allocate (&nt -> data.const_data.buffer, - len + terminated, file, line)) { - log_error ("Can't allocate const_data buffer"); - expression_dereference (expr, file, line); - return 0; - } - nt -> data.const_data.data = - &nt -> data.const_data.buffer -> data [0]; - memcpy (nt -> data.const_data.buffer -> data, - data, len + terminated); - } else - nt -> data.const_data.data = data; - nt -> data.const_data.terminated = terminated; - } else - nt -> data.const_data.data = 0; - - nt -> op = expr_const_data; - nt -> data.const_data.len = len; - return 1; -} - -int make_const_int (expr, val) - struct expression **expr; - unsigned long val; -{ - if (!expression_allocate (expr, MDL)) { - log_error ("No memory for make_const_int tree node."); - return 0; - } - - (*expr) -> op = expr_const_int; - (*expr) -> data.const_int = val; - return 1; -} - -int make_concat (expr, left, right) - struct expression **expr; - struct expression *left, *right; -{ - /* If we're concatenating a null tree to a non-null tree, just - return the non-null tree; if both trees are null, return - a null tree. */ - if (!left) { - if (!right) - return 0; - expression_reference (expr, right, MDL); - return 1; - } - if (!right) { - expression_reference (expr, left, MDL); - return 1; - } - - /* Otherwise, allocate a new node to concatenate the two. */ - if (!expression_allocate (expr, MDL)) { - log_error ("No memory for concatenation expression node."); - return 0; - } - - (*expr) -> op = expr_concat; - expression_reference (&(*expr) -> data.concat [0], left, MDL); - expression_reference (&(*expr) -> data.concat [1], right, MDL); - return 1; -} - -int make_encapsulation (expr, name) - struct expression **expr; - struct data_string *name; -{ - /* Allocate a new node to store the encapsulation. */ - if (!expression_allocate (expr, MDL)) { - log_error ("No memory for encapsulation expression node."); - return 0; - } - - (*expr) -> op = expr_encapsulate; - data_string_copy (&(*expr) -> data.encapsulate, name, MDL); - return 1; -} - -int make_substring (new, expr, offset, length) - struct expression **new; - struct expression *expr; - struct expression *offset; - struct expression *length; -{ - /* Allocate an expression node to compute the substring. */ - if (!expression_allocate (new, MDL)) { - log_error ("no memory for substring expression."); - return 0; - } - (*new) -> op = expr_substring; - expression_reference (&(*new) -> data.substring.expr, expr, MDL); - expression_reference (&(*new) -> data.substring.offset, offset, MDL); - expression_reference (&(*new) -> data.substring.len, length, MDL); - return 1; -} - -int make_limit (new, expr, limit) - struct expression **new; - struct expression *expr; - int limit; -{ - struct expression *rv; - - /* Allocate a node to enforce a limit on evaluation. */ - if (!expression_allocate (new, MDL)) - log_error ("no memory for limit expression"); - (*new) -> op = expr_substring; - expression_reference (&(*new) -> data.substring.expr, expr, MDL); - - /* Offset is a constant 0. */ - if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) { - log_error ("no memory for limit offset expression"); - expression_dereference (new, MDL); - return 0; - } - (*new) -> data.substring.offset -> op = expr_const_int; - (*new) -> data.substring.offset -> data.const_int = 0; - - /* Length is a constant: the specified limit. */ - if (!expression_allocate (&(*new) -> data.substring.len, MDL)) { - log_error ("no memory for limit length expression"); - expression_dereference (new, MDL); - return 0; - } - (*new) -> data.substring.len -> op = expr_const_int; - (*new) -> data.substring.len -> data.const_int = limit; - - return 1; -} - -int option_cache (struct option_cache **oc, struct data_string *dp, - struct expression *expr, struct option *option, - const char *file, int line) -{ - if (!option_cache_allocate (oc, file, line)) - return 0; - if (dp) - data_string_copy (&(*oc) -> data, dp, file, line); - if (expr) - expression_reference (&(*oc) -> expression, expr, file, line); - (*oc) -> option = option; - return 1; -} - -int make_let (result, name) - struct executable_statement **result; - const char *name; -{ - if (!(executable_statement_allocate (result, MDL))) - return 0; - - (*result) -> op = let_statement; - (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL); - if (!(*result) -> data.let.name) { - executable_statement_dereference (result, MDL); - return 0; - } - strcpy ((*result) -> data.let.name, name); - return 1; -} - -static int do_host_lookup (result, dns) - struct data_string *result; - struct dns_host_entry *dns; -{ - struct hostent *h; - unsigned i, count; - unsigned new_len; - -#ifdef DEBUG_EVAL - log_debug ("time: now = %d dns = %d diff = %d", - cur_time, dns -> timeout, cur_time - dns -> timeout); -#endif - - /* If the record hasn't timed out, just copy the data and return. */ - if (cur_time <= dns -> timeout) { -#ifdef DEBUG_EVAL - log_debug ("easy copy: %d %s", - dns -> data.len, - (dns -> data.len > 4 - ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) - : 0)); -#endif - data_string_copy (result, &dns -> data, MDL); - return 1; - } -#ifdef DEBUG_EVAL - log_debug ("Looking up %s", dns -> hostname); -#endif - - /* Otherwise, look it up... */ - h = gethostbyname (dns -> hostname); - if (!h) { -#ifndef NO_H_ERRNO - switch (h_errno) { - case HOST_NOT_FOUND: -#endif - log_error ("%s: host unknown.", dns -> hostname); -#ifndef NO_H_ERRNO - break; - case TRY_AGAIN: - log_error ("%s: temporary name server failure", - dns -> hostname); - break; - case NO_RECOVERY: - log_error ("%s: name server failed", dns -> hostname); - break; - case NO_DATA: - log_error ("%s: no A record associated with address", - dns -> hostname); - } -#endif /* !NO_H_ERRNO */ - - /* Okay to try again after a minute. */ - dns -> timeout = cur_time + 60; - data_string_forget (&dns -> data, MDL); - return 0; - } - -#ifdef DEBUG_EVAL - log_debug ("Lookup succeeded; first address is %s", - inet_ntoa (h -> h_addr_list [0])); -#endif - - /* Count the number of addresses we got... */ - for (count = 0; h -> h_addr_list [count]; count++) - ; - - /* Dereference the old data, if any. */ - data_string_forget (&dns -> data, MDL); - - /* Do we need to allocate more memory? */ - new_len = count * h -> h_length; - if (!buffer_allocate (&dns -> data.buffer, new_len, MDL)) - { - log_error ("No memory for %s.", dns -> hostname); - return 0; - } - - dns -> data.data = &dns -> data.buffer -> data [0]; - dns -> data.len = new_len; - dns -> data.terminated = 0; - - /* Addresses are conveniently stored one to the buffer, so we - have to copy them out one at a time... :'( */ - for (i = 0; i < count; i++) { - memcpy (&dns -> data.buffer -> data [h -> h_length * i], - h -> h_addr_list [i], (unsigned)(h -> h_length)); - } -#ifdef DEBUG_EVAL - log_debug ("dns -> data: %x h -> h_addr_list [0]: %x", - *(int *)(dns -> buffer), h -> h_addr_list [0]); -#endif - - /* XXX Set the timeout for an hour from now. - XXX This should really use the time on the DNS reply. */ - dns -> timeout = cur_time + 3600; - -#ifdef DEBUG_EVAL - log_debug ("hard copy: %d %s", dns -> data.len, - (dns -> data.len > 4 - ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0)); -#endif - data_string_copy (result, &dns -> data, MDL); - return 1; -} - -int evaluate_expression (result, packet, lease, client_state, - in_options, cfg_options, scope, expr, file, line) - struct binding_value **result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct expression *expr; - const char *file; - int line; -{ - struct binding_value *bv; - int status; - struct binding *binding; - - bv = (struct binding_value *)0; - - if (expr -> op == expr_variable_reference) { - if (!scope || !*scope) - return 0; - - binding = find_binding (*scope, expr -> data.variable); - - if (binding && binding -> value) { - if (result) - binding_value_reference (result, - binding -> value, - file, line); - return 1; - } else - return 0; - } else if (expr -> op == expr_funcall) { - struct string_list *s; - struct expression *arg; - struct binding_scope *ns; - struct binding *nb; - - if (!scope || !*scope) { - log_error ("%s: no such function.", - expr -> data.funcall.name); - return 0; - } - - binding = find_binding (*scope, expr -> data.funcall.name); - - if (!binding || !binding -> value) { - log_error ("%s: no such function.", - expr -> data.funcall.name); - return 0; - } - if (binding -> value -> type != binding_function) { - log_error ("%s: not a function.", - expr -> data.funcall.name); - return 0; - } - - /* Create a new binding scope in which to define - the arguments to the function. */ - ns = (struct binding_scope *)0; - if (!binding_scope_allocate (&ns, MDL)) { - log_error ("%s: can't allocate argument scope.", - expr -> data.funcall.name); - return 0; - } - - arg = expr -> data.funcall.arglist; - s = binding -> value -> value.fundef -> args; - while (arg && s) { - nb = dmalloc (sizeof *nb, MDL); - if (!nb) { - blb: - binding_scope_dereference (&ns, MDL); - return 0; - } else { - memset (nb, 0, sizeof *nb); - nb -> name = dmalloc (strlen (s -> string) + 1, - MDL); - if (nb -> name) - strcpy (nb -> name, s -> string); - else { - dfree (nb, MDL); - nb = (struct binding *)0; - goto blb; - } - } - evaluate_expression (&nb -> value, packet, lease, - client_state, - in_options, cfg_options, scope, - arg -> data.arg.val, file, line); - nb -> next = ns -> bindings; - ns -> bindings = nb; - arg = arg -> data.arg.next; - s = s -> next; - } - if (arg) { - log_error ("%s: too many arguments.", - expr -> data.funcall.name); - binding_scope_dereference (&ns, MDL); - return 0; - } - if (s) { - log_error ("%s: too few arguments.", - expr -> data.funcall.name); - binding_scope_dereference (&ns, MDL); - return 0; - } - - if (scope && *scope) - binding_scope_reference (&ns -> outer, *scope, MDL); - - status = (execute_statements - (&bv, packet, - lease, client_state, in_options, cfg_options, &ns, - binding -> value -> value.fundef -> statements)); - binding_scope_dereference (&ns, MDL); - - if (!bv) - return 1; - } else if (is_boolean_expression (expr)) { - if (!binding_value_allocate (&bv, MDL)) - return 0; - bv -> type = binding_boolean; - status = (evaluate_boolean_expression - (&bv -> value.boolean, packet, lease, client_state, - in_options, cfg_options, scope, expr)); - } else if (is_numeric_expression (expr)) { - if (!binding_value_allocate (&bv, MDL)) - return 0; - bv -> type = binding_numeric; - status = (evaluate_numeric_expression - (&bv -> value.intval, packet, lease, client_state, - in_options, cfg_options, scope, expr)); - } else if (is_data_expression (expr)) { - if (!binding_value_allocate (&bv, MDL)) - return 0; - bv -> type = binding_data; - status = (evaluate_data_expression - (&bv -> value.data, packet, lease, client_state, - in_options, cfg_options, scope, expr, MDL)); - } else if (is_dns_expression (expr)) { -#if defined (NSUPDATE) - if (!binding_value_allocate (&bv, MDL)) - return 0; - bv -> type = binding_dns; - status = (evaluate_dns_expression - (&bv -> value.dns, packet, lease, client_state, - in_options, cfg_options, scope, expr)); -#endif - } else { - log_error ("%s: invalid expression type: %d", - "evaluate_expression", expr -> op); - return 0; - } - if (result && status) - binding_value_reference (result, bv, file, line); - binding_value_dereference (&bv, MDL); - - return status; -} - -int binding_value_dereference (struct binding_value **v, - const char *file, int line) -{ - struct binding_value *bv = *v; - - *v = (struct binding_value *)0; - - /* Decrement the reference count. If it's nonzero, we're - done. */ - --(bv -> refcnt); - rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC); - if (bv -> refcnt > 0) - return 1; - if (bv -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (bv); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - switch (bv -> type) { - case binding_boolean: - case binding_numeric: - break; - case binding_data: - if (bv -> value.data.buffer) - data_string_forget (&bv -> value.data, file, line); - break; - case binding_dns: -#if defined (NSUPDATE) - if (bv -> value.dns) { - if (bv -> value.dns -> r_data) { - dfree (bv -> value.dns -> r_data_ephem, MDL); - bv -> value.dns -> r_data = (unsigned char *)0; - bv -> value.dns -> r_data_ephem = - (unsigned char *)0; - } - minires_freeupdrec (bv -> value.dns); - } - break; -#endif - default: - log_error ("%s(%d): invalid binding type: %d", - file, line, bv -> type); - return 0; - } - dfree (bv, file, line); - return 1; -} - -#if defined (NSUPDATE) -int evaluate_dns_expression (result, packet, lease, client_state, in_options, - cfg_options, scope, expr) - ns_updrec **result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct expression *expr; -{ - ns_updrec *foo; - unsigned long ttl = 0; - char *tname; - struct data_string name, data; - int r0, r1, r2, r3; - - if (!result || *result) { - log_error ("evaluate_dns_expression called with non-null %s", - "result pointer"); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - switch (expr -> op) { -#if defined (NSUPDATE) - case expr_ns_add: - r0 = evaluate_numeric_expression (&ttl, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.ns_add.ttl); - goto nsfinish; - - case expr_ns_exists: - ttl = 1; - - case expr_ns_delete: - case expr_ns_not_exists: - r0 = 1; - nsfinish: - memset (&name, 0, sizeof name); - r1 = evaluate_data_expression (&name, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.ns_add.rrname, - MDL); - if (r1) { - /* The result of the evaluation may or may not - be NUL-terminated, but we need it - terminated for sure, so we have to allocate - a buffer and terminate it. */ - tname = dmalloc (name.len + 1, MDL); - if (!tname) { - r2 = 0; - r1 = 0; - data_string_forget (&name, MDL); - } else { - memcpy (tname, name.data, name.len); - tname [name.len] = 0; - memset (&data, 0, sizeof data); - r2 = evaluate_data_expression - (&data, packet, lease, client_state, - in_options, cfg_options, scope, - expr -> data.ns_add.rrdata, MDL); - } - } else - r2 = 0; - if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) { - *result = minires_mkupdrec (((expr -> op == expr_ns_add || - expr -> op == expr_ns_delete) - ? S_UPDATE : S_PREREQ), - tname, - expr -> data.ns_add.rrclass, - expr -> data.ns_add.rrtype, - ttl); - if (!*result) { - ngood: - if (r2) { - data_string_forget (&data, MDL); - r2 = 0; - } - } else { - if (data.len) { - /* As a special case, if we get exactly - four bytes of data, it's an IP address - represented as a 32-bit quantity, which - is actually what we *should* be getting - here. Because res_mkupdrec is currently - broken and expects a dotted quad, convert - it. This should be fixed when the new - resolver is merged. */ - if (data.len == 4) { - (*result) -> r_data_ephem = - dmalloc (16, MDL); - if (!(*result) -> r_data_ephem) - goto dpngood; - (*result) -> r_data = - (*result) -> r_data_ephem; - /*%Audit% 16 bytes max. %2004.06.17,Safe%*/ - sprintf ((char *)(*result) -> r_data_ephem, - "%u.%u.%u.%u", - data.data [0] & 0xff, - data.data [1] & 0xff, - data.data [2] & 0xff, - data.data [3] & 0xff); - (*result) -> r_size = - strlen ((const char *) - (*result) -> r_data); - } else { - (*result) -> r_size = data.len; - (*result) -> r_data_ephem = - dmalloc (data.len, MDL); - if (!(*result) -> r_data_ephem) { - dpngood: /* double plus ungood. */ - minires_freeupdrec (*result); - *result = 0; - goto ngood; - } - (*result) -> r_data = - (*result) -> r_data_ephem; - memcpy ((*result) -> r_data_ephem, - data.data, data.len); - } - } else { - (*result) -> r_data = 0; - (*result) -> r_size = 0; - } - switch (expr -> op) { - case expr_ns_add: - (*result) -> r_opcode = ADD; - break; - case expr_ns_delete: - (*result) -> r_opcode = DELETE; - break; - case expr_ns_exists: - (*result) -> r_opcode = YXRRSET; - break; - case expr_ns_not_exists: - (*result) -> r_opcode = NXRRSET; - break; - - /* Can't happen, but satisfy gcc. */ - default: - break; - } - } - } - if (r1) { - data_string_forget (&name, MDL); - dfree (tname, MDL); - } - if (r2) - data_string_forget (&data, MDL); - /* One flaw in the thinking here: an IP address and an - ASCII string both look like data expressions, but - for A records, we want an ASCII string, not a - binary IP address. Do I need to turn binary IP - addresses into a seperate type? */ - return (r0 && r1 && - (r2 || expr -> op != expr_ns_add) && *result); - -#else - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - return 0; -#endif - case expr_funcall: - log_error ("%s: dns values for functions not supported.", - expr -> data.funcall.name); - break; - - case expr_variable_reference: - log_error ("%s: dns values for variables not supported.", - expr -> data.variable); - break; - - case expr_check: - case expr_equal: - case expr_not_equal: - case expr_and: - case expr_or: - case expr_not: - case expr_match: - case expr_static: - case expr_known: - case expr_exists: - case expr_variable_exists: - log_error ("Boolean opcode in evaluate_dns_expression: %d", - expr -> op); - return 0; - - case expr_none: - case expr_substring: - case expr_suffix: - case expr_option: - case expr_hardware: - case expr_const_data: - case expr_packet: - case expr_concat: - case expr_encapsulate: - case expr_host_lookup: - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - case expr_binary_to_ascii: - case expr_reverse: - case expr_filename: - case expr_sname: - case expr_pick_first_value: - case expr_host_decl_name: - case expr_config_option: - case expr_leased_address: - case expr_null: - log_error ("Data opcode in evaluate_dns_expression: %d", - expr -> op); - return 0; - - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - case expr_const_int: - case expr_lease_time: - case expr_dns_transaction: - case expr_add: - case expr_subtract: - case expr_multiply: - case expr_divide: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - log_error ("Numeric opcode in evaluate_dns_expression: %d", - expr -> op); - return 0; - - case expr_function: - log_error ("Function opcode in evaluate_dns_expression: %d", - expr -> op); - return 0; - - case expr_arg: - break; - } - - log_error ("Bogus opcode in evaluate_dns_expression: %d", - expr -> op); - return 0; -} -#endif /* defined (NSUPDATE) */ - -int evaluate_boolean_expression (result, packet, lease, client_state, - in_options, cfg_options, scope, expr) - int *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct expression *expr; -{ - struct data_string left, right; - struct data_string rrtype, rrname, rrdata; - unsigned long ttl; - int srrtype, srrname, srrdata, sttl; - int bleft, bright; - int sleft, sright; - struct binding *binding; - struct binding_value *bv, *obv; - - switch (expr -> op) { - case expr_check: - *result = check_collection (packet, lease, - expr -> data.check); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: check (%s) returns %s", - expr -> data.check -> name, - *result ? "true" : "false"); -#endif - return 1; - - case expr_equal: - case expr_not_equal: - bv = obv = (struct binding_value *)0; - sleft = evaluate_expression (&bv, packet, lease, client_state, - in_options, cfg_options, scope, - expr -> data.equal [0], MDL); - sright = evaluate_expression (&obv, packet, lease, - client_state, in_options, - cfg_options, scope, - expr -> data.equal [1], MDL); - if (sleft && sright) { - if (bv -> type != obv -> type) - *result = expr -> op == expr_not_equal; - else { - switch (obv -> type) { - case binding_boolean: - if (bv -> value.boolean == obv -> value.boolean) - *result = expr -> op == expr_equal; - else - *result = expr -> op == expr_not_equal; - break; - - case binding_data: - if ((bv -> value.data.len == - obv -> value.data.len) && - !memcmp (bv -> value.data.data, - obv -> value.data.data, - obv -> value.data.len)) - *result = expr -> op == expr_equal; - else - *result = expr -> op == expr_not_equal; - break; - - case binding_numeric: - if (bv -> value.intval == obv -> value.intval) - *result = expr -> op == expr_equal; - else - *result = expr -> op == expr_not_equal; - break; - - case binding_dns: -#if defined (NSUPDATE) - /* XXX This should be a comparison for equal - XXX values, not for identity. */ - if (bv -> value.dns == obv -> value.dns) - *result = expr -> op == expr_equal; - else - *result = expr -> op == expr_not_equal; -#else - *result = expr -> op == expr_not_equal; -#endif - break; - - case binding_function: - if (bv -> value.fundef == obv -> value.fundef) - *result = expr -> op == expr_equal; - else - *result = expr -> op == expr_not_equal; - break; - default: - *result = expr -> op == expr_not_equal; - break; - } - } - } else if (!sleft && !sright) - *result = expr -> op == expr_equal; - else - *result = expr -> op == expr_not_equal; - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: %sequal = %s", - expr -> op == expr_not_equal ? "not" : "", - (*result ? "true" : "false")); -#endif - if (sleft) - binding_value_dereference (&bv, MDL); - if (sright) - binding_value_dereference (&obv, MDL); - return 1; - - case expr_and: - sleft = evaluate_boolean_expression (&bleft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - if (sleft && bleft) - sright = evaluate_boolean_expression - (&bright, packet, lease, client_state, - in_options, cfg_options, - scope, expr -> data.and [1]); - else - sright = bright = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: and (%s, %s) = %s", - sleft ? (bleft ? "true" : "false") : "NULL", - sright ? (bright ? "true" : "false") : "NULL", - ((sleft && sright) - ? (bleft && bright ? "true" : "false") : "NULL")); -#endif - if (sleft && sright) { - *result = bleft && bright; - return 1; - } - return 0; - - case expr_or: - bleft = bright = 0; - sleft = evaluate_boolean_expression (&bleft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.or [0]); - if (!sleft || !bleft) - sright = evaluate_boolean_expression - (&bright, packet, lease, client_state, - in_options, cfg_options, - scope, expr -> data.or [1]); - else - sright = 0; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: or (%s, %s) = %s", - sleft ? (bleft ? "true" : "false") : "NULL", - sright ? (bright ? "true" : "false") : "NULL", - ((sleft || sright) - ? (bleft || bright ? "true" : "false") : "NULL")); -#endif - if (sleft || sright) { - *result = bleft || bright; - return 1; - } - return 0; - - case expr_not: - sleft = evaluate_boolean_expression (&bleft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.not); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: not (%s) = %s", - sleft ? (bleft ? "true" : "false") : "NULL", - ((sleft && sright) - ? (!bleft ? "true" : "false") : "NULL")); - -#endif - if (sleft) { - *result = !bleft; - return 1; - } - return 0; - - case expr_exists: - memset (&left, 0, sizeof left); - if (!in_options || - !get_option (&left, expr -> data.exists -> universe, - packet, lease, client_state, - in_options, cfg_options, in_options, - scope, expr -> data.exists -> code, MDL)) - *result = 0; - else { - *result = 1; - data_string_forget (&left, MDL); - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: exists %s.%s = %s", - expr -> data.option -> universe -> name, - expr -> data.option -> name, - *result ? "true" : "false"); -#endif - return 1; - - case expr_known: - if (!packet) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: known = NULL"); -#endif - return 0; - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: known = %s", - packet -> known ? "true" : "false"); -#endif - *result = packet -> known; - return 1; - - case expr_static: - if (!lease || !(lease -> flags & STATIC_LEASE)) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: static = false (%s %s %s %d)", - lease ? "y" : "n", - (lease && (lease -> flags & STATIC_LEASE) - ? "y" : "n"), - piaddr (lease -> ip_addr), - lease ? lease -> flags : 0); -#endif - *result = 0; - return 1; - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("bool: static = true"); -#endif - *result = 1; - return 1; - - case expr_variable_exists: - if (scope && *scope) { - binding = find_binding (*scope, expr -> data.variable); - - if (binding) { - if (binding -> value) - *result = 1; - else - *result = 0; - } else - *result = 0; - } else - *result = 0; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("boolean: %s? = %s", expr -> data.variable, - *result ? "true" : "false"); -#endif - return 1; - - case expr_variable_reference: - if (scope && *scope) { - binding = find_binding (*scope, expr -> data.variable); - - if (binding && binding -> value) { - if (binding -> value -> type == - binding_boolean) { - *result = binding -> value -> value.boolean; - sleft = 1; - } else { - log_error ("binding type %d in %s.", - binding -> value -> type, - "evaluate_boolean_expression"); - sleft = 0; - } - } else - sleft = 0; - } else - sleft = 0; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("boolean: %s = %s", expr -> data.variable, - sleft ? (*result ? "true" : "false") : "NULL"); -#endif - return sleft; - - case expr_funcall: - bv = (struct binding_value *)0; - sleft = evaluate_expression (&bv, packet, lease, client_state, - in_options, cfg_options, - scope, expr, MDL); - if (sleft) { - if (bv -> type != binding_boolean) - log_error ("%s() returned type %d in %s.", - expr -> data.funcall.name, - bv -> type, - "evaluate_boolean_expression"); - else - *result = bv -> value.boolean; - binding_value_dereference (&bv, MDL); - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("boolean: %s() = %s", expr -> data.funcall.name, - sleft ? (*result ? "true" : "false") : "NULL"); -#endif - break; - - case expr_none: - case expr_match: - case expr_substring: - case expr_suffix: - case expr_option: - case expr_hardware: - case expr_const_data: - case expr_packet: - case expr_concat: - case expr_encapsulate: - case expr_host_lookup: - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - case expr_binary_to_ascii: - case expr_reverse: - case expr_pick_first_value: - case expr_host_decl_name: - case expr_config_option: - case expr_leased_address: - case expr_null: - case expr_filename: - case expr_sname: - log_error ("Data opcode in evaluate_boolean_expression: %d", - expr -> op); - return 0; - - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - case expr_const_int: - case expr_lease_time: - case expr_dns_transaction: - case expr_add: - case expr_subtract: - case expr_multiply: - case expr_divide: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - log_error ("Numeric opcode in evaluate_boolean_expression: %d", - expr -> op); - return 0; - - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - log_error ("dns opcode in evaluate_boolean_expression: %d", - expr -> op); - return 0; - - case expr_function: - log_error ("function definition in evaluate_boolean_expr"); - return 0; - - case expr_arg: - break; - } - - log_error ("Bogus opcode in evaluate_boolean_expression: %d", - expr -> op); - return 0; -} - -int evaluate_data_expression (result, packet, lease, client_state, - in_options, cfg_options, scope, expr, file, line) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct expression *expr; - const char *file; - int line; -{ - struct data_string data, other; - unsigned long offset, len, i; - int s0, s1, s2, s3; - int status; - struct binding *binding; - char *s; - struct binding_value *bv; - - switch (expr -> op) { - /* Extract N bytes starting at byte M of a data string. */ - case expr_substring: - memset (&data, 0, sizeof data); - s0 = evaluate_data_expression (&data, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.substring.expr, - MDL); - - /* Evaluate the offset and length. */ - s1 = evaluate_numeric_expression - (&offset, packet, lease, client_state, in_options, - cfg_options, scope, expr -> data.substring.offset); - s2 = evaluate_numeric_expression (&len, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.substring.len); - - if (s0 && s1 && s2) { - /* If the offset is after end of the string, - return an empty string. Otherwise, do the - adjustments and return what's left. */ - if (data.len > offset) { - data_string_copy (result, &data, file, line); - result -> len -= offset; - if (result -> len > len) { - result -> len = len; - result -> terminated = 0; - } - result -> data += offset; - } - s3 = 1; - } else - s3 = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: substring (%s, %s, %s) = %s", - s0 ? print_hex_1 (data.len, data.data, 30) : "NULL", - s1 ? print_dec_1 (offset) : "NULL", - s2 ? print_dec_2 (len) : "NULL", - (s3 ? print_hex_2 (result -> len, result -> data, 30) - : "NULL")); -#endif - if (s0) - data_string_forget (&data, MDL); - if (s3) - return 1; - return 0; - - - /* Extract the last N bytes of a data string. */ - case expr_suffix: - memset (&data, 0, sizeof data); - s0 = evaluate_data_expression (&data, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.suffix.expr, MDL); - /* Evaluate the length. */ - s1 = evaluate_numeric_expression (&len, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.suffix.len); - if (s0 && s1) { - data_string_copy (result, &data, file, line); - - /* If we are returning the last N bytes of a - string whose length is <= N, just return - the string - otherwise, compute a new - starting address and decrease the - length. */ - if (data.len > len) { - result -> data += data.len - len; - result -> len = len; - } - data_string_forget (&data, MDL); - } - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: suffix (%s, %s) = %s", - s0 ? print_hex_1 (data.len, data.data, 30) : "NULL", - s1 ? print_dec_1 (len) : "NULL", - ((s0 && s1) - ? print_hex_2 (result -> len, result -> data, 30) - : "NULL")); -#endif - return s0 && s1; - - /* Extract an option. */ - case expr_option: - if (in_options) - s0 = get_option (result, - expr -> data.option -> universe, - packet, lease, client_state, - in_options, cfg_options, in_options, - scope, expr -> data.option -> code, - file, line); - else - s0 = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: option %s.%s = %s", - expr -> data.option -> universe -> name, - expr -> data.option -> name, - s0 ? print_hex_1 (result -> len, result -> data, 60) - : "NULL"); -#endif - return s0; - - case expr_config_option: - if (cfg_options) - s0 = get_option (result, - expr -> data.option -> universe, - packet, lease, client_state, - in_options, cfg_options, cfg_options, - scope, expr -> data.option -> code, - file, line); - else - s0 = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: config-option %s.%s = %s", - expr -> data.option -> universe -> name, - expr -> data.option -> name, - s0 ? print_hex_1 (result -> len, result -> data, 60) - : "NULL"); -#endif - return s0; - - /* Combine the hardware type and address. */ - case expr_hardware: - /* On the client, hardware is our hardware. */ - if (client_state) { - memset (result, 0, sizeof *result); - result -> data = - client_state -> interface -> hw_address.hbuf; - result -> len = - client_state -> interface -> hw_address.hlen; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: hardware = %s", - print_hex_1 (result -> len, - result -> data, 60)); -#endif - return 1; - } - - /* The server cares about the client's hardware address, - so only in the case where we are examining a packet can - we return anything. */ - if (!packet || !packet -> raw) { - log_error ("data: hardware: raw packet not available"); - return 0; - } - if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) { - log_error ("data: hardware: invalid hlen (%d)\n", - packet -> raw -> hlen); - return 0; - } - result -> len = packet -> raw -> hlen + 1; - if (buffer_allocate (&result -> buffer, result -> len, - file, line)) { - result -> data = &result -> buffer -> data [0]; - result -> buffer -> data [0] = packet -> raw -> htype; - memcpy (&result -> buffer -> data [1], - packet -> raw -> chaddr, - packet -> raw -> hlen); - result -> terminated = 0; - } else { - log_error ("data: hardware: no memory for buffer."); - return 0; - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: hardware = %s", - print_hex_1 (result -> len, result -> data, 60)); -#endif - return 1; - - /* Extract part of the raw packet. */ - case expr_packet: - if (!packet || !packet -> raw) { - log_error ("data: packet: raw packet not available"); - return 0; - } - - s0 = evaluate_numeric_expression (&offset, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.packet.offset); - s1 = evaluate_numeric_expression (&len, - packet, lease, client_state, - in_options, cfg_options, - scope, - expr -> data.packet.len); - if (s0 && s1 && offset < packet -> packet_length) { - if (offset + len > packet -> packet_length) - result -> len = - packet -> packet_length - offset; - else - result -> len = len; - if (buffer_allocate (&result -> buffer, - result -> len, file, line)) { - result -> data = &result -> buffer -> data [0]; - memcpy (result -> buffer -> data, - (((unsigned char *)(packet -> raw)) - + offset), result -> len); - result -> terminated = 0; - } else { - log_error ("data: packet: no buffer memory."); - return 0; - } - s2 = 1; - } else - s2 = 0; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: packet (%ld, %ld) = %s", - offset, len, - s2 ? print_hex_1 (result -> len, - result -> data, 60) : NULL); -#endif - return s2; - - /* The encapsulation of all defined options in an - option space... */ - case expr_encapsulate: - if (cfg_options) - s0 = option_space_encapsulate - (result, packet, lease, client_state, - in_options, cfg_options, scope, - &expr -> data.encapsulate); - else - s0 = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: encapsulate (%s) = %s", - expr -> data.encapsulate.data, - s0 ? print_hex_1 (result -> len, - result -> data, 60) : "NULL"); -#endif - return s0; - - /* Some constant data... */ - case expr_const_data: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: const = %s", - print_hex_1 (expr -> data.const_data.len, - expr -> data.const_data.data, 60)); -#endif - data_string_copy (result, - &expr -> data.const_data, file, line); - return 1; - - /* Hostname lookup... */ - case expr_host_lookup: - s0 = do_host_lookup (result, expr -> data.host_lookup); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: DNS lookup (%s) = %s", - expr -> data.host_lookup -> hostname, - (s0 - ? print_dotted_quads (result -> len, result -> data) - : "NULL")); -#endif - return s0; - - /* Concatenation... */ - case expr_concat: - memset (&data, 0, sizeof data); - s0 = evaluate_data_expression (&data, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.concat [0], MDL); - memset (&other, 0, sizeof other); - s1 = evaluate_data_expression (&other, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.concat [1], MDL); - - if (s0 && s1) { - result -> len = data.len + other.len; - if (!buffer_allocate (&result -> buffer, - (result -> len + other.terminated), - file, line)) { - log_error ("data: concat: no memory"); - result -> len = 0; - data_string_forget (&data, MDL); - data_string_forget (&other, MDL); - return 0; - } - result -> data = &result -> buffer -> data [0]; - memcpy (result -> buffer -> data, data.data, data.len); - memcpy (&result -> buffer -> data [data.len], - other.data, other.len + other.terminated); - } - - if (s0) - data_string_forget (&data, MDL); - if (s1) - data_string_forget (&other, MDL); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: concat (%s, %s) = %s", - s0 ? print_hex_1 (data.len, data.data, 20) : "NULL", - s1 ? print_hex_2 (other.len, other.data, 20) : "NULL", - ((s0 && s1) - ? print_hex_3 (result -> len, result -> data, 30) - : "NULL")); -#endif - return s0 && s1; - - case expr_encode_int8: - s0 = evaluate_numeric_expression (&len, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.encode_int); - if (s0) { - result -> len = 1; - if (!buffer_allocate (&result -> buffer, - 1, file, line)) { - log_error ("data: encode_int8: no memory"); - result -> len = 0; - s0 = 0; - } else { - result -> data = &result -> buffer -> data [0]; - result -> buffer -> data [0] = len; - } - } else - result -> len = 0; - -#if defined (DEBUG_EXPRESSIONS) - if (!s0) - log_debug ("data: encode_int8 (NULL) = NULL"); - else - log_debug ("data: encode_int8 (%ld) = %s", len, - print_hex_2 (result -> len, - result -> data, 20)); -#endif - return s0; - - - case expr_encode_int16: - s0 = evaluate_numeric_expression (&len, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.encode_int); - if (s0) { - result -> len = 2; - if (!buffer_allocate (&result -> buffer, 2, - file, line)) { - log_error ("data: encode_int16: no memory"); - result -> len = 0; - s0 = 0; - } else { - result -> data = &result -> buffer -> data [0]; - putUShort (result -> buffer -> data, len); - } - } else - result -> len = 0; - -#if defined (DEBUG_EXPRESSIONS) - if (!s0) - log_debug ("data: encode_int16 (NULL) = NULL"); - else - log_debug ("data: encode_int16 (%ld) = %s", len, - print_hex_2 (result -> len, - result -> data, 20)); -#endif - return s0; - - case expr_encode_int32: - s0 = evaluate_numeric_expression (&len, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.encode_int); - if (s0) { - result -> len = 4; - if (!buffer_allocate (&result -> buffer, 4, - file, line)) { - log_error ("data: encode_int32: no memory"); - result -> len = 0; - s0 = 0; - } else { - result -> data = &result -> buffer -> data [0]; - putULong (result -> buffer -> data, len); - } - } else - result -> len = 0; - -#if defined (DEBUG_EXPRESSIONS) - if (!s0) - log_debug ("data: encode_int32 (NULL) = NULL"); - else - log_debug ("data: encode_int32 (%ld) = %s", len, - print_hex_2 (result -> len, - result -> data, 20)); -#endif - return s0; - - case expr_binary_to_ascii: - /* Evaluate the base (offset) and width (len): */ - s0 = evaluate_numeric_expression - (&offset, packet, lease, client_state, in_options, - cfg_options, scope, expr -> data.b2a.base); - s1 = evaluate_numeric_expression (&len, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.b2a.width); - - /* Evaluate the seperator string. */ - memset (&data, 0, sizeof data); - s2 = evaluate_data_expression (&data, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.b2a.seperator, - MDL); - - /* Evaluate the data to be converted. */ - memset (&other, 0, sizeof other); - s3 = evaluate_data_expression (&other, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.b2a.buffer, MDL); - - if (s0 && s1 && s2 && s3) { - unsigned buflen, i; - - if (len != 8 && len != 16 && len != 32) { - log_info ("binary_to_ascii: %s %ld!", - "invalid width", len); - goto b2a_out; - } - len /= 8; - - /* The buffer must be a multiple of the number's - width. */ - if (other.len % len) { - log_info ("binary-to-ascii: %s %d %s %ld!", - "length of buffer", other.len, - "not a multiple of width", len); - status = 0; - goto b2a_out; - } - - /* Count the width of the output. */ - buflen = 0; - for (i = 0; i < other.len; i += len) { - if (len == 1) { - if (offset == 8) { - if (other.data [i] < 8) - buflen++; - else if (other.data [i] < 64) - buflen += 2; - else - buflen += 3; - } else if (offset == 10) { - if (other.data [i] < 10) - buflen++; - else if (other.data [i] < 100) - buflen += 2; - else - buflen += 3; - } else if (offset == 16) { - if (other.data [i] < 16) - buflen++; - else - buflen += 2; - } else - buflen += (converted_length - (&other.data [i], - offset, 1)); - } else - buflen += (converted_length - (&other.data [i], - offset, len)); - if (i + len != other.len) - buflen += data.len; - } - - if (!buffer_allocate (&result -> buffer, - buflen + 1, file, line)) { - log_error ("data: binary-to-ascii: no memory"); - status = 0; - goto b2a_out; - } - result -> data = &result -> buffer -> data [0]; - result -> len = buflen; - result -> terminated = 1; - - buflen = 0; - for (i = 0; i < other.len; i += len) { - buflen += (binary_to_ascii - (&result -> buffer -> data [buflen], - &other.data [i], offset, len)); - if (i + len != other.len) { - memcpy (&result -> - buffer -> data [buflen], - data.data, data.len); - buflen += data.len; - } - } - /* NUL terminate. */ - result -> buffer -> data [buflen] = 0; - status = 1; - } else - status = 0; - - b2a_out: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s", - s0 ? print_dec_1 (offset) : "NULL", - s1 ? print_dec_2 (len) : "NULL", - s2 ? print_hex_1 (data.len, data.data, 30) : "NULL", - s3 ? print_hex_2 (other.len, other.data, 30) : "NULL", - (status ? print_hex_3 (result -> len, result -> data, 30) - : "NULL")); -#endif - if (s2) - data_string_forget (&data, MDL); - if (s3) - data_string_forget (&other, MDL); - if (status) - return 1; - return 0; - - case expr_reverse: - /* Evaluate the width (len): */ - s0 = evaluate_numeric_expression - (&len, packet, lease, client_state, in_options, - cfg_options, scope, expr -> data.reverse.width); - - /* Evaluate the data. */ - memset (&data, 0, sizeof data); - s1 = evaluate_data_expression (&data, packet, lease, - client_state, - in_options, cfg_options, scope, - expr -> data.reverse.buffer, - MDL); - - if (s0 && s1) { - char *upper; - int i; - - /* The buffer must be a multiple of the number's - width. */ - if (data.len % len) { - log_info ("reverse: %s %d %s %ld!", - "length of buffer", data.len, - "not a multiple of width", len); - status = 0; - goto reverse_out; - } - - /* XXX reverse in place? I don't think we can. */ - if (!buffer_allocate (&result -> buffer, - data.len, file, line)) { - log_error ("data: reverse: no memory"); - status = 0; - goto reverse_out; - } - result -> data = &result -> buffer -> data [0]; - result -> len = data.len; - result -> terminated = 0; - - for (i = 0; i < data.len; i += len) { - memcpy (&result -> buffer -> data [i], - &data.data [data.len - i - len], len); - } - status = 1; - } else - status = 0; - - reverse_out: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: reverse (%s, %s) = %s", - s0 ? print_dec_1 (len) : "NULL", - s1 ? print_hex_1 (data.len, data.data, 30) : "NULL", - (status ? print_hex_3 (result -> len, result -> data, 30) - : "NULL")); -#endif - if (s0) - data_string_forget (&data, MDL); - if (status) - return 1; - return 0; - - case expr_leased_address: - if (!lease) { - log_error ("data: leased_address: not available"); - return 0; - } - result -> len = lease -> ip_addr.len; - if (buffer_allocate (&result -> buffer, result -> len, - file, line)) { - result -> data = &result -> buffer -> data [0]; - memcpy (&result -> buffer -> data [0], - lease -> ip_addr.iabuf, lease -> ip_addr.len); - result -> terminated = 0; - } else { - log_error ("data: leased-address: no memory."); - return 0; - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: leased-address = %s", - print_hex_1 (result -> len, result -> data, 60)); -#endif - return 1; - - case expr_pick_first_value: - memset (&data, 0, sizeof data); - if ((evaluate_data_expression - (result, packet, - lease, client_state, in_options, cfg_options, - scope, expr -> data.pick_first_value.car, MDL))) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: pick_first_value (%s, xxx)", - print_hex_1 (result -> len, - result -> data, 40)); -#endif - return 1; - } - - if (expr -> data.pick_first_value.cdr && - (evaluate_data_expression - (result, packet, - lease, client_state, in_options, cfg_options, - scope, expr -> data.pick_first_value.cdr, MDL))) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: pick_first_value (NULL, %s)", - print_hex_1 (result -> len, - result -> data, 40)); -#endif - return 1; - } - -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: pick_first_value (NULL, NULL) = NULL"); -#endif - return 0; - - case expr_host_decl_name: - if (!lease || !lease -> host) { - log_error ("data: host_decl_name: not available"); - return 0; - } - result -> len = strlen (lease -> host -> name); - if (buffer_allocate (&result -> buffer, - result -> len + 1, file, line)) { - result -> data = &result -> buffer -> data [0]; - strcpy ((char *)&result -> buffer -> data [0], - lease -> host -> name); - result -> terminated = 1; - } else { - log_error ("data: host-decl-name: no memory."); - return 0; - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: host-decl-name = %s", lease -> host -> name); -#endif - return 1; - - case expr_null: -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: null = NULL"); -#endif - return 0; - - case expr_variable_reference: - if (scope && *scope) { - binding = find_binding (*scope, expr -> data.variable); - - if (binding && binding -> value) { - if (binding -> value -> type == binding_data) { - data_string_copy (result, - &binding -> value -> value.data, - file, line); - s0 = 1; - } else if (binding -> value -> type != binding_data) { - log_error ("binding type %d in %s.", - binding -> value -> type, - "evaluate_data_expression"); - s0 = 0; - } else - s0 = 0; - } else - s0 = 0; - } else - s0 = 0; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: %s = %s", expr -> data.variable, - s0 ? print_hex_1 (result -> len, - result -> data, 50) : "NULL"); -#endif - return s0; - - case expr_funcall: - bv = (struct binding_value *)0; - s0 = evaluate_expression (&bv, packet, lease, client_state, - in_options, cfg_options, - scope, expr, MDL); - if (s0) { - if (bv -> type != binding_data) - log_error ("%s() returned type %d in %s.", - expr -> data.funcall.name, - bv -> type, - "evaluate_data_expression"); - else - data_string_copy (result, &bv -> value.data, - file, line); - binding_value_dereference (&bv, MDL); - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: %s = %s", expr -> data.funcall.name, - s0 ? print_hex_1 (result -> len, - result -> data, 50) : "NULL"); -#endif - break; - - /* Extract the filename. */ - case expr_filename: - if (packet && packet -> raw -> file [0]) { - char *fn = - memchr (packet -> raw -> file, 0, - sizeof packet -> raw -> file); - if (!fn) - fn = ((char *)packet -> raw -> file + - sizeof packet -> raw -> file); - result -> len = fn - &(packet -> raw -> file [0]); - if (buffer_allocate (&result -> buffer, - result -> len + 1, file, line)) { - result -> data = &result -> buffer -> data [0]; - memcpy (&result -> buffer -> data [0], - packet -> raw -> file, - result -> len); - result -> buffer -> data [result -> len] = 0; - result -> terminated = 1; - s0 = 1; - } else { - log_error ("data: filename: no memory."); - s0 = 0; - } - } else - s0 = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_info ("data: filename = \"%s\"", - s0 ? (const char *)(result -> data) : "NULL"); -#endif - return s0; - - /* Extract the server name. */ - case expr_sname: - if (packet && packet -> raw -> sname [0]) { - char *fn = - memchr (packet -> raw -> sname, 0, - sizeof packet -> raw -> sname); - if (!fn) - fn = ((char *)packet -> raw -> sname + - sizeof packet -> raw -> sname); - result -> len = fn - &packet -> raw -> sname [0]; - if (buffer_allocate (&result -> buffer, - result -> len + 1, file, line)) { - result -> data = &result -> buffer -> data [0]; - memcpy (&result -> buffer -> data [0], - packet -> raw -> sname, - result -> len); - result -> buffer -> data [result -> len] = 0; - result -> terminated = 1; - s0 = 1; - } else { - log_error ("data: sname: no memory."); - s0 = 0; - } - } else - s0 = 0; - -#if defined (DEBUG_EXPRESSIONS) - log_info ("data: sname = \"%s\"", - s0 ? (const char *)(result -> data) : "NULL"); -#endif - return s0; - - case expr_check: - case expr_equal: - case expr_not_equal: - case expr_and: - case expr_or: - case expr_not: - case expr_match: - case expr_static: - case expr_known: - case expr_none: - case expr_exists: - case expr_variable_exists: - log_error ("Boolean opcode in evaluate_data_expression: %d", - expr -> op); - return 0; - - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - case expr_const_int: - case expr_lease_time: - case expr_dns_transaction: - case expr_add: - case expr_subtract: - case expr_multiply: - case expr_divide: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - log_error ("Numeric opcode in evaluate_data_expression: %d", - expr -> op); - return 0; - - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - log_error ("dns update opcode in evaluate_data_expression: %d", - expr -> op); - return 0; - - case expr_function: - log_error ("function definition in evaluate_data_expression"); - return 0; - - case expr_arg: - break; - } - - log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op); - return 0; -} - -int evaluate_numeric_expression (result, packet, lease, client_state, - in_options, cfg_options, scope, expr) - unsigned long *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct expression *expr; -{ - struct data_string data; - int status, sleft, sright; -#if defined (NSUPDATE) - ns_updrec *nut; - ns_updque uq; -#endif - struct expression *cur, *next; - struct binding *binding; - struct binding_value *bv; - unsigned long ileft, iright; - - switch (expr -> op) { - case expr_check: - case expr_equal: - case expr_not_equal: - case expr_and: - case expr_or: - case expr_not: - case expr_match: - case expr_static: - case expr_known: - case expr_none: - case expr_exists: - case expr_variable_exists: - log_error ("Boolean opcode in evaluate_numeric_expression: %d", - expr -> op); - return 0; - - case expr_substring: - case expr_suffix: - case expr_option: - case expr_hardware: - case expr_const_data: - case expr_packet: - case expr_concat: - case expr_encapsulate: - case expr_host_lookup: - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - case expr_binary_to_ascii: - case expr_reverse: - case expr_filename: - case expr_sname: - case expr_pick_first_value: - case expr_host_decl_name: - case expr_config_option: - case expr_leased_address: - case expr_null: - log_error ("Data opcode in evaluate_numeric_expression: %d", - expr -> op); - return 0; - - case expr_extract_int8: - memset (&data, 0, sizeof data); - status = evaluate_data_expression - (&data, packet, lease, client_state, in_options, - cfg_options, scope, expr -> data.extract_int, MDL); - if (status) - *result = data.data [0]; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("num: extract_int8 (%s) = %s", - status ? print_hex_1 (data.len, data.data, 60) : "NULL", - status ? print_dec_1 (*result) : "NULL" ); -#endif - if (status) data_string_forget (&data, MDL); - return status; - - case expr_extract_int16: - memset (&data, 0, sizeof data); - status = (evaluate_data_expression - (&data, packet, lease, client_state, in_options, - cfg_options, scope, expr -> data.extract_int, MDL)); - if (status && data.len >= 2) - *result = getUShort (data.data); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("num: extract_int16 (%s) = %ld", - ((status && data.len >= 2) ? - print_hex_1 (data.len, data.data, 60) : "NULL"), - *result); -#endif - if (status) data_string_forget (&data, MDL); - return (status && data.len >= 2); - - case expr_extract_int32: - memset (&data, 0, sizeof data); - status = (evaluate_data_expression - (&data, packet, lease, client_state, in_options, - cfg_options, scope, expr -> data.extract_int, MDL)); - if (status && data.len >= 4) - *result = getULong (data.data); -#if defined (DEBUG_EXPRESSIONS) - log_debug ("num: extract_int32 (%s) = %ld", - ((status && data.len >= 4) ? - print_hex_1 (data.len, data.data, 60) : "NULL"), - *result); -#endif - if (status) data_string_forget (&data, MDL); - return (status && data.len >= 4); - - case expr_const_int: - *result = expr -> data.const_int; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("number: CONSTANT = %ld", *result); -#endif - return 1; - - case expr_lease_time: - if (!lease) { - log_error ("data: leased_lease: not available"); - return 0; - } - if (lease -> ends < cur_time) { - log_error ("%s %lu when it is now %lu", - "data: lease_time: lease ends at", - (long)(lease -> ends), (long)cur_time); - return 0; - } - *result = lease -> ends - cur_time; -#if defined (DEBUG_EXPRESSIONS) - log_debug ("number: lease-time = (%lu - %lu) = %ld", - lease -> ends, - cur_time, *result); -#endif - return 1; - - case expr_dns_transaction: -#if !defined (NSUPDATE) - return 0; -#else - if (!resolver_inited) { - minires_ninit (&resolver_state); - resolver_inited = 1; - resolver_state.retrans = 1; - resolver_state.retry = 1; - } - ISC_LIST_INIT (uq); - cur = expr; - do { - next = cur -> data.dns_transaction.cdr; - nut = 0; - status = (evaluate_dns_expression - (&nut, packet, - lease, client_state, in_options, cfg_options, - scope, cur -> data.dns_transaction.car)); - if (!status) - goto dns_bad; - ISC_LIST_APPEND (uq, nut, r_link); - cur = next; - } while (next); - - /* Do the update and record the error code, if there was - an error; otherwise set it to NOERROR. */ - *result = minires_nupdate (&resolver_state, - ISC_LIST_HEAD (uq)); - status = 1; - - print_dns_status ((int)*result, &uq); - - dns_bad: - while (!ISC_LIST_EMPTY (uq)) { - ns_updrec *tmp = ISC_LIST_HEAD (uq); - ISC_LIST_UNLINK (uq, tmp, r_link); - if (tmp -> r_data_ephem) { - dfree (tmp -> r_data_ephem, MDL); - tmp -> r_data = (unsigned char *)0; - tmp -> r_data_ephem = (unsigned char *)0; - } - minires_freeupdrec (tmp); - } - return status; -#endif /* NSUPDATE */ - - case expr_variable_reference: - if (scope && *scope) { - binding = find_binding (*scope, expr -> data.variable); - - if (binding && binding -> value) { - if (binding -> value -> type == binding_numeric) { - *result = binding -> value -> value.intval; - status = 1; - } else { - log_error ("binding type %d in %s.", - binding -> value -> type, - "evaluate_numeric_expression"); - status = 0; - } - } else - status = 0; - } else - status = 0; -#if defined (DEBUG_EXPRESSIONS) - if (status) - log_debug ("numeric: %s = %ld", - expr -> data.variable, *result); - else - log_debug ("numeric: %s = NULL", - expr -> data.variable); -#endif - return status; - - case expr_funcall: - bv = (struct binding_value *)0; - status = evaluate_expression (&bv, packet, lease, - client_state, - in_options, cfg_options, - scope, expr, MDL); - if (status) { - if (bv -> type != binding_numeric) - log_error ("%s() returned type %d in %s.", - expr -> data.funcall.name, - bv -> type, - "evaluate_numeric_expression"); - else - *result = bv -> value.intval; - binding_value_dereference (&bv, MDL); - } -#if defined (DEBUG_EXPRESSIONS) - log_debug ("data: %s = %ld", expr -> data.funcall.name, - status ? *result : 0); -#endif - break; - - case expr_add: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) - log_debug ("num: %ld + %ld = %ld", - ileft, iright, ileft + iright); - else if (sleft) - log_debug ("num: %ld + NULL = NULL", ileft); - else - log_debug ("num: NULL + %ld = NULL", iright); -#endif - if (sleft && sright) { - *result = ileft + iright; - return 1; - } - return 0; - - case expr_subtract: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) - log_debug ("num: %ld - %ld = %ld", - ileft, iright, ileft - iright); - else if (sleft) - log_debug ("num: %ld - NULL = NULL", ileft); - else - log_debug ("num: NULL - %ld = NULL", iright); -#endif - if (sleft && sright) { - *result = ileft - iright; - return 1; - } - return 0; - - case expr_multiply: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) - log_debug ("num: %ld * %ld = %ld", - ileft, iright, ileft * iright); - else if (sleft) - log_debug ("num: %ld * NULL = NULL", ileft); - else - log_debug ("num: NULL * %ld = NULL", iright); -#endif - if (sleft && sright) { - *result = ileft * iright; - return 1; - } - return 0; - - case expr_divide: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) { - if (iright != 0) - log_debug ("num: %ld / %ld = %ld", - ileft, iright, ileft / iright); - else - log_debug ("num: %ld / %ld = NULL", - ileft, iright); - } else if (sleft) - log_debug ("num: %ld / NULL = NULL", ileft); - else - log_debug ("num: NULL / %ld = NULL", iright); -#endif - if (sleft && sright && iright) { - *result = ileft / iright; - return 1; - } - return 0; - - case expr_remainder: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) { - if (iright != 0) - log_debug ("num: %ld %% %ld = %ld", - ileft, iright, ileft % iright); - else - log_debug ("num: %ld %% %ld = NULL", - ileft, iright); - } else if (sleft) - log_debug ("num: %ld %% NULL = NULL", ileft); - else - log_debug ("num: NULL %% %ld = NULL", iright); -#endif - if (sleft && sright && iright) { - *result = ileft % iright; - return 1; - } - return 0; - - case expr_binary_and: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) - log_debug ("num: %ld | %ld = %ld", - ileft, iright, ileft & iright); - else if (sleft) - log_debug ("num: %ld & NULL = NULL", ileft); - else - log_debug ("num: NULL & %ld = NULL", iright); -#endif - if (sleft && sright) { - *result = ileft & iright; - return 1; - } - return 0; - - case expr_binary_or: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) - log_debug ("num: %ld | %ld = %ld", - ileft, iright, ileft | iright); - else if (sleft) - log_debug ("num: %ld | NULL = NULL", ileft); - else - log_debug ("num: NULL | %ld = NULL", iright); -#endif - if (sleft && sright) { - *result = ileft | iright; - return 1; - } - return 0; - - case expr_binary_xor: - sleft = evaluate_numeric_expression (&ileft, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [0]); - sright = evaluate_numeric_expression (&iright, packet, lease, - client_state, - in_options, cfg_options, - scope, - expr -> data.and [1]); - -#if defined (DEBUG_EXPRESSIONS) - if (sleft && sright) - log_debug ("num: %ld ^ %ld = %ld", - ileft, iright, ileft ^ iright); - else if (sleft) - log_debug ("num: %ld ^ NULL = NULL", ileft); - else - log_debug ("num: NULL ^ %ld = NULL", iright); -#endif - if (sleft && sright) { - *result = ileft ^ iright; - return 1; - } - return 0; - - case expr_client_state: - if (client_state) { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("num: client-state = %d", - client_state -> state); -#endif - *result = client_state -> state; - return 1; - } else { -#if defined (DEBUG_EXPRESSIONS) - log_debug ("num: client-state = NULL"); -#endif - return 0; - } - - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - log_error ("dns opcode in evaluate_numeric_expression: %d", - expr -> op); - return 0; - - case expr_function: - log_error ("function definition in evaluate_numeric_expr"); - return 0; - - case expr_arg: - break; - } - - log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op); - return 0; -} - -/* Return data hanging off of an option cache structure, or if there - isn't any, evaluate the expression hanging off of it and return the - result of that evaluation. There should never be both an expression - and a valid data_string. */ - -int evaluate_option_cache (result, packet, lease, client_state, - in_options, cfg_options, scope, oc, file, line) - struct data_string *result; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct option_cache *oc; - const char *file; - int line; -{ - if (oc -> data.len) { - data_string_copy (result, &oc -> data, file, line); - return 1; - } - if (!oc -> expression) - return 0; - return evaluate_data_expression (result, packet, lease, client_state, - in_options, cfg_options, scope, - oc -> expression, file, line); -} - -/* Evaluate an option cache and extract a boolean from the result, - returning the boolean. Return false if there is no data. */ - -int evaluate_boolean_option_cache (ignorep, packet, - lease, client_state, in_options, - cfg_options, scope, oc, file, line) - int *ignorep; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct option_cache *oc; - const char *file; - int line; -{ - struct data_string ds; - int result; - - /* So that we can be called with option_lookup as an argument. */ - if (!oc || !in_options) - return 0; - - memset (&ds, 0, sizeof ds); - if (!evaluate_option_cache (&ds, packet, - lease, client_state, in_options, - cfg_options, scope, oc, file, line)) - return 0; - - if (ds.len) { - result = ds.data [0]; - if (result == 2) { - result = 0; - *ignorep = 1; - } else - *ignorep = 0; - } else - result = 0; - data_string_forget (&ds, MDL); - return result; -} - - -/* Evaluate a boolean expression and return the result of the evaluation, - or FALSE if it failed. */ - -int evaluate_boolean_expression_result (ignorep, packet, lease, client_state, - in_options, cfg_options, scope, expr) - int *ignorep; - struct packet *packet; - struct lease *lease; - struct client_state *client_state; - struct option_state *in_options; - struct option_state *cfg_options; - struct binding_scope **scope; - struct expression *expr; -{ - int result; - - /* So that we can be called with option_lookup as an argument. */ - if (!expr) - return 0; - - if (!evaluate_boolean_expression (&result, packet, lease, client_state, - in_options, cfg_options, - scope, expr)) - return 0; - - if (result == 2) { - *ignorep = 1; - result = 0; - } else - *ignorep = 0; - return result; -} - - -/* Dereference an expression node, and if the reference count goes to zero, - dereference any data it refers to, and then free it. */ -void expression_dereference (eptr, file, line) - struct expression **eptr; - const char *file; - int line; -{ - struct expression *expr = *eptr; - - /* Zero the pointer. */ - *eptr = (struct expression *)0; - - /* Decrement the reference count. If it's nonzero, we're - done. */ - --(expr -> refcnt); - rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC); - if (expr -> refcnt > 0) - return; - if (expr -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (expr); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return; -#endif - } - - /* Dereference subexpressions. */ - switch (expr -> op) { - /* All the binary operators can be handled the same way. */ - case expr_equal: - case expr_not_equal: - case expr_concat: - case expr_and: - case expr_or: - case expr_add: - case expr_subtract: - case expr_multiply: - case expr_divide: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - if (expr -> data.equal [0]) - expression_dereference (&expr -> data.equal [0], - file, line); - if (expr -> data.equal [1]) - expression_dereference (&expr -> data.equal [1], - file, line); - break; - - case expr_substring: - if (expr -> data.substring.expr) - expression_dereference (&expr -> data.substring.expr, - file, line); - if (expr -> data.substring.offset) - expression_dereference (&expr -> data.substring.offset, - file, line); - if (expr -> data.substring.len) - expression_dereference (&expr -> data.substring.len, - file, line); - break; - - case expr_suffix: - if (expr -> data.suffix.expr) - expression_dereference (&expr -> data.suffix.expr, - file, line); - if (expr -> data.suffix.len) - expression_dereference (&expr -> data.suffix.len, - file, line); - break; - - case expr_not: - if (expr -> data.not) - expression_dereference (&expr -> data.not, file, line); - break; - - case expr_packet: - if (expr -> data.packet.offset) - expression_dereference (&expr -> data.packet.offset, - file, line); - if (expr -> data.packet.len) - expression_dereference (&expr -> data.packet.len, - file, line); - break; - - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - if (expr -> data.extract_int) - expression_dereference (&expr -> data.extract_int, - file, line); - break; - - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - if (expr -> data.encode_int) - expression_dereference (&expr -> data.encode_int, - file, line); - break; - - case expr_encapsulate: - case expr_const_data: - data_string_forget (&expr -> data.const_data, file, line); - break; - - case expr_host_lookup: - if (expr -> data.host_lookup) - dns_host_entry_dereference (&expr -> data.host_lookup, - file, line); - break; - - case expr_binary_to_ascii: - if (expr -> data.b2a.base) - expression_dereference (&expr -> data.b2a.base, - file, line); - if (expr -> data.b2a.width) - expression_dereference (&expr -> data.b2a.width, - file, line); - if (expr -> data.b2a.seperator) - expression_dereference (&expr -> data.b2a.seperator, - file, line); - if (expr -> data.b2a.buffer) - expression_dereference (&expr -> data.b2a.buffer, - file, line); - break; - - case expr_pick_first_value: - if (expr -> data.pick_first_value.car) - expression_dereference (&expr -> data.pick_first_value.car, - file, line); - if (expr -> data.pick_first_value.cdr) - expression_dereference (&expr -> data.pick_first_value.cdr, - file, line); - break; - - case expr_reverse: - if (expr -> data.reverse.width) - expression_dereference (&expr -> data.reverse.width, - file, line); - if (expr -> data.reverse.buffer) - expression_dereference - (&expr -> data.reverse.buffer, file, line); - break; - - case expr_dns_transaction: - if (expr -> data.dns_transaction.car) - expression_dereference (&expr -> data.dns_transaction.car, - file, line); - if (expr -> data.dns_transaction.cdr) - expression_dereference (&expr -> data.dns_transaction.cdr, - file, line); - break; - - case expr_ns_add: - if (expr -> data.ns_add.rrname) - expression_dereference (&expr -> data.ns_add.rrname, - file, line); - if (expr -> data.ns_add.rrdata) - expression_dereference (&expr -> data.ns_add.rrdata, - file, line); - if (expr -> data.ns_add.ttl) - expression_dereference (&expr -> data.ns_add.ttl, - file, line); - break; - - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - if (expr -> data.ns_delete.rrname) - expression_dereference (&expr -> data.ns_delete.rrname, - file, line); - if (expr -> data.ns_delete.rrdata) - expression_dereference (&expr -> data.ns_delete.rrdata, - file, line); - break; - - case expr_variable_reference: - case expr_variable_exists: - if (expr -> data.variable) - dfree (expr -> data.variable, file, line); - break; - - case expr_funcall: - if (expr -> data.funcall.name) - dfree (expr -> data.funcall.name, file, line); - if (expr -> data.funcall.arglist) - expression_dereference (&expr -> data.funcall.arglist, - file, line); - break; - - case expr_arg: - if (expr -> data.arg.val) - expression_dereference (&expr -> data.arg.val, - file, line); - if (expr -> data.arg.next) - expression_dereference (&expr -> data.arg.next, - file, line); - break; - - case expr_function: - fundef_dereference (&expr -> data.func, file, line); - break; - - /* No subexpressions. */ - case expr_leased_address: - case expr_lease_time: - case expr_filename: - case expr_sname: - case expr_const_int: - case expr_check: - case expr_option: - case expr_hardware: - case expr_exists: - case expr_known: - case expr_null: - break; - - default: - break; - } - free_expression (expr, MDL); -} - -int is_dns_expression (expr) - struct expression *expr; -{ - return (expr -> op == expr_ns_add || - expr -> op == expr_ns_delete || - expr -> op == expr_ns_exists || - expr -> op == expr_ns_not_exists); -} - -int is_boolean_expression (expr) - struct expression *expr; -{ - return (expr -> op == expr_check || - expr -> op == expr_exists || - expr -> op == expr_variable_exists || - expr -> op == expr_equal || - expr -> op == expr_not_equal || - expr -> op == expr_and || - expr -> op == expr_or || - expr -> op == expr_not || - expr -> op == expr_known || - expr -> op == expr_static); -} - -int is_data_expression (expr) - struct expression *expr; -{ - return (expr -> op == expr_substring || - expr -> op == expr_suffix || - expr -> op == expr_option || - expr -> op == expr_hardware || - expr -> op == expr_const_data || - expr -> op == expr_packet || - expr -> op == expr_concat || - expr -> op == expr_encapsulate || - expr -> op == expr_encode_int8 || - expr -> op == expr_encode_int16 || - expr -> op == expr_encode_int32 || - expr -> op == expr_host_lookup || - expr -> op == expr_binary_to_ascii || - expr -> op == expr_filename || - expr -> op == expr_sname || - expr -> op == expr_reverse || - expr -> op == expr_pick_first_value || - expr -> op == expr_host_decl_name || - expr -> op == expr_leased_address || - expr -> op == expr_config_option || - expr -> op == expr_null); -} - -int is_numeric_expression (expr) - struct expression *expr; -{ - return (expr -> op == expr_extract_int8 || - expr -> op == expr_extract_int16 || - expr -> op == expr_extract_int32 || - expr -> op == expr_const_int || - expr -> op == expr_lease_time || - expr -> op == expr_dns_transaction || - expr -> op == expr_add || - expr -> op == expr_subtract || - expr -> op == expr_multiply || - expr -> op == expr_divide || - expr -> op == expr_remainder || - expr -> op == expr_binary_and || - expr -> op == expr_binary_or || - expr -> op == expr_binary_xor || - expr -> op == expr_client_state); -} - -int is_compound_expression (expr) - struct expression *expr; -{ - return (expr -> op == expr_ns_add || - expr -> op == expr_ns_delete || - expr -> op == expr_ns_exists || - expr -> op == expr_ns_not_exists || - expr -> op == expr_substring || - expr -> op == expr_suffix || - expr -> op == expr_option || - expr -> op == expr_concat || - expr -> op == expr_encode_int8 || - expr -> op == expr_encode_int16 || - expr -> op == expr_encode_int32 || - expr -> op == expr_binary_to_ascii || - expr -> op == expr_reverse || - expr -> op == expr_pick_first_value || - expr -> op == expr_config_option || - expr -> op == expr_extract_int8 || - expr -> op == expr_extract_int16 || - expr -> op == expr_extract_int32 || - expr -> op == expr_dns_transaction); -} - -static int op_val PROTO ((enum expr_op)); - -static int op_val (op) - enum expr_op op; -{ - switch (op) { - case expr_none: - case expr_match: - case expr_static: - case expr_check: - case expr_substring: - case expr_suffix: - case expr_concat: - case expr_encapsulate: - case expr_host_lookup: - case expr_not: - case expr_option: - case expr_hardware: - case expr_packet: - case expr_const_data: - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - case expr_const_int: - case expr_exists: - case expr_variable_exists: - case expr_known: - case expr_binary_to_ascii: - case expr_reverse: - case expr_filename: - case expr_sname: - case expr_pick_first_value: - case expr_host_decl_name: - case expr_config_option: - case expr_leased_address: - case expr_lease_time: - case expr_dns_transaction: - case expr_null: - case expr_variable_reference: - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - case expr_arg: - case expr_funcall: - case expr_function: - /* XXXDPN: Need to assign sane precedences to these. */ - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - return 100; - - case expr_equal: - case expr_not_equal: - return 3; - - case expr_and: - case expr_multiply: - case expr_divide: - case expr_remainder: - return 1; - - case expr_or: - case expr_add: - case expr_subtract: - return 2; - } - return 100; -} - -int op_precedence (op1, op2) - enum expr_op op1, op2; -{ - int ov1, ov2; - - return op_val (op1) - op_val (op2); -} - -enum expression_context expression_context (struct expression *expr) -{ - if (is_data_expression (expr)) - return context_data; - if (is_numeric_expression (expr)) - return context_numeric; - if (is_boolean_expression (expr)) - return context_boolean; - if (is_dns_expression (expr)) - return context_dns; - return context_any; -} - -enum expression_context op_context (op) - enum expr_op op; -{ - switch (op) { -/* XXX Why aren't these specific? */ - case expr_none: - case expr_match: - case expr_static: - case expr_check: - case expr_substring: - case expr_suffix: - case expr_concat: - case expr_encapsulate: - case expr_host_lookup: - case expr_not: - case expr_option: - case expr_hardware: - case expr_packet: - case expr_const_data: - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - case expr_const_int: - case expr_exists: - case expr_variable_exists: - case expr_known: - case expr_binary_to_ascii: - case expr_reverse: - case expr_filename: - case expr_sname: - case expr_pick_first_value: - case expr_host_decl_name: - case expr_config_option: - case expr_leased_address: - case expr_lease_time: - case expr_null: - case expr_variable_reference: - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - case expr_dns_transaction: - case expr_arg: - case expr_funcall: - case expr_function: - return context_any; - - case expr_equal: - case expr_not_equal: - return context_data; - - case expr_and: - return context_boolean; - - case expr_or: - return context_boolean; - - case expr_add: - case expr_subtract: - case expr_multiply: - case expr_divide: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - return context_numeric; - } - return context_any; -} - -int write_expression (file, expr, col, indent, firstp) - FILE *file; - struct expression *expr; - int col; - int indent; - int firstp; -{ - struct expression *e; - const char *s; - char obuf [65]; - int scol; - int width; - - /* If this promises to be a fat expression, start a new line. */ - if (!firstp && is_compound_expression (expr)) { - indent_spaces (file, indent); - col = indent; - } - - switch (expr -> op) { - case expr_none: - col = token_print_indent (file, col, indent, "", "", "null"); - break; - - case expr_check: - col = token_print_indent (file, col, indent, "", "", "check"); - col = token_print_indent_concat (file, col, indent, - " ", "", "\"", - expr -> data.check -> name, - "\"", (char *)0); - break; - - case expr_not_equal: - s = "!="; - goto binary; - - case expr_equal: - s = "="; - binary: - col = write_expression (file, expr -> data.equal [0], - col, indent, 1); - col = token_print_indent (file, col, indent, " ", " ", s); - col = write_expression (file, expr -> data.equal [1], - col, indent + 2, 0); - break; - - case expr_substring: - col = token_print_indent (file, col, indent, "", "", - "substring"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - col = write_expression (file, expr -> data.substring.expr, - col, scol, 1); - col = token_print_indent (file, col, indent, "", " ", ","); - col = write_expression (file, expr -> data.substring.offset, - col, indent, 0); - col = token_print_indent (file, col, scol, "", " ", ","); - col = write_expression (file, expr -> data.substring.len, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_suffix: - col = token_print_indent (file, col, indent, "", "", "suffix"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - col = write_expression (file, expr -> data.suffix.expr, - col, scol, 1); - col = token_print_indent (file, col, scol, "", " ", ","); - col = write_expression (file, expr -> data.suffix.len, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_concat: - e = expr; - col = token_print_indent (file, col, indent, "", "", - "concat"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - firstp = 1; - concat_again: - col = write_expression (file, e -> data.concat [0], - col, scol, firstp); - firstp = 0; - if (!e -> data.concat [1]) - goto no_concat_cdr; - col = token_print_indent (file, col, scol, "", " ", ","); - if (e -> data.concat [1] -> op == expr_concat) { - e = e -> data.concat [1]; - goto concat_again; - } - col = write_expression (file, e -> data.concat [1], - col, scol, 0); - no_concat_cdr: - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_host_lookup: - col = token_print_indent (file, col, indent, "", "", - "gethostbyname"); - col = token_print_indent (file, col, indent, " ", "", "("); - col = token_print_indent_concat - (file, col, indent, "", "", - "\"", expr -> data.host_lookup -> hostname, "\"", - (char *)0); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_add: - s = "+"; - goto binary; - - case expr_subtract: - s = "-"; - goto binary; - - case expr_multiply: - s = "*"; - goto binary; - - case expr_divide: - s = "/"; - goto binary; - - case expr_remainder: - s = "%"; - goto binary; - - case expr_binary_and: - s = "&"; - goto binary; - - case expr_binary_or: - s = "|"; - goto binary; - - case expr_binary_xor: - s = "^"; - goto binary; - - case expr_and: - s = "and"; - goto binary; - - case expr_or: - s = "or"; - goto binary; - - case expr_not: - col = token_print_indent (file, col, indent, "", " ", "not"); - col = write_expression (file, - expr -> data.not, col, indent + 2, 1); - break; - - case expr_option: - s = "option"; - - print_option_name: - col = token_print_indent (file, col, indent, "", "", s); - - if (expr -> data.option -> universe != &dhcp_universe) { - col = token_print_indent (file, col, indent, - " ", "", - (expr -> data.option -> - universe -> name)); - col = token_print_indent (file, col, indent, "", "", - "."); - col = token_print_indent (file, col, indent, "", "", - expr -> data.option -> name); - } else { - col = token_print_indent (file, col, indent, " ", "", - expr -> data.option -> name); - } - break; - - case expr_hardware: - col = token_print_indent (file, col, indent, "", "", - "hardware"); - break; - - case expr_packet: - col = token_print_indent (file, col, indent, "", "", - "packet"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - col = write_expression (file, expr -> data.packet.offset, - col, indent, 1); - col = token_print_indent (file, col, scol, "", " ", ","); - col = write_expression (file, expr -> data.packet.len, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_const_data: - col = token_indent_data_string (file, col, indent, "", "", - &expr -> data.const_data); - break; - - case expr_extract_int8: - width = 8; - extract_int: - col = token_print_indent (file, col, indent, "", "", - "extract-int"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - col = write_expression (file, expr -> data.extract_int, - col, indent, 1); - col = token_print_indent (file, col, scol, "", " ", ","); - sprintf (obuf, "%d", width); - col = token_print_indent (file, col, scol, " ", "", obuf); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_extract_int16: - width = 16; - goto extract_int; - - case expr_extract_int32: - width = 32; - goto extract_int; - - case expr_encode_int8: - width = 8; - encode_int: - col = token_print_indent (file, col, indent, "", "", - "encode-int"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - col = write_expression (file, expr -> data.extract_int, - col, indent, 1); - col = token_print_indent (file, col, scol, "", " ", ","); - sprintf (obuf, "%d", width); - col = token_print_indent (file, col, scol, " ", "", obuf); - col = token_print_indent (file, col, indent, "", "", - ")"); - break; - - case expr_encode_int16: - width = 16; - goto encode_int; - - case expr_encode_int32: - width = 32; - goto encode_int; - - case expr_const_int: - sprintf (obuf, "%lu", expr -> data.const_int); - col = token_print_indent (file, col, indent, "", "", obuf); - break; - - case expr_exists: - s = "exists"; - goto print_option_name; - - case expr_encapsulate: - col = token_print_indent (file, col, indent, "", "", - "encapsulate"); - col = token_indent_data_string (file, col, indent, " ", "", - &expr -> data.encapsulate); - break; - - case expr_known: - col = token_print_indent (file, col, indent, "", "", "known"); - break; - - case expr_reverse: - col = token_print_indent (file, col, indent, "", "", - "reverse"); - col = token_print_indent (file, col, indent, " ", "", "("); - scol = col; - col = write_expression (file, expr -> data.reverse.width, - col, scol, 1); - col = token_print_indent (file, col, scol, "", " ", ","); - col = write_expression (file, expr -> data.reverse.buffer, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", - ")"); - break; - - case expr_leased_address: - col = token_print_indent (file, col, indent, "", "", - "leased-address"); - break; - - case expr_client_state: - col = token_print_indent (file, col, indent, "", "", - "client-state"); - break; - - case expr_binary_to_ascii: - col = token_print_indent (file, col, indent, "", "", - "binary-to-ascii"); - col = token_print_indent (file, col, indent, " ", "", - "("); - scol = col; - col = write_expression (file, expr -> data.b2a.base, - col, scol, 1); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.b2a.width, - col, scol, 0); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.b2a.seperator, - col, scol, 0); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.b2a.buffer, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", - ")"); - break; - - case expr_config_option: - s = "config-option"; - goto print_option_name; - - case expr_host_decl_name: - col = token_print_indent (file, col, indent, "", "", - "host-decl-name"); - break; - - case expr_pick_first_value: - e = expr; - col = token_print_indent (file, col, indent, "", "", - "concat"); - col = token_print_indent (file, col, indent, " ", "", - "("); - scol = col; - firstp = 1; - pick_again: - col = write_expression (file, - e -> data.pick_first_value.car, - col, scol, firstp); - firstp = 0; - /* We're being very lisp-like right now - instead of - representing this expression as (first middle . last) we're - representing it as (first middle last), which means that the - tail cdr is always nil. Apologies to non-wisp-lizards - may - this obscure way of describing the problem motivate you to - learn more about the one true computing language. */ - if (!e -> data.pick_first_value.cdr) - goto no_pick_cdr; - col = token_print_indent (file, col, scol, "", " ", - ","); - if (e -> data.pick_first_value.cdr -> op == - expr_pick_first_value) { - e = e -> data.pick_first_value.cdr; - goto pick_again; - } - col = write_expression (file, - e -> data.pick_first_value.cdr, - col, scol, 0); - no_pick_cdr: - col = token_print_indent (file, col, indent, "", "", - ")"); - break; - - case expr_lease_time: - col = token_print_indent (file, col, indent, "", "", - "lease-time"); - break; - - case expr_dns_transaction: - col = token_print_indent (file, col, indent, "", "", - "ns-update"); - col = token_print_indent (file, col, indent, " ", "", - "("); - scol = 0; - for (e = expr; - e && e -> op == expr_dns_transaction; - e = e -> data.dns_transaction.cdr) { - if (!scol) { - scol = col; - firstp = 1; - } else - firstp = 0; - col = write_expression (file, - e -> data.dns_transaction.car, - col, scol, firstp); - if (e -> data.dns_transaction.cdr) - col = token_print_indent (file, col, scol, - "", " ", ","); - } - if (e) - col = write_expression (file, e, col, scol, 0); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - case expr_ns_add: - col = token_print_indent (file, col, indent, "", "", - "update"); - col = token_print_indent (file, col, indent, " ", "", - "("); - scol = col; - sprintf (obuf, "%d", expr -> data.ns_add.rrclass); - col = token_print_indent (file, col, scol, "", "", obuf); - col = token_print_indent (file, col, scol, "", " ", - ","); - sprintf (obuf, "%d", expr -> data.ns_add.rrtype); - col = token_print_indent (file, col, scol, "", "", obuf); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.ns_add.rrname, - col, scol, 0); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.ns_add.rrdata, - col, scol, 0); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.ns_add.ttl, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", - ")"); - break; - - case expr_ns_delete: - col = token_print_indent (file, col, indent, "", "", - "delete"); - col = token_print_indent (file, col, indent, " ", "", - "("); - finish_ns_small: - scol = col; - sprintf (obuf, "%d", expr -> data.ns_add.rrclass); - col = token_print_indent (file, col, scol, "", "", obuf); - col = token_print_indent (file, col, scol, "", " ", - ","); - sprintf (obuf, "%d", expr -> data.ns_add.rrtype); - col = token_print_indent (file, col, scol, "", "", obuf); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.ns_add.rrname, - col, scol, 0); - col = token_print_indent (file, col, scol, "", " ", - ","); - col = write_expression (file, expr -> data.ns_add.rrdata, - col, scol, 0); - col = token_print_indent (file, col, indent, "", "", - ")"); - break; - - case expr_ns_exists: - col = token_print_indent (file, col, indent, "", "", - "exists"); - col = token_print_indent (file, col, indent, " ", "", - "("); - goto finish_ns_small; - - case expr_ns_not_exists: - col = token_print_indent (file, col, indent, "", "", - "not exists"); - col = token_print_indent (file, col, indent, " ", "", - "("); - goto finish_ns_small; - - case expr_static: - col = token_print_indent (file, col, indent, "", "", - "static"); - break; - - case expr_null: - col = token_print_indent (file, col, indent, "", "", "null"); - break; - - case expr_variable_reference: - col = token_print_indent (file, indent, indent, "", "", - expr -> data.variable); - break; - - case expr_variable_exists: - col = token_print_indent (file, indent, indent, "", "", - "defined"); - col = token_print_indent (file, col, indent, " ", "", "("); - col = token_print_indent (file, col, indent, "", "", - expr -> data.variable); - col = token_print_indent (file, col, indent, "", "", ")"); - break; - - default: - log_fatal ("invalid expression type in print_expression: %d", - expr -> op); - } - return col; -} - -struct binding *find_binding (struct binding_scope *scope, const char *name) -{ - struct binding *bp; - struct binding_scope *s; - - for (s = scope; s; s = s -> outer) { - for (bp = s -> bindings; bp; bp = bp -> next) { - if (!strcasecmp (name, bp -> name)) { - return bp; - } - } - } - return (struct binding *)0; -} - -int free_bindings (struct binding_scope *scope, const char *file, int line) -{ - struct binding *bp, *next; - - for (bp = scope -> bindings; bp; bp = next) { - next = bp -> next; - if (bp -> name) - dfree (bp -> name, file, line); - if (bp -> value) - binding_value_dereference (&bp -> value, file, line); - dfree (bp, file, line); - } - scope -> bindings = (struct binding *)0; - return 1; -} - -int binding_scope_dereference (ptr, file, line) - struct binding_scope **ptr; - const char *file; - int line; -{ - int i; - struct binding_scope *binding_scope; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - binding_scope = *ptr; - *ptr = (struct binding_scope *)0; - --binding_scope -> refcnt; - rc_register (file, line, ptr, - binding_scope, binding_scope -> refcnt, 1, RC_MISC); - if (binding_scope -> refcnt > 0) - return 1; - - if (binding_scope -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (binding_scope); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - free_bindings (binding_scope, file, line); - if (binding_scope -> outer) - binding_scope_dereference (&binding_scope -> outer, MDL); - dfree (binding_scope, file, line); - return 1; -} - -int fundef_dereference (ptr, file, line) - struct fundef **ptr; - const char *file; - int line; -{ - struct fundef *bp = *ptr; - struct string_list *sp, *next; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (!bp) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - bp -> refcnt--; - rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC); - if (bp -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (bp); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (!bp -> refcnt) { - for (sp = bp -> args; sp; sp = next) { - next = sp -> next; - dfree (sp, file, line); - } - if (bp -> statements) - executable_statement_dereference (&bp -> statements, - file, line); - dfree (bp, file, line); - } - *ptr = (struct fundef *)0; - return 1; -} - -#if defined (NOTYET) /* Post 3.0 final. */ -int data_subexpression_length (int *rv, - struct expression *expr) -{ - int crhs, clhs, llhs, lrhs; - switch (expr -> op) { - case expr_substring: - if (expr -> data.substring.len && - expr -> data.substring.len -> op == expr_const_int) { - (*rv = - (int)expr -> data.substring.len -> data.const_int); - return 1; - } - return 0; - - case expr_packet: - case expr_suffix: - if (expr -> data.suffix.len && - expr -> data.suffix.len -> op == expr_const_int) { - (*rv = - (int)expr -> data.suffix.len -> data.const_int); - return 1; - } - return 0; - - case expr_concat: - clhs = data_subexpression_length (&llhs, - expr -> data.concat [0]); - crhs = data_subexpression_length (&lrhs, - expr -> data.concat [1]); - if (crhs == 0 || clhs == 0) - return 0; - *rv = llhs + lrhs; - return 1; - break; - - case expr_hardware: - return 0; - - case expr_const_data: - *rv = expr -> data.const_data.len; - return 2; - - case expr_reverse: - return data_subexpression_length (rv, - expr -> data.reverse.buffer); - - case expr_leased_address: - case expr_lease_time: - *rv = 4; - return 2; - - case expr_pick_first_value: - clhs = data_subexpression_length (&llhs, - expr -> data.concat [0]); - crhs = data_subexpression_length (&lrhs, - expr -> data.concat [1]); - if (crhs == 0 || clhs == 0) - return 0; - if (llhs > lrhs) - *rv = llhs; - else - *rv = lrhs; - return 1; - - case expr_binary_to_ascii: - case expr_config_option: - case expr_host_decl_name: - case expr_encapsulate: - case expr_filename: - case expr_sname: - case expr_host_lookup: - case expr_option: - case expr_none: - case expr_match: - case expr_check: - case expr_equal: - case expr_and: - case expr_or: - case expr_not: - case expr_extract_int8: - case expr_extract_int16: - case expr_extract_int32: - case expr_encode_int8: - case expr_encode_int16: - case expr_encode_int32: - case expr_const_int: - case expr_exists: - case expr_known: - case expr_dns_transaction: - case expr_static: - case expr_ns_add: - case expr_ns_delete: - case expr_ns_exists: - case expr_ns_not_exists: - case expr_not_equal: - case expr_null: - case expr_variable_exists: - case expr_variable_reference: - case expr_arg: - case expr_funcall: - case expr_function: - case expr_add: - case expr_subtract: - case expr_multiply: - case expr_divide: - case expr_remainder: - case expr_binary_and: - case expr_binary_or: - case expr_binary_xor: - case expr_client_state: - return 0; - } - return 0; -} - -int expr_valid_for_context (struct expression *expr, - enum expression_context context) -{ - /* We don't know at parse time what type of value a function may - return, so we can't flag an error on it. */ - if (expr -> op == expr_funcall || - expr -> op == expr_variable_reference) - return 1; - - switch (context) { - case context_any: - return 1; - - case context_boolean: - if (is_boolean_expression (expr)) - return 1; - return 0; - - case context_data: - if (is_data_expression (expr)) - return 1; - return 0; - - case context_numeric: - if (is_numeric_expression (expr)) - return 1; - return 0; - - case context_dns: - if (is_dns_expression (expr)) { - return 1; - } - return 0; - - case context_data_or_numeric: - if (is_numeric_expression (expr) || - is_data_expression (expr)) { - return 1; - } - return 0; - - case context_function: - if (expr -> op == expr_function) - return 1; - return 0; - } - return 0; -} -#endif /* NOTYET */ - -struct binding *create_binding (struct binding_scope **scope, const char *name) -{ - struct binding *binding; - - if (!*scope) { - if (!binding_scope_allocate (scope, MDL)) - return (struct binding *)0; - } - - binding = find_binding (*scope, name); - if (!binding) { - binding = dmalloc (sizeof *binding, MDL); - if (!binding) - return (struct binding *)0; - - memset (binding, 0, sizeof *binding); - binding -> name = dmalloc (strlen (name) + 1, MDL); - if (!binding -> name) { - dfree (binding, MDL); - return (struct binding *)0; - } - strcpy (binding -> name, name); - - binding -> next = (*scope) -> bindings; - (*scope) -> bindings = binding; - } - - return binding; -} - - -int bind_ds_value (struct binding_scope **scope, - const char *name, - struct data_string *value) -{ - struct binding *binding; - - binding = create_binding (scope, name); - if (!binding) - return 0; - - if (binding -> value) - binding_value_dereference (&binding -> value, MDL); - - if (!binding_value_allocate (&binding -> value, MDL)) - return 0; - - data_string_copy (&binding -> value -> value.data, value, MDL); - binding -> value -> type = binding_data; - - return 1; -} - - -int find_bound_string (struct data_string *value, - struct binding_scope *scope, - const char *name) -{ - struct binding *binding; - - binding = find_binding (scope, name); - if (!binding || - !binding -> value || - binding -> value -> type != binding_data) - return 0; - - if (binding -> value -> value.data.terminated) { - data_string_copy (value, &binding -> value -> value.data, MDL); - } else { - buffer_allocate (&value -> buffer, - binding -> value -> value.data.len, - MDL); - if (!value -> buffer) - return 0; - - memcpy (value -> buffer -> data, - binding -> value -> value.data.data, - binding -> value -> value.data.len); - value -> data = value -> buffer -> data; - value -> len = binding -> value -> value.data.len; - } - - return 1; -} - -int unset (struct binding_scope *scope, const char *name) -{ - struct binding *binding; - - binding = find_binding (scope, name); - if (binding) { - if (binding -> value) - binding_value_dereference - (&binding -> value, MDL); - return 1; - } - return 0; -} - -/* vim: set tabstop=8: */ diff --git a/contrib/isc-dhcp/common/upf.c b/contrib/isc-dhcp/common/upf.c deleted file mode 100644 index 72e1b29..0000000 --- a/contrib/isc-dhcp/common/upf.c +++ /dev/null @@ -1,371 +0,0 @@ -/* upf.c - - Ultrix PacketFilter interface code. */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about Internet Systems 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 lint -static char copyright[] = -"$Id: upf.c,v 1.21.2.4 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#if defined (USE_UPF_SEND) || defined (USE_UPF_RECEIVE) -#include <sys/ioctl.h> -#include <sys/uio.h> - -#include <net/pfilt.h> -#include <netinet/in_systm.h> -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#ifdef USE_UPF_SEND -void if_reinitialize_send (info) - struct interface_info *info; -{ -} -#endif - -#ifdef USE_UPF_RECEIVE -void if_reinitialize_receive (info) - struct interface_info *info; -{ -} -#endif - -/* Called by get_interface_list for each interface that's discovered. - Opens a packet filter for each interface and adds it to the select - mask. */ - -int if_register_upf (info) - struct interface_info *info; -{ - int sock; - char filename[50]; - int b; - struct endevp param; - - /* Open a UPF device */ - for (b = 0; 1; b++) { - /* %Audit% Cannot exceed 36 bytes. %2004.06.17,Safe% */ - sprintf(filename, "/dev/pf/pfilt%d", b); - - sock = open (filename, O_RDWR, 0); - if (sock < 0) { - if (errno == EBUSY) { - continue; - } else { - log_fatal ("Can't find free upf: %m"); - } - } else { - break; - } - } - - /* Set the UPF device to point at this interface. */ - if (ioctl (sock, EIOCSETIF, info -> ifp) < 0) - log_fatal ("Can't attach interface %s to upf device %s: %m", - info -> name, filename); - - /* Get the hardware address. */ - if (ioctl (sock, EIOCDEVP, ¶m) < 0) - log_fatal ("Can't get interface %s hardware address: %m", - info -> name); - - /* We only know how to do ethernet. */ - if (param.end_dev_type != ENDT_10MB) - log_fatal ("Invalid device type on network interface %s: %d", - info -> name, param.end_dev_type); - - if (param.end_addr_len != 6) - log_fatal ("Invalid hardware address length on %s: %d", - info -> name, param.end_addr_len); - - info -> hw_address.hlen = 7; - info -> hw_address.hbuf [0] = ARPHRD_ETHER; - memcpy (&info -> hw_address.hbuf [1], param.end_addr, 6); - - return sock; -} -#endif /* USE_UPF_SEND || USE_UPF_RECEIVE */ - -#ifdef USE_UPF_SEND -void if_register_send (info) - struct interface_info *info; -{ - /* If we're using the upf API for sending and receiving, - we don't need to register this interface twice. */ -#ifndef USE_UPF_RECEIVE - info -> wfdesc = if_register_upf (info, interface); -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - log_info ("Sending on UPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_send (info) - struct interface_info *info; -{ -#ifndef USE_UPF_RECEIVE - close (info -> wfdesc); -#endif - info -> wfdesc = -1; - if (!quiet_interface_discovery) - log_info ("Disabling output on UPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_UPF_SEND */ - -#ifdef USE_UPF_RECEIVE -/* Packet filter program... - XXX Changes to the filter program may require changes to the constant - offsets used in if_register_send to patch the UPF program! XXX */ - - -void if_register_receive (info) - struct interface_info *info; -{ - int flag = 1; - u_int32_t addr; - struct enfilter pf; - u_int32_t bits; - - /* Open a UPF device and hang it on this interface... */ - info -> rfdesc = if_register_upf (info); - - /* Allow the copyall flag to be set... */ - if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0) - log_fatal ("Can't set ALLOWCOPYALL: %m"); - - /* Clear all the packet filter mode bits first... */ - flag = (ENHOLDSIG | ENBATCH | ENTSTAMP | ENPROMISC | - ENNONEXCL | ENCOPYALL); - if (ioctl (info -> rfdesc, EIOCMBIC, &flag) < 0) - log_fatal ("Can't clear pfilt bits: %m"); - - /* Set the ENBATCH and ENCOPYALL bits... */ - bits = ENBATCH | ENCOPYALL; - if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) - log_fatal ("Can't set ENBATCH|ENCOPYALL: %m"); - - /* Set up the UPF filter program. */ - /* XXX Unlike the BPF filter program, this one won't work if the - XXX IP packet is fragmented or if there are options on the IP - XXX header. */ - pf.enf_Priority = 0; - pf.enf_FilterLen = 0; - - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 6; - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; - pf.enf_Filter [pf.enf_FilterLen++] = htons (ETHERTYPE_IP); - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT; - pf.enf_Filter [pf.enf_FilterLen++] = htons (IPPROTO_UDP); - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 11; - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_AND; - pf.enf_Filter [pf.enf_FilterLen++] = htons (0xFF); - pf.enf_Filter [pf.enf_FilterLen++] = ENF_CAND; - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 18; - pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; - pf.enf_Filter [pf.enf_FilterLen++] = local_port; - - if (ioctl (info -> rfdesc, EIOCSETF, &pf) < 0) - log_fatal ("Can't install packet filter program: %m"); - if (!quiet_interface_discovery) - log_info ("Listening on UPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} - -void if_deregister_receive (info) - struct interface_info *info; -{ - close (info -> rfdesc); - info -> rfdesc = -1; - if (!quiet_interface_discovery) - log_info ("Disabling input on UPF/%s/%s%s%s", - info -> name, - print_hw_addr (info -> hw_address.hbuf [0], - info -> hw_address.hlen - 1, - &info -> hw_address.hbuf [1]), - (info -> shared_network ? "/" : ""), - (info -> shared_network ? - info -> shared_network -> name : "")); -} -#endif /* USE_UPF_RECEIVE */ - -#ifdef USE_UPF_SEND -ssize_t send_packet (interface, packet, raw, len, from, to, hto) - struct interface_info *interface; - struct packet *packet; - struct dhcp_packet *raw; - size_t len; - struct in_addr from; - struct sockaddr_in *to; - struct hardware *hto; -{ - unsigned hbufp = 0, ibufp = 0; - double hw [4]; - double ip [32]; - struct iovec iov [3]; - int result; - int fudge; - - if (!strcmp (interface -> name, "fallback")) - return send_fallback (interface, packet, raw, - len, from, to, hto); - - /* Assemble the headers... */ - assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto); - assemble_udp_ip_header (interface, - (unsigned char *)ip, &ibufp, from.s_addr, - to -> sin_addr.s_addr, to -> sin_port, - (unsigned char *)raw, len); - - /* Fire it off */ - iov [0].iov_base = ((char *)hw); - iov [0].iov_len = hbufp; - iov [1].iov_base = ((char *)ip); - iov [1].iov_len = ibufp; - iov [2].iov_base = (char *)raw; - iov [2].iov_len = len; - - result = writev(interface -> wfdesc, iov, 3); - if (result < 0) - log_error ("send_packet: %m"); - return result; -} -#endif /* USE_UPF_SEND */ - -#ifdef USE_UPF_RECEIVE -ssize_t receive_packet (interface, buf, len, from, hfrom) - struct interface_info *interface; - unsigned char *buf; - size_t len; - struct sockaddr_in *from; - struct hardware *hfrom; -{ - int nread; - int length = 0; - int offset = 0; - unsigned char ibuf [1500 + sizeof (struct enstamp)]; - int bufix = 0; - - length = read (interface -> rfdesc, ibuf, sizeof ibuf); - if (length <= 0) - return length; - - bufix = sizeof (struct enstamp); - /* Decode the physical header... */ - offset = decode_hw_header (interface, ibuf, bufix, hfrom); - - /* If a physical layer checksum failed (dunno of any - physical layer that supports this, but WTH), skip this - packet. */ - if (offset < 0) { - return 0; - } - - bufix += offset; - length -= offset; - - /* Decode the IP and UDP headers... */ - offset = decode_udp_ip_header (interface, ibuf, bufix, - from, (unsigned char *)0, length); - - /* If the IP or UDP checksum was bad, skip the packet... */ - if (offset < 0) - return 0; - - bufix += offset; - length -= offset; - - /* Copy out the data in the packet... */ - memcpy (buf, &ibuf [bufix], length); - return length; -} - -int can_unicast_without_arp (ip) - struct interface_info *ip; -{ - return 1; -} - -int can_receive_unicast_unconfigured (ip) - struct interface_info *ip; -{ - return 1; -} - -int supports_multiple_interfaces (ip) - struct interface_info *ip; -{ - return 1; -} - -void maybe_setup_fallback () -{ - isc_result_t status; - struct interface_info *fbi = (struct interface_info *)0; - if (setup_fallback (&fbi, MDL)) { - if_register_fallback (fbi); - status = omapi_register_io_object ((omapi_object_t *)fbi, - if_readsocket, 0, - fallback_discard, 0, 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register I/O handle for %s: %s", - fbi -> name, isc_result_totext (status)); - interface_dereference (&fbi, MDL); - } -} -#endif |