From b05a03077c919111a1996bc750b5680d14414c50 Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Sun, 24 Jun 2001 06:05:12 +0000 Subject: dhcp 2.0pl5 merge/cleanup/deadcode slashing. still needs more eyes on this but appears to work better than what's been in-tree before for dealing with stupid dhcp servers. --- usr.sbin/dhcp/Makefile.inc | 13 +- usr.sbin/dhcp/common/alloc.c | 137 +- usr.sbin/dhcp/common/bpf.c | 131 +- usr.sbin/dhcp/common/conflex.c | 50 +- usr.sbin/dhcp/common/convert.c | 9 +- usr.sbin/dhcp/common/dhcp-options.5 | 361 +++++- usr.sbin/dhcp/common/dispatch.c | 407 +++--- usr.sbin/dhcp/common/dns.c | 399 ------ usr.sbin/dhcp/common/errwarn.c | 263 +--- usr.sbin/dhcp/common/ethernet.c | 92 ++ usr.sbin/dhcp/common/hash.c | 69 +- usr.sbin/dhcp/common/icmp.c | 27 +- usr.sbin/dhcp/common/inet.c | 28 +- usr.sbin/dhcp/common/inet_addr.c | 150 --- usr.sbin/dhcp/common/memory.c | 140 +- usr.sbin/dhcp/common/nit.c | 347 ----- usr.sbin/dhcp/common/options.c | 239 +++- usr.sbin/dhcp/common/packet.c | 136 +- usr.sbin/dhcp/common/parse.c | 50 +- usr.sbin/dhcp/common/print.c | 48 +- usr.sbin/dhcp/common/raw.c | 132 -- usr.sbin/dhcp/common/resolv.c | 201 --- usr.sbin/dhcp/common/socket.c | 158 +-- usr.sbin/dhcp/common/sysconf.c | 134 -- usr.sbin/dhcp/common/tables.c | 43 +- usr.sbin/dhcp/common/tree.c | 12 +- usr.sbin/dhcp/common/upf.c | 299 ----- usr.sbin/dhcp/dhclient/clparse.c | 79 +- usr.sbin/dhcp/dhclient/dhclient-script.8 | 61 +- usr.sbin/dhcp/dhclient/dhclient.8 | 259 ++-- usr.sbin/dhcp/dhclient/dhclient.c | 2016 ++++++++++++++++------------- usr.sbin/dhcp/dhclient/dhclient.conf | 2 +- usr.sbin/dhcp/dhclient/dhclient.conf.5 | 30 +- usr.sbin/dhcp/dhclient/dhclient.leases.5 | 5 +- usr.sbin/dhcp/includes/cf/alphaosf.h | 22 +- usr.sbin/dhcp/includes/cf/freebsd.h | 8 +- usr.sbin/dhcp/includes/cf/hpux.h | 12 + usr.sbin/dhcp/includes/cf/linux.h | 48 +- usr.sbin/dhcp/includes/cf/nextstep.h | 16 +- usr.sbin/dhcp/includes/cf/openbsd.h | 2 +- usr.sbin/dhcp/includes/cf/qnx.h | 8 + usr.sbin/dhcp/includes/cf/sample.h | 4 +- usr.sbin/dhcp/includes/cf/sunos5-5.h | 9 +- usr.sbin/dhcp/includes/cf/ultrix.h | 5 +- usr.sbin/dhcp/includes/dhcp.h | 1 + usr.sbin/dhcp/includes/dhcpd.h | 188 ++- usr.sbin/dhcp/includes/dhctoken.h | 9 +- usr.sbin/dhcp/includes/hash.h | 5 +- usr.sbin/dhcp/includes/netinet/if_ether.h | 74 -- usr.sbin/dhcp/includes/netinet/ip.h | 171 --- usr.sbin/dhcp/includes/netinet/ip_icmp.h | 182 --- usr.sbin/dhcp/includes/netinet/udp.h | 47 - usr.sbin/dhcp/includes/osdep.h | 109 +- usr.sbin/dhcp/includes/site.h | 2 +- usr.sbin/dhcp/includes/version.h | 3 + usr.sbin/dhcp/relay/dhcrelay.8 | 22 +- usr.sbin/dhcp/relay/dhcrelay.c | 162 ++- usr.sbin/dhcp/server/bootp.c | 104 +- usr.sbin/dhcp/server/confpars.c | 120 +- usr.sbin/dhcp/server/db.c | 46 +- usr.sbin/dhcp/server/dhcp.c | 732 +++++++---- usr.sbin/dhcp/server/dhcpd.8 | 39 +- usr.sbin/dhcp/server/dhcpd.c | 128 +- usr.sbin/dhcp/server/dhcpd.conf | 64 +- usr.sbin/dhcp/server/dhcpd.conf.5 | 136 +- usr.sbin/dhcp/server/dhcpd.leases.5 | 117 +- 66 files changed, 4052 insertions(+), 5070 deletions(-) delete mode 100644 usr.sbin/dhcp/common/dns.c create mode 100644 usr.sbin/dhcp/common/ethernet.c delete mode 100644 usr.sbin/dhcp/common/inet_addr.c delete mode 100644 usr.sbin/dhcp/common/nit.c delete mode 100644 usr.sbin/dhcp/common/raw.c delete mode 100644 usr.sbin/dhcp/common/resolv.c delete mode 100644 usr.sbin/dhcp/common/sysconf.c delete mode 100644 usr.sbin/dhcp/common/upf.c delete mode 100644 usr.sbin/dhcp/includes/netinet/if_ether.h delete mode 100644 usr.sbin/dhcp/includes/netinet/ip.h delete mode 100644 usr.sbin/dhcp/includes/netinet/ip_icmp.h delete mode 100644 usr.sbin/dhcp/includes/netinet/udp.h create mode 100644 usr.sbin/dhcp/includes/version.h diff --git a/usr.sbin/dhcp/Makefile.inc b/usr.sbin/dhcp/Makefile.inc index 031106d26bd..933151d6abc 100644 --- a/usr.sbin/dhcp/Makefile.inc +++ b/usr.sbin/dhcp/Makefile.inc @@ -33,10 +33,15 @@ .include .PATH: ${.CURDIR}/../common -SRCS+= raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \ - packet.c memory.c print.c options.c inet.c convert.c sysconf.c \ - tree.c tables.c hash.c alloc.c errwarn.c inet_addr.c dns.c resolv.c -CPPFLAGS+= -I${.CURDIR}/.. -I${.CURDIR}/../includes + +CLIENT_PATH = '"PATH=/usr/bin:/usr/sbin:/bin:/sbin"' + +SRCS += alloc.c dispatch.c hash.c memory.c print.c bpf.c icmp.c options.c \ + tree.c conflex.c errwarn.c inet.c packet.c socket.c convert.c \ + ethernet.c parse.c tables.c + +CPPFLAGS+= -I${.CURDIR}/.. -I${.CURDIR}/../includes \ + -DCLIENT_PATH=${CLIENT_PATH} -Wall -Werror .if exists(${.CURDIR}/../../Makefile.inc) .include "${.CURDIR}/../../Makefile.inc" diff --git a/usr.sbin/dhcp/common/alloc.c b/usr.sbin/dhcp/common/alloc.c index 8b300ced0c1..38fe5e7536a 100644 --- a/usr.sbin/dhcp/common/alloc.c +++ b/usr.sbin/dhcp/common/alloc.c @@ -3,7 +3,7 @@ Memory allocation... */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,29 +40,23 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: alloc.c,v 1.1 1998/08/18 03:43:25 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" struct dhcp_packet *dhcp_free_list; struct packet *packet_free_list; -VOIDPTR dmalloc (size, name) +void * dmalloc(size, name) int size; char *name; { - VOIDPTR foo = (VOIDPTR)malloc (size); + void *foo = calloc(size, sizeof(char)); if (!foo) warn ("No memory for %s.", name); - memset (foo, 0, size); return foo; } -void dfree (ptr, name) - VOIDPTR ptr; +void dfree(ptr, name) + void *ptr; char *name; { if (!ptr) { @@ -72,33 +66,45 @@ void dfree (ptr, name) free (ptr); } -struct packet *new_packet (name) +struct packet *new_packet(name) char *name; { struct packet *rval; - rval = (struct packet *)dmalloc (sizeof (struct packet), name); + rval = (struct packet *)dmalloc(sizeof(struct packet), name); return rval; } -struct dhcp_packet *new_dhcp_packet (name) +struct dhcp_packet *new_dhcp_packet(name) char *name; { struct dhcp_packet *rval; - rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet), - name); + rval = (struct dhcp_packet *)dmalloc(sizeof(struct dhcp_packet), + name); return rval; } -struct tree *new_tree (name) +struct tree *new_tree(name) char *name; { - struct tree *rval = dmalloc (sizeof (struct tree), name); + struct tree *rval = dmalloc(sizeof(struct tree), name); + return rval; +} + +struct string_list *new_string_list(size, name) + size_t size; + char * name; +{ + struct string_list *rval; + + rval =dmalloc(sizeof(struct string_list) + size, name); + if (rval != NULL) + rval->string = ((char *)rval) + sizeof(struct string_list); return rval; } struct tree_cache *free_tree_caches; -struct tree_cache *new_tree_cache (name) +struct tree_cache *new_tree_cache(name) char *name; { struct tree_cache *rval; @@ -106,85 +112,83 @@ struct tree_cache *new_tree_cache (name) if (free_tree_caches) { rval = free_tree_caches; free_tree_caches = - (struct tree_cache *)(rval -> value); + (struct tree_cache *)(rval->value); } else { - rval = dmalloc (sizeof (struct tree_cache), name); + rval = dmalloc(sizeof(struct tree_cache), name); if (!rval) - error ("unable to allocate tree cache for %s.", name); + error("unable to allocate tree cache for %s.", name); } return rval; } -struct hash_table *new_hash_table (count, name) +struct hash_table *new_hash_table(count, name) int count; char *name; { - struct hash_table *rval = dmalloc (sizeof (struct hash_table) - - (DEFAULT_HASH_SIZE - * sizeof (struct hash_bucket *)) - + (count - * sizeof (struct hash_bucket *)), - name); - rval -> hash_count = count; + struct hash_table *rval; + rval = dmalloc(sizeof (struct hash_table) + - (DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *)) + + (count * sizeof(struct hash_bucket *)), name); + rval->hash_count = count; return rval; } -struct hash_bucket *new_hash_bucket (name) +struct hash_bucket *new_hash_bucket(name) char *name; { - struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name); + struct hash_bucket *rval = dmalloc(sizeof(struct hash_bucket), name); return rval; } -struct lease *new_leases (n, name) +struct lease *new_leases(n, name) int n; char *name; { - struct lease *rval = dmalloc (n * sizeof (struct lease), name); + struct lease *rval = dmalloc(n * sizeof(struct lease), name); return rval; } -struct lease *new_lease (name) +struct lease *new_lease(name) char *name; { - struct lease *rval = dmalloc (sizeof (struct lease), name); + struct lease *rval = dmalloc(sizeof(struct lease), name); return rval; } -struct subnet *new_subnet (name) +struct subnet *new_subnet(name) char *name; { - struct subnet *rval = dmalloc (sizeof (struct subnet), name); + struct subnet *rval = dmalloc(sizeof(struct subnet), name); return rval; } -struct class *new_class (name) +struct class *new_class(name) char *name; { - struct class *rval = dmalloc (sizeof (struct class), name); + struct class *rval = dmalloc(sizeof(struct class), name); return rval; } -struct shared_network *new_shared_network (name) +struct shared_network *new_shared_network(name) char *name; { struct shared_network *rval = - dmalloc (sizeof (struct shared_network), name); + dmalloc (sizeof(struct shared_network), name); return rval; } -struct group *new_group (name) +struct group *new_group(name) char *name; { struct group *rval = - dmalloc (sizeof (struct group), name); + dmalloc(sizeof(struct group), name); return rval; } -struct protocol *new_protocol (name) +struct protocol *new_protocol(name) char *name; { - struct protocol *rval = dmalloc (sizeof (struct protocol), name); + struct protocol *rval = dmalloc(sizeof(struct protocol), name); return rval; } @@ -198,7 +202,7 @@ struct lease_state *new_lease_state (name) if (free_lease_states) { rval = free_lease_states; free_lease_states = - (struct lease_state *)(free_lease_states -> next); + (struct lease_state *)(free_lease_states->next); } else { rval = dmalloc (sizeof (struct lease_state), name); } @@ -225,21 +229,23 @@ void free_name_server (ptr, name) struct name_server *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_domain_search_list (ptr, name) struct domain_search_list *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_lease_state (ptr, name) struct lease_state *ptr; char *name; { - ptr -> next = free_lease_states; + if (ptr->prl) + dfree (ptr->prl, name); + ptr->next = free_lease_states; free_lease_states = ptr; } @@ -247,63 +253,63 @@ void free_protocol (ptr, name) struct protocol *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_group (ptr, name) struct group *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_shared_network (ptr, name) struct shared_network *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_class (ptr, name) struct class *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_subnet (ptr, name) struct subnet *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_lease (ptr, name) struct lease *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_hash_bucket (ptr, name) struct hash_bucket *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_hash_table (ptr, name) struct hash_table *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_tree_cache (ptr, name) struct tree_cache *ptr; char *name; { - ptr -> value = (unsigned char *)free_tree_caches; + ptr->value = (unsigned char *)free_tree_caches; free_tree_caches = ptr; } @@ -311,19 +317,26 @@ void free_packet (ptr, name) struct packet *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_dhcp_packet (ptr, name) struct dhcp_packet *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); } void free_tree (ptr, name) struct tree *ptr; char *name; { - dfree ((VOIDPTR)ptr, name); + dfree (ptr, name); +} + +void free_string_list (ptr, name) + struct string_list *ptr; + char *name; +{ + dfree (ptr, name); } diff --git a/usr.sbin/dhcp/common/bpf.c b/usr.sbin/dhcp/common/bpf.c index cc248613716..2509299291d 100644 --- a/usr.sbin/dhcp/common/bpf.c +++ b/usr.sbin/dhcp/common/bpf.c @@ -3,8 +3,8 @@ BPF socket interface code, originally contributed by Archie Cobbs. */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,41 +40,28 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: bpf.c,v 1.2 2001/01/03 16:04:38 ericj Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" -#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) #include #include - #include -#ifdef NEED_OSF_PFILT_HACKS -#include -#endif + #include -#include "includes/netinet/ip.h" -#include "includes/netinet/udp.h" -#include "includes/netinet/if_ether.h" +#include +#include +#include /* 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 @@ -89,16 +76,17 @@ int if_register_bpf (info) /* Open a BPF device */ for (b = 0; 1; b++) { -#ifndef NO_SNPRINTF snprintf(filename, sizeof(filename), BPF_FORMAT, b); -#else - sprintf(filename, BPF_FORMAT, b); -#endif sock = open (filename, O_RDWR, 0); if (sock < 0) { if (errno == EBUSY) { continue; } else { + if (!b) + error ("No bpf devices.%s%s%s", + " Please read the README", + " section for your operating", + " system."); error ("Can't find free bpf: %m"); } } else { @@ -113,36 +101,31 @@ int if_register_bpf (info) 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) - note ("Sending on BPF/%s/%s/%s", + note ("Sending on BPF/%s/%s%s%s", info -> name, print_hw_addr (info -> hw_address.htype, info -> hw_address.hlen, info -> hw_address.haddr), + (info -> shared_network ? "/" : ""), (info -> shared_network ? - info -> shared_network -> name : "unattached")); + info -> shared_network -> name : "")); } -#endif /* USE_BPF_SEND */ -#ifdef USE_BPF_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 filter [] = { +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), @@ -169,6 +152,22 @@ struct bpf_insn filter [] = { BPF_STMT(BPF_RET+BPF_K, 0), }; +int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn); + +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)); + void if_register_receive (info) struct interface_info *info; { @@ -193,21 +192,6 @@ void if_register_receive (info) if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0) error ("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) - error ("Can't set ALLOWCOPYALL: %m"); - - /* Clear all the packet filter mode bits first... */ - bits = 0; - if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) - error ("Can't clear pfilt bits: %m"); - - /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */ - bits = ENBATCH | ENCOPYALL | ENBPFHDR; - if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) - error ("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) error ("Can't get bpf buffer length: %m"); @@ -218,28 +202,28 @@ void if_register_receive (info) info -> rbuf_len = 0; /* Set up the bpf filter program structure. */ - p.bf_len = sizeof filter / sizeof (struct bpf_insn); - p.bf_insns = filter; + p.bf_len = dhcp_bpf_filter_len; + 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 */ - filter [8].k = ntohs (local_port); + dhcp_bpf_filter [8].k = ntohs (local_port); if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0) error ("Can't install packet filter program: %m"); if (!quiet_interface_discovery) - note ("Listening on BPF/%s/%s/%s", + note ("Listening on BPF/%s/%s%s%s", info -> name, print_hw_addr (info -> hw_address.htype, info -> hw_address.hlen, info -> hw_address.haddr), + (info -> shared_network ? "/" : ""), (info -> shared_network ? - info -> shared_network -> name : "unattached")); + 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; @@ -252,6 +236,11 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto) int bufp = 0; unsigned char buf [256]; struct iovec iov [2]; + int result; + + if (!strcmp (interface -> name, "fallback")) + return send_fallback (interface, packet, raw, + len, from, to, hto); /* Assemble the headers... */ assemble_hw_header (interface, buf, &bufp, hto); @@ -265,11 +254,12 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto) iov [1].iov_base = (char *)raw; iov [1].iov_len = len; - return writev(interface -> wfdesc, iov, 2); + result = writev(interface -> wfdesc, iov, 2); + if (result < 0) + warn ("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; @@ -381,4 +371,25 @@ ssize_t receive_packet (interface, buf, len, from, hfrom) } while (!length); return 0; } -#endif + +int can_unicast_without_arp () +{ + return 1; +} + +int can_receive_unicast_unconfigured (ip) + struct interface_info *ip; +{ + return 1; +} + +void maybe_setup_fallback () +{ + struct interface_info *fbi; + fbi = setup_fallback (); + if (fbi) { + if_register_fallback (fbi); + add_protocol ("fallback", fallback_interface -> wfdesc, + fallback_discard, fallback_interface); + } +} diff --git a/usr.sbin/dhcp/common/conflex.c b/usr.sbin/dhcp/common/conflex.c index 4855a973400..58136a2bc1a 100644 --- a/usr.sbin/dhcp/common/conflex.c +++ b/usr.sbin/dhcp/common/conflex.c @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: conflex.c,v 1.1 1998/08/18 03:43:25 deraadt Exp $ Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include "dhctoken.h" #include @@ -136,19 +131,10 @@ static int get_token (cfile) u = ugflag; c = get_char (cfile); -#ifdef OLD_LEXER - if (c == '\n' && p == 1 && !u - && comment_index < sizeof comments) - comments [comment_index++] = '\n'; -#endif if (!(c == '\n' && eol_token) && isascii (c) && isspace (c)) continue; if (c == '#') { -#ifdef OLD_LEXER - if (comment_index < sizeof comments) - comments [comment_index++] = '#'; -#endif skip_to_eol (cfile); continue; } @@ -237,13 +223,8 @@ static void skip_to_eol (cfile) c = get_char (cfile); if (c == EOF) return; -#ifdef OLD_LEXER - if (comment_index < sizeof (comments)) - comments [comment_index++] = c; -#endif - if (c == EOL) { + if (c == EOL) return; - } } while (1); } @@ -294,13 +275,6 @@ static int read_number (c, cfile) 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)) { ungetc (c, cfile); ugflag = 1; @@ -354,6 +328,8 @@ static int intern (atom, dfv) switch (tolower (atom [0])) { case 'a': + if (!strcasecmp (atom + 1, "lways-reply-rfc1048")) + return ALWAYS_REPLY_RFC1048; if (!strcasecmp (atom + 1, "ppend")) return APPEND; if (!strcasecmp (atom + 1, "llow")) @@ -362,6 +338,8 @@ static int intern (atom, dfv) return ALIAS; if (!strcasecmp (atom + 1, "bandoned")) return ABANDONED; + if (!strcasecmp (atom + 1, "uthoritative")) + return AUTHORITATIVE; break; case 'b': if (!strcasecmp (atom + 1, "ackoff-cutoff")) @@ -417,6 +395,8 @@ static int intern (atom, dfv) return FILENAME; if (!strcasecmp (atom + 1, "ixed-address")) return FIXED_ADDR; + if (!strcasecmp (atom + 1, "ddi")) + return FDDI; break; case 'g': if (!strcasecmp (atom + 1, "iaddr")) @@ -462,6 +442,8 @@ static int intern (atom, dfv) return NETMASK; if (!strcasecmp (atom + 1, "ext-server")) return NEXT_SERVER; + if (!strcasecmp (atom + 1, "ot")) + return TOKEN_NOT; break; case 'o': if (!strcasecmp (atom + 1, "ption")) @@ -526,12 +508,18 @@ static int intern (atom, dfv) return TOKEN_RING; break; case 'u': + 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 (!strcasecmp (atom + 1, "id")) return UID; - if (!strcasecmp (atom + 1, "ser-class")) - return USER_CLASS; - if (!strcasecmp (atom + 1, "se-host-decl-names")) - return USE_HOST_DECL_NAMES; if (!strcasecmp (atom + 1, "nknown-clients")) return UNKNOWN_CLIENTS; break; diff --git a/usr.sbin/dhcp/common/convert.c b/usr.sbin/dhcp/common/convert.c index 60db34258d9..c08e9d3a09f 100644 --- a/usr.sbin/dhcp/common/convert.c +++ b/usr.sbin/dhcp/common/convert.c @@ -41,11 +41,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: convert.c,v 1.1 1998/08/18 03:43:25 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" u_int32_t getULong (buf) @@ -102,7 +97,7 @@ void putLong (obuf, val) void putUShort (obuf, val) unsigned char *obuf; - u_int16_t val; + unsigned int val; { u_int16_t tmp = htons (val); memcpy (obuf, &tmp, sizeof tmp); @@ -110,7 +105,7 @@ void putUShort (obuf, val) void putShort (obuf, val) unsigned char *obuf; - int16_t val; + int val; { int16_t tmp = htons (val); memcpy (obuf, &tmp, sizeof tmp); diff --git a/usr.sbin/dhcp/common/dhcp-options.5 b/usr.sbin/dhcp/common/dhcp-options.5 index 77eb58db99e..5e7ca000249 100644 --- a/usr.sbin/dhcp/common/dhcp-options.5 +++ b/usr.sbin/dhcp/common/dhcp-options.5 @@ -1,6 +1,6 @@ .\" dhcp-options.5 .\" -.\" Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. +.\" Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -37,7 +37,7 @@ .\" Enterprises, see ``http://www.vix.com''. .TH dhcpd-options 5 .SH NAME -dhcp-options - DHCP options +dhcp-options - Dynamic Host Configuration Protocol options .SH DESCRIPTION The Dynamic Host Configuration protocol allows the client to receive .B options @@ -68,13 +68,13 @@ domain name resolves to a single IP address. .PP The .B int32 -data type specifies a signed 32-bit integer. The +data type specifies a signed 32-bit integer. The .B uint32 -data type specifies an unsigned 32-bit integer. The +data type specifies an unsigned 32-bit integer. The .B int16 and .B uint16 -data types specify signed and unsigned 16-bit integers. The +data types specify signed and unsigned 16-bit integers. The .B int8 and .B uint8 @@ -100,12 +100,12 @@ The .B data-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: +hexadecimal, seperated by colons. For example: .nf .sp 1 - option client-identifier "CLIENT-FOO"; + option dhcp-client-identifier "CLIENT-FOO"; or - option client-identifier 43:4c:49:45:54:2d:46:4f:4f; + option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f; .fi .PP The documentation for the various options mentioned below is taken @@ -113,7 +113,7 @@ from the latest IETF draft document on DHCP options. Options which are not listed by name may be defined by the name option-\fInnn\fR, where \fInnn\fI is the decimal number of the option code. These options may be followed either by a string, enclosed in quotes, or by -a series of octets, expressed as two-digit hexadecimal numbers separated +a series of octets, expressed as two-digit hexadecimal numbers seperated by colons. For example: .PP .nf @@ -126,7 +126,8 @@ no checking is done to ensure the correctness of the entered data. .PP The standard options are: .PP - \fBoption subnet-mask\fR \fIip-address\fR\fB;\fR +.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 @@ -136,114 +137,162 @@ for the network on which an address is being assigned. However, 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 - \fBoption time-offset\fR \fIint32\fR\fB;\fR +.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 - \fBoption routers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption time-servers\fR \fIip-address [, \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBien116-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]; +.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 - \fBoption\fR \fBdomain-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBlog-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBcookie-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBimpress-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBresource-location-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.B option \fBresource-location-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... +]\fB;\fR +.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 - \fBoption\fR \fBhost-name\fR \fIstring\fR\fB;\fR +.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. +.RE .PP - \fBoption\fR \fBboot-size\fR \fIuint16\fR\fB;\fR +.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 - \fBoption\fR \fBmerit-dump\fR \fIstring\fR\fB;\fR +.B option \fBmerit-dump\fR \fIstring\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 - \fBoption\fR \fBdomain-name\fR \fIstring\fR\fB;\fR +.B option \fBdomain-name\fR \fIstring\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 - \fBoption\fR \fBswap-server\fR \fIip-address\fR\fB;\fR +.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 - \fBoption\fR \fBroot-path\fR \fIstring\fB;\fR\fR +.B option \fBroot-path\fR \fIstring\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 - \fBoption\fR \fBip-forwarding\fR \fIflag\fR\fB;\fR +.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 0 means disable IP forwarding, and a value of 1 means enable IP forwarding. +.RE .PP - \fBoption\fR \fBnon-local-source-routing\fR \fIflag\fR\fB;\fR +.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 1 means allow forwarding. +.RE .PP - \fBoption\fR \fBpolicy-filter\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR ... ]\fB;\fR +.B option \fBpolicy-filter\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR... +]\fB;\fR +.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 @@ -253,36 +302,49 @@ 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 - \fBoption\fR \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR +.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 value legal value is 576. +.RE .PP - \fBoption\fR \fBdefault-ip-ttl\fR \fIuint8;\fR +.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 - \fBoption\fR \fBpath-mtu-aging-timeout\fR \fIuint32\fR\fB;\fR +.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 - \fBoption\fR \fBpath-mtu-plateau-table\fR \fIuint16\fR [\fB,\fR \fIuint16\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBinterface-mtu\fR \fIuint16\fR\fB;\fR +.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 - \fBoption\fR \fBall-subnets-local\fR \fIflag\fR\fB;\fR +.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 @@ -290,41 +352,54 @@ same MTU as the subnet of that network to which the client is directly connected. A value of 1 indicates that all subnets share the same MTU. A value of 0 means that the client should assume that some subnets of the directly connected network may have smaller MTUs. +.RE .PP - \fBoption\fR \fBbroadcast-address\fR \fIip-address\fR\fB;\fR +.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 - \fBoption\fR \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR +.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 0 indicates that the client should not perform mask discovery. A value of 1 means that the client should perform mask discovery. +.RE .PP - \fBoption\fR \fBmask-supplier\fR \fIflag\fR\fB;\fR +.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 0 indicates that the client should not respond. A value of 1 means that the client should respond. +.RE .PP - \fBoption\fR \fBrouter-discovery\fR \fIflag\fR\fB;\fR +.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 0 indicates that the client should not perform router discovery. A value of 1 means that the client should perform router discovery. +.RE .PP - \fBoption\fR \fBrouter-solicitation-address\fR \fIip-address\fR\fB;\fR +.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 - \fBoption\fR \fBstatic-routes\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR ... ]\fB;\fR +.B option \fBstatic-routes\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR... +]\fB;\fR +.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 @@ -339,106 +414,270 @@ 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. +.RE .PP - \fBoption\fR \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR +.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 1 means that the client should attempt to use trailers. +.RE .PP - \fBoption\fR \fBarp-cache-timeout\fR \fIuint32\fR\fB;\fR +.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 - \fBoption\fR \fBieee802-3-encapsulation\fR \fIflag\fR\fB;\fR +.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 0 indicates that the client should use RFC 894 encapsulation. A value of 1 means that the client should use RFC 1042 encapsulation. +.RE .PP - \fBoption\fR \fBdefault-tcp-ttl\fR \fIuint8\fR\fB;\fR +.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 - \fBoption\fR \fBtcp-keepalive-interval\fR \fIuint32\fR\fB;\fR +.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 - \fBoption\fR \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR +.B option \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR +.RS 0.25i .PP This option specifies the whether or not the client should send TCP keepalive messages with a octet of garbage for compatibility with older implementations. A value of 0 indicates that a garbage octet should not be sent. A value of 1 indicates that a garbage octet should be sent. +.RE .PP - \fBoption\fR \fBnis-domain\fR \fIstring\fR\fB;\fR +.B option \fBnis-domain\fR \fIstring\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 - \fBoption\fR \fBnis-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBntp-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBnetbios-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +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 - \fBoption\fR \fBnetbios-dd-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBnetbios-node-type\fR \fIuint8\fR\fB;\fR +.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. -A value of 1 corresponds to a NetBIOS B-node; a value of 2 corresponds -to a P-node; a value of 4 corresponds to an M-node; a value of 8 -corresponds to an H-node. .PP - \fBoption\fR \fBnetbios-scope\fR \fIstring\fR\fB;\fR +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 +.B netbios-scope +.I string\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 - \fBoption\fR \fBfont-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 - \fBoption\fR \fBx-display-manager\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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 .PP - \fBoption\fR \fBdhcp-client-identifier\fR \fIdata-string\fR\fB;\fR +.B option \fBdhcp-client-identifier\fR \fIdata-string\fR\fB;\fR +.RS 0.25i .PP This option can be used to specify the a DHCP client identifier in a host declaration, so that dhcpd can find the host record by matching against the client identifier. +.RE +.B option \fBnisplus-domain\fR \fIstring\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 +.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 \fBtftp-server-name\fR \fIstring\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 \fBbootfile-name\fR \fIstring\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 \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 \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 +.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 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 available to the +client. Servers should be listed in order of preference. +.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 available to the +client. Servers should be listed in order of preference. +.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 available to the +client. Servers should be listed in order of preference. +.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 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 \fBstreetalk-directory-assistance-server\fR \fIip-address\fR [\fB,\fR +\fIip-address\fR... ]\fB;\fR +.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 .SH SEE ALSO dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcpd(8), dhclient(8), RFC2132, RFC2131. diff --git a/usr.sbin/dhcp/common/dispatch.c b/usr.sbin/dhcp/common/dispatch.c index 5470e19e758..3e1aff476e1 100644 --- a/usr.sbin/dhcp/common/dispatch.c +++ b/usr.sbin/dhcp/common/dispatch.c @@ -3,8 +3,8 @@ Network input dispatcher... */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,29 +40,26 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: dispatch.c,v 1.4 2001/01/03 16:04:38 ericj Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include +#include #include + /* Most boxes has less than 16 interfaces, so this might be a good guess. */ #define INITIAL_IFREQ_COUNT 16 -struct interface_info *interfaces, *dummy_interfaces; +struct interface_info *interfaces, *dummy_interfaces, *fallback_interface; struct protocol *protocols; struct timeout *timeouts; static struct timeout *free_timeouts; static int interfaces_invalidated; void (*bootp_packet_handler) PROTO ((struct interface_info *, - unsigned char *, int, unsigned short, + struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *)); -int interface_status PROTO((struct interface_info *)); -static void got_one PROTO ((struct protocol *)); +static int interface_status(struct interface_info *ifinfo); + int quiet_interface_discovery; /* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces. @@ -85,12 +82,10 @@ void discover_interfaces (state) struct shared_network *share; struct sockaddr_in foo; int ir; + struct ifreq *tif; #ifdef ALIAS_NAMES_PERMUTED char *s; #endif -#ifdef USE_FALLBACK - static struct shared_network fallback_network; -#endif /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) @@ -133,37 +128,17 @@ void discover_interfaces (state) else ir = INTERFACE_REQUESTED; - /* Cycle through the list of interfaces looking for IP addresses. - Go through twice; once to count the number of addresses, and a - second time to copy them into an array of addresses. */ + /* 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) - i += ((sizeof ifp -> ifr_name) + - (ifp -> ifr_addr.sa_len > - sizeof (struct sockaddr) ? - ifp -> ifr_addr.sa_len : - sizeof (struct sockaddr))); + 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. */ - strlcpy (ifr.ifr_name, ifp -> ifr_name, sizeof(ifr.ifr_name)); + strlcpy (ifr.ifr_name, ifp -> ifr_name, IFNAMSIZ); if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) error ("Can't get interface flags for %s: %m", ifr.ifr_name); @@ -172,9 +147,7 @@ void discover_interfaces (state) except don't skip down interfaces if we're trying to get a list of configurable interfaces. */ if ((ifr.ifr_flags & IFF_LOOPBACK) || -#ifdef IFF_POINTOPOINT (ifr.ifr_flags & IFF_POINTOPOINT) || -#endif (!(ifr.ifr_flags & IFF_UP) && state != DISCOVER_UNCONFIGURED)) continue; @@ -192,17 +165,14 @@ void discover_interfaces (state) if (!tmp) error ("Insufficient memory to %s %s", "record interface", ifp -> ifr_name); - strlcpy (tmp -> name, ifp -> ifr_name, - sizeof(tmp->name)); + strlcpy (tmp -> name, ifp -> ifr_name, IFNAMSIZ); tmp -> next = interfaces; tmp -> flags = ir; - tmp -> noifmedia = tmp -> dead = tmp->errors = 0; interfaces = tmp; } /* If we have the capability, extract link information and record it in a linked list. */ -#ifdef AF_LINK if (ifp -> ifr_addr.sa_family == AF_LINK) { struct sockaddr_dl *foo = ((struct sockaddr_dl *) (&ifp -> ifr_addr)); @@ -211,64 +181,10 @@ void discover_interfaces (state) memcpy (tmp -> hw_address.haddr, LLADDR (foo), foo -> sdl_alen); } else -#endif /* AF_LINK */ if (ifp -> ifr_addr.sa_family == AF_INET) { struct iaddr addr; -#if defined (SIOCGIFHWADDR) && !defined (AF_LINK) - struct ifreq ifr; - struct sockaddr sa; - int b, sk; - - /* Read the hardware address from this interface. */ - ifr = *ifp; - if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0) - error ("Can't get hardware address for %s: %m", - ifr.ifr_name); - - sa = *(struct sockaddr *)&ifr.ifr_hwaddr; - - switch (sa.sa_family) { -#ifdef ARPHRD_LOOPBACK - case ARPHRD_LOOPBACK: - /* ignore loopback interface */ - break; -#endif - - case ARPHRD_ETHER: - tmp -> hw_address.hlen = 6; - tmp -> hw_address.htype = ARPHRD_ETHER; - memcpy (tmp -> hw_address.haddr, - sa.sa_data, 6); - break; - -#ifndef ARPHRD_IEEE802 -# define ARPHRD_IEEE802 HTYPE_IEEE802 -#endif - case ARPHRD_IEEE802: - tmp -> hw_address.hlen = 6; - tmp -> hw_address.htype = ARPHRD_IEEE802; - memcpy (tmp -> hw_address.haddr, - sa.sa_data, 6); - break; - -#ifdef ARPHRD_METRICOM - case ARPHRD_METRICOM: - tmp -> hw_address.hlen = 6; - tmp -> hw_address.htype = ARPHRD_METRICOM; - memcpy (tmp -> hw_address.haddr, - sa.sa_data, 6); - - break; -#endif - - default: - error ("%s: unknown hardware address type %d", - ifr.ifr_name, sa.sa_family); - } -#endif /* defined (SIOCGIFHWADDR) && !defined (AF_LINK) */ - /* Get a pointer to the address... */ memcpy (&foo, &ifp -> ifr_addr, sizeof ifp -> ifr_addr); @@ -282,13 +198,8 @@ void discover_interfaces (state) found, keep a pointer to ifreq structure in which we found it. */ if (!tmp -> ifp) { - struct ifreq *tif; -#ifdef HAVE_SA_LEN int len = ((sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len); -#else - int len = sizeof *ifp; -#endif tif = (struct ifreq *)malloc (len); if (!tif) error ("no space to remember ifp."); @@ -341,6 +252,9 @@ void discover_interfaces (state) } } + /* Now cycle through all the interfaces we found, looking for + hardware addresses. */ + /* 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) @@ -374,9 +288,14 @@ void discover_interfaces (state) sizeof tmp -> ifp -> ifr_addr); /* We must have a subnet declaration for each interface. */ - if (!tmp -> shared_network && (state == DISCOVER_SERVER)) - error ("No subnet declaration for %s (%s).", - tmp -> name, inet_ntoa (foo.sin_addr)); + if (!tmp -> shared_network && (state == DISCOVER_SERVER)) { + warn ("No subnet declaration for %s (%s).", + tmp -> name, inet_ntoa (foo.sin_addr)); + warn ("Please write a subnet declaration in your %s", + "dhcpd.conf file for the"); + error ("network segment to which interface %s %s", + tmp -> name, "is attached."); + } /* Find subnets that don't have valid interface addresses... */ @@ -404,14 +323,26 @@ void discover_interfaces (state) close (sock); -#ifdef USE_FALLBACK - strlcpy (fallback_interface.name, "fallback", sizeof(fallback_interface.name)); - fallback_interface.shared_network = &fallback_network; - fallback_network.name = "fallback-net"; - if_register_fallback (&fallback_interface); - add_protocol ("fallback", fallback_interface.wfdesc, - fallback_discard, &fallback_interface); -#endif + maybe_setup_fallback (); +} + +struct interface_info *setup_fallback () +{ + fallback_interface = + ((struct interface_info *) + dmalloc (sizeof *fallback_interface, "discover_interfaces")); + if (!fallback_interface) + error ("Insufficient memory to record fallback interface."); + memset (fallback_interface, 0, sizeof *fallback_interface); + strlcpy (fallback_interface -> name, "fallback", IFNAMSIZ); + fallback_interface -> shared_network = + new_shared_network ("parse_statement"); + if (!fallback_interface -> shared_network) + error ("No memory for shared subnet"); + memset (fallback_interface -> shared_network, 0, + sizeof (struct shared_network)); + fallback_interface -> shared_network -> name = "fallback-net"; + return fallback_interface; } void reinitialize_interfaces () @@ -423,28 +354,34 @@ void reinitialize_interfaces () if_reinitialize_send (ip); } -#ifdef USE_FALLBACK - if_reinitialize_fallback (&fallback_interface); -#endif + if (fallback_interface) + if_reinitialize_send (fallback_interface); interfaces_invalidated = 1; } -/* 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 do_packet to try to - do something with it. */ +/* Wait for packets to come in using poll(). When a packet comes in, + 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 () { - fd_set r, w, x; struct protocol *l; - int max = 0; + int nfds = 0; + struct pollfd *fds; int count; - struct timeval tv, *tvp; + int i; + time_t howlong; + int to_msec; - FD_ZERO (&w); - FD_ZERO (&x); + nfds = 0; + for (l = protocols; l; l = l -> next) { + ++nfds; + } + fds = (struct pollfd *)malloc ((nfds) * sizeof (struct pollfd)); + if (fds == NULL) + error ("Can't allocate poll structures."); do { /* Call any expired timeouts, and then if there's @@ -461,69 +398,84 @@ void dispatch () free_timeouts = t; goto another; } - tv.tv_sec = timeouts -> when - cur_time; - tv.tv_usec = 0; - tvp = &tv; + /* + * Figure timeout in milliseconds, and check for + * potential overflow, so we can cram into an int + * for poll, while not polling with a negative + * timeout and blocking indefinetely. + */ + + howlong = timeouts -> when - cur_time; + if (howlong > INT_MAX / 1000) + howlong = INT_MAX / 1000; + to_msec = howlong * 1000; } else - tvp = (struct timeval *)0; - - /* Set up the read mask. */ - FD_ZERO (&r); - - max = -1; + to_msec = -1; + /* Set up the descriptors to be polled. */ + i = 0; for (l = protocols; l; l = l -> next) { - struct interface_info *ip = l -> local; - if (ip && !ip->dead) { - FD_SET (l -> fd, &r); - if (l -> fd > max) - max = l -> fd; - } + struct interface_info *ip = l -> local; + if (ip && !ip->dead) { + fds [i].fd = l -> fd; + fds [i].events = POLLIN; + fds [i].revents = 0; + ++i; + } } - if (max == -1) - error("No interfaces to select on - exiting."); + if (i == 0) + error("No live interfaces to poll on - exiting."); /* Wait for a packet or a timeout... XXX */ - count = select (max + 1, &r, &w, &x, tvp); + count = poll (fds, nfds, to_msec); + + /* Not likely to be transitory... */ + if (count == -1) { + if (errno == EAGAIN || errno == EINTR) { + GET_TIME (&cur_time); + continue; + } + else + error ("poll: %m"); + } /* Get the current time... */ GET_TIME (&cur_time); - /* Not likely to be transitory... */ - if (count == -1) - error ("select: %m"); - + i = 0; for (l = protocols; l; l = l -> next) { - struct interface_info *ip; - if (!FD_ISSET (l -> fd, &r)) - continue; - ip = l->local; - if (ip && !ip-> dead && l -> handler) - (*(l -> handler)) (l); - if (interfaces_invalidated) - break; + if ((fds [i].revents & POLLIN)) { + fds [i].revents = 0; + if (l -> handler) + (*(l -> handler)) (l); + if (interfaces_invalidated) + break; + } + ++i; } interfaces_invalidated = 0; } while (1); } -static void got_one (l) +void got_one (l) struct protocol *l; { struct sockaddr_in from; struct hardware hfrom; struct iaddr ifrom; size_t result; - static unsigned char packbuf [4095]; /* Packet input buffer. - Must be as large as largest - possible MTU. */ + 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 = l -> local; - - if ((result = receive_packet (ip, packbuf, sizeof packbuf, - &from, &hfrom)) == -1) { + if ((result = + receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) == -1) { warn ("receive_packet failed on %s: %s", ip -> name, strerror(errno)); ip->errors++; @@ -544,11 +496,71 @@ static void got_one (l) ifrom.len = 4; memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); - (*bootp_packet_handler) (ip, packbuf, result, + (*bootp_packet_handler) (ip, &u.packet, result, from.sin_port, ifrom, &hfrom); } } +int +interface_status(struct interface_info *ifinfo) +{ + char * ifname = ifinfo->name; + int ifsock = ifinfo->rfdesc; + struct ifreq ifr; + struct ifmediareq ifmr; + + /* get interface flags */ + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { + syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", + ifname); + goto inactive; + } + /* + * if one of UP and RUNNING flags is dropped, + * the interface is not active. + */ + if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { + goto inactive; + } + /* Next, check carrier on the interface, if possible */ + if (ifinfo->noifmedia) + goto active; + memset(&ifmr, 0, sizeof(ifmr)); + strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); + if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { + if (errno != EINVAL) { + syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m", + ifname); + ifinfo->noifmedia = 1; + goto active; + } + /* + * EINVAL (or ENOTTY) simply means that the interface + * does not support the SIOCGIFMEDIA ioctl. We regard it alive. + */ + ifinfo->noifmedia = 1; + goto active; + } + if (ifmr.ifm_status & IFM_AVALID) { + switch(ifmr.ifm_active & IFM_NMASK) { + case IFM_ETHER: + if (ifmr.ifm_status & IFM_ACTIVE) + goto active; + else + goto inactive; + break; + default: + goto inactive; + } + } + inactive: + return(0); + active: + return(1); +} + int locate_network (packet) struct packet *packet; { @@ -699,70 +711,3 @@ void remove_protocol (proto) } } } - -int -interface_status(struct interface_info *ifinfo) -{ - char * ifname = ifinfo->name; - int ifsock = ifinfo->rfdesc; - struct ifreq ifr; - struct ifmediareq ifmr; - - - - /* get interface flags */ - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", - ifname); - goto inactive; - } - /* - * if one of UP and RUNNING flags is dropped, - * the interface is not active. - */ - if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - goto inactive; - } - - /* Next, check carrier on the interface, if possible */ - if (ifinfo->noifmedia) - goto active; - memset(&ifmr, 0, sizeof(ifmr)); - strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); - - if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { - if (errno != EINVAL) { - syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m", - ifname); - ifinfo->noifmedia = 1; - goto active; - } - /* - * EINVAL (or ENOTTY) simply means that the interface - * does not support the SIOCGIFMEDIA ioctl. We regard it alive. - */ - ifinfo->noifmedia = 1; - goto active; - } - - if (ifmr.ifm_status & IFM_AVALID) { - switch(ifmr.ifm_active & IFM_NMASK) { - case IFM_ETHER: - if (ifmr.ifm_status & IFM_ACTIVE) - goto active; - else - goto inactive; - break; - default: - goto inactive; - } - } - - inactive: - return(0); - - active: - return(1); -} diff --git a/usr.sbin/dhcp/common/dns.c b/usr.sbin/dhcp/common/dns.c deleted file mode 100644 index 6e2d539dc38..00000000000 --- a/usr.sbin/dhcp/common/dns.c +++ /dev/null @@ -1,399 +0,0 @@ -/* dns.c - - Domain Name Service subroutines. */ - -/* - * Copyright (C) 1992 by Ted Lemon. - * Copyright (c) 1997 The Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is based on software written in 1992 by Ted Lemon for - * a portable network boot loader. That original code base has been - * substantially modified for use in the Internet Software Consortium - * DHCP suite. - * - * These later modifications were done on behalf of the Internet - * Software Consortium by Ted Lemon in cooperation - * with Vixie Enterprises. To learn more about the Internet Software - * Consortium, see ``http://www.vix.com/isc''. To learn more about - * Vixie Enterprises, see ``http://www.vix.com''. - */ - -#ifndef lint -static char copyright[] = -"$Id: dns.c,v 1.3 2001/01/03 16:04:38 ericj Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include "arpa/nameser.h" - -int dns_protocol_initialized; -int dns_protocol_fd; - -static int addlabel PROTO ((u_int8_t *, char *)); -static int skipname PROTO ((u_int8_t *)); -static int copy_out_name PROTO ((u_int8_t *, u_int8_t *, char *)); -static int nslookup PROTO ((u_int8_t, char *, int, u_int16_t, u_int16_t)); -static int zonelookup PROTO ((u_int8_t, char *, int, u_int16_t)); -u_int16_t dns_port; - -/* Initialize the DNS protocol. */ - -void dns_startup () -{ - struct servent *srv; - - /* Only initialize icmp once. */ - if (dns_protocol_initialized) - error ("attempted to reinitialize dns protocol"); - dns_protocol_initialized = 1; - - /* Get the protocol number (should be 1). */ - srv = getservbyname ("domain", "tcp"); - if (srv) - dns_port = srv -> s_port; - else - dns_port = htons (53); - - /* Get a socket for the DNS protocol. */ - dns_protocol_fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (!dns_protocol_fd) - error ("unable to create dns socket: %m"); - - pick_name_server (); - - add_protocol ("dns", dns_protocol_fd, dns_packet, 0); -} - -/* Label manipulation stuff; see RFC1035, page 28 section 4.1.2 and - page 30, section 4.1.4. */ - -/* addlabel copies a label into the specified buffer, putting the length of - the label in the first character, the contents of the label in subsequent - characters, and returning the length of the conglomeration. */ - -static int addlabel (buf, label) - u_int8_t *buf; - char *label; -{ - *buf = strlen (label); - memcpy (buf + 1, label, *buf); - return *buf + 1; -} - -/* skipname skips over all of the labels in a single domain name, - returning the length of the domain name. */ - -static int skipname (label) - u_int8_t *label; -{ - if (*label & INDIR_MASK) - return 2; - if (*label == 0) - return 1; - return *label + 1 + skipname (label + *label + 1); -} - -/* copy_out_name copies out the name appearing at the specified location - into a string, stored as fields separated by dots rather than lengths - and labels. The length of the label-formatted name is returned. */ - -static int copy_out_name (base, name, buf) - u_int8_t *base; - u_int8_t *name; - char *buf; -{ - if (*name & INDIR_MASK) { - int offset = (*name & ~INDIR_MASK) + (*name + 1); - return copy_out_name (base, base + offset, buf); - } - if (!*name) { - *buf = 0; - return 1; - } - memcpy (buf, name + 1, *name); - *(buf + *name) = '.'; - return (*name + 1 - + copy_out_name (base, name + *name + 1, buf + *name + 1)); -} - -/* ns_inaddr_lookup constructs a PTR lookup query for an internet address - - e.g., 1.200.9.192.in-addr.arpa. If the specified timeout period passes - before the query is satisfied, or if the query fails, the callback is - called with a null pointer. Otherwise, the callback is called with the - address of the string returned by the name server. */ - -int ns_inaddr_lookup (id, inaddr) - u_int16_t id; - struct iaddr inaddr; -{ - unsigned char namebuf [512]; - unsigned char *s = namebuf; - unsigned char *label; - int i; - unsigned char c; - - for (i = 3; i >= 0; --i) { - label = s++; - *label = 1; - c = inaddr.iabuf [i]; - if (c > 100) { - ++*label; - *s++ = '0' + c / 100; - } - if (c > 10) { - ++*label; - *s++ = '0' + ((c / 10) % 10); - } - *s++ = '0' + (c % 10); - } - s += addlabel (s, "in-addr"); - s += addlabel (s, "arpa"); - *s++ = 0; -/* return nslookup (id, namebuf, s - namebuf, T_PTR, C_IN); */ - return zonelookup (id, namebuf, s - namebuf, C_IN); -} - -/* Construct and transmit a name server query. */ - -static int nslookup (id, qname, namelen, qtype, qclass) - u_int8_t id; - char *qname; - int namelen; - u_int16_t qtype; - u_int16_t qclass; -{ - HEADER *hdr; - unsigned char query [512]; - u_int8_t *s; - int status; - struct sockaddr_in *server = pick_name_server (); - - if (!server) - return 0; - - /* Construct a header... */ - hdr = (HEADER *)query; - memset (hdr, 0, sizeof *hdr); - hdr -> id = htons (id); - hdr -> rd = 1; - hdr -> opcode = QUERY; - hdr -> qdcount = htons (1); - - /* Copy in the name we're looking up. */ - s = (u_int8_t *)(hdr + 1); - memcpy (s, qname, namelen); - s += namelen; - - /* Set the query type. */ - putUShort (s, qtype); - s += sizeof (u_int16_t); - - /* Set the query class. */ - putUShort (s, qclass); - s += sizeof (u_int16_t); - - /* Send the query. */ - status = sendto (dns_protocol_fd, query, s - query, 0, - (struct sockaddr *)server, sizeof *server); - - /* If the send failed, report the failure. */ - if (status < 0) - return 0; - return 1; -} - -/* Construct a query for the SOA for a specified name. - Try every possible SOA name starting from the name specified and going - to the root name - e.g., for - - 215.5.5.192.in-addr.arpa, look for SOAs matching: - - 215.5.5.5.192.in-addr.arpa - 5.5.192.in-addr.arpa - 5.192.in-addr.arpa - 192.in-addr.arpa - in-addr.arpa - arpa */ - -static int zonelookup (id, qname, namelen, qclass) - u_int8_t id; - char *qname; - int namelen; - u_int16_t qclass; -{ - HEADER *hdr; - unsigned char query [512]; - u_int8_t *s, *nptr; - int status, count; - struct sockaddr_in *server = pick_name_server (); - - if (!server) - return 0; - - /* Construct a header... */ - hdr = (HEADER *)query; - memset (hdr, 0, sizeof *hdr); - hdr -> id = htons (id); - hdr -> rd = 1; - hdr -> opcode = QUERY; - - /* Copy in the name we're looking up. */ - s = (u_int8_t *)(hdr + 1); - memcpy (s, qname, namelen); - s += namelen; - - /* Set the query type. */ - putUShort (s, T_SOA); - s += sizeof (u_int16_t); - - /* Set the query class. */ - putUShort (s, qclass); - s += sizeof (u_int16_t); - count = 1; - - /* Now query up the hierarchy. */ - nptr = (u_int8_t *)(hdr + 1); - while (*(nptr += *nptr + 1)) { - /* Store a compressed reference from the full name. */ - putUShort (s, ntohs (htons (0xC000) | - htons (nptr - &query [0]))); - s += sizeof (u_int16_t); - - /* Store the query type. */ - putUShort (s, T_SOA); - s += sizeof (u_int16_t); - - putUShort (s, qclass); - s += sizeof (u_int16_t); - - /* Increment the query count... */ - ++count; -break; - } - hdr -> qdcount = htons (count); - -dump_raw (query, s - query); - /* Send the query. */ - status = sendto (dns_protocol_fd, query, s - query, 0, - (struct sockaddr *)server, sizeof *server); - - /* If the send failed, report the failure. */ - if (status < 0) - return 0; - return 1; -} - -/* Process a reply from a name server. */ - -void dns_packet (protocol) - struct protocol *protocol; -{ - HEADER *ns_header; - struct sockaddr_in from; - unsigned char buf [4096]; - unsigned char nbuf [512]; - unsigned char *base; - unsigned char *dptr; - u_int16_t type; - u_int16_t class; - TIME ttl; - u_int16_t rdlength; - int len, status; - int i; - - len = sizeof from; - status = recvfrom (protocol -> fd, buf, sizeof buf, 0, - (struct sockaddr *)&from, &len); - if (status < 0) { - warn ("icmp_echoreply: %m"); - return; - } - - ns_header = (HEADER *)buf; - base = (unsigned char *)(ns_header + 1); - -#if 0 - /* Ignore invalid packets... */ - if (ntohs (ns_header -> id) > ns_query_max) { - printf ("Out-of-range NS message; id = %d\n", - ntohs (ns_header -> id)); - return; - } -#endif - - /* Parse the response... */ - dptr = base; - - /* Skip over the queries... */ - for (i = 0; i < ntohs (ns_header -> qdcount); i++) { - dptr += skipname (dptr); - /* Skip over the query type and query class. */ - dptr += 2 * sizeof (u_int16_t); - } - - /* Process the answers... */ - for (i = 0; i < ntohs (ns_header -> ancount); i++) { - /* Skip over the name we looked up. */ - dptr += skipname (dptr); - - /* Get the type. */ - type = getUShort (dptr); - dptr += sizeof type; - - /* Get the class. */ - class = getUShort (dptr); - dptr += sizeof class; - - /* Get the time-to-live. */ - ttl = getULong (dptr); - dptr += sizeof ttl; - - /* Get the length of the reply. */ - rdlength = getUShort (dptr); - dptr += sizeof rdlength; - - switch (type) { - case T_A: - note ("A record; value is %d.%d.%d.%d", - dptr [0], dptr [1], dptr [2], dptr [3]); - break; - - case T_CNAME: - case T_PTR: - copy_out_name (base, dptr, nbuf); - note ("Domain name; value is %s\n", nbuf); - return; - - default: - note ("unhandled type: %x", type); - } - } -} diff --git a/usr.sbin/dhcp/common/errwarn.c b/usr.sbin/dhcp/common/errwarn.c index d370ff612ce..a76e46254df 100644 --- a/usr.sbin/dhcp/common/errwarn.c +++ b/usr.sbin/dhcp/common/errwarn.c @@ -40,15 +40,10 @@ * with Vixie Laboratories. */ -#ifndef lint -static char copyright[] = -"$Id: errwarn.c,v 1.3 2001/01/03 16:04:38 ericj Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include -static void do_percentm PROTO ((char *obuf, char *ibuf)); +static void do_percentm PROTO ((char *obuf, size_t size, char *ibuf)); static char mbuf [1024]; static char fbuf [1024]; @@ -57,20 +52,20 @@ int warnings_occurred; /* Log an error message, then exit... */ -void error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT) +void error (char * fmt, ...) KandR (char *fmt;) va_dcl { va_list list; - do_percentm (fbuf, fmt); + do_percentm (fbuf, sizeof(fbuf), fmt); - VA_start (list, fmt); + va_start (list, fmt); vsnprintf (mbuf, sizeof mbuf, fbuf, list); va_end (list); #ifndef DEBUG - syslog (log_priority | LOG_ERR, "%s", mbuf); + syslog (log_priority | LOG_ERR, mbuf); #endif /* Also log it to stderr? */ @@ -90,20 +85,20 @@ void error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT) /* Log a warning message... */ -int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) +int warn (char * fmt, ...) KandR (char *fmt;) va_dcl { va_list list; - do_percentm (fbuf, fmt); + do_percentm (fbuf, sizeof(fbuf), fmt); - VA_start (list, fmt); + va_start (list, fmt); vsnprintf (mbuf, sizeof mbuf, fbuf, list); va_end (list); #ifndef DEBUG - syslog (log_priority | LOG_ERR, "%s", mbuf); + syslog (log_priority | LOG_ERR, mbuf); #endif if (log_perror) { @@ -116,20 +111,20 @@ int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) /* Log a note... */ -int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) +int note (char * fmt, ...) KandR (char *fmt;) va_dcl { va_list list; - do_percentm (fbuf, fmt); + do_percentm (fbuf, sizeof(fbuf), fmt); - VA_start (list, fmt); + va_start (list, fmt); vsnprintf (mbuf, sizeof mbuf, fbuf, list); va_end (list); #ifndef DEBUG - syslog (log_priority | LOG_INFO, "%s", mbuf); + syslog (log_priority | LOG_INFO, mbuf); #endif if (log_perror) { @@ -142,20 +137,20 @@ int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) /* Log a debug message... */ -int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) +int debug (char * fmt, ...) KandR (char *fmt;) va_dcl { va_list list; - do_percentm (fbuf, fmt); + do_percentm (fbuf, sizeof(fbuf), fmt); - VA_start (list, fmt); + va_start (list, fmt); vsnprintf (mbuf, sizeof mbuf, fbuf, list); va_end (list); #ifndef DEBUG - syslog (log_priority | LOG_DEBUG, "%s", mbuf); + syslog (log_priority | LOG_DEBUG, mbuf); #endif if (log_perror) { @@ -168,70 +163,59 @@ int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) /* Find %m in the input string and substitute an error message string. */ -static void do_percentm (obuf, ibuf) +static void do_percentm (obuf, size, ibuf) char *obuf; + size_t size; char *ibuf; { + char ch; char *s = ibuf; - char *p = obuf; - int infmt = 0; - const char *m; - - while (*s) - { - if (infmt) - { - if (*s == 'm') - { -#ifndef __CYGWIN32__ - m = strerror (errno); -#else - m = pWSAError (); -#endif - if (!m) - m = ""; - strcpy (p - 1, m); - p += strlen (p); - ++s; + char *t = obuf; + size_t prlen; + size_t fmt_left; + int saved_errno = errno; + + /* + * We wouldn't need this mess if printf handled %m, or if + * strerror() had been invented before syslog(). + */ + for (fmt_left = size; (ch = *s); ++s) { + if (ch == '%' && s[1] == 'm') { + ++s; + prlen = snprintf(t, fmt_left, "%s", + strerror(saved_errno)); + if (prlen >= fmt_left) + prlen = fmt_left - 1; + t += prlen; + fmt_left -= prlen; + } else { + if (fmt_left > 1) { + *t++ = ch; + fmt_left--; } - else - *p++ = *s++; - infmt = 0; - } - else - { - if (*s == '%') - infmt = 1; - *p++ = *s++; } } - *p = 0; + *t = '\0'; } -int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) +int parse_warn (char * fmt, ...) KandR (char *fmt;) va_dcl { va_list list; static char spaces [] = " "; - do_percentm (mbuf, fmt); -#ifndef NO_SNPRINTF + do_percentm (mbuf, sizeof(mbuf), fmt); snprintf (fbuf, sizeof fbuf, "%s line %d: %s", tlname, lexline, mbuf); -#else - sprintf (fbuf, "%s line %d: %s", - tlname, lexline, mbuf); -#endif - VA_start (list, fmt); vsnprintf (mbuf, sizeof mbuf, fbuf, list); va_end (list); #ifndef DEBUG - syslog (log_priority | LOG_ERR, "%s", mbuf); - syslog (log_priority | LOG_ERR, "%s", token_line); + syslog (log_priority | LOG_ERR, mbuf); + syslog (log_priority | LOG_ERR, token_line); if (lexline < 81) syslog (log_priority | LOG_ERR, "%s^", &spaces [sizeof spaces - lexchar]); @@ -250,156 +234,3 @@ int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) return 0; } - -void -write_pidfile(file, pid) - char *file; - pid_t pid; -{ - FILE *fp; - - (void)unlink(file); - - if ((fp = fopen(file , "w")) != NULL) { - fprintf(fp, "%d\n", pid); - (void)fclose(fp); - } -} - -#ifdef NO_STRERROR -char *strerror (err) - int err; -{ - extern char *sys_errlist []; - extern int sys_nerr; - static char errbuf [128]; - - if (err < 0 || err >= sys_nerr) { - sprintf (errbuf, "Error %d", err); - return errbuf; - } - return sys_errlist [err]; -} -#endif /* NO_STRERROR */ - -#ifdef _WIN32 -char *pWSAError () -{ - int err = WSAGetLastError (); - - switch (err) - { - case WSAEACCES: - return "Permission denied"; - case WSAEADDRINUSE: - return "Address already in use"; - case WSAEADDRNOTAVAIL: - return "Cannot assign requested address"; - case WSAEAFNOSUPPORT: - return "Address family not supported by protocol family"; - case WSAEALREADY: - return "Operation already in progress"; - case WSAECONNABORTED: - return "Software caused connection abort"; - case WSAECONNREFUSED: - return "Connection refused"; - case WSAECONNRESET: - return "Connection reset by peer"; - case WSAEDESTADDRREQ: - return "Destination address required"; - case WSAEFAULT: - return "Bad address"; - case WSAEHOSTDOWN: - return "Host is down"; - case WSAEHOSTUNREACH: - return "No route to host"; - case WSAEINPROGRESS: - return "Operation now in progress"; - case WSAEINTR: - return "Interrupted function call"; - case WSAEINVAL: - return "Invalid argument"; - case WSAEISCONN: - return "Socket is already connected"; - case WSAEMFILE: - return "Too many open files"; - case WSAEMSGSIZE: - return "Message too long"; - case WSAENETDOWN: - return "Network is down"; - case WSAENETRESET: - return "Network dropped connection on reset"; - case WSAENETUNREACH: - return "Network is unreachable"; - case WSAENOBUFS: - return "No buffer space available"; - case WSAENOPROTOOPT: - return "Bad protocol option"; - case WSAENOTCONN: - return "Socket is not connected"; - case WSAENOTSOCK: - return "Socket operation on non-socket"; - case WSAEOPNOTSUPP: - return "Operation not supported"; - case WSAEPFNOSUPPORT: - return "Protocol family not supported"; - case WSAEPROCLIM: - return "Too many processes"; - case WSAEPROTONOSUPPORT: - return "Protocol not supported"; - case WSAEPROTOTYPE: - return "Protocol wrong type for socket"; - case WSAESHUTDOWN: - return "Cannot send after socket shutdown"; - case WSAESOCKTNOSUPPORT: - return "Socket type not supported"; - case WSAETIMEDOUT: - return "Connection timed out"; - case WSAEWOULDBLOCK: - return "Resource temporarily unavailable"; - case WSAHOST_NOT_FOUND: - return "Host not found"; -#if 0 - case WSA_INVALID_HANDLE: - return "Specified event object handle is invalid"; - case WSA_INVALID_PARAMETER: - return "One or more parameters are invalid"; - case WSAINVALIDPROCTABLE: - return "Invalid procedure table from service provider"; - case WSAINVALIDPROVIDER: - return "Invalid service provider version number"; - case WSA_IO_PENDING: - return "Overlapped operations will complete later"; - case WSA_IO_INCOMPLETE: - return "Overlapped I/O event object not in signaled state"; - case WSA_NOT_ENOUGH_MEMORY: - return "Insufficient memory available"; -#endif - case WSANOTINITIALISED: - return "Successful WSAStartup not yet performer"; - case WSANO_DATA: - return "Valid name, no data record of requested type"; - case WSANO_RECOVERY: - return "This is a non-recoverable error"; -#if 0 - case WSAPROVIDERFAILEDINIT: - return "Unable to initialize a service provider"; - case WSASYSCALLFAILURE: - return "System call failure"; -#endif - case WSASYSNOTREADY: - return "Network subsystem is unavailable"; - case WSATRY_AGAIN: - return "Non-authoritative host not found"; - case WSAVERNOTSUPPORTED: - return "WINSOCK.DLL version out of range"; - case WSAEDISCON: - return "Graceful shutdown in progress"; -#if 0 - case WSA_OPERATION_ABORTED: - return "Overlapped operation aborted"; -#endif - } - return "Unknown WinSock error"; -} -#endif /* _WIN32 */ diff --git a/usr.sbin/dhcp/common/ethernet.c b/usr.sbin/dhcp/common/ethernet.c new file mode 100644 index 00000000000..1adface63a8 --- /dev/null +++ b/usr.sbin/dhcp/common/ethernet.c @@ -0,0 +1,92 @@ +/* packet.c + + Packet assembly code, originally contributed by Archie Cobbs. */ + +/* + * Copyright (c) 1995, 1996 The Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie + * Enterprises. To learn more about the Internet Software Consortium, + * see ``http://www.vix.com/isc''. To learn more about Vixie + * Enterprises, see ``http://www.vix.com''. + */ + +#include "dhcpd.h" + +#include +#define ETHER_HEADER_SIZE (ETHER_ADDR_LEN * 2 + sizeof (u_int16_t)) + +/* Assemble an hardware header... */ +/* XXX currently only supports ethernet; doesn't check for other types. */ + +void assemble_ethernet_header (interface, buf, bufix, to) + struct interface_info *interface; + unsigned char *buf; + int *bufix; + struct hardware *to; +{ + struct ether_header eh; + + if (to && to -> hlen == 6) /* XXX */ + memcpy (eh.ether_dhost, to -> haddr, sizeof eh.ether_dhost); + else + memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost)); + if (interface -> hw_address.hlen == sizeof (eh.ether_shost)) + memcpy (eh.ether_shost, interface -> hw_address.haddr, + 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; +} + +/* Decode a hardware header... */ + +ssize_t decode_ethernet_header (interface, buf, bufix, from) + struct interface_info *interface; + unsigned char *buf; + int bufix; + struct hardware *from; +{ + struct ether_header eh; + + memcpy (&eh, buf + bufix, ETHER_HEADER_SIZE); + + memcpy (from -> haddr, eh.ether_shost, sizeof (eh.ether_shost)); + from -> htype = ARPHRD_ETHER; + from -> hlen = sizeof eh.ether_shost; + + return sizeof eh; +} diff --git a/usr.sbin/dhcp/common/hash.c b/usr.sbin/dhcp/common/hash.c index 23892c7ce14..b4bba2186c9 100644 --- a/usr.sbin/dhcp/common/hash.c +++ b/usr.sbin/dhcp/common/hash.c @@ -3,7 +3,7 @@ Routines for manipulating hash tables... */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,14 +40,9 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: hash.c,v 1.1 1998/08/18 03:43:26 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" -static INLINE int do_hash PROTO ((char *, int, int)); +static int do_hash PROTO ((unsigned char *, int, int)); struct hash_table *new_hash () { @@ -59,31 +54,20 @@ struct hash_table *new_hash () return rv; } -static INLINE int do_hash (name, len, size) - char *name; +static int do_hash (name, len, size) + unsigned char *name; int len; int size; { register int accum = 0; - register unsigned char *s = (unsigned char *)name; + register unsigned char *s = name; int i = len; - if (i) { - while (i--) { - /* Add the character in... */ - accum += *s++; - /* Add carry back in... */ - while (accum > 255) { - accum = (accum & 255) + (accum >> 8); - } - } - } else { - while (*s) { - /* Add the character in... */ - accum += *s++; - /* Add carry back in... */ - while (accum > 255) { - accum = (accum & 255) + (accum >> 8); - } + while (i--) { + /* Add the character in... */ + accum += *s++; + /* Add carry back in... */ + while (accum > 255) { + accum = (accum & 255) + (accum >> 8); } } return accum % size; @@ -92,7 +76,7 @@ static INLINE int do_hash (name, len, size) void add_hash (table, name, len, pointer) struct hash_table *table; int len; - char *name; + unsigned char *name; unsigned char *pointer; { int hashno; @@ -100,6 +84,8 @@ void add_hash (table, name, len, pointer) if (!table) return; + if (!len) + len = strlen ((char *)name); hashno = do_hash (name, len, table -> hash_count); bp = new_hash_bucket ("add_hash"); @@ -118,20 +104,23 @@ void add_hash (table, name, len, pointer) void delete_hash_entry (table, name, len) struct hash_table *table; int len; - char *name; + unsigned char *name; { int hashno; struct hash_bucket *bp, *pbp = (struct hash_bucket *)0; if (!table) return; + if (!len) + len = strlen ((char *)name); hashno = do_hash (name, len, table -> hash_count); /* Go through the list looking for an entry that matches; if we find it, delete it. */ for (bp = table -> buckets [hashno]; bp; bp = bp -> next) { - if ((!bp -> len && !strcmp (bp -> name, name)) || + if ((!bp -> len && + !strcmp ((char *)bp -> name, (char *)name)) || (bp -> len == len && !memcmp (bp -> name, name, len))) { if (pbp) { @@ -148,7 +137,7 @@ void delete_hash_entry (table, name, len) unsigned char *hash_lookup (table, name, len) struct hash_table *table; - char *name; + unsigned char *name; int len; { int hashno; @@ -156,19 +145,15 @@ unsigned char *hash_lookup (table, name, len) if (!table) return (unsigned char *)0; + + if (!len) + len = strlen ((char *)name); + hashno = do_hash (name, len, table -> hash_count); - if (len) { - for (bp = table -> buckets [hashno]; bp; bp = bp -> next) { - if (len == bp -> len - && !memcmp (bp -> name, name, len)) - return bp -> value; - } - } else { - for (bp = table -> buckets [hashno]; bp; bp = bp -> next) - if (!strcmp (bp -> name, name)) - return bp -> value; + for (bp = table -> buckets [hashno]; bp; bp = bp -> next) { + if (len == bp -> len && !memcmp (bp -> name, name, len)) + return bp -> value; } return (unsigned char *)0; } - diff --git a/usr.sbin/dhcp/common/icmp.c b/usr.sbin/dhcp/common/icmp.c index d32553a02a3..d64aef0ab44 100644 --- a/usr.sbin/dhcp/common/icmp.c +++ b/usr.sbin/dhcp/common/icmp.c @@ -1,10 +1,10 @@ -/* dhcp.c +/* icmp.c ICMP Protocol engine - for sending out pings and receiving responses. */ /* - * Copyright (c) 1997 The Internet Software Consortium. + * Copyright (c) 1997, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,14 +41,10 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: icmp.c,v 1.2 2001/01/03 16:04:38 ericj Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" -#include "netinet/ip.h" -#include "netinet/ip_icmp.h" +#include +#include +#include static int icmp_protocol_initialized; static int icmp_protocol_fd; @@ -84,7 +80,8 @@ void icmp_startup (routep, handler) (char *)&state, sizeof state) < 0) error ("Unable to disable SO_DONTROUTE on ICMP socket: %m"); - add_protocol ("icmp", icmp_protocol_fd, icmp_echoreply, handler); + add_protocol ("icmp", icmp_protocol_fd, icmp_echoreply, + (void *)handler); } int icmp_echorequest (addr) @@ -97,9 +94,7 @@ int icmp_echorequest (addr) if (!icmp_protocol_initialized) error ("attempt to use ICMP protocol before initialization."); -#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 */ @@ -134,14 +129,14 @@ void icmp_echoreply (protocol) { struct icmp *icfrom; struct sockaddr_in from; - unsigned char icbuf [1500]; + u_int8_t icbuf [1500]; int status; int len; struct iaddr ia; void (*handler) PROTO ((struct iaddr, u_int8_t *, int)); len = sizeof from; - status = recvfrom (protocol -> fd, icbuf, sizeof icbuf, 0, + status = recvfrom (protocol -> fd, (char *)icbuf, sizeof icbuf, 0, (struct sockaddr *)&from, &len); if (status < 0) { warn ("icmp_echoreply: %m"); @@ -163,7 +158,9 @@ void icmp_echoreply (protocol) /* If we were given a second-stage handler, call it. */ if (protocol -> local) { - handler = protocol -> local; + handler = ((void (*) PROTO ((struct iaddr, + u_int8_t *, int))) + protocol -> local); memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr); ia.len = sizeof from.sin_addr; diff --git a/usr.sbin/dhcp/common/inet.c b/usr.sbin/dhcp/common/inet.c index 9f43950c3f6..16097b08185 100644 --- a/usr.sbin/dhcp/common/inet.c +++ b/usr.sbin/dhcp/common/inet.c @@ -64,8 +64,9 @@ struct iaddr subnet_number (addr, mask) } /* 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. */ + * 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; @@ -163,16 +164,21 @@ int addr_eq (addr1, addr2) char *piaddr (addr) struct iaddr addr; { - static char pbuf [4 * 16]; - char *s = pbuf; - int i; + static char pbuf [32]; + char *s; + struct in_addr a; + + memcpy(&a, &(addr.iabuf), sizeof(struct in_addr)); if (addr.len == 0) { - strcpy (s, ""); - } - for (i = 0; i < addr.len; i++) { - sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]); - s += strlen (s); + strlcpy (pbuf, "", sizeof(pbuf)); } - return pbuf; + else { + s = inet_ntoa(a); + if (s != NULL) + strlcpy(pbuf, s, sizeof(pbuf)); + else + strlcpy (pbuf, "", sizeof(pbuf)); + } + return(pbuf); } diff --git a/usr.sbin/dhcp/common/inet_addr.c b/usr.sbin/dhcp/common/inet_addr.c deleted file mode 100644 index 312e63f7f1e..00000000000 --- a/usr.sbin/dhcp/common/inet_addr.c +++ /dev/null @@ -1,150 +0,0 @@ -/* $NetBSD: inet_addr.c,v 1.1.1.1 1997/03/29 21:52:17 mellon Exp $ */ - -/* - * Copyright (c) 1983, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -#else -static char rcsid[] = "$NetBSD: inet_addr.c,v 1.1.1.1 1997/03/29 21:52:17 mellon Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#ifndef lint -static char copyright[] = -"$Id: inet_addr.c,v 1.1 1998/08/18 03:43:26 deraadt Exp $ Copyright (c) 1983, 1990, 1993 The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#ifdef NEED_INET_ATON -/* - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - */ -int -inet_aton(cp, addr) - char *cp; - struct in_addr *addr; -{ - register u_long val; - register int base, n; - register char c; - u_int parts[4]; - register u_int *pp = parts; - - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, other=decimal. - */ - val = 0; base = 10; - if (*cp == '0') { - if (*++cp == 'x' || *cp == 'X') - base = 16, cp++; - else - base = 8; - } - while ((c = *cp) != '\0') { - if (isascii(c) && isdigit(c)) { - val = (val * base) + (c - '0'); - cp++; - continue; - } - if (base == 16 && isascii(c) && isxdigit(c)) { - val = (val << 4) + - (c + 10 - (islower(c) ? 'a' : 'A')); - cp++; - continue; - } - break; - } - if (*cp == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16-bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3 || val > 0xff) - return (0); - *pp++ = val, cp++; - } else - break; - } - /* - * Check for trailing characters. - */ - if (*cp && (!isascii(*cp) || !isspace(*cp))) - return (0); - /* - * Concoct the address according to - * the number of parts specified. - */ - n = pp - parts + 1; - switch (n) { - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffff) - return (0); - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - if (addr) - addr->s_addr = htonl(val); - return (1); -} -#endif diff --git a/usr.sbin/dhcp/common/memory.c b/usr.sbin/dhcp/common/memory.c index b8674016f0a..d383320bf8a 100644 --- a/usr.sbin/dhcp/common/memory.c +++ b/usr.sbin/dhcp/common/memory.c @@ -3,7 +3,7 @@ Memory-resident database... */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: memory.c,v 1.3 2000/07/21 00:33:53 beck Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" static struct subnet *subnets; @@ -206,7 +201,7 @@ void new_address_range (low, high, subnet, dynamic) /* All subnets should have attached shared network structures. */ if (!share) { - strcpy (netbuf, piaddr (subnet -> net)); + strlcpy (netbuf, piaddr (subnet -> net), sizeof(netbuf)); error ("No shared network for network %s (%s)", netbuf, piaddr (subnet -> netmask)); } @@ -222,18 +217,18 @@ void new_address_range (low, high, subnet, dynamic) /* Make sure that high and low addresses are in same subnet. */ net = subnet_number (low, subnet -> netmask); if (!addr_eq (net, subnet_number (high, subnet -> netmask))) { - strcpy (lowbuf, piaddr (low)); - strcpy (highbuf, piaddr (high)); - strcpy (netbuf, piaddr (subnet -> netmask)); + strlcpy (lowbuf, piaddr (low), sizeof(lowbuf)); + strlcpy (highbuf, piaddr (high), sizeof(highbuf)); + strlcpy (netbuf, piaddr (subnet -> netmask), sizeof(netbuf)); error ("Address range %s to %s, netmask %s spans %s!", lowbuf, highbuf, netbuf, "multiple subnets"); } /* Make sure that the addresses are on the correct subnet. */ if (!addr_eq (net, subnet -> net)) { - strcpy (lowbuf, piaddr (low)); - strcpy (highbuf, piaddr (high)); - strcpy (netbuf, piaddr (subnet -> netmask)); + strlcpy (lowbuf, piaddr (low), sizeof(lowbuf)); + strlcpy (highbuf, piaddr (high), sizeof(highbuf)); + strlcpy (netbuf, piaddr (subnet -> netmask), sizeof(netbuf)); error ("Address range %s to %s not on net %s/%s!", lowbuf, highbuf, piaddr (subnet -> net), netbuf); } @@ -251,8 +246,8 @@ void new_address_range (low, high, subnet, dynamic) /* Get a lease structure for each address in the range. */ address_range = new_leases (max - min + 1, "new_address_range"); if (!address_range) { - strcpy (lowbuf, piaddr (low)); - strcpy (highbuf, piaddr (high)); + strlcpy (lowbuf, piaddr (low), sizeof(lowbuf)); + strlcpy (highbuf, piaddr (high), sizeof(highbuf)); error ("No memory for address range %s-%s.", lowbuf, highbuf); } memset (address_range, 0, (sizeof *address_range) * (max - min + 1)); @@ -280,13 +275,14 @@ void new_address_range (low, high, subnet, dynamic) if (!h) warn ("No hostname for %s", inet_ntoa (ia)); else { + int len = strlen(h->h_name) + 1; address_range [i].hostname = - malloc (strlen (h -> h_name) + 1); + malloc (len); if (!address_range [i].hostname) error ("no memory for hostname %s.", h -> h_name); - strcpy (address_range [i].hostname, - h -> h_name); + strlcpy (address_range [i].hostname, + h -> h_name, len); } } @@ -357,36 +353,59 @@ struct subnet *find_grouped_subnet (share, addr) return (struct subnet *)0; } +int subnet_inner_than (subnet, scan, warnp) + struct subnet *subnet, *scan; + int warnp; +{ + if (addr_eq (subnet_number (subnet -> net, scan -> netmask), + scan -> net) || + addr_eq (subnet_number (scan -> net, subnet -> netmask), + subnet -> net)) { + char n1buf [16]; + int i, j; + for (i = 0; i < 32; i++) + if (subnet -> netmask.iabuf [3 - (i >> 3)] + & (1 << (i & 7))) + break; + for (j = 0; j < 32; j++) + if (scan -> netmask.iabuf [3 - (j >> 3)] & + (1 << (j & 7))) + break; + strlcpy (n1buf, piaddr (subnet -> net), sizeof(n1buf)); + if (warnp) + warn ("%ssubnet %s/%d conflicts with subnet %s/%d", + "Warning: ", n1buf, 32 - i, + piaddr (scan -> net), 32 - j); + if (i < j) + return 1; + } + return 0; +} + /* Enter a new subnet into the subnet list. */ void enter_subnet (subnet) struct subnet *subnet; { - struct subnet *scan; + struct subnet *scan, *prev = (struct subnet *)0; /* Check for duplicates... */ for (scan = subnets; scan; scan = scan -> next_subnet) { - if (addr_eq (subnet_number (subnet -> net, scan -> netmask), - scan -> net) || - addr_eq (subnet_number (scan -> net, subnet -> netmask), - subnet -> net)) { - char n1buf [16]; - int i, j; - for (i = 0; i < 32; i++) - if (subnet -> netmask.iabuf [3 - (i >> 3)] - & (1 << (i & 7))) - break; - for (j = 0; j < 32; j++) - if (scan -> netmask.iabuf [3 - (j >> 3)] - & (1 << (j & 7))) - break; - strcpy (n1buf, piaddr (subnet -> net)); - error ("subnet %s/%d conflicts with subnet %s/%d", - n1buf, i, piaddr (scan -> net), j); + /* When we find a conflict, make sure that the + subnet with the narrowest subnet mask comes + first. */ + if (subnet_inner_than (subnet, scan, 1)) { + if (prev) { + prev -> next_subnet = subnet; + } else + subnets = subnet; + subnet -> next_subnet = scan; + return; } + prev = scan; } - /* XXX Sort the nets into a balanced tree to make searching quicker. */ + /* XXX use the BSD radix tree code instead of a linked list. */ subnet -> next_subnet = subnets; subnets = subnet; } @@ -421,9 +440,9 @@ void enter_lease (lease) piaddr (lease -> ip_addr)); } *comp = *lease; - lease -> next = dangling_leases; - lease -> prev = (struct lease *)0; - dangling_leases = lease; + comp -> next = dangling_leases; + comp -> prev = (struct lease *)0; + dangling_leases = comp; } else { /* Record the hostname information in the lease. */ comp -> hostname = lease -> hostname; @@ -504,7 +523,6 @@ int supersede_lease (comp, lease, commit) /* Copy the data files, but not the linkages. */ comp -> starts = lease -> starts; - comp -> timestamp = lease -> timestamp; if (lease -> uid) { if (lease -> uid_len < sizeof (lease -> uid_buf)) { memcpy (comp -> uid_buf, @@ -626,12 +644,15 @@ void release_lease (lease) struct lease lt; lt = *lease; - lt.ends = cur_time; - supersede_lease (lease, <, 1); - note ("Released lease for IP address %s", - piaddr (lease -> ip_addr)); + if (lt.ends > cur_time) { + lt.ends = cur_time; + supersede_lease (lease, <, 1); + note ("Released lease for IP address %s", + piaddr (lease -> ip_addr)); + } } + /* Abandon the specified lease for the specified time. sets it's particulars to zero, the end time apropriately and re-hash it as appropriate. abandons permanently if abtime is 0 */ @@ -838,21 +859,23 @@ struct class *add_class (type, name) return (struct class *)0; memset (class, 0, sizeof *class); - strcpy (tname, name); + strlcpy (tname, name, strlen(name) + 1); class -> name = tname; if (type) add_hash (user_class_hash, - tname, strlen (tname), (unsigned char *)class); + (unsigned char *)tname, strlen (tname), + (unsigned char *)class); else add_hash (vendor_class_hash, - tname, strlen (tname), (unsigned char *)class); + (unsigned char *)tname, strlen (tname), + (unsigned char *)class); return class; } struct class *find_class (type, name, len) int type; - char *name; + unsigned char *name; int len; { struct class *class = @@ -899,16 +922,21 @@ void dump_subnets () struct shared_network *s; struct subnet *n; + note ("Subnets:"); + for (n = subnets; n; n = n -> next_subnet) { + debug (" Subnet %s", piaddr (n -> net)); + debug (" netmask %s", + piaddr (n -> netmask)); + } + note ("Shared networks:"); for (s = shared_networks; s; s = s -> next) { - for (n = subnets; n; n = n -> next_sibling) { - debug ("Subnet %s", piaddr (n -> net)); - debug (" netmask %s", - piaddr (n -> netmask)); - } + note (" %s", s -> name); for (l = s -> leases; l; l = l -> next) { print_lease (l); } - debug ("Last Lease:"); - print_lease (s -> last_lease); + if (s -> last_lease) { + debug (" Last Lease:"); + print_lease (s -> last_lease); + } } } diff --git a/usr.sbin/dhcp/common/nit.c b/usr.sbin/dhcp/common/nit.c deleted file mode 100644 index 296c17a3a1c..00000000000 --- a/usr.sbin/dhcp/common/nit.c +++ /dev/null @@ -1,347 +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) 1996 The Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This software has been written for the Internet Software Consortium - * by Ted Lemon in cooperation with Vixie - * Enterprises. To learn more about the Internet Software Consortium, - * see ``http://www.vix.com/isc''. To learn more about Vixie - * Enterprises, see ``http://www.vix.com''. */ - -#ifndef lint -static char copyright[] = -"$Id: nit.c,v 1.1 1998/08/18 03:43:26 deraadt Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE) -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#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) - error ("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) - error ("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) - error ("Can't get physical layer address for %s: %m", - info -> name); - - /* XXX code below assumes ethernet interface! */ - info -> hw_address.hlen = 6; - info -> hw_address.htype = ARPHRD_ETHER; - memcpy (info -> hw_address.haddr, ifr.ifr_ifru.ifru_addr.sa_data, 6); - - if (ioctl (sock, I_PUSH, "pf") < 0) - error ("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) - error ("Can't set NIT filter: %m"); -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - note ("Sending on NIT/%s/%s", - print_hw_addr (info -> hw_address.htype, - info -> hw_address.hlen, - info -> hw_address.haddr), - (info -> shared_network ? - info -> shared_network -> name : "unattached")); -} -#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) - error ("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) - note ("I_SRDOPT failed on %s: %m", info -> name); - -#if 0 - /* Push on the chunker... */ - if (ioctl (info -> rfdesc, I_PUSH, "nbuf") < 0) - error ("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) - error ("Can't set chunk timeout: %m"); -#endif - - /* Ask for no header... */ - x = 0; - if (ioctl (info -> rfdesc, NIOCSFLAGS, &x) < 0) - error ("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) - error ("Can't set NIT filter on %s: %m", info -> name); - - if (!quiet_interface_discovery) - note ("Listening on NIT/%s/%s", - print_hw_addr (info -> hw_address.htype, - info -> hw_address.hlen, - info -> hw_address.haddr), - (info -> shared_network ? - info -> shared_network -> name : "unattached")); -} -#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; -{ - int bufp; - unsigned char buf [1536 + sizeof (struct sockaddr)]; - struct sockaddr *junk; - struct strbuf ctl, data; - int hw_end; - struct sockaddr_in foo; - - /* Start with the sockaddr struct... */ - junk = (struct sockaddr *)&buf [0]; - bufp = ((unsigned char *)&junk -> sa_data [0]) - &buf [0]; - - /* Assemble the headers... */ - assemble_hw_header (interface, buf, &bufp, hto); - hw_end = bufp; - assemble_udp_ip_header (interface, buf, &bufp, from.s_addr, - to -> sin_addr.s_addr, to -> sin_port, - raw, len); - - /* Copy the data into the buffer (yuk). */ - memcpy (buf + bufp, raw, len); - - /* Set up the sockaddr structure... */ -#if USE_SIN_LEN - junk -> sa_len = hw_end - 2; /* XXX */ -#endif - junk -> sa_family = AF_UNSPEC; - -#if 0 /* Already done. */ - memcpy (junk.sa_data, buf, hw_len); -#endif - - /* Set up the msg_buf structure... */ - ctl.buf = (char *)&buf [0]; - ctl.maxlen = ctl.len = hw_end; - data.buf = (char *)&buf [hw_end]; - data.maxlen = data.len = bufp + len - hw_end; - - return putmsg (interface -> wfdesc, &ctl, &data, 0); -} -#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; -} -#endif diff --git a/usr.sbin/dhcp/common/options.c b/usr.sbin/dhcp/common/options.c index 61064a97673..b88e6fcc0a7 100644 --- a/usr.sbin/dhcp/common/options.c +++ b/usr.sbin/dhcp/common/options.c @@ -3,7 +3,7 @@ DHCP options parsing and reassembly. */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,13 +40,12 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: options.c,v 1.2 2000/11/10 15:33:13 provos Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #define DHCP_OPTION_DATA #include "dhcpd.h" +#include + +int bad_options = 0; +int bad_options_max = 5; /* Parse all available options out of the specified packet. */ @@ -72,10 +71,12 @@ void parse_options (packet) && packet -> options [DHO_DHCP_OPTION_OVERLOAD].data) { if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1) parse_option_buffer (packet, + (unsigned char *) packet -> raw -> file, sizeof packet -> raw -> file); if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2) parse_option_buffer (packet, + (unsigned char *) packet -> raw -> sname, sizeof packet -> raw -> sname); } @@ -97,27 +98,51 @@ void parse_option_buffer (packet, buffer, length) for (s = buffer; *s != DHO_END && s < end; ) { code = s [0]; + /* Pad options don't have a length - just skip them. */ if (code == DHO_PAD) { ++s; continue; } + if (s + 2 > end) { + len = 65536; + goto bogus; + } + /* All other fields (except end, see above) have a one-byte length. */ len = s [1]; - /* If the length is outrageous, the options are bad. */ + /* If the length is outrageous, silently skip the + * rest, and mark the packet bad. Unfortuntely + * some crappy dhcp servers always seem to give + * us garbage on the end of a packet. so rather than + * keep refusing, give up and try to take one after + * seeing a few without anything good. + */ if (s + len + 2 > end) { - warn ("Option %s length %d overflows input buffer.", - dhcp_options [code].name, - len); - packet -> options_valid = 0; + bogus: + bad_options++; + warn ("option %s (%d) %s.", + dhcp_options [code].name, len, + "larger than buffer"); + if (bad_options == bad_options_max) { + packet -> options_valid = 1; + bad_options = 0; + warn ("Many bogus options seen in offers."); + warn ("Taking this offer in spite of bogus"); + warn ("options - hope for the best!"); + } else { + warn ("rejecting bogus offer."); + packet -> options_valid = 0; + } return; } /* If we haven't seen this option before, just make space for it and copy it there. */ if (!packet -> options [code].data) { - if (!(t = (unsigned char *)malloc (len + 1))) + if (!(t = ((unsigned char *) + dmalloc (len + 1, "parse_option_buffer")))) error ("Can't allocate storage for option %s.", dhcp_options [code].name); /* Copy and NUL-terminate the option (in case it's an @@ -130,10 +155,9 @@ void parse_option_buffer (packet, buffer, length) /* If it's a repeat, concatenate it to whatever we last saw. This is really only required for clients, but what the heck... */ - t = (unsigned char *) - malloc (len - + packet -> options [code].len - + 1); + t = ((unsigned char *) + dmalloc (len + packet -> options [code].len + 1, + "parse_option_buffer")); if (!t) error ("Can't expand storage for option %s.", dhcp_options [code].name); @@ -143,7 +167,8 @@ void parse_option_buffer (packet, buffer, length) &s [2], len); packet -> options [code].len += len; t [packet -> options [code].len] = 0; - free (packet -> options [code].data); + dfree (packet -> options [code].data, + "parse_option_buffer"); packet -> options [code].data = t; } s += len + 2; @@ -152,16 +177,20 @@ void parse_option_buffer (packet, buffer, length) } /* cons options into a big buffer, and then split them out into the - three separate buffers if needed. This allows us to cons up a set + 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, options, overload, terminate, bootpp) +int cons_options (inpacket, outpacket, mms, + options, overload, terminate, bootpp, prl, prl_len) struct packet *inpacket; struct dhcp_packet *outpacket; + int mms; struct tree_cache **options; int overload; /* Overload flags that may be set. */ int terminate; int bootpp; + u_int8_t *prl; + int prl_len; { unsigned char priority_list [300]; int priority_len; @@ -176,21 +205,29 @@ int cons_options (inpacket, outpacket, options, overload, terminate, bootpp) 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 (inpacket && inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].data) { - main_buffer_size = - (getUShort (inpacket -> options - [DHO_DHCP_MAX_MESSAGE_SIZE].data) - - DHCP_FIXED_LEN); - /* Enforce a minimum packet size... */ - if (main_buffer_size < (576 - DHCP_FIXED_LEN)) - main_buffer_size = 576 - DHCP_FIXED_LEN; - if (main_buffer_size > sizeof buffer) - main_buffer_size = sizeof buffer; - } else if (bootpp) + if (!mms && + inpacket && + inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].data && + (inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].len >= + sizeof (u_int16_t))) + mms = getUShort (inpacket -> options + [DHO_DHCP_MAX_MESSAGE_SIZE].data); + + /* 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; + else if (bootpp) main_buffer_size = 64; else main_buffer_size = 576 - DHCP_FIXED_LEN; + 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; @@ -210,9 +247,17 @@ int cons_options (inpacket, outpacket, options, overload, terminate, bootpp) prlen = (sizeof priority_list) - priority_len; memcpy (&priority_list [priority_len], - inpacket -> options - [DHO_DHCP_PARAMETER_REQUEST_LIST].data, prlen); + (inpacket -> options + [DHO_DHCP_PARAMETER_REQUEST_LIST].data), prlen); priority_len += prlen; + prl = priority_list; + } else if (prl) { + if (prl_len + priority_len > sizeof priority_list) + prl_len = (sizeof priority_list) - priority_len; + + memcpy (&priority_list [priority_len], prl, prl_len); + priority_len += prl_len; + prl = priority_list; } else { memcpy (&priority_list [priority_len], dhcp_option_default_priority_list, @@ -416,12 +461,14 @@ char *pretty_print_option (code, data, len, emit_commas, emit_quotes) int numhunk = -1; int numelem = 0; char fmtbuf [32]; - int i, j; + int i, j, k; char *op = optbuf; + int opleft = sizeof(optbuf); unsigned char *dp = data; struct in_addr foo; char comma; + /* Code should be between 0 and 255. */ if (code > 255) error ("pretty_print_option: bad code %d\n", code); @@ -448,11 +495,21 @@ char *pretty_print_option (code, data, len, emit_commas, emit_quotes) numhunk = 0; break; case 'X': - fmtbuf [i] = 'x'; + for (k = 0; k < len; k++) { + if (!isascii (data [k]) || + !isprint (data [k])) + break; + } + if (k == len) { + fmtbuf [i] = 't'; + numhunk = -2; + } else { + fmtbuf [i] = 'x'; + hunksize++; + comma = ':'; + numhunk = 0; + } fmtbuf [i + 1] = 0; - hunksize++; - numhunk = 0; - comma = ':'; break; case 't': fmtbuf [i] = 't'; @@ -512,79 +569,135 @@ char *pretty_print_option (code, data, len, emit_commas, emit_quotes) /* Cycle through the array (or hunk) printing the data. */ for (i = 0; i < numhunk; i++) { for (j = 0; j < numelem; j++) { + int opcount; switch (fmtbuf [j]) { case 't': - if (emit_quotes) + if (emit_quotes) { *op++ = '"'; - strcpy (op, dp); - op += strlen (dp); - if (emit_quotes) + opleft--; + } + for (; dp < data + len; dp++) { + if (!isascii (*dp) || + !isprint (*dp)) { + snprintf (op, opleft, "\\%03o", + *dp); + op += 4; + opleft -= 4; + + } else if (*dp == '"' || + *dp == '\'' || + *dp == '$' || + *dp == '`' || + *dp == '\\') { + *op++ = '\\'; + *op++ = *dp; + opleft -= 2; + } else { + *op++ = *dp; + opleft--; + } + } + if (emit_quotes) { *op++ = '"'; + opleft--; + } + *op = 0; break; case 'I': - foo.s_addr = htonl (getULong (dp)); - strcpy (op, inet_ntoa (foo)); + foo.s_addr = htonl(getULong (dp)); + opcount = strlcpy(op, inet_ntoa (foo), + opleft); + opleft -= opcount; dp += 4; break; case 'l': - sprintf (op, "%ld", (long)getLong (dp)); + opcount = snprintf(op, opleft,"%ld", + (long)getLong (dp)); + opleft -= opcount; dp += 4; break; case 'L': - sprintf (op, "%ld", - (unsigned long)getULong (dp)); + opcount = snprintf(op, opleft, "%ld", + (unsigned long)getULong (dp)); + opleft -= opcount; dp += 4; break; case 's': - sprintf (op, "%d", getShort (dp)); + opcount = snprintf(op, opleft, "%d", + getShort (dp)); + opleft -= opcount; dp += 2; break; case 'S': - sprintf (op, "%d", getUShort (dp)); + opcount = snprintf(op, opleft, "%d", + getUShort (dp)); + opleft -= opcount; dp += 2; break; case 'b': - sprintf (op, "%d", *(char *)dp++); + opcount = snprintf(op, opleft, "%d", + *(char *)dp++); + opleft -= opcount; break; case 'B': - sprintf (op, "%d", *dp++); + opcount = snprintf(op, opleft, "%d", *dp++); + opleft -= opcount; break; case 'x': - sprintf (op, "%x", *dp++); + opcount = snprintf(op, opleft, "%x", *dp++); + opleft -= opcount; break; - case 'f': - strcpy (op, *dp++ ? "true" : "false"); + case 'f': + opcount = strlcpy(op, + *dp++ ? "true" : "false", opleft); + opleft -= opcount; break; default: warn ("Unexpected format code %c", fmtbuf [j]); } op += strlen (op); - if (j + 1 < numelem && comma != ':') + opleft -= strlen(op); + if (opleft < 1) { + warn ("dhcp option too large"); + return ""; + } + if (j + 1 < numelem && comma != ':') { *op++ = ' '; + opleft--; + } } if (i + 1 < numhunk) { *op++ = comma; + opleft--; + } + if (opleft < 1) { + warn ("dhcp option too large"); + return ""; } } return optbuf; } -void do_packet (interface, packbuf, len, from_port, from, hfrom) +void do_packet (interface, packet, len, from_port, from, hfrom) struct interface_info *interface; - unsigned char *packbuf; + struct dhcp_packet *packet; int len; - unsigned short from_port; + unsigned int from_port; struct iaddr from; struct hardware *hfrom; { struct packet tp; - struct dhcp_packet tdp; + int i; + + if (packet -> hlen > sizeof packet -> chaddr) { + note ("Discarding packet with invalid hlen."); + return; + } - memcpy (&tdp, packbuf, len); memset (&tp, 0, sizeof tp); - tp.raw = &tdp; + tp.raw = packet; tp.packet_length = len; tp.client_port = from_port; tp.client_addr = from; @@ -600,5 +713,11 @@ void do_packet (interface, packbuf, len, from_port, from, hfrom) dhcp (&tp); else bootp (&tp); + + /* Free the data associated with the options. */ + for (i = 0; i < 256; i++) { + if (tp.options [i].len && tp.options [i].data) + dfree (tp.options [i].data, "do_packet"); + } } diff --git a/usr.sbin/dhcp/common/packet.c b/usr.sbin/dhcp/common/packet.c index 5b136c394ff..499f20cb1bf 100644 --- a/usr.sbin/dhcp/common/packet.c +++ b/usr.sbin/dhcp/common/packet.c @@ -3,7 +3,7 @@ Packet assembly code, originally contributed by Archie Cobbs. */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1999 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,18 +40,11 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: packet.c,v 1.3 2001/01/14 23:01:19 angelos Exp $ Copyright (c) 1996 The Internet Software 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 */ +#include +#include +#include /* Compute the easy part of the checksum on a range of bytes. */ @@ -60,7 +53,7 @@ u_int32_t checksum (buf, nbytes, sum) unsigned nbytes; u_int32_t sum; { - unsigned i; + int i; #ifdef DEBUG_CHECKSUM debug ("checksum (%x %d %x)", buf, nbytes, sum); @@ -92,7 +85,7 @@ u_int32_t checksum (buf, nbytes, sum) return sum; } -/* Finish computing the checksum, and then put it into network byte order. */ +/* Finish computing the sum, and then put it into network byte order. */ u_int32_t wrapsum (sum) u_int32_t sum; @@ -103,7 +96,7 @@ u_int32_t wrapsum (sum) sum = ~sum & 0xFFFF; #ifdef DEBUG_CHECKSUM_VERBOSE - log_debug ("sum = %x", sum); + debug ("sum = %x", sum); #endif #ifdef DEBUG_CHECKSUM @@ -112,7 +105,6 @@ u_int32_t wrapsum (sum) return htons(sum); } -#ifdef PACKET_ASSEMBLY /* Assemble an hardware header... */ /* XXX currently only supports ethernet; doesn't check for other types. */ @@ -122,26 +114,13 @@ void assemble_hw_header (interface, buf, bufix, to) int *bufix; struct hardware *to; { - struct ether_header eh; - - if (to && to -> hlen == 6) /* XXX */ - memcpy (eh.ether_dhost, to -> haddr, sizeof eh.ether_dhost); - else - memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost)); - if (interface -> hw_address.hlen == sizeof (eh.ether_shost)) - memcpy (eh.ether_shost, interface -> hw_address.haddr, - sizeof (eh.ether_shost)); +#if defined (HAVE_TR_SUPPORT) + if (interface -> hw_address.htype == HTYPE_IEEE802) + assemble_tr_header (interface, buf, bufix, to); else - memset (eh.ether_shost, 0x00, sizeof (eh.ether_shost)); - -#ifdef BROKEN_FREEBSD_BPF /* Fixed in FreeBSD 2.2 */ - eh.ether_type = ETHERTYPE_IP; -#else - eh.ether_type = htons (ETHERTYPE_IP); #endif + assemble_ethernet_header (interface, buf, bufix, to); - memcpy (&buf [*bufix], &eh, sizeof eh); - *bufix += sizeof eh; } /* UDP header and IP header assembled together for convenience. */ @@ -153,7 +132,7 @@ void assemble_udp_ip_header (interface, buf, bufix, int *bufix; u_int32_t from; u_int32_t to; - u_int16_t port; + unsigned int port; unsigned char *data; int len; { @@ -189,7 +168,6 @@ void assemble_udp_ip_header (interface, buf, bufix, /* Compute UDP checksums, including the ``pseudo-header'', the UDP header and the data. */ -#if 1 udp.uh_sum = wrapsum (checksum ((unsigned char *)&udp, sizeof udp, checksum (data, len, @@ -199,17 +177,13 @@ void assemble_udp_ip_header (interface, buf, bufix, IPPROTO_UDP + (u_int32_t) ntohs (udp.uh_ulen))))); -#endif /* 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; @@ -217,55 +191,57 @@ ssize_t decode_hw_header (interface, buf, bufix, from) int bufix; struct hardware *from; { - struct ether_header eh; - - memcpy (&eh, buf + bufix, sizeof eh); - -#ifdef USERLAND_FILTER - if (ntohs (eh.ether_type) != ETHERTYPE_IP) - return -1; +#if defined (HAVE_TR_SUPPORT) + if (interface -> hw_address.htype == HTYPE_IEEE802) + return decode_tr_header (interface, buf, bufix, from); + else #endif - memcpy (from -> haddr, eh.ether_shost, sizeof (eh.ether_shost)); - from -> htype = ARPHRD_ETHER; - from -> hlen = sizeof eh.ether_shost; - - return sizeof eh; + 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, len) +ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, buflen) struct interface_info *interface; unsigned char *buf; int bufix; struct sockaddr_in *from; unsigned char *data; - int len; + int 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; + int len = 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 */ - /* Check the IP header checksum - it should be zero. */ + ++ip_packets_seen; if (wrapsum (checksum (buf + bufix, ip_len, 0))) { - note ("Bad IP checksum: %x", - wrapsum (checksum (buf + bufix, sizeof *ip, 0))); + ++ip_packets_bad_checksum; + if (ip_packets_seen > 4 && + (ip_packets_seen / ip_packets_bad_checksum) < 2) { + note ("%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) + 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); @@ -275,10 +251,25 @@ ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, len) if (!data) { data = buf + bufix + ip_len + sizeof *udp; - len -= ip_len + sizeof *udp; + len = ntohs (udp -> uh_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) { + note ("%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) + debug ("accepting packet with data after udp payload."); } -#if 0 usum = udp -> uh_sum; udp -> uh_sum = 0; @@ -286,20 +277,25 @@ ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, len) checksum (data, len, checksum ((unsigned char *) &ip -> ip_src, - sizeof ip -> ip_src, + 2 * sizeof ip -> ip_src, IPPROTO_UDP + (u_int32_t) ntohs (udp -> uh_ulen))))); + udp_packets_seen++; if (usum && usum != sum) { - note ("Bad udp checksum: %x %x", usum, sum); + udp_packets_bad_checksum++; + if (udp_packets_seen > 4 && + (udp_packets_seen / udp_packets_bad_checksum) < 2) { + note ("%d bad udp checksums in %d packets", + udp_packets_bad_checksum, udp_packets_seen); + udp_packets_seen = udp_packets_bad_checksum = 0; + } return -1; } -#endif /* 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/usr.sbin/dhcp/common/parse.c b/usr.sbin/dhcp/common/parse.c index 16390797650..0ffc4b09337 100644 --- a/usr.sbin/dhcp/common/parse.c +++ b/usr.sbin/dhcp/common/parse.c @@ -3,7 +3,7 @@ Common parser code for dhcpd and dhclient. */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: parse.c,v 1.3 2001/01/03 16:04:39 ericj Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include "dhctoken.h" @@ -127,7 +122,7 @@ char *parse_string (cfile) s = (char *)malloc (strlen (val) + 1); if (!s) error ("no memory for string %s.", val); - strcpy (s, val); + strlcpy (s, val, strlen(val) + 1); if (!parse_semi (cfile)) return (char *)0; @@ -158,7 +153,7 @@ char *parse_host_name (cfile) /* Store this identifier... */ if (!(s = (char *)malloc (strlen (val) + 1))) error ("can't allocate temp space for hostname."); - strcpy (s, val); + strlcpy (s, val, strlen(val) + 1); c = cons ((caddr_t)s, c); len += strlen (s) + 1; /* Look for a dot; if it's there, keep going, otherwise @@ -219,6 +214,9 @@ void parse_hardware_param (cfile, hardware) case TOKEN_RING: hardware -> htype = HTYPE_IEEE802; break; + case FDDI: + hardware -> htype = HTYPE_FDDI; + break; default: parse_warn ("expecting a network hardware type"); skip_to_semi (cfile); @@ -244,6 +242,9 @@ void parse_hardware_param (cfile, hardware) hardware -> hlen = hlen; memcpy ((unsigned char *)&hardware -> haddr [0], t, hardware -> hlen); + if (hlen < sizeof hardware -> haddr) + memset (&hardware -> haddr [hlen], 0, + (sizeof hardware -> haddr) - hlen); free (t); } @@ -277,24 +278,25 @@ void parse_lease_time (cfile, timep) } /* No BNF for numeric aggregates - that's defined by the caller. What - this function does is to parse a sequence of numbers separated by - the token specified in separator. If max is zero, any number of + 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, separator, base, size) + max, seperator, base, size) FILE *cfile; unsigned char *buf; int *max; - int separator; + int seperator; int base; int size; { char *val; int token; - unsigned char *bufp = buf, *s, *t; + unsigned char *bufp = buf, *s = NULL; + char *t; int count = 0; pair c = (pair)0; @@ -308,7 +310,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf, do { if (count) { token = peek_token (&val, cfile); - if (token != separator) { + if (token != seperator) { if (!*max) break; if (token != RBRACE && token != LBRACE) @@ -340,10 +342,10 @@ unsigned char *parse_numeric_aggregate (cfile, buf, convert_num (s, val, base, size); s += size / 8; } else { - t = (unsigned char *)malloc (strlen (val) + 1); + t = (char *)malloc (strlen (val) + 1); if (!t) error ("no temp space for number."); - strcpy (t, val); + strlcpy (t, val, strlen(val)+1); c = cons (t, c); } } while (++count != *max); @@ -516,10 +518,10 @@ TIME parse_date (cfile) if (tm.tm_year > 1900) tm.tm_year -= 1900; - /* Slash separating year from month... */ + /* Slash seperating year from month... */ token = next_token (&val, cfile); if (token != SLASH) { - parse_warn ("expected slash separating year from month."); + parse_warn ("expected slash seperating year from month."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; @@ -535,10 +537,10 @@ TIME parse_date (cfile) } tm.tm_mon = atoi (val) - 1; - /* Slash separating month from day... */ + /* Slash seperating month from day... */ token = next_token (&val, cfile); if (token != SLASH) { - parse_warn ("expected slash separating month from day."); + parse_warn ("expected slash seperating month from day."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; @@ -564,10 +566,10 @@ TIME parse_date (cfile) } tm.tm_hour = atoi (val); - /* Colon separating hour from minute... */ + /* Colon seperating hour from minute... */ token = next_token (&val, cfile); if (token != COLON) { - parse_warn ("expected colon separating hour from minute."); + parse_warn ("expected colon seperating hour from minute."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; @@ -583,10 +585,10 @@ TIME parse_date (cfile) } tm.tm_min = atoi (val); - /* Colon separating minute from second... */ + /* Colon seperating minute from second... */ token = next_token (&val, cfile); if (token != COLON) { - parse_warn ("expected colon separating hour from minute."); + parse_warn ("expected colon seperating hour from minute."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; diff --git a/usr.sbin/dhcp/common/print.c b/usr.sbin/dhcp/common/print.c index 7ff64ffdd46..6d2becd5008 100644 --- a/usr.sbin/dhcp/common/print.c +++ b/usr.sbin/dhcp/common/print.c @@ -3,7 +3,7 @@ Turn data structures into printable text. */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: print.c,v 1.1 1998/08/18 03:43:27 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" char *print_hw_addr (htype, hlen, data) @@ -59,10 +54,12 @@ char *print_hw_addr (htype, hlen, data) if (htype == 0 || hlen == 0) { strcpy (habuf, ""); } else { + int slen = sizeof(habuf); s = habuf; for (i = 0; i < hlen; i++) { - sprintf (s, "%02x", data [i]); + snprintf (s, slen, "%02x", data [i]); s += strlen (s); + slen -= (strlen(s) + 1); *s++ = ':'; } *--s = 0; @@ -76,26 +73,26 @@ void print_lease (lease) struct tm *t; char tbuf [32]; - debug (" Lease %s", + debug (" Lease %s", piaddr (lease -> ip_addr)); t = gmtime (&lease -> starts); - strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t); - debug (" start %s", tbuf); + strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); + debug (" start %s", tbuf); t = gmtime (&lease -> ends); - strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t); - debug (" end %s", tbuf); + strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); + debug (" end %s", tbuf); t = gmtime (&lease -> timestamp); - strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t); - debug (" stamp %s", tbuf); + strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); + debug (" stamp %s", tbuf); - debug (" hardware addr = %s", + debug (" hardware addr = %s", print_hw_addr (lease -> hardware_addr.htype, lease -> hardware_addr.hlen, lease -> hardware_addr.haddr)); - debug (" host %s ", + debug (" host %s ", lease -> host ? lease -> host -> name : ""); } @@ -141,8 +138,9 @@ void dump_raw (buf, len) unsigned char *buf; int len; { - int i; + int i, j; char lbuf [80]; + int llen = sizeof(lbuf); int lbix = 0; lbuf [0] = 0; @@ -151,12 +149,16 @@ void dump_raw (buf, len) if ((i & 15) == 0) { if (lbix) note (lbuf); - sprintf (lbuf, "%03x:", i); - lbix = 4; - } else if ((i & 7) == 0) + j = snprintf (lbuf, llen, "%03x:", i); + lbix+=j; + llen-=j; + } else if ((i & 7) == 0) { lbuf [lbix++] = ' '; - sprintf (&lbuf [lbix], " %02x", buf [i]); - lbix += 3; + len--; + } + j = snprintf (&lbuf [lbix], llen, " %02x", buf [i]); + lbix += j; + llen -= j; } note (lbuf); } @@ -178,7 +180,7 @@ void hash_dump (table) if (bp -> len) dump_raw (bp -> name, bp -> len); else - note (bp -> name); + note ((char *)bp -> name); } } } diff --git a/usr.sbin/dhcp/common/raw.c b/usr.sbin/dhcp/common/raw.c deleted file mode 100644 index 38c53121500..00000000000 --- a/usr.sbin/dhcp/common/raw.c +++ /dev/null @@ -1,132 +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) 1995, 1996 The Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This software has been written for the Internet Software Consortium - * by Ted Lemon in cooperation with Vixie - * Enterprises. To learn more about the Internet Software Consortium, - * see ``http://www.vix.com/isc''. To learn more about Vixie - * Enterprises, see ``http://www.vix.com''. */ - -#ifndef lint -static char copyright[] = -"$Id: raw.c,v 1.1 1998/08/18 03:43:27 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -#if defined (USE_RAW_SEND) -#include - -/* 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) - note ("Sending on %s, port %d", - piaddr (info -> address), htons (local_port)); - if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) - error ("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) - error ("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) - error ("Can't set IP_HDRINCL flag: %m"); - - info -> wfdesc = sock; - if (!quiet_interface_discovery) - note ("Sending on Raw/%s/%s", - info -> name, - (info -> shared_network ? - info -> shared_network -> name : "unattached")); -} - -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]; - - /* 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; - - return writev(interface -> wfdesc, iov, 2); -} -#endif /* USE_SOCKET_SEND */ diff --git a/usr.sbin/dhcp/common/resolv.c b/usr.sbin/dhcp/common/resolv.c deleted file mode 100644 index a26608e40ee..00000000000 --- a/usr.sbin/dhcp/common/resolv.c +++ /dev/null @@ -1,201 +0,0 @@ -/* resolv.c - - Parser for /etc/resolv.conf file. */ - -/* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This software has been written for the Internet Software Consortium - * by Ted Lemon in cooperation with Vixie - * Enterprises. To learn more about the Internet Software Consortium, - * see ``http://www.vix.com/isc''. To learn more about Vixie - * Enterprises, see ``http://www.vix.com''. - */ - -#ifndef lint -static char copyright[] = -"$Id: resolv.c,v 1.2 2001/01/03 16:04:39 ericj Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include "dhctoken.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; -{ - FILE *cfile; - char *val; - int token; - struct name_server *sp, *sl, *ns; - struct domain_search_list *dp, *dl, *nd; - - new_parse (path_resolv_conf); - - eol_token = 1; - if ((cfile = fopen (path_resolv_conf, "r")) == NULL) { - warn ("Can't open %s: %m", path_resolv_conf); - return; - } - - do { - token = next_token (&val, cfile); - if (token == EOF) - 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 - ("read_resolv_conf"); - if (!nd) - error ("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, cfile); - } while (token != EOL); - if (token != EOL) { - parse_warn ("junk after domain declaration"); - skip_to_semi (cfile); - } - token = next_token (&val, 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 ("read_resolv_conf"); - if (!ns) - error ("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); - } - } while (1); - token = next_token (&val, cfile); /* Clear the peek buffer */ - - /* 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; - free_name_server (sp, "pick_name_server"); - } 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, "pick_name_server"); - } else - dl = dp; - } - eol_token = 0; -} - -/* Pick a name server from the /etc/resolv.conf file. */ - -struct sockaddr_in *pick_name_server () -{ - 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) { - warn ("Can't stat %s", path_resolv_conf); - return (struct sockaddr_in *)0; - } - if (st.st_mtime > rcdate) { - rcdate = cur_time + 1; - - read_resolv_conf (rcdate); - } - } - - if (name_servers) - return &name_servers -> addr; - return (struct sockaddr_in *)0; -} diff --git a/usr.sbin/dhcp/common/socket.c b/usr.sbin/dhcp/common/socket.c index 2f19de70bd1..03aac4a4a9f 100644 --- a/usr.sbin/dhcp/common/socket.c +++ b/usr.sbin/dhcp/common/socket.c @@ -3,8 +3,8 @@ BSD socket interface code... */ /* - * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,60 +40,8 @@ * Enterprises, see ``http://www.vix.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.2 2000/12/30 17:54:07 angelos Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" -#ifdef USE_SOCKET_FALLBACK -# define USE_SOCKET_SEND -# define if_register_send if_register_fallback -# define send_packet send_fallback -# define if_reinitialize_send if_reinitialize_fallback -#endif - -static int once = 0; - -/* Reinitializes the specified interface after an address change. This - is not required for packet-filter APIs. */ - -#ifdef USE_SOCKET_SEND -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) /* Generic interface registration routine... */ int if_register_socket (info) struct interface_info *info; @@ -102,14 +50,6 @@ int if_register_socket (info) int sock; int flag; -#ifndef SO_BINDTODEVICE - /* Make sure only one interface is registered. */ - if (once) - error ("The standard socket API can only support %s", - "hosts with a single network interface."); - once = 1; -#endif - /* Set up the address we're going to bind to. */ name.sin_family = AF_INET; name.sin_port = local_port; @@ -130,7 +70,7 @@ int if_register_socket (info) flag = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, (char *)&flag, sizeof flag) < 0) - error ("Can't set SO_REUSEPORT option on dhcp socket: %m"); + error ("Can't set SO_REUSEPORT option on dhcp socket: %m"); /* Set the BROADCAST option so that we can broadcast DHCP responses. */ if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, @@ -141,53 +81,24 @@ int if_register_socket (info) if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) error ("Can't bind to dhcp address: %m"); -#ifdef SO_BINDTODEVICE - /* Bind this socket to this interface. */ - if (setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE, - (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) { - error("setting SO_BINDTODEVICE"); - } -#endif - return sock; } -#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */ -#ifdef USE_SOCKET_SEND -void if_register_send (info) +void if_register_fallback (info) struct interface_info *info; { -#ifndef USE_SOCKET_RECEIVE - info -> wfdesc = if_register_socket (info); -#else - info -> wfdesc = info -> rfdesc; -#endif - if (!quiet_interface_discovery) - note ("Sending on Socket/%s/%s", - info -> name, - (info -> shared_network ? - info -> shared_network -> name : "unattached")); -} -#endif /* USE_SOCKET_SEND */ + info -> wfdesc = if_register_socket (info); -#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) - note ("Listening on Socket/%s/%s", + note ("Sending on Socket/%s%s%s", info -> name, + (info -> shared_network ? "/" : ""), (info -> shared_network ? - info -> shared_network -> name : "unattached")); + info -> shared_network -> name : "")); } -#endif /* USE_SOCKET_RECEIVE */ -#ifdef USE_SOCKET_SEND -ssize_t send_packet (interface, packet, raw, len, from, to, hto) +ssize_t send_fallback (interface, packet, raw, len, from, to, hto) struct interface_info *interface; struct packet *packet; struct dhcp_packet *raw; @@ -197,51 +108,19 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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 - return result; -} -#endif /* USE_SOCKET_SEND */ -#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; -{ - int flen = sizeof *from; - int result; + result = sendto (interface -> wfdesc, (char *)raw, len, 0, + (struct sockaddr *)to, sizeof *to); -#ifdef IGNORE_HOSTUNREACH - int retry = 0; - do { -#endif - result = recvfrom (interface -> rfdesc, buf, len, 0, - (struct sockaddr *)from, &flen); -#ifdef IGNORE_HOSTUNREACH - } while (result < 0 && - (errno == EHOSTUNREACH || - errno == ECONNREFUSED) && - retry++ < 10); -#endif + if (result == -1) { + warn ("send_fallback: %m"); + if (errno == ENETUNREACH) + warn ("send_fallback: please consult README file %s", + "regarding broadcast address."); + } return result; } -#endif /* USE_SOCKET_RECEIVE */ -#ifdef USE_SOCKET_FALLBACK /* This just reads in a packet and silently discards it. */ void fallback_discard (protocol) @@ -255,7 +134,6 @@ void fallback_discard (protocol) status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0, (struct sockaddr *)&from, &flen); - if (status < 0) + if (status == 0) warn ("fallback_discard: %m"); } -#endif /* USE_SOCKET_RECEIVE */ diff --git a/usr.sbin/dhcp/common/sysconf.c b/usr.sbin/dhcp/common/sysconf.c deleted file mode 100644 index 98cbb1073cf..00000000000 --- a/usr.sbin/dhcp/common/sysconf.c +++ /dev/null @@ -1,134 +0,0 @@ -/* sysconf.c - - System status watcher... - - !!!Boy, howdy, is this ever not guaranteed not to change!!! */ - -/* - * Copyright (c) 1997 The Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This software has been written for the Internet Software Consortium - * by Ted Lemon in cooperation with Vixie - * Enterprises. To learn more about the Internet Software Consortium, - * see ``http://www.vix.com/isc''. To learn more about Vixie - * Enterprises, see ``http://www.vix.com''. - */ - -#ifndef lint -static char copyright[] = -"$Id: sysconf.c,v 1.1 1998/08/18 03:43:27 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -int sysconf_initialized; -int sysconf_fd; - -void sysconf_startup (handler) - void (*handler) PROTO ((struct sysconf_header *, void *)); -{ - struct sockaddr_un name; - static int once; - - /* Only initialize sysconf once. */ - if (sysconf_initialized) - error ("attempted to reinitialize sysconf protocol"); - sysconf_initialized = 1; - - sysconf_fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (sysconf_fd < 0) - error ("unable to create sysconf socket: %m"); - - /* XXX for now... */ - name.sun_family = PF_UNIX; - strcpy (name.sun_path, "/var/run/sysconf"); - name.sun_len = ((sizeof name) - (sizeof name.sun_path) + - strlen (name.sun_path)); - - if (connect (sysconf_fd, (struct sockaddr *)&name, name.sun_len) < 0) { - if (!once) - warn ("can't connect to sysconf socket: %m"); - once = 1; - close (sysconf_fd); - sysconf_initialized = 0; - add_timeout (cur_time + 60, sysconf_restart, handler); - } else - add_protocol ("sysconf", sysconf_fd, sysconf_message, handler); -} - -void sysconf_restart (v) - void *v; -{ - void (*handler) PROTO ((struct sysconf_header *, void *)) = v; - - sysconf_startup (handler); -} - -void sysconf_message (proto) - struct protocol *proto; -{ - struct sysconf_header hdr; - int status; - char *buf; - void (*handler) PROTO ((struct sysconf_header *, void *)); - - status = read (sysconf_fd, &hdr, sizeof hdr); - if (status < 0) { - warn ("sysconf_message: %m"); - lose: - add_timeout (cur_time + 60, sysconf_restart, proto -> local); - remove_protocol (proto); - return; - } - if (status < sizeof (hdr)) { - warn ("sysconf_message: short message"); - goto lose; - } - - if (hdr.length) { - buf = malloc (hdr.length); - if (!buf) - error ("sysconf_message: can't buffer payload"); - status = read (sysconf_fd, buf, hdr.length); - if (status < 0) - error ("sysconf_message payload read: %m"); - if (status != hdr.length) - error ("sysconf_message payload: short read"); - } else - buf = (char *)0; - - /* Call the handler... */ - if ((handler = proto -> local)) - (*handler) (&hdr, buf); - - if (buf) - free (buf); -} diff --git a/usr.sbin/dhcp/common/tables.c b/usr.sbin/dhcp/common/tables.c index 454962a0857..d336516c01c 100644 --- a/usr.sbin/dhcp/common/tables.c +++ b/usr.sbin/dhcp/common/tables.c @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: tables.c,v 1.1 1998/08/18 03:43:27 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" /* DHCP Option names, formats and codes, from RFC1533. @@ -78,7 +73,7 @@ struct option dhcp_options [256] = { { "lpr-servers", "IA", &dhcp_universe, 9 }, { "impress-servers", "IA", &dhcp_universe, 10 }, { "resource-location-servers", "IA", &dhcp_universe, 11 }, - { "host-name", "t", &dhcp_universe, 12 }, + { "host-name", "X", &dhcp_universe, 12 }, { "boot-size", "S", &dhcp_universe, 13 }, { "merit-dump", "t", &dhcp_universe, 14 }, { "domain-name", "t", &dhcp_universe, 15 }, @@ -130,20 +125,20 @@ struct option dhcp_options [256] = { { "dhcp-client-identifier", "X", &dhcp_universe, 61 }, { "option-62", "X", &dhcp_universe, 62 }, { "option-63", "X", &dhcp_universe, 63 }, - { "option-64", "X", &dhcp_universe, 64 }, - { "option-65", "X", &dhcp_universe, 65 }, - { "option-66", "X", &dhcp_universe, 66 }, - { "option-67", "X", &dhcp_universe, 67 }, - { "option-68", "X", &dhcp_universe, 68 }, - { "option-69", "X", &dhcp_universe, 69 }, - { "option-70", "X", &dhcp_universe, 70 }, - { "option-71", "X", &dhcp_universe, 71 }, - { "option-72", "X", &dhcp_universe, 72 }, - { "option-73", "X", &dhcp_universe, 73 }, - { "option-74", "X", &dhcp_universe, 74 }, - { "option-75", "X", &dhcp_universe, 75 }, - { "option-76", "X", &dhcp_universe, 76 }, - { "dhcp-user-class-identifier", "t", &dhcp_universe, 77 }, + { "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 }, { "option-78", "X", &dhcp_universe, 78 }, { "option-79", "X", &dhcp_universe, 79 }, { "option-80", "X", &dhcp_universe, 80 }, @@ -418,7 +413,7 @@ char *hardware_types [] = { "unknown-5", "token-ring", "unknown-7", - "unknown-8", + "fddi", "unknown-9", "unknown-10", "unknown-11", @@ -681,10 +676,12 @@ void initialize_universes() error ("Can't allocate dhcp option hash table."); for (i = 0; i < 256; i++) { dhcp_universe.options [i] = &dhcp_options [i]; - add_hash (dhcp_universe.hash, dhcp_options [i].name, 0, + add_hash (dhcp_universe.hash, + (unsigned char *)dhcp_options [i].name, 0, (unsigned char *)&dhcp_options [i]); } universe_hash.hash_count = DEFAULT_HASH_SIZE; - add_hash (&universe_hash, dhcp_universe.name, 0, + add_hash (&universe_hash, + (unsigned char *)dhcp_universe.name, 0, (unsigned char *)&dhcp_universe); } diff --git a/usr.sbin/dhcp/common/tree.c b/usr.sbin/dhcp/common/tree.c index aeb48d13026..0fdc4e53fba 100644 --- a/usr.sbin/dhcp/common/tree.c +++ b/usr.sbin/dhcp/common/tree.c @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: tree.c,v 1.1 1998/08/18 03:43:27 deraadt Exp $ Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *, @@ -313,13 +308,10 @@ static TIME do_host_lookup (bufix, bufp, bufcount, dns) /* Otherwise, look it up... */ h = gethostbyname (dns -> hostname); - if (!h) { -#ifndef NO_H_ERRNO + if (h != NULL) { switch (h_errno) { case HOST_NOT_FOUND: -#endif warn ("%s: host unknown.", dns -> hostname); -#ifndef NO_H_ERRNO break; case TRY_AGAIN: warn ("%s: temporary name server failure", @@ -332,8 +324,6 @@ static TIME do_host_lookup (bufix, bufp, bufcount, dns) warn ("%s: no A record associated with address", dns -> hostname); } -#endif /* !NO_H_ERRNO */ - /* Okay to try again after a minute. */ return cur_time + 60; } diff --git a/usr.sbin/dhcp/common/upf.c b/usr.sbin/dhcp/common/upf.c deleted file mode 100644 index a83ac5bf9c6..00000000000 --- a/usr.sbin/dhcp/common/upf.c +++ /dev/null @@ -1,299 +0,0 @@ -/* upf.c - * - * Ultrix PacketFilter interface code. - */ - -/* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This software has been written for the Internet Software Consortium - * by Ted Lemon in cooperation with Vixie - * Enterprises. To learn more about the Internet Software Consortium, - * see ``http://www.vix.com/isc''. To learn more about Vixie - * Enterprises, see ``http://www.vix.com''. - */ - -#ifndef lint -static char copyright[] = -"$Id: upf.c,v 1.2 2001/01/03 16:04:39 ericj Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#if defined (USE_UPF_SEND) || defined (USE_UPF_RECEIVE) -#include -#include - -#include -#include -#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++) { -#ifndef NO_SNPRINTF - snprintf(filename, sizeof(filename), "/dev/pf/pfilt%d", b); -#else - sprintf(filename, "/dev/pf/pfilt%d", b); -#endif - sock = open (filename, O_RDWR, 0); - if (sock < 0) { - if (errno == EBUSY) { - continue; - } else { - error ("Can't find free upf: %m"); - } - } else { - break; - } - } - - /* Set the UPF device to point at this interface. */ - if (ioctl (sock, EIOCSETIF, info -> ifp) < 0) - error ("Can't attach interface %s to upf device %s: %m", - info -> name, filename); - - /* Get the hardware address. */ - if (ioctl (sock, EIOCDEVP, ¶m) < 0) - error ("Can't get interface %s hardware address: %m", - info -> name); - - /* We only know how to do ethernet. */ - if (param.end_dev_type != ENDT_10MB) - error ("Invalid device type on network interface %s: %d", - info -> name, param.end_dev_type); - - if (param.end_addr_len != 6) - error ("Invalid hardware address length on %s: %d", - info -> name, param.end_addr_len); - - info -> hw_address.hlen = 6; - info -> hw_address.htype = ARPHRD_ETHER; - memcpy (&info -> hw_address.haddr [0], 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) - note ("Sending on UPF/%s/%s/%s", - info -> name, - print_hw_addr (info -> hw_address.htype, - info -> hw_address.hlen, - info -> hw_address.haddr), - (info -> shared_network ? - info -> shared_network -> name : "unattached")); -} -#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) - error ("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) - error ("Can't clear pfilt bits: %m"); - - /* Set the ENBATCH and ENCOPYALL bits... */ - bits = ENBATCH | ENCOPYALL; - if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) - error ("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) - error ("Can't install packet filter program: %m"); - if (!quiet_interface_discovery) - note ("Listening on UPF/%s/%s/%s", - info -> name, - print_hw_addr (info -> hw_address.htype, - info -> hw_address.hlen, - info -> hw_address.haddr), - (info -> shared_network ? - info -> shared_network -> name : "unattached")); -} -#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; -{ - int bufp = 0; - unsigned char buf [256]; - struct iovec iov [2]; - - /* Assemble the headers... */ - assemble_hw_header (interface, buf, &bufp, hto); - 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; - - return writev(interface -> wfdesc, iov, 2); -} -#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; -} -#endif diff --git a/usr.sbin/dhcp/dhclient/clparse.c b/usr.sbin/dhcp/dhclient/clparse.c index 8bf65d1dd0f..5f112c10872 100644 --- a/usr.sbin/dhcp/dhclient/clparse.c +++ b/usr.sbin/dhcp/dhclient/clparse.c @@ -40,18 +40,12 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: clparse.c,v 1.7 2001/01/06 22:02:23 angelos Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include "dhctoken.h" -static TIME parsed_time; - struct client_config top_level_config; -u_int32_t requested_lease_time; + +char client_script_name [] = "/sbin/dhclient-script"; /* client-conf-file :== client-declarations EOF client-declarations :== @@ -63,9 +57,7 @@ int read_client_conf () FILE *cfile; char *val; int token; - int declaration = 0; struct client_config *config; - struct client_state *state; struct interface_info *ip; new_parse (path_dhclient_conf); @@ -81,10 +73,10 @@ int read_client_conf () top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; top_level_config.retry_interval = 300; - top_level_config.backoff_cutoff = 120; - top_level_config.initial_interval = 10; + top_level_config.backoff_cutoff = 15; + top_level_config.initial_interval = 3; top_level_config.bootp_policy = ACCEPT; - top_level_config.script_name = "/sbin/dhclient-script"; + top_level_config.script_name = client_script_name; top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_SUBNET_MASK; @@ -106,22 +98,19 @@ int read_client_conf () top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_HOST_NAME; - requested_lease_time = htonl(7200); - top_level_config.send_options [DHO_DHCP_LEASE_TIME].data - = (unsigned char *)&requested_lease_time; - top_level_config.send_options [DHO_DHCP_LEASE_TIME].len - = sizeof requested_lease_time; - - if ((cfile = fopen (path_dhclient_conf, "r")) == NULL) - error ("Can't open %s: %m", path_dhclient_conf); - do { - token = peek_token (&val, cfile); - if (token == EOF) - break; - parse_client_statement (cfile, (struct interface_info *)0, - &top_level_config); - } while (1); - token = next_token (&val, cfile); /* Clear the peek buffer */ + + if ((cfile = fopen (path_dhclient_conf, "r")) != NULL) { + do { + token = peek_token (&val, cfile); + if (token == EOF) + break; + parse_client_statement (cfile, + (struct interface_info *)0, + &top_level_config); + } while (1); + token = next_token (&val, cfile); /* Clear the peek buffer */ + fclose (cfile); + } /* Set up state and config structures for clients that don't have per-interface configuration declarations. */ @@ -331,7 +320,6 @@ int parse_X (cfile, buf, max) int token; char *val; int len; - u_int8_t *s; token = peek_token (&val, cfile); if (token == NUMBER_OR_NAME || token == NUMBER) { @@ -425,9 +413,7 @@ void parse_interface_declaration (cfile, outer_config) int token; char *val; - struct interface_info dummy_interface, *ip; - struct client_state dummy_state; - struct client_config dummy_config; + struct interface_info *ip; token = next_token (&val, cfile); if (token != STRING) { @@ -662,7 +648,6 @@ void parse_client_lease_declaration (cfile, lease, ipp) { int token; char *val; - char *t, *n; struct interface_info *ip; switch (next_token (&val, cfile)) { @@ -751,8 +736,10 @@ struct option *parse_option_decl (cfile, options) skip_to_semi (cfile); return (struct option *)0; } - if ((vendor = (char *)strdup (val)) == NULL) + vendor = malloc (strlen (val) + 1); + if (!vendor) error ("no memory for vendor information."); + strlcpy (vendor, val, strlen(val) + 1); token = peek_token (&val, cfile); if (token == DOT) { /* Go ahead and take the DOT token... */ @@ -769,8 +756,9 @@ struct option *parse_option_decl (cfile, options) /* Look up the option name hash table for the specified vendor. */ - universe = (struct universe *)hash_lookup (&universe_hash, - vendor, 0); + universe = ((struct universe *) + hash_lookup (&universe_hash, + (unsigned char *)vendor, 0)); /* If it's not there, we can't parse the rest of the declaration. */ if (!universe) { @@ -786,7 +774,8 @@ struct option *parse_option_decl (cfile, options) } /* Look up the actual option info... */ - option = (struct option *)hash_lookup (universe -> hash, val, 0); + option = (struct option *)hash_lookup (universe -> hash, + (unsigned char *)val, 0); /* If we didn't get an option structure, it's an undefined option. */ if (!option) { @@ -804,11 +793,6 @@ struct option *parse_option_decl (cfile, options) /* 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; @@ -963,14 +947,17 @@ void parse_string_list (cfile, lp, multiple) return; } +#ifdef OH_THE_HORROR tmp = (struct string_list *)malloc (strlen (val) + 1 + sizeof (struct string_list *)); - if (!tmp) +#endif + tmp = new_string_list(strlen(val) + 1, "parse tmp"); + if (tmp == NULL) error ("no memory for string list entry."); - strcpy (tmp -> string, val); - tmp -> next = (struct string_list *)0; + strlcpy (tmp -> string, val, strlen(val) + 1); + tmp -> next = NULL; /* Store this medium at the end of the media list. */ if (cur) diff --git a/usr.sbin/dhcp/dhclient/dhclient-script.8 b/usr.sbin/dhcp/dhclient/dhclient-script.8 index 42f79a131fa..82212db6cf6 100644 --- a/usr.sbin/dhcp/dhclient/dhclient-script.8 +++ b/usr.sbin/dhcp/dhclient/dhclient-script.8 @@ -35,7 +35,7 @@ .\" Enterprises. To learn more about the Internet Software Consortium, .\" see ``http://www.isc.org/isc''. To learn more about Vixie .\" Enterprises, see ``http://www.vix.com''. -.TH dhclient 8 +.TH dhclient-script 8 .SH NAME dhclient-script - DHCP client network configuration script .SH DESCRIPTION @@ -47,15 +47,49 @@ interface's final configuration once a lease has been acquired. If no lease is acquired, the script is used to test predefined leases, if any, and also called once if no valid lease can be identified. .PP -This script is not meant to be customized by the end user. However, -the script may not work on particular versions of particular operating -systems (indeed, no standard script exists for some operating -systems), so a pioneering user may well need to create a new script or -modify an existing one. In general, customizations specific to a -particular computer should be done in the -.B /etc/dhclient.conf -script. If you find that you can't make such a customization without -customizing dhclient.conf, please submit a bug report. +This script is not meant to be customized by the end user. If local +customizations are needed, they should be possible using the enter and +exit hooks provided (see HOOKS for details). These hooks will allow the +user to override the default behaviour of the client in creating a +.B /etc/resolv.conf +file. +.PP +No standard client script exists for some operating systems, even though +the actual client may work, so a pioneering user may well need to create +a new script or modify an existing one. In general, customizations specific +to a particular computer should be done in the +.B ETCDIR/dhclient.conf +file. If you find that you can't make such a customization without +customizing +.B dhclient-script +or using the enter and exit hooks, please submit a bug report. +.SH HOOKS +When it starts, the client script first defines a shell function, +.B make_resolv_conf , +which is later used to create the +.B /etc/resolv.conf +file. To override the default behaviour, redefine this function in +the enter hook script. +.PP +On after defining the make_resolv_conf function, the client script checks +for the presence of an executable +.B ETCDIR/dhclient-enter-hooks +script, and if present, it invokes the script inline, using the Bourne +shell '.' command. The entire environment documented under OPERATION +is available to this script, which may modify the environment if needed +to change the behaviour of the script. If an error occurs during the +execution of the script, it can set the exit_status variable to a nonzero +value, and +.B ETCDIR/dhclient-script +will exit with that error code immediately after the client script exits. +.PP +After all processing has completed, +.B ETCDIR/dhclient-script +checks for the presence of an executable +.B ETCDIR/dhclient-exit-hooks +script, which if present is invoked using the '.' command. The exit status +is passed in the exit_status shell variable, and will always be zero if the +script succeeded at the task for which it was invoked. .SH OPERATION When dhclient needs to invoke the client configuration script, it writes a shell script into /tmp which defines a variety of variables. @@ -89,7 +123,7 @@ no examples exist yet. The IP address to check is passed in $new_ip_address, and the interface name is passed in $interface. .SH ARPCHECK The DHCP client wants to know if a response to the ARP request send -using ARPCHECK has been received. If one has, the script should exit +using ARPSEND has been received. If one has, the script should exit with a nonzero status, indicating that the offered address has already been requested and should be declined. $new_ip_address and $interface are set as with ARPSEND. @@ -107,9 +141,8 @@ When a binding has been completed, a lot of network parameters are likely to need to be set up. A new /etc/resolv.conf needs to be created, using the values of $new_domain_name and $new_domain_name_servers (which may list more than one server, -separated by spaces). If /etc/resolv.conf.tail exists, it is appended -to the newly-created /etc/resolv.conf file. A default route should -be set using $new_routers, and static routes may need to be set up using +seperated by spaces). A default route should be set using +$new_routers, and static routes may need to be set up using $new_static_routes. .PP If an IP alias has been declared, it must be set up here. The alias diff --git a/usr.sbin/dhcp/dhclient/dhclient.8 b/usr.sbin/dhcp/dhclient/dhclient.8 index 576f08f3c9f..eae843776c7 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.8 +++ b/usr.sbin/dhcp/dhclient/dhclient.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: dhclient.8,v 1.10 2000/10/30 02:35:33 deraadt Exp $ +.\" dhclient.8 .\" .\" Copyright (c) 1997 The Internet Software Consortium. .\" All rights reserved. @@ -35,178 +35,141 @@ .\" Enterprises. To learn more about the Internet Software Consortium, .\" see ``http://www.isc.org/isc''. To learn more about Vixie .\" Enterprises, see ``http://www.vix.com''. -.Dd October 1, 1999 -.Dt DHCLIENT 8 -.Os -.Sh NAME -.Nm dhclient -.Nd Dynamic Host Configuration Protocol (DHCP) Client -.Sh SYNOPSIS -.Nm -.Op Fl 1du -.Op Fl p Ar port -.Op Ar interface ... -.Sh DESCRIPTION -The -.Nm -utility provides a means for configuring network interfaces using DHCP, BOOTP, -or if these protocols fail, by statically assigning an address. -.Pp -The names of the network interfaces that -.Nm -should attempt to -configure may be specified on the command line. -If no interface names are given, -.Nm -will identify all network -interfaces, eliminating non-broadcast interfaces if possible, and -attempt to configure each one. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl 1 -Forces -.Nm -to exit if it failed to configure an interface. -.It Fl d -Forces -.Nm -to always run as a foreground process. -By default, -.Nm -runs in the foreground until it has configured an interface, and then -will revert to running in the background. -.It Fl u -Forces dhclient to reject leases with unknown options in them. The default -behaviour is to accept such lease offers -.It Fl p Ar port -Specifies the UDP -.Ar port -.Nm -should listen on, instead of the default (68). -.El -.Pp +.TH dhclient 8 +.SH NAME +dhclient - Dynamic Host Configuration Protocol Client +.SH SYNOPSIS +.B dhclient +[ +.B -p +.I port +] +[ +.B -d +] +[ +.I if0 +[ +.I ...ifN +] +] +.SH DESCRIPTION +The Internet Software Consortium DHCP Client, dhclient, provides a +means for configuring one or more network interfaces using the Dynamic +Host Configuration Protocol, BOOTP protocol, or if these protocols +fail, by statically assigning an address. +.SH OPERATION +.PP The DHCP protocol allows a host to contact a central server which maintains a list of IP addresses which may be assigned on one or more -subnets. -A DHCP client may request an address from this pool, and -then use it on a temporary basis for communication on the network. -The DHCP protocol also provides a mechanism whereby a client can learn +subnets. A DHCP client may request an address from this pool, and +then use it on a temporary basis for communication on network. The +DHCP protocol also provides a mechanism whereby a client can learn important details about the network to which it is attached, such as the location of a default router, the location of a name server, and so on. -.Pp -On startup, -.Nm -reads -.Pa /etc/dhclient.conf -for configuration instructions. -It then gets a list of all the -network interfaces that are configured in the current system. -It then attempts to configure each interface with DHCP. -.Pp +.PP +On startup, dhclient reads the +.IR dhclient.conf +for configuration instructions. It then gets a list of all the +network interfaces that are configured in the current system. For +each interface, it attempts to configure the interface using the DHCP +protocol. +.PP In order to keep track of leases across system reboots and server -restarts, -.Nm -keeps a list of leases it has been assigned in the -.Pa /var/db/dhclient.leases -file. -On startup, after reading the -.Pa dhclient.conf -file, -.Nm -reads the leases file to refresh its memory about what leases it has been -assigned. -.Pp -When a new lease is acquired, it is appended to the end of -.Pa /var/db/dhclient.leases . -In order to prevent the file from becoming arbitrarily large, from time to time -.Nm -creates a new -.Pa dhclient.leases -file from its in-core lease database. -The old version of is retained under the name -.Pa /var/db/dhcpd.leases~ -until the next time -.Nm -rewrites the database. -.Pp +restarts, dhclient keeps a list of leases it has been assigned in the +dhclient.leases(5) file. On startup, after reading the dhclient.conf +file, dhclient reads the dhclient.leases file to refresh its memory +about what leases it has been assigned. +.PP +When a new lease is acquired, it is appended to the end of the +dhclient.leases file. In order to prevent the file from becoming +arbitrarily large, from time to time dhclient creates a new +dhclient.leases file from its in-core lease database. The old version +of the dhclient.leases file is retained under the name +.IR dhcpd.leases~ +until the next time dhclient rewrites the database. +.PP Old leases are kept around in case the DHCP server is unavailable when -.Nm -is first invoked (generally during the initial system boot -process). -In that event, old leases from the -.Pa dhclient.leases -file which have not yet expired are tested, and if they are determined to +dhclient is first invoked (generally during the initial system boot +process). In that event, old leases from the dhclient.leases file +which have not yet expired are tested, and if they are determined to be valid, they are used until either they expire or the DHCP server becomes available. -.Pp +.PP A mobile host which may sometimes need to access a network on which no DHCP server exists may be preloaded with a lease for a fixed -address on that network. -When all attempts to contact a DHCP server have failed, -.Nm -will try to validate the static lease, and if it -succeeds, it will use that lease until it is restarted. -.Pp +address on that network. When all attempts to contact a DHCP server +have failed, dhclient will try to validate the static lease, and if it +succeeds, will use that lease until it is restarted. +.PP A mobile host may also travel to some networks on which DHCP is not -available but BOOTP is. -In that case, it may be advantageous to +available but BOOTP is. In that case, it may be advantageous to arrange with the network administrator for an entry on the BOOTP database, so that the host can boot quickly on that network rather than cycling through the list of old leases. -.Sh NOTES -You must have the Berkeley Packet Filter (BPF) configured in your kernel. -.Nm -requires at least one -.Pa /dev/bpf* -file for each broadcast network interface that is attached to your system. -See -.Xr bpf 4 -for more information. -.Sh FILES -.Bl -tag -width /var/db/dhclient.leases~ -compact -.It Pa /etc/dhclient.conf -DHCP client configuration file -.It Pa /var/db/dhclient.leases -database of acquired leases -.It Pa /var/db/dhclient.leases~ -backup of dhclient.leases -.It Pa /var/run/dhclient.pid -process ID of -.Nm -.El -.Sh SEE ALSO -.Xr dhclient.conf 5 , -.Xr dhclient.leases 5 , -.Xr dhclient-script 8 , -.Xr dhcp 8 , -.Xr dhcpd 8 , -.Xr dhcrelay 8 -.Sh AUTHOR -.Nm +.SH COMMAND LINE +.PP +The names of the network interfaces that dhclient should attempt to +configure may be specified on the command line. If no interface names +are specified on the command line dhclient will identify all network +interfaces, elimininating non-broadcast interfaces if possible, and +attempt to configure each interface. +.PP +If dhclient should listen and transmit on a port other than the +standard (port 68), the +.B -p +flag may used. It should be followed by the udp port number that +dhclient should use. This is mostly useful for debugging purposes. +If the +.B -p +flag is specified, the client will transmit responses to servers at a +port number that is one less than the one specified - i.e., if you +specify +.B -p +68, then the client will listen on port 68 and transmit to port 67. +Datagrams that must go through relay agents are sent to the port +number specified with the +.B -p +flag - if you wish to use alternate port numbers, you must configure +any relay agents you are using to use the same alternate port numbers. +.PP +Dhclient will normally run in the foreground until it has configured +an interface, and then will revert to running in the background. +To run force dhclient to always run as a foreground process, the +.B -d +flag should be specified. This is useful when running dhclient under +a debugger, or when running it out of inittab on System V systems. +.PP +.SH CONFIGURATION +The syntax of the dhclient.conf(8) file is discussed seperately. +.SH FILES +.B ETCDIR/dhclient.conf, DBDIR/dhclient.leases, RUNDIR/dhclient.pid, +.B DBDIR/dhclient.leases~. +.SH SEE ALSO +dhcpd(8), dhcrelay(8), dhclient.conf(5), dhclient.leases(5) +.SH AUTHOR +.B dhclient(8) has been written for the Internet Software Consortium by Ted Lemon in cooperation with Vixie -Enterprises. -To learn more about the Internet Software Consortium, see -.Pp -.Dl http://www.vix.com/isc. -.Pp -To learn more about Vixie Enterprises, see -.Pp -.Dl http://www.vix.com. -.Pp +Enterprises. To learn more about the Internet Software Consortium, +see +.B http://www.vix.com/isc. +To learn more about Vixie +Enterprises, see +.B http://www.vix.com. +.PP This client was substantially modified and enhanced by Elliot Poger for use on Linux while he was working on the MosquitoNet project at Stanford. -.Pp +.PP The current version owes much to Elliot's Linux enhancements, but was substantially reorganized and partially rewritten by Ted Lemon so as to use the same networking framework that the Internet Software -Consortium DHCP server uses. -Much system-specific configuration code +Consortium DHCP server uses. Much system-specific configuration code was moved into a shell script so that as support for more operating systems is added, it will not be necessary to port and maintain system-specific configuration code to these operating systems - instead, the shell script can invoke the native tools to accomplish the same purpose. +.PP diff --git a/usr.sbin/dhcp/dhclient/dhclient.c b/usr.sbin/dhcp/dhclient/dhclient.c index 848b9d9fea3..50fdb0ba47d 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.c +++ b/usr.sbin/dhcp/dhclient/dhclient.c @@ -3,8 +3,8 @@ DHCP Client. */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -54,26 +54,21 @@ * purpose. */ -#ifndef lint -static char copyright[] = -"$Id: dhclient.c,v 1.17 2001/06/04 23:41:56 angelos Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" - +#include "version.h" #define PERIOD 0x2e -#define hyphenchar(c) ((c) == 0x2d) +#define hyphenchar(c) ((c) == 0x2d) #define bslashchar(c) ((c) == 0x5c) #define periodchar(c) ((c) == PERIOD) #define asterchar(c) ((c) == 0x2a) #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ - || ((c) >= 0x61 && (c) <= 0x7a)) + || ((c) >= 0x61 && (c) <= 0x7a)) #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) #define borderchar(c) (alphachar(c) || digitchar(c)) #define middlechar(c) (borderchar(c) || hyphenchar(c)) -#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) TIME cur_time; TIME default_lease_time = 43200; /* 12 hours... */ @@ -82,6 +77,7 @@ struct tree_cache *global_options [256]; char *path_dhclient_conf = _PATH_DHCLIENT_CONF; char *path_dhclient_db = _PATH_DHCLIENT_DB; +char *path_dhclient_pid = _PATH_DHCLIENT_PID; int interfaces_requested = 0; @@ -96,23 +92,29 @@ struct sockaddr_in sockaddr_broadcast; assert (state_is == state_shouldbe). */ #define ASSERT_STATE(state_is, state_shouldbe) {} -#ifdef USE_FALLBACK -struct interface_info fallback_interface; -#endif - u_int16_t local_port; u_int16_t remote_port; int log_priority; int no_daemon; -int onetry; +int save_scripts; +int onetry = 0; int unknown_ok = 1; -static void usage PROTO ((void)); +static char copyright[] = +"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; +static char arr [] = "All rights reserved."; +static char message [] = "Internet Software Consortium DHCP Client"; +static char contrib [] = "Please contribute if you find this software useful."; +static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html"; + +static void usage PROTO ((char *)); static int check_option (struct client_lease *l, int option); static int ipv4addrs(char * buf); +static int res_hnok(const char *dn); + int main (argc, argv, envp) int argc; char **argv, **envp; @@ -120,24 +122,55 @@ int main (argc, argv, envp) int i, fd; struct servent *ent; struct interface_info *ip; + int seed; + int quiet = 0; + char *s; + + s = strrchr (argv [0], '/'); + if (!s) + s = argv [0]; + else + s++; + + /* Initially, log errors to stderr as well as to syslogd. */ + openlog (s, LOG_NDELAY, DHCPD_LOG_FACILITY); - openlog ("dhclient", LOG_NDELAY, LOG_DAEMON); +#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__)) + setlogmask (LOG_UPTO (LOG_INFO)); +#endif for (i = 1; i < argc; i++) { if (!strcmp (argv [i], "-p")) { if (++i == argc) - usage (); - local_port = htons (atoi (argv [i])); - debug ("binding to user-specified port %d", - ntohs (local_port)); + usage (s); + local_port = htons(atoi(argv [i])); + debug("binding to user-specified port %d", + ntohs(local_port)); } else if (!strcmp (argv [i], "-d")) { no_daemon = 1; + } else if (!strcmp (argv [i], "-D")) { + save_scripts = 1; + } else if (!strcmp (argv [i], "-cf")) { + if (++i == argc) + usage (s); + path_dhclient_conf = argv [i]; + } else if (!strcmp (argv [i], "-pf")) { + if (++i == argc) + usage (s); + path_dhclient_pid = argv [i]; + } else if (!strcmp (argv [i], "-lf")) { + if (++i == argc) + usage (s); + path_dhclient_db = argv [i]; + } else if (!strcmp (argv [i], "-q")) { + quiet = 1; + quiet_interface_discovery = 1; } else if (!strcmp (argv [i], "-u")) { unknown_ok = 0; } else if (!strcmp (argv [i], "-1")) { onetry = 1; } else if (argv [i][0] == '-') { - usage (); + usage (s); } else { struct interface_info *tmp = ((struct interface_info *) @@ -146,75 +179,83 @@ int main (argc, argv, envp) error ("Insufficient memory to %s %s", "record interface", argv [i]); memset (tmp, 0, sizeof *tmp); - strlcpy (tmp -> name, argv [i], IFNAMSIZ); - tmp -> next = interfaces; - tmp -> flags = INTERFACE_REQUESTED; + strlcpy (tmp->name, argv [i], IFNAMSIZ); + tmp->next = interfaces; + tmp->flags = INTERFACE_REQUESTED; interfaces_requested = 1; interfaces = tmp; } } + + if (!quiet) { + note("%s %s", message, DHCP_VERSION); + } else + log_perror = 0; + /* Default to the DHCP/BOOTP port. */ if (!local_port) { - ent = getservbyname ("dhcpc", "udp"); + ent = getservbyname("dhcpc", "udp"); if (!ent) - local_port = htons (68); + local_port = htons(68); else - local_port = ent -> s_port; + local_port = ent->s_port; } - remote_port = htons (ntohs (local_port) - 1); /* XXX */ + remote_port = htons(ntohs(local_port) - 1); /* XXX */ /* Get the current time... */ - GET_TIME (&cur_time); + GET_TIME(&cur_time); sockaddr_broadcast.sin_family = AF_INET; sockaddr_broadcast.sin_port = remote_port; sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; -#ifdef HAVE_SA_LEN sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast; -#endif inaddr_any.s_addr = INADDR_ANY; /* Discover all the network interfaces. */ - discover_interfaces (DISCOVER_UNCONFIGURED); + discover_interfaces(DISCOVER_UNCONFIGURED); /* Parse the dhclient.conf file. */ - read_client_conf (); + read_client_conf(); /* Lock the leases file */ - fd = open (path_dhclient_db, O_RDONLY | O_EXLOCK | O_CREAT, 0); + fd = open(path_dhclient_db, O_RDONLY | O_EXLOCK | O_CREAT, 0); if (fd < 0) - error ("can't open and lock %s: %m", path_dhclient_db); + error("can't open and lock %s: %m", path_dhclient_db); /* Parse the lease database. */ - read_client_leases (); + read_client_leases(); /* Rewrite the lease database... */ - rewrite_client_leases (); + rewrite_client_leases(); /* Close and unlock */ close(fd); - + /* If no broadcast interfaces were discovered, call the script and tell it so. */ if (!interfaces) { - script_init ((struct interface_info *)0, "NBI", + script_init((struct interface_info *)0, "NBI", (struct string_list *)0); - script_go ((struct interface_info *)0); + script_go((struct interface_info *)0); + note("No broadcast interfaces found - exiting."); /* Nothing more to do. */ - exit (0); + exit(0); } else { /* Call the script with the list of interfaces. */ - for (ip = interfaces; ip; ip = ip -> next) { - if ((interfaces_requested == 0) || - (ip->flags == INTERFACE_REQUESTED)) { - script_init (ip, "PREINIT", - (struct string_list *)0); - if (ip -> client -> alias) - script_write_params(ip, "alias_", - ip->client->alias); - script_go (ip); - } + for (ip = interfaces; ip; ip = ip->next) { + /* If interfaces were specified, don't configure + interfaces that weren't specified! */ + if (interfaces_requested && + ((ip->flags & (INTERFACE_REQUESTED | + INTERFACE_AUTOMATIC)) != + INTERFACE_REQUESTED)) + continue; + script_init(ip, "PREINIT", (struct string_list *)0); + if (ip->client->alias) + script_write_params(ip, "alias_", + ip->client->alias); + script_go(ip); } } @@ -222,44 +263,67 @@ int main (argc, argv, envp) are relevant should be running, so now we once again call discover_interfaces(), and this time ask it to actually set up the interfaces. */ - discover_interfaces (interfaces_requested + discover_interfaces(interfaces_requested ? DISCOVER_REQUESTED : DISCOVER_RUNNING); + /* Make up a seed for the random number generator from current + time plus the sum of the last four bytes of each + interface's hardware address interpreted as an integer. + Not much entropy, but we're booting, so we're not likely to + find anything better. */ + seed = 0; /* Unfortunately, what's on the stack isn't random. :') */ + for(ip = interfaces; ip; ip = ip->next) { + int junk; + memcpy(&junk, + &ip->hw_address.haddr [ip->hw_address.hlen - + sizeof seed], sizeof seed); + seed += junk; + } + srandom(seed + cur_time); + /* Start a configuration state machine for each interface. */ - for (ip = interfaces; ip; ip = ip -> next) { - ip -> client -> state = S_INIT; - state_reboot (ip); + for(ip = interfaces; ip; ip = ip->next) { + ip->client->state = S_INIT; + state_reboot(ip); } /* Set up the bootp packet handler... */ bootp_packet_handler = do_packet; /* Start dispatching packets and timeouts... */ - dispatch (); + dispatch(); /*NOTREACHED*/ return 0; } -static void usage () +static void usage (appname) + char *appname; { - error ("Usage: dhclient [-1] [-c] [-p ] [interface]"); + note("%s", message); + note("%s", copyright); + note("%s", arr); + note(""); + note("%s", contrib); + note("%s", url); + note(""); + + warn("Usage: %s [-c1u] [-p ] [-lf lease-file]", appname); + error(" [-pf pidfile] [interface]"); } void cleanup () { - /* Make sure the pidfile is gone. */ - (void) unlink (_PATH_DHCLIENT_PID); } /* Individual States: * * Each routine is called from the dhclient_state_machine() in one of * these conditions: - * -> entering INIT state - * -> recvpacket_flag == 0: timeout in this state - * -> otherwise: received a packet in this state + *->entering INIT state + *->recvpacket_flag == 0: timeout in this state + *->otherwise: received a packet in this state * * Return conditions as handled by dhclient_state_machine(): * Returns 1, sendpacket_flag = 1: send packet, reset timer. @@ -288,25 +352,29 @@ void state_reboot (ipp) struct interface_info *ip = ipp; /* If we don't remember an active lease, go straight to INIT. */ - if (!ip -> client -> active || - ip -> client -> active -> is_bootp) { + if (!ip->client->active || + ip->client->active->is_bootp) { state_init (ip); return; } /* We are in the rebooting state. */ - ip -> client -> state = S_REBOOTING; + ip->client->state = S_REBOOTING; + + /* make_request doesn't initialize xid because it normally comes + from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER, + so pick an xid now. */ + ip->client->xid = random (); /* Make a DHCPREQUEST packet, and set appropriate per-interface flags. */ - make_request (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; - ip -> client -> destination = iaddr_broadcast; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; + make_request (ip, ip->client->active); + ip->client->destination = iaddr_broadcast; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; /* Zap the medium list... */ - ip -> client -> medium = (struct string_list *)0; + ip->client->medium = (struct string_list *)0; /* Send out the first DHCPREQUEST packet. */ send_request (ip); @@ -324,12 +392,12 @@ void state_init (ipp) /* Make a DHCPDISCOVER packet, and set appropriate per-interface flags. */ - make_discover (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; - ip -> client -> destination = iaddr_broadcast; - ip -> client -> state = S_SELECTING; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; + make_discover (ip, ip->client->active); + ip->client->xid = ip->client->packet.xid; + ip->client->destination = iaddr_broadcast; + ip->client->state = S_SELECTING; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; /* Add an immediate timeout to cause the first DHCPDISCOVER packet to go out. */ @@ -357,13 +425,13 @@ void state_selecting (ipp) the only criterion by which we judge leases is whether or not we get a response when we arp for them. */ picked = (struct client_lease *)0; - for (lp = ip -> client -> offered_leases; lp; lp = next) { - next = lp -> next; + for (lp = ip->client->offered_leases; lp; lp = next) { + next = lp->next; /* Check to see if we got an ARPREPLY for the address in this particular lease. */ if (!picked) { - script_init (ip, "ARPCHECK", lp -> medium); + script_init (ip, "ARPCHECK", lp->medium); script_write_params (ip, "check_", lp); /* If the ARPCHECK code detects another @@ -376,33 +444,33 @@ void state_selecting (ipp) goto freeit; } picked = lp; - picked -> next = (struct client_lease *)0; + picked->next = (struct client_lease *)0; } else { freeit: free_client_lease (lp); } } - ip -> client -> offered_leases = (struct client_lease *)0; + ip->client->offered_leases = (struct client_lease *)0; /* If we just tossed all the leases we were offered, go back to square one. */ if (!picked) { - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; state_init (ip); return; } /* If it was a BOOTREPLY, we can just take the address right now. */ - if (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) { - ip -> client -> new = picked; + if (!picked->options [DHO_DHCP_MESSAGE_TYPE].len) { + ip->client->new = picked; /* Make up some lease expiry times XXX these should be configurable. */ - ip -> client -> new -> expiry = cur_time + 12000; - ip -> client -> new -> renewal += cur_time + 8000; - ip -> client -> new -> rebind += cur_time + 10000; + ip->client->new->expiry = cur_time + 12000; + ip->client->new->renewal += cur_time + 8000; + ip->client->new->rebind += cur_time + 10000; - ip -> client -> state = S_REQUESTING; + ip->client->state = S_REQUESTING; /* Bind to the address we received. */ bind_lease (ip); @@ -410,14 +478,14 @@ void state_selecting (ipp) } /* Go to the REQUESTING state. */ - ip -> client -> destination = iaddr_broadcast; - ip -> client -> state = S_REQUESTING; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; + ip->client->destination = iaddr_broadcast; + ip->client->state = S_REQUESTING; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; /* Make a DHCPREQUEST packet from the lease we picked. */ make_request (ip, picked); - ip -> client -> xid = ip -> client -> packet.xid; + ip->client->xid = ip->client->packet.xid; /* Toss the lease we picked - we'll get it back in a DHCPACK. */ free_client_lease (picked); @@ -432,26 +500,33 @@ void state_selecting (ipp) void dhcpack (packet) struct packet *packet; { - struct interface_info *ip = packet -> interface; + struct interface_info *ip = packet->interface; struct client_lease *lease; - int i; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ - if (packet -> interface -> client -> xid != packet -> raw -> xid) { + if (packet->interface->client->xid != packet->raw->xid || + (packet->interface->hw_address.hlen != + packet->raw->hlen) || + (memcmp (packet->interface->hw_address.haddr, + packet->raw->chaddr, packet->raw->hlen))) { +#if defined (DEBUG) debug ("DHCPACK in wrong transaction."); +#endif return; } - if (ip -> client -> state != S_REBOOTING && - ip -> client -> state != S_REQUESTING && - ip -> client -> state != S_RENEWING && - ip -> client -> state != S_REBINDING) { + if (ip->client->state != S_REBOOTING && + ip->client->state != S_REQUESTING && + ip->client->state != S_RENEWING && + ip->client->state != S_REBINDING) { +#if defined (DEBUG) debug ("DHCPACK in wrong state."); +#endif return; } - note ("DHCPACK from %s", piaddr (packet -> client_addr)); + note ("DHCPACK from %s", piaddr (packet->client_addr)); lease = packet_to_lease (packet); if (!lease) { @@ -459,43 +534,54 @@ void dhcpack (packet) return; } - ip -> client -> new = lease; + ip->client->new = lease; /* Stop resending DHCPREQUEST. */ cancel_timeout (send_request, ip); /* Figure out the lease time. */ - if (ip -> client -> new -> options [DHO_DHCP_LEASE_TIME].data) - ip -> client -> new -> expiry = - getULong (ip -> client -> - new -> options [DHO_DHCP_LEASE_TIME].data); + if (ip->client->new->options [DHO_DHCP_LEASE_TIME].data) + ip->client->new->expiry = + getULong (ip->client -> + new->options [DHO_DHCP_LEASE_TIME].data); else - ip -> client -> new -> expiry = default_lease_time; + ip->client->new->expiry = default_lease_time; + /* A number that looks negative here is really just very large, + because the lease expiry offset is unsigned. */ + if (ip->client->new->expiry < 0) + ip->client->new->expiry = TIME_MAX; /* Take the server-provided renewal time if there is one; otherwise figure it out according to the spec. */ - if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len) - ip -> client -> new -> renewal = - getULong (ip -> client -> - new -> options [DHO_DHCP_RENEWAL_TIME].data); + if (ip->client->new->options [DHO_DHCP_RENEWAL_TIME].len) + ip->client->new->renewal = + getULong (ip->client -> + new->options [DHO_DHCP_RENEWAL_TIME].data); else - ip -> client -> new -> renewal = - ip -> client -> new -> expiry / 2; + ip->client->new->renewal = + ip->client->new->expiry / 2; /* Same deal with the rebind time. */ - if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len) - ip -> client -> new -> rebind = - getULong (ip -> client -> new -> + if (ip->client->new->options [DHO_DHCP_REBINDING_TIME].len) + ip->client->new->rebind = + getULong (ip->client->new -> options [DHO_DHCP_REBINDING_TIME].data); else - ip -> client -> new -> rebind = - ip -> client -> new -> renewal + - ip -> client -> new -> renewal / 2 + - ip -> client -> new -> renewal / 4; - - ip -> client -> new -> expiry += cur_time; - ip -> client -> new -> renewal += cur_time; - ip -> client -> new -> rebind += cur_time; + ip->client->new->rebind = + ip->client->new->renewal + + ip->client->new->renewal / 2 + + ip->client->new->renewal / 4; + + ip->client->new->expiry += cur_time; + /* Lease lengths can never be negative. */ + if (ip->client->new->expiry < cur_time) + ip->client->new->expiry = TIME_MAX; + ip->client->new->renewal += cur_time; + if (ip->client->new->renewal < cur_time) + ip->client->new->renewal = TIME_MAX; + ip->client->new->rebind += cur_time; + if (ip->client->new->rebind < cur_time) + ip->client->new->rebind = TIME_MAX; bind_lease (ip); } @@ -503,51 +589,41 @@ void dhcpack (packet) void bind_lease (ip) struct interface_info *ip; { - int fd; - /* Remember the medium. */ - ip -> client -> new -> medium = ip -> client -> medium; - - /* Lock the leases file */ - fd = open (path_dhclient_db, O_RDONLY | O_EXLOCK | O_CREAT, 0); - if (fd < 0) - error ("can't open and lock %s: %m", path_dhclient_db); + ip->client->new->medium = ip->client->medium; /* Write out the new lease. */ - write_client_lease (ip, ip -> client -> new); - - /* Close and unlock lease file */ - close(fd); + write_client_lease (ip, ip->client->new, 0); /* Run the client script with the new parameters. */ - script_init (ip, (ip -> client -> state == S_REQUESTING + script_init (ip, (ip->client->state == S_REQUESTING ? "BOUND" - : (ip -> client -> state == S_RENEWING + : (ip->client->state == S_RENEWING ? "RENEW" - : (ip -> client -> state == S_REBOOTING + : (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))), - ip -> client -> new -> medium); - if (ip -> client -> active && ip -> client -> state != S_REBOOTING) - script_write_params (ip, "old_", ip -> client -> active); - script_write_params (ip, "new_", ip -> client -> new); - if (ip -> client -> alias) - script_write_params (ip, "alias_", ip -> client -> alias); + ip->client->new->medium); + if (ip->client->active && ip->client->state != S_REBOOTING) + script_write_params (ip, "old_", ip->client->active); + script_write_params (ip, "new_", ip->client->new); + if (ip->client->alias) + script_write_params (ip, "alias_", ip->client->alias); script_go (ip); /* Replace the old active lease with the new one. */ - if (ip -> client -> active) - free_client_lease (ip -> client -> active); - ip -> client -> active = ip -> client -> new; - ip -> client -> new = (struct client_lease *)0; + if (ip->client->active) + free_client_lease (ip->client->active); + ip->client->active = ip->client->new; + ip->client->new = (struct client_lease *)0; /* Set up a timeout to start the renewal process. */ - add_timeout (ip -> client -> active -> renewal, + add_timeout (ip->client->active->renewal, state_bound, ip); note ("bound to %s -- renewal in %d seconds.", - piaddr (ip -> client -> active -> address), - ip -> client -> active -> renewal - cur_time); - ip -> client -> state = S_BOUND; + piaddr (ip->client->active->address), + ip->client->active->renewal - cur_time); + ip->client->state = S_BOUND; reinitialize_interfaces (); go_daemon (); } @@ -565,21 +641,21 @@ void state_bound (ipp) ASSERT_STATE(state, S_BOUND); /* T1 has expired. */ - make_request (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; + make_request (ip, ip->client->active); + ip->client->xid = ip->client->packet.xid; - if (ip -> client -> active -> + if (ip->client->active -> options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) { - memcpy (ip -> client -> destination.iabuf, - ip -> client -> active -> + memcpy (ip->client->destination.iabuf, + ip->client->active -> options [DHO_DHCP_SERVER_IDENTIFIER].data, 4); - ip -> client -> destination.len = 4; + ip->client->destination.len = 4; } else - ip -> client -> destination = iaddr_broadcast; + ip->client->destination = iaddr_broadcast; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; - ip -> client -> state = S_RENEWING; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; + ip->client->state = S_RENEWING; /* Send the first packet immediately. */ send_request (ip); @@ -605,16 +681,16 @@ void bootp (packet) { struct iaddrlist *ap; - if (packet -> raw -> op != BOOTREPLY) + if (packet->raw->op != BOOTREPLY) return; /* If there's a reject list, make sure this packet's sender isn't on it. */ - for (ap = packet -> interface -> client -> config -> reject_list; - ap; ap = ap -> next) { - if (addr_eq (packet -> client_addr, ap -> addr)) { + for (ap = packet->interface->client->config->reject_list; + ap; ap = ap->next) { + if (addr_eq (packet->client_addr, ap->addr)) { note ("BOOTREPLY from %s rejected.", - piaddr (ap -> addr)); + piaddr (ap->addr)); return; } } @@ -630,7 +706,7 @@ void dhcp (packet) void (*handler) PROTO ((struct packet *)); char *type; - switch (packet -> packet_type) { + switch (packet->packet_type) { case DHCPOFFER: handler = dhcpoffer; type = "DHCPOFFER"; @@ -656,25 +732,24 @@ void dhcp (packet) * can set yiaddr to 0 on non-DHCPNAK packets * we ignore those here. */ - struct in_addr tmp; - memset(&tmp, 0, sizeof(struct in_addr)); - - if (memcmp(&tmp, &packet -> raw -> yiaddr, sizeof(tmp)) == 0) - { - note ( - "%s from %s rejected due to bogus yiaddr of 0.0.0.0.", - type, piaddr (packet->client_addr)); - return; - } + struct in_addr tmp; + memset(&tmp, 0, sizeof(struct in_addr)); + + if (memcmp(&tmp, &packet->raw->yiaddr, sizeof(tmp)) == 0) + { + note("%s from %s rejected due to bogus yiaddr of 0.0.0.0.", + type, piaddr (packet->client_addr)); + return; + } } /* If there's a reject list, make sure this packet's sender isn't on it. */ - for (ap = packet -> interface -> client -> config -> reject_list; - ap; ap = ap -> next) { - if (addr_eq (packet -> client_addr, ap -> addr)) { + for (ap = packet->interface->client->config->reject_list; + ap; ap = ap->next) { + if (addr_eq (packet->client_addr, ap->addr)) { note ("%s from %s rejected.", - type, piaddr (ap -> addr)); + type, piaddr (ap->addr)); return; } } @@ -684,13 +759,12 @@ void dhcp (packet) void dhcpoffer (packet) struct packet *packet; { - struct interface_info *ip = packet -> interface; + struct interface_info *ip = packet->interface; struct client_lease *lease, *lp; int i; int arp_timeout_needed, stop_selecting; - char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len + char *name = (packet->options [DHO_DHCP_MESSAGE_TYPE].len ? "DHCPOFFER" : "BOOTREPLY"); - struct iaddrlist *ap; #ifdef DEBUG_PACKET dump_packet (packet); @@ -698,19 +772,25 @@ void dhcpoffer (packet) /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ - if (ip -> client -> state != S_SELECTING || - packet -> interface -> client -> xid != packet -> raw -> xid) { + if (ip->client->state != S_SELECTING || + packet->interface->client->xid != packet->raw->xid || + (packet->interface->hw_address.hlen != + packet->raw->hlen) || + (memcmp (packet->interface->hw_address.haddr, + packet->raw->chaddr, packet->raw->hlen))) { +#if defined (DEBUG) debug ("%s in wrong transaction.", name); +#endif return; } - note ("%s from %s", name, piaddr (packet -> client_addr)); + note ("%s from %s", name, piaddr (packet->client_addr)); /* If this lease doesn't supply the minimum required parameters, blow it off. */ - for (i = 0; ip -> client -> config -> required_options [i]; i++) { - if (!packet -> options [ip -> client -> config -> + for (i = 0; ip->client->config->required_options [i]; i++) { + if (!packet->options [ip->client->config -> required_options [i]].len) { note ("%s isn't satisfactory.", name); return; @@ -718,11 +798,11 @@ void dhcpoffer (packet) } /* If we've already seen this lease, don't record it again. */ - for (lease = ip -> client -> offered_leases; - lease; lease = lease -> next) { - if (lease -> address.len == sizeof packet -> raw -> yiaddr && - !memcmp (lease -> address.iabuf, - &packet -> raw -> yiaddr, lease -> address.len)) { + for (lease = ip->client->offered_leases; + lease; lease = lease->next) { + if (lease->address.len == sizeof packet->raw->yiaddr && + !memcmp (lease->address.iabuf, + &packet->raw->yiaddr, lease->address.len)) { debug ("%s already seen.", name); return; } @@ -736,14 +816,14 @@ void dhcpoffer (packet) /* If this lease was acquired through a BOOTREPLY, record that fact. */ - if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len) - lease -> is_bootp = 1; + if (!packet->options [DHO_DHCP_MESSAGE_TYPE].len) + lease->is_bootp = 1; /* Record the medium under which this lease was offered. */ - lease -> medium = ip -> client -> medium; + lease->medium = ip->client->medium; /* Send out an ARP Request for the offered IP address. */ - script_init (ip, "ARPSEND", lease -> medium); + script_init (ip, "ARPSEND", lease->medium); script_write_params (ip, "check_", lease); /* If the script can't send an ARP request without waiting, we'll be waiting when we do the ARPCHECK, so don't wait now. */ @@ -753,35 +833,35 @@ void dhcpoffer (packet) arp_timeout_needed = 2; /* Figure out when we're supposed to stop selecting. */ - stop_selecting = (ip -> client -> first_sending + - ip -> client -> config -> select_interval); + stop_selecting = (ip->client->first_sending + + ip->client->config->select_interval); /* If this is the lease we asked for, put it at the head of the list, and don't mess with the arp request timeout. */ - if (lease -> address.len == ip -> client -> requested_address.len && - !memcmp (lease -> address.iabuf, - ip -> client -> requested_address.iabuf, - ip -> client -> requested_address.len)) { - lease -> next = ip -> client -> offered_leases; - ip -> client -> offered_leases = lease; + if (lease->address.len == ip->client->requested_address.len && + !memcmp (lease->address.iabuf, + ip->client->requested_address.iabuf, + ip->client->requested_address.len)) { + lease->next = ip->client->offered_leases; + ip->client->offered_leases = lease; } else { /* If we already have an offer, and arping for this offer would take us past the selection timeout, then don't extend the timeout - just hope for the best. */ - if (ip -> client -> offered_leases && + if (ip->client->offered_leases && (cur_time + arp_timeout_needed) > stop_selecting) arp_timeout_needed = 0; /* Put the lease at the end of the list. */ - lease -> next = (struct client_lease *)0; - if (!ip -> client -> offered_leases) - ip -> client -> offered_leases = lease; + lease->next = (struct client_lease *)0; + if (!ip->client->offered_leases) + ip->client->offered_leases = lease; else { - for (lp = ip -> client -> offered_leases; lp -> next; - lp = lp -> next) + for (lp = ip->client->offered_leases; lp->next; + lp = lp->next) ; - lp -> next = lease; + lp->next = lease; } } @@ -822,23 +902,23 @@ struct client_lease *packet_to_lease (packet) /* Copy the lease options. */ for (i = 0; i < 256; i++) { - if (packet -> options [i].len) { - lease -> options [i].data = + if (packet->options [i].len) { + lease->options [i].data = (unsigned char *) - malloc (packet -> options [i].len + 1); - if (!lease -> options [i].data) { + malloc (packet->options [i].len + 1); + if (!lease->options [i].data) { warn ("dhcpoffer: no memory for option %d\n", i); free_client_lease (lease); return (struct client_lease *)0; } else { - memcpy (lease -> options [i].data, - packet -> options [i].data, - packet -> options [i].len); - lease -> options [i].len = - packet -> options [i].len; - lease -> options [i].data - [lease -> options [i].len] = 0; + memcpy (lease->options [i].data, + packet->options [i].data, + packet->options [i].len); + lease->options [i].len = + packet->options [i].len; + lease->options [i].data + [lease->options [i].len] = 0; } if (!check_option(lease,i)) { /* ignore a bogus lease offer */ @@ -849,37 +929,37 @@ struct client_lease *packet_to_lease (packet) } } - lease -> address.len = sizeof (packet -> raw -> yiaddr); - memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr, - lease -> address.len); + lease->address.len = sizeof (packet->raw->yiaddr); + memcpy (lease->address.iabuf, &packet->raw->yiaddr, + lease->address.len); /* If the server name was filled out, copy it. */ - if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || - !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) && - packet -> raw -> sname [0]) { - /* Don't count on the NUL terminator. */ - lease->server_name = malloc(DHCP_SNAME_LEN + 1); - if (!lease -> server_name ) { - warn ("dhcpoffer: no memory for filename."); + if ((!packet->options [DHO_DHCP_OPTION_OVERLOAD].len || + !(packet->options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) && + packet->raw->sname [0]) { + lease->server_name = malloc (DHCP_SNAME_LEN + 1); + if (!lease->server_name) { + warn ("dhcpoffer: no memory for server name."); free_client_lease (lease); return (struct client_lease *)0; - } - memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); - lease->server_name[DHCP_SNAME_LEN]='\0'; + } + memcpy(lease->filename, packet->raw->sname, DHCP_SNAME_LEN); + lease->filename[DHCP_SNAME_LEN]='\0'; if (! res_hnok (lease->server_name) ) { warn ("Bogus server name %s", lease->server_name ); free_client_lease (lease); return (struct client_lease *)0; } + } /* Ditto for the filename. */ - if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || - !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) && - packet -> raw -> file [0]) { - /* Don't count on the NUL terminator. */ + if ((!packet->options [DHO_DHCP_OPTION_OVERLOAD].len || + !(packet->options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) && + packet->raw->file [0]) { + /* Don't count on the NUL terminator. */ lease->filename = malloc(DHCP_FILE_LEN + 1); - if (!lease -> filename) { + if (!lease->filename) { warn ("dhcpoffer: no memory for filename."); free_client_lease (lease); return (struct client_lease *)0; @@ -893,37 +973,45 @@ struct client_lease *packet_to_lease (packet) void dhcpnak (packet) struct packet *packet; { - struct interface_info *ip = packet -> interface; + struct interface_info *ip = packet->interface; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ - if (packet -> interface -> client -> xid != packet -> raw -> xid) { + if (packet->interface->client->xid != packet->raw->xid || + (packet->interface->hw_address.hlen != + packet->raw->hlen) || + (memcmp (packet->interface->hw_address.haddr, + packet->raw->chaddr, packet->raw->hlen))) { +#if defined (DEBUG) debug ("DHCPNAK in wrong transaction."); +#endif return; } - if (ip -> client -> state != S_REBOOTING && - ip -> client -> state != S_REQUESTING && - ip -> client -> state != S_RENEWING && - ip -> client -> state != S_REBINDING) { + if (ip->client->state != S_REBOOTING && + ip->client->state != S_REQUESTING && + ip->client->state != S_RENEWING && + ip->client->state != S_REBINDING) { +#if defined (DEBUG) debug ("DHCPNAK in wrong state."); +#endif return; } - note ("DHCPNAK from %s", piaddr (packet -> client_addr)); + note ("DHCPNAK from %s", piaddr (packet->client_addr)); - if (!ip -> client -> active) { + if (!ip->client->active) { note ("DHCPNAK with no active lease.\n"); return; } - free_client_lease (ip -> client -> active); - ip -> client -> active = (struct client_lease *)0; + free_client_lease (ip->client->active); + ip->client->active = (struct client_lease *)0; /* Stop sending DHCPREQUEST packets... */ cancel_timeout (send_request, ip); - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; state_init (ip); } @@ -941,11 +1029,11 @@ void send_discover (ipp) int increase = 1; /* Figure out how long it's been since we started transmitting. */ - interval = cur_time - ip -> client -> first_sending; + interval = cur_time - ip->client->first_sending; /* If we're past the panic timeout, call the script and tell it we haven't found anything for this interface yet. */ - if (interval > ip -> client -> config -> timeout) { + if (interval > ip->client->config->timeout) { state_panic (ip); return; } @@ -953,27 +1041,27 @@ void send_discover (ipp) /* If we're selecting media, try the whole list before doing the exponential backoff, but if we've already received an offer, stop looping, because we obviously have it right. */ - if (!ip -> client -> offered_leases && - ip -> client -> config -> media) { + if (!ip->client->offered_leases && + ip->client->config->media) { int fail = 0; again: - if (ip -> client -> medium) { - ip -> client -> medium = - ip -> client -> medium -> next; + if (ip->client->medium) { + ip->client->medium = + ip->client->medium->next; increase = 0; } - if (!ip -> client -> medium) { + if (!ip->client->medium) { if (fail) error ("No valid media types for %s!", - ip -> name); - ip -> client -> medium = - ip -> client -> config -> media; + ip->name); + ip->client->medium = + ip->client->config->media; increase = 1; } note ("Trying medium \"%s\" %d", - ip -> client -> medium -> string, increase); - script_init (ip, "MEDIUM", ip -> client -> medium); + ip->client->medium->string, increase); + script_init (ip, "MEDIUM", ip->client->medium); if (script_go (ip)) { goto again; } @@ -985,54 +1073,54 @@ void send_discover (ipp) zero and two times itself. On average, this means that it will double with every transmission. */ if (increase) { - if (!ip -> client -> interval) - ip -> client -> interval = - ip -> client -> config -> initial_interval; + if (!ip->client->interval) + ip->client->interval = + ip->client->config->initial_interval; else { - ip -> client -> interval += - ((arc4random () >> 2) % - (2 * ip -> client -> interval)); + ip->client->interval += + ((random () >> 2) % + (2 * ip->client->interval)); } /* Don't backoff past cutoff. */ - if (ip -> client -> interval > - ip -> client -> config -> backoff_cutoff) - ip -> client -> interval = - ((ip -> client -> config -> backoff_cutoff / 2) - + ((arc4random () >> 2) - % ip -> client -> interval)); - } else if (!ip -> client -> interval) - ip -> client -> interval = - ip -> client -> config -> initial_interval; + if (ip->client->interval > + ip->client->config->backoff_cutoff) + ip->client->interval = + ((ip->client->config->backoff_cutoff / 2) + + ((random () >> 2) % + ip->client->config->backoff_cutoff)); + } else if (!ip->client->interval) + ip->client->interval = + ip->client->config->initial_interval; /* If the backoff would take us to the panic timeout, just use that as the interval. */ - if (cur_time + ip -> client -> interval > - ip -> client -> first_sending + ip -> client -> config -> timeout) - ip -> client -> interval = - (ip -> client -> first_sending + - ip -> client -> config -> timeout) - cur_time + 1; + if (cur_time + ip->client->interval > + ip->client->first_sending + ip->client->config->timeout) + ip->client->interval = + (ip->client->first_sending + + ip->client->config->timeout) - cur_time + 1; /* Record the number of seconds since we started sending. */ - if (interval < 255) - ip -> client -> packet.secs = interval; + if (interval < 65536) + ip->client->packet.secs = htons (interval); else - ip -> client -> packet.secs = 255; + ip->client->packet.secs = htons (65535); + ip->client->secs = ip->client->packet.secs; note ("DHCPDISCOVER on %s to %s port %d interval %ld", - ip -> name, + ip->name, inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval); + ntohs (sockaddr_broadcast.sin_port), ip->client->interval); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); - if (result < 0) - warn ("send_discover/send_packet: %m"); - add_timeout (cur_time + ip -> client -> interval, send_discover, ip); + + add_timeout (cur_time + ip->client->interval, send_discover, ip); } /* state_panic gets called if we haven't received any offers in a preset @@ -1045,46 +1133,46 @@ void state_panic (ipp) { struct interface_info *ip = ipp; - struct client_lease *loop = ip -> client -> active; + struct client_lease *loop = ip->client->active; struct client_lease *lp; note ("No DHCPOFFERS received."); /* We may not have an active lease, but we may have some predefined leases that we can try. */ - if (!ip -> client -> active && ip -> client -> leases) + if (!ip->client->active && ip->client->leases) goto activate_next; /* Run through the list of leases and see if one can be used. */ - while (ip -> client -> active) { - if (ip -> client -> active -> expiry > cur_time) { + while (ip->client->active) { + if (ip->client->active->expiry > cur_time) { note ("Trying recorded lease %s", - piaddr (ip -> client -> active -> address)); + piaddr (ip->client->active->address)); /* Run the client script with the existing parameters. */ script_init (ip, "TIMEOUT", - ip -> client -> active -> medium); + ip->client->active->medium); script_write_params (ip, "new_", - ip -> client -> active); - if (ip -> client -> alias) + ip->client->active); + if (ip->client->alias) script_write_params (ip, "alias_", - ip -> client -> alias); + ip->client->alias); /* If the old lease is still good and doesn't yet need renewal, go into BOUND state and timeout at the renewal time. */ if (!script_go (ip)) { if (cur_time < - ip -> client -> active -> renewal) { - ip -> client -> state = S_BOUND; + ip->client->active->renewal) { + ip->client->state = S_BOUND; note ("bound: renewal in %d seconds.", - ip -> client -> active -> renewal + ip->client->active->renewal - cur_time); - add_timeout ((ip -> client -> - active -> renewal), + add_timeout ((ip->client -> + active->renewal), state_bound, ip); } else { - ip -> client -> state = S_BOUND; + ip->client->state = S_BOUND; note ("bound: immediate renewal."); state_bound (ip); } @@ -1095,31 +1183,31 @@ void state_panic (ipp) } /* If there are no other leases, give up. */ - if (!ip -> client -> leases) { - ip -> client -> leases = ip -> client -> active; - ip -> client -> active = (struct client_lease *)0; + if (!ip->client->leases) { + ip->client->leases = ip->client->active; + ip->client->active = (struct client_lease *)0; break; } activate_next: /* Otherwise, put the active lease at the end of the lease list, and try another lease.. */ - for (lp = ip -> client -> leases; lp -> next; lp = lp -> next) + for (lp = ip->client->leases; lp->next; lp = lp->next) ; - lp -> next = ip -> client -> active; - if (lp -> next) { - lp -> next -> next = (struct client_lease *)0; + lp->next = ip->client->active; + if (lp->next) { + lp->next->next = (struct client_lease *)0; } - ip -> client -> active = ip -> client -> leases; - ip -> client -> leases = ip -> client -> leases -> next; + ip->client->active = ip->client->leases; + ip->client->leases = ip->client->leases->next; /* If we already tried this lease, we've exhausted the set of leases, so we might as well give up for now. */ - if (ip -> client -> active == loop) + if (ip->client->active == loop) break; else if (!loop) - loop = ip -> client -> active; + loop = ip->client->active; } /* No leases were available, or what was available didn't work, so @@ -1129,11 +1217,11 @@ void state_panic (ipp) exit(1); note ("No working leases in persistent database - sleeping.\n"); script_init (ip, "FAIL", (struct string_list *)0); - if (ip -> client -> alias) - script_write_params (ip, "alias_", ip -> client -> alias); + if (ip->client->alias) + script_write_params (ip, "alias_", ip->client->alias); script_go (ip); - ip -> client -> state = S_INIT; - add_timeout (cur_time + ip -> client -> config -> retry_interval, + ip->client->state = S_INIT; + add_timeout (cur_time + ip->client->config->retry_interval, state_init, ip); go_daemon (); } @@ -1149,7 +1237,7 @@ void send_request (ipp) struct in_addr from; /* Figure out how long it's been since we started transmitting. */ - interval = cur_time - ip -> client -> first_sending; + interval = cur_time - ip->client->first_sending; /* If we're in the INIT-REBOOT or REQUESTING state and we're past the reboot timeout, go to INIT and see if we can @@ -1161,11 +1249,11 @@ void send_request (ipp) us a new address, but we could also have successfully reused our old address. In the former case, we're hosed anyway. This is not a win-prone situation. */ - if ((ip -> client -> state == S_REBOOTING || - ip -> client -> state == S_REQUESTING) && - interval > ip -> client -> config -> reboot_timeout) { + if ((ip->client->state == S_REBOOTING || + ip->client->state == S_REQUESTING) && + interval > ip->client->config->reboot_timeout) { cancel: - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; cancel_timeout (send_request, ip); state_init (ip); return; @@ -1173,114 +1261,121 @@ void send_request (ipp) /* If we're in the reboot state, make sure the media is set up correctly. */ - if (ip -> client -> state == S_REBOOTING && - !ip -> client -> medium && - ip -> client -> active -> medium ) { - script_init (ip, "MEDIUM", ip -> client -> active -> medium); + if (ip->client->state == S_REBOOTING && + !ip->client->medium && + ip->client->active->medium ) { + script_init (ip, "MEDIUM", ip->client->active->medium); /* If the medium we chose won't fly, go to INIT state. */ if (script_go (ip)) goto cancel; /* Record the medium. */ - ip -> client -> medium = ip -> client -> active -> medium; + ip->client->medium = ip->client->active->medium; } /* If the lease has expired, relinquish the address and go back to the INIT state. */ - if (ip -> client -> state != S_REQUESTING && - cur_time > ip -> client -> active -> expiry) { + if (ip->client->state != S_REQUESTING && + cur_time > ip->client->active->expiry) { /* Run the client script with the new parameters. */ script_init (ip, "EXPIRE", (struct string_list *)0); - script_write_params (ip, "old_", ip -> client -> active); - if (ip -> client -> alias) + script_write_params (ip, "old_", ip->client->active); + if (ip->client->alias) + script_write_params (ip, "alias_", + ip->client->alias); + script_go (ip); + + /* Now do a preinit on the interface so that we can + discover a new address. */ + script_init (ip, "PREINIT", (struct string_list *)0); + if (ip->client->alias) script_write_params (ip, "alias_", - ip -> client -> alias); + ip->client->alias); script_go (ip); - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; state_init (ip); return; } /* Do the exponential backoff... */ - if (!ip -> client -> interval) - ip -> client -> interval = - ip -> client -> config -> initial_interval; + if (!ip->client->interval) + ip->client->interval = + ip->client->config->initial_interval; else { - ip -> client -> interval += - ((arc4random () >> 2) % - (2 * ip -> client -> interval)); + ip->client->interval += + ((random () >> 2) % + (2 * ip->client->interval)); } /* Don't backoff past cutoff. */ - if (ip -> client -> interval > - ip -> client -> config -> backoff_cutoff) - ip -> client -> interval = - ((ip -> client -> config -> backoff_cutoff / 2) - + ((arc4random () >> 2) - % ip -> client -> interval)); + if (ip->client->interval > + ip->client->config->backoff_cutoff) + ip->client->interval = + ((ip->client->config->backoff_cutoff / 2) + + ((random () >> 2) + % ip->client->interval)); /* If the backoff would take us to the expiry time, just set the timeout to the expiry time. */ - if (ip -> client -> state != S_REQUESTING && - cur_time + ip -> client -> interval > - ip -> client -> active -> expiry) - ip -> client -> interval = - ip -> client -> active -> expiry - cur_time + 1; + if (ip->client->state != S_REQUESTING && + cur_time + ip->client->interval > + ip->client->active->expiry) + ip->client->interval = + ip->client->active->expiry - cur_time + 1; /* If the lease T2 time has elapsed, or if we're not yet bound, broadcast the DHCPREQUEST rather than unicasting. */ - if (ip -> client -> state == S_REQUESTING || - cur_time > ip -> client -> active -> rebind) + if (ip->client->state == S_REQUESTING || + ip->client->state == S_REBOOTING || + cur_time > ip->client->active->rebind) destination.sin_addr.s_addr = INADDR_BROADCAST; else memcpy (&destination.sin_addr.s_addr, - ip -> client -> destination.iabuf, + ip->client->destination.iabuf, sizeof destination.sin_addr.s_addr); destination.sin_port = remote_port; destination.sin_family = AF_INET; -#ifdef HAVE_SA_LEN destination.sin_len = sizeof destination; -#endif - if (ip -> client -> state != S_REQUESTING) - memcpy (&from, ip -> client -> active -> address.iabuf, + if (ip->client->state != S_REQUESTING) + memcpy (&from, ip->client->active->address.iabuf, sizeof from); else from.s_addr = INADDR_ANY; /* Record the number of seconds since we started sending. */ - if (interval < 255) - ip -> client -> packet.secs = interval; - else - ip -> client -> packet.secs = 255; + if (ip->client->state == S_REQUESTING) + ip->client->packet.secs = ip->client->secs; + else { + if (interval < 65536) + ip->client->packet.secs = htons (interval); + else + ip->client->packet.secs = htons (65535); + } - note ("DHCPREQUEST on %s to %s port %d", ip -> name, + note ("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa (destination.sin_addr), ntohs (destination.sin_port)); -#ifdef USE_FALLBACK - if (destination.sin_addr.s_addr != INADDR_BROADCAST) - result = send_fallback (&fallback_interface, - (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - from, &destination, - (struct hardware *)0); + if (destination.sin_addr.s_addr != INADDR_BROADCAST && + fallback_interface) + result = send_packet (fallback_interface, + (struct packet *)0, + &ip->client->packet, + ip->client->packet_length, + from, &destination, + (struct hardware *)0); else -#endif /* USE_FALLBACK */ /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, from, &destination, (struct hardware *)0); - if (result < 0) - warn ("send_request/send_packet: %m"); - - add_timeout (cur_time + ip -> client -> interval, + add_timeout (cur_time + ip->client->interval, send_request, ip); } @@ -1291,18 +1386,16 @@ void send_decline (ipp) int result; - note ("DHCPDECLINE on %s to %s port %d", ip -> name, + note ("DHCPDECLINE on %s to %s port %d", ip->name, inet_ntoa (sockaddr_broadcast.sin_addr), ntohs (sockaddr_broadcast.sin_port)); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); - if (result < 0) - warn ("send_decline/send_packet: %m"); } void send_release (ipp) @@ -1312,25 +1405,22 @@ void send_release (ipp) int result; - note ("DHCPRELEASE on %s to %s port %d", ip -> name, + note ("DHCPRELEASE on %s to %s port %d", ip->name, inet_ntoa (sockaddr_broadcast.sin_addr), ntohs (sockaddr_broadcast.sin_port)); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); - if (result < 0) - warn ("send_release/send_packet: %m"); } void make_discover (ip, lease) struct interface_info *ip; struct client_lease *lease; { - struct dhcp_packet *raw; unsigned char discover = DHCPDISCOVER; int i; @@ -1339,85 +1429,90 @@ void make_discover (ip, lease) memset (option_elements, 0, sizeof option_elements); memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &option_elements [i]; - options [i] -> value = &discover; - options [i] -> len = sizeof discover; - options [i] -> buf_size = sizeof discover; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &discover; + options [i]->len = sizeof discover; + options [i]->buf_size = sizeof discover; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Request the options we want */ i = DHO_DHCP_PARAMETER_REQUEST_LIST; options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> requested_options; - options [i] -> len = ip -> client -> config -> requested_option_count; - options [i] -> buf_size = - ip -> client -> config -> requested_option_count; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = ip->client->config->requested_options; + options [i]->len = ip->client->config->requested_option_count; + options [i]->buf_size = + ip->client->config->requested_option_count; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* If we had an address, try to get it again. */ if (lease) { - ip -> client -> requested_address = lease -> address; + ip->client->requested_address = lease->address; i = DHO_DHCP_REQUESTED_ADDRESS; options [i] = &option_elements [i]; - options [i] -> value = lease -> address.iabuf; - options [i] -> len = lease -> address.len; - options [i] -> buf_size = lease -> address.len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->address.iabuf; + options [i]->len = lease->address.len; + options [i]->buf_size = lease->address.len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } else { - ip -> client -> requested_address.len = 0; + ip->client->requested_address.len = 0; } /* Send any options requested in the config file. */ for (i = 0; i < 256; i++) { if (!options [i] && - ip -> client -> config -> send_options [i].data) { + ip->client->config->send_options [i].data) { options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> + options [i]->value = ip->client->config -> send_options [i].data; - options [i] -> len = ip -> client -> config -> + options [i]->len = ip->client->config -> send_options [i].len; - options [i] -> buf_size = ip -> client -> config -> + options [i]->buf_size = ip->client->config -> send_options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } } /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = arc4random (); - ip -> client -> packet.secs = 0; /* filled in by send_discover. */ - ip -> client -> packet.flags = 0; - memset (&(ip -> client -> packet.ciaddr), - 0, sizeof ip -> client -> packet.ciaddr); - memset (&(ip -> client -> packet.yiaddr), - 0, sizeof ip -> client -> packet.yiaddr); - memset (&(ip -> client -> packet.siaddr), - 0, sizeof ip -> client -> packet.siaddr); - memset (&(ip -> client -> packet.giaddr), - 0, sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = arc4random (); + ip->client->packet.secs = 0; /* filled in by send_discover. */ + + if (can_receive_unicast_unconfigured (ip)) + ip->client->packet.flags = 0; + else + ip->client->packet.flags = htons (BOOTP_BROADCAST); + + memset (&(ip->client->packet.ciaddr), + 0, sizeof ip->client->packet.ciaddr); + memset (&(ip->client->packet.yiaddr), + 0, sizeof ip->client->packet.yiaddr); + memset (&(ip->client->packet.siaddr), + 0, sizeof ip->client->packet.siaddr); + memset (&(ip->client->packet.giaddr), + 0, sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, + dump_raw ((unsigned char *)ip->client->packet, sendpkt->packet_length); #endif } @@ -1434,107 +1529,112 @@ void make_request (ip, lease) struct tree_cache option_elements [256]; memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &option_elements [i]; - options [i] -> value = &request; - options [i] -> len = sizeof request; - options [i] -> buf_size = sizeof request; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &request; + options [i]->len = sizeof request; + options [i]->buf_size = sizeof request; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Request the options we want */ i = DHO_DHCP_PARAMETER_REQUEST_LIST; options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> requested_options; - options [i] -> len = ip -> client -> config -> requested_option_count; - options [i] -> buf_size = - ip -> client -> config -> requested_option_count; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = ip->client->config->requested_options; + options [i]->len = ip->client->config->requested_option_count; + options [i]->buf_size = + ip->client->config->requested_option_count; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* If we are requesting an address that hasn't yet been assigned to us, use the DHCP Requested Address option. */ - if (ip -> client -> state == S_REQUESTING) { + if (ip->client->state == S_REQUESTING) { /* Send back the server identifier... */ i = DHO_DHCP_SERVER_IDENTIFIER; options [i] = &option_elements [i]; - options [i] -> value = lease -> options [i].data; - options [i] -> len = lease -> options [i].len; - options [i] -> buf_size = lease -> options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; - } - if (ip -> client -> state == S_REQUESTING || - ip -> client -> state == S_REBOOTING) { - ip -> client -> requested_address = lease -> address; + options [i]->value = lease->options [i].data; + options [i]->len = lease->options [i].len; + options [i]->buf_size = lease->options [i].len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; + } + if (ip->client->state == S_REQUESTING || + ip->client->state == S_REBOOTING) { + ip->client->requested_address = lease->address; i = DHO_DHCP_REQUESTED_ADDRESS; options [i] = &option_elements [i]; - options [i] -> value = lease -> address.iabuf; - options [i] -> len = lease -> address.len; - options [i] -> buf_size = lease -> address.len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->address.iabuf; + options [i]->len = lease->address.len; + options [i]->buf_size = lease->address.len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } else { - ip -> client -> requested_address.len = 0; + ip->client->requested_address.len = 0; } /* Send any options requested in the config file. */ for (i = 0; i < 256; i++) { if (!options [i] && - ip -> client -> config -> send_options [i].data) { + ip->client->config->send_options [i].data) { options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> + options [i]->value = ip->client->config -> send_options [i].data; - options [i] -> len = ip -> client -> config -> + options [i]->len = ip->client->config -> send_options [i].len; - options [i] -> buf_size = ip -> client -> config -> + options [i]->buf_size = ip->client->config -> send_options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } } /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> xid; - ip -> client -> packet.secs = 0; /* Filled in by send_request. */ - ip -> client -> packet.flags = 0; + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = ip->client->xid; + ip->client->packet.secs = 0; /* Filled in by send_request. */ /* If we own the address we're requesting, put it in ciaddr; otherwise set ciaddr to zero. */ - if (ip -> client -> state == S_BOUND || - ip -> client -> state == S_RENEWING || - ip -> client -> state == S_REBINDING) - memcpy (&ip -> client -> packet.ciaddr, - lease -> address.iabuf, lease -> address.len); - else - memset (&ip -> client -> packet.ciaddr, 0, - sizeof ip -> client -> packet.ciaddr); - - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + if (ip->client->state == S_BOUND || + ip->client->state == S_RENEWING || + ip->client->state == S_REBINDING) { + memcpy (&ip->client->packet.ciaddr, + lease->address.iabuf, lease->address.len); + ip->client->packet.flags = 0; + } else { + memset (&ip->client->packet.ciaddr, 0, + sizeof ip->client->packet.ciaddr); + if (can_receive_unicast_unconfigured (ip)) + ip->client->packet.flags = 0; + else + ip->client->packet.flags = htons (BOOTP_BROADCAST); + } + + memset (&ip->client->packet.yiaddr, 0, + sizeof ip->client->packet.yiaddr); + memset (&ip->client->packet.siaddr, 0, + sizeof ip->client->packet.siaddr); + memset (&ip->client->packet.giaddr, 0, + sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); + dump_raw ((unsigned char *)ip->client->packet, sendpkt->packet_length); #endif } @@ -1552,80 +1652,80 @@ void make_decline (ip, lease) struct tree_cache client_id_tree; memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &message_type_tree; - options [i] -> value = &decline; - options [i] -> len = sizeof decline; - options [i] -> buf_size = sizeof decline; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &decline; + options [i]->len = sizeof decline; + options [i]->buf_size = sizeof decline; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send back the server identifier... */ i = DHO_DHCP_SERVER_IDENTIFIER; options [i] = &server_id_tree; - options [i] -> value = lease -> options [i].data; - options [i] -> len = lease -> options [i].len; - options [i] -> buf_size = lease -> options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->options [i].data; + options [i]->len = lease->options [i].len; + options [i]->buf_size = lease->options [i].len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send back the address we're declining. */ i = DHO_DHCP_REQUESTED_ADDRESS; options [i] = &requested_address_tree; - options [i] -> value = lease -> address.iabuf; - options [i] -> len = lease -> address.len; - options [i] -> buf_size = lease -> address.len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->address.iabuf; + options [i]->len = lease->address.len; + options [i]->buf_size = lease->address.len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send the uid if the user supplied one. */ i = DHO_DHCP_CLIENT_IDENTIFIER; - if (ip -> client -> config -> send_options [i].len) { + if (ip->client->config->send_options [i].len) { options [i] = &client_id_tree; - options [i] -> value = ip -> client -> config -> + options [i]->value = ip->client->config -> send_options [i].data; - options [i] -> len = ip -> client -> config -> + options [i]->len = ip->client->config -> send_options [i].len; - options [i] -> buf_size = ip -> client -> config -> + options [i]->buf_size = ip->client->config -> send_options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> xid; - ip -> client -> packet.secs = 0; /* Filled in by send_request. */ - ip -> client -> packet.flags = 0; + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = ip->client->xid; + ip->client->packet.secs = 0; /* Filled in by send_request. */ + ip->client->packet.flags = 0; /* ciaddr must always be zero. */ - memset (&ip -> client -> packet.ciaddr, 0, - sizeof ip -> client -> packet.ciaddr); - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + memset (&ip->client->packet.ciaddr, 0, + sizeof ip->client->packet.ciaddr); + memset (&ip->client->packet.yiaddr, 0, + sizeof ip->client->packet.yiaddr); + memset (&ip->client->packet.siaddr, 0, + sizeof ip->client->packet.siaddr); + memset (&ip->client->packet.giaddr, 0, + sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); + dump_raw ((unsigned char *)ip->client->packet, sendpkt->packet_length); #endif } @@ -1638,59 +1738,59 @@ void make_release (ip, lease) struct tree_cache *options [256]; struct tree_cache message_type_tree; - struct tree_cache requested_address_tree; struct tree_cache server_id_tree; memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &message_type_tree; - options [i] -> value = &request; - options [i] -> len = sizeof request; - options [i] -> buf_size = sizeof request; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &request; + options [i]->len = sizeof request; + options [i]->buf_size = sizeof request; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send back the server identifier... */ i = DHO_DHCP_SERVER_IDENTIFIER; options [i] = &server_id_tree; - options [i] -> value = lease -> options [i].data; - options [i] -> len = lease -> options [i].len; - options [i] -> buf_size = lease -> options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->options [i].data; + options [i]->len = lease->options [i].len; + options [i]->buf_size = lease->options [i].len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = arc4random(); - ip -> client -> packet.secs = 0; - ip -> client -> packet.flags = 0; - memcpy (&ip -> client -> packet.ciaddr, - lease -> address.iabuf, lease -> address.len); - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = random (); + ip->client->packet.secs = 0; + ip->client->packet.flags = 0; + + memset (&ip->client->packet.ciaddr, 0, + sizeof ip->client->packet.ciaddr); + memset (&ip->client->packet.yiaddr, 0, + sizeof ip->client->packet.yiaddr); + memset (&ip->client->packet.siaddr, 0, + sizeof ip->client->packet.siaddr); + memset (&ip->client->packet.giaddr, 0, + sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, - ip -> client -> packet_length); + dump_raw ((unsigned char *)ip->client->packet, + ip->client->packet_length); #endif } @@ -1699,13 +1799,13 @@ void free_client_lease (lease) { int i; - if (lease -> server_name) - free (lease -> server_name); - if (lease -> filename) - free (lease -> filename); + if (lease->server_name) + free (lease->server_name); + if (lease->filename) + free (lease->filename); for (i = 0; i < 256; i++) { - if (lease -> options [i].len) - free (lease -> options [i].data); + if (lease->options [i].len) + free (lease->options [i].data); } free (lease); } @@ -1725,36 +1825,45 @@ void rewrite_client_leases () /* Write out all the leases attached to configured interfaces that we know about. */ - for (ip = interfaces; ip; ip = ip -> next) { - for (lp = ip -> client -> leases; lp; lp = lp -> next) { - write_client_lease (ip, lp); + for (ip = interfaces; ip; ip = ip->next) { + for (lp = ip->client->leases; lp; lp = lp->next) { + write_client_lease (ip, lp, 1); } - if (ip -> client -> active) - write_client_lease (ip, ip -> client -> active); + if (ip->client->active) + write_client_lease (ip, ip->client->active, 1); } /* Write out any leases that are attached to interfaces that aren't currently configured. */ - for (ip = dummy_interfaces; ip; ip = ip -> next) { - for (lp = ip -> client -> leases; lp; lp = lp -> next) { - write_client_lease (ip, lp); + for (ip = dummy_interfaces; ip; ip = ip->next) { + for (lp = ip->client->leases; lp; lp = lp->next) { + write_client_lease (ip, lp, 1); } - if (ip -> client -> active) - write_client_lease (ip, ip -> client -> active); + if (ip->client->active) + write_client_lease (ip, ip->client->active, 1); } fflush (leaseFile); } -void write_client_lease (ip, lease) +void write_client_lease (ip, lease, rewrite) struct interface_info *ip; struct client_lease *lease; + int rewrite; { int i; struct tm *t; + static int leases_written; + + if (!rewrite) { + if (leases_written++ > 20) { + rewrite_client_leases (); + leases_written = 0; + } + } /* If the lease came from the config file, we don't need to stash a copy in the lease database. */ - if (lease -> is_static) + if (lease->is_static) return; if (!leaseFile) { /* XXX */ @@ -1764,48 +1873,52 @@ void write_client_lease (ip, lease) } fprintf (leaseFile, "lease {\n"); - if (lease -> is_bootp) + if (lease->is_bootp) fprintf (leaseFile, " bootp;\n"); - fprintf (leaseFile, " interface \"%s\";\n", ip -> name); + fprintf (leaseFile, " interface \"%s\";\n", ip->name); fprintf (leaseFile, " fixed-address %s;\n", - piaddr (lease -> address)); - if (lease -> filename) + piaddr (lease->address)); + if (lease->filename) fprintf (leaseFile, " filename \"%s\";\n", - lease -> filename); - if (lease -> server_name) + lease->filename); + if (lease->server_name) fprintf (leaseFile, " server-name \"%s\";\n", - lease -> filename); - if (lease -> medium) + lease->server_name); + if (lease->medium) fprintf (leaseFile, " medium \"%s\";\n", - lease -> medium -> string); + lease->medium->string); for (i = 0; i < 256; i++) { - if (lease -> options [i].len) { + if (lease->options [i].len) { fprintf (leaseFile, " option %s %s;\n", dhcp_options [i].name, pretty_print_option - (i, lease -> options [i].data, - lease -> options [i].len, 1, 1)); + (i, lease->options [i].data, + lease->options [i].len, 1, 1)); } } - t = gmtime (&lease -> renewal); + + /* 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. */ + t = gmtime (&lease->renewal); fprintf (leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - t = gmtime (&lease -> rebind); + t->tm_wday, t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + t = gmtime (&lease->rebind); fprintf (leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - t = gmtime (&lease -> expiry); + t->tm_wday, t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + t = gmtime (&lease->expiry); fprintf (leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); + t->tm_wday, t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); fprintf (leaseFile, "}\n"); fflush (leaseFile); } @@ -1813,76 +1926,35 @@ void write_client_lease (ip, lease) /* Variables holding name of script and file pointer for writing to script. Needless to say, this is not reentrant - only one script can be invoked at a time. */ -char **scriptEnv = NULL; -int scriptEnvsize = 0; - -void script_set_env (name, value) - char *name; - char *value; -{ - int i, namelen; - - namelen = strlen(name); - - for (i = 0; scriptEnv[i]; i++) { - if (strncmp(scriptEnv[i], name, namelen) == 0 && - scriptEnv[i][namelen] == '=') - break; - } - if (scriptEnv[i]) { - /* Reuse the slot. */ - free(scriptEnv[i]); - } else { - /* New variable. Expand if necessary. */ - if (i >= scriptEnvsize - 1) { - scriptEnvsize += 50; - scriptEnv = realloc(scriptEnv, scriptEnvsize); - if (scriptEnv == NULL) - error("script_set_env: no memory for variable"); - } - /* Need to set the NULL pointer at end of array beyond - the new slot. */ - scriptEnv[i + 1] = NULL; - } - /* Allocate space and format the variable in the appropriate slot. */ - scriptEnv[i] = malloc(strlen(name) + 1 + strlen(value) + 1); - if (scriptEnv[i] == NULL) - error("script_set_env: no memory for variable assignment"); - - snprintf(scriptEnv[i], strlen(name) + 1 + strlen(value) + 1, - "%s=%s", name, value); -} - -void script_flush_env() -{ - int i; - - for (i = 0; scriptEnv[i]; i++) { - free(scriptEnv[i]); - scriptEnv[i] = NULL; - } -} +char scriptName [256]; +FILE *scriptFile; void script_init (ip, reason, medium) struct interface_info *ip; char *reason; struct string_list *medium; { - scriptEnvsize = 100; - scriptEnv = malloc(scriptEnvsize * sizeof(char *)); + if (ip) { + ip->client->scriptEnvsize = 100; + ip->client->scriptEnv = malloc(ip->client->scriptEnvsize + * sizeof(char *)); + if (ip->client->scriptEnv == NULL) + error ("script_init: no memory for environment initialization"); + + ip->client->scriptEnv[0]=strdup(CLIENT_PATH); + if (ip->client->scriptEnv[0] == NULL) + error ("script_init:n no memory for environment initialization"); - if (scriptEnv == NULL) - error ("script_init: no memory for environment initialization"); + ip->client->scriptEnv[1]=NULL; - scriptEnv[0] = NULL; + script_set_env(ip->client, "", "interface", ip->name); - if (ip) { - script_set_env ("interface", ip -> name); - } - if (medium) { - script_set_env ("medium", medium -> string); + if (medium) + script_set_env(ip->client, "", "medium", + medium->string); + + script_set_env(ip->client, "", "reason", reason); } - script_set_env ("reason", reason); } void script_write_params (ip, prefix, lease) @@ -1892,11 +1964,11 @@ void script_write_params (ip, prefix, lease) { int i; u_int8_t dbuf [1500]; - char name[1024], value[1024]; - int len; + int len = 0; + char tbuf[128]; - snprintf (name, sizeof(name), "%sip_address", prefix); - script_set_env (name, piaddr (lease -> address)); + script_set_env(ip->client, prefix, "ip_address", + piaddr(lease->address)); /* For the benefit of Linux (and operating systems which may have similar needs), compute the network address based on @@ -1905,65 +1977,58 @@ void script_write_params (ip, prefix, lease) broadcast address, not the host address all zeroes broadcast address). */ - if (lease -> options [DHO_SUBNET_MASK].len && - (lease -> options [DHO_SUBNET_MASK].len < - sizeof lease -> address.iabuf)) { + if (lease->options [DHO_SUBNET_MASK].len && + (lease->options [DHO_SUBNET_MASK].len < + sizeof lease->address.iabuf)) { struct iaddr netmask, subnet, broadcast; memcpy (netmask.iabuf, - lease -> options [DHO_SUBNET_MASK].data, - lease -> options [DHO_SUBNET_MASK].len); - netmask.len = lease -> options [DHO_SUBNET_MASK].len; - - subnet = subnet_number (lease -> address, netmask); + lease->options [DHO_SUBNET_MASK].data, + lease->options [DHO_SUBNET_MASK].len); + netmask.len = lease->options [DHO_SUBNET_MASK].len; + + subnet = subnet_number (lease->address, netmask); if (subnet.len) { - snprintf (name, sizeof(name), "%snetwork_number", - prefix); - script_set_env (name, piaddr (subnet)); - - if (!lease -> options [DHO_BROADCAST_ADDRESS].len) { + script_set_env(ip->client, prefix, "network_number", + piaddr(subnet)); + if (!lease->options [DHO_BROADCAST_ADDRESS].len) { broadcast = broadcast_addr (subnet, netmask); - if (broadcast.len) { - snprintf (name, sizeof(name), - "%sbroadcast_address", - prefix); - script_set_env (name, - piaddr (broadcast)); - } + if (broadcast.len) + script_set_env(ip->client, prefix, + "broadcast_address", + piaddr(broadcast)); } } } - - if (lease -> filename) { - snprintf (name, sizeof(name), "%sfilename", prefix); - script_set_env (name, lease -> filename); - } - if (lease -> server_name) { - snprintf (name, sizeof(name), "%sserver_name", prefix); - script_set_env (name, lease -> server_name); - } + + if (lease->filename) + script_set_env(ip->client, prefix, "filename", + lease->filename); + if (lease->server_name) + script_set_env(ip->client, prefix, "server_name", + lease->server_name); for (i = 0; i < 256; i++) { - u_int8_t *dp; - - if (ip -> client -> config -> defaults [i].len) { - if (lease -> options [i].len) { - switch (ip -> client -> - config -> default_actions [i]) { + u_int8_t *dp = NULL; + + if (ip->client->config->defaults [i].len) { + if (lease->options [i].len) { + switch (ip->client -> + config->default_actions [i]) { case ACTION_DEFAULT: - dp = lease -> options [i].data; - len = lease -> options [i].len; + dp = lease->options [i].data; + len = lease->options [i].len; break; case ACTION_SUPERSEDE: supersede: - dp = ip -> client -> - config -> defaults [i].data; - len = ip -> client -> - config -> defaults [i].len; + dp = ip->client -> + config->defaults [i].data; + len = ip->client -> + config->defaults [i].len; break; case ACTION_PREPEND: - len = (ip -> client -> - config -> defaults [i].len + - lease -> options [i].len); + len = (ip->client -> + config->defaults [i].len + + lease->options [i].len); if (len > sizeof dbuf) { warn ("no space to %s %s", "prepend option", @@ -1972,20 +2037,20 @@ void script_write_params (ip, prefix, lease) } dp = dbuf; memcpy (dp, - ip -> client -> - config -> defaults [i].data, - ip -> client -> - config -> defaults [i].len); - memcpy (dp + ip -> client -> - config -> defaults [i].len, - lease -> options [i].data, - lease -> options [i].len); - dp [len] = '\0'; + ip->client-> + config->defaults [i].data, + ip->client-> + config->defaults [i].len); + memcpy (dp + ip->client-> + config->defaults [i].len, + lease->options [i].data, + lease->options [i].len); + dp [len] = '\0'; break; case ACTION_APPEND: - len = (ip -> client -> - config -> defaults [i].len + - lease -> options [i].len); + len = (ip->client -> + config->defaults [i].len + + lease->options [i].len); if (len > sizeof dbuf) { warn ("no space to %s %s", "append option", @@ -1993,98 +2058,161 @@ void script_write_params (ip, prefix, lease) goto supersede; } dp = dbuf; - memcpy (dp, lease -> options [i].data, - lease -> options [i].len); - memcpy (dp + lease -> options [i].len, - ip -> client -> - config -> defaults [i].data, - ip -> client -> - config -> defaults [i].len); + memcpy (dp, + lease->options [i].data, + lease->options [i].len); + memcpy (dp + lease->options [i].len, + ip->client-> + config->defaults [i].data, + ip->client-> + config->defaults [i].len); dp [len] = '\0'; } } else { - dp = ip -> client -> - config -> defaults [i].data; - len = ip -> client -> - config -> defaults [i].len; + dp = ip->client -> + config->defaults [i].data; + len = ip->client -> + config->defaults [i].len; } - } else if (lease -> options [i].len) { - len = lease -> options [i].len; - dp = lease -> options [i].data; + } else if (lease->options [i].len) { + len = lease->options [i].len; + dp = lease->options [i].data; } else { len = 0; } if (len) { - char *s = dhcp_option_ev_name (&dhcp_options [i]); - - snprintf (name, sizeof(name), "%s%s", prefix, s); - script_set_env (name, pretty_print_option (i, dp, len, 0, 0)); + char name [256]; + if (dhcp_option_ev_name (name, sizeof name, + &dhcp_options [i])) + script_set_env(ip->client, prefix, name, + pretty_print_option (i, dp, len, 0, 0)); } } - snprintf (name, sizeof(name), "%sexpiry", prefix); - snprintf (value, sizeof(value), "%d", (int)lease -> expiry); /* XXX */ - script_set_env (name, value); + snprintf(tbuf, sizeof(tbuf), "%d", (int) lease->expiry); + script_set_env(ip->client, prefix, "expiry", tbuf); } int script_go (ip) struct interface_info *ip; { - char *p, *script_name, *script_argv[2]; - pid_t pid, wait_pid; - int status; - - if (ip) - script_name = ip -> client -> config -> script_name; - else - script_name = top_level_config.script_name; + char *scriptName; + char *argv [2]; + char **envp; + char *epp [3]; + char reason [] = "REASON=NBI"; + static char client_path [] = CLIENT_PATH; + int pid, wpid, wstatus; - if ((p = strrchr(script_name, '/')) != NULL) - p++; - else - p = script_name; - - script_argv[0] = p; - script_argv[1] = NULL; - - if ((pid = fork()) < 0) - error("Can't fork script: %m"); + if (ip) { + scriptName = ip->client->config->script_name; + envp = ip->client ->scriptEnv; + } else { + scriptName = top_level_config.script_name; + epp [0] = reason; + epp [1] = client_path; + epp [2] = (char *)0; + envp = epp; + } + + argv [0] = scriptName; + argv [1] = (char *)0; + + pid = fork (); + if (pid < 0) { + error ("fork: %m"); + wstatus = 0; + } else if (pid) { + do { + wpid = wait (&wstatus); + } while (wpid != pid && wpid > 0); + if (wpid < 0) { + error ("wait: %m"); + wstatus = 0; + } + } else { + execve (scriptName, argv, envp); + error ("execve (%s, ...): %m", scriptName); + exit (0); + } + + if (ip) { + script_flush_env(ip->client); + } + return wstatus & 0xff; +} + +void script_set_env (client, prefix, name, value) + struct client_state *client; + const char *prefix; + const char *name; + const char *value; +{ + int i, namelen; + + namelen = strlen(name); - if (pid == 0) { - execve(script_name, script_argv, scriptEnv); - error("script_go: exec: %m"); + for (i = 0; client->scriptEnv[i]; i++) { + if (strncmp(client->scriptEnv[i], name, namelen) == 0 && + client->scriptEnv[i][namelen] == '=') + break; + } + if (client->scriptEnv[i]) { + /* Reuse the slot. */ + free(client->scriptEnv[i]); + } else { + /* New variable. Expand if necessary. */ + if (i >= client->scriptEnvsize - 1) { + client->scriptEnvsize += 50; + client->scriptEnv = realloc(client->scriptEnv, + client->scriptEnvsize); + if (client->scriptEnv == NULL) + error("script_set_env: no memory for variable"); + } + /* need to set the NULL pointer at end of array beyond + the new slot. */ + client->scriptEnv[i + 1] = NULL; } - script_flush_env(); + /* Allocate space and format the variable in the appropriate slot. */ + client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 + + strlen(value) + 1); + if (client->scriptEnv[i] == NULL) + error("script_set_env: no memory for variable assignment"); - wait_pid = wait((int *) &status); + snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) + + 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value); +} + +void script_flush_env(struct client_state *client) +{ + int i; - if (wait_pid != -1) { - if (wait_pid != pid) - error ("got wrong pid"); - if (WIFEXITED(status) || WIFSIGNALED(status)) - return (WEXITSTATUS(status)); + for (i = 0; client->scriptEnv[i]; i++) { + free(client->scriptEnv[i]); + client->scriptEnv[i] = NULL; } - return (-1); + client->scriptEnvsize = 0; } -char *dhcp_option_ev_name (option) +int dhcp_option_ev_name (buf, buflen, option) + char *buf; + size_t buflen; struct option *option; { - static char evbuf [256]; int i; - if (strlen (option -> name) + 1 > sizeof evbuf) - error ("option %s name is larger than static buffer."); - for (i = 0; option -> name [i]; i++) { - if (option -> name [i] == '-') - evbuf [i] = '_'; + for (i = 0; option->name [i]; i++) { + if (i + 1 == buflen) + return 0; + if (option->name [i] == '-') + buf [i] = '_'; else - evbuf [i] = option -> name [i]; + buf [i] = option->name [i]; } - evbuf [i] = 0; - return evbuf; + buf [i] = 0; + return 1; } - + void go_daemon () { static int state = 0; @@ -2092,7 +2220,7 @@ void go_daemon () /* Don't become a daemon if the user requested otherwise. */ if (no_daemon) { - write_pidfile(_PATH_DHCLIENT_PID, getpid()); + write_client_pid_file (); return; } @@ -2112,101 +2240,127 @@ void go_daemon () /* Become session leader and get pid... */ pid = setsid (); - write_pidfile(_PATH_DHCLIENT_PID, getpid()); + /* Close standard I/O descriptors. */ + close(0); + close(1); + close(2); + + write_client_pid_file (); +} + +void write_client_pid_file () +{ + FILE *pf; + int pfdesc; + + pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644); + + if (pfdesc < 0) { + warn ("Can't create %s: %m", path_dhclient_pid); + return; + } + + pf = fdopen (pfdesc, "w"); + if (!pf) + warn ("Can't fdopen %s: %m", path_dhclient_pid); + else { + fprintf (pf, "%ld\n", (long)getpid ()); + fclose (pf); + } } int check_option (struct client_lease *l, int option) { - char *opbuf; - - /* we use this, since this is what gets passed to dhclient-script */ - - opbuf = pretty_print_option (option, l->options[option].data, - l->options[option].len, 0, 0); - switch(option) { - case DHO_SUBNET_MASK : - case DHO_TIME_SERVERS : - case DHO_NAME_SERVERS : - case DHO_ROUTERS : - case DHO_DOMAIN_NAME_SERVERS : - case DHO_LOG_SERVERS : - case DHO_COOKIE_SERVERS : - case DHO_LPR_SERVERS : - case DHO_IMPRESS_SERVERS : - case DHO_RESOURCE_LOCATION_SERVERS : - case DHO_SWAP_SERVER : - case DHO_BROADCAST_ADDRESS : - case DHO_NIS_SERVERS : - case DHO_NTP_SERVERS : - case DHO_NETBIOS_NAME_SERVERS : - case DHO_NETBIOS_DD_SERVER : - case DHO_FONT_SERVERS : - /* These should be a list of one or more IP addresses, separated - * by spaces. If they aren't, this lease is not valid. - */ - if (!ipv4addrs(opbuf)) { - warn("Invalid IP address in option: %s", opbuf); - return(0); - } - return(1) ; - case DHO_HOST_NAME : - case DHO_DOMAIN_NAME : - case DHO_NIS_DOMAIN : - case DHO_DHCP_SERVER_IDENTIFIER : - /* This has to be a valid internet domain name */ - if (!res_hnok(opbuf)) { - warn("Bogus name option: %s", opbuf); - return(0); - } - return(1); - case DHO_PAD : - case DHO_TIME_OFFSET : - case DHO_BOOT_SIZE : - case DHO_MERIT_DUMP : - case DHO_ROOT_PATH : - case DHO_EXTENSIONS_PATH : - case DHO_IP_FORWARDING : - case DHO_NON_LOCAL_SOURCE_ROUTING : - case DHO_POLICY_FILTER : - case DHO_MAX_DGRAM_REASSEMBLY : - case DHO_DEFAULT_IP_TTL : - case DHO_PATH_MTU_AGING_TIMEOUT : - case DHO_PATH_MTU_PLATEAU_TABLE : - case DHO_INTERFACE_MTU : - case DHO_ALL_SUBNETS_LOCAL : - case DHO_PERFORM_MASK_DISCOVERY : - case DHO_MASK_SUPPLIER : - case DHO_ROUTER_DISCOVERY : - case DHO_ROUTER_SOLICITATION_ADDRESS : - case DHO_STATIC_ROUTES : - case DHO_TRAILER_ENCAPSULATION : - case DHO_ARP_CACHE_TIMEOUT : - case DHO_IEEE802_3_ENCAPSULATION : - case DHO_DEFAULT_TCP_TTL : - case DHO_TCP_KEEPALIVE_INTERVAL : - case DHO_TCP_KEEPALIVE_GARBAGE : - case DHO_VENDOR_ENCAPSULATED_OPTIONS : - case DHO_NETBIOS_NODE_TYPE : - case DHO_NETBIOS_SCOPE : - case DHO_X_DISPLAY_MANAGER : - case DHO_DHCP_REQUESTED_ADDRESS : - case DHO_DHCP_LEASE_TIME : - case DHO_DHCP_OPTION_OVERLOAD : - case DHO_DHCP_MESSAGE_TYPE : - case DHO_DHCP_PARAMETER_REQUEST_LIST : - case DHO_DHCP_MESSAGE : - case DHO_DHCP_MAX_MESSAGE_SIZE : - case DHO_DHCP_RENEWAL_TIME : - case DHO_DHCP_REBINDING_TIME : - case DHO_DHCP_CLASS_IDENTIFIER : - case DHO_DHCP_CLIENT_IDENTIFIER : - case DHO_DHCP_USER_CLASS_ID : - case DHO_END : - /* do nothing */ - return(1); - default: - warn("unknown dhcp option value 0x%x", option); - return(unknown_ok); - } + char *opbuf; + + /* we use this, since this is what gets passed to dhclient-script */ + + opbuf = pretty_print_option (option, l->options[option].data, + l->options[option].len, 0, 0); + switch(option) { + case DHO_SUBNET_MASK : + case DHO_TIME_SERVERS : + case DHO_NAME_SERVERS : + case DHO_ROUTERS : + case DHO_DOMAIN_NAME_SERVERS : + case DHO_LOG_SERVERS : + case DHO_COOKIE_SERVERS : + case DHO_LPR_SERVERS : + case DHO_IMPRESS_SERVERS : + case DHO_RESOURCE_LOCATION_SERVERS : + case DHO_SWAP_SERVER : + case DHO_BROADCAST_ADDRESS : + case DHO_NIS_SERVERS : + case DHO_NTP_SERVERS : + case DHO_NETBIOS_NAME_SERVERS : + case DHO_NETBIOS_DD_SERVER : + case DHO_FONT_SERVERS : + /* These should be a list of one or more IP addresses, separated + * by spaces. If they aren't, this lease is not valid. + */ + if (!ipv4addrs(opbuf)) { + warn("Invalid IP address in option: %s", opbuf); + return(0); + } + return(1) ; + case DHO_HOST_NAME : + case DHO_DOMAIN_NAME : + case DHO_NIS_DOMAIN : + case DHO_DHCP_SERVER_IDENTIFIER : + /* This has to be a valid internet domain name */ + if (!res_hnok(opbuf)) { + warn("Bogus name option: %s", opbuf); + return(0); + } + return(1); + case DHO_PAD : + case DHO_TIME_OFFSET : + case DHO_BOOT_SIZE : + case DHO_MERIT_DUMP : + case DHO_ROOT_PATH : + case DHO_EXTENSIONS_PATH : + case DHO_IP_FORWARDING : + case DHO_NON_LOCAL_SOURCE_ROUTING : + case DHO_POLICY_FILTER : + case DHO_MAX_DGRAM_REASSEMBLY : + case DHO_DEFAULT_IP_TTL : + case DHO_PATH_MTU_AGING_TIMEOUT : + case DHO_PATH_MTU_PLATEAU_TABLE : + case DHO_INTERFACE_MTU : + case DHO_ALL_SUBNETS_LOCAL : + case DHO_PERFORM_MASK_DISCOVERY : + case DHO_MASK_SUPPLIER : + case DHO_ROUTER_DISCOVERY : + case DHO_ROUTER_SOLICITATION_ADDRESS : + case DHO_STATIC_ROUTES : + case DHO_TRAILER_ENCAPSULATION : + case DHO_ARP_CACHE_TIMEOUT : + case DHO_IEEE802_3_ENCAPSULATION : + case DHO_DEFAULT_TCP_TTL : + case DHO_TCP_KEEPALIVE_INTERVAL : + case DHO_TCP_KEEPALIVE_GARBAGE : + case DHO_VENDOR_ENCAPSULATED_OPTIONS : + case DHO_NETBIOS_NODE_TYPE : + case DHO_NETBIOS_SCOPE : + case DHO_X_DISPLAY_MANAGER : + case DHO_DHCP_REQUESTED_ADDRESS : + case DHO_DHCP_LEASE_TIME : + case DHO_DHCP_OPTION_OVERLOAD : + case DHO_DHCP_MESSAGE_TYPE : + case DHO_DHCP_PARAMETER_REQUEST_LIST : + case DHO_DHCP_MESSAGE : + case DHO_DHCP_MAX_MESSAGE_SIZE : + case DHO_DHCP_RENEWAL_TIME : + case DHO_DHCP_REBINDING_TIME : + case DHO_DHCP_CLASS_IDENTIFIER : + case DHO_DHCP_CLIENT_IDENTIFIER : + case DHO_DHCP_USER_CLASS_ID : + case DHO_END : + /* do nothing */ + return(1); + default: + warn("unknown dhcp option value 0x%x", option); + return(unknown_ok); + } } int @@ -2214,10 +2368,10 @@ res_hnok(dn) const char *dn; { int pch = PERIOD, ch = *dn++; - + while (ch != '\0') { int nch = *dn++; - + if (periodchar(ch)) { ; } else if (periodchar(pch)) { @@ -2240,17 +2394,17 @@ res_hnok(dn) * otherwise, return 0 */ int ipv4addrs(char * buf) { - struct in_addr jnk; - int count = 0; - - while (inet_aton(buf, &jnk) == 1){ - count++; - while (periodchar(*buf) || digitchar(*buf)) - buf++; - if (*buf == '\0') - return(count); - while (*buf == ' ') - buf++; - } - return(0); + struct in_addr jnk; + int count = 0; + + while (inet_aton(buf, &jnk) == 1){ + count++; + while (periodchar(*buf) || digitchar(*buf)) + buf++; + if (*buf == '\0') + return(count); + while (*buf == ' ') + buf++; + } + return(0); } diff --git a/usr.sbin/dhcp/dhclient/dhclient.conf b/usr.sbin/dhcp/dhclient/dhclient.conf index bb7b8f7f988..147e0045a5d 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.conf +++ b/usr.sbin/dhcp/dhclient/dhclient.conf @@ -11,7 +11,7 @@ retry 60; reboot 10; select-timeout 5; initial-interval 2; -script "/sbin/dhclient-script"; +script "/etc/dhclient-script"; media "-link0 -link1 -link2", "link0 link1"; reject 192.33.137.209; diff --git a/usr.sbin/dhcp/dhclient/dhclient.conf.5 b/usr.sbin/dhcp/dhclient/dhclient.conf.5 index 3386db8f354..691908193e0 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.conf.5 +++ b/usr.sbin/dhcp/dhclient/dhclient.conf.5 @@ -248,7 +248,7 @@ statement. .PP If for some set of options the client should always use its own value rather than any value supplied by the server, these values can be -defined in the +defined in the .B supersede statement. .PP @@ -259,14 +259,15 @@ statement. \fBprepend { [ \fIoption declaration\fR ] [\fB,\fI ... \fIoption declaration\fR ]\fB}\fR .PP -If for some set of options the client should first a value it -supplies, and then use the values supplied by +If for some set of options the client should use a value you +supply, and then use the values supplied by the server, if any, these values can be defined in the .B prepend statement. The .B prepend statement can only be used for options which -allow more than one value to be given. +allow more than one value to be given. This restriction is not +enforced - if violated, the results are unpredictable. .PP .I The .B append @@ -275,14 +276,15 @@ allow more than one value to be given. \fBappend { [ \fIoption declaration\fR ] [\fB,\fI ... \fIoption declaration\fR ]\fB}\fR .PP -If for some set of options the client should first a value it -supplies, and then use the values supplied by -the server, if any, these values can be defined in the +If for some set of options the client should first use the values +supplied by the server, if any, and then use values you supply, these +values can be defined in the .B append statement. The .B append statement can only be used for options which -allow more than one value to be given. +allow more than one value to be given. This restriction is not +enforced - if you ignore it, the behaviour will be unpredictable. .SH LEASE DECLARATIONS .PP .I The @@ -292,7 +294,7 @@ allow more than one value to be given. \fBlease {\fR \fIlease-declaration\fR [ ... \fIlease-declaration ] \fB}\fR .PP The DHCP client may decide after some period of time (see \fBPROTOCOL -TIMING\fR) that it is not going to succeed in contacting a +TIMING\fR) decide that it is not going to succeed in contacting a server. At that time, it consults its own database of old leases and tests each one that has not yet timed out by pinging the listed router for that lease to see if that lease could work. It is possible to @@ -378,7 +380,7 @@ interface's final configuration once a lease has been acquired. If no lease is acquired, the script is used to test predefined leases, if any, and also called once if no valid lease can be identified. For more information, see -.B dhclient-script(8). +.B dhclient-lease(8). .PP \fBmedium "\fImedia setup\fB";\fR .PP @@ -389,7 +391,7 @@ automatically determine the type of network to which they are connected. The media setup string is a system-dependent parameter which is passed to the dhcp client configuration script when initializing the interface. On Unix and Unix-like systems, the -argument is passed on the ifconfig command line when configuring the +argument is passed on the ifconfig command line when configuring te interface. .PP The dhcp client automatically declares this parameter if it used a @@ -430,8 +432,8 @@ specified as zero. The year is specified with the century, so it should generally be four digits except for really long leases. The month is specified as a number starting with 1 for January. The day of the month is likewise specified starting with 1. The hour is a -number between 0 and 23, the minute a number between 0 and 60, and the -second also a number between 0 and 60. +number between 0 and 23, the minute a number between 0 and 69, and the +second also a number between 0 and 69. .SH ALIAS DECLARATIONS \fBalias { \fI declarations ... \fB}\fR .PP @@ -518,7 +520,7 @@ interface "ep0" { request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, host-name; require subnet-mask, domain-name-servers; - script "/sbin/dhclient-script"; + script "/etc/dhclient-script"; media "media 10baseT/UTP", "media 10base2/BNC"; } diff --git a/usr.sbin/dhcp/dhclient/dhclient.leases.5 b/usr.sbin/dhcp/dhclient/dhclient.leases.5 index 1c61a60b1cc..e0da360524a 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.leases.5 +++ b/usr.sbin/dhcp/dhclient/dhclient.leases.5 @@ -1,4 +1,3 @@ -.\" $OpenBSD: dhclient.leases.5,v 1.2 1999/05/30 02:42:22 pjanzen Exp $ .\" dhclient.conf.5 .\" .\" Copyright (c) 1997 The Internet Software Consortium. @@ -45,12 +44,12 @@ database of leases that it has acquired that are still valid. The database is a free-form ASCII file containing one valid declaration per lease. If more than one declaration appears for a given lease, the last one in the file is used. The file is written as a log, so -this is not an unusual occurrence. +this is not an unusual occurrance. .PP The format of the lease declarations is described in .B dhclient.conf(5). .SH FILES -.B /var/db/dhclient.leases +.B DBDIR/dhclient.leases .SH SEE ALSO dhclient(8), dhcp-options(5), dhclient.conf(5), dhcpd(8), dhcpd.conf(5), RFC2132, RFC2131. diff --git a/usr.sbin/dhcp/includes/cf/alphaosf.h b/usr.sbin/dhcp/includes/cf/alphaosf.h index e8298ba3d14..91171404409 100644 --- a/usr.sbin/dhcp/includes/cf/alphaosf.h +++ b/usr.sbin/dhcp/includes/cf/alphaosf.h @@ -35,16 +35,6 @@ * under a contract with Vixie Laboratories. */ -/* Define the basic integer types... */ -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; - -typedef unsigned char u_int8_t; -typedef unsigned short u_int16_t; -typedef unsigned int u_int32_t; -typedef unsigned long u_int64_t; - #include #include #include @@ -63,6 +53,18 @@ extern int h_errno; #include #include +/* Define the basic integer types... */ +#if !defined (__BIT_TYPES_DEFINED__) +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; +typedef unsigned long u_int64_t; +#endif + /* Varargs stuff... */ #include #define VA_DOTDOTDOT va_alist diff --git a/usr.sbin/dhcp/includes/cf/freebsd.h b/usr.sbin/dhcp/includes/cf/freebsd.h index 965d33236f2..032d52c2b00 100644 --- a/usr.sbin/dhcp/includes/cf/freebsd.h +++ b/usr.sbin/dhcp/includes/cf/freebsd.h @@ -3,7 +3,8 @@ System dependencies for FreeBSD... */ /* - * Copyright (c) 1996 The Internet Software Consortium. All rights reserved. + * Copyright (c) 1996, 1998 The Internet Software Consortium. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,7 +54,10 @@ extern int h_errno; #include #include -#define INADDR_LOOPBACK ((u_int32_t)0x7f000001) +#include +#if !defined (INADDR_LOOPBACK) +# define INADDR_LOOPBACK ((u_int32_t)0x7f000001) +#endif /* Varargs stuff... */ #include diff --git a/usr.sbin/dhcp/includes/cf/hpux.h b/usr.sbin/dhcp/includes/cf/hpux.h index 7271931fa6d..191839401f4 100644 --- a/usr.sbin/dhcp/includes/cf/hpux.h +++ b/usr.sbin/dhcp/includes/cf/hpux.h @@ -65,9 +65,17 @@ extern int h_errno; #define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" #endif +#if !defined (__ANSI__) +/* Varargs stuff: use stdarg.h instead ... */ +#include +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl +#else #include #define VA_DOTDOTDOT va_alist #define VA_start(list, last) va_start (list) +#endif #define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) #define NO_SNPRINTF @@ -82,3 +90,7 @@ extern int h_errno; #define GET_TIME(x) time ((x)) #define random rand + +#define BIG_ENDIAN 1 +#define LITTLE_ENDIEN 2 +#define BYTE_ORDER BIG_ENDIAN diff --git a/usr.sbin/dhcp/includes/cf/linux.h b/usr.sbin/dhcp/includes/cf/linux.h index 4386a7e2ff8..cb7e23c57fe 100644 --- a/usr.sbin/dhcp/includes/cf/linux.h +++ b/usr.sbin/dhcp/includes/cf/linux.h @@ -5,7 +5,7 @@ Based on a configuration originally supplied by Jonathan Stone. */ /* - * Copyright (c) 1996, 1998 The Internet Software Consortium. + * Copyright (c) 1996, 1998, 1999 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,10 @@ typedef unsigned short u_int16_t; typedef unsigned long u_int32_t; #endif /* __BIT_TYPES_DEFINED__ */ +typedef u_int8_t u8; +typedef u_int16_t u16; +typedef u_int32_t u32; + #include #include #include @@ -63,7 +67,7 @@ extern int h_errno; #include #include -#if defined (LINUX_1_X) +#if LINUX_MAJOR == 1 # include # include /* also necessary */ #else @@ -72,14 +76,19 @@ extern int h_errno; #include /* gettimeofday()*/ -#ifndef _PATH_DHCPD_PID -#define _PATH_DHCPD_PID "/var/run/dhcpd.pid" -#endif -#ifndef _PATH_DHCLIENT_PID -#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" +/* Databases go in /var/state/dhcp. It would also be valid to put them + in /var/state/misc - indeed, given that there's only one lease file, it + would probably be better. However, I have some ideas for optimizing + the lease database that may result in a _lot_ of smaller files being + created, so in that context it makes more sense to have a seperate + directory. */ + +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "/var/state/dhcp/dhcpd.leases" #endif + #ifndef _PATH_DHCLIENT_DB -#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" +#define _PATH_DHCLIENT_DB "/var/state/dhcp/dhclient.leases" #endif /* Varargs stuff... */ @@ -102,9 +111,28 @@ extern int h_errno; #define TIME time_t #define GET_TIME(x) time ((x)) -#if defined (USE_DEFAULT_NETWORK) +#if (LINUX_MAJOR >= 2) +# if (LINUX_MINOR >= 1) +# if defined (USE_DEFAULT_NETWORK) +# define USE_LPF +# endif +# define LINUX_SLASHPROC_DISCOVERY +# define PROCDEV_DEVICE "/proc/net/dev" +# define HAVE_ARPHRD_TUNNEL +# define HAVE_TR_SUPPORT +# endif +# define HAVE_ARPHRD_METRICOM +# define HAVE_ARPHRD_IEEE802 +# define HAVE_ARPHRD_LOOPBACK +# define HAVE_SO_BINDTODEVICE +# define HAVE_SIOCGIFHWADDR +#endif + +#if !defined (USE_LPF) +# if defined (USE_DEFAULT_NETWORK) # define USE_SOCKETS -# define IGNORE_HOSTUNREACH +# endif +# define IGNORE_HOSTUNREACH #endif #define ALIAS_NAMES_PERMUTED diff --git a/usr.sbin/dhcp/includes/cf/nextstep.h b/usr.sbin/dhcp/includes/cf/nextstep.h index c1e88e1d205..38b4d479d1d 100644 --- a/usr.sbin/dhcp/includes/cf/nextstep.h +++ b/usr.sbin/dhcp/includes/cf/nextstep.h @@ -68,9 +68,19 @@ extern int h_errno; #define IPTOS_THROUGHPUT 0x08 #define IPTOS_RELIABILITY 0x04 #endif -#define _PATH_DHCPD_PID "/etc/dhcpd.pid" -#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" -#define _PATH_DHCLIENT_PID "/etc/dhcrelay.pid" + +#if !defined (_PATH_DHCPD_PID) +# define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif + +#if !defined (_PATH_DHCLIENT_PID) +# define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif + +#if !defined (_PATH_DHCRELAY_PID) +# define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + /* Stdarg definitions for ANSI-compliant C compilers. */ #import #define VA_DOTDOTDOT ... diff --git a/usr.sbin/dhcp/includes/cf/openbsd.h b/usr.sbin/dhcp/includes/cf/openbsd.h index a70d4b6f063..1c9b3690a3b 100644 --- a/usr.sbin/dhcp/includes/cf/openbsd.h +++ b/usr.sbin/dhcp/includes/cf/openbsd.h @@ -1,4 +1,4 @@ -/* OpenBSD.h +/* netbsd.h System dependencies for OpenBSD... */ diff --git a/usr.sbin/dhcp/includes/cf/qnx.h b/usr.sbin/dhcp/includes/cf/qnx.h index 0e78582dc44..1f5b7f8de0e 100644 --- a/usr.sbin/dhcp/includes/cf/qnx.h +++ b/usr.sbin/dhcp/includes/cf/qnx.h @@ -86,6 +86,7 @@ extern int h_errno; typedef unsigned char u_int8_t; typedef unsigned short u_int16_t; typedef unsigned long u_int32_t; +typedef signed char int8_t; typedef signed short int16_t; typedef signed long int32_t; @@ -100,6 +101,13 @@ typedef signed long int32_t; #define NO_SNPRINTF #undef AF_LINK +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + /* NOTE: to get the routing of the 255.255.255.255 broadcasts to work under QNX, you need to issue the following command before starting diff --git a/usr.sbin/dhcp/includes/cf/sample.h b/usr.sbin/dhcp/includes/cf/sample.h index e50d8b17b0e..892303b977e 100644 --- a/usr.sbin/dhcp/includes/cf/sample.h +++ b/usr.sbin/dhcp/includes/cf/sample.h @@ -255,13 +255,13 @@ char *strerror PROTO ((int)); /* #define HAVE_SA_LEN */ -/* Every operating system has its own way of separating lines in a +/* Every operating system has its own way of seperating lines in a sequential text file. Most modern systems use a single character, either an ASCII Newline (10) or an ASCII Carriage Return (13). The most notable exception is MS-DOS (and consequently, Windows), which uses an ASCII Carriage Return followed by a Newline to - separate each line. Fortunately, MS-DOS C compiler libraries + seperate each line. Fortunately, MS-DOS C compiler libraries typically hide this from the programmer, returning just a Newline. Define EOL to be whatever getc() returns for a newline. */ diff --git a/usr.sbin/dhcp/includes/cf/sunos5-5.h b/usr.sbin/dhcp/includes/cf/sunos5-5.h index f88084f6d9e..07343b2d5ef 100644 --- a/usr.sbin/dhcp/includes/cf/sunos5-5.h +++ b/usr.sbin/dhcp/includes/cf/sunos5-5.h @@ -3,7 +3,8 @@ System dependencies for Solaris 2.x (tested on 2.5 with gcc)... */ /* - * Copyright (c) 1996 The Internet Software Consortium. All rights reserved. + * Copyright (c) 1996, 1998 The Internet Software Consortium. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -116,11 +117,9 @@ extern int h_errno; #define NEED_INET_ATON -/* By default, use BSD Socket API for receiving and sending packets. - This actually works pretty well on Solaris, which doesn't censor - the all-ones broadcast address. */ #if defined (USE_DEFAULT_NETWORK) -# define USE_SOCKETS +# define USE_DLPI +# define USE_DLPI_PFMOD #endif #define USE_POLL diff --git a/usr.sbin/dhcp/includes/cf/ultrix.h b/usr.sbin/dhcp/includes/cf/ultrix.h index da7c35c6c1a..c6a2fe80182 100644 --- a/usr.sbin/dhcp/includes/cf/ultrix.h +++ b/usr.sbin/dhcp/includes/cf/ultrix.h @@ -3,7 +3,8 @@ System dependencies for Ultrix 4.2 (tested on 4.2a+multicast)... */ /* - * Copyright (c) 1996 The Internet Software Consortium. All rights reserved. + * Copyright (c) 1996, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -70,6 +71,8 @@ extern int h_errno; #define u_int16_t unsigned short #define u_int32_t unsigned long +#define ssize_t size_t + /* The jmp_buf type is an array on ultrix, so we can't dereference it and must declare it differently. */ #define jbp_decl(x) jmp_buf x diff --git a/usr.sbin/dhcp/includes/dhcp.h b/usr.sbin/dhcp/includes/dhcp.h index 18127757952..b96ec3d096d 100644 --- a/usr.sbin/dhcp/includes/dhcp.h +++ b/usr.sbin/dhcp/includes/dhcp.h @@ -84,6 +84,7 @@ struct dhcp_packet { /* Possible values for hardware type (htype) field... */ #define HTYPE_ETHER 1 /* Ethernet 10Mbps */ #define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */ +#define HTYPE_FDDI 8 /* FDDI... */ /* Magic cookie validating dhcp options field (and bootp vendor extensions field). */ diff --git a/usr.sbin/dhcp/includes/dhcpd.h b/usr.sbin/dhcp/includes/dhcpd.h index 404624d34d2..25396eb29c9 100644 --- a/usr.sbin/dhcp/includes/dhcpd.h +++ b/usr.sbin/dhcp/includes/dhcpd.h @@ -3,8 +3,8 @@ Definitions for dhcpd... */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -75,7 +75,7 @@ struct option_data { struct string_list { struct string_list *next; - char string [1]; + char *string; }; /* A name server, from /etc/resolv.conf. */ @@ -106,6 +106,8 @@ struct packet { of local sender (maybe gateway). */ struct shared_network *shared_network; struct option_data options [256]; + int got_requested_address; /* True if client sent the + dhcp-requested-address option. */ }; struct hardware { @@ -144,7 +146,7 @@ struct lease { # define ABANDONED_LEASE 16 struct lease_state *state; - u_int8_t releasing; + u_int8_t releasing; }; struct lease_state { @@ -156,7 +158,20 @@ struct lease_state { struct tree_cache *options [256]; u_int32_t expiry, renewal, rebind; - char *filename, *server_name; + char filename [DHCP_FILE_LEN]; + char *server_name; + + struct iaddr from; + + int max_message_size; + u_int8_t *prl; + int prl_len; + int got_requested_address; /* True if client sent the + dhcp-requested-address option. */ + int got_server_identifier; /* True if client sent the + dhcp-server-identifier option. */ + struct shared_network *shared_network; /* Shared network of interface + on which request arrived. */ u_int32_t xid; u_int16_t secs; @@ -205,6 +220,9 @@ struct group { int one_lease_per_client; int get_lease_hostnames; int use_host_decl_names; + int use_lease_addr_for_default_route; + int authoritative; + int always_reply_rfc1048; struct tree_cache *options [256]; }; @@ -328,6 +346,7 @@ struct client_state { enum dhcp_state state; /* Current state for this interface. */ struct iaddr destination; /* Where to send packet. */ u_int32_t xid; /* Transaction ID. */ + u_int16_t secs; /* secs value from DHCPDISCOVER. */ TIME first_sending; /* When was first copy sent? */ TIME interval; /* What's the current resend interval? */ struct string_list *medium; /* Last media type tried. */ @@ -338,6 +357,12 @@ struct client_state { struct iaddr requested_address; /* Address we would like to get. */ struct client_config *config; /* Information from config file. */ + + char **scriptEnv; /* Client script env */ + int scriptEnvsize; /* size of the env table */ + + struct string_list *env; /* Client script environment. */ + int envc; /* Number of entries in environment. */ }; /* Information about each network interface. */ @@ -364,9 +389,9 @@ struct interface_info { /* Only used by DHCP client code. */ struct client_state *client; - int noifmedia; - int errors; - int dead; + int noifmedia; + int errors; + int dead; }; struct hardware_link { @@ -456,15 +481,16 @@ typedef unsigned char option_mask [16]; void parse_options PROTO ((struct packet *)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); -int cons_options PROTO ((struct packet *, struct dhcp_packet *, - struct tree_cache **, int, int, int)); +int cons_options PROTO ((struct packet *, struct dhcp_packet *, int, + struct tree_cache **, int, int, int, + u_int8_t *, int)); int store_options PROTO ((unsigned char *, int, struct tree_cache **, unsigned char *, int, int, int, int)); char *pretty_print_option PROTO ((unsigned int, unsigned char *, int, int, int)); void do_packet PROTO ((struct interface_info *, - unsigned char *, int, - unsigned short, struct iaddr, struct hardware *)); + struct dhcp_packet *, int, + unsigned int, struct iaddr, struct hardware *)); /* errwarn.c */ extern int warnings_occurred; @@ -473,7 +499,6 @@ int warn PROTO ((char *, ...)); int note PROTO ((char *, ...)); int debug PROTO ((char *, ...)); int parse_warn PROTO ((char *, ...)); -void write_pidfile PROTO((char *, pid_t)); /* dhcpd.c */ extern TIME cur_time; @@ -484,10 +509,6 @@ extern u_int16_t remote_port; extern int log_priority; extern int log_perror; -#ifdef USE_FALLBACK -extern struct interface_info fallback_interface; -#endif - extern char *path_dhcpd_conf; extern char *path_dhcpd_db; extern char *path_dhcpd_pid; @@ -558,7 +579,7 @@ void dhcprelease PROTO ((struct packet *)); void dhcpdecline PROTO ((struct packet *)); void dhcpinform PROTO ((struct packet *)); void nak_lease PROTO ((struct packet *, struct iaddr *cip)); -void ack_lease PROTO ((struct packet *, struct lease *, unsigned char, TIME)); +void ack_lease PROTO ((struct packet *, struct lease *, unsigned int, TIME)); void dhcp_reply PROTO ((struct lease *)); struct lease *find_lease PROTO ((struct packet *, struct shared_network *, int *)); @@ -582,6 +603,7 @@ extern struct subnet *find_grouped_subnet PROTO ((struct shared_network *, struct iaddr)); extern struct subnet *find_subnet PROTO ((struct iaddr)); void enter_shared_network PROTO ((struct shared_network *)); +int subnet_inner_than PROTO ((struct subnet *, struct subnet *, int)); void enter_subnet PROTO ((struct subnet *)); void enter_lease PROTO ((struct lease *)); int supersede_lease PROTO ((struct lease *, struct lease *, int)); @@ -595,7 +617,7 @@ void uid_hash_delete PROTO ((struct lease *)); void hw_hash_add PROTO ((struct lease *)); void hw_hash_delete PROTO ((struct lease *)); struct class *add_class PROTO ((int, char *)); -struct class *find_class PROTO ((int, char *, int)); +struct class *find_class PROTO ((int, unsigned char *, int)); struct group *clone_group PROTO ((struct group *, char *)); void write_leases PROTO ((void)); void dump_subnets PROTO ((void)); @@ -619,6 +641,7 @@ struct protocol *new_protocol PROTO ((char *)); struct lease_state *new_lease_state PROTO ((char *)); struct domain_search_list *new_domain_search_list PROTO ((char *)); struct name_server *new_name_server PROTO ((char *)); +struct string_list *new_string_list PROTO ((size_t size, char * name)); void free_name_server PROTO ((struct name_server *, char *)); void free_domain_search_list PROTO ((struct domain_search_list *, char *)); void free_lease_state PROTO ((struct lease_state *, char *)); @@ -634,6 +657,7 @@ void free_tree_cache PROTO ((struct tree_cache *, char *)); void free_packet PROTO ((struct packet *, char *)); void free_dhcp_packet PROTO ((struct dhcp_packet *, char *)); void free_tree PROTO ((struct tree *, char *)); +void free_string_list PROTO ((struct string_list *, char *)); /* print.c */ char *print_hw_addr PROTO ((int, int, unsigned char *)); @@ -648,14 +672,13 @@ void hash_dump PROTO ((struct hash_table *)); int if_register_socket PROTO ((struct interface_info *)); #endif -#ifdef USE_SOCKET_FALLBACK +#if defined (USE_SOCKET_FALLBACK) && !defined (USE_SOCKET_SEND) void if_reinitialize_fallback PROTO ((struct interface_info *)); void if_register_fallback PROTO ((struct interface_info *)); ssize_t send_fallback PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); -void fallback_discard PROTO ((struct protocol *)); #endif #ifdef USE_SOCKET_SEND @@ -666,6 +689,9 @@ ssize_t send_packet PROTO ((struct interface_info *, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif +#if defined (USE_SOCKET_FALLBACK) +void fallback_discard PROTO ((struct protocol *)); +#endif #ifdef USE_SOCKET_RECEIVE void if_reinitialize_receive PROTO ((struct interface_info *)); void if_register_receive PROTO ((struct interface_info *)); @@ -673,8 +699,10 @@ ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif -#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK) -void if_enable PROTO ((struct interface_info *)); +#if defined (USE_SOCKET_SEND) +int can_unicast_without_arp PROTO ((void)); +int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); +void maybe_setup_fallback PROTO ((void)); #endif /* bpf.c */ @@ -697,7 +725,34 @@ ssize_t receive_packet PROTO ((struct interface_info *, struct sockaddr_in *, struct hardware *)); #endif #if defined (USE_BPF_SEND) -void if_enable PROTO ((struct interface_info *)); +int can_unicast_without_arp PROTO ((void)); +int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); +void maybe_setup_fallback PROTO ((void)); +#endif + +/* lpf.c */ +#if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) +int if_register_lpf PROTO ( (struct interface_info *)); +#endif +#ifdef USE_LPF_SEND +void if_reinitialize_send PROTO ((struct interface_info *)); +void if_register_send PROTO ((struct interface_info *)); +ssize_t send_packet PROTO ((struct interface_info *, + struct packet *, struct dhcp_packet *, size_t, + struct in_addr, + struct sockaddr_in *, struct hardware *)); +#endif +#ifdef USE_LPF_RECEIVE +void if_reinitialize_receive PROTO ((struct interface_info *)); +void if_register_receive PROTO ((struct interface_info *)); +ssize_t receive_packet PROTO ((struct interface_info *, + unsigned char *, size_t, + struct sockaddr_in *, struct hardware *)); +#endif +#if defined (USE_LPF_SEND) +int can_unicast_without_arp PROTO ((void)); +int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); +void maybe_setup_fallback PROTO ((void)); #endif /* nit.c */ @@ -720,8 +775,31 @@ ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif -#if defined (USE_BPF_SEND) -void if_enable PROTO ((struct interface_info *)); +#if defined (USE_NIT_SEND) +int can_unicast_without_arp PROTO ((void)); +int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); +void maybe_setup_fallback PROTO ((void)); +#endif + +#ifdef USE_DLPI_SEND +void if_reinitialize_send PROTO ((struct interface_info *)); +void if_register_send PROTO ((struct interface_info *)); +ssize_t send_packet PROTO ((struct interface_info *, + struct packet *, struct dhcp_packet *, size_t, + struct in_addr, + struct sockaddr_in *, struct hardware *)); +#endif +#ifdef USE_DLPI_RECEIVE +void if_reinitialize_receive PROTO ((struct interface_info *)); +void if_register_receive PROTO ((struct interface_info *)); +ssize_t receive_packet PROTO ((struct interface_info *, + unsigned char *, size_t, + struct sockaddr_in *, struct hardware *)); +#endif +#if defined (USE_DLPI_SEND) +int can_unicast_without_arp PROTO ((void)); +int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); +void maybe_setup_fallback PROTO ((void)); #endif /* raw.c */ @@ -732,24 +810,28 @@ ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); +int can_unicast_without_arp PROTO ((void)); +int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); +void maybe_setup_fallback PROTO ((void)); #endif /* dispatch.c */ -extern struct interface_info *interfaces, *dummy_interfaces; +extern struct interface_info *interfaces, + *dummy_interfaces, *fallback_interface; extern struct protocol *protocols; extern int quiet_interface_discovery; extern void (*bootp_packet_handler) PROTO ((struct interface_info *, - unsigned char *, int, unsigned short, - struct iaddr, struct hardware *)); + struct dhcp_packet *, int, + unsigned int, + struct iaddr, struct hardware *)); extern struct timeout *timeouts; void discover_interfaces PROTO ((int)); +struct interface_info *setup_fallback PROTO ((void)); void reinitialize_interfaces PROTO ((void)); void dispatch PROTO ((void)); int locate_network PROTO ((struct packet *)); +void got_one PROTO ((struct protocol *)); void add_timeout PROTO ((TIME, void (*) PROTO ((void *)), void *)); -#if 0 -void add_fast_timeout PROTO ((UTIME, void (*) PROTO ((void *)), void *)); -#endif void cancel_timeout PROTO ((void (*) PROTO ((void *)), void *)); void add_protocol PROTO ((char *, int, void (*) PROTO ((struct protocol *)), void *)); @@ -758,9 +840,10 @@ void remove_protocol PROTO ((struct protocol *)); /* hash.c */ struct hash_table *new_hash PROTO ((void)); -void add_hash PROTO ((struct hash_table *, char *, int, unsigned char *)); -void delete_hash_entry PROTO ((struct hash_table *, char *, int)); -unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int)); +void add_hash PROTO ((struct hash_table *, unsigned char *, + int, unsigned char *)); +void delete_hash_entry PROTO ((struct hash_table *, unsigned char *, int)); +unsigned char *hash_lookup PROTO ((struct hash_table *, unsigned char *, int)); /* tables.c */ extern struct option dhcp_options [256]; @@ -778,8 +861,8 @@ u_int16_t getUShort PROTO ((unsigned char *)); int16_t getShort PROTO ((unsigned char *)); void putULong PROTO ((unsigned char *, u_int32_t)); void putLong PROTO ((unsigned char *, int32_t)); -void putUShort PROTO ((unsigned char *, u_int16_t)); -void putShort PROTO ((unsigned char *, int16_t)); +void putUShort PROTO ((unsigned char *, unsigned int)); +void putShort PROTO ((unsigned char *, int)); /* inet.c */ struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr)); @@ -823,14 +906,19 @@ void make_release PROTO ((struct interface_info *, struct client_lease *)); void free_client_lease PROTO ((struct client_lease *)); void rewrite_client_leases PROTO ((void)); void write_client_lease PROTO ((struct interface_info *, - struct client_lease *)); -char *dhcp_option_ev_name PROTO ((struct option *)); + struct client_lease *, int)); void script_init PROTO ((struct interface_info *, char *, struct string_list *)); void script_write_params PROTO ((struct interface_info *, char *, struct client_lease *)); int script_go PROTO ((struct interface_info *)); +void client_envadd PROTO ((struct client_state *, + const char *, const char *, const char *, ...)); +void script_set_env (struct client_state *, const char *, const char *, + const char *); +void script_flush_env(struct client_state *); +int dhcp_option_ev_name (char *, size_t, struct option *); struct client_lease *packet_to_lease PROTO ((struct packet *)); void go_daemon PROTO ((void)); @@ -850,7 +938,7 @@ u_int32_t wrapsum PROTO ((u_int32_t)); void assemble_hw_header PROTO ((struct interface_info *, unsigned char *, int *, struct hardware *)); void assemble_udp_ip_header PROTO ((struct interface_info *, unsigned char *, - int *, u_int32_t, u_int32_t, u_int16_t, + int *, u_int32_t, u_int32_t, unsigned int, unsigned char *, int)); ssize_t decode_hw_header PROTO ((struct interface_info *, unsigned char *, int, struct hardware *)); @@ -858,6 +946,20 @@ ssize_t decode_udp_ip_header PROTO ((struct interface_info *, unsigned char *, int, struct sockaddr_in *, unsigned char *, int)); +/* ethernet.c */ +void assemble_ethernet_header PROTO ((struct interface_info *, unsigned char *, + int *, struct hardware *)); +ssize_t decode_ethernet_header PROTO ((struct interface_info *, + unsigned char *, + int, struct hardware *)); + +/* tr.c */ +void assemble_tr_header PROTO ((struct interface_info *, unsigned char *, + int *, struct hardware *)); +ssize_t decode_tr_header PROTO ((struct interface_info *, + unsigned char *, + int, struct hardware *)); + /* dhxpxlt.c */ void convert_statement PROTO ((FILE *)); void convert_host_statement PROTO ((FILE *, jrefproto)); @@ -917,8 +1019,8 @@ int parse_ip_addr PROTO ((FILE *, struct iaddr *)); void parse_reject_statement PROTO ((FILE *, struct client_config *)); /* dhcrelay.c */ -void relay PROTO ((struct interface_info *, u_int8_t *, int, - unsigned short, struct iaddr, struct hardware *)); +void relay PROTO ((struct interface_info *, struct dhcp_packet *, int, + unsigned int, struct iaddr, struct hardware *)); /* icmp.c */ void icmp_startup PROTO ((int, void (*) PROTO ((struct iaddr, @@ -941,7 +1043,7 @@ struct sockaddr_in *pick_name_server PROTO ((void)); /* inet_addr.c */ #ifdef NEED_INET_ATON -int inet_aton PROTO ((char *, struct in_addr *)); +int inet_aton PROTO ((const char *, struct in_addr *)); #endif /* sysconf.c */ diff --git a/usr.sbin/dhcp/includes/dhctoken.h b/usr.sbin/dhcp/includes/dhctoken.h index 88acd162298..2aeb5303af1 100644 --- a/usr.sbin/dhcp/includes/dhctoken.h +++ b/usr.sbin/dhcp/includes/dhctoken.h @@ -3,8 +3,8 @@ Tokens for config file lexer and parser. */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -124,6 +124,11 @@ #define HOSTNAME 328 #define CLIENT_HOSTNAME 329 #define REJECT 330 +#define FDDI 331 +#define USE_LEASE_ADDR_FOR_DEFAULT_ROUTE 332 +#define AUTHORITATIVE 333 +#define TOKEN_NOT 334 +#define ALWAYS_REPLY_RFC1048 335 #define is_identifier(x) ((x) >= FIRST_TOKEN && \ (x) != STRING && \ diff --git a/usr.sbin/dhcp/includes/hash.h b/usr.sbin/dhcp/includes/hash.h index d30072b3c12..1bebb3140f8 100644 --- a/usr.sbin/dhcp/includes/hash.h +++ b/usr.sbin/dhcp/includes/hash.h @@ -3,7 +3,8 @@ Definitions for hashing... */ /* - * Copyright (c) 1995 The Internet Software Consortium. All rights reserved. + * Copyright (c) 1995, 1996 The Internet Software Consortium. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,7 +44,7 @@ struct hash_bucket { struct hash_bucket *next; - char *name; + unsigned char *name; int len; unsigned char *value; }; diff --git a/usr.sbin/dhcp/includes/netinet/if_ether.h b/usr.sbin/dhcp/includes/netinet/if_ether.h deleted file mode 100644 index 2af9198e542..00000000000 --- a/usr.sbin/dhcp/includes/netinet/if_ether.h +++ /dev/null @@ -1,74 +0,0 @@ -/* $NetBSD: if_ether.h,v 1.1.1.1 1997/03/29 21:52:18 mellon Exp $ */ - -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_ether.h 8.1 (Berkeley) 6/10/93 - */ - -/* - * Ethernet address - 6 octets - * this is only used by the ethers(3) functions. - */ -struct ether_addr { - u_int8_t ether_addr_octet[6]; -}; - -/* - * Structure of a 10Mb/s Ethernet header. - */ -#define ETHER_ADDR_LEN 6 - -struct ether_header { - u_int8_t ether_dhost[ETHER_ADDR_LEN]; - u_int8_t ether_shost[ETHER_ADDR_LEN]; - u_int16_t ether_type; -}; - -#define ETHERTYPE_PUP 0x0200 /* PUP protocol */ -#define ETHERTYPE_IP 0x0800 /* IP protocol */ -#define ETHERTYPE_ARP 0x0806 /* address resolution protocol */ -#define ETHERTYPE_REVARP 0x8035 /* reverse addr resolution protocol */ - -/* - * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have - * (type-ETHERTYPE_TRAIL)*512 bytes of data followed - * by an ETHER type (as given above) and then the (variable-length) header. - */ -#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ -#define ETHERTYPE_NTRAILER 16 - -#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ - -#define ETHERMTU 1500 -#define ETHERMIN (60-14) - diff --git a/usr.sbin/dhcp/includes/netinet/ip.h b/usr.sbin/dhcp/includes/netinet/ip.h deleted file mode 100644 index bb02d2eaf0a..00000000000 --- a/usr.sbin/dhcp/includes/netinet/ip.h +++ /dev/null @@ -1,171 +0,0 @@ -/* $NetBSD: ip.h,v 1.1.1.1 1997/03/29 21:52:18 mellon Exp $ */ - -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip.h 8.1 (Berkeley) 6/10/93 - */ - -/* - * Definitions for internet protocol version 4. - * Per RFC 791, September 1981. - */ -#define IPVERSION 4 - -/* - * Structure of an internet header, naked of options. - * - * We declare ip_len and ip_off to be short, rather than u_short - * pragmatically since otherwise unsigned comparisons can result - * against negative integers quite easily, and fail in subtle ways. - */ -struct ip { -#if BYTE_ORDER == LITTLE_ENDIAN - u_int8_t ip_hl:4, /* header length */ - ip_v:4; /* version */ -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int8_t ip_v:4, /* version */ - ip_hl:4; /* header length */ -#endif - u_int8_t ip_tos; /* type of service */ - int16_t ip_len; /* total length */ - u_int16_t ip_id; /* identification */ - int16_t ip_off; /* fragment offset field */ -#define IP_DF 0x4000 /* dont fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - u_int8_t ip_ttl; /* time to live */ - u_int8_t ip_p; /* protocol */ - u_int16_t ip_sum; /* checksum */ - struct in_addr ip_src, ip_dst; /* source and dest address */ -}; - -#define IP_MAXPACKET 65535 /* maximum packet size */ - -/* - * Definitions for IP type of service (ip_tos) - */ -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -/* IPTOS_LOWCOST 0x02 XXX */ - -/* - * Definitions for IP precedence (also in ip_tos) (hopefully unused) - */ -#define IPTOS_PREC_NETCONTROL 0xe0 -#define IPTOS_PREC_INTERNETCONTROL 0xc0 -#define IPTOS_PREC_CRITIC_ECP 0xa0 -#define IPTOS_PREC_FLASHOVERRIDE 0x80 -#define IPTOS_PREC_FLASH 0x60 -#define IPTOS_PREC_IMMEDIATE 0x40 -#define IPTOS_PREC_PRIORITY 0x20 -#define IPTOS_PREC_ROUTINE 0x00 - -/* - * Definitions for options. - */ -#define IPOPT_COPIED(o) ((o)&0x80) -#define IPOPT_CLASS(o) ((o)&0x60) -#define IPOPT_NUMBER(o) ((o)&0x1f) - -#define IPOPT_CONTROL 0x00 -#define IPOPT_RESERVED1 0x20 -#define IPOPT_DEBMEAS 0x40 -#define IPOPT_RESERVED2 0x60 - -#define IPOPT_EOL 0 /* end of option list */ -#define IPOPT_NOP 1 /* no operation */ - -#define IPOPT_RR 7 /* record packet route */ -#define IPOPT_TS 68 /* timestamp */ -#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ -#define IPOPT_LSRR 131 /* loose source route */ -#define IPOPT_SATID 136 /* satnet id */ -#define IPOPT_SSRR 137 /* strict source route */ - -/* - * Offsets to fields in options other than EOL and NOP. - */ -#define IPOPT_OPTVAL 0 /* option ID */ -#define IPOPT_OLEN 1 /* option length */ -#define IPOPT_OFFSET 2 /* offset within option */ -#define IPOPT_MINOFF 4 /* min value of above */ - -/* - * Time stamp option structure. - */ -struct ip_timestamp { - u_int8_t ipt_code; /* IPOPT_TS */ - u_int8_t ipt_len; /* size of structure (variable) */ - u_int8_t ipt_ptr; /* index of current entry */ -#if BYTE_ORDER == LITTLE_ENDIAN - u_int8_t ipt_flg:4, /* flags, see below */ - ipt_oflw:4; /* overflow counter */ -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int8_t ipt_oflw:4, /* overflow counter */ - ipt_flg:4; /* flags, see below */ -#endif - union ipt_timestamp { - u_int32_t ipt_time[1]; - struct ipt_ta { - struct in_addr ipt_addr; - u_int32_t ipt_time; - } ipt_ta[1]; - } ipt_timestamp; -}; - -/* flag bits for ipt_flg */ -#define IPOPT_TS_TSONLY 0 /* timestamps only */ -#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ -#define IPOPT_TS_PRESPEC 3 /* specified modules only */ - -/* bits for security (not byte swapped) */ -#define IPOPT_SECUR_UNCLASS 0x0000 -#define IPOPT_SECUR_CONFID 0xf135 -#define IPOPT_SECUR_EFTO 0x789a -#define IPOPT_SECUR_MMMM 0xbc4d -#define IPOPT_SECUR_RESTR 0xaf13 -#define IPOPT_SECUR_SECRET 0xd788 -#define IPOPT_SECUR_TOPSECRET 0x6bc5 - -/* - * Internet implementation parameters. - */ -#define MAXTTL 255 /* maximum time to live (seconds) */ -#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ -#define IPFRAGTTL 60 /* time to live for frags, slowhz */ -#define IPTTLDEC 1 /* subtracted when forwarding */ - -#define IP_MSS 576 /* default maximum segment size */ diff --git a/usr.sbin/dhcp/includes/netinet/ip_icmp.h b/usr.sbin/dhcp/includes/netinet/ip_icmp.h deleted file mode 100644 index e8cd0eda204..00000000000 --- a/usr.sbin/dhcp/includes/netinet/ip_icmp.h +++ /dev/null @@ -1,182 +0,0 @@ -/* $NetBSD: ip_icmp.h,v 1.1.1.1 1997/03/29 21:52:18 mellon Exp $ */ - -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 - */ - - -/* - * Interface Control Message Protocol Definitions. - * Per RFC 792, September 1981. - */ - -/* - * Internal of an ICMP Router Advertisement - */ -struct icmp_ra_addr { - u_int32_t ira_addr; - u_int32_t ira_preference; -}; - -/* - * Structure of an icmp header. - */ -struct icmp { - u_int8_t icmp_type; /* type of message, see below */ - u_int8_t icmp_code; /* type sub code */ - u_int16_t icmp_cksum; /* ones complement cksum of struct */ - union { - u_int8_t ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ - struct ih_idseq { - int16_t icd_id; - int16_t icd_seq; - } ih_idseq; - int32_t ih_void; - - /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ - struct ih_pmtu { - int16_t ipm_void; - int16_t ipm_nextmtu; - } ih_pmtu; - struct ih_rtradv { - u_int8_t irt_num_addrs; - u_int8_t irt_wpa; - u_int16_t irt_lifetime; - } ih_rtradv; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void -#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void -#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu -#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs -#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa -#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime - union { - struct id_ts { - u_int32_t its_otime; - u_int32_t its_rtime; - u_int32_t its_ttime; - } id_ts; - struct id_ip { - struct ip idi_ip; - /* options and then 64 bits of data */ - } id_ip; - struct icmp_ra_addr id_radv; - u_int32_t id_mask; - int8_t id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_radv icmp_dun.id_mask -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -}; - -/* - * Lower bounds on packet lengths for various types. - * For the error advice packets must first insure that the - * packet is large enought to contain the returned ip header. - * Only then can we do the check to see if 64 bits of packet - * data have been returned, since we need to check the returned - * ip header length. - */ -#define ICMP_MINLEN 8 /* abs minimum */ -#define ICMP_TSLEN (8 + 3 * sizeof (u_int32_t)) /* timestamp */ -#define ICMP_MASKLEN 12 /* address mask */ -#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ -#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) - /* N.B.: must separately check that ip_hl >= 5 */ - -/* - * Definition of type and code field values. - */ -#define ICMP_ECHOREPLY 0 /* echo reply */ -#define ICMP_UNREACH 3 /* dest unreachable, codes: */ -#define ICMP_UNREACH_NET 0 /* bad net */ -#define ICMP_UNREACH_HOST 1 /* bad host */ -#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ -#define ICMP_UNREACH_PORT 3 /* bad port */ -#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ -#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ -#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ -#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ -#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ -#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ -#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ -#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ -#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ -#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ -#define ICMP_REDIRECT 5 /* shorter route, codes: */ -#define ICMP_REDIRECT_NET 0 /* for network */ -#define ICMP_REDIRECT_HOST 1 /* for host */ -#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ -#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ -#define ICMP_ECHO 8 /* echo service */ -#define ICMP_ROUTERADVERT 9 /* router advertisement */ -#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ -#define ICMP_TIMXCEED 11 /* time exceeded, code: */ -#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ -#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ -#define ICMP_PARAMPROB 12 /* ip header bad */ -#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ -#define ICMP_TSTAMP 13 /* timestamp request */ -#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ -#define ICMP_IREQ 15 /* information request */ -#define ICMP_IREQREPLY 16 /* information reply */ -#define ICMP_MASKREQ 17 /* address mask request */ -#define ICMP_MASKREPLY 18 /* address mask reply */ - -#define ICMP_MAXTYPE 18 - -#define ICMP_INFOTYPE(type) \ - ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ - (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ - (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ - (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ - (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) - -#ifdef _KERNEL -void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *)); -void icmp_input __P((struct mbuf *, ...)); -void icmp_reflect __P((struct mbuf *)); -void icmp_send __P((struct mbuf *, struct mbuf *)); -int icmp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); -#endif - diff --git a/usr.sbin/dhcp/includes/netinet/udp.h b/usr.sbin/dhcp/includes/netinet/udp.h deleted file mode 100644 index 8ad181b390f..00000000000 --- a/usr.sbin/dhcp/includes/netinet/udp.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $NetBSD: udp.h,v 1.1.1.1 1997/03/29 21:52:18 mellon Exp $ */ - -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)udp.h 8.1 (Berkeley) 6/10/93 - */ - -/* - * Udp protocol header. - * Per RFC 768, September, 1981. - */ -struct udphdr { - u_int16_t uh_sport; /* source port */ - u_int16_t uh_dport; /* destination port */ - int16_t uh_ulen; /* udp length */ - u_int16_t uh_sum; /* udp checksum */ -}; diff --git a/usr.sbin/dhcp/includes/osdep.h b/usr.sbin/dhcp/includes/osdep.h index 801eba5223a..ff5fc74ac4c 100644 --- a/usr.sbin/dhcp/includes/osdep.h +++ b/usr.sbin/dhcp/includes/osdep.h @@ -3,7 +3,8 @@ Operating system dependencies... */ /* - * Copyright (c) 1996 The Internet Software Consortium. All rights reserved. + * Copyright (c) 1996, 1997, 1998, 1999 The Internet Software Consortium. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,9 +51,14 @@ !defined (USE_BPF) && \ !defined (USE_BPF_SEND) && \ !defined (USE_BPF_RECEIVE) && \ + !defined (USE_LPF) && \ + !defined (USE_LPF_SEND) && \ + !defined (USE_LPF_RECEIVE) && \ !defined (USE_NIT) && \ !defined (USE_NIT_SEND) && \ - !defined (USE_NIT_RECEIVE) + !defined (USE_NIT_RECEIVE) && \ + !defined (USR_DLPI_SEND) && \ + !defined (USE_DLPI_RECEIVE) # define USE_DEFAULT_NETWORK #endif @@ -69,6 +75,10 @@ # endif #endif +#ifdef aix +# include "cf/aix.h" +#endif + #ifdef bsdi # include "cf/bsdos.h" #endif @@ -101,7 +111,7 @@ # include "cf/sco.h" #endif -#ifdef hpux +#if defined (hpux) || defined (__hpux) # include "cf/hpux.h" #endif @@ -113,8 +123,20 @@ # include "cf/cygwin32.h" #endif -#ifdef NeXT +#ifdef __APPLE__ +# include "cf/rhapsody.h" +#else +# if defined (NeXT) # include "cf/nextstep.h" +# endif +#endif + +#if defined(IRIX) || defined(__sgi) +# include "cf/irix.h" +#endif + +#if !defined (TIME_MAX) +# define TIME_MAX 2147483647 #endif /* Porting:: @@ -138,11 +160,21 @@ # define USE_BPF_RECEIVE #endif +#ifdef USE_LPF +# define USE_LPF_SEND +# define USE_LPF_RECEIVE +#endif + #ifdef USE_NIT # define USE_NIT_SEND # define USE_NIT_RECEIVE #endif +#ifdef USE_DLPI +# define USE_DLPI_SEND +# define USE_DLPI_RECEIVE +#endif + #ifdef USE_UPF # define USE_UPF_SEND # define USE_UPF_RECEIVE @@ -156,7 +188,8 @@ Currently, all low-level packet interfaces use BSD sockets as a fallback. */ -#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || defined (USE_UPF_SEND) +#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \ + defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || defined (USE_LPF_SEND) # define USE_SOCKET_FALLBACK # define USE_FALLBACK #endif @@ -168,7 +201,8 @@ definition for your interface to the list tested below. */ #if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \ - defined (USE_NIT_SEND) || defined (USE_UPF_SEND) + defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \ + defined (USE_DLPI_SEND) || defined (USE_LPF_SEND) # define PACKET_ASSEMBLY #endif @@ -179,10 +213,19 @@ definition for your interface to the list tested below. */ #if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \ - defined (USE_NIT_RECEIVE) || defined (USE_UPF_SEND) + defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \ + defined (USE_DLPI_RECEIVE) || \ + defined (USE_LPF_SEND) || \ + (defined (USE_SOCKET_SEND) && defined (SO_BINDTODEVICE)) # define PACKET_DECODING #endif +/* If we don't have a DLPI packet filter, we have to filter in userland. + Probably not worth doing, actually. */ +#if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD) +# define USERLAND_FILTER +#endif + /* jmp_buf is assumed to be a struct unless otherwise defined in the system header. */ #ifndef jbp_decl @@ -201,3 +244,55 @@ #ifndef BPF_FORMAT # define BPF_FORMAT "/dev/bpf%d" #endif + +#if defined (IFF_POINTOPOINT) && !defined (HAVE_IFF_POINTOPOINT) +# define HAVE_IFF_POINTOPOINT +#endif + +#if defined (AF_LINK) && !defined (HAVE_AF_LINK) +# define HAVE_AF_LINK +#endif + +#if defined (ARPHRD_TUNNEL) && !defined (HAVE_ARPHRD_TUNNEL) +# define HAVE_ARPHRD_TUNNEL +#endif + +#if defined (ARPHRD_LOOPBACK) && !defined (HAVE_ARPHRD_LOOPBACK) +# define HAVE_ARPHRD_LOOPBACK +#endif + +#if defined (ARPHRD_ROSE) && !defined (HAVE_ARPHRD_ROSE) +# define HAVE_ARPHRD_ROSE +#endif + +#if defined (ARPHRD_IEEE802) && !defined (HAVE_ARPHRD_IEEE802) +# define HAVE_ARPHRD_IEEE802 +#endif + +#if defined (ARPHRD_FDDI) && !defined (HAVE_ARPHRD_FDDI) +# define HAVE_ARPHRD_FDDI +#endif + +#if defined (ARPHRD_AX25) && !defined (HAVE_ARPHRD_AX25) +# define HAVE_ARPHRD_AX25 +#endif + +#if defined (ARPHRD_NETROM) && !defined (HAVE_ARPHRD_NETROM) +# define HAVE_ARPHRD_NETROM +#endif + +#if defined (ARPHRD_METRICOM) && !defined (HAVE_ARPHRD_METRICOM) +# define HAVE_ARPHRD_METRICOM +#endif + +#if defined (SO_BINDTODEVICE) && !defined (HAVE_SO_BINDTODEVICE) +# define HAVE_SO_BINDTODEVICE +#endif + +#if defined (SIOCGIFHWADDR) && !defined (HAVE_SIOCGIFHWADDR) +# define HAVE_SIOCGIFHWADDR +#endif + +#if defined (AF_LINK) && !defined (HAVE_AF_LINK) +# define HAVE_AF_LINK +#endif diff --git a/usr.sbin/dhcp/includes/site.h b/usr.sbin/dhcp/includes/site.h index e420661061c..30fdb703005 100644 --- a/usr.sbin/dhcp/includes/site.h +++ b/usr.sbin/dhcp/includes/site.h @@ -78,7 +78,7 @@ /* Define this to use the Berkeley Packet Filter API. The BPF API is available on all 4.4-BSD derivatives, including - OpenBSD, NetBSD, FreeBSD and BSDI's BSD/OS. It's also available on + NetBSD, FreeBSD and BSDI's BSD/OS. It's also available on DEC Alpha OSF/1 in a compatibility mode supported by the Alpha OSF/1 packetfilter interface. */ diff --git a/usr.sbin/dhcp/includes/version.h b/usr.sbin/dhcp/includes/version.h new file mode 100644 index 00000000000..2897e2e2a72 --- /dev/null +++ b/usr.sbin/dhcp/includes/version.h @@ -0,0 +1,3 @@ +/* Current version of ISC DHCP Distribution. */ + +#define DHCP_VERSION "2.0pl5-OpenBSD" diff --git a/usr.sbin/dhcp/relay/dhcrelay.8 b/usr.sbin/dhcp/relay/dhcrelay.8 index 795e0888e3d..ec4f5c74bf4 100644 --- a/usr.sbin/dhcp/relay/dhcrelay.8 +++ b/usr.sbin/dhcp/relay/dhcrelay.8 @@ -37,7 +37,7 @@ .\" Enterprises, see ``http://www.vix.com''. .TH dhcrelay 8 .SH NAME -dhcrelay - Dynamic Host Configuration Protocol (DHCP) Relay Agent +dhcrelay - Dynamic Host Configuration Protocol Relay Agent .SH SYNOPSIS .B dhcrelay [ @@ -66,13 +66,8 @@ dhcrelay - Dynamic Host Configuration Protocol (DHCP) Relay Agent .SH DESCRIPTION The Internet Software Consortium DHCP Relay Agent, dhcrelay, provides a means for relaying DHCP and BOOTP requests from a subnet to which -no DHCP server is directly to one or more DHCP servers on other +no DHCP server is directly connected to one or more DHCP servers on other subnets. -.SH SYSTEM REQUIREMENTS -You must have the Berkeley -Packet Filter (bpf) configured in your kernel. You must have -at least one /dev/bpf* file for each broadcast network interface that -is attached to your system. .SH OPERATION .PP The DHCP Relay Agent listens for DHCP requests on all interfaces @@ -99,7 +94,7 @@ configure may be specified on the command line using the .I -i option. If no interface names are specified on the command line dhcrelay will identify all network -interfaces, eliminating non-broadcast interfaces if possible, and +interfaces, elimininating non-broadcast interfaces if possible, and attempt to configure each interface. .PP If dhcrelay should listen and transmit on a port other than the @@ -107,6 +102,17 @@ standard (port 67), the .B -p flag may used. It should be followed by the udp port number that dhcrelay should use. This is mostly useful for debugging purposes. +If the +.B -p +flag is specified, the relay agent will transmit responses to clients +at a port number that is one greater than the one specified - i.e., if +you specify +.B -p +67, then the relay agent will listen on port 67 and transmit to port +68. Transmissions to servers will be sent to the same port number +that it specified in the +.B -p +flag. .PP Dhcrelay will normally run in the foreground until it has configured an interface, and then will revert to running in the background. diff --git a/usr.sbin/dhcp/relay/dhcrelay.c b/usr.sbin/dhcp/relay/dhcrelay.c index ec53a883d68..6fc4f5011f4 100644 --- a/usr.sbin/dhcp/relay/dhcrelay.c +++ b/usr.sbin/dhcp/relay/dhcrelay.c @@ -3,7 +3,7 @@ DHCP/BOOTP Relay Agent. */ /* - * Copyright (c) 1997 The Internet Software Consortium. + * Copyright (c) 1997, 1998, 1999 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,14 +40,10 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: dhcrelay.c,v 1.2 2001/01/03 16:04:40 ericj Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" +#include "version.h" -static void usage PROTO ((void)); +static void usage PROTO ((char *)); TIME cur_time; TIME default_lease_time = 43200; /* 12 hours... */ @@ -56,9 +52,13 @@ struct tree_cache *global_options [256]; int log_perror = 1; -#ifdef USE_FALLBACK -struct interface_info fallback_interface; -#endif +/* Needed to prevent linking against conflex.c. */ +int lexline; +int lexchar; +char *token_line; +char *tlname; + +char *path_dhcrelay_pid = _PATH_DHCRELAY_PID; u_int16_t local_port; u_int16_t remote_port; @@ -69,6 +69,13 @@ struct server_list { struct sockaddr_in to; } *servers; +static char copyright [] = +"Copyright 1997, 1998, 1999 The Internet Software Consortium."; +static char arr [] = "All rights reserved."; +static char message [] = "Internet Software Consortium DHCP Relay Agent"; +static char contrib [] = "Please contribute if you find this software useful."; +static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html"; + int main (argc, argv, envp) int argc; char **argv, **envp; @@ -78,25 +85,30 @@ int main (argc, argv, envp) struct server_list *sp = (struct server_list *)0; int no_daemon = 0; int quiet = 0; + char *s; + + s = strrchr (argv [0], '/'); + if (!s) + s = argv [0]; + else + s++; -#ifdef SYSLOG_4_2 - openlog ("dhcrelay", LOG_NDELAY); - log_priority = LOG_DAEMON; -#else - openlog ("dhcrelay", LOG_NDELAY, LOG_DAEMON); -#endif + /* Initially, log errors to stderr as well as to syslogd. */ + openlog (s, LOG_NDELAY, DHCPD_LOG_FACILITY); -#if !(defined (DEBUG) || defined (SYSLOG_4_2)) setlogmask (LOG_UPTO (LOG_INFO)); -#endif for (i = 1; i < argc; i++) { if (!strcmp (argv [i], "-p")) { if (++i == argc) - usage (); + usage (s); local_port = htons (atoi (argv [i])); debug ("binding to user-specified port %d", ntohs (local_port)); + } else if (!strcmp (argv [i], "-pf")) { + if (++i == argc) + usage (s); + path_dhcrelay_pid = argv [i]; } else if (!strcmp (argv [i], "-d")) { no_daemon = 1; } else if (!strcmp (argv [i], "-i")) { @@ -107,10 +119,10 @@ int main (argc, argv, envp) error ("Insufficient memory to %s %s", "record interface", argv [i]); if (++i == argc) { - usage (); + usage (s); } memset (tmp, 0, sizeof *tmp); - strlcpy (tmp -> name, argv [i], sizeof(tmp->name)); + strcpy (tmp -> name, argv [i]); tmp -> next = interfaces; tmp -> flags = INTERFACE_REQUESTED; interfaces = tmp; @@ -118,7 +130,7 @@ int main (argc, argv, envp) quiet = 1; quiet_interface_discovery = 1; } else if (argv [i][0] == '-') { - usage (); + usage (s); } else { struct hostent *he; struct in_addr ia, *iap = (struct in_addr *)0; @@ -145,6 +157,17 @@ int main (argc, argv, envp) } } + if (!quiet) { + note ("%s %s", message, DHCP_VERSION); + note (copyright); + note (arr); + note (""); + note (contrib); + note (url); + note (""); + } else + log_perror = 0; + /* Default to the DHCP/BOOTP port. */ if (!local_port) { ent = getservbyname ("dhcps", "udp"); @@ -158,16 +181,14 @@ int main (argc, argv, envp) /* We need at least one server. */ if (!sp) { - usage (); + usage (s); } /* Set up the server sockaddrs. */ for (sp = servers; sp; sp = sp -> next) { sp -> to.sin_port = local_port; sp -> to.sin_family = AF_INET; -#ifdef HAVE_SA_LEN sp -> to.sin_len = sizeof sp -> to; -#endif } /* Get the current time... */ @@ -192,7 +213,21 @@ int main (argc, argv, envp) else if (pid) exit (0); - write_pidfile(_PATH_DHCRELAY_PID, getpid()); + pfdesc = open (path_dhcrelay_pid, + O_CREAT | O_TRUNC | O_WRONLY, 0644); + + if (pfdesc < 0) { + warn ("Can't create %s: %m", path_dhcrelay_pid); + } else { + pf = fdopen (pfdesc, "w"); + if (!pf) + warn ("Can't fdopen %s: %m", + path_dhcrelay_pid); + else { + fprintf (pf, "%ld\n", (long)getpid ()); + fclose (pf); + } + } close (0); close (1); @@ -207,41 +242,42 @@ int main (argc, argv, envp) return 0; } -void relay (ip, packbuf, length, from_port, from, hfrom) +void relay (ip, packet, length, from_port, from, hfrom) struct interface_info *ip; - u_int8_t *packbuf; + struct dhcp_packet *packet; int length; - u_int16_t from_port; + unsigned int from_port; struct iaddr from; struct hardware *hfrom; { - struct dhcp_packet *packet = (struct dhcp_packet *)packbuf; struct server_list *sp; struct sockaddr_in to; struct interface_info *out; struct hardware hto; + if (packet -> hlen > sizeof packet -> chaddr) { + note ("Discarding packet with invalid hlen."); + return; + } + /* If it's a bootreply, forward it to the client. */ if (packet -> op == BOOTREPLY) { -#ifndef USE_FALLBACK - if (!(packet -> flags & htons (BOOTP_BROADCAST))) { + if (!(packet -> flags & htons (BOOTP_BROADCAST)) && + can_unicast_without_arp ()) { to.sin_addr = packet -> yiaddr; to.sin_port = remote_port; - } else -#endif - { + } else { to.sin_addr.s_addr = htonl (INADDR_BROADCAST); to.sin_port = remote_port; } to.sin_family = AF_INET; -#ifdef HAVE_SA_LEN to.sin_len = sizeof to; -#endif - memcpy (hto.haddr, packet -> chaddr, - (packet -> hlen > sizeof hto.haddr - ? sizeof hto.haddr - : packet -> hlen)); + /* Set up the hardware destination address. */ + hto.hlen = packet -> hlen; + if (hto.hlen > sizeof hto.haddr) + hto.hlen = sizeof hto.haddr; + memcpy (hto.haddr, packet -> chaddr, hto.hlen); hto.htype = packet -> htype; /* Find the interface that corresponds to the giaddr @@ -258,12 +294,10 @@ void relay (ip, packbuf, length, from_port, from, hfrom) return; } - if (send_packet (out, - (struct packet *)0, - packet, length, out -> primary_address, - &to, &hto) < 0) - debug ("sendpkt: %m"); - else + if (!send_packet (out, + (struct packet *)0, + packet, length, out -> primary_address, + &to, &hto) < 0) debug ("forwarded BOOTREPLY for %s to %s", print_hw_addr (packet -> htype, packet -> hlen, packet -> chaddr), @@ -288,21 +322,11 @@ void relay (ip, packbuf, length, from_port, from, hfrom) /* Otherwise, it's a BOOTREQUEST, so forward it to all the servers. */ for (sp = servers; sp; sp = sp -> next) { - if ( -#ifdef USE_FALLBACK - send_fallback (&fallback_interface, - (struct packet *)0, - packet, length, ip -> primary_address, - &sp -> to, (struct hardware *)0) -#else - send_packet (interfaces, - (struct packet *)0, - packet, length, ip -> primary_address, - &sp -> to, (struct hardware *)0) -#endif - < 0) { - debug ("send_packet: %m"); - } else { + if (!send_packet ((fallback_interface + ? fallback_interface : interfaces), + (struct packet *)0, + packet, length, ip -> primary_address, + &sp -> to, (struct hardware *)0) < 0) { debug ("forwarded BOOTREQUEST for %s to %s", print_hw_addr (packet -> htype, packet -> hlen, packet -> chaddr), @@ -312,9 +336,19 @@ void relay (ip, packbuf, length, from_port, from, hfrom) } -static void usage () +static void usage (appname) + char *appname; { - error ("Usage: dhcrelay [-c] [-p ] [server1 [... serverN]]"); + note (message); + note (copyright); + note (arr); + note (""); + note (contrib); + note (url); + note (""); + + warn ("Usage: %s [-i] [-d] [-i if0] [...-i ifN] [-p ]", appname); + error (" [-pf pidfilename] [server1 [... serverN]]"); } void cleanup () diff --git a/usr.sbin/dhcp/server/bootp.c b/usr.sbin/dhcp/server/bootp.c index 9694f6a15e3..a5e636b7c2c 100644 --- a/usr.sbin/dhcp/server/bootp.c +++ b/usr.sbin/dhcp/server/bootp.c @@ -3,7 +3,7 @@ BOOTP Protocol support. */ /* - * Copyright (c) 1995, 1996 The Internet Software Consortium. + * Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: bootp.c,v 1.1 1998/08/18 03:43:34 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" void bootp (packet) @@ -67,13 +62,14 @@ void bootp (packet) if (packet -> raw -> op != BOOTREQUEST) return; - note ("BOOTREQUEST from %s via %s", + note ("BOOTREQUEST from %s via %s%s", print_hw_addr (packet -> raw -> htype, packet -> raw -> hlen, packet -> raw -> chaddr), packet -> raw -> giaddr.s_addr ? inet_ntoa (packet -> raw -> giaddr) - : packet -> interface -> name); + : packet -> interface -> name, + packet -> options_valid ? "" : " (non-rfc1048)"); @@ -110,13 +106,21 @@ void bootp (packet) if (host && (!host -> group -> allow_booting)) { note ("Ignoring excluded BOOTP client %s", - host -> name); + host -> name + ? host -> name + : print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr)); return; } if (host && (!host -> group -> allow_bootp)) { note ("Ignoring BOOTP request from client %s", - host -> name); + host -> name + ? host -> name + : print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr)); return; } @@ -224,11 +228,15 @@ void bootp (packet) /* If we didn't get a known vendor magic number on the way in, just copy the input options to the output. */ - if (!packet -> options_valid) { + if (!packet -> options_valid && + !subnet -> group -> always_reply_rfc1048 && + (!hp || !hp -> group -> always_reply_rfc1048)) { memcpy (outgoing.raw -> options, packet -> raw -> options, DHCP_OPTION_LEN); outgoing.packet_length = BOOTP_MIN_LEN; } else { + struct tree_cache netmask_tree; /* -- RBF */ + /* Come up with a list of options that we want to send to this client. Start with the per-subnet options, and then override those with client-specific @@ -241,12 +249,25 @@ void bootp (packet) options [i] = hp -> group -> options [i]; } + /* Use the subnet mask from the subnet declaration if no other + mask has been provided. */ + if (!options [DHO_SUBNET_MASK]) { + options [DHO_SUBNET_MASK] = &netmask_tree; + netmask_tree.flags = TC_TEMPORARY; + netmask_tree.value = lease -> subnet -> netmask.iabuf; + netmask_tree.len = lease -> subnet -> netmask.len; + netmask_tree.buf_size = lease -> subnet -> netmask.len; + netmask_tree.timeout = 0xFFFFFFFF; + netmask_tree.tree = (struct tree *)0; + } + /* Pack the options into the buffer. Unlike DHCP, we can't pack options into the filename and server name buffers. */ outgoing.packet_length = - cons_options (packet, outgoing.raw, options, 0, 0, 1); + cons_options (packet, outgoing.raw, + 0, options, 0, 0, 1, (u_int8_t *)0, 0); if (outgoing.packet_length < BOOTP_MIN_LEN) outgoing.packet_length = BOOTP_MIN_LEN; } @@ -255,13 +276,11 @@ void bootp (packet) raw.op = BOOTREPLY; raw.htype = packet -> raw -> htype; raw.hlen = packet -> raw -> hlen; - memcpy (raw.chaddr, packet -> raw -> chaddr, raw.hlen); - memset (&raw.chaddr [raw.hlen], 0, - (sizeof raw.chaddr) - raw.hlen); + memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr); raw.hops = packet -> raw -> hops; raw.xid = packet -> raw -> xid; raw.secs = packet -> raw -> secs; - raw.flags = 0; + raw.flags = packet -> raw -> flags; raw.ciaddr = packet -> raw -> ciaddr; memcpy (&raw.yiaddr, ip_address.iabuf, sizeof raw.yiaddr); @@ -276,22 +295,21 @@ void bootp (packet) raw.siaddr = packet -> interface -> primary_address; raw.giaddr = packet -> raw -> giaddr; - if (hp -> group -> server_name) { + if (hp -> group -> server_name) strncpy (raw.sname, hp -> group -> server_name, - (sizeof raw.sname) - 1); - raw.sname [(sizeof raw.sname) - 1] = 0; - } + (sizeof raw.sname)); + else if (subnet -> group -> server_name) + strncpy (raw.sname, subnet -> group -> server_name, + (sizeof raw.sname)); - /* If the client requested a specific boot file, echo it - back per RFC951; some clients are unable to boot properly - without this (e.g. DECstations). */ - if (packet -> raw -> file[0] != '\0') - memcpy (raw.file, packet -> raw -> file, sizeof raw.file); - else if (hp -> group -> filename) { + if (hp -> group -> filename) strncpy (raw.file, hp -> group -> filename, - (sizeof raw.file) - 1); - raw.file [(sizeof raw.file) - 1] = 0; - } + (sizeof raw.file)); + else if (subnet -> group -> filename) + strncpy (raw.file, subnet -> group -> filename, + (sizeof raw.file)); + else + memcpy (raw.file, packet -> raw -> file, sizeof raw.file); /* Set up the hardware destination address... */ hto.htype = packet -> raw -> htype; @@ -322,15 +340,23 @@ void bootp (packet) to.sin_addr = raw.giaddr; to.sin_port = local_port; -#ifdef USE_FALLBACK - result = send_fallback (&fallback_interface, - (struct packet *)0, - &raw, outgoing.packet_length, - from, &to, &hto); - if (result < 0) - warn ("send_fallback: %m"); - return; -#endif + if (fallback_interface) { + result = send_packet (fallback_interface, + (struct packet *)0, + &raw, outgoing.packet_length, + from, &to, &hto); + return; + } + + /* If it comes from a client that already knows its address + and is not requesting a broadcast response, and we can + unicast to a client without using the ARP protocol, sent it + directly to that client. */ + } else if (!(raw.flags & htons (BOOTP_BROADCAST)) && + can_unicast_without_arp ()) { + to.sin_addr = raw.yiaddr; + to.sin_port = remote_port; + /* Otherwise, broadcast it on the local network. */ } else { to.sin_addr.s_addr = INADDR_BROADCAST; @@ -341,6 +367,4 @@ void bootp (packet) result = send_packet (packet -> interface, packet, &raw, outgoing.packet_length, from, &to, &hto); - if (result < 0) - warn ("send_packet: %m"); } diff --git a/usr.sbin/dhcp/server/confpars.c b/usr.sbin/dhcp/server/confpars.c index 14cd539949a..93fdf19d54d 100644 --- a/usr.sbin/dhcp/server/confpars.c +++ b/usr.sbin/dhcp/server/confpars.c @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: confpars.c,v 1.2 2000/11/10 15:33:14 provos Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include "dhctoken.h" @@ -73,9 +68,12 @@ int readconf () root_group.boot_unknown_clients = 1; root_group.allow_bootp = 1; root_group.allow_booting = 1; + root_group.authoritative = 1; - if ((cfile = fopen (path_dhcpd_conf, "r")) == NULL) + if ((cfile = fopen (path_dhcpd_conf, "r")) == NULL) { error ("Can't open %s: %m", path_dhcpd_conf); + } + do { token = peek_token (&val, cfile); if (token == EOF) @@ -112,10 +110,13 @@ void read_leases () human has corrected the database problem, then we are left thinking that no leases have been assigned to anybody, which could create severe network chaos. */ - if ((cfile = fopen (path_dhcpd_db, "r")) == NULL) - error ("Can't open lease database %s: %m -- %s", - path_dhcpd_db, - "check for failed database rewrite attempt!"); + if ((cfile = fopen (path_dhcpd_db, "r")) == NULL) { + warn ("Can't open lease database %s: %m -- %s", + path_dhcpd_db, + "check for failed database rewrite attempt!"); + warn ("Please read the dhcpd.leases manual page if you."); + error ("don't know what to do about this."); } + do { token = next_token (&val, cfile); if (token == EOF) @@ -155,6 +156,7 @@ void read_leases () | fixed-address-parameter | ALLOW allow-deny-keyword | DENY allow-deny-keyword + | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean declaration :== host-declaration | group-declaration @@ -239,16 +241,24 @@ int parse_statement (cfile, group, type, host_decl, declaration) share -> group -> shared_network = share; parse_subnet_declaration (cfile, share); + + /* share -> subnets is the subnet we just parsed. */ if (share -> subnets) { share -> interface = share -> subnets -> interface; + /* Make the shared network name from network number. */ n = piaddr (share -> subnets -> net); t = malloc (strlen (n) + 1); if (!t) error ("no memory for subnet name"); - strcpy (t, n); + strlcpy (t, n, (strlen(n) + 1)); share -> name = t; + + /* Copy the authoritative parameter from the subnet, + since there is no opportunity to declare it here. */ + share -> group -> authoritative = + share -> subnets -> group -> authoritative; enter_shared_network (share); } return 1; @@ -295,12 +305,44 @@ int parse_statement (cfile, group, type, host_decl, declaration) group -> get_lease_hostnames = parse_boolean (cfile); break; + case ALWAYS_REPLY_RFC1048: + group -> always_reply_rfc1048 = parse_boolean (cfile); + break; + case USE_HOST_DECL_NAMES: if (type == HOST_DECL) parse_warn ("use-host-decl-names not allowed here."); group -> use_host_decl_names = parse_boolean (cfile); break; + case USE_LEASE_ADDR_FOR_DEFAULT_ROUTE: + group -> use_lease_addr_for_default_route = + parse_boolean (cfile); + break; + + case TOKEN_NOT: + token = next_token (&val, cfile); + switch (token) { + case AUTHORITATIVE: + if (type == HOST_DECL) + parse_warn ("authority makes no sense here."); + group -> authoritative = 0; + parse_semi (cfile); + break; + default: + parse_warn ("expecting assertion"); + skip_to_semi (cfile); + break; + } + break; + + case AUTHORITATIVE: + if (type == HOST_DECL) + parse_warn ("authority makes no sense here."); + group -> authoritative = 1; + parse_semi (cfile); + break; + case NEXT_SERVER: tree = parse_ip_addr_or_hostname (cfile, 0); if (!tree) @@ -319,17 +361,11 @@ int parse_statement (cfile, group, type, host_decl, declaration) break; case SERVER_IDENTIFIER: - if (type != ROOT_GROUP) - parse_warn ("server-identifier only allowed at top %s", - "level."); tree = parse_ip_addr_or_hostname (cfile, 0); if (!tree) return declaration; - cache = tree_cache (tree); - if (type == ROOT_GROUP) { - if (!tree_evaluate (cache)) - error ("server-identifier is not known"); - } + group -> options [DHO_DHCP_SERVER_IDENTIFIER] = + tree_cache (tree); token = next_token (&val, cfile); break; @@ -621,7 +657,7 @@ void parse_shared_net_declaration (cfile, group) name = malloc (strlen (val) + 1); if (!name) error ("no memory for shared network name"); - strcpy (name, val); + strlcpy (name, val, strlen(val) + 1); } else { name = parse_host_name (cfile); if (!name) @@ -664,7 +700,7 @@ void parse_subnet_declaration (cfile, share) { char *val; int token; - struct subnet *subnet, *t; + struct subnet *subnet, *t, *u; struct iaddr iaddr; unsigned char addr [4]; int len = sizeof addr; @@ -731,10 +767,19 @@ void parse_subnet_declaration (cfile, share) if (!share -> subnets) share -> subnets = subnet; else { - for (t = share -> subnets; - t -> next_sibling; t = t -> next_sibling) - ; - t -> next_sibling = subnet; + u = (struct subnet *)0; + for (t = share -> subnets; t; t = t -> next_sibling) { + if (subnet_inner_than (subnet, t, 0)) { + if (u) + u -> next_sibling = subnet; + else + share -> subnets = subnet; + subnet -> next_sibling = t; + return; + } + u = t; + } + u -> next_sibling = subnet; } } @@ -873,7 +918,7 @@ void parse_option_param (cfile, group) vendor = malloc (strlen (val) + 1); if (!vendor) error ("no memory for vendor token."); - strcpy (vendor, val); + strlcpy (vendor, val, strlen(val) + 1); token = peek_token (&val, cfile); if (token == DOT) { /* Go ahead and take the DOT token... */ @@ -890,8 +935,9 @@ void parse_option_param (cfile, group) /* Look up the option name hash table for the specified vendor. */ - universe = (struct universe *)hash_lookup (&universe_hash, - vendor, 0); + universe = ((struct universe *) + hash_lookup (&universe_hash, + (unsigned char *)vendor, 0)); /* If it's not there, we can't parse the rest of the declaration. */ if (!universe) { @@ -907,7 +953,8 @@ void parse_option_param (cfile, group) } /* Look up the actual option info... */ - option = (struct option *)hash_lookup (universe -> hash, val, 0); + option = (struct option *)hash_lookup (universe -> hash, + (unsigned char *)val, 0); /* If we didn't get an option structure, it's an undefined option. */ if (!option) { @@ -958,7 +1005,8 @@ void parse_option_param (cfile, group) token = next_token (&val, cfile); tree = tree_concat (tree, - tree_const (val, + tree_const ((unsigned char *) + val, strlen (val))); } else { parse_warn ("expecting string %s.", @@ -977,9 +1025,10 @@ void parse_option_param (cfile, group) skip_to_semi (cfile); return; } - tree = tree_concat (tree, - tree_const (val, - strlen (val))); + tree = tree_concat + (tree, + tree_const ((unsigned char *)val, + strlen (val))); break; case 'I': /* IP address or hostname. */ @@ -1158,13 +1207,13 @@ struct lease *parse_lease_declaration (cfile) } } else { switch (token) { - /* Colon-separated hexadecimal octets... */ + /* Colon-seperated hexadecimal octets... */ case UID: seenbit = 8; token = peek_token (&val, cfile); if (token == STRING) { token = next_token (&val, cfile); - lease.uid_len = strlen (val) + 1; + lease.uid_len = strlen (val); lease.uid = (unsigned char *) malloc (lease.uid_len); if (!lease.uid) { @@ -1172,6 +1221,7 @@ struct lease *parse_lease_declaration (cfile) return (struct lease *)0; } memcpy (lease.uid, val, lease.uid_len); + parse_semi (cfile); } else { lease.uid_len = 0; lease.uid = parse_numeric_aggregate diff --git a/usr.sbin/dhcp/server/db.c b/usr.sbin/dhcp/server/db.c index 538adc39c43..ae39a2ec24e 100644 --- a/usr.sbin/dhcp/server/db.c +++ b/usr.sbin/dhcp/server/db.c @@ -40,11 +40,6 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: db.c,v 1.1 1998/08/18 03:43:34 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" FILE *db_file; @@ -61,6 +56,7 @@ int write_lease (lease) struct tm *t; char tbuf [64]; int errors = 0; + int i; if (counting) ++count; @@ -71,7 +67,7 @@ int write_lease (lease) } t = gmtime (&lease -> starts); - sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", + snprintf (tbuf, sizeof tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", t -> tm_wday, t -> tm_year + 1900, t -> tm_mon + 1, t -> tm_mday, t -> tm_hour, t -> tm_min, t -> tm_sec); @@ -82,7 +78,7 @@ int write_lease (lease) } t = gmtime (&lease -> ends); - sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", + snprintf (tbuf, sizeof tbuf,"%d %d/%02d/%02d %02d:%02d:%02d;", t -> tm_wday, t -> tm_year + 1900, t -> tm_mon + 1, t -> tm_mday, t -> tm_hour, t -> tm_min, t -> tm_sec); @@ -134,6 +130,10 @@ int write_lease (lease) } } if (lease -> client_hostname) { + for (i = 0; lease -> client_hostname [i]; i++) + if (lease -> client_hostname [i] < 33 || + lease -> client_hostname [i] > 126) + goto bad_client_hostname; errno = 0; fprintf (db_file, "\n\tclient-hostname \"%s\";", lease -> client_hostname); @@ -141,7 +141,13 @@ int write_lease (lease) ++errors; } } + bad_client_hostname: if (lease -> hostname) { + for (i = 0; lease -> hostname [i]; i++) + if (lease -> hostname [i] < 33 || + lease -> hostname [i] > 126) + goto bad_hostname; + errno = 0; errno = 0; fprintf (db_file, "\n\thostname \"%s\";", lease -> hostname); @@ -149,6 +155,7 @@ int write_lease (lease) ++errors; } } + bad_hostname: errno = 0; fputs ("\n}\n", db_file); if (errno) { @@ -171,7 +178,7 @@ int commit_leases () note ("commit_leases: unable to commit: %m"); return 0; } - if (fsync (fileno (db_file)) < 0) { + if (fsync (fileno (db_file)) == -1) { note ("commit_leases: unable to commit: %m"); return 0; } @@ -198,8 +205,8 @@ void db_startup () void new_lease_file () { - char newfname [512]; - char backfname [512]; + char newfname [MAXPATHLEN]; + char backfname [MAXPATHLEN]; TIME t; int db_fd; @@ -210,30 +217,37 @@ void new_lease_file () /* Make a temporary lease file... */ GET_TIME (&t); - sprintf (newfname, "%s.%d", path_dhcpd_db, (int)t); + snprintf (newfname, sizeof newfname,"%s.%d", path_dhcpd_db, (int)t); db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664); - if (db_fd < 0) { + if (db_fd == -1) { error ("Can't create new lease file: %m"); } if ((db_file = fdopen (db_fd, "w")) == NULL) { error ("Can't fdopen new lease file!"); } + /* Write an introduction so people don't complain about time + being off. */ + fprintf (db_file, "# All times in this file are in UTC (GMT), not %s", + "your local timezone.\n"); + fprintf (db_file, "# The format of this file is documented in the %s", + "dhcpd.leases(5) manual page.\n\n"); + /* Write out all the leases that we know of... */ counting = 0; write_leases (); /* Get the old database out of the way... */ - sprintf (backfname, "%s~", path_dhcpd_db); - if (unlink (backfname) < 0 && errno != ENOENT) + snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db); + if (unlink (backfname) == -1 && errno != ENOENT) error ("Can't remove old lease database backup %s: %m", backfname); - if (link (path_dhcpd_db, backfname) < 0) + if (link (path_dhcpd_db, backfname) == -1) error ("Can't backup lease database %s to %s: %m", path_dhcpd_db, backfname); /* Move in the new file... */ - if (rename (newfname, path_dhcpd_db) < 0) + if (rename (newfname, path_dhcpd_db) == -1) error ("Can't install new lease database %s to %s: %m", newfname, path_dhcpd_db); diff --git a/usr.sbin/dhcp/server/dhcp.c b/usr.sbin/dhcp/server/dhcp.c index 6dc9f5e185a..5e36623fe4b 100644 --- a/usr.sbin/dhcp/server/dhcp.c +++ b/usr.sbin/dhcp/server/dhcp.c @@ -3,8 +3,8 @@ DHCP Protocol engine. */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,16 +40,11 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: dhcp.c,v 1.5 2001/04/25 11:40:11 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" int outstanding_pings; -static unsigned char dhcp_message [256]; +static char dhcp_message [256]; void dhcp (packet) struct packet *packet; @@ -119,10 +114,26 @@ void dhcpdiscover (packet) /* If we find an abandoned lease, take it, but print a warning message, so that if it continues to lose, the administrator will eventually investigate. */ - if (lease -> flags & ABANDONED_LEASE) { - warn ("Reclaiming abandoned IP address %s.\n", - piaddr (lease -> ip_addr)); - lease -> flags &= ~ABANDONED_LEASE; + if ((lease -> flags & ABANDONED_LEASE)) { + struct lease *lp; + + /* See if we can find an unabandoned lease first. */ + for (lp = lease; lp; lp = lp -> prev) { + if (lp -> ends > cur_time) + break; + if (!(lp -> flags & ABANDONED_LEASE)) { + lease = lp; + break; + } + } + + /* If we can't find an unabandoned lease, reclaim the + abandoned lease. */ + if ((lease -> flags & ABANDONED_LEASE)) { + warn ("Reclaiming abandoned IP address %s.", + piaddr (lease -> ip_addr)); + lease -> flags &= ~ABANDONED_LEASE; + } } /* Try to find a host_decl that matches the client @@ -162,7 +173,11 @@ void dhcpdiscover (packet) } else if (lease -> host && !lease -> host -> group -> allow_booting) { note ("Declining to boot client %s", - lease -> host -> name); + lease -> host -> name + ? lease -> host -> name + : print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr)); } else ack_lease (packet, lease, DHCPOFFER, cur_time + 120); } @@ -248,13 +263,16 @@ void dhcprequest (packet) if (!packet -> shared_network || (packet -> raw -> ciaddr.s_addr && packet -> raw -> giaddr.s_addr) || - packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) { + (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len && + !packet -> raw -> ciaddr.s_addr)) { /* If we don't know where it came from but we do know where it claims to have come from, it didn't come from there. Fry it. */ if (!packet -> shared_network) { - if (subnet) { + if (subnet && + subnet -> shared_network -> group -> authoritative) + { nak_lease (packet, &cip); return; } @@ -266,7 +284,8 @@ void dhcprequest (packet) address that is not on that shared network, nak it. */ subnet = find_grouped_subnet (packet -> shared_network, cip); if (!subnet) { - nak_lease (packet, &cip); + if (packet -> shared_network -> group -> authoritative) + nak_lease (packet, &cip); return; } } @@ -277,7 +296,7 @@ void dhcprequest (packet) if (lease && !addr_eq (lease -> ip_addr, cip)) { /* If we found the address the client asked for, but it wasn't what got picked, the lease belongs to us, - so we can tenuously justify NAKing it. */ + so we should NAK it. */ if (ours) nak_lease (packet, &cip); return; @@ -290,6 +309,26 @@ void dhcprequest (packet) return; } + /* If we're not allowed to serve this client anymore, don't. */ + if (lease && + !lease -> host && + !lease -> subnet -> group -> boot_unknown_clients) { + note ("Ignoring unknown client %s", + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr)); + return; + } else if (lease && lease -> host && + !lease -> host -> group -> allow_booting) { + note ("Declining to renew client %s", + lease -> host -> name + ? lease -> host -> name + : print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr)); + return; + } + /* If we own the lease that the client is asking for, and it's already been assigned to the client, ack it. */ if (lease && @@ -306,6 +345,16 @@ void dhcprequest (packet) ack_lease (packet, lease, DHCPACK, 0); return; } + + /* At this point, the client has requested a lease, and it's + available, but it wasn't assigned to the client, which + means that the client probably hasn't gone through the + DHCPDISCOVER part of the protocol. We are within our + rights to send a DHCPNAK. We can also send a DHCPACK. + The thing we probably should not do is to remain silent. + For now, we'll just assign the lease to the client anyway. */ + if (lease) + ack_lease (packet, lease, DHCPACK, 0); } void dhcprelease (packet) @@ -329,63 +378,78 @@ void dhcprelease (packet) if (packet -> options [i].len) { lease = find_lease_by_uid (packet -> options [i].data, packet -> options [i].len); - } else - lease = (struct lease *)0; - /* The client is supposed to pass a valid client-identifier, - but the spec on this has changed historically, so try the - IP address in ciaddr if the client-identifier fails. */ - if (!lease) { + /* See if we can find a lease that matches the IP address + the client is claiming. */ + for (; lease; lease = lease -> n_uid) { + if (!memcmp (&packet -> raw -> ciaddr, + lease -> ip_addr.iabuf, 4)) { + break; + } + } + } else { + /* The client is supposed to pass a valid client-identifier, + but the spec on this has changed historically, so try the + IP address in ciaddr if the client-identifier fails. */ cip.len = 4; memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4); lease = find_lease_by_ip_addr (cip); } + note ("DHCPRELEASE of %s from %s via %s (%sfound)", + inet_ntoa (packet -> raw -> ciaddr), + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr), + packet -> raw -> giaddr.s_addr + ? inet_ntoa (packet -> raw -> giaddr) + : packet -> interface -> name, + lease ? "" : "not "); /* If we found a lease, release it. */ - if (lease) { - /* first, we ping this lease to see if it's still + if (lease && lease -> ends > cur_time) { + /* first, we ping this lease to see if it's still * there. if it is, we don't release it. * this avoids the problem of spoofed releases * being used to liberate addresses from the * server. */ - if (! lease->releasing) { - note ("DHCPRELEASE of %s from %s via %s (found)", - inet_ntoa (packet -> raw -> ciaddr), - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr), - packet -> raw -> giaddr.s_addr - ? inet_ntoa (packet -> raw -> giaddr) - : packet -> interface -> name, - lease ? "" : "not "); - - lease->releasing = 1; - add_timeout (cur_time + 1, lease_ping_timeout, lease); - icmp_echorequest (&(lease -> ip_addr)); - ++outstanding_pings; - } - else { - note ("DHCPRELEASE of %s from %s via %s ignored (release already pending)", - inet_ntoa (packet -> raw -> ciaddr), - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr), - packet -> raw -> giaddr.s_addr - ? inet_ntoa (packet -> raw -> giaddr) - : packet -> interface -> name); - } + if (! lease->releasing) { + note ("DHCPRELEASE of %s from %s via %s (found)", + inet_ntoa (packet -> raw -> ciaddr), + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr), + packet -> raw -> giaddr.s_addr + ? inet_ntoa (packet -> raw -> giaddr) + : packet -> interface -> name, + lease ? "" : "not "); + + lease->releasing = 1; + add_timeout (cur_time + 1, lease_ping_timeout, lease); + icmp_echorequest (&(lease -> ip_addr)); + ++outstanding_pings; + } + else { + note ("DHCPRELEASE of %s from %s via %s ignored (release already pending)", + inet_ntoa (packet -> raw -> ciaddr), + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr), + packet -> raw -> giaddr.s_addr + ? inet_ntoa (packet -> raw -> giaddr) + : packet -> interface -> name); + } } else { - note ("DHCPRELEASE of %s from %s via %s for nonexistent lease", - inet_ntoa (packet -> raw -> ciaddr), - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr), - packet -> raw -> giaddr.s_addr - ? inet_ntoa (packet -> raw -> giaddr) - : packet -> interface -> name); + note ("DHCPRELEASE of %s from %s via %s for nonexistent lease", + inet_ntoa (packet -> raw -> ciaddr), + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr), + packet -> raw -> giaddr.s_addr + ? inet_ntoa (packet -> raw -> giaddr) + : packet -> interface -> name); } } @@ -438,6 +502,7 @@ void nak_lease (packet, cip) unsigned char nak = DHCPNAK; struct packet outgoing; struct hardware hto; + int i; struct tree_cache *options [256]; struct tree_cache dhcpnak_tree; @@ -458,20 +523,24 @@ void nak_lease (packet, cip) /* Set DHCP_MESSAGE to whatever the message is */ options [DHO_DHCP_MESSAGE] = &dhcpmsg_tree; - options [DHO_DHCP_MESSAGE] -> value = dhcp_message; - options [DHO_DHCP_MESSAGE] -> len = strlen (dhcp_message); - options [DHO_DHCP_MESSAGE] -> buf_size = strlen (dhcp_message); + options [DHO_DHCP_MESSAGE] -> value = (unsigned char *)dhcp_message; + options [DHO_DHCP_MESSAGE] -> len = + options [DHO_DHCP_MESSAGE] -> buf_size = strlen (dhcp_message); options [DHO_DHCP_MESSAGE] -> timeout = 0xFFFFFFFF; options [DHO_DHCP_MESSAGE] -> tree = (struct tree *)0; /* Do not use the client's requested parameter list. */ - packet -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].len = 0; - packet -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data = - (unsigned char *)0; + i = DHO_DHCP_PARAMETER_REQUEST_LIST; + if (packet -> options [i].data) { + packet -> options [i].len = 0; + dfree (packet -> options [i].data, "nak_lease"); + packet -> options [i].data = (unsigned char *)0; + } /* Set up the option buffer... */ outgoing.packet_length = - cons_options (packet, outgoing.raw, options, 0, 0, 0); + cons_options (packet, outgoing.raw, 0, options, 0, 0, 0, + (u_int8_t *)0, 0); /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ raw.siaddr = packet -> interface -> primary_address; @@ -511,9 +580,8 @@ void nak_lease (packet, cip) /* Set up the common stuff... */ to.sin_family = AF_INET; -#ifdef HAVE_SA_LEN to.sin_len = sizeof to; -#endif + memset (to.sin_zero, 0, sizeof to.sin_zero); from = packet -> interface -> primary_address; @@ -528,14 +596,15 @@ void nak_lease (packet, cip) to.sin_addr = raw.giaddr; to.sin_port = local_port; -#ifdef USE_FALLBACK - result = send_fallback (&fallback_interface, - packet, &raw, outgoing.packet_length, - from, &to, &hto); - if (result < 0) - warn ("send_fallback: %m"); - return; -#endif + if (fallback_interface) { + result = send_packet (fallback_interface, + packet, &raw, + outgoing.packet_length, + from, &to, &hto); + if (result == -1) + warn ("send_fallback: %m"); + return; + } } else { to.sin_addr.s_addr = htonl (INADDR_BROADCAST); to.sin_port = remote_port; @@ -545,20 +614,21 @@ void nak_lease (packet, cip) result = send_packet (packet -> interface, packet, &raw, outgoing.packet_length, from, &to, (struct hardware *)0); - if (result < 0) - warn ("send_packet: %m"); } void ack_lease (packet, lease, offer, when) struct packet *packet; struct lease *lease; - unsigned char offer; + unsigned int offer; TIME when; { struct lease lt; struct lease_state *state; TIME lease_time; TIME offered_lease_time; + TIME max_lease_time; + TIME default_lease_time; + int ulafdr; struct class *vendor_class, *user_class; int i; @@ -613,6 +683,12 @@ void ack_lease (packet, lease, offer, when) if (!state) error ("unable to allocate lease state!"); memset (state, 0, sizeof *state); + state -> got_requested_address = packet -> got_requested_address; + state -> shared_network = packet -> interface -> shared_network; + + /* Remember if we got a server identifier option. */ + if (packet -> options [DHO_DHCP_SERVER_IDENTIFIER].len) + state -> got_server_identifier = 1; /* Replace the old lease hostname with the new one, if it's changed. */ if (packet -> options [DHO_HOST_NAME].len && @@ -642,12 +718,23 @@ void ack_lease (packet, lease, offer, when) /* Choose a filename; first from the host_decl, if any, then from the user class, then from the vendor class. */ if (lease -> host && lease -> host -> group -> filename) - state -> filename = lease -> host -> group -> filename; + strlcpy (state -> filename, lease -> host -> group -> filename, + sizeof state -> filename); else if (user_class && user_class -> group -> filename) - state -> filename = user_class -> group -> filename; + strlcpy (state -> filename, user_class -> group -> filename, + sizeof state -> filename); else if (vendor_class && vendor_class -> group -> filename) - state -> filename = vendor_class -> group -> filename; - else state -> filename = (char *)0; + strlcpy (state -> filename, vendor_class -> group -> filename, + sizeof state -> filename); + else if (packet -> raw -> file [0]) + strlcpy (state -> filename, packet -> raw -> file, + sizeof state -> filename); + else if (lease -> subnet -> group -> filename) + strlcpy (state -> filename, + lease -> subnet -> group -> filename, + sizeof state -> filename); + else + strlcpy (state -> filename, "", sizeof state -> filename); /* Choose a server name as above. */ if (lease -> host && lease -> host -> group -> server_name) @@ -656,6 +743,9 @@ void ack_lease (packet, lease, offer, when) state -> server_name = user_class -> group -> server_name; else if (vendor_class && vendor_class -> group -> server_name) state -> server_name = vendor_class -> group -> server_name; + else if (lease -> subnet -> group -> server_name) + state -> server_name = + lease -> subnet -> group -> server_name; else state -> server_name = (char *)0; /* At this point, we have a lease that we can offer the client. @@ -671,6 +761,22 @@ void ack_lease (packet, lease, offer, when) /* Start now. */ lt.starts = cur_time; + /* Figure out maximum lease time. */ + if (lease -> host && + lease -> host -> group -> max_lease_time) + max_lease_time = lease -> host -> group -> max_lease_time; + else + max_lease_time = lease -> subnet -> group -> max_lease_time; + + /* Figure out default lease time. */ + if (lease -> host + && lease -> host -> group -> default_lease_time) + default_lease_time = + lease -> host -> group -> default_lease_time; + else + default_lease_time = + lease -> subnet -> group -> default_lease_time; + /* Figure out how long a lease to assign. If this is a dynamic BOOTP lease, its duration must be infinite. */ if (offer) { @@ -680,27 +786,10 @@ void ack_lease (packet, lease, offer, when) /* Don't let the client ask for a longer lease than is supported for this subnet or host. */ - if (lease -> host && - lease -> host -> group -> max_lease_time) { - if (lease_time > - lease -> host -> group -> max_lease_time) - lease_time = (lease -> host -> - group -> max_lease_time); - } else { - if (lease_time > - lease -> subnet -> group -> max_lease_time) - lease_time = (lease -> subnet -> - group -> max_lease_time); - } - } else { - if (lease -> host - && lease -> host -> group -> default_lease_time) - lease_time = (lease -> host -> - group -> default_lease_time); - else - lease_time = (lease -> subnet -> - group -> default_lease_time); - } + if (lease_time > max_lease_time) + lease_time = max_lease_time; + } else + lease_time = default_lease_time; state -> offered_expiry = cur_time + lease_time; if (when) @@ -727,8 +816,6 @@ void ack_lease (packet, lease, offer, when) lt.flags = BOOTP_LEASE; } - lt.timestamp = cur_time; - /* Record the uid, if given... */ i = DHO_DHCP_CLIENT_IDENTIFIER; if (packet -> options [i].len) { @@ -759,13 +846,13 @@ void ack_lease (packet, lease, offer, when) lease -> hardware_addr.hlen = packet -> raw -> hlen; lease -> hardware_addr.htype = packet -> raw -> htype; memcpy (lease -> hardware_addr.haddr, packet -> raw -> chaddr, - packet -> raw -> hlen); + sizeof packet -> raw -> chaddr); /* XXX */ } else { /* Record the hardware address, if given... */ lt.hardware_addr.hlen = packet -> raw -> hlen; lt.hardware_addr.htype = packet -> raw -> htype; memcpy (lt.hardware_addr.haddr, packet -> raw -> chaddr, - packet -> raw -> hlen); + sizeof packet -> raw -> chaddr); /* Install the new information about this lease in the database. If this is a DHCPACK or a dynamic BOOTREPLY @@ -838,6 +925,33 @@ void ack_lease (packet, lease, offer, when) group -> options [i]); } + /* Get the Maximum Message Size option from the packet, if one + was sent. */ + i = DHO_DHCP_MAX_MESSAGE_SIZE; + if (packet -> options [i].data && + (packet -> options [i].len == sizeof (u_int16_t))) + state -> max_message_size = + getUShort (packet -> options [i].data); + /* Otherwise, if a maximum message size was specified, use that. */ + else if (state -> options [i] && state -> options [i] -> value) + state -> max_message_size = + getUShort (state -> options [i] -> value); + + /* Save the parameter request list if there is one. */ + i = DHO_DHCP_PARAMETER_REQUEST_LIST; + if (packet -> options [i].data) { + state -> prl = dmalloc (packet -> options [i].len, + "ack_lease: prl"); + if (!state -> prl) + warn ("no memory for parameter request list"); + else { + memcpy (state -> prl, + packet -> options [i].data, + packet -> options [i].len); + state -> prl_len = packet -> options [i].len; + } + } + /* If we didn't get a hostname from an option somewhere, see if we can get one from the lease. */ i = DHO_HOST_NAME; @@ -865,23 +979,43 @@ void ack_lease (packet, lease, offer, when) state -> options [i] -> tree = (struct tree *)0; i = DHO_DHCP_SERVER_IDENTIFIER; - state -> options [i] = new_tree_cache ("server-id"); - state -> options [i] -> value = - (unsigned char *)&state -> ip -> primary_address; - state -> options [i] -> len = - sizeof state -> ip -> primary_address; - state -> options [i] -> buf_size = state -> options [i] -> len; - state -> options [i] -> timeout = 0xFFFFFFFF; - state -> options [i] -> tree = (struct tree *)0; + if (!state -> options [i]) { + use_primary: + state -> options [i] = new_tree_cache ("server-id"); + state -> options [i] -> value = + (unsigned char *)&state -> + ip -> primary_address; + state -> options [i] -> len = + sizeof state -> ip -> primary_address; + state -> options [i] -> buf_size + = state -> options [i] -> len; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + state -> from.len = + sizeof state -> ip -> primary_address; + memcpy (state -> from.iabuf, + &state -> ip -> primary_address, + state -> from.len); + } else { + /* Find the value of the server identifier... */ + if (!tree_evaluate (state -> options [i])) + goto use_primary; + if (!state -> options [i] -> value || + (state -> options [i] -> len > + sizeof state -> from.iabuf)) + goto use_primary; + + state -> from.len = state -> options [i] -> len; + memcpy (state -> from.iabuf, + state -> options [i] -> value, + state -> from.len); + } /* Sanity check the lease time. */ if ((state -> offered_expiry - cur_time) < 15) - offered_lease_time = (lease -> subnet -> - group -> default_lease_time); - else if (state -> offered_expiry - cur_time > - lease -> subnet -> group -> max_lease_time) - offered_lease_time = (lease -> subnet -> - group -> max_lease_time); + offered_lease_time = default_lease_time; + else if (state -> offered_expiry - cur_time > max_lease_time) + offered_lease_time = max_lease_time; else offered_lease_time = state -> offered_expiry - cur_time; @@ -977,6 +1111,40 @@ void ack_lease (packet, lease, offer, when) state -> options [i] -> tree = (struct tree *)0; } + /* If so directed, use the leased IP address as the router address. + This supposedly makes Win95 machines ARP for all IP addresses, + so if the local router does proxy arp, you win. */ + + ulafdr = 0; + if (lease -> host) { + if (lease -> host -> group -> use_lease_addr_for_default_route) + ulafdr = 1; + } else if (user_class) { + if (user_class -> group -> use_lease_addr_for_default_route) + ulafdr = 1; + } else if (vendor_class) { + if (vendor_class -> group -> use_lease_addr_for_default_route) + ulafdr = 1; + } else if (lease -> subnet -> group -> + use_lease_addr_for_default_route) + ulafdr = 1; + else + ulafdr = 0; + + i = DHO_ROUTERS; + if (ulafdr && !state -> options [i]) { + state -> options [i] = new_tree_cache ("routers"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + lease -> ip_addr.iabuf; + state -> options [i] -> len = + lease -> ip_addr.len; + state -> options [i] -> buf_size = + lease -> ip_addr.len; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + } + #ifdef DEBUG_PACKET dump_packet (packet); dump_raw ((unsigned char *)packet -> raw, packet -> packet_length); @@ -986,11 +1154,14 @@ void ack_lease (packet, lease, offer, when) /* If this is a DHCPOFFER, ping the lease address before actually sending the offer. */ - if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE)) { + if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) && + cur_time - lease -> timestamp > 60) { + lease -> timestamp = cur_time; icmp_echorequest (&lease -> ip_addr); add_timeout (cur_time + 1, lease_ping_timeout, lease); ++outstanding_pings; } else { + lease -> timestamp = cur_time; dhcp_reply (lease); } } @@ -1008,6 +1179,8 @@ void dhcp_reply (lease) int i; struct lease_state *state = lease -> state; int nulltp, bootpp; + u_int8_t *prl; + int prl_len; if (!state) error ("dhcp_reply was supplied lease with no state!"); @@ -1017,20 +1190,19 @@ void dhcp_reply (lease) /* Copy in the filename if given; otherwise, flag the filename buffer as available for options. */ - if (state -> filename) - strncpy (raw.file, state -> filename, sizeof raw.file); + if (state -> filename [0]) + strlcpy (raw.file, state -> filename, sizeof raw.file); else bufs |= 1; /* Copy in the server name if given; otherwise, flag the server_name buffer as available for options. */ if (state -> server_name) - strncpy (raw.sname, state -> server_name, sizeof raw.sname); + strlcpy (raw.sname, state -> server_name, sizeof raw.sname); else bufs |= 2; /* XXX */ - memcpy (raw.chaddr, lease -> hardware_addr.haddr, - lease -> hardware_addr.hlen); + memcpy (raw.chaddr, lease -> hardware_addr.haddr, sizeof raw.chaddr); raw.hlen = lease -> hardware_addr.hlen; raw.htype = lease -> hardware_addr.htype; @@ -1047,9 +1219,25 @@ void dhcp_reply (lease) else bootpp = 1; + if (state -> options [DHO_DHCP_PARAMETER_REQUEST_LIST] && + state -> options [DHO_DHCP_PARAMETER_REQUEST_LIST] -> value) { + prl = state -> options + [DHO_DHCP_PARAMETER_REQUEST_LIST] -> value; + prl_len = state -> options + [DHO_DHCP_PARAMETER_REQUEST_LIST] -> len; + } else if (state -> prl) { + prl = state -> prl; + prl_len = state -> prl_len; + } else { + prl = (u_int8_t *)0; + prl_len = 0; + } + /* Insert such options as will fit into the buffer. */ packet_length = cons_options ((struct packet *)0, &raw, - state -> options, bufs, nulltp, bootpp); + state -> max_message_size, + state -> options, + bufs, nulltp, bootpp, prl, prl_len); /* Having done the cons_options(), we can release the tree_cache entries. */ @@ -1107,8 +1295,6 @@ void dhcp_reply (lease) #endif memset (to.sin_zero, 0, sizeof to.sin_zero); - from = state -> ip -> primary_address; - #ifdef DEBUG_PACKET dump_raw ((unsigned char *)&raw, packet_length); #endif @@ -1123,51 +1309,70 @@ void dhcp_reply (lease) to.sin_addr = raw.giaddr; to.sin_port = local_port; -#ifdef USE_FALLBACK - result = send_fallback (&fallback_interface, - (struct packet *)0, - &raw, packet_length, - raw.siaddr, &to, &hto); - if (result < 0) - warn ("send_fallback: %m"); + if (fallback_interface) { + result = send_packet (fallback_interface, + (struct packet *)0, + &raw, packet_length, + raw.siaddr, + &to, (struct hardware *)0); - free_lease_state (state, "dhcp_reply fallback 1"); - lease -> state = (struct lease_state *)0; - return; -#endif + free_lease_state (state, "dhcp_reply fallback 1"); + lease -> state = (struct lease_state *)0; + return; + } - /* If it comes from a client who already knows its address and - is not requesting a broadcast response, sent it directly to - that client. */ - } else if (raw.ciaddr.s_addr && state -> offer == DHCPACK && - !(raw.flags & htons (BOOTP_BROADCAST))) { - to.sin_addr = state -> ciaddr; - to.sin_port = remote_port; /* XXX */ - -#ifdef USE_FALLBACK - result = send_fallback (&fallback_interface, - (struct packet *)0, - &raw, packet_length, - raw.siaddr, &to, &hto); - if (result < 0) - warn ("send_fallback: %m"); - free_lease_state (state, "dhcp_reply fallback 1"); - lease -> state = (struct lease_state *)0; - return; -#endif + /* If the client is RENEWING, unicast to the client using the + regular IP stack. Some clients, particularly those that + follow RFC1541, are buggy, and send both ciaddr and + server-identifier. We deal with this situation by assuming + that if we got both dhcp-server-identifier and ciaddr, and + giaddr was not set, then the client is on the local + network, and we can therefore unicast or broadcast to it + successfully. A client in REQUESTING state on another + network that's making this mistake will have set giaddr, + and will therefore get a relayed response from the above + code. */ + } else if (raw.ciaddr.s_addr && + !((state -> got_server_identifier || + (raw.flags & htons (BOOTP_BROADCAST))) && + /* XXX This won't work if giaddr isn't zero, but it is: */ + (state -> shared_network == lease -> shared_network)) && + state -> offer == DHCPACK) { + to.sin_addr = raw.ciaddr; + to.sin_port = remote_port; + + if (fallback_interface) { + result = send_packet (fallback_interface, + (struct packet *)0, + &raw, packet_length, + raw.siaddr, &to, + (struct hardware *)0); + free_lease_state (state, + "dhcp_reply fallback 2"); + lease -> state = (struct lease_state *)0; + return; + } + + /* If it comes from a client that already knows its address + and is not requesting a broadcast response, and we can + unicast to a client without using the ARP protocol, sent it + directly to that client. */ + } else if (!(raw.flags & htons (BOOTP_BROADCAST)) && + can_unicast_without_arp ()) { + to.sin_addr = raw.yiaddr; + to.sin_port = remote_port; /* Otherwise, broadcast it on the local network. */ } else { to.sin_addr.s_addr = htonl (INADDR_BROADCAST); - to.sin_port = remote_port; /* XXX */ + to.sin_port = remote_port; } + memcpy (&from, state -> from.iabuf, sizeof from); result = send_packet (state -> ip, (struct packet *)0, &raw, packet_length, - raw.siaddr, &to, &hto); - if (result < 0) - warn ("sendpkt: %m"); + from, &to, &hto); free_lease_state (state, "dhcp_reply"); lease -> state = (struct lease_state *)0; @@ -1184,6 +1389,20 @@ struct lease *find_lease (packet, share, ours) struct host_decl *hp, *host = (struct host_decl *)0; struct lease *fixed_lease; + /* Figure out what IP address the client is requesting, if any. */ + if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len && + packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len == 4) { + packet -> got_requested_address = 1; + cip.len = 4; + memcpy (cip.iabuf, + packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data, + cip.len); + } else if (packet -> raw -> ciaddr.s_addr) { + cip.len = 4; + memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4); + } else + cip.len = 0; + /* Try to find a host or lease that's been assigned to the specified unique client identifier. */ if (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len) { @@ -1230,6 +1449,20 @@ struct lease *find_lease (packet, share, ours) } } + /* If fixed_lease is present but does not match the requested + IP address, and this is a DHCPREQUEST, then we can't return + any other lease, so we might as well return now. */ + if (packet -> packet_type == DHCPREQUEST && fixed_lease && + (fixed_lease -> ip_addr.len != cip.len || + memcmp (fixed_lease -> ip_addr.iabuf, + cip.iabuf, cip.len))) { + if (ours) + *ours = 1; + strlcpy (dhcp_message, "requested address is incorrect", + sizeof (dhcp_message)); + return (struct lease *)0; + } + /* Try to find a lease that's been attached to the client's hardware address... */ hw_lease = find_lease_by_hw_addr (packet -> raw -> chaddr, @@ -1238,7 +1471,7 @@ struct lease *find_lease (packet, share, ours) (if any). */ for (; hw_lease; hw_lease = hw_lease -> n_hw) { if (hw_lease -> shared_network == share) { - if (hw_lease -> flags & ABANDONED_LEASE) + if ((hw_lease -> flags & ABANDONED_LEASE)) continue; if (packet -> packet_type) break; @@ -1250,18 +1483,9 @@ struct lease *find_lease (packet, share, ours) /* Try to find a lease that's been allocated to the client's IP address. */ - if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len && - packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len == 4) { - cip.len = 4; - memcpy (cip.iabuf, - packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data, - cip.len); + if (cip.len) ip_lease = find_lease_by_ip_addr (cip); - } else if (packet -> raw -> ciaddr.s_addr) { - cip.len = 4; - memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4); - ip_lease = find_lease_by_ip_addr (cip); - } else + else ip_lease = (struct lease *)0; /* If ip_lease is valid at this point, set ours to one, so that @@ -1271,36 +1495,88 @@ struct lease *find_lease (packet, share, ours) *ours = 1; /* If the requested IP address isn't on the network the packet - came from, or if it's been abandoned, don't use it. */ - if (ip_lease && (ip_lease -> shared_network != share || - (ip_lease -> flags & ABANDONED_LEASE))) + came from, don't use it. Allow abandoned leases to be matched + here - if the client is requesting it, there's a decent chance + that it's because the lease database got trashed and a client + that thought it had this lease answered an ARP or PING, causing the + lease to be abandoned. If so, this request probably came from + that client. */ + if (ip_lease && (ip_lease -> shared_network != share)) { ip_lease = (struct lease *)0; + strlcpy (dhcp_message, "requested address on bad subnet", + sizeof(dhcp_message)); + } - /* Toss ip_lease if it hasn't yet expired and the uid doesn't - match */ + /* Toss ip_lease if it hasn't yet expired and isn't owned by the + client. */ if (ip_lease && ip_lease -> ends >= cur_time && - ip_lease -> uid && ip_lease != uid_lease) { + ip_lease != uid_lease) { int i = DHO_DHCP_CLIENT_IDENTIFIER; - /* If for some reason the client has more than one lease - on the subnet that matches its uid, pick the one that - it asked for. It might be nice in some cases to - release the extraneous leases, but better to leave - that to a human. */ - if (packet -> options [i].data && - ip_lease -> uid_len == packet -> options [i].len && - !memcmp (packet -> options [i].data, - ip_lease -> uid, ip_lease -> uid_len)) { - warn ("client %s has duplicate leases on %s", - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr), - ip_lease -> shared_network -> name); - uid_lease = ip_lease; + /* Make sure that ip_lease actually belongs to the client, + and toss it if not. */ + if ((ip_lease -> uid_len && + packet -> options [i].data && + ip_lease -> uid_len == packet -> options [i].len && + !memcmp (packet -> options [i].data, + ip_lease -> uid, ip_lease -> uid_len)) || + (!ip_lease -> uid_len && + (ip_lease -> hardware_addr.htype == + packet -> raw -> htype) && + ip_lease -> hardware_addr.hlen == packet -> raw -> hlen && + !memcmp (ip_lease -> hardware_addr.haddr, + packet -> raw -> chaddr, + ip_lease -> hardware_addr.hlen))) { + if (uid_lease) { + if (uid_lease -> ends > cur_time) { + warn ("client %s has duplicate leases on %s", + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr), + ip_lease -> shared_network -> name); + + if (uid_lease && + !packet -> raw -> ciaddr.s_addr) + release_lease (uid_lease); + } + uid_lease = ip_lease; + } + } else { + strlcpy (dhcp_message, + "requested address is not available", + sizeof(dhcp_message)); + ip_lease = (struct lease *)0; + } + + /* If we get to here and fixed_lease is not null, that means + that there are both a dynamic lease and a fixed-address + declaration for the same IP address. */ + if (packet -> packet_type == DHCPREQUEST && fixed_lease) { + fixed_lease = (struct lease *)0; + db_conflict: + warn ("Both dynamic and static leases present for %s.", + piaddr (cip)); + warn ("Either remove host declaration %s or remove %s", + (fixed_lease && fixed_lease -> host + ? (fixed_lease -> host -> name + ? fixed_lease -> host -> name : piaddr (cip)) + : piaddr (cip)), + piaddr (cip)); + warn ("from the dynamic address pool for %s", + share -> name); + if (fixed_lease) + ip_lease = (struct lease *)0; + strlcpy (dhcp_message, + "database conflict - call for help!", + sizeof(dhcp_message)); } - ip_lease = (struct lease *)0; } + /* If we get to here with both fixed_lease and ip_lease not + null, then we have a configuration file bug. */ + if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease) + goto db_conflict; + /* Toss hw_lease if it hasn't yet expired and the uid doesn't match, except that if the hardware address matches and the client is now doing dynamic BOOTP (and thus hasn't provided @@ -1313,48 +1589,47 @@ struct lease *find_lease (packet, share, ours) hw_lease = (struct lease *)0; /* Toss extra pointers to the same lease... */ - if (ip_lease == hw_lease) - ip_lease = (struct lease *)0; if (hw_lease == uid_lease) hw_lease = (struct lease *)0; + if (ip_lease == hw_lease) + hw_lease = (struct lease *)0; if (ip_lease == uid_lease) - ip_lease = (struct lease *)0; - - /* If we got an ip address lease, make sure it isn't assigned to - some *other* client! If it was assigned to this client, we'd - have zeroed it out above, so the only way we can take it at this - point is if some other client had it but it's timed out, or if no - other client has ever had it. */ - if (ip_lease && - ip_lease -> ends >= cur_time) - ip_lease = (struct lease *)0; + uid_lease = (struct lease *)0; /* If we've already eliminated the lease, it wasn't there to begin with. If we have come up with a matching lease, set the message to bad network in case we have to throw it out. */ - if (!ip_lease && !hw_lease && !uid_lease) { - strcpy (dhcp_message, "requested address not available"); - } else { - strcpy (dhcp_message, "requested address on bad subnet"); + if (!ip_lease) { + strlcpy (dhcp_message, "requested address not available", + sizeof(dhcp_message)); } /* Now eliminate leases that are on the wrong network... */ if (ip_lease && (share != ip_lease -> shared_network)) { - release_lease (ip_lease); + if (packet -> packet_type == DHCPREQUEST) + release_lease (ip_lease); ip_lease = (struct lease *)0; } if (uid_lease && (share != uid_lease -> shared_network)) { - release_lease (uid_lease); + if (packet -> packet_type == DHCPREQUEST) + release_lease (uid_lease); uid_lease = (struct lease *)0; } if (hw_lease && (share != hw_lease -> shared_network)) { - release_lease (hw_lease); + if (packet -> packet_type == DHCPREQUEST) + release_lease (hw_lease); hw_lease = (struct lease *)0; } + /* If this is a DHCPREQUEST, make sure the lease we're going to return + matches the requested IP address. If it doesn't, don't return a + lease at all. */ + if (packet -> packet_type == DHCPREQUEST && !ip_lease && !fixed_lease) + return (struct lease *)0; + /* At this point, if fixed_lease is nonzero, we can assign it to this client. */ if (fixed_lease) { @@ -1365,7 +1640,8 @@ struct lease *find_lease (packet, share, ours) a better offer, use that; otherwise, release it. */ if (ip_lease) { if (lease) { - release_lease (ip_lease); + if (packet -> packet_type == DHCPREQUEST) + release_lease (ip_lease); } else { lease = ip_lease; lease -> host = (struct host_decl *)0; @@ -1377,7 +1653,8 @@ struct lease *find_lease (packet, share, ours) the lease that matched the client identifier. */ if (uid_lease) { if (lease) { - release_lease (uid_lease); + if (packet -> packet_type == DHCPREQUEST) + release_lease (uid_lease); } else { lease = uid_lease; lease -> host = (struct host_decl *)0; @@ -1387,7 +1664,8 @@ struct lease *find_lease (packet, share, ours) /* The lease that matched the hardware address is treated likewise. */ if (hw_lease) { if (lease) { - release_lease (hw_lease); + if (packet -> packet_type == DHCPREQUEST) + release_lease (hw_lease); } else { lease = hw_lease; lease -> host = (struct host_decl *)0; @@ -1407,6 +1685,18 @@ struct lease *find_lease (packet, share, ours) } } + /* If we find an abandoned lease, take it, but print a + warning message, so that if it continues to lose, + the administrator will eventually investigate. */ + if (lease && (lease -> flags & ABANDONED_LEASE)) { + if (packet -> packet_type == DHCPREQUEST) { + warn ("Reclaiming REQUESTed abandoned IP address %s.", + piaddr (lease -> ip_addr)); + lease -> flags &= ~ABANDONED_LEASE; + } else + lease = (struct lease *)0; + } + return lease; } diff --git a/usr.sbin/dhcp/server/dhcpd.8 b/usr.sbin/dhcp/server/dhcpd.8 index b59436d8510..b7e31881345 100644 --- a/usr.sbin/dhcp/server/dhcpd.8 +++ b/usr.sbin/dhcp/server/dhcpd.8 @@ -37,7 +37,7 @@ .\" Enterprises, see ``http://www.vix.com''. .TH dhcpd 8 .SH NAME -dhcpd - Dynamic Host Configuration Protocol (DHCP)Server +dhcpd - Dynamic Host Configuration Protocol Server .SH SYNOPSIS .B dhcpd [ @@ -74,13 +74,6 @@ Protocol (BOOTP). DHCP allows hosts on a TCP/IP network to request and be assigned IP addresses, and also to discover information about the network to which they are attached. BOOTP provides similar functionality, with certain restrictions. -.SH SYSTEM REQUIREMENTS -There \fPmust\fR be a /etc/dhcpd.conf file. There \fBmust\fR -be a /var/db/dhcpd.leases file. This file can initially be created by -typing \fItouch /var/db/dhcpd.leases\fR. You must have the Berkeley -Packet Filter (bpf) configured in your kernel. You must have -at least one /dev/bpf* file for each broadcast network interface that -is attached to your system. .SH OPERATION .PP The DHCP protocol allows a host which is unknown to the network @@ -123,8 +116,8 @@ contain all the lease information, so there is no need for a special crash recovery process. .PP BOOTP support is also provided by this server. Unlike DHCP, the BOOTP -protocol does not provides a protocol for recovering -dynamically assigned addresses once they are no longer needed. It is +protocol does not provide a protocol for recovering +dynamically-assigned addresses once they are no longer needed. It is still possible to dynamically assign addresses to BOOTP clients, but some administrative process for reclaiming addresses is required. By default, leases are granted to BOOTP clients in perpetuity, although @@ -138,7 +131,7 @@ BOOTP client, permanently assigning an address to each client. Whenever changes are made to the dhcpd.conf file, dhcpd must be restarted. To restart dhcpd, send a SIGTERM (signal 15) to the process ID contained in -.IR /var/run/dhcpd.pid , +.IR RUNDIR/dhcpd.pid , and then re-invoke dhcpd. Because the DHCP server database is not as lightweight as a BOOTP database, dhcpd does not automatically restart itself when it sees a change to the dhcpd.conf file. @@ -157,7 +150,7 @@ broadcasts may be specified on the command line. This should be done on systems where dhcpd is unable to identify non-broadcast interfaces, but should not be required on other systems. If no interface names are specified on the command line dhcpd will identify all network -interfaces which are up, eliminating non-broadcast interfaces if +interfaces which are up, elimininating non-broadcast interfaces if possible, and listen for DHCP broadcasts on each interface. .PP If dhcpd should listen on a port other than the standard (port 67), @@ -165,6 +158,18 @@ the .B -p flag may used. It should be followed by the udp port number on which dhcpd should listen. This is mostly useful for debugging purposes. +If the +.B -p +flag is specified, the server will transmit responses to clients at a +port number that is one greater than the one specified - i.e., if you +specify +.B -p +67, then the server will listen on port 67 and transmit to port 68. +Datagrams that must go through relay agents are sent to the port +number specified with the +.B -p +flag - if you wish to use alternate port numbers, you must configure +any relay agents you are using to use the same alternate port numbers. .PP To run dhcpd as a foreground process, rather than allowing it to run as a daemon in the background, the @@ -195,7 +200,7 @@ startup. To avoid printing this message, the .B -q flag may be specified. .SH CONFIGURATION -The syntax of the dhcpd.conf(5) file is discussed separately. This +The syntax of the dhcpd.conf(5) file is discussed seperately. This section should be used as an overview of the configuration process, and the dhcpd.conf(5) documentation should be consulted for detailed reference information. @@ -279,7 +284,7 @@ client declaration might look like this: } .fi .SH Options -DHCP (and also BOOTP with Vendor Extensions) provide a mechanism +DHCP (and also BOOTP with Vendor Extensions) provides a mechanism whereby the server can provide the client with information about how to configure its network interface (e.g., subnet mask), and also how the client can access various network services (e.g., DNS, IP routers, @@ -320,10 +325,10 @@ use a different name server might be declared as follows: A more complete description of the dhcpd.conf file syntax is provided in dhcpd.conf(5). .SH FILES -.B /etc/dhcpd.conf, /var/db/dhcpd.leases, /var/run/dhcpd.pid, -.B /var/db/dhcpd.leases~. +.B ETCDIR/dhcpd.conf, DBDIR/dhcpd.leases, RUNDIR/dhcpd.pid, +.B DBDIR/dhcpd.leases~. .SH SEE ALSO -dhclient(8), dhcrelay(8), dhcpd.conf(5), dhcpd.leases(5), bpf(4) +dhclient(8), dhcrelay(8), dhcpd.conf(5), dhcpd.leases(5) .SH AUTHOR .B dhcpd(8) was written by Ted Lemon diff --git a/usr.sbin/dhcp/server/dhcpd.c b/usr.sbin/dhcp/server/dhcpd.c index dcbb746c78b..6a8dbd179c2 100644 --- a/usr.sbin/dhcp/server/dhcpd.c +++ b/usr.sbin/dhcp/server/dhcpd.c @@ -3,8 +3,8 @@ DHCP Server Daemon. */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,19 +40,18 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char ocopyright[] = -"$Id: dhcpd.c,v 1.3 2001/01/03 16:04:40 ericj Exp $ Copyright 1995, 1996 The Internet Software Consortium."; -#endif static char copyright[] = -"Copyright 1995, 1996 The Internet Software Consortium."; +"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; static char arr [] = "All rights reserved."; -static char message [] = "Internet Software Consortium DHCPD $Name: $"; +static char message [] = "Internet Software Consortium DHCP Server"; +static char contrib [] = "Please contribute if you find this software useful."; +static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html"; #include "dhcpd.h" +#include "version.h" -static void usage PROTO ((void)); +static void usage PROTO ((char *)); TIME cur_time; struct group root_group; @@ -60,10 +59,6 @@ struct group root_group; struct iaddr server_identifier; int server_identifier_matched; -#ifdef USE_FALLBACK -struct interface_info fallback_interface; -#endif - u_int16_t local_port; u_int16_t remote_port; @@ -76,6 +71,7 @@ int log_perror = 1; char *path_dhcpd_conf = _PATH_DHCPD_CONF; char *path_dhcpd_db = _PATH_DHCPD_DB; +char *path_dhcpd_pid = _PATH_DHCPD_PID; int main (argc, argv, envp) int argc; @@ -83,36 +79,30 @@ int main (argc, argv, envp) { int i, status; struct servent *ent; - char *s; + char *s, *appname; int cftest = 0; #ifndef DEBUG int pidfilewritten = 0; - pid_t pid; + int pid; char pbuf [20]; int daemon = 1; #endif int quiet = 0; - /* Initially, log errors to stderr as well as to syslogd. */ -#ifdef SYSLOG_4_2 - openlog ("dhcpd", LOG_NDELAY); - log_priority = DHCPD_LOG_FACILITY; -#else - openlog ("dhcpd", LOG_NDELAY, DHCPD_LOG_FACILITY); -#endif + appname = strrchr (argv [0], '/'); + if (!appname) + appname = argv [0]; + else + appname++; -#ifndef DEBUG -#ifndef SYSLOG_4_2 -#ifndef __CYGWIN32__ /* XXX */ + /* Initially, log errors to stderr as well as to syslogd. */ + openlog (appname, LOG_NDELAY, DHCPD_LOG_FACILITY); setlogmask (LOG_UPTO (LOG_INFO)); -#endif -#endif -#endif for (i = 1; i < argc; i++) { if (!strcmp (argv [i], "-p")) { if (++i == argc) - usage (); + usage (appname); for (s = argv [i]; *s; s++) if (!isdigit (*s)) error ("%s: not a valid UDP port", @@ -135,11 +125,15 @@ int main (argc, argv, envp) log_perror = -1; } else if (!strcmp (argv [i], "-cf")) { if (++i == argc) - usage (); + usage (appname); path_dhcpd_conf = argv [i]; + } else if (!strcmp (argv [i], "-pf")) { + if (++i == argc) + usage (appname); + path_dhcpd_pid = argv [i]; } else if (!strcmp (argv [i], "-lf")) { if (++i == argc) - usage (); + usage (appname); path_dhcpd_db = argv [i]; } else if (!strcmp (argv [i], "-t")) { /* test configurations only */ @@ -152,7 +146,7 @@ int main (argc, argv, envp) quiet = 1; quiet_interface_discovery = 1; } else if (argv [i][0] == '-') { - usage (); + usage (appname); } else { struct interface_info *tmp = ((struct interface_info *) @@ -161,18 +155,23 @@ int main (argc, argv, envp) error ("Insufficient memory to %s %s", "record interface", argv [i]); memset (tmp, 0, sizeof *tmp); - strlcpy(tmp->name, argv[i], IFNAMSIZ); - tmp -> next = interfaces; - tmp -> flags = INTERFACE_REQUESTED; + strlcpy (tmp->name, argv [i], sizeof(tmp->name)); + tmp->next = interfaces; + tmp->flags = INTERFACE_REQUESTED; interfaces = tmp; } } if (!quiet) { - note (message); + note ("%s %s", message, DHCP_VERSION); note (copyright); note (arr); - } + note (""); + note (contrib); + note (url); + note (""); + } else + log_perror = 0; /* Default to the DHCP/BOOTP port. */ if (!local_port) @@ -204,7 +203,7 @@ int main (argc, argv, envp) db_startup (); /* Discover all the network interfaces and initialize them. */ - discover_interfaces (1); + discover_interfaces (DISCOVER_SERVER); /* Initialize icmp support... */ icmp_startup (1, lease_pinged); @@ -212,25 +211,33 @@ int main (argc, argv, envp) #ifndef DEBUG if (daemon) { /* First part of becoming a daemon... */ - if ((pid = fork ()) < 0) + if ((pid = fork ()) == -1) error ("Can't fork daemon: %m"); else if (pid) exit (0); } /* Read previous pid file. */ - if ((i = open (_PATH_DHCPD_PID, O_RDONLY)) >= 0) { + if ((i = open (path_dhcpd_pid, O_RDONLY)) != -1) { status = read (i, pbuf, (sizeof pbuf) - 1); close (i); pbuf [status] = 0; - pid = (pid_t)atoi(pbuf); + pid = atoi (pbuf); /* If the previous server process is not still running, write a new pid file immediately. */ - if (pid && kill (pid, 0) < 0) { - write_pidfile(_PATH_DHCPD_PID, getpid()); - pidfilewritten = 1; - } + if (pid && (pid == getpid () || kill (pid, 0) == -1)) { + unlink (path_dhcpd_pid); + if ((i = open (path_dhcpd_pid, + O_WRONLY | O_CREAT, 0640)) != -1) { + snprintf (pbuf, sizeof(pbuf), "%d\n", + (int)getpid ()); + write (i, pbuf, strlen (pbuf)); + close (i); + pidfilewritten = 1; + } + } else + error ("There's already a DHCP server running.\n"); } /* If we were requested to log to stdout on the command line, @@ -253,8 +260,15 @@ int main (argc, argv, envp) meaning nothing is listening on the bootp port, then write the pid file out - what's in it now is bogus anyway. */ if (!pidfilewritten) { - write_pidfile(_PATH_DHCPD_PID, getpid()); - pidfilewritten = 1; + unlink (path_dhcpd_pid); + if ((i = open (path_dhcpd_pid, + O_WRONLY | O_CREAT, 0640)) != -1) { + snprintf (pbuf, sizeof(pbuf), "%d\n", + (int)getpid ()); + write (i, pbuf, strlen (pbuf)); + close (i); + pidfilewritten = 1; + } } #endif /* !DEBUG */ @@ -270,14 +284,20 @@ int main (argc, argv, envp) /* Print usage message. */ -static void usage () +static void usage (appname) + char *appname; { note (message); note (copyright); note (arr); - - error ("Usage: dhcpd [-p ] [-d] [-f] [-cf config-file]%s", - "\n [-lf lease-file] [if0 [...ifN]]"); + note (""); + note (contrib); + note (url); + note (""); + + warn ("Usage: %s [-p ] [-d] [-f] [-cf config-file]", + appname); + error(" [-lf lease-file] [-pf pidfile] [if0 [...ifN]]"); } void cleanup () @@ -320,7 +340,7 @@ void lease_pinged (from, packet, length) * and something answered, so we don't release it. */ if (lp -> releasing) { - warn ("IP address %s answers a ping after sending a release", + warn ("IP address %s answers a ping after sending a release", piaddr (lp -> ip_addr)); warn ("Possible release spoof - Not releasing address %s", piaddr (lp -> ip_addr)); @@ -329,7 +349,6 @@ void lease_pinged (from, packet, length) else { free_lease_state (lp -> state, "lease_pinged"); lp -> state = (struct lease_state *)0; - abandon_lease (lp, "pinged before offer"); } cancel_timeout (lease_ping_timeout, lp); @@ -346,7 +365,6 @@ void lease_ping_timeout (vlp) lp->releasing = 0; release_lease(lp); } - else { + else dhcp_reply (lp); - } } diff --git a/usr.sbin/dhcp/server/dhcpd.conf b/usr.sbin/dhcp/server/dhcpd.conf index a50dee0751d..d58d54d6eaf 100644 --- a/usr.sbin/dhcp/server/dhcpd.conf +++ b/usr.sbin/dhcp/server/dhcpd.conf @@ -1,67 +1,29 @@ # dhcpd.conf # -# Configuration file for ISC dhcpd +# Sample configuration file for ISC dhcpd # -# Hosts with more than one interface MUST specify a ``server-identifier'', -# which should be the IP address of the server's primary network interface, -# or if there is no interface that can be described that way, at least an -# interface whose address isn't likely to change. - -server-identifier toccata.fugue.com; - # option definitions common to all supported networks... option domain-name "fugue.com"; option domain-name-servers toccata.fugue.com; -# Shared network declaration is used to group subnets which share the same -# physical network together. The name is specified so that the shared -# network can be referred to in log messages - it serves no other function. - -shared-network FUGUE { - -# option definitions common to this shared network. - option subnet-mask 255.255.255.224; - default-lease-time 600; - max-lease-time 7200; +option subnet-mask 255.255.255.224; +default-lease-time 600; +max-lease-time 7200; -# One of the two IP subnets that share this physical network -# -# Address ranges can be specified for each subnet attached to -# a shared network. Since these subnets share the same physical -# network, addresses are pooled together, and assignments are made -# without regard to the actual subnet. If the optional dynamic-bootp -# keyword is given in the address range declaration, then addresses -# in that range can be assigned either with the DHCP protocol or the -# BOOTP protocol; otherwise, only DHCP clients will have addresses -# allocated from the address range. -# -# Note that each IP subnet can have its own options specific to that subnet. -# options that aren't specified in the subnet are taken from the shared -# network (if any) and then from the global option list. - - subnet 204.254.239.0 netmask 255.255.255.224 { - range 204.254.239.10 204.254.239.20; - option broadcast-address 204.254.239.31; - option routers prelude.fugue.com; - } +subnet 204.254.239.0 netmask 255.255.255.224 { + range 204.254.239.10 204.254.239.20; + option broadcast-address 204.254.239.31; + option routers prelude.fugue.com; +} # The other subnet that shares this physical network - subnet 204.254.239.32 netmask 255.255.255.224 { - range dynamic-bootp 204.254.239.10 204.254.239.20; - option broadcast-address 204.254.239.31; - option routers snarg.fugue.com; - } +subnet 204.254.239.32 netmask 255.255.255.224 { + range dynamic-bootp 204.254.239.10 204.254.239.20; + option broadcast-address 204.254.239.31; + option routers snarg.fugue.com; } -# IP subnets that are alone on their physical wire should be declared by -# themselves. ISC dhcpd may still refer to them as shared networks in -# log messages, but this is simply an artifact of the underlying data -# structures. -# -# Note that options can be specified in the subnet declaration which -# supersede the global options specified earlier. - subnet 192.5.5.0 netmask 255.255.255.224 { range 192.5.5.26 192.5.5.30; option name-servers bb.home.vix.com, gw.home.vix.com; diff --git a/usr.sbin/dhcp/server/dhcpd.conf.5 b/usr.sbin/dhcp/server/dhcpd.conf.5 index f7228b2a45d..b4b44ca8a62 100644 --- a/usr.sbin/dhcp/server/dhcpd.conf.5 +++ b/usr.sbin/dhcp/server/dhcpd.conf.5 @@ -1,7 +1,7 @@ .\" dhcpd.conf.5 .\" -.\" Copyright (c) 1995, 1996 The Internet Software Consortium. -.\" All rights reserved. +.\" Copyright (c) 1995, 1996, 1997, 1998, 1998, 1999 +.\" The Internet Software Consortium. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -37,7 +37,7 @@ .\" Enterprises, see ``http://www.vix.com''. .TH dhcpd.conf 5 .SH NAME -dhcpd.conf - DHCP server configuration file +dhcpd.conf - dhcpd configuration file .SH DESCRIPTION The dhcpd.conf file contains configuration information for .IR dhcpd, @@ -85,9 +85,9 @@ even if no addresses will be dynamically allocated on that subnet. Some installations have physical networks on which more than one IP subnet operates. For example, if there is a site-wide requirement that 8-bit subnet masks be used, but a department with a single -physical Ethernet network expands to the point where it has more than +physical ethernet network expands to the point where it has more than 254 nodes, it may be necessary to run two 8-bit subnets on the same -Ethernet until such time as a new physical network can be added. In +ethernet until such time as a new physical network can be added. In this case, the \fIsubnet\fR declarations for these two networks may be enclosed in a \fIshared-network\fR declaration. .PP @@ -176,7 +176,7 @@ Figure 2 As you can see in Figure 2, it's legal to specify host addresses in parameters as domain names rather than as numeric IP addresses. If a given hostname resolves to more than one IP address (for example, if -that host has two Ethernet interfaces), both addresses are supplied to +that host has two ethernet interfaces), both addresses are supplied to the client. .PP In Figure 1, you can see that both the shared-network statement and @@ -278,7 +278,7 @@ group { .fi .SH REFERENCE: DECLARATIONS .PP -.B The +.B The .I shared-network .B statement .PP @@ -308,7 +308,7 @@ shared network. The name may have the syntax of a valid domain name (although it will never be used as such), or it may be any arbitrary name, enclosed in quotes. .PP -.B The +.B The .I subnet .B statement .PP @@ -329,7 +329,7 @@ declaration. The .I subnet-number should be an IP address or domain name which resolves to the subnet -number of the subnet being described. The +number of the subnet being described. The .I netmask should be an IP address or domain name which resolves to the subnet mask of the subnet being described. The subnet number, together with the @@ -372,7 +372,7 @@ single address, \fIhigh-address\fR can be omitted. .PP There must be at least one .B host -statement for every BOOTP client that is to be served. +statement for every BOOTP client that is to be served. .B host statements may also be specified for DHCP clients, although this is not required unless booting is only enabled for known hosts. @@ -386,7 +386,7 @@ parameter, or more than one statement may be specified. .PP If client-specific boot parameters must change based on the network -to which the client is attached, then multiple +to which the client is attached, then multiple .B host statements should be used. @@ -493,7 +493,7 @@ should be the maximum length in seconds that will be assigned to a lease if the client requesting the lease asks for a specific expiration time. .PP -.B The +.B The .I hardware .B statement .PP @@ -506,16 +506,16 @@ statement. .I hardware-type must be the name of a physical hardware interface type. Currently, only the -.B Ethernet -type is recognized, although support for -.B token-ring +.B ethernet and +.B token-ring +types are recognized, although support for a .B fddi -hardware types would also be desirable. +hardware type (and others) would also be desirable. The .I hardware-address should be a set of hexadecimal octets (numbers from 0 through ff) -separated by colons. The \fIhardwarefR statement may also be used +seperated by colons. The \fIhardware\fR statement may also be used for DHCP clients. .PP .B The @@ -579,7 +579,7 @@ or more IP addresses. The \fIdynamic-bootp-lease-cutoff\fR statement sets the ending time for all leases assigned dynamically to BOOTP clients. Because BOOTP clients do not have any way of renewing leases, and don't know that -their leases could expire, by default dhcpd assigns infinite leases +their leases could expire, by default dhcpd assignes infinite leases to all BOOTP clients. However, it may make sense in some situations to set a cutoff date for all BOOTP leases - for example, the end of a school term, or the time at night when a facility is closed and all @@ -597,7 +597,7 @@ from zero (Sunday) to six (Saturday). YYYY is the year, including the century. MM is the month expressed as a number from 1 to 12. DD is the day of the month, counting from 1. HH is the hour, from zero to 23. MM is the minute and SS is the second. The time is always in -Greenwich Mean Time (GMT), not local time. +Universal Coordinated Time (UTC), not local time. .PP .B The .I dynamic-bootp-lease-length @@ -663,13 +663,107 @@ An \fIoption host-name\fR statement within a host declaration will override the use of the name in the host declaration. .PP .B The +.I authoritative +.B statement +.PP + \fBauthoritative;\fR +.PP + \fBnot authoritative;\fR +.PP +The DHCP server will normally assume that the configuration +information about a given network segment is known to be correct and +is authoritative. So if a client requests an IP address on a given +network segment that the server knows is not valid for that segment, +the server will respond with a DHCPNAK message, causing the client to +forget its IP address and try to get a new one. +.PP +If a DHCP server is being configured by somebody who is not the +network administrator and who therefore does not wish to assert this +level of authority, then the statement "not authoritative" should be +written in the appropriate scope in the configuration file. +.PP +Usually, writing \fBnot authoritative;\fR at the top level of the file +should be sufficient. However, if a DHCP server is to be set up so +that it is aware of some networks for which it is authoritative and +some networks for which it is not, it may be more appropriate to +declare authority on a per-network-segment basis. +.PP +Note that the most specific scope for which the concept of authority +makes any sense is the physical network segment - either a +shared-network statement or a subnet statement that is not contained +within a shared-network statement. It is not meaningful to specify +that the server is authoritative for some subnets within a shared +network, but not authoritative for others, nor is it meaningful to +specify that the server is authoritative for some host declarations +and not others. +.PP +.B The +.I use-lease-addr-for-default-route +.B statement +.PP + \fBuse-lease-addr-for-default-route\fR \fIflag\fR\fB;\fR +.PP +If the \fIuse-lease-addr-for-default-route\fR parameter is true in a +given scope, then instead of sending the value specified in the +routers option (or sending no value at all), the IP address of the +lease being assigned is sent to the client. This supposedly causes +Win95 machines to ARP for all IP addresses, which can be helpful if +your router is configured for proxy ARP. +.PP +If use-lease-addr-for-default-route is enabled and an option routers +statement are both in scope, the routers option will be preferred. +The rationale for this is that in situations where you want to use +this feature, you probably want it enabled for a whole bunch of +Windows 95 machines, and you want to override it for a few other +machines. Unfortunately, if the opposite happens to be true for you +site, you are probably better off not trying to use this flag. +.PP +.B The +.I always-reply-rfc1048 +.B statement +.PP + \fBalways-reply-rfc1048\fR \fIflag\fR\fB;\fR +.PP +Some BOOTP clients expect RFC1048-style responses, but do not follow +RFC1048 when sending their requests. You can tell that a client is +having this problem if it is not getting the options you have +configured for it and if you see in the server log the message +"(non-rfc1048)" printed with each BOOTREQUEST that is logged. +.PP +If you want to send rfc1048 options to such a client, you can set the +.B always-reply-rfc1048 +option in that client's host declaration, and the DHCP server will +respond with an RFC-1048-style vendor options field. This flag can +be set in any scope, and will affect all clients covered by that +scope. +.PP +.B The .I server-identifier .B statement .PP \fBserver-identifier \fIhostname\fR\fB;\fR .PP -The server-identifier statement is now obsolete and is ignored by -the DHCP server. +The server-identifier statement can be used to define the value that +is sent in the DHCP Server Identifier option for a given scope. The +value specified \fBmust\fR be an IP address for the DHCP server, and +must be reachable by all clients served by a particular scope. +.PP +The use of the server-identifier statement is not recommended - the only +reason to use it is to force a value other than the default value to be +sent on occasions where the default value would be incorrect. The default +value is the first IP address associated with the physical network interface +on which the request arrived. +.PP +The usual case where the +\fIserver-identifier\fR statement needs to be sent is when a physical +interface has more than one IP address, and the one being sent by default +isn't appropriate for some or all clients served by that interface. +Another common case is when an alias is defined for the purpose of +having a consistent IP address for the DHCP server, and it is desired +that the clients use this IP address when contacting the server. +.PP +Supplying a value for the dhcp-server-identifier option is equivalent +to using the server-identifier statement. .SH REFERENCE: OPTION STATEMENTS .PP DHCP option statements are documented in the diff --git a/usr.sbin/dhcp/server/dhcpd.leases.5 b/usr.sbin/dhcp/server/dhcpd.leases.5 index d0ba7505e59..b579c29d79e 100644 --- a/usr.sbin/dhcp/server/dhcpd.leases.5 +++ b/usr.sbin/dhcp/server/dhcpd.leases.5 @@ -1,7 +1,6 @@ -.\" $OpenBSD: dhcpd.leases.5,v 1.2 1999/05/30 02:42:23 pjanzen Exp $ -.\" dhcpd.conf.5 +.\" dhcpd.leases.5 .\" -.\" Copyright (c) 1997 The Internet Software Consortium. +.\" Copyright (c) 1997, 1998 The Internet Software Consortium. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -42,36 +41,128 @@ dhcpd.leases - DHCP client lease database .SH DESCRIPTION The Internet Software Consortium DHCP Server keeps a persistent database of leases that it has assigned. This database is a free-form -ASCII file containing one valid declaration per lease. If more than -one declaration appears for a given lease, the last one in the file is -used. The file is written as a log, so this is not an unusual -occurrence. +ASCII file containing a series of lease declarations. Every time a +lease is acquired, renewed or released, its new value is recorded at +the end of the lease file. So if more than one declaration appears +for a given lease, the last one in the file is the current one. .PP When dhcpd is first installed, there is no lease database. However, dhcpd requires that a lease database be present before it will start. To make the initial lease database, just create an empty file called -/var/db/dhcpd.leases. +DBDIR/dhcpd.leases. .PP In order to prevent the lease database from growing without bound, the file is rewritten from time to time. First, a temporary lease database is created and all known leases are dumped to it. Then, the -old lease database is renamed /var/db/dhcpd.leases~. Finally, the +old lease database is renamed DBDIR/dhcpd.leases~. Finally, the newly written lease database is moved into place. .PP There is a window of vulnerability where if the dhcpd process is killed or the system crashes after the old lease database has been renamed but before the new one has been moved into place, there will -be no /var/db/dhcpd.leases. In this case, dhcpd will refuse to start, +be no DBDIR/dhcpd.leases. In this case, dhcpd will refuse to start, and will require manual intervention. \fBDO NOT\fR simply create a new lease file when this happens - if you do, you will lose all your old bindings, and chaos will ensue. Instead, rename -/var/db/dhcpd.leases~ to /var/db/dhcpd.leases, restoring the old, valid +DBDIR/dhcpd.leases~ to DBDIR/dhcpd.leases, restoring the old, valid lease file, and then start dhcpd. This guarantees that a valid lease file will be restored. .SH FORMAT -The format of the lease declarations is not currently documented. +Lease descriptions are stored in a format that is parsed by the same +recursive descent parser used to read the +.B dhcpd.conf(5) +and +.B dhclient.conf(5) +files. Currently, the only declaration that is +used in the dhcpd.leases file is the +.B lease +declaration. +.PP + \fBlease \fIip-address\fB { \fIstatements...\fB } +.PP +Each lease declaration include the single IP address that has been +leased to the client. The statements within the braces define the +duration of the lease and to whom it is assigned. +.PP +The start and end time of a lease are recorded using the ``starts'' +and ``ends'' statements: +.PP + \fB starts \fIdate\fB;\fR + \fB ends \fIdate\fB;\fR +.PP +Dates are specified as follows: +.PP + \fIweekday year\fB/\fImonth\fB/\fIday +hour\fB:\fIminute\fB:\fIsecond\fR +.PP +The weekday is present to make it easy for a human to tell when a +lease expires - it's specified as a number from zero to six, with zero +being Sunday. The day of week is ignored on input. The year is +specified with the century, so it should generally be four digits +except for really long leases. The month is specified as a number +starting with 1 for January. The day of the month is likewise +specified starting with 1. The hour is a number between 0 and 23, the +minute a number between 0 and 59, and the second also a number between +0 and 59. +.PP +Lease times are specified in Greenwich Mean Time (GMT), not in the +local time zone. Since Greenwich is actually on Daylight Savings +Time part of the year, there is probably nowhere in the world where +the times recorded on a lease are always the same as wall clock times. +On a unix machine, one can often figure out the current time in GMT by +typing \fBdate -u\fR. +.PP +The MAC address of the network interface that was used to acquire the +lease is recorded with the \fBhardware\fR statement: +.PP + \fBhardware \fIhardware-type mac-address\fB;\fR +.PP +The MAC address is specified as a series of hexadecimal octets, +seperated by colons. +.PP +If the client used a client identifier to acquire its address, the +client identifier is recorded using the \fBuid\fR statement: +.PP + \fBuid \fIclient-identifier\fB;\fR +.PP +The client identifier is recorded as a series of hexadecimal octets, +regardless of whether the client specifies an ASCII string or uses the +newer hardware type/MAC address format. +.PP +If the client sends a hostname using the \fIClient Hostname\fR option, +as specified in some versions of the DHCP-DNS Interaction draft, that +hostname is recorded using the \fBclient-hostname\fR statement. +.PP + \fBclient-hostname "\fIhostname\fB";\fR +.PP +If the client sends its hostname using the \fIHostname\fR option, as +Windows 95 does, it is recorded using the \fBhostname\fR statement. +.PP + \fBhostname "\fIhostname\fB";\fR +.PP +The DHCP server may determine that a lease has been misused in some +way, either because a client that has been assigned a lease NAKs it, +or because the server's own attempt to see if an address is in use +prior to reusing it reveals that the address is in fact already in +use. In that case, the \fBabandoned\fR statement will be used to +indicate that the lease should not be reassigned. +.PP + \fBabandoned;\fR +.PP +Abandoned leases are reclaimed automatically. When a client asks for +a new address, and the server finds that there are no new addresses, +it checks to see if there are any abandoned leases, and allocates the +least recently abandoned lease. The standard mechanisms for checking +for lease address conflicts are still followed, so if the abandoned +lease's IP address is still in use, it will be reabandoned. +.PP +If a client \fBrequests\fR an abandoned address, the server assumes +that the reason the address was abandoned was that the lease file was +corrupted, and that the client is the machine that responded when the +lease was probed, causing it to be abandoned. In that case, the +address is immediately assigned to the client. .SH FILES -.B /var/db/dhcpd.leases +.B DBDIR/dhcpd.leases .SH SEE ALSO dhcpd(8), dhcp-options(5), dhcpd.conf(5), RFC2132, RFC2131. .SH AUTHOR -- cgit v1.2.3