diff options
97 files changed, 30022 insertions, 2 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 78476001bee..e18c249624f 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,11 +1,11 @@ -# $OpenBSD: Makefile,v 1.35 1998/04/26 21:49:54 deraadt Exp $ +# $OpenBSD: Makefile,v 1.36 1998/08/18 03:43:20 deraadt Exp $ # not yet done: catman .include <bsd.own.mk> SUBDIR= ac accton adduser amd arp bootpd bootpgw bootpef bootptest \ - chown chroot config cron ctm dev_mkdb \ + chown chroot config cron ctm dev_mkdb dhcp \ edquota gspa httpd inetd iostat \ ipftest ipmon ipsend kgmon \ kvm_mkdb lpr map-mbone mrinfo mopd mrouted mtrace mtree named \ diff --git a/usr.sbin/dhcp/CHANGES b/usr.sbin/dhcp/CHANGES new file mode 100644 index 00000000000..471929701bf --- /dev/null +++ b/usr.sbin/dhcp/CHANGES @@ -0,0 +1,104 @@ +970609 + +- Don't trust hostnames provided by client - Win95 allows *spaces* in + client-supplied hostnames! + +- Be lenient in parsing client-hostname statement in case a bad hostname + got recorded. + +970607 + +- Change size_t to ssize_t in return values where a negative number + is used to indicate an error. + +- Always write out two digits for single-byte quantities in arrays. + +- When parsing a lease database, correctly transfer the client + hostname and hostname to the memory-resident lease structure. + +- If the lease we want to give the client is different than the + one it's asking for, and we recognize the one it's asking for as + ours, NAK it. + +- Only accept a DHCPRELEASE or DHCPNAK if the client supplies an IP + address and the lease corresponding to that address is available to + that client. + +- Make it a warning rather than an error if resolv.conf is missing. + +970605 + +- Add client-hostname token to lexer so that the parser can use it. + Fixes a serious lease database bug. + +- Disable log message on receipt of short ICMP Echo replies. + +970602 + +- Added DHCP Client scripts for FreeBSD, Solaris, and Linux, but + they're not guaranteed to work. + +- Added some Cygwin32 (Windows NT/Windows 95) support, but this is not + sufficiently complete to be useful yet. + +- Updated README + +- Put something useful in TODO - formerly it mostly listed projects + that were way out on the back burner. + +In DHCP Client: + +- Add default, supersede, prepend and append option support, so that a + client can override or modify server-supplied options, and provide + default values if the server provides no values. + +- Add reject keyword, so that packets from rogue DHCP or BOOTP servers + can be rejected out of hand. + +- Added support for booting from BOOTP servers. + +- Added BOOTP flag to client lease declaration, to indicated that a + particular lease was acquired through a BOOTP server. + +- Don't try to do INIT-REBOOT on leases acquired from BOOTP servers. + +- Print server's IP address instead of its IP address when logging + DHCP/BOOTP messages received by client. + +- Fix some bugs in saved lease activation. + +- Fix some scripting bugs. + +- New sample dhclient.conf script demonstrates new features. + +In common code: + +- Partially implemented asynchronous DNS lookups. + +- Fixed some bugs in dispatch routine. + +- Fix date parsing bug that was setting dates forward one day every + time dhcpd was restarted (this has been fixed for a while in the 1.0 + branch). + +- Change name-server option name to ien116-name-server so as to reduce + the potential for confusion. + +DHCP Relay daemon: + +- Fixed an operator precedence bug having to do with the broadcast + flag. + +DHCP Server: + +- Add support to record the client-supplied hostname in the lease file, + for better readability. + +- Fixed a bug in the renewal code that resulted in the server ignoring + unicast renewals from non-local subnets. This bug caused some + heartburn for Win95 machines. + +- Copy ciaddr from saved ciaddr, not from giaddr. + +- New -t flag tests /etc/dhcpd.conf for syntax errors. + diff --git a/usr.sbin/dhcp/Makefile b/usr.sbin/dhcp/Makefile new file mode 100644 index 00000000000..7881c73b478 --- /dev/null +++ b/usr.sbin/dhcp/Makefile @@ -0,0 +1,37 @@ +# Makefile.dist +# +# Copyright (c) 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. +# + +SUBDIR= common server client relay + +all-server all-client all-relay: all-common + +.include <bsd.subdir.mk> diff --git a/usr.sbin/dhcp/Makefile.inc b/usr.sbin/dhcp/Makefile.inc new file mode 100644 index 00000000000..fa8f58505f4 --- /dev/null +++ b/usr.sbin/dhcp/Makefile.inc @@ -0,0 +1,46 @@ +# Makefile.inc +# +# Copyright (c) 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. +# + +.include <bsd.obj.mk> + +WARNS?= 0 + +COBJDIR!=cd $(.CURDIR)/../common; \ + printf "xxx: .MAKE\n\t@echo \$${.OBJDIR}\n" | ${MAKE} -s -f- + +CPPFLAGS+= -I${.CURDIR}/.. -I${.CURDIR}/../includes +LDADD= ${COBJDIR}/libdhcp.a +DPADD= ${COBJDIR}/libdhcp.a + +.if exists(${.CURDIR}/../../Makefile.inc) +.include "${.CURDIR}/../../Makefile.inc" +.endif diff --git a/usr.sbin/dhcp/client/Makefile b/usr.sbin/dhcp/client/Makefile new file mode 100644 index 00000000000..865977b68de --- /dev/null +++ b/usr.sbin/dhcp/client/Makefile @@ -0,0 +1,45 @@ +# Makefile +# +# Copyright (c) 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. +# + +.include <bsd.own.mk> + +SUBDIR= scripts +SRCS = dhclient.c clparse.c +PROG = dhclient +MAN = dhclient.8 dhclient.conf.5 dhclient.leases.5 dhclient-script.8 + +# XXX +BINDIR?= /sbin +LDSTATIC?= -static + +.include <bsd.prog.mk> +.include <bsd.subdir.mk> diff --git a/usr.sbin/dhcp/client/clparse.c b/usr.sbin/dhcp/client/clparse.c new file mode 100644 index 00000000000..9a38e5a0c49 --- /dev/null +++ b/usr.sbin/dhcp/client/clparse.c @@ -0,0 +1,1024 @@ +/* clparse.c + + Parser for dhclient config and lease files... */ + +/* + * 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 <mellon@fugue.com> 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: clparse.c,v 1.1 1998/08/18 03:43:22 deraadt 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; + +/* client-conf-file :== client-declarations EOF + client-declarations :== <nil> + | client-declaration + | client-declarations client-declaration */ + +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); + + /* Set up the initial dhcp option universe. */ + initialize_universes (); + + /* Initialize the top level client configuration. */ + memset (&top_level_config, 0, sizeof top_level_config); + + /* Set some defaults... */ + top_level_config.timeout = 60; + 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.bootp_policy = ACCEPT; + top_level_config.script_name = "/etc/dhclient-script"; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_SUBNET_MASK; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_BROADCAST_ADDRESS; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_TIME_OFFSET; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_ROUTERS; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_DOMAIN_NAME; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_DOMAIN_NAME_SERVERS; + top_level_config.requested_options + [top_level_config.requested_option_count++] = + DHO_HOST_NAME; + requested_lease_time = 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 */ + + /* Set up state and config structures for clients that don't + have per-interface configuration declarations. */ + config = (struct client_config *)0; + for (ip = interfaces; ip; ip = ip -> next) { + if (!ip -> client) { + ip -> client = (struct client_state *) + malloc (sizeof (struct client_state)); + if (!ip -> client) + error ("no memory for client state."); + memset (ip -> client, 0, sizeof *(ip -> client)); + } + if (!ip -> client -> config) { + if (!config) { + config = (struct client_config *) + malloc (sizeof (struct client_config)); + if (!config) + error ("no memory for client config."); + memcpy (config, &top_level_config, + sizeof top_level_config); + } + ip -> client -> config = config; + } + } + + return !warnings_occurred; +} + +/* lease-file :== client-lease-statements EOF + client-lease-statements :== <nil> + | client-lease-statements LEASE client-lease-statement */ + +void read_client_leases () +{ + FILE *cfile; + char *val; + int token; + + new_parse (path_dhclient_db); + + /* Open the lease file. If we can't open it, just return - + we can safely trust the server to remember our state. */ + if ((cfile = fopen (path_dhclient_db, "r")) == NULL) + return; + do { + token = next_token (&val, cfile); + if (token == EOF) + break; + if (token != LEASE) { + warn ("Corrupt lease file - possible data loss!"); + skip_to_semi (cfile); + break; + } else + parse_client_lease_statement (cfile, 0); + + } while (1); +} + +/* client-declaration :== + SEND option-decl | + DEFAULT option-decl | + SUPERSEDE option-decl | + PREPEND option-decl | + APPEND option-decl | + hardware-declaration | + REQUEST option-list | + REQUIRE option-list | + TIMEOUT number | + RETRY number | + REBOOT number | + SELECT_TIMEOUT number | + SCRIPT string | + interface-declaration | + LEASE client-lease-statement | + ALIAS client-lease-statement */ + +void parse_client_statement (cfile, ip, config) + FILE *cfile; + struct interface_info *ip; + struct client_config *config; +{ + int token; + char *val; + struct option *option; + + switch (next_token (&val, cfile)) { + case SEND: + parse_option_decl (cfile, &config -> send_options [0]); + return; + + case DEFAULT: + option = parse_option_decl (cfile, &config -> defaults [0]); + if (option) + config -> default_actions [option -> code] = + ACTION_DEFAULT; + return; + + case SUPERSEDE: + option = parse_option_decl (cfile, &config -> defaults [0]); + if (option) + config -> default_actions [option -> code] = + ACTION_SUPERSEDE; + return; + + case APPEND: + option = parse_option_decl (cfile, &config -> defaults [0]); + if (option) + config -> default_actions [option -> code] = + ACTION_APPEND; + return; + + case PREPEND: + option = parse_option_decl (cfile, &config -> defaults [0]); + if (option) + config -> default_actions [option -> code] = + ACTION_PREPEND; + return; + + case MEDIA: + parse_string_list (cfile, &config -> media, 1); + return; + + case HARDWARE: + if (ip) { + parse_hardware_param (cfile, &ip -> hw_address); + } else { + parse_warn ("hardware address parameter %s", + "not allowed here."); + skip_to_semi (cfile); + } + return; + + case REQUEST: + config -> requested_option_count = + parse_option_list (cfile, config -> requested_options); + return; + + case REQUIRE: + memset (config -> required_options, 0, + sizeof config -> required_options); + parse_option_list (cfile, config -> required_options); + return; + + case TIMEOUT: + parse_lease_time (cfile, &config -> timeout); + return; + + case RETRY: + parse_lease_time (cfile, &config -> retry_interval); + return; + + case SELECT_TIMEOUT: + parse_lease_time (cfile, &config -> select_interval); + return; + + case REBOOT: + parse_lease_time (cfile, &config -> reboot_timeout); + return; + + case BACKOFF_CUTOFF: + parse_lease_time (cfile, &config -> backoff_cutoff); + return; + + case INITIAL_INTERVAL: + parse_lease_time (cfile, &config -> initial_interval); + return; + + case SCRIPT: + config -> script_name = parse_string (cfile); + return; + + case INTERFACE: + if (ip) + parse_warn ("nested interface declaration."); + parse_interface_declaration (cfile, config); + return; + + case LEASE: + parse_client_lease_statement (cfile, 1); + return; + + case ALIAS: + parse_client_lease_statement (cfile, 2); + return; + + case REJECT: + parse_reject_statement (cfile, config); + return; + + default: + parse_warn ("expecting a statement."); + skip_to_semi (cfile); + break; + } + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + } +} + +int parse_X (cfile, buf, max) + FILE *cfile; + u_int8_t *buf; + int max; +{ + int token; + char *val; + int len; + u_int8_t *s; + + token = peek_token (&val, cfile); + if (token == NUMBER_OR_NAME || token == NUMBER) { + len = 0; + do { + token = next_token (&val, cfile); + if (token != NUMBER && token != NUMBER_OR_NAME) { + parse_warn ("expecting hexadecimal constant."); + skip_to_semi (cfile); + return 0; + } + convert_num (&buf [len], val, 16, 8); + if (len++ > max) { + parse_warn ("hexadecimal constant too long."); + skip_to_semi (cfile); + return 0; + } + token = peek_token (&val, cfile); + if (token == COLON) + token = next_token (&val, cfile); + } while (token == COLON); + val = (char *)buf; + } else if (token == STRING) { + token = next_token (&val, cfile); + len = strlen (val); + if (len + 1 > max) { + parse_warn ("string constant too long."); + skip_to_semi (cfile); + return 0; + } + memcpy (buf, val, len + 1); + } else { + parse_warn ("expecting string or hexadecimal data"); + skip_to_semi (cfile); + return 0; + } + return len; +} + +/* option-list :== option_name | + option_list COMMA option_name */ + +int parse_option_list (cfile, list) + FILE *cfile; + u_int8_t *list; +{ + int ix, i; + int token; + char *val; + + ix = 0; + do { + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expected option name."); + skip_to_semi (cfile); + return 0; + } + for (i = 0; i < 256; i++) { + if (!strcasecmp (dhcp_options [i].name, val)) + break; + } + if (i == 256) { + parse_warn ("%s: expected option name."); + skip_to_semi (cfile); + return 0; + } + list [ix++] = i; + if (ix == 256) { + parse_warn ("%s: too many options.", val); + skip_to_semi (cfile); + return 0; + } + token = next_token (&val, cfile); + } while (token == COMMA); + if (token != SEMI) { + parse_warn ("expecting semicolon."); + skip_to_semi (cfile); + return 0; + } + return ix; +} + +/* interface-declaration :== + INTERFACE string LBRACE client-declarations RBRACE */ + +void parse_interface_declaration (cfile, outer_config) + FILE *cfile; + struct client_config *outer_config; +{ + int token; + char *val; + + struct interface_info dummy_interface, *ip; + struct client_state dummy_state; + struct client_config dummy_config; + + token = next_token (&val, cfile); + if (token != STRING) { + parse_warn ("expecting interface name (in quotes)."); + skip_to_semi (cfile); + return; + } + + ip = interface_or_dummy (val); + + if (!ip -> client) + make_client_state (ip); + + if (!ip -> client -> config) + make_client_config (ip, outer_config); + + ip -> flags &= ~INTERFACE_AUTOMATIC; + interfaces_requested = 1; + + token = next_token (&val, cfile); + if (token != LBRACE) { + parse_warn ("expecting left brace."); + skip_to_semi (cfile); + return; + } + + do { + token = peek_token (&val, cfile); + if (token == EOF) { + parse_warn ("unterminated interface declaration."); + return; + } + if (token == RBRACE) + break; + parse_client_statement (cfile, ip, ip -> client -> config); + } while (1); + token = next_token (&val, cfile); +} + +struct interface_info *interface_or_dummy (name) + char *name; +{ + struct interface_info *ip; + + /* Find the interface (if any) that matches the name. */ + for (ip = interfaces; ip; ip = ip -> next) { + if (!strcmp (ip -> name, name)) + break; + } + + /* If it's not a real interface, see if it's on the dummy list. */ + if (!ip) { + for (ip = dummy_interfaces; ip; ip = ip -> next) { + if (!strcmp (ip -> name, name)) + break; + } + } + + /* If we didn't find an interface, make a dummy interface as + a placeholder. */ + if (!ip) { + ip = ((struct interface_info *)malloc (sizeof *ip)); + if (!ip) + error ("Insufficient memory to record interface %s", + name); + memset (ip, 0, sizeof *ip); + strcpy (ip -> name, name); + ip -> next = dummy_interfaces; + dummy_interfaces = ip; + } + return ip; +} + +void make_client_state (ip) + struct interface_info *ip; +{ + ip -> client = + ((struct client_state *)malloc (sizeof *(ip -> client))); + if (!ip -> client) + error ("no memory for state on %s\n", ip -> name); + memset (ip -> client, 0, sizeof *(ip -> client)); +} + +void make_client_config (ip, config) + struct interface_info *ip; + struct client_config *config; +{ + ip -> client -> config = + ((struct client_config *) + malloc (sizeof (struct client_config))); + if (!ip -> client -> config) + error ("no memory for config for %s\n", ip -> name); + memset (ip -> client -> config, 0, + sizeof *(ip -> client -> config)); + memcpy (ip -> client -> config, config, sizeof *config); +} + +/* client-lease-statement :== + RBRACE client-lease-declarations LBRACE + + client-lease-declarations :== + <nil> | + client-lease-declaration | + client-lease-declarations client-lease-declaration */ + + +void parse_client_lease_statement (cfile, is_static) + FILE *cfile; + int is_static; +{ + struct client_lease *lease, *lp, *pl; + struct interface_info *ip; + int token; + char *val; + + token = next_token (&val, cfile); + if (token != LBRACE) { + parse_warn ("expecting left brace."); + skip_to_semi (cfile); + return; + } + + lease = (struct client_lease *)malloc (sizeof (struct client_lease)); + if (!lease) + error ("no memory for lease.\n"); + memset (lease, 0, sizeof *lease); + lease -> is_static = is_static; + + ip = (struct interface_info *)0; + + do { + token = peek_token (&val, cfile); + if (token == EOF) { + parse_warn ("unterminated lease declaration."); + return; + } + if (token == RBRACE) + break; + parse_client_lease_declaration (cfile, lease, &ip); + } while (1); + token = next_token (&val, cfile); + + /* If the lease declaration didn't include an interface + declaration that we recognized, it's of no use to us. */ + if (!ip) { + free_client_lease (lease); + return; + } + + /* Make sure there's a client state structure... */ + if (!ip -> client) + make_client_state (ip); + + /* If this is an alias lease, it doesn't need to be sorted in. */ + if (is_static == 2) { + ip -> client -> alias = lease; + return; + } + + /* The new lease may supersede a lease that's not the + active lease but is still on the lease list, so scan the + lease list looking for a lease with the same address, and + if we find it, toss it. */ + pl = (struct client_lease *)0; + for (lp = ip -> client -> leases; lp; lp = lp -> next) { + if (lp -> address.len == lease -> address.len && + !memcmp (lp -> address.iabuf, lease -> address.iabuf, + lease -> address.len)) { + if (pl) + pl -> next = lp -> next; + else + ip -> client -> leases = lp -> next; + free_client_lease (lp); + break; + } + } + + /* If this is a preloaded lease, just put it on the list of recorded + leases - don't make it the active lease. */ + if (is_static) { + lease -> next = ip -> client -> leases; + ip -> client -> leases = lease; + return; + } + + /* The last lease in the lease file on a particular interface is + the active lease for that interface. Of course, we don't know + what the last lease in the file is until we've parsed the whole + file, so at this point, we assume that the lease we just parsed + is the active lease for its interface. If there's already + an active lease for the interface, and this lease is for the same + ip address, then we just toss the old active lease and replace + it with this one. If this lease is for a different address, + then if the old active lease has expired, we dump it; if not, + we put it on the list of leases for this interface which are + still valid but no longer active. */ + if (ip -> client -> active) { + if (ip -> client -> active -> expiry < cur_time) + free_client_lease (ip -> client -> active); + else if (ip -> client -> active -> address.len == + lease -> address.len && + !memcmp (ip -> client -> active -> address.iabuf, + lease -> address.iabuf, + lease -> address.len)) + free_client_lease (ip -> client -> active); + else { + ip -> client -> active -> next = + ip -> client -> leases; + ip -> client -> leases = ip -> client -> active; + } + } + ip -> client -> active = lease; + + /* phew. */ +} + +/* client-lease-declaration :== + BOOTP | + INTERFACE string | + FIXED_ADDR ip_address | + FILENAME string | + SERVER_NAME string | + OPTION option-decl | + RENEW time-decl | + REBIND time-decl | + EXPIRE time-decl */ + +void parse_client_lease_declaration (cfile, lease, ipp) + FILE *cfile; + struct client_lease *lease; + struct interface_info **ipp; +{ + int token; + char *val; + char *t, *n; + struct interface_info *ip; + + switch (next_token (&val, cfile)) { + case BOOTP: + lease -> is_bootp = 1; + break; + + case INTERFACE: + token = next_token (&val, cfile); + if (token != STRING) { + parse_warn ("expecting interface name (in quotes)."); + skip_to_semi (cfile); + break; + } + ip = interface_or_dummy (val); + *ipp = ip; + break; + + case FIXED_ADDR: + if (!parse_ip_addr (cfile, &lease -> address)) + return; + break; + + case MEDIUM: + parse_string_list (cfile, &lease -> medium, 0); + return; + + case FILENAME: + lease -> filename = parse_string (cfile); + return; + + case SERVER_NAME: + lease -> server_name = parse_string (cfile); + return; + + case RENEW: + lease -> renewal = parse_date (cfile); + return; + + case REBIND: + lease -> rebind = parse_date (cfile); + return; + + case EXPIRE: + lease -> expiry = parse_date (cfile); + return; + + case OPTION: + parse_option_decl (cfile, lease -> options); + return; + + default: + parse_warn ("expecting lease declaration."); + skip_to_semi (cfile); + break; + } + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("expecting semicolon."); + skip_to_semi (cfile); + } +} + +struct option *parse_option_decl (cfile, options) + FILE *cfile; + struct option_data *options; +{ + char *val; + int token; + u_int8_t buf [4]; + u_int8_t hunkbuf [1024]; + int hunkix = 0; + char *vendor; + char *fmt; + struct universe *universe; + struct option *option; + struct iaddr ip_addr; + u_int8_t *dp; + int len; + int nul_term = 0; + + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier after option keyword."); + if (token != SEMI) + skip_to_semi (cfile); + return (struct option *)0; + } + vendor = malloc (strlen (val) + 1); + if (!vendor) + error ("no memory for vendor information."); + strcpy (vendor, val); + token = peek_token (&val, cfile); + if (token == DOT) { + /* Go ahead and take the DOT token... */ + token = next_token (&val, cfile); + + /* The next token should be an identifier... */ + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier after '.'"); + if (token != SEMI) + skip_to_semi (cfile); + return (struct option *)0; + } + + /* Look up the option name hash table for the specified + vendor. */ + universe = (struct universe *)hash_lookup (&universe_hash, + vendor, 0); + /* If it's not there, we can't parse the rest of the + declaration. */ + if (!universe) { + parse_warn ("no vendor named %s.", vendor); + skip_to_semi (cfile); + return (struct option *)0; + } + } else { + /* Use the default hash table, which contains all the + standard dhcp option names. */ + val = vendor; + universe = &dhcp_universe; + } + + /* Look up the actual option info... */ + option = (struct option *)hash_lookup (universe -> hash, val, 0); + + /* If we didn't get an option structure, it's an undefined option. */ + if (!option) { + if (val == vendor) + parse_warn ("no option named %s", val); + else + parse_warn ("no option named %s for vendor %s", + val, vendor); + skip_to_semi (cfile); + return (struct option *)0; + } + + /* Free the initial identifier token. */ + free (vendor); + + /* Parse the option data... */ + do { + /* Set a flag if this is an array of a simple type (i.e., + not an array of pairs of IP addresses, or something + like that. */ + int uniform = option -> format [1] == 'A'; + + for (fmt = option -> format; *fmt; fmt++) { + if (*fmt == 'A') + break; + switch (*fmt) { + case 'X': + len = parse_X (cfile, &hunkbuf [hunkix], + sizeof hunkbuf - hunkix); + hunkix += len; + break; + + case 't': /* Text string... */ + token = next_token (&val, cfile); + if (token != STRING) { + parse_warn ("expecting string."); + skip_to_semi (cfile); + return (struct option *)0; + } + len = strlen (val); + if (hunkix + len + 1 > sizeof hunkbuf) { + parse_warn ("option data buffer %s", + "overflow"); + skip_to_semi (cfile); + return (struct option *)0; + } + memcpy (&hunkbuf [hunkix], val, len + 1); + nul_term = 1; + hunkix += len; + break; + + case 'I': /* IP address. */ + if (!parse_ip_addr (cfile, &ip_addr)) + return (struct option *)0; + len = ip_addr.len; + dp = ip_addr.iabuf; + + alloc: + if (hunkix + len > sizeof hunkbuf) { + parse_warn ("option data buffer %s", + "overflow"); + skip_to_semi (cfile); + return (struct option *)0; + } + memcpy (&hunkbuf [hunkix], dp, len); + hunkix += len; + break; + + case 'L': /* Unsigned 32-bit integer... */ + case 'l': /* Signed 32-bit integer... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + need_number: + parse_warn ("expecting number."); + if (token != SEMI) + skip_to_semi (cfile); + return (struct option *)0; + } + convert_num (buf, val, 0, 32); + len = 4; + dp = buf; + goto alloc; + + case 's': /* Signed 16-bit integer. */ + case 'S': /* Unsigned 16-bit integer. */ + token = next_token (&val, cfile); + if (token != NUMBER) + goto need_number; + convert_num (buf, val, 0, 16); + len = 2; + dp = buf; + goto alloc; + + case 'b': /* Signed 8-bit integer. */ + case 'B': /* Unsigned 8-bit integer. */ + token = next_token (&val, cfile); + if (token != NUMBER) + goto need_number; + convert_num (buf, val, 0, 8); + len = 1; + dp = buf; + goto alloc; + + case 'f': /* Boolean flag. */ + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier."); + bad_flag: + if (token != SEMI) + skip_to_semi (cfile); + return (struct option *)0; + } + if (!strcasecmp (val, "true") + || !strcasecmp (val, "on")) + buf [0] = 1; + else if (!strcasecmp (val, "false") + || !strcasecmp (val, "off")) + buf [0] = 0; + else { + parse_warn ("expecting boolean."); + goto bad_flag; + } + len = 1; + dp = buf; + goto alloc; + + default: + warn ("Bad format %c in parse_option_param.", + *fmt); + skip_to_semi (cfile); + return (struct option *)0; + } + } + token = next_token (&val, cfile); + } while (*fmt == 'A' && token == COMMA); + + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + return (struct option *)0; + } + + options [option -> code].data = + (unsigned char *)malloc (hunkix + nul_term); + if (!options [option -> code].data) + error ("out of memory allocating option data."); + memcpy (options [option -> code].data, hunkbuf, hunkix + nul_term); + options [option -> code].len = hunkix; + return option; +} + +void parse_string_list (cfile, lp, multiple) + FILE *cfile; + struct string_list **lp; + int multiple; +{ + int token; + char *val; + struct string_list *cur, *tmp; + + /* Find the last medium in the media list. */ + if (*lp) { + for (cur = *lp; cur -> next; cur = cur -> next) + ; + } else { + cur = (struct string_list *)0; + } + + do { + token = next_token (&val, cfile); + if (token != STRING) { + parse_warn ("Expecting media options."); + skip_to_semi (cfile); + return; + } + + tmp = (struct string_list *)malloc (strlen (val) + 1 + + sizeof + (struct string_list *)); + if (!tmp) + error ("no memory for string list entry."); + + strcpy (tmp -> string, val); + tmp -> next = (struct string_list *)0; + + /* Store this medium at the end of the media list. */ + if (cur) + cur -> next = tmp; + else + *lp = tmp; + cur = tmp; + + token = next_token (&val, cfile); + } while (multiple && token == COMMA); + + if (token != SEMI) { + parse_warn ("expecting semicolon."); + skip_to_semi (cfile); + } +} + +void parse_reject_statement (cfile, config) + FILE *cfile; + struct client_config *config; +{ + int token; + char *val; + struct iaddr addr; + struct iaddrlist *list; + + do { + if (!parse_ip_addr (cfile, &addr)) { + parse_warn ("expecting IP address."); + skip_to_semi (cfile); + return; + } + + list = (struct iaddrlist *)malloc (sizeof (struct iaddrlist)); + if (!list) + error ("no memory for reject list!"); + + list -> addr = addr; + list -> next = config -> reject_list; + config -> reject_list = list; + + token = next_token (&val, cfile); + } while (token == COMMA); + + if (token != SEMI) { + parse_warn ("expecting semicolon."); + skip_to_semi (cfile); + } +} diff --git a/usr.sbin/dhcp/client/dhclient-script.8 b/usr.sbin/dhcp/client/dhclient-script.8 new file mode 100644 index 00000000000..3bd5b79ba9d --- /dev/null +++ b/usr.sbin/dhcp/client/dhclient-script.8 @@ -0,0 +1,191 @@ +.\" dhclient-script.8 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 +.SH NAME +dhclient-script - DHCP client network configuration script +.SH DESCRIPTION +The DHCP client network configuration script is invoked from time to +time by \fBdhclient(8)\fR. This script is used by the dhcp client to +set each interface's initial configuration prior to requesting an +address, to test the address once it has been offered, and to set the +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. +.SH OPERATION +When dhclient needs to invoke the client configuration script, it +writes a shell script into /tmp which defines a variety of variables. +In all cases, $reason is set to the name of the reason why the script +has been invoked. The following reasons are currently defined: +MEDIUM, PREINIT, ARPCHECK, ARPSEND, BOUND, RENEW, REBIND, REBOOT, +EXPIRE, FAIL and TIMEOUT. +.PP +.SH MEDIUM +The DHCP client is requesting that an interface's media type +be set. The interface name is passed in $interface, and the media +type is passed in $medium. +.SH PREINIT +The DHCP client is requesting that an interface be configured as +required in order to send packets prior to receiving an actual +address. For clients which use the BSD socket library, this means +configuring the interface with an IP address of 0.0.0.0 and a +broadcast address of 255.255.255.255. For other clients, it may be +possible to simply configure the interface up without actually giving +it an IP address at all. The interface name is passed in $interface, +and the media type in $medium. +.PP +If an IP alias has been declared in dhclient.conf, its address will be +passed in $alias_ip_address, and that ip alias should be deleted from +the interface, along with any routes to it. +.SH ARPSEND +The DHCP client is requesting that an address that has been offered to +it be checked to see if somebody else is using it, by sending an ARP +request for that address. It's not clear how to implement this, so +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 +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. +.SH BOUND +The DHCP client has done an initial binding to a new address. The +new ip address is passed in $new_ip_address, and the interface name is +passed in $interface. The media type is passed in $medium. Any +options acquired from the server are passed using the option name +described in \fBdhcp-options\fR, except that dashes ('-') are replaced +by underscores ('_') in order to make valid shell variables, and the +variable names start with new_. So for example, the new subnet mask +would be passed in $new_subnet_mask. +.PP +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, +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 +IP address will be written as $alias_ip_address, and other DHCP +options that are set for the alias (e.g., subnet mask) will be passed +in variables named as described previously except starting with +$alias_ instead of $new_. Care should be taken that the alias IP +address not be used if it is identical to the bound IP address +($new_ip_address), since the other alias parameters may be incorrect +in this case. +.SH RENEW +When a binding has been renewed, the script is called as in BOUND, +except that in addition to all the variables starting with $new_, +there is another set of variables starting with $old_. Persistent +settings that may have changed need to be deleted - for example, if a +local route to the bound address is being configured, the old local +route should be deleted. If the default route has changed, the old default +route should be deleted. If the static routes have changed, the old +ones should be deleted. Otherwise, processing can be done as with +BOUND. +.SH REBIND +The DHCP client has rebound to a new DHCP server. This can be handled +as with RENEW, except that if the IP address has changed, the ARP +table should be cleared. +.SH REBOOT +The DHCP client has successfully reacquired its old address after a +reboot. This can be processed as with BOUND. +.SH EXPIRE +The DHCP client has failed to renew its lease or acquire a new one, +and the lease has expired. The IP address must be relinquished, and +all related parameters should be deleted, as in RENEW and REBIND. +.SH FAIL +The DHCP client has been unable to contact any DHCP servers, and any +leases that have been tested have not proved to be valid. The +parameters from the last lease tested should be deconfigured. This +can be handled in the same way as EXPIRE. +.SH TIMEOUT +The DHCP client has been unable to contact any DHCP servers. +However, an old lease has been identified, and its parameters have +been passed in as with BOUND. The client configuration script should +test these parameters and, if it has reason to believe they are valid, +should exit with a value of zero. If not, it should exit with a +nonzero value. +.PP +The usual way to test a lease is to set up the network as with REBIND +(since this may be called to test more than one lease) and then ping +the first router defined in $routers. If a response is received, the +lease must be valid for the network to which the interface is +currently connected. It would be more complete to try to ping all of +the routers listed in $new_routers, as well as those listed in +$new_static_routes, but current scripts do not do this. +.SH FILES +Each operating system should generally have its own script file, +although the script files for similar operating systems may be similar +or even identical. The script files included in the Internet +Software Consortium DHCP distribution appear in the distribution tree +under client/scripts, and bear the names of the operating systems on +which they are intended to work. +.SH BUGS +If more than one interface is being used, there's no obvious way to +avoid clashes between server-supplied configuration parameters - for +example, the stock dhclient-script rewrites /etc/resolv.conf. If +more than one interface is being configured, /etc/resolv.conf will be +repeatedly initialized to the values provided by one server, and then +the other. Assuming the information provided by both servers is +valid, this shouldn't cause any real problems, but it could be +confusing. +.SH SEE ALSO +dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and +dhclient.leases(5). +.SH AUTHOR +.B dhclient-script(8) +has been written for the Internet Software Consortium +by Ted Lemon <mellon@fugue.com> in cooperation with Vixie +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. diff --git a/usr.sbin/dhcp/client/dhclient.8 b/usr.sbin/dhcp/client/dhclient.8 new file mode 100644 index 00000000000..3a1702f5d54 --- /dev/null +++ b/usr.sbin/dhcp/client/dhclient.8 @@ -0,0 +1,168 @@ +.\" dhclient.8 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 +.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 SYSTEM REQUIREMENTS +You must have the Berkeley +Packet Filter (bpf) configured in your NetBSD 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 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 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, 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, 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 +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 +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, 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 +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 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. +.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 /etc/dhclient.conf, /var/db/dhclient.leases, /var/run/dhclient.pid, +.B /var/db/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 <mellon@fugue.com> in cooperation with Vixie +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 +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 +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/client/dhclient.c b/usr.sbin/dhcp/client/dhclient.c new file mode 100644 index 00000000000..3611d379cbd --- /dev/null +++ b/usr.sbin/dhcp/client/dhclient.c @@ -0,0 +1,2056 @@ +/* dhclient.c + + DHCP Client. */ + +/* + * 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 <mellon@fugue.com> 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''. + * + * This client was substantially modified and enhanced by Elliot Poger + * for use on Linux while he was working on the MosquitoNet project at + * Stanford. + * + * 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 + * 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. + */ + +#ifndef lint +static char copyright[] = +"$Id: dhclient.c,v 1.1 1998/08/18 03:43:23 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" + +TIME cur_time; +TIME default_lease_time = 43200; /* 12 hours... */ +TIME max_lease_time = 86400; /* 24 hours... */ +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; + +int log_perror = 1; + +struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; +struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } }; +struct in_addr inaddr_any; +struct sockaddr_in sockaddr_broadcast; + +/* ASSERT_STATE() does nothing now; it used to be + 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 save_scripts; + +static void usage PROTO ((void)); + +int main (argc, argv, envp) + int argc; + char **argv, **envp; +{ + int i; + struct servent *ent; + struct interface_info *ip; + int seed; + +#ifdef SYSLOG_4_2 + openlog ("dhclient", LOG_NDELAY); + log_priority = LOG_DAEMON; +#else + openlog ("dhclient", LOG_NDELAY, LOG_DAEMON); +#endif + +#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)); + } else if (!strcmp (argv [i], "-d")) { + no_daemon = 1; + } else if (!strcmp (argv [i], "-D")) { + save_scripts = 1; + } else if (argv [i][0] == '-') { + usage (); + } else { + struct interface_info *tmp = + ((struct interface_info *) + dmalloc (sizeof *tmp, "specified_interface")); + if (!tmp) + error ("Insufficient memory to %s %s", + "record interface", argv [i]); + memset (tmp, 0, sizeof *tmp); + strcpy (tmp -> name, argv [i]); + tmp -> next = interfaces; + tmp -> flags = INTERFACE_REQUESTED; + interfaces_requested = 1; + interfaces = tmp; + } + } + /* Default to the DHCP/BOOTP port. */ + if (!local_port) { + ent = getservbyname ("dhcpc", "udp"); + if (!ent) + local_port = htons (68); + else + local_port = ent -> s_port; +#ifndef __CYGWIN32__ + endservent (); +#endif + } + remote_port = htons (ntohs (local_port) - 1); /* XXX */ + + /* Get the current 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); + + /* Parse the dhclient.conf file. */ + read_client_conf (); + + /* Parse the lease database. */ + read_client_leases (); + + /* Rewrite the lease database... */ + rewrite_client_leases (); + + /* If no broadcast interfaces were discovered, call the script + and tell it so. */ + if (!interfaces) { + script_init ((struct interface_info *)0, "NBI", + (struct string_list *)0); + script_go ((struct interface_info *)0); + + /* Nothing more to do. */ + 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); + } + } + } + + /* At this point, all the interfaces that the script thinks + 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_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); + } + + /* Set up the bootp packet handler... */ + bootp_packet_handler = do_packet; + + /* Start dispatching packets and timeouts... */ + dispatch (); + + /*NOTREACHED*/ + return 0; +} + +static void usage () +{ + error ("Usage: dhclient [-c] [-p <port>] [interface]"); +} + +void cleanup () +{ +} + +/* 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 + * + * Return conditions as handled by dhclient_state_machine(): + * Returns 1, sendpacket_flag = 1: send packet, reset timer. + * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone). + * Returns 0: finish the nap which was interrupted for no good reason. + * + * Several per-interface variables are used to keep track of the process: + * active_lease: the lease that is being used on the interface + * (null pointer if not configured yet). + * offered_leases: leases corresponding to DHCPOFFER messages that have + * been sent to us by DHCP servers. + * acked_leases: leases corresponding to DHCPACK messages that have been + * sent to us by DHCP servers. + * sendpacket: DHCP packet we're trying to send. + * destination: IP address to send sendpacket to + * In addition, there are several relevant per-lease variables. + * T1_expiry, T2_expiry, lease_expiry: lease milestones + * In the active lease, these control the process of renewing the lease; + * In leases on the acked_leases list, this simply determines when we + * can no longer legitimately use the lease. + */ + +void state_reboot (ipp) + void *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) { + state_init (ip); + return; + } + + /* We are in the rebooting state. */ + ip -> client -> state = S_REBOOTING; + + /* 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; + + /* Zap the medium list... */ + ip -> client -> medium = (struct string_list *)0; + + /* Send out the first DHCPREQUEST packet. */ + send_request (ip); +} + +/* Called when a lease has completely expired and we've been unable to + renew it. */ + +void state_init (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + ASSERT_STATE(state, S_INIT); + + /* 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; + + /* Add an immediate timeout to cause the first DHCPDISCOVER packet + to go out. */ + send_discover (ip); +} + +/* state_selecting is called when one or more DHCPOFFER packets have been + received and a configurable period of time has passed. */ + +void state_selecting (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + struct client_lease *lp, *next, *picked; + + ASSERT_STATE(state, S_SELECTING); + + /* Cancel state_selecting and send_discover timeouts, since either + one could have got us here. */ + cancel_timeout (state_selecting, ip); + cancel_timeout (send_discover, ip); + + /* We have received one or more DHCPOFFER packets. Currently, + 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; + + /* Check to see if we got an ARPREPLY for the address + in this particular lease. */ + if (!picked) { + script_init (ip, "ARPCHECK", lp -> medium); + script_write_params (ip, "check_", lp); + + /* If the ARPCHECK code detects another + machine using the offered address, it exits + nonzero. We need to send a DHCPDECLINE and + toss the lease. */ + if (script_go (ip)) { + make_decline (ip, lp); + send_decline (ip); + goto freeit; + } + picked = lp; + picked -> next = (struct client_lease *)0; + } else { + freeit: + free_client_lease (lp); + } + } + 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; + 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; + + /* 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 -> state = S_REQUESTING; + + /* Bind to the address we received. */ + bind_lease (ip); + return; + } + + /* 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; + + /* Make a DHCPREQUEST packet from the lease we picked. */ + make_request (ip, picked); + ip -> client -> xid = ip -> client -> packet.xid; + + /* Toss the lease we picked - we'll get it back in a DHCPACK. */ + free_client_lease (picked); + + /* Add an immediate timeout to send the first DHCPREQUEST packet. */ + send_request (ip); +} + +/* state_requesting is called when we receive a DHCPACK message after + having sent out one or more DHCPREQUEST packets. */ + +void dhcpack (packet) + struct packet *packet; +{ + 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) { + debug ("DHCPACK in wrong transaction."); + return; + } + + if (ip -> client -> state != S_REBOOTING && + ip -> client -> state != S_REQUESTING && + ip -> client -> state != S_RENEWING && + ip -> client -> state != S_REBINDING) { + debug ("DHCPACK in wrong state."); + return; + } + + note ("DHCPACK from %s", piaddr (packet -> client_addr)); + + lease = packet_to_lease (packet); + if (!lease) { + note ("packet_to_lease failed."); + return; + } + + ip -> client -> new = lease; + + /* Stop resending DHCPREQUEST. */ + cancel_timeout (send_request, ip); + + /* Figure out the lease time. */ + ip -> client -> new -> expiry = + getULong (ip -> client -> + new -> options [DHO_DHCP_LEASE_TIME].data); + + /* 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); + else + 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 -> + 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; + + bind_lease (ip); +} + +void bind_lease (ip) + struct interface_info *ip; +{ + /* Remember the medium. */ + ip -> client -> new -> medium = ip -> client -> medium; + + /* Write out the new lease. */ + write_client_lease (ip, ip -> client -> new); + + /* Run the client script with the new parameters. */ + script_init (ip, (ip -> client -> state == S_REQUESTING + ? "BOUND" + : (ip -> client -> state == S_RENEWING + ? "RENEW" + : (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); + 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; + + /* Set up a timeout to start the renewal process. */ + 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; + reinitialize_interfaces (); + go_daemon (); +} + +/* state_bound is called when we've successfully bound to a particular + lease, but the renewal time on that lease has expired. We are + expected to unicast a DHCPREQUEST to the server that gave us our + original lease. */ + +void state_bound (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + ASSERT_STATE(state, S_BOUND); + + /* T1 has expired. */ + make_request (ip, ip -> client -> active); + ip -> client -> xid = ip -> client -> packet.xid; + + if (ip -> client -> active -> + options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) { + memcpy (ip -> client -> destination.iabuf, + ip -> client -> active -> + options [DHO_DHCP_SERVER_IDENTIFIER].data, 4); + ip -> client -> destination.len = 4; + } else + ip -> client -> destination = iaddr_broadcast; + + 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); +} + +int commit_leases () +{ + return 0; +} + +int write_lease (lease) + struct lease *lease; +{ + return 0; +} + +void db_startup () +{ +} + +void bootp (packet) + struct packet *packet; +{ + struct iaddrlist *ap; + + 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)) { + note ("BOOTREPLY from %s rejected.", + piaddr (ap -> addr)); + return; + } + } + + dhcpoffer (packet); + +} + +void dhcp (packet) + struct packet *packet; +{ + struct iaddrlist *ap; + void (*handler) PROTO ((struct packet *)); + char *type; + + switch (packet -> packet_type) { + case DHCPOFFER: + handler = dhcpoffer; + type = "DHCPOFFER"; + break; + + case DHCPNAK: + handler = dhcpnak; + type = "DHCPNACK"; + break; + + case DHCPACK: + handler = dhcpack; + type = "DHCPACK"; + break; + + default: + 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)) { + note ("%s from %s rejected.", + type, piaddr (ap -> addr)); + return; + } + } + (*handler) (packet); +} + +void dhcpoffer (packet) + struct packet *packet; +{ + 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 + ? "DHCPOFFER" : "BOOTREPLY"); + struct iaddrlist *ap; + +#ifdef DEBUG_PACKET + dump_packet (packet); +#endif + + /* 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) { + debug ("%s in wrong transaction.", name); + return; + } + + 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 -> + required_options [i]].len) { + note ("%s isn't satisfactory.", name); + return; + } + } + + /* 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)) { + debug ("%s already seen.", name); + return; + } + } + + lease = packet_to_lease (packet); + if (!lease) { + note ("packet_to_lease failed."); + return; + } + + /* If this lease was acquired through a BOOTREPLY, record that + fact. */ + 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; + + /* Send out an ARP Request for the offered IP address. */ + 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. */ + if (script_go (ip)) + arp_timeout_needed = 0; + else + arp_timeout_needed = 2; + + /* Figure out when we're supposed to stop selecting. */ + 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; + } 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 && + (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; + else { + for (lp = ip -> client -> offered_leases; lp -> next; + lp = lp -> next) + ; + lp -> next = lease; + } + } + + /* If we're supposed to stop selecting before we've had time + to wait for the ARPREPLY, add some delay to wait for + the ARPREPLY. */ + if (stop_selecting - cur_time < arp_timeout_needed) + stop_selecting = cur_time + arp_timeout_needed; + + /* If the selecting interval has expired, go immediately to + state_selecting(). Otherwise, time out into + state_selecting at the select interval. */ + if (stop_selecting <= 0) + state_selecting (ip); + else { + add_timeout (stop_selecting, state_selecting, ip); + cancel_timeout (send_discover, ip); + } +} + +/* Allocate a client_lease structure and initialize it from the parameters + in the specified packet. */ + +struct client_lease *packet_to_lease (packet) + struct packet *packet; +{ + struct client_lease *lease; + int i; + + lease = (struct client_lease *)malloc (sizeof (struct client_lease)); + + if (!lease) { + warn ("dhcpoffer: no memory to record lease.\n"); + return (struct client_lease *)0; + } + + memset (lease, 0, sizeof *lease); + + /* Copy the lease options. */ + for (i = 0; i < 256; i++) { + if (packet -> options [i].len) { + lease -> options [i].data = + (unsigned char *) + 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; + } + } + } + + 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]) { + int len; + /* Don't count on the NUL terminator. */ + for (len = 0; len < 64; len++) + if (!packet -> raw -> sname [len]) + break; + lease -> server_name = malloc (len + 1); + if (!lease -> server_name) { + warn ("dhcpoffer: no memory for filename.\n"); + free_client_lease (lease); + return (struct client_lease *)0; + } else { + memcpy (lease -> server_name, + packet -> raw -> sname, len); + lease -> server_name [len] = 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]) { + int len; + /* Don't count on the NUL terminator. */ + for (len = 0; len < 64; len++) + if (!packet -> raw -> file [len]) + break; + lease -> filename = malloc (len + 1); + if (!lease -> filename) { + warn ("dhcpoffer: no memory for filename.\n"); + free_client_lease (lease); + return (struct client_lease *)0; + } else { + memcpy (lease -> filename, + packet -> raw -> file, len); + lease -> filename [len] = 0; + } + } + return lease; +} + +void dhcpnak (packet) + struct packet *packet; +{ + 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) { + debug ("DHCPNAK in wrong transaction."); + return; + } + + if (ip -> client -> state != S_REBOOTING && + ip -> client -> state != S_REQUESTING && + ip -> client -> state != S_RENEWING && + ip -> client -> state != S_REBINDING) { + debug ("DHCPNAK in wrong state."); + return; + } + + note ("DHCPNAK from %s", piaddr (packet -> client_addr)); + + 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; + + /* Stop sending DHCPREQUEST packets... */ + cancel_timeout (send_request, ip); + + ip -> client -> state = S_INIT; + state_init (ip); +} + +/* Send out a DHCPDISCOVER packet, and set a timeout to send out another + one after the right interval has expired. If we don't get an offer by + the time we reach the panic interval, call the panic function. */ + +void send_discover (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + int result; + int interval; + int increase = 1; + + /* Figure out how long it's been since we started transmitting. */ + 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) { + state_panic (ip); + return; + } + + /* 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) { + int fail = 0; + again: + if (ip -> client -> medium) { + ip -> client -> medium = + ip -> client -> medium -> next; + increase = 0; + } + if (!ip -> client -> medium) { + if (fail) + error ("No valid media types for %s!", + 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); + if (script_go (ip)) { + goto again; + } + } + + /* If we're supposed to increase the interval, do so. If it's + currently zero (i.e., we haven't sent any packets yet), set + it to one; otherwise, add to it a random number between + 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; + else { + 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) + + ((random () >> 2) + % ip -> client -> interval)); + } 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; + + /* Record the number of seconds since we started sending. */ + if (interval < 255) + ip -> client -> packet.secs = interval; + else + ip -> client -> packet.secs = 255; + + note ("DHCPDISCOVER on %s to %s port %d interval %ld", + ip -> name, + inet_ntoa (sockaddr_broadcast.sin_addr), + 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, + inaddr_any, &sockaddr_broadcast, + (struct hardware *)0); + if (result < 0) + warn ("send_packet: %m"); + + add_timeout (cur_time + ip -> client -> interval, send_discover, ip); +} + +/* state_panic gets called if we haven't received any offers in a preset + amount of time. When this happens, we try to use existing leases that + haven't yet expired, and failing that, we call the client script and + hope it can do something. */ + +void state_panic (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + 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) + 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) { + note ("Trying recorded lease %s", + piaddr (ip -> client -> active -> address)); + /* Run the client script with the existing + parameters. */ + script_init (ip, "TIMEOUT", + ip -> client -> active -> medium); + script_write_params (ip, "new_", + ip -> client -> active); + if (ip -> client -> alias) + script_write_params (ip, "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; + note ("bound: renewal in %d seconds.", + ip -> client -> active -> renewal + - cur_time); + add_timeout ((ip -> client -> + active -> renewal), + state_bound, ip); + } else { + ip -> client -> state = S_BOUND; + note ("bound: immediate renewal."); + state_bound (ip); + } + reinitialize_interfaces (); + go_daemon (); + return; + } + } + + /* 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; + 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) + ; + 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; + + /* 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) + break; + else if (!loop) + loop = ip -> client -> active; + } + + /* No leases were available, or what was available didn't work, so + tell the shell script that we failed to allocate an address, + and try again later. */ + 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); + script_go (ip); + ip -> client -> state = S_INIT; + add_timeout (cur_time + ip -> client -> config -> retry_interval, + state_init, ip); + go_daemon (); +} + +void send_request (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + int result; + int interval; + struct sockaddr_in destination; + struct in_addr from; + + /* Figure out how long it's been since we started transmitting. */ + 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 + DISCOVER an address... */ + /* XXX In the INIT-REBOOT state, if we don't get an ACK, it + means either that we're on a network with no DHCP server, + or that our server is down. In the latter case, assuming + that there is a backup DHCP server, DHCPDISCOVER will get + 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) { + cancel: + ip -> client -> state = S_INIT; + cancel_timeout (send_request, ip); + state_init (ip); + return; + } + + /* 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 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; + } + + /* 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) { + /* 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, "alias_", + ip -> client -> alias); + script_go (ip); + + 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; + else { + 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) + + ((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 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) + destination.sin_addr.s_addr = INADDR_BROADCAST; + else + memcpy (&destination.sin_addr.s_addr, + 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, + 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; + + 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); + else +#endif /* USE_FALLBACK */ + /* Send out a packet. */ + result = send_packet (ip, (struct packet *)0, + &ip -> client -> packet, + ip -> client -> packet_length, + from, &destination, + (struct hardware *)0); + + if (result < 0) + warn ("send_packet: %m"); + + add_timeout (cur_time + ip -> client -> interval, + send_request, ip); +} + +void send_decline (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + int result; + + 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, + inaddr_any, &sockaddr_broadcast, + (struct hardware *)0); + if (result < 0) + warn ("send_packet: %m"); +} + +void send_release (ipp) + void *ipp; +{ + struct interface_info *ip = ipp; + + int result; + + 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, + inaddr_any, &sockaddr_broadcast, + (struct hardware *)0); + if (result < 0) + warn ("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; + + struct tree_cache *options [256]; + struct tree_cache option_elements [256]; + + memset (option_elements, 0, sizeof option_elements); + memset (options, 0, sizeof options); + 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; + + /* 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; + + /* If we had an address, try to get it again. */ + if (lease) { + 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; + } else { + 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) { + options [i] = &option_elements [i]; + options [i] -> value = ip -> client -> config -> + send_options [i].data; + options [i] -> len = ip -> client -> config -> + send_options [i].len; + options [i] -> buf_size = ip -> client -> config -> + send_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 = random (); + ip -> client -> packet.secs = 0; /* filled in by send_discover. */ + ip -> client -> packet.flags = htons (BOOTP_BROADCAST); /* XXX */ + 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); +#endif +} + + +void make_request (ip, lease) + struct interface_info *ip; + struct client_lease *lease; +{ + unsigned char request = DHCPREQUEST; + int i; + + struct tree_cache *options [256]; + struct tree_cache option_elements [256]; + + memset (options, 0, sizeof options); + 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; + + /* 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; + + /* 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) { + /* 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; + 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; + } else { + 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) { + options [i] = &option_elements [i]; + options [i] -> value = ip -> client -> config -> + send_options [i].data; + options [i] -> len = ip -> client -> config -> + send_options [i].len; + options [i] -> buf_size = ip -> client -> config -> + send_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 = ip -> client -> xid; + ip -> client -> packet.secs = 0; /* Filled in by send_request. */ + ip -> client -> packet.flags = htons (BOOTP_BROADCAST); + + /* 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); + +#ifdef DEBUG_PACKET + dump_packet (sendpkt); + dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); +#endif +} + +void make_decline (ip, lease) + struct interface_info *ip; + struct client_lease *lease; +{ + unsigned char decline = DHCPDECLINE; + int i; + + struct tree_cache *options [256]; + struct tree_cache message_type_tree; + struct tree_cache requested_address_tree; + struct tree_cache server_id_tree; + struct tree_cache client_id_tree; + + memset (options, 0, sizeof options); + 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; + + /* 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; + + /* 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; + + /* Send the uid if the user supplied one. */ + i = DHO_DHCP_CLIENT_IDENTIFIER; + if (ip -> client -> config -> send_options [i].len) { + options [i] = &client_id_tree; + options [i] -> value = ip -> client -> config -> + send_options [i].data; + options [i] -> len = ip -> client -> config -> + send_options [i].len; + options [i] -> buf_size = ip -> client -> config -> + send_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 = ip -> client -> xid; + ip -> client -> packet.secs = 0; /* Filled in by send_request. */ + ip -> client -> packet.flags = htons (BOOTP_BROADCAST); + + /* 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); + +#ifdef DEBUG_PACKET + dump_packet (sendpkt); + dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); +#endif +} + +void make_release (ip, lease) + struct interface_info *ip; + struct client_lease *lease; +{ + unsigned char request = DHCPRELEASE; + int i; + + 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)); + + /* 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; + + /* 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; + + /* 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 -> packet.xid; + 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); + +#ifdef DEBUG_PACKET + dump_packet (sendpkt); + dump_raw ((unsigned char *)ip -> client -> packet, + ip -> client -> packet_length); +#endif +} + +void free_client_lease (lease) + struct client_lease *lease; +{ + int i; + + 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); + } + free (lease); +} + +FILE *leaseFile; + +void rewrite_client_leases () +{ + struct interface_info *ip; + struct client_lease *lp; + + if (leaseFile) + fclose (leaseFile); + leaseFile = fopen (path_dhclient_db, "w"); + if (!leaseFile) + error ("can't create /var/db/dhclient.leases: %m"); + + /* 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); + } + if (ip -> client -> active) + write_client_lease (ip, ip -> client -> active); + } + + /* 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); + } + if (ip -> client -> active) + write_client_lease (ip, ip -> client -> active); + } + fflush (leaseFile); +} + +void write_client_lease (ip, lease) + struct interface_info *ip; + struct client_lease *lease; +{ + int i; + struct tm *t; + + /* If the lease came from the config file, we don't need to stash + a copy in the lease database. */ + if (lease -> is_static) + return; + + if (!leaseFile) { /* XXX */ + leaseFile = fopen (path_dhclient_db, "w"); + if (!leaseFile) + error ("can't create /var/db/dhclient.leases: %m"); + } + + fprintf (leaseFile, "lease {\n"); + if (lease -> is_bootp) + fprintf (leaseFile, " bootp;\n"); + fprintf (leaseFile, " interface \"%s\";\n", ip -> name); + fprintf (leaseFile, " fixed-address %s;\n", + piaddr (lease -> address)); + if (lease -> filename) + fprintf (leaseFile, " filename \"%s\";\n", + lease -> filename); + if (lease -> server_name) + fprintf (leaseFile, " server-name \"%s\";\n", + lease -> filename); + if (lease -> medium) + fprintf (leaseFile, " medium \"%s\";\n", + lease -> medium -> string); + for (i = 0; i < 256; i++) { + 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)); + } + } + 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); + 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); + 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); + fprintf (leaseFile, "}\n"); + fflush (leaseFile); +} + +/* 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 scriptName [256]; +FILE *scriptFile; + +void script_init (ip, reason, medium) + struct interface_info *ip; + char *reason; + struct string_list *medium; +{ + int fd; +#ifndef HAVE_MKSTEMP + + do { +#endif + strcpy (scriptName, "/tmp/dcsXXXXXX"); +#ifdef HAVE_MKSTEMP + fd = mkstemp (scriptName); +#else + mktemp (scriptName); + fd = creat (scriptName, 0600); + } while (fd < 0); +#endif + + scriptFile = fdopen (fd, "w"); + if (!scriptFile) + error ("can't write script file: %m"); + fprintf (scriptFile, "#!/bin/sh\n\n"); + if (ip) { + fprintf (scriptFile, "interface=\"%s\"\n", ip -> name); + fprintf (scriptFile, "export interface\n"); + } + if (medium) { + fprintf (scriptFile, "medium=\"%s\"\n", medium -> string); + fprintf (scriptFile, "export medium\n"); + } + fprintf (scriptFile, "reason=\"%s\"\n", reason); + fprintf (scriptFile, "export reason\n"); +} + +void script_write_params (ip, prefix, lease) + struct interface_info *ip; + char *prefix; + struct client_lease *lease; +{ + int i; + u_int8_t dbuf [1500]; + int len; + + fprintf (scriptFile, "%sip_address=\"%s\"\n", + prefix, piaddr (lease -> address)); + fprintf (scriptFile, "export %sip_address\n", prefix); + + /* For the benefit of Linux (and operating systems which may + have similar needs), compute the network address based on + the supplied ip address and netmask, if provided. Also + compute the broadcast address (the host address all ones + 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)) { + 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); + if (subnet.len) { + fprintf (scriptFile, "%snetwork_number=\"%s\";\n", + prefix, piaddr (subnet)); + fprintf (scriptFile, "export %snetwork_number\n", + prefix); + + if (!lease -> options [DHO_BROADCAST_ADDRESS].len) { + broadcast = broadcast_addr (subnet, netmask); + if (broadcast.len) { + fprintf (scriptFile, + "%s%s=\"%s\";\n", prefix, + "broadcast_address", + piaddr (broadcast)); + fprintf (scriptFile, + "export %s%s\n", prefix, + "broadcast_address"); + } + } + } + } + + if (lease -> filename) { + fprintf (scriptFile, "%sfilename=\"%s\";\n", + prefix, lease -> filename); + fprintf (scriptFile, "export %sfilename\n", prefix); + } + if (lease -> server_name) { + fprintf (scriptFile, "%sserver_name=\"%s\";\n", + prefix, lease -> server_name); + fprintf (scriptFile, "export %sserver_name\n", prefix); + } + 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]) { + case ACTION_DEFAULT: + 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; + break; + case ACTION_PREPEND: + len = (ip -> client -> + config -> defaults [i].len + + lease -> options [i].len); + if (len > sizeof dbuf) { + warn ("no space to %s %s", + "prepend option", + dhcp_options [i].name); + goto supersede; + } + 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); + break; + case ACTION_APPEND: + len = (ip -> client -> + config -> defaults [i].len + + lease -> options [i].len); + if (len > sizeof dbuf) { + warn ("no space to %s %s", + "prepend option", + dhcp_options [i].name); + goto supersede; + } + 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); + } + } else { + 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 { + len = 0; + } + if (len) { + char *s = dhcp_option_ev_name (&dhcp_options [i]); + + fprintf (scriptFile, "%s%s=\"%s\"\n", prefix, s, + pretty_print_option (i, dp, len, 0, 0)); + fprintf (scriptFile, "export %s%s\n", prefix, s); + } + } + fprintf (scriptFile, "%sexpiry=\"%d\"\n", + prefix, (int)lease -> expiry); /* XXX */ + fprintf (scriptFile, "export %sexpiry\n", prefix); +} + +int script_go (ip) + struct interface_info *ip; +{ + int rval; + + if (ip) + fprintf (scriptFile, "%s\n", + ip -> client -> config -> script_name); + else + fprintf (scriptFile, "%s\n", + top_level_config.script_name); + fprintf (scriptFile, "exit $?\n"); + fclose (scriptFile); + chmod (scriptName, 0700); + rval = system (scriptName); + if (!save_scripts) + unlink (scriptName); + return rval; +} + +char *dhcp_option_ev_name (option) + 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] = '_'; + else + evbuf [i] = option -> name [i]; + } + + evbuf [i] = 0; + return evbuf; +} + +void go_daemon () +{ + static int state = 0; + int pid; + + /* Don't become a daemon if the user requested otherwise. */ + if (no_daemon) { + write_client_pid_file (); + return; + } + + /* Only do it once. */ + if (state) + return; + state = 1; + + /* Stop logging to stderr... */ + log_perror = 0; + + /* Become a daemon... */ + if ((pid = fork ()) < 0) + error ("Can't fork daemon: %m"); + else if (pid) + exit (0); + /* Become session leader and get pid... */ + pid = setsid (); + + 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); + } +} diff --git a/usr.sbin/dhcp/client/dhclient.conf b/usr.sbin/dhcp/client/dhclient.conf new file mode 100644 index 00000000000..147e0045a5d --- /dev/null +++ b/usr.sbin/dhcp/client/dhclient.conf @@ -0,0 +1,36 @@ +send host-name "andare.fugue.com"; +send dhcp-client-identifier 1:0:a0:24:ab:fb:9c; +send dhcp-lease-time 3600; +supersede domain-name "fugue.com home.vix.com"; +prepend domain-name-servers 127.0.0.1; +request subnet-mask, broadcast-address, time-offset, routers, + domain-name, domain-name-servers, host-name; +require subnet-mask, domain-name-servers; +timeout 60; +retry 60; +reboot 10; +select-timeout 5; +initial-interval 2; +script "/etc/dhclient-script"; +media "-link0 -link1 -link2", "link0 link1"; +reject 192.33.137.209; + +alias { + interface "ep0"; + fixed-address 192.5.5.213; + option subnet-mask 255.255.255.255; +} + +lease { + interface "ep0"; + fixed-address 192.33.137.200; + medium "link0 link1"; + option host-name "andare.swiftmedia.com"; + option subnet-mask 255.255.255.0; + option broadcast-address 192.33.137.255; + option routers 192.33.137.250; + option domain-name-servers 127.0.0.1; + renew 2 2000/1/12 00:00:01; + rebind 2 2000/1/12 00:00:01; + expire 2 2000/1/12 00:00:01; +} diff --git a/usr.sbin/dhcp/client/dhclient.conf.5 b/usr.sbin/dhcp/client/dhclient.conf.5 new file mode 100644 index 00000000000..c5af648cf91 --- /dev/null +++ b/usr.sbin/dhcp/client/dhclient.conf.5 @@ -0,0 +1,543 @@ +.\" dhclient.conf.5 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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.conf 5 +.SH NAME +dhclient.conf - DHCP client configuration file +.SH DESCRIPTION +The dhclient.conf file contains configuration information for +.IR dhclient, +the Internet Software Consortium DHCP Client. +.PP +The dhclient.conf file is a free-form ASCII text file. It is parsed by +the recursive-descent parser built into dhclient. The file may contain +extra tabs and newlines for formatting purposes. Keywords in the file +are case-insensitive. Comments may be placed anywhere within the +file (except within quotes). Comments begin with the # character and +end at the end of the line. +.PP +The dhclient.conf file can be used to configure the behaviour of the +client in a wide variety of ways: protocol timing, information +requested from the server, information required of the server, +defaults to use if the server does not provide certain information, +values with which to override information provided by the server, or +values to prepend or append to information provided by the server. +The configuration file can also be preinitialized with addresses to +use on networks that don't have DHCP servers. +.SH PROTOCOL TIMING +The timing behaviour of the client need not be configured by the user. +If no timing configuration is provided by the user, a fairly +reasonable timing behaviour will be used by default - one which +results in fairly timely updates without placing an inordinate load on +the server. +.PP +The following statements can be used to adjust the timing behaviour of +the DHCP client if required, however: +.PP +.I The +.B timeout +.I statement +.PP +.B timeout +.I time +.B ; +.PP +The +.I timeout +statement determines the amount of time that must pass between the +time that the client begins to try to determine its address and the +time that it decides that it's not going to be able to contact a +server. By default, this timeout is sixty seconds. After the +timeout has passed, if there are any static leases defined in the +configuration file, or any leases remaining in the lease database that +have not yet expired, the client will loop through these leases +attempting to validate them, and if it finds one that appears to be +valid, it will use that lease's address. If there are no valid +static leases or unexpired leases in the lease database, the client +will restart the protocol after the defined retry interval. +.PP +.I The +.B retry +.I statement +.PP + \fBretry \fItime\fR\fB;\fR +.PP +The +.I retry +statement determines the time that must pass after the client has +determined that there is no DHCP server present before it tries again +to contact a DHCP server. By default, this is five minutes. +.PP +.I The +.B select-timeout +.I statement +.PP + \fBselect-timeout \fItime\fR\fB;\fR +.PP +It is possible (some might say desirable) for there to be more than +one DHCP server serving any given network. In this case, it is +possible that a client may be sent more than one offer in response to +its initial lease discovery message. It may be that one of these +offers is preferable to the other (e.g., one offer may have the +address the client previously used, and the other may not). +.PP +The +.I select-timeout +is the time after the client sends its first lease discovery request +at which it stops waiting for offers from servers, assuming that it +has received at least one such offer. If no offers have been +received by the time the +.I select-timeout +has expired, the client will accept the first offer that arrives. +.PP +By default, the select-timeout is zero seconds - that is, the client +will take the first offer it sees. +.PP +.I The +.B reboot +.I statement +.PP + \fBreboot \fItime\fR\fB;\fR +.PP +When the client is restarted, it first tries to reacquire the last +address it had. This is called the INIT-REBOOT state. If it is +still attached to the same network it was attached to when it last +ran, this is the quickest way to get started. The +.I reboot +statement sets the time that must elapse after the client first tries +to reacquire its old address before it gives up and tries to discover +a new address. By default, the reboot timeout is ten seconds. +.PP +.I The +.B backoff-cutoff +.I statement +.PP + \fBbackoff-cutoff \fItime\fR\fB;\fR +.PP +The client uses an exponential backoff algorithm with some randomness, +so that if many clients try to configure themselves at the same time, +they will not make their requests in lockstep. The +.I backoff-cutoff +statement determines the maximum amount of time that the client is +allowed to back off. It defaults to two minutes. +.PP +.I The +.B initial-interval +.I statement +.PP + \fBinitial-interval \fItime\fR\fB;\fR +.PP +The +.I initial-interval +statement sets the amount of time between the first attempt to reach a +server and the second attempt to reach a server. Each time a message +is sent, the interval between messages is incremented by twice the +current interval multiplied by a random number between zero and one. +If it is greater than the backoff-cutoff amount, it is set to that +amount. It defaults to ten seconds. +.SH LEASE REQUIREMENTS AND REQUESTS +The DHCP protocol allows the client to request that the server send it +specific information, and not send it other information that it is not +prepared to accept. The protocol also allows the client to reject +offers from servers if they don't contain information the client +needs, or if the information provided is not satisfactory. +.PP +There is a variety of data contained in offers that DHCP servers send +to DHCP clients. The data that can be specifically requested is what +are called \fIDHCP Options\fR. DHCP Options are defined in + \fBdhcp-options(5)\fR. +.PP +.I The +.B request +.I statement +.PP + \fBrequest [ \fIoption\fR ] [\fB,\fI ... \fIoption\fR ]\fB;\fR +.PP +The request statement causes the client to request that any server +responding to the client send the client its values for the specified +options. Only the option names should be specified in the request +statement - not option parameters. +.PP +.I The +.B require +.I statement +.PP + \fBrequire [ \fIoption\fR ] [\fB,\fI ... \fIoption ]\fB;\fR +.PP +The require statement lists options that must be sent in order for an +offer to be accepted. Offers that do not contain all the listed +options will be ignored. +.PP +.I The +.B send +.I statement +.PP + \fBsend { [ \fIoption declaration\fR ] +[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR +.PP +The send statement causes the client to send the specified options to +the server with the specified values. These are full option +declarations as described in \fBdhcp-options(5)\fR. Options that are +always sent in the DHCP protocol should not be specified here, except +that the client can specify a \fBrequested-lease-time\fR option other +than the default requested lease time, which is two hours. The other +obvious use for this statement is to send information to the server +that will allow it to differentiate between this client and other +clients or kinds of clients. +.SH OPTION MODIFIERS +In some cases, a client may receive option data from the server which +is not really appropriate for that client, or may not receive +information that it needs, and for which a useful default value +exists. It may also receive information which is useful, but which +needs to be supplemented with local information. To handle these +needs, several option modifiers are available. +.PP +.I The +.B default +.I statement +.PP + \fBdefault { [ \fIoption declaration\fR ] +[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR +.PP +If for some set of options the client should use the value supplied by +the server, but needs to use some default value if no value was supplied +by the server, these values can be defined in the +.B default +statement. +.PP +.I The +.B supersede +.I statement +.PP + \fBsupersede { [ \fIoption declaration\fR ] +[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR +.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 +.B supersede +statement. +.PP +.I The +.B prepend +.I statement +.PP + \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 +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. +.PP +.I The +.B append +.I statement +.PP + \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 +.B append +statement. The +.B append +statement can only be used for options which +allow more than one value to be given. +.SH LEASE DECLARATIONS +.PP +.I The +.B lease +.I declaration +.PP + \fBlease {\fR \fIlease-declaration\fR [ ... \fIlease-declaration ] \fB}\fR +.PP +The DHCP client may decide after some period of time (see \fBPROTOCOL +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 +define one or more \fIfixed\fR leases in the client configuration file +for networks where there is no DHCP or BOOTP service, so that the +client can still automatically configure its address. This is done +with the +.B lease +statement. +.PP +NOTE: the lease statement is also used in the dhclient.leases file in +order to record leases that have been received from DHCP servers. +Some of the syntax for leases as described below is only needed in the +dhclient.leases file. Such syntax is documented here for +completeness. +.PP +A lease statement consists of the lease keyword, followed by a left +curly brace, followed by one or more lease declaration statements, +followed by a right curly brace. The following lease declarations +are possible: +.PP + \fBbootp;\fR +.PP +The +.B bootp +statement is used to indicate that the lease was acquired using the +BOOTP protocol rather than the DHCP protocol. It is never necessary +to specify this in the client configuration file. The client uses +this syntax in its lease database file. +.PP + \fBinterface\fR \fB"\fR\fIstring\fR\fB";\fR +.PP +The +.B interface +lease statement is used to indicate the interface on which the lease +is valid. If set, this lease will only be tried on a particular +interface. When the client receives a lease from a server, it always +records the interface number on which it received that lease. +If predefined leases are specified in the dhclient.conf file, the +interface should also be specified, although this is not required. +.PP + \fBfixed-address\fR \fIip-address\fR\fB;\fR +.PP +The +.B fixed-address +statement is used to set the ip address of a particular lease. This +is required for all lease statements. The IP address must be +specified as a dotted quad (e.g., 12.34.56.78). +.PP + \fBfilename "\fR\fIstring\fR\fB";\fR +.PP +The +.B filename +statement specifies the name of the boot filename to use. This is +not used by the standard client configuration script, but is included +for completeness. +.PP + \fBserver-name "\fR\fIstring\fR\fB";\fR +.PP +The +.B server-name +statement specifies the name of the boot server name to use. This is +also not used by the standard client configuration script. +.PP + \fBoption\fR \fIoption-declaration\fR\fB;\fR +.PP +The +.B option +statement is used to specify the value of an option supplied by the +server, or, in the case of predefined leases declared in +dhclient.conf, the value that the user wishes the client configuration +script to use if the predefined lease is used. +.PP + \fBscript "\fIscript-name\fB";\fR +.PP +The +.B script +statement is used to specify the pathname of the dhcp client +configuration script. This script is used by the dhcp client to set +each interface's initial configuration prior to requesting an address, +to test the address once it has been offered, and to set the +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-lease(8). +.PP + \fBmedium "\fImedia setup\fB";\fR +.PP +The +.B medium +statement can be used on systems where network interfaces cannot +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 te +interface. +.PP +The dhcp client automatically declares this parameter if it used a +media type (see the +.B media +statement) when configuring the interface in order to obtain a lease. +This statement should be used in predefined leases only if the network +interface requires media type configuration. +.PP + \fBrenew\fR \fIdate\fB;\fR +.PP + \fBrebind\fR \fIdate\fB;\fR +.PP + \fBexpire\fR \fIdate\fB;\fR +.PP +The \fBrenew\fR statement defines the time at which the dhcp client +should begin trying to contact its server to renew a lease that it is +using. The \fBrebind\fR statement defines the time at which the dhcp +client should begin to try to contact \fIany\fR dhcp server in order +to renew its lease. The \fBexpire\fR statement defines the time at +which the dhcp client must stop using a lease if it has not been able +to contact a server in order to renew it. +.PP +These declarations are automatically set in leases acquired by the +DHCP client, but must also be configured in predefined leases - a +predefined lease whose expiry time has passed will not be used by the +DHCP client. +.PP +Dates are specified as follows: +.PP + \fI<weekday> <year>\fB/\fI<month>\fB/\fI<day> +<hour>\fB:\fI<minute>\fB:\fI<second>\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. When declaring a predefined lease, it can always be +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 69, and the +second also a number between 0 and 69. +.SH ALIAS DECLARATIONS + \fBalias { \fI declarations ... \fB}\fR +.PP +Some DHCP clients running TCP/IP roaming protocols may require that in +addition to the lease they may acquire via DHCP, their interface also +be configured with a predefined IP alias so that they can have a +permanent IP address even while roaming. The Internet Software +Consortium DHCP client doesn't support roaming with fixed addresses +directly, but in order to facilitate such experimentation, the dhcp +client can be set up to configure an IP alias using the +.B alias +declaration. +.PP +The alias declaration resembles a lease declaration, except that +options other than the subnet-mask option are ignored by the standard +client configuration script, and expiry times are ignored. A typical +alias declaration includes an interface declaration, a fixed-address +declaration for the IP alias address, and a subnet-mask option +declaration. A medium statement should never be included in an alias +declaration. +.SH OTHER DECLARATIONS + \fBreject \fIip-address\fB;\fR +.PP +The reject statement causes the DHCP client to reject offers from +servers who use the specified address as a server identifier. This +can be used to avoid being configured by rogue or misconfigured dhcp +servers, although it should be a last resort - better to track down +the bad DHCP server and fix it. +.PP + \fBinterface "\fIname\fB" { \fIdeclarations ... \fB } +.PP +A client with more than one network interface may require different +behaviour depending on which interface is being configured. All +timing parameters and declarations other than lease and alias +declarations can be enclosed in an interface declaration, and those +parameters will then be used only for the interface that matches the +specified name. Interfaces for which there is no interface +declaration will use the parameters declared outside of any interface +declaration, or the default settings. +.PP + \fBmedia "\fImedia setup\fB"\fI [ \fB, "\fImedia setup\fB", \fI... ]\fB;\fR +.PP +The +.B media +statement defines one or more media configuration parameters which may +be tried while attempting to acquire an IP address. The dhcp client +will cycle through each media setup string on the list, configuring +the interface using that setup and attempting to boot, and then trying +the next one. This can be used for network interfaces which aren't +capable of sensing the media type unaided - whichever media type +succeeds in getting a request to the server and hearing the reply is +probably right (no guarantees). +.PP +The media setup is only used for the initial phase of address +acquisition (the DHCPDISCOVER and DHCPOFFER packtes). Once an +address has been acquired, the dhcp client will record it in its lease +database and will record the media type used to acquire the address. +Whenever the client tries to renew the lease, it will use that same +media type. The lease must expire before the client will go back to +cycling through media types. +.SH SAMPLE +The following configuration file is used on a laptop running NetBSD +1.3. The laptop has an IP alias of 192.5.5.213, and has one +interface, ep0 (a 3com 3C589C). Booting intervals have been +shortened somewhat from the default, because the client is known to +spend most of its time on networks with little DHCP activity. The +laptop does roam to multiple networks. + +.nf + +timeout 60; +retry 60; +reboot 10; +select-timeout 5; +initial-interval 2; +reject 192.33.137.209; + +interface "ep0" { + send host-name "andare.fugue.com"; + send dhcp-client-identifier 1:0:a0:24:ab:fb:9c; + send dhcp-lease-time 3600; + supersede domain-name "fugue.com rc.vix.com home.vix.com"; + prepend domain-name-servers 127.0.0.1; + request subnet-mask, broadcast-address, time-offset, routers, + domain-name, domain-name-servers, host-name; + require subnet-mask, domain-name-servers; + script "/etc/dhclient-script"; + media "media 10baseT/UTP", "media 10base2/BNC"; +} + +alias { + interface "ep0"; + fixed-address 192.5.5.213; + option subnet-mask 255.255.255.255; +} +.fi +This is a very complicated dhclient.conf file - in general, yours +should be much simpler. In many cases, it's sufficient to just +create an empty dhclient.conf file - the defaults are usually fine. +.SH SEE ALSO +dhcp-options(5), dhclient.leases(5), dhcpd(8), dhcpd.conf(5), RFC2132, +RFC2131. +.SH AUTHOR +.B dhclient(8) +was written by Ted Lemon <mellon@vix.com> +under a contract with Vixie Labs. Funding +for this project was provided by the Internet Software Corporation. +Information about the Internet Software Consortium can be found at +.B http://www.isc.org/isc. diff --git a/usr.sbin/dhcp/client/dhclient.leases.5 b/usr.sbin/dhcp/client/dhclient.leases.5 new file mode 100644 index 00000000000..1a787b8cf31 --- /dev/null +++ b/usr.sbin/dhcp/client/dhclient.leases.5 @@ -0,0 +1,62 @@ +.\" dhclient.conf.5 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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.leases 5 +.SH NAME +dhclient.leases - DHCP client lease database +.SH DESCRIPTION +The Internet Software Consortium DHCP client keeps a persistent +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 occurrance. +.PP +The format of the lease declarations is described in +.B dhclient.conf(5). +.SH FILES +.B /var/db/dhclient.leases +.SH SEE ALSO +dhclient(8), dhcp-options(5), dhclient.conf(5), dhcpd(8), +dhcpd.conf(5), RFC2132, RFC2131. +.SH AUTHOR +.B dhclient(8) +was written by Ted Lemon <mellon@vix.com> +under a contract with Vixie Labs. Funding +for this project was provided by the Internet Software Corporation. +Information about the Internet Software Consortium can be found at +.B http://www.isc.org/isc. diff --git a/usr.sbin/dhcp/client/scripts/Makefile b/usr.sbin/dhcp/client/scripts/Makefile new file mode 100644 index 00000000000..c19aa9b3ea3 --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/Makefile @@ -0,0 +1,37 @@ +# Makefile.dist +# +# Copyright (c) 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. +# + +SCRIPTS=netbsd +SCRIPTSNAME_netbsd=dhclient-script +SCRIPTSDIR=/etc + +.include <bsd.prog.mk> diff --git a/usr.sbin/dhcp/client/scripts/bsdos b/usr.sbin/dhcp/client/scripts/bsdos new file mode 100644 index 00000000000..7236a67a9a9 --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/bsdos @@ -0,0 +1,174 @@ +#!/bin/sh + +if [ x$new_network_number != x ]; then + echo New Network Number: $new_network_number +fi + +if [ x$new_broadcast_address != x ]; then + echo New Broadcast Address: $new_broadcast_address + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_netmask_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_netmask_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi + +if [ x$reason = xMEDIUM ]; then + ifconfig $interface $medium + ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1 + sleep 1 + exit 0 +fi + +if [ x$reason = xPREINIT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ + broadcast 255.255.255.255 up + exit 0 +fi + +if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then + exit 0; +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + if [ "$new_static_routes" != "" ]; then + set $new_static_routes + while [ $# -gt 1 ]; do + route add $1 $2 + shift; shift + done + fi + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + echo search $new_domain_name >/etc/resolv.conf + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf + done + exit 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + exit 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + sleep 1 + if [ "$new_routers" != "" ]; then + set $new_routers + if ping -q -c 1 -w 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + set $new_static_routes + while [ $# -gt 1 ]; do + route add $0 $1 + shift; shift + done + echo search $new_domain_name >/etc/resolv.conf.std + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.std + done + if [ -f /etc/resolv.conf ]; then + rm -f /etc/resolv.conf + fi + mv /etc/resolv.conf.std /etc/resolv.conf + exit 0 + fi + ifconfig $interface inet -alias $new_ip_address $medium + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + exit 1 +fi + +exit 0 diff --git a/usr.sbin/dhcp/client/scripts/freebsd b/usr.sbin/dhcp/client/scripts/freebsd new file mode 100644 index 00000000000..7236a67a9a9 --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/freebsd @@ -0,0 +1,174 @@ +#!/bin/sh + +if [ x$new_network_number != x ]; then + echo New Network Number: $new_network_number +fi + +if [ x$new_broadcast_address != x ]; then + echo New Broadcast Address: $new_broadcast_address + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_netmask_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_netmask_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi + +if [ x$reason = xMEDIUM ]; then + ifconfig $interface $medium + ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1 + sleep 1 + exit 0 +fi + +if [ x$reason = xPREINIT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ + broadcast 255.255.255.255 up + exit 0 +fi + +if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then + exit 0; +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + if [ "$new_static_routes" != "" ]; then + set $new_static_routes + while [ $# -gt 1 ]; do + route add $1 $2 + shift; shift + done + fi + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + echo search $new_domain_name >/etc/resolv.conf + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf + done + exit 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + exit 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + sleep 1 + if [ "$new_routers" != "" ]; then + set $new_routers + if ping -q -c 1 -w 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + set $new_static_routes + while [ $# -gt 1 ]; do + route add $0 $1 + shift; shift + done + echo search $new_domain_name >/etc/resolv.conf.std + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.std + done + if [ -f /etc/resolv.conf ]; then + rm -f /etc/resolv.conf + fi + mv /etc/resolv.conf.std /etc/resolv.conf + exit 0 + fi + ifconfig $interface inet -alias $new_ip_address $medium + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + exit 1 +fi + +exit 0 diff --git a/usr.sbin/dhcp/client/scripts/linux b/usr.sbin/dhcp/client/scripts/linux new file mode 100644 index 00000000000..f97539dd23f --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/linux @@ -0,0 +1,146 @@ +#!/bin/sh +# dhclient-script for Linux. Dan Halbert, March, 1997. +# No guarantees about this. I'm a novice at the details of Linux +# networking. + +# Notes: + +# 0. This script is based on the netbsd script supplied with dhcp-970306. + +# 1. ifconfig down apparently deletes all relevant routes and flushes +# the arp cache, so this doesn't need to be done explicitly. + +# 2. The alias address handling here has not been tested AT ALL. +# I'm just going by the doc of modern Linux ip aliasing, which uses +# notations like eth0:0, eth0:1, for each alias. + +# 3. I have to calculate the network address, and calculate the broadcast +# address if it is not supplied. This might be much more easily done +# by the dhclient C code, and passed on. + +# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious +# of the $1 in its args. + +if [ x$new_broadcast_address != x ]; then + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_subnet_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_subnet_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi + +if [ x$reason = xMEDIUM ]; then + # Linux doesn't do mediums (ok, ok, media). + exit 0 +fi + +if [ x$reason = xPREINIT ]; then + if [ x$alias_ip_address != x ]; then + # Bring down alias interface. Its routes will disappear too. + ifconfig $interface:0- inet 0 + fi + ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ + broadcast 255.255.255.255 up + # Add route to make broadcast work. Do not omit netmask. + route add default dev $interface netmask 0.0.0.0 + exit 0 +fi + +if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then + exit 0; +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + # Possible new alias. Remove old alias. + ifconfig $interface:0- inet 0 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + # IP address changed. Bringing down the interface will delete all routes, + # and clear the ARP cache. + ifconfig $interface inet down + + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + + ifconfig $interface inet $new_ip_address $new_subnet_arg \ + $new_broadcast_arg + # Add a network route to the computed network address. + route add -net $new_network_number $new_subnet_arg dev $interface + for router in $new_routers; do + route add default gw $router + done + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface:0- inet 0 + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + route add -host $alias_ip_address $interface:0 + fi + echo domain $new_domain_name >/etc/resolv.conf + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf + done + exit 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then + if [ x$alias_ip_address != x ]; then + # Turn off alias interface. + ifconfig $interface:0- inet 0 + fi + if [ x$old_ip_address != x ]; then + # Shut down interface, which will delete routes and clear arp cache. + ifconfig $interface inet down + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + route add -host $alias_ip_address $interface:0 + fi + exit 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface:0- inet 0 + fi + ifconfig $interface inet $new_ip_address $new_subnet_arg \ + $new_broadcast_arg + set $new_routers + ############## what is -w in ping? + if ping -q -c 1 -w 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + route add -host $alias_ip_address dev $interface:0 + fi + route add -net $new_network_number + for router in $new_routers; do + route add default gw $router + done + echo domain $new_domain_name >/etc/resolv.conf.std + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.std + done + if [ -f /etc/resolv.conf ]; then + rm -f /etc/resolv.conf + ln /etc/resolv.conf.std /etc/resolv.conf + fi + exit 0 + fi + ifconfig $interface inet down + exit 1 +fi + +exit 0 diff --git a/usr.sbin/dhcp/client/scripts/netbsd b/usr.sbin/dhcp/client/scripts/netbsd new file mode 100644 index 00000000000..7236a67a9a9 --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/netbsd @@ -0,0 +1,174 @@ +#!/bin/sh + +if [ x$new_network_number != x ]; then + echo New Network Number: $new_network_number +fi + +if [ x$new_broadcast_address != x ]; then + echo New Broadcast Address: $new_broadcast_address + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_netmask_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_netmask_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi + +if [ x$reason = xMEDIUM ]; then + ifconfig $interface $medium + ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1 + sleep 1 + exit 0 +fi + +if [ x$reason = xPREINIT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ + broadcast 255.255.255.255 up + exit 0 +fi + +if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then + exit 0; +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + if [ "$new_static_routes" != "" ]; then + set $new_static_routes + while [ $# -gt 1 ]; do + route add $1 $2 + shift; shift + done + fi + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + echo search $new_domain_name >/etc/resolv.conf + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf + done + exit 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + exit 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + sleep 1 + if [ "$new_routers" != "" ]; then + set $new_routers + if ping -q -c 1 -w 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + set $new_static_routes + while [ $# -gt 1 ]; do + route add $0 $1 + shift; shift + done + echo search $new_domain_name >/etc/resolv.conf.std + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.std + done + if [ -f /etc/resolv.conf ]; then + rm -f /etc/resolv.conf + fi + mv /etc/resolv.conf.std /etc/resolv.conf + exit 0 + fi + ifconfig $interface inet -alias $new_ip_address $medium + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + if [ "$old_static_routes" != "" ]; then + set $old_static_routes + while [ $# -gt 1 ]; do + route delete $1 $2 + shift; shift + done + fi + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + exit 1 +fi + +exit 0 diff --git a/usr.sbin/dhcp/client/scripts/nextstep b/usr.sbin/dhcp/client/scripts/nextstep new file mode 100644 index 00000000000..15623a38e9a --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/nextstep @@ -0,0 +1,37 @@ +#!/bin/sh +# +# simplified dhclient-script for NeXTSTEP/OPENSTEP +# +# removed a lot of the cruft from the netbsd version since NeXTSTEP doesn't +# support aliases and lots of things were breaking for no good reason +# +# 14 Sep 1997, David W. Young +# +if [ x$reason = xPREINIT ]; then + ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 up >/dev/null 2>&1 + exit 0 +fi +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + ifconfig $interface $new_ip_address netmask $new_subnet_mask >/dev/null 2>&1 + route add $new_ip_address 127.1 0 >/dev/null 2>&1 + for router in $new_routers ; do + route add default $router 1 >/dev/null 2>&1 + done + fi + echo search $new_domain_name >/etc/resolv.conf + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf + done + exit 0 +fi +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then + if [ x$old_ip_address != x ]; then + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for $router in $old_routers ; do + route delete default $router >/dev/null 2>&1 + done + fi + exit 0 +fi diff --git a/usr.sbin/dhcp/client/scripts/solaris b/usr.sbin/dhcp/client/scripts/solaris new file mode 100644 index 00000000000..4f60ebaa7e1 --- /dev/null +++ b/usr.sbin/dhcp/client/scripts/solaris @@ -0,0 +1,148 @@ +#!/bin/sh + +if [ x$new_broadcast_address != x ]; then + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_netmask_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_netmask_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi + +# For Solaris, ifconfig lives in /sbin +OS=`uname -r` +if [ $OS = "5.5.1" ]; then + PATH=/sbin:$PATH +fi + +if [ x$reason = xMEDIUM ]; then + ifconfig $interface $medium + ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1 + ifconfig $interface + sleep 1 + exit 0 +fi + +if [ x$reason = xPREINIT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ $OS = "5.5.1" ]; then + # Turn the interface on + ifconfig $interface plumb + ifconfig $interface inet 10.0.0.1 up + else + ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ + broadcast 255.255.255.255 up + fi + exit 0 +fi + +if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then + exit 0; +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + echo search $new_domain_name >/etc/resolv.conf + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf + done + exit 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + if [ x$old_ip_address != x ]; then + ifconfig $interface inet -alias $old_ip_address $medium + route delete $old_ip_address 127.1 >/dev/null 2>&1 + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p'i \ + |sh >/dev/null 2>&1 + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + exit 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1 + route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1 + fi + ifconfig $interface inet $new_ip_address $new_netmask_arg \ + $new_broadcast_arg $medium + sleep 1 + set $new_routers + if ping -c 1 -w 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg + route add $alias_ip_address 127.0.0.1 + fi + route add $new_ip_address 127.1 >/dev/null 2>&1 + for router in $new_routers; do + route add default $router >/dev/null 2>&1 + done + echo search $new_domain_name >/etc/resolv.conf.std + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.std + done + if [ -f /etc/resolv.conf ]; then + rm -f /etc/resolv.conf + ln /etc/resolv.conf.std /etc/resolv.conf + fi + exit 0 + fi + ifconfig $interface inet -alias $new_ip_address $medium + for router in $old_routers; do + route delete default $router >/dev/null 2>&1 + done + arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \ + |sh >/dev/null 2>&1 + exit 1 +fi + +exit 0 diff --git a/usr.sbin/dhcp/common/Makefile b/usr.sbin/dhcp/common/Makefile new file mode 100644 index 00000000000..8d1c99be55d --- /dev/null +++ b/usr.sbin/dhcp/common/Makefile @@ -0,0 +1,44 @@ +# Makefile.dist +# +# 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. +# + +MAN = dhcp-options.5 +LIB = dhcp +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 + +NOPROFILE= +NOPIC= + +# only needed during build +libinstall:: + +.include <bsd.lib.mk> diff --git a/usr.sbin/dhcp/common/alloc.c b/usr.sbin/dhcp/common/alloc.c new file mode 100644 index 00000000000..8b300ced0c1 --- /dev/null +++ b/usr.sbin/dhcp/common/alloc.c @@ -0,0 +1,329 @@ +/* alloc.c + + Memory allocation... */ + +/* + * 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 <mellon@fugue.com> 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: 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) + int size; + char *name; +{ + VOIDPTR foo = (VOIDPTR)malloc (size); + if (!foo) + warn ("No memory for %s.", name); + memset (foo, 0, size); + return foo; +} + +void dfree (ptr, name) + VOIDPTR ptr; + char *name; +{ + if (!ptr) { + warn ("dfree %s: free on null pointer.", name); + return; + } + free (ptr); +} + +struct packet *new_packet (name) + char *name; +{ + struct packet *rval; + rval = (struct packet *)dmalloc (sizeof (struct packet), name); + return rval; +} + +struct dhcp_packet *new_dhcp_packet (name) + char *name; +{ + struct dhcp_packet *rval; + rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet), + name); + return rval; +} + +struct tree *new_tree (name) + char *name; +{ + struct tree *rval = dmalloc (sizeof (struct tree), name); + return rval; +} + +struct tree_cache *free_tree_caches; + +struct tree_cache *new_tree_cache (name) + char *name; +{ + struct tree_cache *rval; + + if (free_tree_caches) { + rval = free_tree_caches; + free_tree_caches = + (struct tree_cache *)(rval -> value); + } else { + rval = dmalloc (sizeof (struct tree_cache), name); + if (!rval) + error ("unable to allocate tree cache for %s.", name); + } + return rval; +} + +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; + return rval; +} + +struct hash_bucket *new_hash_bucket (name) + char *name; +{ + struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name); + return rval; +} + +struct lease *new_leases (n, name) + int n; + char *name; +{ + struct lease *rval = dmalloc (n * sizeof (struct lease), name); + return rval; +} + +struct lease *new_lease (name) + char *name; +{ + struct lease *rval = dmalloc (sizeof (struct lease), name); + return rval; +} + +struct subnet *new_subnet (name) + char *name; +{ + struct subnet *rval = dmalloc (sizeof (struct subnet), name); + return rval; +} + +struct class *new_class (name) + char *name; +{ + struct class *rval = dmalloc (sizeof (struct class), name); + return rval; +} + +struct shared_network *new_shared_network (name) + char *name; +{ + struct shared_network *rval = + dmalloc (sizeof (struct shared_network), name); + return rval; +} + +struct group *new_group (name) + char *name; +{ + struct group *rval = + dmalloc (sizeof (struct group), name); + return rval; +} + +struct protocol *new_protocol (name) + char *name; +{ + struct protocol *rval = dmalloc (sizeof (struct protocol), name); + return rval; +} + +struct lease_state *free_lease_states; + +struct lease_state *new_lease_state (name) + char *name; +{ + struct lease_state *rval; + + if (free_lease_states) { + rval = free_lease_states; + free_lease_states = + (struct lease_state *)(free_lease_states -> next); + } else { + rval = dmalloc (sizeof (struct lease_state), name); + } + return rval; +} + +struct domain_search_list *new_domain_search_list (name) + char *name; +{ + struct domain_search_list *rval = + dmalloc (sizeof (struct domain_search_list), name); + return rval; +} + +struct name_server *new_name_server (name) + char *name; +{ + struct name_server *rval = + dmalloc (sizeof (struct name_server), name); + return rval; +} + +void free_name_server (ptr, name) + struct name_server *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_domain_search_list (ptr, name) + struct domain_search_list *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_lease_state (ptr, name) + struct lease_state *ptr; + char *name; +{ + ptr -> next = free_lease_states; + free_lease_states = ptr; +} + +void free_protocol (ptr, name) + struct protocol *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_group (ptr, name) + struct group *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_shared_network (ptr, name) + struct shared_network *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_class (ptr, name) + struct class *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_subnet (ptr, name) + struct subnet *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_lease (ptr, name) + struct lease *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_hash_bucket (ptr, name) + struct hash_bucket *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_hash_table (ptr, name) + struct hash_table *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_tree_cache (ptr, name) + struct tree_cache *ptr; + char *name; +{ + ptr -> value = (unsigned char *)free_tree_caches; + free_tree_caches = ptr; +} + +void free_packet (ptr, name) + struct packet *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_dhcp_packet (ptr, name) + struct dhcp_packet *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} + +void free_tree (ptr, name) + struct tree *ptr; + char *name; +{ + dfree ((VOIDPTR)ptr, name); +} diff --git a/usr.sbin/dhcp/common/bpf.c b/usr.sbin/dhcp/common/bpf.c new file mode 100644 index 00000000000..c373004a2b7 --- /dev/null +++ b/usr.sbin/dhcp/common/bpf.c @@ -0,0 +1,386 @@ +/* bpf.c + + BPF socket interface 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 <mellon@fugue.com> 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: bpf.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" +#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) +#include <sys/ioctl.h> +#include <sys/uio.h> + +#include <net/bpf.h> +#ifdef NEED_OSF_PFILT_HACKS +#include <net/pfilt.h> +#endif +#include <netinet/in_systm.h> +#include "includes/netinet/ip.h" +#include "includes/netinet/udp.h" +#include "includes/netinet/if_ether.h" + +/* Reinitializes the specified interface after an address change. This + is not required for packet-filter APIs. */ + +#ifdef USE_BPF_SEND +void if_reinitialize_send (info) + struct interface_info *info; +{ +} +#endif + +#ifdef USE_BPF_RECEIVE +void if_reinitialize_receive (info) + struct interface_info *info; +{ +} +#endif + +/* Called by get_interface_list for each interface that's discovered. + Opens a packet filter for each interface and adds it to the select + mask. */ + +int if_register_bpf (info) + struct interface_info *info; +{ + int sock; + char filename[50]; + int b; + + /* Open a BPF device */ + for (b = 0; 1; b++) { +#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 { + error ("Can't find free bpf: %m"); + } + } else { + break; + } + } + + /* Set the BPF device to point at this interface. */ + if (ioctl (sock, BIOCSETIF, info -> ifp) < 0) + error ("Can't attach interface %s to bpf device %s: %m", + info -> name, filename); + + return sock; +} +#endif /* USE_BPF_SEND || USE_BPF_RECEIVE */ + +#ifdef USE_BPF_SEND +void if_register_send (info) + struct interface_info *info; +{ + /* If we're using the bpf API for sending and receiving, + we don't need to register this interface twice. */ +#ifndef USE_BPF_RECEIVE + info -> wfdesc = if_register_bpf (info, interface); +#else + info -> wfdesc = info -> rfdesc; +#endif + if (!quiet_interface_discovery) + note ("Sending on BPF/%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_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 [] = { + /* Make sure this is an IP packet... */ + BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12), + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), + + /* Make sure it's a UDP packet... */ + BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23), + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), + + /* Make sure this isn't a fragment... */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), + BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), + + /* Get the IP header length... */ + BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), + + /* Make sure it's to the right port... */ + BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ + + /* If we passed all the tests, ask for the whole packet. */ + BPF_STMT(BPF_RET+BPF_K, (u_int)-1), + + /* Otherwise, drop it. */ + BPF_STMT(BPF_RET+BPF_K, 0), +}; + +void if_register_receive (info) + struct interface_info *info; +{ + int flag = 1; + struct bpf_version v; + u_int32_t addr; + struct bpf_program p; + u_int32_t bits; + + /* Open a BPF device and hang it on this interface... */ + info -> rfdesc = if_register_bpf (info); + + /* Make sure the BPF version is in range... */ + if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0) + error ("Can't get BPF version: %m"); + + if (v.bv_major != BPF_MAJOR_VERSION || + v.bv_minor < BPF_MINOR_VERSION) + error ("Kernel BPF version out of range - recompile dhcpd!"); + + /* Set immediate mode so that reads return as soon as a packet + comes in, rather than waiting for the input buffer to fill with + packets. */ + if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0) + 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"); + info -> rbuf = malloc (info -> rbuf_max); + if (!info -> rbuf) + error ("Can't allocate %d bytes for bpf input buffer."); + info -> rbuf_offset = 0; + info -> rbuf_len = 0; + + /* Set up the bpf filter program structure. */ + p.bf_len = sizeof filter / sizeof (struct bpf_insn); + p.bf_insns = 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); + + 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", + 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_BPF_RECEIVE */ + +#ifdef USE_BPF_SEND +ssize_t send_packet (interface, packet, raw, len, from, to, hto) + struct interface_info *interface; + struct packet *packet; + struct dhcp_packet *raw; + size_t len; + struct in_addr from; + struct sockaddr_in *to; + struct hardware *hto; +{ + 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_BPF_SEND */ + +#ifdef USE_BPF_RECEIVE +ssize_t receive_packet (interface, buf, len, from, hfrom) + struct interface_info *interface; + unsigned char *buf; + size_t len; + struct sockaddr_in *from; + struct hardware *hfrom; +{ + int length = 0; + int offset = 0; + struct bpf_hdr hdr; + + /* All this complexity is because BPF doesn't guarantee + that only one packet will be returned at a time. We're + getting what we deserve, though - this is a terrible abuse + of the BPF interface. Sigh. */ + + /* Process packets until we get one we can return or until we've + done a read and gotten nothing we can return... */ + + do { + /* If the buffer is empty, fill it. */ + if (interface -> rbuf_offset == interface -> rbuf_len) { + length = read (interface -> rfdesc, + interface -> rbuf, + interface -> rbuf_max); + if (length <= 0) + return length; + interface -> rbuf_offset = 0; + interface -> rbuf_len = length; + } + + /* If there isn't room for a whole bpf header, something went + wrong, but we'll ignore it and hope it goes away... XXX */ + if (interface -> rbuf_len - + interface -> rbuf_offset < sizeof hdr) { + interface -> rbuf_offset = interface -> rbuf_len; + continue; + } + + /* Copy out a bpf header... */ + memcpy (&hdr, &interface -> rbuf [interface -> rbuf_offset], + sizeof hdr); + + /* If the bpf header plus data doesn't fit in what's left + of the buffer, stick head in sand yet again... */ + if (interface -> rbuf_offset + + hdr.bh_hdrlen + hdr.bh_caplen > interface -> rbuf_len) { + interface -> rbuf_offset = interface -> rbuf_len; + continue; + } + + /* If the captured data wasn't the whole packet, or if + the packet won't fit in the input buffer, all we + can do is drop it. */ + if (hdr.bh_caplen != hdr.bh_datalen) { + interface -> rbuf_offset += + hdr.bh_hdrlen = hdr.bh_caplen; + continue; + } + + /* Skip over the BPF header... */ + interface -> rbuf_offset += hdr.bh_hdrlen; + + /* Decode the physical header... */ + offset = decode_hw_header (interface, + interface -> rbuf, + interface -> rbuf_offset, + hfrom); + + /* If a physical layer checksum failed (dunno of any + physical layer that supports this, but WTH), skip this + packet. */ + if (offset < 0) { + interface -> rbuf_offset += hdr.bh_caplen; + continue; + } + interface -> rbuf_offset += offset; + hdr.bh_caplen -= offset; + + /* Decode the IP and UDP headers... */ + offset = decode_udp_ip_header (interface, + interface -> rbuf, + interface -> rbuf_offset, + from, + (unsigned char *)0, + hdr.bh_caplen); + + /* If the IP or UDP checksum was bad, skip the packet... */ + if (offset < 0) { + interface -> rbuf_offset += hdr.bh_caplen; + continue; + } + interface -> rbuf_offset += offset; + hdr.bh_caplen -= offset; + + /* If there's not enough room to stash the packet data, + we have to skip it (this shouldn't happen in real + life, though). */ + if (hdr.bh_caplen > len) { + interface -> rbuf_offset += hdr.bh_caplen; + continue; + } + + /* Copy out the data in the packet... */ + memcpy (buf, interface -> rbuf + interface -> rbuf_offset, + hdr.bh_caplen); + interface -> rbuf_offset += hdr.bh_caplen; + return hdr.bh_caplen; + } while (!length); + return 0; +} +#endif diff --git a/usr.sbin/dhcp/common/conflex.c b/usr.sbin/dhcp/common/conflex.c new file mode 100644 index 00000000000..4855a973400 --- /dev/null +++ b/usr.sbin/dhcp/common/conflex.c @@ -0,0 +1,548 @@ +/* conflex.c + + Lexical scanner for dhcpd config 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 <mellon@fugue.com> 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: 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 <ctype.h> + +int lexline; +int lexchar; +char *token_line; +char *prev_line; +char *cur_line; +char *tlname; +int eol_token; + +static char line1 [81]; +static char line2 [81]; +static int lpos; +static int line; +static int tlpos; +static int tline; +static int token; +static int ugflag; +static char *tval; +static char tokbuf [1500]; + +#ifdef OLD_LEXER +char comments [4096]; +int comment_index; +#endif + + +static int get_char PROTO ((FILE *)); +static int get_token PROTO ((FILE *)); +static void skip_to_eol PROTO ((FILE *)); +static int read_string PROTO ((FILE *)); +static int read_number PROTO ((int, FILE *)); +static int read_num_or_name PROTO ((int, FILE *)); +static int intern PROTO ((char *, int)); + +void new_parse (name) + char *name; +{ + tlname = name; + lpos = line = 1; + cur_line = line1; + prev_line = line2; + token_line = cur_line; + cur_line [0] = prev_line [0] = 0; + warnings_occurred = 0; +} + +static int get_char (cfile) + FILE *cfile; +{ + int c = getc (cfile); + if (!ugflag) { + if (c == EOL) { + if (cur_line == line1) { + cur_line = line2; + prev_line = line1; + } else { + cur_line = line2; + prev_line = line1; + } + line++; + lpos = 1; + cur_line [0] = 0; + } else if (c != EOF) { + if (lpos <= 81) { + cur_line [lpos - 1] = c; + cur_line [lpos] = 0; + } + lpos++; + } + } else + ugflag = 0; + return c; +} + +static int get_token (cfile) + FILE *cfile; +{ + int c; + int ttok; + static char tb [2]; + int l, p, u; + + do { + l = line; + p = lpos; + 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; + } + if (c == '"') { + lexline = l; + lexchar = p; + ttok = read_string (cfile); + break; + } + if ((isascii (c) && isdigit (c)) || c == '-') { + lexline = l; + lexchar = p; + ttok = read_number (c, cfile); + break; + } else if (isascii (c) && isalpha (c)) { + lexline = l; + lexchar = p; + ttok = read_num_or_name (c, cfile); + break; + } else { + lexline = l; + lexchar = p; + tb [0] = c; + tb [1] = 0; + tval = tb; + ttok = c; + break; + } + } while (1); + return ttok; +} + +int next_token (rval, cfile) + char **rval; + FILE *cfile; +{ + int rv; + + if (token) { + if (lexline != tline) + token_line = cur_line; + lexchar = tlpos; + lexline = tline; + rv = token; + token = 0; + } else { + rv = get_token (cfile); + token_line = cur_line; + } + if (rval) + *rval = tval; +#ifdef DEBUG_TOKENS + fprintf (stderr, "%s:%d ", tval, rv); +#endif + return rv; +} + +int peek_token (rval, cfile) + char **rval; + FILE *cfile; +{ + int x; + + if (!token) { + tlpos = lexchar; + tline = lexline; + token = get_token (cfile); + if (lexline != tline) + token_line = prev_line; + x = lexchar; lexchar = tlpos; tlpos = x; + x = lexline; lexline = tline; tline = x; + } + if (rval) + *rval = tval; +#ifdef DEBUG_TOKENS + fprintf (stderr, "(%s:%d) ", tval, token); +#endif + return token; +} + +static void skip_to_eol (cfile) + FILE *cfile; +{ + int c; + do { + c = get_char (cfile); + if (c == EOF) + return; +#ifdef OLD_LEXER + if (comment_index < sizeof (comments)) + comments [comment_index++] = c; +#endif + if (c == EOL) { + return; + } + } while (1); +} + +static int read_string (cfile) + FILE *cfile; +{ + int i; + int bs = 0; + int c; + + for (i = 0; i < sizeof tokbuf; i++) { + c = get_char (cfile); + if (c == EOF) { + parse_warn ("eof in string constant"); + break; + } + if (bs) { + bs = 0; + tokbuf [i] = c; + } else if (c == '\\') + bs = 1; + else if (c == '"') + break; + else + tokbuf [i] = c; + } + /* Normally, I'd feel guilty about this, but we're talking about + strings that'll fit in a DHCP packet here... */ + if (i == sizeof tokbuf) { + parse_warn ("string constant larger than internal buffer"); + --i; + } + tokbuf [i] = 0; + tval = tokbuf; + return STRING; +} + +static int read_number (c, cfile) + int c; + FILE *cfile; +{ + int seenx = 0; + int i = 0; + int token = NUMBER; + + tokbuf [i++] = c; + for (; i < sizeof tokbuf; i++) { + c = get_char (cfile); + if (!seenx && c == 'x') { + seenx = 1; +#ifndef OLD_LEXER + } else if (isascii (c) && !isxdigit (c) && + (c == '-' || c == '_' || isalpha (c))) { + token = NAME; + } else if (isascii (c) && !isdigit (c) && isxdigit (c)) { + token = NUMBER_OR_NAME; +#endif + } else if (!isascii (c) || !isxdigit (c)) { + ungetc (c, cfile); + ugflag = 1; + break; + } + tokbuf [i] = c; + } + if (i == sizeof tokbuf) { + parse_warn ("numeric token larger than internal buffer"); + --i; + } + tokbuf [i] = 0; + tval = tokbuf; + return token; +} + +static int read_num_or_name (c, cfile) + int c; + FILE *cfile; +{ + int i = 0; + int rv = NUMBER_OR_NAME; + tokbuf [i++] = c; + for (; i < sizeof tokbuf; i++) { + c = get_char (cfile); + if (!isascii (c) || + (c != '-' && c != '_' && !isalnum (c))) { + ungetc (c, cfile); + ugflag = 1; + break; + } + if (!isxdigit (c)) + rv = NAME; + tokbuf [i] = c; + } + if (i == sizeof tokbuf) { + parse_warn ("token larger than internal buffer"); + --i; + } + tokbuf [i] = 0; + tval = tokbuf; + return intern (tval, rv); +} + +static int intern (atom, dfv) + char *atom; + int dfv; +{ + if (!isascii (atom [0])) + return dfv; + + switch (tolower (atom [0])) { + case 'a': + if (!strcasecmp (atom + 1, "ppend")) + return APPEND; + if (!strcasecmp (atom + 1, "llow")) + return ALLOW; + if (!strcasecmp (atom + 1, "lias")) + return ALIAS; + if (!strcasecmp (atom + 1, "bandoned")) + return ABANDONED; + break; + case 'b': + if (!strcasecmp (atom + 1, "ackoff-cutoff")) + return BACKOFF_CUTOFF; + if (!strcasecmp (atom + 1, "ootp")) + return BOOTP; + if (!strcasecmp (atom + 1, "ooting")) + return BOOTING; + if (!strcasecmp (atom + 1, "oot-unknown-clients")) + return BOOT_UNKNOWN_CLIENTS; + case 'c': + if (!strcasecmp (atom + 1, "lass")) + return CLASS; + if (!strcasecmp (atom + 1, "iaddr")) + return CIADDR; + if (!strcasecmp (atom + 1, "lient-identifier")) + return CLIENT_IDENTIFIER; + if (!strcasecmp (atom + 1, "lient-hostname")) + return CLIENT_HOSTNAME; + break; + case 'd': + if (!strcasecmp (atom + 1, "omain")) + return DOMAIN; + if (!strcasecmp (atom + 1, "eny")) + return DENY; + if (!strncasecmp (atom + 1, "efault", 6)) { + if (!atom [7]) + return DEFAULT; + if (!strcasecmp (atom + 7, "-lease-time")) + return DEFAULT_LEASE_TIME; + break; + } + if (!strncasecmp (atom + 1, "ynamic-bootp", 12)) { + if (!atom [13]) + return DYNAMIC_BOOTP; + if (!strcasecmp (atom + 13, "-lease-cutoff")) + return DYNAMIC_BOOTP_LEASE_CUTOFF; + if (!strcasecmp (atom + 13, "-lease-length")) + return DYNAMIC_BOOTP_LEASE_LENGTH; + break; + } + break; + case 'e': + if (!strcasecmp (atom + 1, "thernet")) + return ETHERNET; + if (!strcasecmp (atom + 1, "nds")) + return ENDS; + if (!strcasecmp (atom + 1, "xpire")) + return EXPIRE; + break; + case 'f': + if (!strcasecmp (atom + 1, "ilename")) + return FILENAME; + if (!strcasecmp (atom + 1, "ixed-address")) + return FIXED_ADDR; + break; + case 'g': + if (!strcasecmp (atom + 1, "iaddr")) + return GIADDR; + if (!strcasecmp (atom + 1, "roup")) + return GROUP; + if (!strcasecmp (atom + 1, "et-lease-hostnames")) + return GET_LEASE_HOSTNAMES; + break; + case 'h': + if (!strcasecmp (atom + 1, "ost")) + return HOST; + if (!strcasecmp (atom + 1, "ardware")) + return HARDWARE; + if (!strcasecmp (atom + 1, "ostname")) + return HOSTNAME; + break; + case 'i': + if (!strcasecmp (atom + 1, "nitial-interval")) + return INITIAL_INTERVAL; + if (!strcasecmp (atom + 1, "nterface")) + return INTERFACE; + break; + case 'l': + if (!strcasecmp (atom + 1, "ease")) + return LEASE; + break; + case 'm': + if (!strcasecmp (atom + 1, "ax-lease-time")) + return MAX_LEASE_TIME; + if (!strncasecmp (atom + 1, "edi", 3)) { + if (!strcasecmp (atom + 4, "a")) + return MEDIA; + if (!strcasecmp (atom + 4, "um")) + return MEDIUM; + break; + } + break; + case 'n': + if (!strcasecmp (atom + 1, "ameserver")) + return NAMESERVER; + if (!strcasecmp (atom + 1, "etmask")) + return NETMASK; + if (!strcasecmp (atom + 1, "ext-server")) + return NEXT_SERVER; + break; + case 'o': + if (!strcasecmp (atom + 1, "ption")) + return OPTION; + if (!strcasecmp (atom + 1, "ne-lease-per-client")) + return ONE_LEASE_PER_CLIENT; + break; + case 'p': + if (!strcasecmp (atom + 1, "repend")) + return PREPEND; + if (!strcasecmp (atom + 1, "acket")) + return PACKET; + break; + case 'r': + if (!strcasecmp (atom + 1, "ange")) + return RANGE; + if (!strcasecmp (atom + 1, "equest")) + return REQUEST; + if (!strcasecmp (atom + 1, "equire")) + return REQUIRE; + if (!strcasecmp (atom + 1, "etry")) + return RETRY; + if (!strcasecmp (atom + 1, "enew")) + return RENEW; + if (!strcasecmp (atom + 1, "ebind")) + return REBIND; + if (!strcasecmp (atom + 1, "eboot")) + return REBOOT; + if (!strcasecmp (atom + 1, "eject")) + return REJECT; + break; + case 's': + if (!strcasecmp (atom + 1, "earch")) + return SEARCH; + if (!strcasecmp (atom + 1, "tarts")) + return STARTS; + if (!strcasecmp (atom + 1, "iaddr")) + return SIADDR; + if (!strcasecmp (atom + 1, "ubnet")) + return SUBNET; + if (!strcasecmp (atom + 1, "hared-network")) + return SHARED_NETWORK; + if (!strcasecmp (atom + 1, "erver-name")) + return SERVER_NAME; + if (!strcasecmp (atom + 1, "erver-identifier")) + return SERVER_IDENTIFIER; + if (!strcasecmp (atom + 1, "elect-timeout")) + return SELECT_TIMEOUT; + if (!strcasecmp (atom + 1, "end")) + return SEND; + if (!strcasecmp (atom + 1, "cript")) + return SCRIPT; + if (!strcasecmp (atom + 1, "upersede")) + return SUPERSEDE; + break; + case 't': + if (!strcasecmp (atom + 1, "imestamp")) + return TIMESTAMP; + if (!strcasecmp (atom + 1, "imeout")) + return TIMEOUT; + if (!strcasecmp (atom + 1, "oken-ring")) + return TOKEN_RING; + break; + case 'u': + 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; + case 'v': + if (!strcasecmp (atom + 1, "endor-class")) + return VENDOR_CLASS; + break; + case 'y': + if (!strcasecmp (atom + 1, "iaddr")) + return YIADDR; + break; + } + return dfv; +} diff --git a/usr.sbin/dhcp/common/convert.c b/usr.sbin/dhcp/common/convert.c new file mode 100644 index 00000000000..60db34258d9 --- /dev/null +++ b/usr.sbin/dhcp/common/convert.c @@ -0,0 +1,118 @@ +/* convert.c + + Safe copying of option values into and out of the option buffer, which + can't be assumed to be aligned. */ + +/* + * 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 <mellon@fugue.com> 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: 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) + unsigned char *buf; +{ + unsigned long ibuf; + + memcpy (&ibuf, buf, sizeof (u_int32_t)); + return ntohl (ibuf); +} + +int32_t getLong (buf) + unsigned char *buf; +{ + long ibuf; + + memcpy (&ibuf, buf, sizeof (int32_t)); + return ntohl (ibuf); +} + +u_int16_t getUShort (buf) + unsigned char *buf; +{ + unsigned short ibuf; + + memcpy (&ibuf, buf, sizeof (u_int16_t)); + return ntohs (ibuf); +} + +int16_t getShort (buf) + unsigned char *buf; +{ + short ibuf; + + memcpy (&ibuf, buf, sizeof (int16_t)); + return ntohs (ibuf); +} + +void putULong (obuf, val) + unsigned char *obuf; + u_int32_t val; +{ + u_int32_t tmp = htonl (val); + memcpy (obuf, &tmp, sizeof tmp); +} + +void putLong (obuf, val) + unsigned char *obuf; + int32_t val; +{ + int32_t tmp = htonl (val); + memcpy (obuf, &tmp, sizeof tmp); +} + +void putUShort (obuf, val) + unsigned char *obuf; + u_int16_t val; +{ + u_int16_t tmp = htons (val); + memcpy (obuf, &tmp, sizeof tmp); +} + +void putShort (obuf, val) + unsigned char *obuf; + int16_t 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 new file mode 100644 index 00000000000..eb90ed6eac9 --- /dev/null +++ b/usr.sbin/dhcp/common/dhcp-options.5 @@ -0,0 +1,451 @@ +.\" dhcp-options.5 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 dhcpd-options 5 +.SH NAME +dhcp-options - Dynamic Host Configuration Protocol options +.SH DESCRIPTION +The Dynamic Host Configuration protocol allows the client to receive +.B options +from the DHCP server describing the network configuration and various +services that are available on the network. When configuring +.B dhcpd(8) +or +.B dhclient(8) , +options must often be declared. The syntax for declaring options, +and the names and formats of the options that can be declared, are +documented here. +.SH REFERENCE: OPTION STATEMENTS +.PP +DHCP \fIoption\fR statements always start with the \fIoption\fR +keyword, followed by an option name, followed by option data. The +option names and data formats are described below. It is not +necessary to exhaustively specify all DHCP options - only those +options which are needed by clients must be specified. +.PP +Option data comes in a variety of formats, as defined below: +.PP +The +.B ip-address +data type can be entered either as an explicit IP +address (e.g., 239.254.197.10) or as a domain name (e.g., +haagen.isc.org). When entering a domain name, be sure that that +domain name resolves to a single IP address. +.PP +The +.B int32 +data type specifies a signed 32-bit integer. The +.B uint32 +data type specifies an unsigned 32-bit integer. The +.B int16 +and +.B uint16 +data types specify signed and unsigned 16-bit integers. The +.B int8 +and +.B uint8 +data types specify signed and unsigned 8-bit integers. +Unsigned 8-bit integers are also sometimes referred to as octets. +.PP +The +.B string +data type specifies an NVT ASCII string, which must be +enclosed in double quotes - for example, to specify a domain-name +option, the syntax would be +.nf +.sp 1 + option domain-name "isc.org"; +.fi +.PP +The +.B flag +data type specifies a boolean value. Booleans can be either true or +false (or on or off, if that makes more sense to you). +.PP +The +.B data-string +data type specifies either an NVT ASCII string +enclosed in double quotes, or a series of octets specified in +hexadecimal, seperated by colons. For example: +.nf +.sp 1 + option client-identifier "CLIENT-FOO"; +or + option client-identifier 43:4c:49:45:54:2d:46:4f:4f; +.fi +.PP +The documentation for the various options mentioned below is taken +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 seperated +by colons. For example: +.PP +.nf + option option-133 "my-option-133-text"; + option option-129 1:54:c9:2b:47; +.fi +.PP +Because dhcpd does not know the format of these undefined option codes, +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 +.PP +The subnet mask option specifies the client's subnet mask as per RFC +950. If no subnet mask option is provided anywhere in scope, as a +last resort dhcpd will use the subnet mask from the subnet declaration +for the network on which an address is being assigned. However, +.I any +subnet-mask option declaration that is in scope for the address being +assigned will override the subnet mask specified in the subnet +declaration. +.PP + \fBoption time-offset\fR \fIint32\fR\fB;\fR +.PP +The time-offset option specifies the offset of the client's subnet in +seconds from Coordinated Universal Time (UTC). +.PP + \fBoption routers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption time-servers\fR \fIip-address [, \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBien116-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]; +.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. +.PP + \fBoption\fR \fBdomain-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBlog-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBcookie-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBimpress-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.PP +The impress-server option specifies a list of Imagen Impress servers +available to the client. Servers should be listed in order of +preference. +.PP + \fBoption\fR \fBresource-location-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.PP +This option specifies a list of RFC 887 Resource Location +servers available to the client. Servers should be listed in order +of preference. +.PP + \fBoption\fR \fBhost-name\fR \fIstring\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBboot-size\fR \fIuint16\fR\fB;\fR +.PP +This option specifies the length in 512-octet blocks of the default +boot image for the client. +.PP + \fBoption\fR \fBmerit-dump\fR \fIstring\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBdomain-name\fR \fIstring\fR\fB;\fR +.PP +This option specifies the domain name that client should use when +resolving hostnames via the Domain Name System. +.PP + \fBoption\fR \fBswap-server\fR \fIip-address\fR\fB;\fR +.PP +This specifies the IP address of the client's swap server. +.PP + \fBoption\fR \fBroot-path\fR \fIstring\fB;\fR\fR +.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. +.PP + \fBoption\fR \fBip-forwarding\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBnon-local-source-routing\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBpolicy-filter\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR ... ]\fB;\fR +.PP +This option specifies policy filters for non-local source routing. +The filters consist of a list of IP addresses and masks which specify +destination/mask pairs with which to filter incoming source routes. +.PP +Any source routed datagram whose next-hop address does not match one +of the filters should be discarded by the client. +.PP +See STD 3 (RFC1122) for further information. +.PP + \fBoption\fR \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR +.PP +This option specifies the maximum size datagram that the client +should be prepared to reassemble. The minimum value legal value is +576. +.PP + \fBoption\fR \fBdefault-ip-ttl\fR \fIuint8;\fR +.PP +This option specifies the default time-to-live that the client should +use on outgoing datagrams. +.PP + \fBoption\fR \fBpath-mtu-aging-timeout\fR \fIuint32\fR\fB;\fR +.PP +This option specifies the timeout (in seconds) to use when aging Path +MTU values discovered by the mechanism defined in RFC 1191. +.PP + \fBoption\fR \fBpath-mtu-plateau-table\fR \fIuint16\fR [\fB,\fR \fIuint16\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBinterface-mtu\fR \fIuint16\fR\fB;\fR +.PP +This option specifies the MTU to use on this interface. The minimum +legal value for the MTU is 68. +.PP + \fBoption\fR \fBall-subnets-local\fR \fIflag\fR\fB;\fR +.PP +This option specifies whether or not the client may assume that all +subnets of the IP network to which the client is connected use the +same MTU as the subnet of that network to which the client is +directly connected. A value of 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. +.PP + \fBoption\fR \fBbroadcast-address\fR \fIip-address\fR\fB;\fR +.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). +.PP + \fBoption\fR \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBmask-supplier\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBrouter-discovery\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBrouter-solicitation-address\fR \fIip-address\fR\fB;\fR +.PP +This option specifies the address to which the client should transmit +router solicitation requests. +.PP + \fBoption\fR \fBstatic-routes\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR ... ]\fB;\fR +.PP +This option specifies a list of static routes that the client should +install in its routing cache. If multiple routes to the same +destination are specified, they are listed in descending order of +priority. +.PP +The routes consist of a list of IP address pairs. The first address +is the destination address, and the second address is the router for +the destination. +.PP +The default route (0.0.0.0) is an illegal destination for a static +route. To specify the default route, use the +.B routers +option. +.PP + \fBoption\fR \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBarp-cache-timeout\fR \fIuint32\fR\fB;\fR +.PP +This option specifies the timeout in seconds for ARP cache entries. +.PP + \fBoption\fR \fBieee802-3-encapsulation\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBdefault-tcp-ttl\fR \fIuint8\fR\fB;\fR +.PP +This option specifies the default TTL that the client should use when +sending TCP segments. The minimum value is 1. +.PP + \fBoption\fR \fBtcp-keepalive-interval\fR \fIuint32\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBnis-domain\fR \fIstring\fR\fB;\fR +.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. +.PP + \fBoption\fR \fBnis-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.PP +This option specifies a list of IP addresses indicating NIS servers +available to the client. Servers should be listed in order of +preference. +.PP + \fBoption\fR \fBntp-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBnetbios-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.PP +The NetBIOS name server (NBNS) option specifies a list of RFC +1001/1002 NBNS name servers listed in order of preference. +.PP + \fBoption\fR \fBnetbios-dd-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.PP +The NetBIOS datagram distribution server (NBDD) option specifies a +list of RFC 1001/1002 NBDD servers listed in order of preference. +.PP + \fBoption\fR \fBnetbios-node-type\fR \fIuint8\fR\fB;\fR +.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 +.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. +.PP + \fBoption\fR \fBfont-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.PP +This option specifies a list of X Window System Font servers available +to the client. Servers should be listed in order of preference. +.PP + \fBoption\fR \fBx-display-manager\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR +.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. +.PP + \fBoption\fR \fBdhcp-client-identifier\fR \fIdata-string\fR\fB;\fR +.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. +.SH SEE ALSO +dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcpd(8), +dhclient(8), RFC2132, RFC2131. +.SH AUTHOR +.B dhcpd(8) +was written by Ted Lemon <mellon@vix.com> +under a contract with Vixie Labs. Funding +for this project was provided by the Internet Software Corporation. +Information about the Internet Software Consortium can be found at +.B http://www.isc.org/isc. diff --git a/usr.sbin/dhcp/common/dispatch.c b/usr.sbin/dhcp/common/dispatch.c new file mode 100644 index 00000000000..7a672229859 --- /dev/null +++ b/usr.sbin/dhcp/common/dispatch.c @@ -0,0 +1,747 @@ +/* dispatch.c + + Network input dispatcher... */ + +/* + * 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 <mellon@fugue.com> 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: dispatch.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" +#include <sys/ioctl.h> + +struct interface_info *interfaces, *dummy_interfaces; +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 iaddr, struct hardware *)); + +static void got_one PROTO ((struct protocol *)); +int quiet_interface_discovery; + +/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces. + For each interface that's of type INET and not the loopback interface, + register that interface with the network I/O software, figure out what + subnet it's on, and add it to the list of interfaces. */ + +void discover_interfaces (state) + int state; +{ + struct interface_info *tmp; + struct interface_info *last, *next; + char buf [8192]; + struct ifconf ic; + struct ifreq ifr; + int i; + int sock; + int address_count = 0; + struct subnet *subnet; + struct shared_network *share; + struct sockaddr_in foo; + int ir; +#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) + error ("Can't create addrlist socket"); + + /* Get the interface configuration information... */ + ic.ifc_len = sizeof buf; + ic.ifc_ifcu.ifcu_buf = (caddr_t)buf; + i = ioctl(sock, SIOCGIFCONF, &ic); + + if (i < 0) + error ("ioctl: SIOCGIFCONF: %m"); + + /* If we already have a list of interfaces, and we're running as + a DHCP server, the interfaces were requested. */ + if (interfaces && (state == DISCOVER_SERVER || + state == DISCOVER_RELAY || + state == DISCOVER_REQUESTED)) + ir = 0; + else if (state == DISCOVER_UNCONFIGURED) + ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC; + else + ir = INTERFACE_REQUESTED; + + /* Cycle through the list of interfaces looking for IP addresses. + Go through twice; once to count the number of addresses, and a + second time to copy them into an array of 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; + else +#endif + i += sizeof *ifp; + +#ifdef ALIAS_NAMES_PERMUTED + if ((s = strrchr (ifp -> ifr_name, ':'))) { + *s = 0; + } +#endif + +#ifdef SKIP_DUMMY_INTERFACES + if (!strncmp (ifp -> ifr_name, "dummy", 5)) + continue; +#endif + + + /* See if this is the sort of interface we want to + deal with. */ + strcpy (ifr.ifr_name, ifp -> ifr_name); + if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) + error ("Can't get interface flags for %s: %m", + ifr.ifr_name); + + /* Skip loopback, point-to-point and down interfaces, + 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; + + /* See if we've seen an interface that matches this one. */ + for (tmp = interfaces; tmp; tmp = tmp -> next) + if (!strcmp (tmp -> name, ifp -> ifr_name)) + break; + + /* If there isn't already an interface by this name, + allocate one. */ + if (!tmp) { + tmp = ((struct interface_info *) + dmalloc (sizeof *tmp, "discover_interfaces")); + if (!tmp) + error ("Insufficient memory to %s %s", + "record interface", ifp -> ifr_name); + strcpy (tmp -> name, ifp -> ifr_name); + tmp -> next = interfaces; + tmp -> flags = ir; + 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)); + tmp -> hw_address.hlen = foo -> sdl_alen; + tmp -> hw_address.htype = HTYPE_ETHER; /* XXX */ + 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); + + /* We don't want the loopback interface. */ + if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK)) + continue; + + + /* If this is the first real IP address we've + found, keep a pointer to ifreq structure in + which we found it. */ + if (!tmp -> ifp) { + 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."); + memcpy (tif, ifp, len); + tmp -> ifp = tif; + tmp -> primary_address = foo.sin_addr; + } + + /* Grab the address... */ + addr.len = 4; + memcpy (addr.iabuf, &foo.sin_addr.s_addr, + addr.len); + + /* If there's a registered subnet for this address, + connect it together... */ + if ((subnet = find_subnet (addr))) { + /* If this interface has multiple aliases + on the same subnet, ignore all but the + first we encounter. */ + if (!subnet -> interface) { + subnet -> interface = tmp; + subnet -> interface_address = addr; + } else if (subnet -> interface != tmp) { + warn ("Multiple %s %s: %s %s", + "interfaces match the", + "same subnet", + subnet -> interface -> name, + tmp -> name); + } + share = subnet -> shared_network; + if (tmp -> shared_network && + tmp -> shared_network != share) { + warn ("Interface %s matches %s", + tmp -> name, + "multiple shared networks"); + } else { + tmp -> shared_network = share; + } + + if (!share -> interface) { + share -> interface = tmp; + } else if (share -> interface != tmp) { + warn ("Multiple %s %s: %s %s", + "interfaces match the", + "same shared network", + share -> interface -> name, + tmp -> name); + } + } + } + } + + /* 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) + return; + + /* Weed out the interfaces that did not have IP addresses. */ + last = (struct interface_info *)0; + for (tmp = interfaces; tmp; tmp = next) { + next = tmp -> next; + if ((tmp -> flags & INTERFACE_AUTOMATIC) && + state == DISCOVER_REQUESTED) + tmp -> flags &= ~(INTERFACE_AUTOMATIC | + INTERFACE_REQUESTED); + if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) { + if ((tmp -> flags & INTERFACE_REQUESTED) != ir) + error ("%s: not found", tmp -> name); + if (!last) + interfaces = interfaces -> next; + else + last -> next = tmp -> next; + + /* Remember the interface in case we need to know + about it later. */ + tmp -> next = dummy_interfaces; + dummy_interfaces = tmp; + continue; + } + last = tmp; + + memcpy (&foo, &tmp -> ifp -> ifr_addr, + sizeof tmp -> ifp -> ifr_addr); + + /* We must have a subnet declaration for each interface. */ + if (!tmp -> shared_network && (state == DISCOVER_SERVER)) + error ("No subnet declaration for %s (%s).", + tmp -> name, inet_ntoa (foo.sin_addr)); + + /* Find subnets that don't have valid interface + addresses... */ + for (subnet = (tmp -> shared_network + ? tmp -> shared_network -> subnets + : (struct subnet *)0); + subnet; subnet = subnet -> next_sibling) { + if (!subnet -> interface_address.len) { + /* Set the interface address for this subnet + to the first address we found. */ + subnet -> interface_address.len = 4; + memcpy (subnet -> interface_address.iabuf, + &foo.sin_addr.s_addr, 4); + } + } + + /* Register the interface... */ + if_register_receive (tmp); + if_register_send (tmp); + } + + /* Now register all the remaining interfaces as protocols. */ + for (tmp = interfaces; tmp; tmp = tmp -> next) + add_protocol (tmp -> name, tmp -> rfdesc, got_one, tmp); + + close (sock); + +#ifdef USE_FALLBACK + strcpy (fallback_interface.name, "fallback"); + 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 +} + +void reinitialize_interfaces () +{ + struct interface_info *ip; + + for (ip = interfaces; ip; ip = ip -> next) { + if_reinitialize_receive (ip); + if_reinitialize_send (ip); + } + +#ifdef USE_FALLBACK + if_reinitialize_fallback (&fallback_interface); +#endif + + interfaces_invalidated = 1; +} + +#ifdef USE_POLL +/* Wait for packets to come in using poll(). Anyway, when a packet + comes in, 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. + + As you can see by comparing this with the code that uses select(), + below, this is gratuitously complex. Quelle surprise, eh? This is + SysV we're talking about, after all, and even in the 90's, it + wouldn't do for SysV to make networking *easy*, would it? Rant, + rant... */ + +void dispatch () +{ + struct protocol *l; + int nfds = 0; + struct pollfd *fds; + int count; + int i; + int to_msec; + + nfds = 0; + for (l = protocols; l; l = l -> next) { + ++nfds; + } + fds = (struct pollfd *)malloc ((nfds) * sizeof (struct pollfd)); + if (!fds) + error ("Can't allocate poll structures."); + + do { + /* Call any expired timeouts, and then if there's + still a timeout registered, time out the select + call then. */ + another: + if (timeouts) { + struct timeout *t; + if (timeouts -> when <= cur_time) { + t = timeouts; + timeouts = timeouts -> next; + (*(t -> func)) (t -> what); + t -> next = free_timeouts; + free_timeouts = t; + goto another; + } + /* Figure timeout in milliseconds, and check for + potential overflow. We assume that integers + are 32 bits, which is harmless if they're 64 + bits - we'll just get extra timeouts in that + case. Lease times would have to be quite + long in order for a 32-bit integer to overflow, + anyway. */ + to_msec = timeouts -> when - cur_time; + if (to_msec > 2147483) + to_msec = 2147483; + to_msec *= 1000; + } else + to_msec = -1; + + /* Set up the descriptors to be polled. */ + i = 0; + for (l = protocols; l; l = l -> next) { + fds [i].fd = l -> fd; + fds [i].events = POLLIN; + fds [i].revents = 0; + ++i; + } + + /* Wait for a packet or a timeout... XXX */ + count = poll (fds, nfds, to_msec); + + /* Get the current time... */ + GET_TIME (&cur_time); + + /* Not likely to be transitory... */ + if (count < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + else + error ("poll: %m"); + } + + i = 0; + for (l = protocols; l; l = l -> next) { + 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); +} +#else +/* 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. */ + +void dispatch () +{ + fd_set r, w, x; + struct protocol *l; + int max = 0; + int count; + struct timeval tv, *tvp; + + FD_ZERO (&w); + FD_ZERO (&x); + + do { + /* Call any expired timeouts, and then if there's + still a timeout registered, time out the select + call then. */ + another: + if (timeouts) { + struct timeout *t; + if (timeouts -> when <= cur_time) { + t = timeouts; + timeouts = timeouts -> next; + (*(t -> func)) (t -> what); + t -> next = free_timeouts; + free_timeouts = t; + goto another; + } + tv.tv_sec = timeouts -> when - cur_time; + tv.tv_usec = 0; + tvp = &tv; + } else + tvp = (struct timeval *)0; + + /* Set up the read mask. */ + FD_ZERO (&r); + + for (l = protocols; l; l = l -> next) { + FD_SET (l -> fd, &r); + if (l -> fd > max) + max = l -> fd; + } + + /* Wait for a packet or a timeout... XXX */ + count = select (max + 1, &r, &w, &x, tvp); + + /* Get the current time... */ + GET_TIME (&cur_time); + + /* Not likely to be transitory... */ + if (count < 0) + error ("select: %m"); + + for (l = protocols; l; l = l -> next) { + if (!FD_ISSET (l -> fd, &r)) + continue; + if (l -> handler) + (*(l -> handler)) (l); + if (interfaces_invalidated) + break; + } + interfaces_invalidated = 0; + } while (1); +} +#endif /* USE_POLL */ + +static void got_one (l) + struct protocol *l; +{ + struct sockaddr_in from; + struct hardware hfrom; + struct iaddr ifrom; + int result; + static unsigned char packbuf [4095]; /* Packet input buffer. + Must be as large as largest + possible MTU. */ + struct interface_info *ip = l -> local; + + if ((result = receive_packet (ip, packbuf, sizeof packbuf, + &from, &hfrom)) < 0) { + warn ("receive_packet failed on %s: %m", ip -> name); + return; + } + if (result == 0) + return; + + if (bootp_packet_handler) { + ifrom.len = 4; + memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); + + (*bootp_packet_handler) (ip, packbuf, result, + from.sin_port, ifrom, &hfrom); + } +} + +int locate_network (packet) + struct packet *packet; +{ + struct iaddr ia; + + /* If this came through a gateway, find the corresponding subnet... */ + if (packet -> raw -> giaddr.s_addr) { + struct subnet *subnet; + ia.len = 4; + memcpy (ia.iabuf, &packet -> raw -> giaddr, 4); + subnet = find_subnet (ia); + if (subnet) + packet -> shared_network = subnet -> shared_network; + else + packet -> shared_network = (struct shared_network *)0; + } else { + packet -> shared_network = + packet -> interface -> shared_network; + } + if (packet -> shared_network) + return 1; + return 0; +} + +void add_timeout (when, where, what) + TIME when; + void (*where) PROTO ((void *)); + void *what; +{ + struct timeout *t, *q; + + /* See if this timeout supersedes an existing timeout. */ + t = (struct timeout *)0; + for (q = timeouts; q; q = q -> next) { + if (q -> func == where && q -> what == what) { + if (t) + t -> next = q -> next; + else + timeouts = q -> next; + break; + } + t = q; + } + + /* If we didn't supersede a timeout, allocate a timeout + structure now. */ + if (!q) { + if (free_timeouts) { + q = free_timeouts; + free_timeouts = q -> next; + q -> func = where; + q -> what = what; + } else { + q = (struct timeout *)malloc (sizeof (struct timeout)); + if (!q) + error ("Can't allocate timeout structure!"); + q -> func = where; + q -> what = what; + } + } + + q -> when = when; + + /* Now sort this timeout into the timeout list. */ + + /* Beginning of list? */ + if (!timeouts || timeouts -> when > q -> when) { + q -> next = timeouts; + timeouts = q; + return; + } + + /* Middle of list? */ + for (t = timeouts; t -> next; t = t -> next) { + if (t -> next -> when > q -> when) { + q -> next = t -> next; + t -> next = q; + return; + } + } + + /* End of list. */ + t -> next = q; + q -> next = (struct timeout *)0; +} + +void cancel_timeout (where, what) + void (*where) PROTO ((void *)); + void *what; +{ + struct timeout *t, *q; + + /* Look for this timeout on the list, and unlink it if we find it. */ + t = (struct timeout *)0; + for (q = timeouts; q; q = q -> next) { + if (q -> func == where && q -> what == what) { + if (t) + t -> next = q -> next; + else + timeouts = q -> next; + break; + } + t = q; + } + + /* If we found the timeout, put it on the free list. */ + if (q) { + q -> next = free_timeouts; + free_timeouts = q; + } +} + +/* Add a protocol to the list of protocols... */ +void add_protocol (name, fd, handler, local) + char *name; + int fd; + void (*handler) PROTO ((struct protocol *)); + void *local; +{ + struct protocol *p; + + p = (struct protocol *)malloc (sizeof *p); + if (!p) + error ("can't allocate protocol struct for %s", name); + + p -> fd = fd; + p -> handler = handler; + p -> local = local; + + p -> next = protocols; + protocols = p; +} + +void remove_protocol (proto) + struct protocol *proto; +{ + struct protocol *p, *next, *prev; + + prev = (struct protocol *)0; + for (p = protocols; p; p = next) { + next = p -> next; + if (p == proto) { + if (prev) + prev -> next = p -> next; + else + protocols = p -> next; + free (p); + } + } +} diff --git a/usr.sbin/dhcp/common/dns.c b/usr.sbin/dhcp/common/dns.c new file mode 100644 index 00000000000..1d61b827862 --- /dev/null +++ b/usr.sbin/dhcp/common/dns.c @@ -0,0 +1,403 @@ +/* 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 <mellon@fugue.com> 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.1 1998/08/18 03:43:25 deraadt 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; + struct sockaddr_in from; + + /* 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 seperated 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 len; + int i, 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 len; + int i, 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; + int fl; + 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 new file mode 100644 index 00000000000..761cee47859 --- /dev/null +++ b/usr.sbin/dhcp/common/errwarn.c @@ -0,0 +1,391 @@ +/* errwarn.c + + Errors and warnings... */ + +/* + * Copyright (c) 1996 The Internet Software Consortium. + * All Rights Reserved. + * Copyright (c) 1995 RadioMail Corporation. 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 RadioMail Corporation, 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 RADIOMAIL CORPORATION, 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 RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon + * under a contract with Vixie Enterprises. Further modifications have + * been made for the Internet Software Consortium under a contract + * with Vixie Laboratories. + */ + +#ifndef lint +static char copyright[] = +"$Id: errwarn.c,v 1.1 1998/08/18 03:43:25 deraadt Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" +#include <errno.h> + +static void do_percentm PROTO ((char *obuf, char *ibuf)); + +static char mbuf [1024]; +static char fbuf [1024]; + +int warnings_occurred; + +/* Log an error message, then exit... */ + +void error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT) + KandR (char *fmt;) + va_dcl +{ + va_list list; + extern int logged_in; + + do_percentm (fbuf, fmt); + + VA_start (list, fmt); + vsnprintf (mbuf, sizeof mbuf, fbuf, list); + va_end (list); + +#ifndef DEBUG + syslog (log_priority | LOG_ERR, mbuf); +#endif + + /* Also log it to stderr? */ + if (log_perror) { + write (2, mbuf, strlen (mbuf)); + write (2, "\n", 1); + } + + syslog (LOG_CRIT, "exiting."); + if (log_perror) { + fprintf (stderr, "exiting.\n"); + fflush (stderr); + } + cleanup (); + exit (1); +} + +/* Log a warning message... */ + +int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) + KandR (char *fmt;) + va_dcl +{ + va_list list; + + do_percentm (fbuf, fmt); + + VA_start (list, fmt); + vsnprintf (mbuf, sizeof mbuf, fbuf, list); + va_end (list); + +#ifndef DEBUG + syslog (log_priority | LOG_ERR, mbuf); +#endif + + if (log_perror) { + write (2, mbuf, strlen (mbuf)); + write (2, "\n", 1); + } + + return 0; +} + +/* Log a note... */ + +int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) + KandR (char *fmt;) + va_dcl +{ + va_list list; + + do_percentm (fbuf, fmt); + + VA_start (list, fmt); + vsnprintf (mbuf, sizeof mbuf, fbuf, list); + va_end (list); + +#ifndef DEBUG + syslog (log_priority | LOG_INFO, mbuf); +#endif + + if (log_perror) { + write (2, mbuf, strlen (mbuf)); + write (2, "\n", 1); + } + + return 0; +} + +/* Log a debug message... */ + +int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) + KandR (char *fmt;) + va_dcl +{ + va_list list; + + do_percentm (fbuf, fmt); + + VA_start (list, fmt); + vsnprintf (mbuf, sizeof mbuf, fbuf, list); + va_end (list); + +#ifndef DEBUG + syslog (log_priority | LOG_DEBUG, mbuf); +#endif + + if (log_perror) { + write (2, mbuf, strlen (mbuf)); + write (2, "\n", 1); + } + + return 0; +} + +/* Find %m in the input string and substitute an error message string. */ + +static void do_percentm (obuf, ibuf) + char *obuf; + char *ibuf; +{ + 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 = "<unknown error>"; + strcpy (p - 1, m); + p += strlen (p); + ++s; + } + else + *p++ = *s++; + infmt = 0; + } + else + { + if (*s == '%') + infmt = 1; + *p++ = *s++; + } + } + *p = 0; +} + + +int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT) + KandR (char *fmt;) + va_dcl +{ + va_list list; + static char spaces [] = " "; + + do_percentm (mbuf, fmt); +#ifndef NO_SNPRINTF + 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, mbuf); + syslog (log_priority | LOG_ERR, token_line); + if (lexline < 81) + syslog (log_priority | LOG_ERR, + "%s^", &spaces [sizeof spaces - lexchar]); +#endif + + if (log_perror) { + write (2, mbuf, strlen (mbuf)); + write (2, "\n", 1); + write (2, token_line, strlen (token_line)); + write (2, "\n", 1); + write (2, spaces, lexchar - 1); + write (2, "^\n", 2); + } + + warnings_occurred = 1; + + return 0; +} + +#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/hash.c b/usr.sbin/dhcp/common/hash.c new file mode 100644 index 00000000000..23892c7ce14 --- /dev/null +++ b/usr.sbin/dhcp/common/hash.c @@ -0,0 +1,174 @@ +/* hash.c + + Routines for manipulating hash tables... */ + +/* + * 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 <mellon@fugue.com> 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: 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)); + +struct hash_table *new_hash () +{ + struct hash_table *rv = new_hash_table (DEFAULT_HASH_SIZE, "new_hash"); + if (!rv) + return rv; + memset (&rv -> buckets [0], 0, + DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *)); + return rv; +} + +static INLINE int do_hash (name, len, size) + char *name; + int len; + int size; +{ + register int accum = 0; + register unsigned char *s = (unsigned char *)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); + } + } + } + return accum % size; +} + +void add_hash (table, name, len, pointer) + struct hash_table *table; + int len; + char *name; + unsigned char *pointer; +{ + int hashno; + struct hash_bucket *bp; + + if (!table) + return; + + hashno = do_hash (name, len, table -> hash_count); + bp = new_hash_bucket ("add_hash"); + + if (!bp) { + warn ("Can't add %s to hash table.", name); + return; + } + bp -> name = name; + bp -> value = pointer; + bp -> next = table -> buckets [hashno]; + bp -> len = len; + table -> buckets [hashno] = bp; +} + +void delete_hash_entry (table, name, len) + struct hash_table *table; + int len; + char *name; +{ + int hashno; + struct hash_bucket *bp, *pbp = (struct hash_bucket *)0; + + if (!table) + return; + + 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)) || + (bp -> len == len && + !memcmp (bp -> name, name, len))) { + if (pbp) { + pbp -> next = bp -> next; + } else { + table -> buckets [hashno] = bp -> next; + } + free_hash_bucket (bp, "delete_hash_entry"); + break; + } + pbp = bp; /* jwg, 9/6/96 - nice catch! */ + } +} + +unsigned char *hash_lookup (table, name, len) + struct hash_table *table; + char *name; + int len; +{ + int hashno; + struct hash_bucket *bp; + + if (!table) + return (unsigned char *)0; + 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; + } + return (unsigned char *)0; +} + diff --git a/usr.sbin/dhcp/common/icmp.c b/usr.sbin/dhcp/common/icmp.c new file mode 100644 index 00000000000..157c2ed3ca8 --- /dev/null +++ b/usr.sbin/dhcp/common/icmp.c @@ -0,0 +1,174 @@ +/* dhcp.c + + ICMP Protocol engine - for sending out pings and receiving + responses. */ + +/* + * 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 <mellon@fugue.com> 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: icmp.c,v 1.1 1998/08/18 03:43:26 deraadt 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" + +static int icmp_protocol_initialized; +static int icmp_protocol_fd; + +/* Initialize the ICMP protocol. */ + +void icmp_startup (routep, handler) + int routep; + void (*handler) PROTO ((struct iaddr, u_int8_t *, int)); +{ + struct protoent *proto; + int protocol = 1; + struct sockaddr_in from; + int fd; + int state; + + /* Only initialize icmp once. */ + if (icmp_protocol_initialized) + error ("attempted to reinitialize icmp protocol"); + icmp_protocol_initialized = 1; + + /* Get the protocol number (should be 1). */ + proto = getprotobyname ("icmp"); + if (proto) + protocol = proto -> p_proto; + + /* Get a raw socket for the ICMP protocol. */ + icmp_protocol_fd = socket (AF_INET, SOCK_RAW, protocol); + if (icmp_protocol_fd < 0) + error ("unable to create icmp socket: %m"); + + /* Make sure it does routing... */ + state = 0; + if (setsockopt (icmp_protocol_fd, SOL_SOCKET, SO_DONTROUTE, + (char *)&state, sizeof state) < 0) + error ("Unable to disable SO_DONTROUTE on ICMP socket: %m"); + + add_protocol ("icmp", icmp_protocol_fd, icmp_echoreply, handler); +} + +int icmp_echorequest (addr) + struct iaddr *addr; +{ + struct sockaddr_in to; + struct icmp icmp; + int status; + + 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 */ + + icmp.icmp_type = ICMP_ECHO; + icmp.icmp_code = 0; + icmp.icmp_cksum = 0; + icmp.icmp_seq = 0; +#ifdef PTRSIZE_64BIT + icmp.icmp_id = (((u_int32_t)(u_int64_t)addr) ^ + (u_int32_t)(((u_int64_t)addr) >> 32)); +#else + icmp.icmp_id = (u_int32_t)addr; +#endif + + icmp.icmp_cksum = wrapsum (checksum ((unsigned char *)&icmp, + sizeof icmp, 0)); + + /* Send the ICMP packet... */ + status = sendto (icmp_protocol_fd, (char *)&icmp, sizeof icmp, 0, + (struct sockaddr *)&to, sizeof to); + if (status < 0) + warn ("icmp_echorequest %s: %m", inet_ntoa(to.sin_addr)); + + if (status != sizeof icmp) + return 0; + return 1; +} + +void icmp_echoreply (protocol) + struct protocol *protocol; +{ + struct icmp *icfrom; + struct sockaddr_in from; + unsigned char 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, + (struct sockaddr *)&from, &len); + if (status < 0) { + warn ("icmp_echoreply: %m"); + return; + } + + /* Probably not for us. */ + if (status < (sizeof (struct ip)) + (sizeof *icfrom)) { + return; + } + + len = status - sizeof (struct ip); + icfrom = (struct icmp *)(icbuf + sizeof (struct ip)); + + /* Silently discard ICMP packets that aren't echoreplies. */ + if (icfrom -> icmp_type != ICMP_ECHOREPLY) { + return; + } + + /* If we were given a second-stage handler, call it. */ + if (protocol -> local) { + handler = protocol -> local; + memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr); + ia.len = sizeof from.sin_addr; + + (*handler) (ia, icbuf, len); + } +} diff --git a/usr.sbin/dhcp/common/inet.c b/usr.sbin/dhcp/common/inet.c new file mode 100644 index 00000000000..b7c4ba43848 --- /dev/null +++ b/usr.sbin/dhcp/common/inet.c @@ -0,0 +1,178 @@ +/* inet.c + + Subroutines to manipulate internet addresses in a safely portable + way... */ + +/* + * 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 <mellon@fugue.com> 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" + +/* Return just the network number of an internet address... */ + +struct iaddr subnet_number (addr, mask) + struct iaddr addr; + struct iaddr mask; +{ + int i; + struct iaddr rv; + + rv.len = 0; + + /* Both addresses must have the same length... */ + if (addr.len != mask.len) + return rv; + + rv.len = addr.len; + for (i = 0; i < rv.len; i++) + rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i]; + return rv; +} + +/* Combine a network number and a integer to produce an internet address. + This won't work for subnets with more than 32 bits of host address, but + maybe this isn't a problem. */ + +struct iaddr ip_addr (subnet, mask, host_address) + struct iaddr subnet; + struct iaddr mask; + u_int32_t host_address; +{ + int i, j, k; + u_int32_t swaddr; + struct iaddr rv; + unsigned char habuf [sizeof swaddr]; + + swaddr = htonl (host_address); + memcpy (habuf, &swaddr, sizeof swaddr); + + /* Combine the subnet address and the host address. If + the host address is bigger than can fit in the subnet, + return a zero-length iaddr structure. */ + rv = subnet; + j = rv.len - sizeof habuf; + for (i = sizeof habuf - 1; i >= 0; i--) { + if (mask.iabuf [i + j]) { + if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) { + rv.len = 0; + return rv; + } + for (k = i - 1; k >= 0; k--) { + if (habuf [k]) { + rv.len = 0; + return rv; + } + } + rv.iabuf [i + j] |= habuf [i]; + break; + } else + rv.iabuf [i + j] = habuf [i]; + } + + return rv; +} + +/* Given a subnet number and netmask, return the address on that subnet + for which the host portion of the address is all ones (the standard + broadcast address). */ + +struct iaddr broadcast_addr (subnet, mask) + struct iaddr subnet; + struct iaddr mask; +{ + int i, j, k; + struct iaddr rv; + + if (subnet.len != mask.len) { + rv.len = 0; + return rv; + } + + for (i = 0; i < subnet.len; i++) { + rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255); + } + rv.len = subnet.len; + + return rv; +} + +u_int32_t host_addr (addr, mask) + struct iaddr addr; + struct iaddr mask; +{ + int i; + u_int32_t swaddr; + struct iaddr rv; + + rv.len = 0; + + /* Mask out the network bits... */ + rv.len = addr.len; + for (i = 0; i < rv.len; i++) + rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i]; + + /* Copy out up to 32 bits... */ + memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr); + + /* Swap it and return it. */ + return ntohl (swaddr); +} + +int addr_eq (addr1, addr2) + struct iaddr addr1, addr2; +{ + if (addr1.len != addr2.len) + return 0; + return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0; +} + +char *piaddr (addr) + struct iaddr addr; +{ + static char pbuf [4 * 16]; + char *s = pbuf; + int i; + + if (addr.len == 0) { + strcpy (s, "<null address>"); + } + for (i = 0; i < addr.len; i++) { + sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]); + s += strlen (s); + } + return pbuf; +} diff --git a/usr.sbin/dhcp/common/inet_addr.c b/usr.sbin/dhcp/common/inet_addr.c new file mode 100644 index 00000000000..312e63f7f1e --- /dev/null +++ b/usr.sbin/dhcp/common/inet_addr.c @@ -0,0 +1,150 @@ +/* $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 new file mode 100644 index 00000000000..d425bf54ad5 --- /dev/null +++ b/usr.sbin/dhcp/common/memory.c @@ -0,0 +1,909 @@ +/* memory.c + + Memory-resident database... */ + +/* + * 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 <mellon@fugue.com> 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: memory.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 struct subnet *subnets; +static struct shared_network *shared_networks; +static struct hash_table *host_hw_addr_hash; +static struct hash_table *host_uid_hash; +static struct hash_table *lease_uid_hash; +static struct hash_table *lease_ip_addr_hash; +static struct hash_table *lease_hw_addr_hash; +static struct lease *dangling_leases; + +static struct hash_table *vendor_class_hash; +static struct hash_table *user_class_hash; + +void enter_host (hd) + struct host_decl *hd; +{ + struct host_decl *hp = (struct host_decl *)0; + struct host_decl *np = (struct host_decl *)0; + + hd -> n_ipaddr = (struct host_decl *)0; + + if (hd -> interface.hlen) { + if (!host_hw_addr_hash) + host_hw_addr_hash = new_hash (); + else + hp = (struct host_decl *) + hash_lookup (host_hw_addr_hash, + hd -> interface.haddr, + hd -> interface.hlen); + + /* If there isn't already a host decl matching this + address, add it to the hash table. */ + if (!hp) + add_hash (host_hw_addr_hash, + hd -> interface.haddr, hd -> interface.hlen, + (unsigned char *)hd); + } + + /* If there was already a host declaration for this hardware + address, add this one to the end of the list. */ + + if (hp) { + for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr) + ; + np -> n_ipaddr = hd; + } + + if (hd -> group -> options [DHO_DHCP_CLIENT_IDENTIFIER]) { + if (!tree_evaluate (hd -> group -> options + [DHO_DHCP_CLIENT_IDENTIFIER])) + return; + + /* If there's no uid hash, make one; otherwise, see if + there's already an entry in the hash for this host. */ + if (!host_uid_hash) { + host_uid_hash = new_hash (); + hp = (struct host_decl *)0; + } else + hp = (struct host_decl *) hash_lookup + (host_uid_hash, + hd -> group -> options + [DHO_DHCP_CLIENT_IDENTIFIER] -> value, + hd -> group -> options + [DHO_DHCP_CLIENT_IDENTIFIER] -> len); + + /* If there's already a host declaration for this + client identifier, add this one to the end of the + list. Otherwise, add it to the hash table. */ + if (hp) { + /* Don't link it in twice... */ + if (!np) { + for (np = hp; np -> n_ipaddr; + np = np -> n_ipaddr) + ; + np -> n_ipaddr = hd; + } + } else { + add_hash (host_uid_hash, + hd -> group -> options + [DHO_DHCP_CLIENT_IDENTIFIER] -> value, + hd -> group -> options + [DHO_DHCP_CLIENT_IDENTIFIER] -> len, + (unsigned char *)hd); + } + } +} + +struct host_decl *find_hosts_by_haddr (htype, haddr, hlen) + int htype; + unsigned char *haddr; + int hlen; +{ + struct host_decl *foo; + + foo = (struct host_decl *)hash_lookup (host_hw_addr_hash, + haddr, hlen); + return foo; +} + +struct host_decl *find_hosts_by_uid (data, len) + unsigned char *data; + int len; +{ + struct host_decl *foo; + + foo = (struct host_decl *)hash_lookup (host_uid_hash, data, len); + return foo; +} + +/* More than one host_decl can be returned by find_hosts_by_haddr or + find_hosts_by_uid, and each host_decl can have multiple addresses. + Loop through the list of hosts, and then for each host, through the + list of addresses, looking for an address that's in the same shared + network as the one specified. Store the matching address through + the addr pointer, update the host pointer to point at the host_decl + that matched, and return the subnet that matched. */ + +struct subnet *find_host_for_network (host, addr, share) + struct host_decl **host; + struct iaddr *addr; + struct shared_network *share; +{ + int i; + struct subnet *subnet; + struct iaddr ip_address; + struct host_decl *hp; + + for (hp = *host; hp; hp = hp -> n_ipaddr) { + if (!hp -> fixed_addr || !tree_evaluate (hp -> fixed_addr)) + continue; + for (i = 0; i < hp -> fixed_addr -> len; i += 4) { + ip_address.len = 4; + memcpy (ip_address.iabuf, + hp -> fixed_addr -> value + i, 4); + subnet = find_grouped_subnet (share, ip_address); + if (subnet) { + *addr = ip_address; + *host = hp; + return subnet; + } + } + } + return (struct subnet *)0; +} + +void new_address_range (low, high, subnet, dynamic) + struct iaddr low, high; + struct subnet *subnet; + int dynamic; +{ + struct lease *address_range, *lp, *plp; + struct iaddr net; + int min, max, i; + char lowbuf [16], highbuf [16], netbuf [16]; + struct shared_network *share = subnet -> shared_network; + struct hostent *h; + struct in_addr ia; + + /* All subnets should have attached shared network structures. */ + if (!share) { + strcpy (netbuf, piaddr (subnet -> net)); + error ("No shared network for network %s (%s)", + netbuf, piaddr (subnet -> netmask)); + } + + /* Initialize the hash table if it hasn't been done yet. */ + if (!lease_uid_hash) + lease_uid_hash = new_hash (); + if (!lease_ip_addr_hash) + lease_ip_addr_hash = new_hash (); + if (!lease_hw_addr_hash) + lease_hw_addr_hash = new_hash (); + + /* 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)); + 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)); + error ("Address range %s to %s not on net %s/%s!", + lowbuf, highbuf, piaddr (subnet -> net), netbuf); + } + + /* Get the high and low host addresses... */ + max = host_addr (high, subnet -> netmask); + min = host_addr (low, subnet -> netmask); + + /* Allow range to be specified high-to-low as well as low-to-high. */ + if (min > max) { + max = min; + min = host_addr (high, subnet -> netmask); + } + + /* 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)); + error ("No memory for address range %s-%s.", lowbuf, highbuf); + } + memset (address_range, 0, (sizeof *address_range) * (max - min + 1)); + + /* Fill in the last lease if it hasn't been already... */ + if (!share -> last_lease) { + share -> last_lease = &address_range [0]; + } + + /* Fill out the lease structures with some minimal information. */ + for (i = 0; i < max - min + 1; i++) { + address_range [i].ip_addr = + ip_addr (subnet -> net, subnet -> netmask, i + min); + address_range [i].starts = + address_range [i].timestamp = MIN_TIME; + address_range [i].ends = MIN_TIME; + address_range [i].subnet = subnet; + address_range [i].shared_network = share; + address_range [i].flags = dynamic ? DYNAMIC_BOOTP_OK : 0; + + memcpy (&ia, address_range [i].ip_addr.iabuf, 4); + + if (subnet -> group -> get_lease_hostnames) { + h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET); + if (!h) + warn ("No hostname for %s", inet_ntoa (ia)); + else { + address_range [i].hostname = + malloc (strlen (h -> h_name) + 1); + if (!address_range [i].hostname) + error ("no memory for hostname %s.", + h -> h_name); + strcpy (address_range [i].hostname, + h -> h_name); + } + } + + /* Link this entry into the list. */ + address_range [i].next = share -> leases; + address_range [i].prev = (struct lease *)0; + share -> leases = &address_range [i]; + if (address_range [i].next) + address_range [i].next -> prev = share -> leases; + add_hash (lease_ip_addr_hash, + address_range [i].ip_addr.iabuf, + address_range [i].ip_addr.len, + (unsigned char *)&address_range [i]); + } + + /* Find out if any dangling leases are in range... */ + plp = (struct lease *)0; + for (lp = dangling_leases; lp; lp = lp -> next) { + struct iaddr lnet; + int lhost; + + lnet = subnet_number (lp -> ip_addr, subnet -> netmask); + lhost = host_addr (lp -> ip_addr, subnet -> netmask); + + /* If it's in range, fill in the real lease structure with + the dangling lease's values, and remove the lease from + the list of dangling leases. */ + if (addr_eq (lnet, subnet -> net) && + lhost >= i && lhost <= max) { + if (plp) { + plp -> next = lp -> next; + } else { + dangling_leases = lp -> next; + } + lp -> next = (struct lease *)0; + address_range [lhost - i].hostname = lp -> hostname; + address_range [lhost - i].client_hostname = + lp -> client_hostname; + supersede_lease (&address_range [lhost - i], lp, 0); + free_lease (lp, "new_address_range"); + } else + plp = lp; + } +} + +struct subnet *find_subnet (addr) + struct iaddr addr; +{ + struct subnet *rv; + + for (rv = subnets; rv; rv = rv -> next_subnet) { + if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) + return rv; + } + return (struct subnet *)0; +} + +struct subnet *find_grouped_subnet (share, addr) + struct shared_network *share; + struct iaddr addr; +{ + struct subnet *rv; + + for (rv = share -> subnets; rv; rv = rv -> next_sibling) { + if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) + return rv; + } + return (struct subnet *)0; +} + +/* Enter a new subnet into the subnet list. */ + +void enter_subnet (subnet) + struct subnet *subnet; +{ + struct subnet *scan; + + /* 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); + } + } + + /* XXX Sort the nets into a balanced tree to make searching quicker. */ + subnet -> next_subnet = subnets; + subnets = subnet; +} + +/* Enter a new shared network into the shared network list. */ + +void enter_shared_network (share) + struct shared_network *share; +{ + /* XXX Sort the nets into a balanced tree to make searching quicker. */ + share -> next = shared_networks; + shared_networks = share; +} + +/* Enter a lease into the system. This is called by the parser each + time it reads in a new lease. If the subnet for that lease has + already been read in (usually the case), just update that lease; + otherwise, allocate temporary storage for the lease and keep it around + until we're done reading in the config file. */ + +void enter_lease (lease) + struct lease *lease; +{ + struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr); + + /* If we don't have a place for this lease yet, save it for + later. */ + if (!comp) { + comp = new_lease ("enter_lease"); + if (!comp) { + error ("No memory for lease %s\n", + piaddr (lease -> ip_addr)); + } + *comp = *lease; + lease -> next = dangling_leases; + lease -> prev = (struct lease *)0; + dangling_leases = lease; + } else { + /* Record the hostname information in the lease. */ + comp -> hostname = lease -> hostname; + comp -> client_hostname = lease -> client_hostname; + supersede_lease (comp, lease, 0); + } +} + +/* Replace the data in an existing lease with the data in a new lease; + adjust hash tables to suit, and insertion sort the lease into the + list of leases by expiry time so that we can always find the oldest + lease. */ + +int supersede_lease (comp, lease, commit) + struct lease *comp, *lease; + int commit; +{ + int enter_uid = 0; + int enter_hwaddr = 0; + struct lease *lp; + + /* Static leases are not currently kept in the database... */ + if (lease -> flags & STATIC_LEASE) + return 1; + + /* If the existing lease hasn't expired and has a different + unique identifier or, if it doesn't have a unique + identifier, a different hardware address, then the two + leases are in conflict. If the existing lease has a uid + and the new one doesn't, but they both have the same + hardware address, and dynamic bootp is allowed on this + lease, then we allow that, in case a dynamic BOOTP lease is + requested *after* a DHCP lease has been assigned. */ + + if (!(lease -> flags & ABANDONED_LEASE) && + comp -> ends > cur_time && + (((comp -> uid && lease -> uid) && + (comp -> uid_len != lease -> uid_len || + memcmp (comp -> uid, lease -> uid, comp -> uid_len))) || + (!comp -> uid && + ((comp -> hardware_addr.htype != + lease -> hardware_addr.htype) || + (comp -> hardware_addr.hlen != + lease -> hardware_addr.hlen) || + memcmp (comp -> hardware_addr.haddr, + lease -> hardware_addr.haddr, + comp -> hardware_addr.hlen))))) { + warn ("Lease conflict at %s", + piaddr (comp -> ip_addr)); + return 0; + } else { + /* If there's a Unique ID, dissociate it from the hash + table and free it if necessary. */ + if (comp -> uid) { + uid_hash_delete (comp); + enter_uid = 1; + if (comp -> uid != &comp -> uid_buf [0]) { + free (comp -> uid); + comp -> uid_max = 0; + comp -> uid_len = 0; + } + comp -> uid = (unsigned char *)0; + } else + enter_uid = 1; + + if (comp -> hardware_addr.htype && + ((comp -> hardware_addr.hlen != + lease -> hardware_addr.hlen) || + (comp -> hardware_addr.htype != + lease -> hardware_addr.htype) || + memcmp (comp -> hardware_addr.haddr, + lease -> hardware_addr.haddr, + comp -> hardware_addr.hlen))) { + hw_hash_delete (comp); + enter_hwaddr = 1; + } else if (!comp -> hardware_addr.htype) + enter_hwaddr = 1; + + /* 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, + lease -> uid, lease -> uid_len); + comp -> uid = &comp -> uid_buf [0]; + comp -> uid_max = sizeof comp -> uid_buf; + } else if (lease -> uid != &lease -> uid_buf [0]) { + comp -> uid = lease -> uid; + comp -> uid_max = lease -> uid_max; + lease -> uid = (unsigned char *)0; + lease -> uid_max = 0; + } else { + error ("corrupt lease uid."); /* XXX */ + } + } else { + comp -> uid = (unsigned char *)0; + comp -> uid_max = 0; + } + comp -> uid_len = lease -> uid_len; + comp -> host = lease -> host; + comp -> hardware_addr = lease -> hardware_addr; + comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) | + (comp -> flags & ~EPHEMERAL_FLAGS)); + + /* Record the lease in the uid hash if necessary. */ + if (enter_uid && lease -> uid) { + uid_hash_add (comp); + } + + /* Record it in the hardware address hash if necessary. */ + if (enter_hwaddr && lease -> hardware_addr.htype) { + hw_hash_add (comp); + } + + /* Remove the lease from its current place in the + timeout sequence. */ + if (comp -> prev) { + comp -> prev -> next = comp -> next; + } else { + comp -> shared_network -> leases = comp -> next; + } + if (comp -> next) { + comp -> next -> prev = comp -> prev; + } + if (comp -> shared_network -> last_lease == comp) { + comp -> shared_network -> last_lease = comp -> prev; + } + + /* Find the last insertion point... */ + if (comp == comp -> shared_network -> insertion_point || + !comp -> shared_network -> insertion_point) { + lp = comp -> shared_network -> leases; + } else { + lp = comp -> shared_network -> insertion_point; + } + + if (!lp) { + /* Nothing on the list yet? Just make comp the + head of the list. */ + comp -> shared_network -> leases = comp; + comp -> shared_network -> last_lease = comp; + } else if (lp -> ends > lease -> ends) { + /* Skip down the list until we run out of list + or find a place for comp. */ + while (lp -> next && lp -> ends > lease -> ends) { + lp = lp -> next; + } + if (lp -> ends > lease -> ends) { + /* If we ran out of list, put comp + at the end. */ + lp -> next = comp; + comp -> prev = lp; + comp -> next = (struct lease *)0; + comp -> shared_network -> last_lease = comp; + } else { + /* If we didn't, put it between lp and + the previous item on the list. */ + if ((comp -> prev = lp -> prev)) + comp -> prev -> next = comp; + comp -> next = lp; + lp -> prev = comp; + } + } else { + /* Skip up the list until we run out of list + or find a place for comp. */ + while (lp -> prev && lp -> ends < lease -> ends) { + lp = lp -> prev; + } + if (lp -> ends < lease -> ends) { + /* If we ran out of list, put comp + at the beginning. */ + lp -> prev = comp; + comp -> next = lp; + comp -> prev = (struct lease *)0; + comp -> shared_network -> leases = comp; + } else { + /* If we didn't, put it between lp and + the next item on the list. */ + if ((comp -> next = lp -> next)) + comp -> next -> prev = comp; + comp -> prev = lp; + lp -> next = comp; + } + } + comp -> shared_network -> insertion_point = comp; + comp -> ends = lease -> ends; + } + + /* Return zero if we didn't commit the lease to permanent storage; + nonzero if we did. */ + return commit && write_lease (comp) && commit_leases (); +} + +/* Release the specified lease and re-hash it as appropriate. */ + +void release_lease (lease) + struct lease *lease; +{ + struct lease lt; + + lt = *lease; + lt.ends = cur_time; + supersede_lease (lease, <, 1); +} + +/* Abandon the specified lease (set its timeout to infinity and its + particulars to zero, and re-hash it as appropriate. */ + +void abandon_lease (lease, message) + struct lease *lease; + char *message; +{ + struct lease lt; + + lease -> flags |= ABANDONED_LEASE; + lt = *lease; + lt.ends = MAX_TIME; + warn ("Abandoning IP address %s: %s", + piaddr (lease -> ip_addr), message); + lt.hardware_addr.htype = 0; + lt.hardware_addr.hlen = 0; + lt.uid = (unsigned char *)0; + lt.uid_len = 0; + supersede_lease (lease, <, 1); +} + +/* Locate the lease associated with a given IP address... */ + +struct lease *find_lease_by_ip_addr (addr) + struct iaddr addr; +{ + struct lease *lease = (struct lease *)hash_lookup (lease_ip_addr_hash, + addr.iabuf, + addr.len); + return lease; +} + +struct lease *find_lease_by_uid (uid, len) + unsigned char *uid; + int len; +{ + struct lease *lease = (struct lease *)hash_lookup (lease_uid_hash, + uid, len); + return lease; +} + +struct lease *find_lease_by_hw_addr (hwaddr, hwlen) + unsigned char *hwaddr; + int hwlen; +{ + struct lease *lease = (struct lease *)hash_lookup (lease_hw_addr_hash, + hwaddr, hwlen); + return lease; +} + +/* Add the specified lease to the uid hash. */ + +void uid_hash_add (lease) + struct lease *lease; +{ + struct lease *head = + find_lease_by_uid (lease -> uid, lease -> uid_len); + struct lease *scan; + +#ifdef DEBUG + if (lease -> n_uid) + abort (); +#endif + + /* If it's not in the hash, just add it. */ + if (!head) + add_hash (lease_uid_hash, lease -> uid, + lease -> uid_len, (unsigned char *)lease); + else { + /* Otherwise, attach it to the end of the list. */ + for (scan = head; scan -> n_uid; scan = scan -> n_uid) +#ifdef DEBUG + if (scan == lease) + abort () +#endif + ; + scan -> n_uid = lease; + } +} + +/* Delete the specified lease from the uid hash. */ + +void uid_hash_delete (lease) + struct lease *lease; +{ + struct lease *head = + find_lease_by_uid (lease -> uid, lease -> uid_len); + struct lease *scan; + + /* If it's not in the hash, we have no work to do. */ + if (!head) { + lease -> n_uid = (struct lease *)0; + return; + } + + /* If the lease we're freeing is at the head of the list, + remove the hash table entry and add a new one with the + next lease on the list (if there is one). */ + if (head == lease) { + delete_hash_entry (lease_uid_hash, + lease -> uid, lease -> uid_len); + if (lease -> n_uid) + add_hash (lease_uid_hash, + lease -> n_uid -> uid, + lease -> n_uid -> uid_len, + (unsigned char *)(lease -> n_uid)); + } else { + /* Otherwise, look for the lease in the list of leases + attached to the hash table entry, and remove it if + we find it. */ + for (scan = head; scan -> n_uid; scan = scan -> n_uid) { + if (scan -> n_uid == lease) { + scan -> n_uid = scan -> n_uid -> n_uid; + break; + } + } + } + lease -> n_uid = (struct lease *)0; +} + +/* Add the specified lease to the hardware address hash. */ + +void hw_hash_add (lease) + struct lease *lease; +{ + struct lease *head = + find_lease_by_hw_addr (lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen); + struct lease *scan; + + /* If it's not in the hash, just add it. */ + if (!head) + add_hash (lease_hw_addr_hash, + lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen, + (unsigned char *)lease); + else { + /* Otherwise, attach it to the end of the list. */ + for (scan = head; scan -> n_hw; scan = scan -> n_hw) + ; + scan -> n_hw = lease; + } +} + +/* Delete the specified lease from the hardware address hash. */ + +void hw_hash_delete (lease) + struct lease *lease; +{ + struct lease *head = + find_lease_by_hw_addr (lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen); + struct lease *scan; + + /* If it's not in the hash, we have no work to do. */ + if (!head) { + lease -> n_hw = (struct lease *)0; + return; + } + + /* If the lease we're freeing is at the head of the list, + remove the hash table entry and add a new one with the + next lease on the list (if there is one). */ + if (head == lease) { + delete_hash_entry (lease_hw_addr_hash, + lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen); + if (lease -> n_hw) + add_hash (lease_hw_addr_hash, + lease -> n_hw -> hardware_addr.haddr, + lease -> n_hw -> hardware_addr.hlen, + (unsigned char *)(lease -> n_hw)); + } else { + /* Otherwise, look for the lease in the list of leases + attached to the hash table entry, and remove it if + we find it. */ + for (scan = head; scan -> n_hw; scan = scan -> n_hw) { + if (scan -> n_hw == lease) { + scan -> n_hw = scan -> n_hw -> n_hw; + break; + } + } + } + lease -> n_hw = (struct lease *)0; +} + + +struct class *add_class (type, name) + int type; + char *name; +{ + struct class *class = new_class ("add_class"); + char *tname = (char *)malloc (strlen (name) + 1); + + if (!vendor_class_hash) + vendor_class_hash = new_hash (); + if (!user_class_hash) + user_class_hash = new_hash (); + + if (!tname || !class || !vendor_class_hash || !user_class_hash) + return (struct class *)0; + + memset (class, 0, sizeof *class); + strcpy (tname, name); + class -> name = tname; + + if (type) + add_hash (user_class_hash, + tname, strlen (tname), (unsigned char *)class); + else + add_hash (vendor_class_hash, + tname, strlen (tname), (unsigned char *)class); + return class; +} + +struct class *find_class (type, name, len) + int type; + char *name; + int len; +{ + struct class *class = + (struct class *)hash_lookup (type + ? user_class_hash + : vendor_class_hash, name, len); + return class; +} + +struct group *clone_group (group, caller) + struct group *group; + char *caller; +{ + struct group *g = new_group (caller); + if (!g) + error ("%s: can't allocate new group", caller); + *g = *group; + return g; +} + +/* Write all interesting leases to permanent storage. */ + +void write_leases () +{ + struct lease *l; + struct shared_network *s; + + for (s = shared_networks; s; s = s -> next) { + for (l = s -> leases; l; l = l -> next) { + if (l -> hardware_addr.hlen || + l -> uid_len || + (l -> flags & ABANDONED_LEASE)) + if (!write_lease (l)) + error ("Can't rewrite lease database"); + } + } + if (!commit_leases ()) + error ("Can't commit leases to new database: %m"); +} + +void dump_subnets () +{ + struct lease *l; + struct shared_network *s; + struct subnet *n; + + 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)); + } + for (l = s -> leases; l; l = l -> next) { + print_lease (l); + } + debug ("Last Lease:"); + print_lease (s -> last_lease); + } +} diff --git a/usr.sbin/dhcp/common/nit.c b/usr.sbin/dhcp/common/nit.c new file mode 100644 index 00000000000..296c17a3a1c --- /dev/null +++ b/usr.sbin/dhcp/common/nit.c @@ -0,0 +1,347 @@ +/* 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 <mellon@fugue.com> 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 <sys/ioctl.h> +#include <sys/uio.h> + +#include <sys/time.h> +#include <net/nit.h> +#include <net/nit_if.h> +#include <net/nit_pf.h> +#include <net/nit_buf.h> +#include <sys/stropts.h> +#include <net/packetfilt.h> + +#include <netinet/in_systm.h> +#include "includes/netinet/ip.h" +#include "includes/netinet/udp.h" +#include "includes/netinet/if_ether.h" + +/* Reinitializes the specified interface after an address change. This + is not required for packet-filter APIs. */ + +#ifdef USE_NIT_SEND +void if_reinitialize_send (info) + struct interface_info *info; +{ +} +#endif + +#ifdef USE_NIT_RECEIVE +void if_reinitialize_receive (info) + struct interface_info *info; +{ +} +#endif + +/* Called by get_interface_list for each interface that's discovered. + Opens a packet filter for each interface and adds it to the select + mask. */ + +int if_register_nit (info) + struct interface_info *info; +{ + int sock; + char filename[50]; + struct ifreq ifr; + struct strioctl sio; + + /* Open a NIT device */ + sock = open ("/dev/nit", O_RDWR); + if (sock < 0) + 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 new file mode 100644 index 00000000000..0935c888328 --- /dev/null +++ b/usr.sbin/dhcp/common/options.c @@ -0,0 +1,604 @@ +/* options.c + + DHCP options parsing and reassembly. */ + +/* + * 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 <mellon@fugue.com> 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: options.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 */ + +#define DHCP_OPTION_DATA +#include "dhcpd.h" + +/* Parse all available options out of the specified packet. */ + +void parse_options (packet) + struct packet *packet; +{ + /* Initially, zero all option pointers. */ + memset (packet -> options, 0, sizeof (packet -> options)); + + /* If we don't see the magic cookie, there's nothing to parse. */ + if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) { + packet -> options_valid = 0; + return; + } + + /* Go through the options field, up to the end of the packet + or the End field. */ + parse_option_buffer (packet, &packet -> raw -> options [4], + packet -> packet_length - DHCP_FIXED_NON_UDP - 4); + /* If we parsed a DHCP Option Overload option, parse more + options out of the buffer(s) containing them. */ + if (packet -> options_valid + && packet -> options [DHO_DHCP_OPTION_OVERLOAD].data) { + if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1) + parse_option_buffer (packet, + packet -> raw -> file, + sizeof packet -> raw -> file); + if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2) + parse_option_buffer (packet, + packet -> raw -> sname, + sizeof packet -> raw -> sname); + } +} + +/* Parse options out of the specified buffer, storing addresses of option + values in packet -> options and setting packet -> options_valid if no + errors are encountered. */ + +void parse_option_buffer (packet, buffer, length) + struct packet *packet; + unsigned char *buffer; + int length; +{ + unsigned char *s, *t; + unsigned char *end = buffer + length; + int len; + int code; + + 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; + } + /* 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 (s + len + 2 > end) { + warn ("Option %s length %d overflows input buffer.", + dhcp_options [code].name, + len); + 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))) + error ("Can't allocate storage for option %s.", + dhcp_options [code].name); + /* Copy and NUL-terminate the option (in case it's an + ASCII string. */ + memcpy (t, &s [2], len); + t [len] = 0; + packet -> options [code].len = len; + packet -> options [code].data = t; + } else { + /* 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); + if (!t) + error ("Can't expand storage for option %s.", + dhcp_options [code].name); + memcpy (t, packet -> options [code].data, + packet -> options [code].len); + memcpy (t + packet -> options [code].len, + &s [2], len); + packet -> options [code].len += len; + t [packet -> options [code].len] = 0; + free (packet -> options [code].data); + packet -> options [code].data = t; + } + s += len + 2; + } + packet -> options_valid = 1; +} + +/* cons options into a big buffer, and then split them out into the + three seperate buffers if needed. This allows us to cons up a set + of vendor options using the same routine. */ + +int cons_options (inpacket, outpacket, options, overload, terminate, bootpp) + struct packet *inpacket; + struct dhcp_packet *outpacket; + struct tree_cache **options; + int overload; /* Overload flags that may be set. */ + int terminate; + int bootpp; +{ + unsigned char priority_list [300]; + int priority_len; + unsigned char buffer [4096]; /* Really big buffer... */ + int main_buffer_size; + int mainbufix, bufix; + int option_size; + int length; + + /* 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 (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) + main_buffer_size = 64; + else + main_buffer_size = 576 - DHCP_FIXED_LEN; + + /* Preload the option priority list with mandatory options. */ + priority_len = 0; + priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE; + priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER; + priority_list [priority_len++] = DHO_DHCP_LEASE_TIME; + priority_list [priority_len++] = DHO_DHCP_MESSAGE; + + /* If the client has provided a list of options that it wishes + returned, use it to prioritize. Otherwise, prioritize + based on the default priority list. */ + + if (inpacket && + inpacket -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data) { + int prlen = (inpacket -> + options [DHO_DHCP_PARAMETER_REQUEST_LIST].len); + if (prlen + priority_len > sizeof priority_list) + prlen = (sizeof priority_list) - priority_len; + + memcpy (&priority_list [priority_len], + inpacket -> options + [DHO_DHCP_PARAMETER_REQUEST_LIST].data, prlen); + priority_len += prlen; + } else { + memcpy (&priority_list [priority_len], + dhcp_option_default_priority_list, + sizeof_dhcp_option_default_priority_list); + priority_len += sizeof_dhcp_option_default_priority_list; + } + + /* Copy the options into the big buffer... */ + option_size = store_options (buffer, + (main_buffer_size - 7 + + ((overload & 1) ? DHCP_FILE_LEN : 0) + + ((overload & 2) ? DHCP_SNAME_LEN : 0)), + options, priority_list, priority_len, + main_buffer_size, + (main_buffer_size + + ((overload & 1) ? DHCP_FILE_LEN : 0)), + terminate); + + /* Put the cookie up front... */ + memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4); + mainbufix = 4; + + /* If we're going to have to overload, store the overload + option at the beginning. If we can, though, just store the + whole thing in the packet's option buffer and leave it at + that. */ + if (option_size <= main_buffer_size - mainbufix) { + memcpy (&outpacket -> options [mainbufix], + buffer, option_size); + mainbufix += option_size; + if (mainbufix < main_buffer_size) + outpacket -> options [mainbufix++] + = DHO_END; + length = DHCP_FIXED_NON_UDP + mainbufix; + } else { + outpacket -> options [mainbufix++] = + DHO_DHCP_OPTION_OVERLOAD; + outpacket -> options [mainbufix++] = 1; + if (option_size > main_buffer_size - mainbufix + DHCP_FILE_LEN) + outpacket -> options [mainbufix++] = 3; + else + outpacket -> options [mainbufix++] = 1; + + memcpy (&outpacket -> options [mainbufix], + buffer, main_buffer_size - mainbufix); + bufix = main_buffer_size - mainbufix; + length = DHCP_FIXED_NON_UDP + mainbufix; + if (overload & 1) { + if (option_size - bufix <= DHCP_FILE_LEN) { + memcpy (outpacket -> file, + &buffer [bufix], option_size - bufix); + mainbufix = option_size - bufix; + if (mainbufix < DHCP_FILE_LEN) + outpacket -> file [mainbufix++] + = DHO_END; + while (mainbufix < DHCP_FILE_LEN) + outpacket -> file [mainbufix++] + = DHO_PAD; + } else { + memcpy (outpacket -> file, + &buffer [bufix], DHCP_FILE_LEN); + bufix += DHCP_FILE_LEN; + } + } + if ((overload & 2) && option_size < bufix) { + memcpy (outpacket -> sname, + &buffer [bufix], option_size - bufix); + + mainbufix = option_size - bufix; + if (mainbufix < DHCP_SNAME_LEN) + outpacket -> file [mainbufix++] + = DHO_END; + while (mainbufix < DHCP_SNAME_LEN) + outpacket -> file [mainbufix++] + = DHO_PAD; + } + } + return length; +} + +/* Store all the requested options into the requested buffer. */ + +int store_options (buffer, buflen, options, priority_list, priority_len, + first_cutoff, second_cutoff, terminate) + unsigned char *buffer; + int buflen; + struct tree_cache **options; + unsigned char *priority_list; + int priority_len; + int first_cutoff, second_cutoff; + int terminate; +{ + int bufix = 0; + int option_stored [256]; + int i; + int ix; + int tto; + + /* Zero out the stored-lengths array. */ + memset (option_stored, 0, sizeof option_stored); + + /* Copy out the options in the order that they appear in the + priority list... */ + for (i = 0; i < priority_len; i++) { + /* Code for next option to try to store. */ + int code = priority_list [i]; + int optstart; + + /* Number of bytes left to store (some may already + have been stored by a previous pass). */ + int length; + + /* If no data is available for this option, skip it. */ + if (!options [code]) { + continue; + } + + /* The client could ask for things that are mandatory, + in which case we should avoid storing them twice... */ + if (option_stored [code]) + continue; + option_stored [code] = 1; + + /* Find the value of the option... */ + if (!tree_evaluate (options [code])) { + continue; + } + + /* We should now have a constant length for the option. */ + length = options [code] -> len; + + /* Do we add a NUL? */ + if (terminate && dhcp_options [code].format [0] == 't') { + length++; + tto = 1; + } else { + tto = 0; + } + + /* Try to store the option. */ + + /* If the option's length is more than 255, we must store it + in multiple hunks. Store 255-byte hunks first. However, + in any case, if the option data will cross a buffer + boundary, split it across that boundary. */ + + ix = 0; + + optstart = bufix; + while (length) { + unsigned char incr = length > 255 ? 255 : length; + + /* If this hunk of the buffer will cross a + boundary, only go up to the boundary in this + pass. */ + if (bufix < first_cutoff && + bufix + incr > first_cutoff) + incr = first_cutoff - bufix; + else if (bufix < second_cutoff && + bufix + incr > second_cutoff) + incr = second_cutoff - bufix; + + /* If this option is going to overflow the buffer, + skip it. */ + if (bufix + 2 + incr > buflen) { + bufix = optstart; + break; + } + + /* Everything looks good - copy it in! */ + buffer [bufix] = code; + buffer [bufix + 1] = incr; + if (tto && incr == length) { + memcpy (buffer + bufix + 2, + options [code] -> value + ix, + incr - 1); + buffer [bufix + 2 + incr - 1] = 0; + } else { + memcpy (buffer + bufix + 2, + options [code] -> value + ix, incr); + } + length -= incr; + ix += incr; + bufix += 2 + incr; + } + } + return bufix; +} + +/* Format the specified option so that a human can easily read it. */ + +char *pretty_print_option (code, data, len, emit_commas, emit_quotes) + unsigned int code; + unsigned char *data; + int len; + int emit_commas; + int emit_quotes; +{ + static char optbuf [32768]; /* XXX */ + int hunksize = 0; + int numhunk = -1; + int numelem = 0; + char fmtbuf [32]; + int i, j; + char *op = 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); + + if (emit_commas) + comma = ','; + else + comma = ' '; + + /* Figure out the size of the data. */ + for (i = 0; dhcp_options [code].format [i]; i++) { + if (!numhunk) { + warn ("%s: Excess information in format string: %s\n", + dhcp_options [code].name, + &(dhcp_options [code].format [i])); + break; + } + numelem++; + fmtbuf [i] = dhcp_options [code].format [i]; + switch (dhcp_options [code].format [i]) { + case 'A': + --numelem; + fmtbuf [i] = 0; + numhunk = 0; + break; + case 'X': + fmtbuf [i] = 'x'; + fmtbuf [i + 1] = 0; + hunksize++; + numhunk = 0; + comma = ':'; + break; + case 't': + fmtbuf [i] = 't'; + fmtbuf [i + 1] = 0; + numhunk = -2; + break; + case 'I': + case 'l': + case 'L': + hunksize += 4; + break; + case 's': + case 'S': + hunksize += 2; + break; + case 'b': + case 'B': + case 'f': + hunksize++; + break; + case 'e': + break; + default: + warn ("%s: garbage in format string: %s\n", + dhcp_options [code].name, + &(dhcp_options [code].format [i])); + break; + } + } + + /* Check for too few bytes... */ + if (hunksize > len) { + warn ("%s: expecting at least %d bytes; got %d", + dhcp_options [code].name, + hunksize, len); + return "<error>"; + } + /* Check for too many bytes... */ + if (numhunk == -1 && hunksize < len) + warn ("%s: %d extra bytes", + dhcp_options [code].name, + len - hunksize); + + /* If this is an array, compute its size. */ + if (!numhunk) + numhunk = len / hunksize; + /* See if we got an exact number of hunks. */ + if (numhunk > 0 && numhunk * hunksize < len) + warn ("%s: %d extra bytes at end of array\n", + dhcp_options [code].name, + len - numhunk * hunksize); + + /* A one-hunk array prints the same as a single hunk. */ + if (numhunk < 0) + numhunk = 1; + + /* Cycle through the array (or hunk) printing the data. */ + for (i = 0; i < numhunk; i++) { + for (j = 0; j < numelem; j++) { + switch (fmtbuf [j]) { + case 't': + if (emit_quotes) + *op++ = '"'; + strcpy (op, dp); + op += strlen (dp); + if (emit_quotes) + *op++ = '"'; + *op = 0; + break; + case 'I': + foo.s_addr = htonl (getULong (dp)); + strcpy (op, inet_ntoa (foo)); + dp += 4; + break; + case 'l': + sprintf (op, "%ld", (long)getLong (dp)); + dp += 4; + break; + case 'L': + sprintf (op, "%ld", + (unsigned long)getULong (dp)); + dp += 4; + break; + case 's': + sprintf (op, "%d", getShort (dp)); + dp += 2; + break; + case 'S': + sprintf (op, "%d", getUShort (dp)); + dp += 2; + break; + case 'b': + sprintf (op, "%d", *(char *)dp++); + break; + case 'B': + sprintf (op, "%d", *dp++); + break; + case 'x': + sprintf (op, "%x", *dp++); + break; + case 'f': + strcpy (op, *dp++ ? "true" : "false"); + break; + default: + warn ("Unexpected format code %c", fmtbuf [j]); + } + op += strlen (op); + if (j + 1 < numelem && comma != ':') + *op++ = ' '; + } + if (i + 1 < numhunk) { + *op++ = comma; + } + + } + return optbuf; +} + +void do_packet (interface, packbuf, len, from_port, from, hfrom) + struct interface_info *interface; + unsigned char *packbuf; + int len; + unsigned short from_port; + struct iaddr from; + struct hardware *hfrom; +{ + struct packet tp; + struct dhcp_packet tdp; + + memcpy (&tdp, packbuf, len); + memset (&tp, 0, sizeof tp); + tp.raw = &tdp; + tp.packet_length = len; + tp.client_port = from_port; + tp.client_addr = from; + tp.interface = interface; + tp.haddr = hfrom; + + parse_options (&tp); + if (tp.options_valid && + tp.options [DHO_DHCP_MESSAGE_TYPE].data) + tp.packet_type = + tp.options [DHO_DHCP_MESSAGE_TYPE].data [0]; + if (tp.packet_type) + dhcp (&tp); + else + bootp (&tp); +} + diff --git a/usr.sbin/dhcp/common/packet.c b/usr.sbin/dhcp/common/packet.c new file mode 100644 index 00000000000..87e08d1f5a7 --- /dev/null +++ b/usr.sbin/dhcp/common/packet.c @@ -0,0 +1,311 @@ +/* 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 <mellon@fugue.com> 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: packet.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 (PACKET_ASSEMBLY) || defined (PACKET_DECODING) +#include "includes/netinet/ip.h" +#include "includes/netinet/udp.h" +#include "includes/netinet/if_ether.h" +#endif /* PACKET_ASSEMBLY || PACKET_DECODING */ + +/* Compute the easy part of the checksum on a range of bytes. */ + +u_int32_t checksum (buf, nbytes, sum) + unsigned char *buf; + int nbytes; + u_int32_t sum; +{ + int i; + +#ifdef DEBUG_CHECKSUM + debug ("checksum (%x %d %x)", buf, nbytes, sum); +#endif + + /* Checksum all the pairs of bytes first... */ + for (i = 0; i < (nbytes & ~1); i += 2) { +#ifdef DEBUG_CHECKSUM_VERBOSE + debug ("sum = %x", sum); +#endif + sum += (u_int16_t) ntohs(*((u_int16_t *)(buf + i))); + } + + /* If there's a single byte left over, checksum it, too. Network + byte order is big-endian, so the remaining byte is the high byte. */ + if (i < nbytes) { +#ifdef DEBUG_CHECKSUM_VERBOSE + debug ("sum = %x", sum); +#endif + sum += buf [i] << 8; + } + + return sum; +} + +/* Fold the upper sixteen bits of the checksum down into the lower bits, + complement the sum, and then put it into network byte order. */ + +u_int32_t wrapsum (sum) + u_int32_t sum; +{ +#ifdef DEBUG_CHECKSUM + debug ("wrapsum (%x)", sum); +#endif + + while (sum > 0x10000) { + sum = (sum >> 16) + (sum & 0xFFFF); +#ifdef DEBUG_CHECKSUM_VERBOSE + debug ("sum = %x", sum); +#endif + sum += (sum >> 16); +#ifdef DEBUG_CHECKSUM_VERBOSE + debug ("sum = %x", sum); +#endif + } + sum = sum ^ 0xFFFF; +#ifdef DEBUG_CHECKSUM_VERBOSE + debug ("sum = %x", sum); +#endif + +#ifdef DEBUG_CHECKSUM + debug ("wrapsum returns %x", htons (sum)); +#endif + return htons(sum); +} + +#ifdef PACKET_ASSEMBLY +/* Assemble an hardware header... */ +/* XXX currently only supports ethernet; doesn't check for other types. */ + +void assemble_hw_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)); + +#ifdef BROKEN_FREEBSD_BPF /* Fixed in FreeBSD 2.2 */ + eh.ether_type = ETHERTYPE_IP; +#else + eh.ether_type = htons (ETHERTYPE_IP); +#endif + + memcpy (&buf [*bufix], &eh, sizeof eh); + *bufix += sizeof eh; +} + +/* UDP header and IP header assembled together for convenience. */ + +void assemble_udp_ip_header (interface, buf, bufix, + from, to, port, data, len) + struct interface_info *interface; + unsigned char *buf; + int *bufix; + u_int32_t from; + u_int32_t to; + u_int16_t port; + unsigned char *data; + int len; +{ + struct ip ip; + struct udphdr udp; + + /* Fill out the IP header */ + ip.ip_v = 4; + ip.ip_hl = 5; + ip.ip_tos = IPTOS_LOWDELAY; + ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); + ip.ip_id = 0; + ip.ip_off = 0; + ip.ip_ttl = 16; + ip.ip_p = IPPROTO_UDP; + ip.ip_sum = 0; + ip.ip_src.s_addr = from; + ip.ip_dst.s_addr = to; + + /* Checksum the IP header... */ + ip.ip_sum = wrapsum (checksum ((unsigned char *)&ip, sizeof ip, 0)); + + /* Copy the ip header into the buffer... */ + memcpy (&buf [*bufix], &ip, sizeof ip); + *bufix += sizeof ip; + + /* Fill out the UDP header */ + udp.uh_sport = local_port; /* XXX */ + udp.uh_dport = port; /* XXX */ + udp.uh_ulen = htons(sizeof(udp) + len); + memset (&udp.uh_sum, 0, sizeof udp.uh_sum); + + /* Compute UDP checksums, including the ``pseudo-header'', the UDP + header and the data. */ + +#if 0 + udp.uh_sum = + wrapsum (checksum ((unsigned char *)&udp, sizeof udp, + checksum (data, len, + checksum ((unsigned char *) + &ip.ip_src, + sizeof ip.ip_src, + 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; + unsigned char *buf; + 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; +#endif + memcpy (from -> haddr, eh.ether_shost, sizeof (eh.ether_shost)); + from -> htype = ARPHRD_ETHER; + from -> hlen = sizeof eh.ether_shost; + + return sizeof eh; +} + +/* UDP header and IP header decoded together for convenience. */ + +ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, len) + struct interface_info *interface; + unsigned char *buf; + int bufix; + struct sockaddr_in *from; + unsigned char *data; + int len; +{ + struct ip *ip; + struct udphdr *udp; + u_int32_t ip_len = (buf [bufix] & 0xf) << 2; + u_int32_t sum, usum; + + 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. */ + if (wrapsum (checksum (buf + bufix, ip_len, 0))) { + note ("Bad IP checksum: %x", + wrapsum (checksum (buf + bufix, sizeof *ip, 0))); + return -1; + } + + /* Copy out the IP source address... */ + memcpy (&from -> sin_addr, &ip -> ip_src, 4); + + /* Compute UDP checksums, including the ``pseudo-header'', the UDP + header and the data. If the UDP checksum field is zero, we're + not supposed to do a checksum. */ + + if (!data) { + data = buf + bufix + ip_len + sizeof *udp; + len -= ip_len + sizeof *udp; + } + +#if 0 + usum = udp -> uh_sum; + udp -> uh_sum = 0; + + sum = wrapsum (checksum ((unsigned char *)udp, sizeof *udp, + checksum (data, len, + checksum ((unsigned char *) + &ip -> ip_src, + sizeof ip -> ip_src, + IPPROTO_UDP + + (u_int32_t) + ntohs (udp -> uh_ulen))))); + + if (usum && usum != sum) { + note ("Bad udp checksum: %x %x", usum, sum); + 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 new file mode 100644 index 00000000000..374e2b6e6ec --- /dev/null +++ b/usr.sbin/dhcp/common/parse.c @@ -0,0 +1,642 @@ +/* parse.c + + Common parser code for dhcpd and dhclient. */ + +/* + * 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 <mellon@fugue.com> 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: parse.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" +#include "dhctoken.h" + +/* Skip to the semicolon ending the current statement. If we encounter + braces, the matching closing brace terminates the statement. If we + encounter a right brace but haven't encountered a left brace, return + leaving the brace in the token buffer for the caller. If we see a + semicolon and haven't seen a left brace, return. This lets us skip + over: + + statement; + statement foo bar { } + statement foo bar { statement { } } + statement} + + ...et cetera. */ + +void skip_to_semi (cfile) + FILE *cfile; +{ + int token; + char *val; + int brace_count = 0; + + do { + token = peek_token (&val, cfile); + if (token == RBRACE) { + if (brace_count) { + token = next_token (&val, cfile); + if (!--brace_count) + return; + } else + return; + } else if (token == LBRACE) { + brace_count++; + } else if (token == SEMI && !brace_count) { + token = next_token (&val, cfile); + return; + } else if (token == EOL) { + /* EOL only happens when parsing /etc/resolv.conf, + and we treat it like a semicolon because the + resolv.conf file is line-oriented. */ + token = next_token (&val, cfile); + return; + } + token = next_token (&val, cfile); + } while (token != EOF); +} + +int parse_semi (cfile) + FILE *cfile; +{ + int token; + char *val; + + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + return 0; + } + return 1; +} + +/* string-parameter :== STRING SEMI */ + +char *parse_string (cfile) + FILE *cfile; +{ + char *val; + int token; + char *s; + + token = next_token (&val, cfile); + if (token != STRING) { + parse_warn ("filename must be a string"); + skip_to_semi (cfile); + return (char *)0; + } + s = (char *)malloc (strlen (val) + 1); + if (!s) + error ("no memory for string %s.", val); + strcpy (s, val); + + if (!parse_semi (cfile)) + return (char *)0; + return s; +} + +/* hostname :== identifier | hostname DOT identifier */ + +char *parse_host_name (cfile) + FILE *cfile; +{ + char *val; + int token; + int len = 0; + char *s; + char *t; + pair c = (pair)0; + + /* Read a dotted hostname... */ + do { + /* Read a token, which should be an identifier. */ + token = next_token (&val, cfile); + if (!is_identifier (token) && token != NUMBER) { + parse_warn ("expecting an identifier in hostname"); + skip_to_semi (cfile); + return (char *)0; + } + /* Store this identifier... */ + if (!(s = (char *)malloc (strlen (val) + 1))) + error ("can't allocate temp space for hostname."); + strcpy (s, val); + c = cons ((caddr_t)s, c); + len += strlen (s) + 1; + /* Look for a dot; if it's there, keep going, otherwise + we're done. */ + token = peek_token (&val, cfile); + if (token == DOT) + token = next_token (&val, cfile); + } while (token == DOT); + + /* Assemble the hostname together into a string. */ + if (!(s = (char *)malloc (len))) + error ("can't allocate space for hostname."); + t = s + len; + *--t = 0; + while (c) { + pair cdr = c -> cdr; + int l = strlen ((char *)(c -> car)); + t -= l; + memcpy (t, (char *)(c -> car), l); + /* Free up temp space. */ + free (c -> car); + free (c); + c = cdr; + if (t != s) + *--t = '.'; + } + return s; +} + +int parse_ip_addr (cfile, addr) + FILE *cfile; + struct iaddr *addr; +{ + char *val; + int token; + + addr -> len = 4; + if (parse_numeric_aggregate (cfile, addr -> iabuf, + &addr -> len, DOT, 10, 8)) + return 1; + return 0; +} + +/* hardware-parameter :== HARDWARE ETHERNET csns SEMI + csns :== NUMBER | csns COLON NUMBER */ + +void parse_hardware_param (cfile, hardware) + FILE *cfile; + struct hardware *hardware; +{ + char *val; + int token; + int hlen; + unsigned char *t; + + token = next_token (&val, cfile); + switch (token) { + case ETHERNET: + hardware -> htype = HTYPE_ETHER; + break; + case TOKEN_RING: + hardware -> htype = HTYPE_IEEE802; + break; + default: + parse_warn ("expecting a network hardware type"); + skip_to_semi (cfile); + return; + } + + /* Parse the hardware address information. Technically, + it would make a lot of sense to restrict the length of the + data we'll accept here to the length of a particular hardware + address type. Unfortunately, there are some broken clients + out there that put bogus data in the chaddr buffer, and we accept + that data in the lease file rather than simply failing on such + clients. Yuck. */ + hlen = 0; + t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen, + COLON, 16, 8); + if (!t) + return; + if (hlen > sizeof hardware -> haddr) { + free (t); + parse_warn ("hardware address too long"); + } else { + hardware -> hlen = hlen; + memcpy ((unsigned char *)&hardware -> haddr [0], + t, hardware -> hlen); + free (t); + } + + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("expecting semicolon."); + skip_to_semi (cfile); + } +} + +/* lease-time :== NUMBER SEMI */ + +void parse_lease_time (cfile, timep) + FILE *cfile; + TIME *timep; +{ + char *val; + int token; + + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("Expecting numeric lease time"); + skip_to_semi (cfile); + return; + } + convert_num ((unsigned char *)timep, val, 10, 32); + /* Unswap the number - convert_num returns stuff in NBO. */ + *timep = ntohl (*timep); /* XXX */ + + parse_semi (cfile); +} + +/* No BNF for numeric aggregates - that's defined by the caller. What + this function does is to parse a sequence of numbers seperated by + the token specified in seperator. If max is zero, any number of + numbers will be parsed; otherwise, exactly max numbers are + expected. Base and size tell us how to internalize the numbers + once they've been tokenized. */ + +unsigned char *parse_numeric_aggregate (cfile, buf, + max, seperator, base, size) + FILE *cfile; + unsigned char *buf; + int *max; + int seperator; + int base; + int size; +{ + char *val; + int token; + unsigned char *bufp = buf, *s, *t; + int count = 0; + pair c = (pair)0; + + if (!bufp && *max) { + bufp = (unsigned char *)malloc (*max * size / 8); + if (!bufp) + error ("can't allocate space for numeric aggregate"); + } else + s = bufp; + + do { + if (count) { + token = peek_token (&val, cfile); + if (token != seperator) { + if (!*max) + break; + if (token != RBRACE && token != LBRACE) + token = next_token (&val, cfile); + parse_warn ("too few numbers."); + if (token != SEMI) + skip_to_semi (cfile); + return (unsigned char *)0; + } + token = next_token (&val, cfile); + } + token = next_token (&val, cfile); + + if (token == EOF) { + parse_warn ("unexpected end of file"); + break; + } + + /* Allow NUMBER_OR_NAME if base is 16. */ + if (token != NUMBER && + (base != 16 || token != NUMBER_OR_NAME)) { + parse_warn ("expecting numeric value."); + skip_to_semi (cfile); + return (unsigned char *)0; + } + /* If we can, convert the number now; otherwise, build + a linked list of all the numbers. */ + if (s) { + convert_num (s, val, base, size); + s += size / 8; + } else { + t = (unsigned char *)malloc (strlen (val) + 1); + if (!t) + error ("no temp space for number."); + strcpy (t, val); + c = cons (t, c); + } + } while (++count != *max); + + /* If we had to cons up a list, convert it now. */ + if (c) { + bufp = (unsigned char *)malloc (count * size / 8); + if (!bufp) + error ("can't allocate space for numeric aggregate."); + s = bufp + count - size / 8; + *max = count; + } + while (c) { + pair cdr = c -> cdr; + convert_num (s, (char *)(c -> car), base, size); + s -= size / 8; + /* Free up temp space. */ + free (c -> car); + free (c); + c = cdr; + } + return bufp; +} + +void convert_num (buf, str, base, size) + unsigned char *buf; + char *str; + int base; + int size; +{ + char *ptr = str; + int negative = 0; + u_int32_t val = 0; + int tval; + int max; + + if (*ptr == '-') { + negative = 1; + ++ptr; + } + + /* If base wasn't specified, figure it out from the data. */ + if (!base) { + if (ptr [0] == '0') { + if (ptr [1] == 'x') { + base = 16; + ptr += 2; + } else if (isascii (ptr [1]) && isdigit (ptr [1])) { + base = 8; + ptr += 1; + } else { + base = 10; + } + } else { + base = 10; + } + } + + do { + tval = *ptr++; + /* XXX assumes ASCII... */ + if (tval >= 'a') + tval = tval - 'a' + 10; + else if (tval >= 'A') + tval = tval - 'A' + 10; + else if (tval >= '0') + tval -= '0'; + else { + warn ("Bogus number: %s.", str); + break; + } + if (tval >= base) { + warn ("Bogus number: %s: digit %d not in base %d\n", + str, tval, base); + break; + } + val = val * base + tval; + } while (*ptr); + + if (negative) + max = (1 << (size - 1)); + else + max = (1 << (size - 1)) + ((1 << (size - 1)) - 1); + if (val > max) { + switch (base) { + case 8: + warn ("value %s%o exceeds max (%d) for precision.", + negative ? "-" : "", val, max); + break; + case 16: + warn ("value %s%x exceeds max (%d) for precision.", + negative ? "-" : "", val, max); + break; + default: + warn ("value %s%u exceeds max (%d) for precision.", + negative ? "-" : "", val, max); + break; + } + } + + if (negative) { + switch (size) { + case 8: + *buf = -(unsigned long)val; + break; + case 16: + putShort (buf, -(unsigned long)val); + break; + case 32: + putLong (buf, -(unsigned long)val); + break; + default: + warn ("Unexpected integer size: %d\n", size); + break; + } + } else { + switch (size) { + case 8: + *buf = (u_int8_t)val; + break; + case 16: + putUShort (buf, (u_int16_t)val); + break; + case 32: + putULong (buf, val); + break; + default: + warn ("Unexpected integer size: %d\n", size); + break; + } + } +} + +/* date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER + NUMBER COLON NUMBER COLON NUMBER SEMI + + Dates are always in GMT; first number is day of week; next is + year/month/day; next is hours:minutes:seconds on a 24-hour + clock. */ + +TIME parse_date (cfile) + FILE *cfile; +{ + struct tm tm; + int guess; + char *val; + int token; + static int months [11] = { 31, 59, 90, 120, 151, 181, + 212, 243, 273, 304, 334 }; + + /* Day of week... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric day of week expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_wday = atoi (val); + + /* Year... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric year expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_year = atoi (val); + if (tm.tm_year > 1900) + tm.tm_year -= 1900; + + /* Slash seperating year from month... */ + token = next_token (&val, cfile); + if (token != SLASH) { + parse_warn ("expected slash seperating year from month."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + + /* Month... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric month expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_mon = atoi (val) - 1; + + /* Slash seperating month from day... */ + token = next_token (&val, cfile); + if (token != SLASH) { + parse_warn ("expected slash seperating month from day."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + + /* Month... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric day of month expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_mday = atoi (val); + + /* Hour... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric hour expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_hour = atoi (val); + + /* Colon seperating hour from minute... */ + token = next_token (&val, cfile); + if (token != COLON) { + parse_warn ("expected colon seperating hour from minute."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + + /* Minute... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric minute expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_min = atoi (val); + + /* Colon seperating minute from second... */ + token = next_token (&val, cfile); + if (token != COLON) { + parse_warn ("expected colon seperating hour from minute."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + + /* Minute... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + parse_warn ("numeric minute expected."); + if (token != SEMI) + skip_to_semi (cfile); + return (TIME)0; + } + tm.tm_sec = atoi (val); + tm.tm_isdst = 0; + + /* XXX */ /* We assume that mktime does not use tm_yday. */ + tm.tm_yday = 0; + + /* Make sure the date ends in a semicolon... */ + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + return 0; + } + + /* Guess the time value... */ + guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */ + (tm.tm_year - 69) / 4 + /* Leap days since '70 */ + (tm.tm_mon /* Days in months this year */ + ? months [tm.tm_mon - 1] + : 0) + + (tm.tm_mon > 1 && /* Leap day this year */ + !((tm.tm_year - 72) & 3)) + + tm.tm_mday - 1) * 24) + /* Day of month */ + tm.tm_hour) * 60) + + tm.tm_min) * 60) + tm.tm_sec; + + /* This guess could be wrong because of leap seconds or other + weirdness we don't know about that the system does. For + now, we're just going to accept the guess, but at some point + it might be nice to do a successive approximation here to + get an exact value. Even if the error is small, if the + server is restarted frequently (and thus the lease database + is reread), the error could accumulate into something + significant. */ + + return guess; +} diff --git a/usr.sbin/dhcp/common/print.c b/usr.sbin/dhcp/common/print.c new file mode 100644 index 00000000000..7ff64ffdd46 --- /dev/null +++ b/usr.sbin/dhcp/common/print.c @@ -0,0 +1,184 @@ +/* print.c + + Turn data structures into printable text. */ + +/* + * 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 <mellon@fugue.com> 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: 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) + int htype; + int hlen; + unsigned char *data; +{ + static char habuf [49]; + char *s; + int i; + + if (htype == 0 || hlen == 0) { + strcpy (habuf, "<null>"); + } else { + s = habuf; + for (i = 0; i < hlen; i++) { + sprintf (s, "%02x", data [i]); + s += strlen (s); + *s++ = ':'; + } + *--s = 0; + } + return habuf; +} + +void print_lease (lease) + struct lease *lease; +{ + struct tm *t; + char tbuf [32]; + + debug (" Lease %s", + piaddr (lease -> ip_addr)); + + t = gmtime (&lease -> starts); + strftime (tbuf, sizeof tbuf, "%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); + + t = gmtime (&lease -> timestamp); + strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t); + debug (" stamp %s", tbuf); + + debug (" hardware addr = %s", + print_hw_addr (lease -> hardware_addr.htype, + lease -> hardware_addr.hlen, + lease -> hardware_addr.haddr)); + debug (" host %s ", + lease -> host ? lease -> host -> name : "<none>"); +} + +void dump_packet (tp) + struct packet *tp; +{ + struct dhcp_packet *tdp = tp -> raw; + + debug ("packet length %d", tp -> packet_length); + debug ("op = %d htype = %d hlen = %d hops = %d", + tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops); + debug ("xid = %x secs = %d flags = %x", + tdp -> xid, tdp -> secs, tdp -> flags); + debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr)); + debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr)); + debug ("siaddr = %s", inet_ntoa (tdp -> siaddr)); + debug ("giaddr = %s", inet_ntoa (tdp -> giaddr)); + debug ("chaddr = %02.2x:%02.2x:%02.2x:%02.2x:%02.2x:%02.2x", + ((unsigned char *)(tdp -> chaddr)) [0], + ((unsigned char *)(tdp -> chaddr)) [1], + ((unsigned char *)(tdp -> chaddr)) [2], + ((unsigned char *)(tdp -> chaddr)) [3], + ((unsigned char *)(tdp -> chaddr)) [4], + ((unsigned char *)(tdp -> chaddr)) [5]); + debug ("filename = %s", tdp -> file); + debug ("server_name = %s", tdp -> sname); + if (tp -> options_valid) { + int i; + + for (i = 0; i < 256; i++) { + if (tp -> options [i].data) + debug (" %s = %s", + dhcp_options [i].name, + pretty_print_option + (i, tp -> options [i].data, + tp -> options [i].len, 1, 1)); + } + } + debug (""); +} + +void dump_raw (buf, len) + unsigned char *buf; + int len; +{ + int i; + char lbuf [80]; + int lbix = 0; + + lbuf [0] = 0; + + for (i = 0; i < len; i++) { + if ((i & 15) == 0) { + if (lbix) + note (lbuf); + sprintf (lbuf, "%03x:", i); + lbix = 4; + } else if ((i & 7) == 0) + lbuf [lbix++] = ' '; + sprintf (&lbuf [lbix], " %02x", buf [i]); + lbix += 3; + } + note (lbuf); +} + +void hash_dump (table) + struct hash_table *table; +{ + int i; + struct hash_bucket *bp; + + if (!table) + return; + + for (i = 0; i < table -> hash_count; i++) { + if (!table -> buckets [i]) + continue; + note ("hash bucket %d:", i); + for (bp = table -> buckets [i]; bp; bp = bp -> next) { + if (bp -> len) + dump_raw (bp -> name, bp -> len); + else + note (bp -> name); + } + } +} diff --git a/usr.sbin/dhcp/common/raw.c b/usr.sbin/dhcp/common/raw.c new file mode 100644 index 00000000000..38c53121500 --- /dev/null +++ b/usr.sbin/dhcp/common/raw.c @@ -0,0 +1,132 @@ +/* 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 <mellon@fugue.com> 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 <sys/uio.h> + +/* Generic interface registration routine... */ +void if_register_send (info) + struct interface_info *info; +{ + struct sockaddr_in name; + int sock; + struct socklist *tmp; + int flag; + + /* Set up the address we're going to connect to. */ + name.sin_family = AF_INET; + name.sin_port = local_port; + name.sin_addr.s_addr = htonl (INADDR_BROADCAST); + memset (name.sin_zero, 0, sizeof (name.sin_zero)); + + /* List addresses on which we're listening. */ + if (!quiet_interface_discovery) + 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 new file mode 100644 index 00000000000..7bd79e68093 --- /dev/null +++ b/usr.sbin/dhcp/common/resolv.c @@ -0,0 +1,206 @@ +/* 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 <mellon@fugue.com> 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.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" +#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; + int declaration = 0; + struct name_server *sp, *sl, *ns; + struct domain_search_list *dp, *dl, *nd; + struct iaddr *iaddr; + + 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 () +{ + FILE *rc; + static TIME rcdate; + struct stat st; + + /* Check /etc/resolv.conf and reload it if it's changed. */ + if (cur_time > rcdate) { + if (stat (path_resolv_conf, &st) < 0) { + warn ("Can't stat %s", path_resolv_conf); + return (struct sockaddr_in *)0; + } + if (st.st_mtime > rcdate) { + char rcbuf [512]; + char *s, *t, *u; + 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 new file mode 100644 index 00000000000..c8d086be479 --- /dev/null +++ b/usr.sbin/dhcp/common/socket.c @@ -0,0 +1,256 @@ +/* socket.c + + BSD socket interface code... */ + +/* + * Copyright (c) 1995, 1996, 1997, 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 + * 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 <mellon@fugue.com> 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''. + */ + +/* 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.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" + +#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; +{ + struct sockaddr_in name; + 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; + name.sin_addr.s_addr = INADDR_ANY; + memset (name.sin_zero, 0, sizeof (name.sin_zero)); + + /* Make a socket... */ + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + error ("Can't create dhcp socket: %m"); + + /* Set the REUSEADDR option so that we don't fail to start if + we're being restarted. */ + flag = 1; + if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&flag, sizeof flag) < 0) + error ("Can't set SO_REUSEADDR option on dhcp socket: %m"); + + /* Set the BROADCAST option so that we can broadcast DHCP responses. */ + if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, + (char *)&flag, sizeof flag) < 0) + error ("Can't set SO_BROADCAST option on dhcp socket: %m"); + + /* Bind the socket to this interface's IP address. */ + if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) + 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) + 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 */ + +#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", + info -> name, + (info -> shared_network ? + info -> shared_network -> name : "unattached")); +} +#endif /* USE_SOCKET_RECEIVE */ + +#ifdef USE_SOCKET_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 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; + +#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 + return result; +} +#endif /* USE_SOCKET_RECEIVE */ + +#ifdef USE_SOCKET_FALLBACK +/* This just reads in a packet and silently discards it. */ + +void fallback_discard (protocol) + struct protocol *protocol; +{ + char buf [1540]; + struct sockaddr_in from; + int flen = sizeof from; + int status; + struct interface_info *interface = protocol -> local; + + status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0, + (struct sockaddr *)&from, &flen); + 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 new file mode 100644 index 00000000000..98cbb1073cf --- /dev/null +++ b/usr.sbin/dhcp/common/sysconf.c @@ -0,0 +1,134 @@ +/* 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 <mellon@fugue.com> 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 new file mode 100644 index 00000000000..454962a0857 --- /dev/null +++ b/usr.sbin/dhcp/common/tables.c @@ -0,0 +1,690 @@ +/* tables.c + + Tables of information... */ + +/* + * 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 <mellon@fugue.com> 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: 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. + + Format codes: + + e - end of data + I - IP address + l - 32-bit signed integer + L - 32-bit unsigned integer + s - 16-bit signed integer + S - 16-bit unsigned integer + b - 8-bit signed integer + B - 8-bit unsigned integer + t - ASCII text + f - flag (true or false) + A - array of whatever precedes (e.g., IA means array of IP addresses) +*/ + +struct universe dhcp_universe; +struct option dhcp_options [256] = { + { "pad", "", &dhcp_universe, 0 }, + { "subnet-mask", "I", &dhcp_universe, 1 }, + { "time-offset", "l", &dhcp_universe, 2 }, + { "routers", "IA", &dhcp_universe, 3 }, + { "time-servers", "IA", &dhcp_universe, 4 }, + { "ien116-name-servers", "IA", &dhcp_universe, 5 }, + { "domain-name-servers", "IA", &dhcp_universe, 6 }, + { "log-servers", "IA", &dhcp_universe, 7 }, + { "cookie-servers", "IA", &dhcp_universe, 8 }, + { "lpr-servers", "IA", &dhcp_universe, 9 }, + { "impress-servers", "IA", &dhcp_universe, 10 }, + { "resource-location-servers", "IA", &dhcp_universe, 11 }, + { "host-name", "t", &dhcp_universe, 12 }, + { "boot-size", "S", &dhcp_universe, 13 }, + { "merit-dump", "t", &dhcp_universe, 14 }, + { "domain-name", "t", &dhcp_universe, 15 }, + { "swap-server", "I", &dhcp_universe, 16 }, + { "root-path", "t", &dhcp_universe, 17 }, + { "extensions-path", "t", &dhcp_universe, 18 }, + { "ip-forwarding", "f", &dhcp_universe, 19 }, + { "non-local-source-routing", "f", &dhcp_universe, 20 }, + { "policy-filter", "IIA", &dhcp_universe, 21 }, + { "max-dgram-reassembly", "S", &dhcp_universe, 22 }, + { "default-ip-ttl", "B", &dhcp_universe, 23 }, + { "path-mtu-aging-timeout", "L", &dhcp_universe, 24 }, + { "path-mtu-plateau-table", "SA", &dhcp_universe, 25 }, + { "interface-mtu", "S", &dhcp_universe, 26 }, + { "all-subnets-local", "f", &dhcp_universe, 27 }, + { "broadcast-address", "I", &dhcp_universe, 28 }, + { "perform-mask-discovery", "f", &dhcp_universe, 29 }, + { "mask-supplier", "f", &dhcp_universe, 30 }, + { "router-discovery", "f", &dhcp_universe, 31 }, + { "router-solicitation-address", "I", &dhcp_universe, 32 }, + { "static-routes", "IIA", &dhcp_universe, 33 }, + { "trailer-encapsulation", "f", &dhcp_universe, 34 }, + { "arp-cache-timeout", "L", &dhcp_universe, 35 }, + { "ieee802-3-encapsulation", "f", &dhcp_universe, 36 }, + { "default-tcp-ttl", "B", &dhcp_universe, 37 }, + { "tcp-keepalive-interval", "L", &dhcp_universe, 38 }, + { "tcp-keepalive-garbage", "f", &dhcp_universe, 39 }, + { "nis-domain", "t", &dhcp_universe, 40 }, + { "nis-servers", "IA", &dhcp_universe, 41 }, + { "ntp-servers", "IA", &dhcp_universe, 42 }, + { "vendor-encapsulated-options", "X", &dhcp_universe, 43 }, + { "netbios-name-servers", "IA", &dhcp_universe, 44 }, + { "netbios-dd-server", "IA", &dhcp_universe, 45 }, + { "netbios-node-type", "B", &dhcp_universe, 46 }, + { "netbios-scope", "t", &dhcp_universe, 47 }, + { "font-servers", "IA", &dhcp_universe, 48 }, + { "x-display-manager", "IA", &dhcp_universe, 49 }, + { "dhcp-requested-address", "I", &dhcp_universe, 50 }, + { "dhcp-lease-time", "L", &dhcp_universe, 51 }, + { "dhcp-option-overload", "B", &dhcp_universe, 52 }, + { "dhcp-message-type", "B", &dhcp_universe, 53 }, + { "dhcp-server-identifier", "I", &dhcp_universe, 54 }, + { "dhcp-parameter-request-list", "BA", &dhcp_universe, 55 }, + { "dhcp-message", "t", &dhcp_universe, 56 }, + { "dhcp-max-message-size", "S", &dhcp_universe, 57 }, + { "dhcp-renewal-time", "L", &dhcp_universe, 58 }, + { "dhcp-rebinding-time", "L", &dhcp_universe, 59 }, + { "dhcp-class-identifier", "t", &dhcp_universe, 60 }, + { "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 }, + { "option-78", "X", &dhcp_universe, 78 }, + { "option-79", "X", &dhcp_universe, 79 }, + { "option-80", "X", &dhcp_universe, 80 }, + { "option-81", "X", &dhcp_universe, 81 }, + { "option-82", "X", &dhcp_universe, 82 }, + { "option-83", "X", &dhcp_universe, 83 }, + { "option-84", "X", &dhcp_universe, 84 }, + { "nds-servers", "IA", &dhcp_universe, 85 }, + { "nds-tree-name", "X", &dhcp_universe, 86 }, + { "nds-context", "X", &dhcp_universe, 87 }, + { "option-88", "X", &dhcp_universe, 88 }, + { "option-89", "X", &dhcp_universe, 89 }, + { "option-90", "X", &dhcp_universe, 90 }, + { "option-91", "X", &dhcp_universe, 91 }, + { "option-92", "X", &dhcp_universe, 92 }, + { "option-93", "X", &dhcp_universe, 93 }, + { "option-94", "X", &dhcp_universe, 94 }, + { "option-95", "X", &dhcp_universe, 95 }, + { "option-96", "X", &dhcp_universe, 96 }, + { "option-97", "X", &dhcp_universe, 97 }, + { "option-98", "X", &dhcp_universe, 98 }, + { "option-99", "X", &dhcp_universe, 99 }, + { "option-100", "X", &dhcp_universe, 100 }, + { "option-101", "X", &dhcp_universe, 101 }, + { "option-102", "X", &dhcp_universe, 102 }, + { "option-103", "X", &dhcp_universe, 103 }, + { "option-104", "X", &dhcp_universe, 104 }, + { "option-105", "X", &dhcp_universe, 105 }, + { "option-106", "X", &dhcp_universe, 106 }, + { "option-107", "X", &dhcp_universe, 107 }, + { "option-108", "X", &dhcp_universe, 108 }, + { "option-109", "X", &dhcp_universe, 109 }, + { "option-110", "X", &dhcp_universe, 110 }, + { "option-111", "X", &dhcp_universe, 111 }, + { "option-112", "X", &dhcp_universe, 112 }, + { "option-113", "X", &dhcp_universe, 113 }, + { "option-114", "X", &dhcp_universe, 114 }, + { "option-115", "X", &dhcp_universe, 115 }, + { "option-116", "X", &dhcp_universe, 116 }, + { "option-117", "X", &dhcp_universe, 117 }, + { "option-118", "X", &dhcp_universe, 118 }, + { "option-119", "X", &dhcp_universe, 119 }, + { "option-120", "X", &dhcp_universe, 120 }, + { "option-121", "X", &dhcp_universe, 121 }, + { "option-122", "X", &dhcp_universe, 122 }, + { "option-123", "X", &dhcp_universe, 123 }, + { "option-124", "X", &dhcp_universe, 124 }, + { "option-125", "X", &dhcp_universe, 125 }, + { "option-126", "X", &dhcp_universe, 126 }, + { "option-127", "X", &dhcp_universe, 127 }, + { "option-128", "X", &dhcp_universe, 128 }, + { "option-129", "X", &dhcp_universe, 129 }, + { "option-130", "X", &dhcp_universe, 130 }, + { "option-131", "X", &dhcp_universe, 131 }, + { "option-132", "X", &dhcp_universe, 132 }, + { "option-133", "X", &dhcp_universe, 133 }, + { "option-134", "X", &dhcp_universe, 134 }, + { "option-135", "X", &dhcp_universe, 135 }, + { "option-136", "X", &dhcp_universe, 136 }, + { "option-137", "X", &dhcp_universe, 137 }, + { "option-138", "X", &dhcp_universe, 138 }, + { "option-139", "X", &dhcp_universe, 139 }, + { "option-140", "X", &dhcp_universe, 140 }, + { "option-141", "X", &dhcp_universe, 141 }, + { "option-142", "X", &dhcp_universe, 142 }, + { "option-143", "X", &dhcp_universe, 143 }, + { "option-144", "X", &dhcp_universe, 144 }, + { "option-145", "X", &dhcp_universe, 145 }, + { "option-146", "X", &dhcp_universe, 146 }, + { "option-147", "X", &dhcp_universe, 147 }, + { "option-148", "X", &dhcp_universe, 148 }, + { "option-149", "X", &dhcp_universe, 149 }, + { "option-150", "X", &dhcp_universe, 150 }, + { "option-151", "X", &dhcp_universe, 151 }, + { "option-152", "X", &dhcp_universe, 152 }, + { "option-153", "X", &dhcp_universe, 153 }, + { "option-154", "X", &dhcp_universe, 154 }, + { "option-155", "X", &dhcp_universe, 155 }, + { "option-156", "X", &dhcp_universe, 156 }, + { "option-157", "X", &dhcp_universe, 157 }, + { "option-158", "X", &dhcp_universe, 158 }, + { "option-159", "X", &dhcp_universe, 159 }, + { "option-160", "X", &dhcp_universe, 160 }, + { "option-161", "X", &dhcp_universe, 161 }, + { "option-162", "X", &dhcp_universe, 162 }, + { "option-163", "X", &dhcp_universe, 163 }, + { "option-164", "X", &dhcp_universe, 164 }, + { "option-165", "X", &dhcp_universe, 165 }, + { "option-166", "X", &dhcp_universe, 166 }, + { "option-167", "X", &dhcp_universe, 167 }, + { "option-168", "X", &dhcp_universe, 168 }, + { "option-169", "X", &dhcp_universe, 169 }, + { "option-170", "X", &dhcp_universe, 170 }, + { "option-171", "X", &dhcp_universe, 171 }, + { "option-172", "X", &dhcp_universe, 172 }, + { "option-173", "X", &dhcp_universe, 173 }, + { "option-174", "X", &dhcp_universe, 174 }, + { "option-175", "X", &dhcp_universe, 175 }, + { "option-176", "X", &dhcp_universe, 176 }, + { "option-177", "X", &dhcp_universe, 177 }, + { "option-178", "X", &dhcp_universe, 178 }, + { "option-179", "X", &dhcp_universe, 179 }, + { "option-180", "X", &dhcp_universe, 180 }, + { "option-181", "X", &dhcp_universe, 181 }, + { "option-182", "X", &dhcp_universe, 182 }, + { "option-183", "X", &dhcp_universe, 183 }, + { "option-184", "X", &dhcp_universe, 184 }, + { "option-185", "X", &dhcp_universe, 185 }, + { "option-186", "X", &dhcp_universe, 186 }, + { "option-187", "X", &dhcp_universe, 187 }, + { "option-188", "X", &dhcp_universe, 188 }, + { "option-189", "X", &dhcp_universe, 189 }, + { "option-190", "X", &dhcp_universe, 190 }, + { "option-191", "X", &dhcp_universe, 191 }, + { "option-192", "X", &dhcp_universe, 192 }, + { "option-193", "X", &dhcp_universe, 193 }, + { "option-194", "X", &dhcp_universe, 194 }, + { "option-195", "X", &dhcp_universe, 195 }, + { "option-196", "X", &dhcp_universe, 196 }, + { "option-197", "X", &dhcp_universe, 197 }, + { "option-198", "X", &dhcp_universe, 198 }, + { "option-199", "X", &dhcp_universe, 199 }, + { "option-200", "X", &dhcp_universe, 200 }, + { "option-201", "X", &dhcp_universe, 201 }, + { "option-202", "X", &dhcp_universe, 202 }, + { "option-203", "X", &dhcp_universe, 203 }, + { "option-204", "X", &dhcp_universe, 204 }, + { "option-205", "X", &dhcp_universe, 205 }, + { "option-206", "X", &dhcp_universe, 206 }, + { "option-207", "X", &dhcp_universe, 207 }, + { "option-208", "X", &dhcp_universe, 208 }, + { "option-209", "X", &dhcp_universe, 209 }, + { "option-210", "X", &dhcp_universe, 210 }, + { "option-211", "X", &dhcp_universe, 211 }, + { "option-212", "X", &dhcp_universe, 212 }, + { "option-213", "X", &dhcp_universe, 213 }, + { "option-214", "X", &dhcp_universe, 214 }, + { "option-215", "X", &dhcp_universe, 215 }, + { "option-216", "X", &dhcp_universe, 216 }, + { "option-217", "X", &dhcp_universe, 217 }, + { "option-218", "X", &dhcp_universe, 218 }, + { "option-219", "X", &dhcp_universe, 219 }, + { "option-220", "X", &dhcp_universe, 220 }, + { "option-221", "X", &dhcp_universe, 221 }, + { "option-222", "X", &dhcp_universe, 222 }, + { "option-223", "X", &dhcp_universe, 223 }, + { "option-224", "X", &dhcp_universe, 224 }, + { "option-225", "X", &dhcp_universe, 225 }, + { "option-226", "X", &dhcp_universe, 226 }, + { "option-227", "X", &dhcp_universe, 227 }, + { "option-228", "X", &dhcp_universe, 228 }, + { "option-229", "X", &dhcp_universe, 229 }, + { "option-230", "X", &dhcp_universe, 230 }, + { "option-231", "X", &dhcp_universe, 231 }, + { "option-232", "X", &dhcp_universe, 232 }, + { "option-233", "X", &dhcp_universe, 233 }, + { "option-234", "X", &dhcp_universe, 234 }, + { "option-235", "X", &dhcp_universe, 235 }, + { "option-236", "X", &dhcp_universe, 236 }, + { "option-237", "X", &dhcp_universe, 237 }, + { "option-238", "X", &dhcp_universe, 238 }, + { "option-239", "X", &dhcp_universe, 239 }, + { "option-240", "X", &dhcp_universe, 240 }, + { "option-241", "X", &dhcp_universe, 241 }, + { "option-242", "X", &dhcp_universe, 242 }, + { "option-243", "X", &dhcp_universe, 243 }, + { "option-244", "X", &dhcp_universe, 244 }, + { "option-245", "X", &dhcp_universe, 245 }, + { "option-246", "X", &dhcp_universe, 246 }, + { "option-247", "X", &dhcp_universe, 247 }, + { "option-248", "X", &dhcp_universe, 248 }, + { "option-249", "X", &dhcp_universe, 249 }, + { "option-250", "X", &dhcp_universe, 250 }, + { "option-251", "X", &dhcp_universe, 251 }, + { "option-252", "X", &dhcp_universe, 252 }, + { "option-253", "X", &dhcp_universe, 253 }, + { "option-254", "X", &dhcp_universe, 254 }, + { "option-end", "e", &dhcp_universe, 255 }, +}; + +/* Default dhcp option priority list (this is ad hoc and should not be + mistaken for a carefully crafted and optimized list). */ +unsigned char dhcp_option_default_priority_list [] = { + DHO_DHCP_REQUESTED_ADDRESS, + DHO_DHCP_OPTION_OVERLOAD, + DHO_DHCP_MAX_MESSAGE_SIZE, + DHO_DHCP_RENEWAL_TIME, + DHO_DHCP_REBINDING_TIME, + DHO_DHCP_CLASS_IDENTIFIER, + DHO_DHCP_CLIENT_IDENTIFIER, + DHO_SUBNET_MASK, + DHO_TIME_OFFSET, + DHO_ROUTERS, + DHO_TIME_SERVERS, + DHO_NAME_SERVERS, + DHO_DOMAIN_NAME_SERVERS, + DHO_HOST_NAME, + DHO_LOG_SERVERS, + DHO_COOKIE_SERVERS, + DHO_LPR_SERVERS, + DHO_IMPRESS_SERVERS, + DHO_RESOURCE_LOCATION_SERVERS, + DHO_HOST_NAME, + DHO_BOOT_SIZE, + DHO_MERIT_DUMP, + DHO_DOMAIN_NAME, + DHO_SWAP_SERVER, + DHO_ROOT_PATH, + DHO_EXTENSIONS_PATH, + DHO_IP_FORWARDING, + DHO_NON_LOCAL_SOURCE_ROUTING, + DHO_POLICY_FILTER, + DHO_MAX_DGRAM_REASSEMBLY, + DHO_DEFAULT_IP_TTL, + DHO_PATH_MTU_AGING_TIMEOUT, + DHO_PATH_MTU_PLATEAU_TABLE, + DHO_INTERFACE_MTU, + DHO_ALL_SUBNETS_LOCAL, + DHO_BROADCAST_ADDRESS, + DHO_PERFORM_MASK_DISCOVERY, + DHO_MASK_SUPPLIER, + DHO_ROUTER_DISCOVERY, + DHO_ROUTER_SOLICITATION_ADDRESS, + DHO_STATIC_ROUTES, + DHO_TRAILER_ENCAPSULATION, + DHO_ARP_CACHE_TIMEOUT, + DHO_IEEE802_3_ENCAPSULATION, + DHO_DEFAULT_TCP_TTL, + DHO_TCP_KEEPALIVE_INTERVAL, + DHO_TCP_KEEPALIVE_GARBAGE, + DHO_NIS_DOMAIN, + DHO_NIS_SERVERS, + DHO_NTP_SERVERS, + DHO_VENDOR_ENCAPSULATED_OPTIONS, + DHO_NETBIOS_NAME_SERVERS, + DHO_NETBIOS_DD_SERVER, + DHO_NETBIOS_NODE_TYPE, + DHO_NETBIOS_SCOPE, + DHO_FONT_SERVERS, + DHO_X_DISPLAY_MANAGER, + DHO_DHCP_PARAMETER_REQUEST_LIST, + + /* Presently-undefined options... */ + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, +}; + +int sizeof_dhcp_option_default_priority_list = + sizeof dhcp_option_default_priority_list; + + +char *hardware_types [] = { + "unknown-0", + "ethernet", + "unknown-2", + "unknown-3", + "unknown-4", + "unknown-5", + "token-ring", + "unknown-7", + "unknown-8", + "unknown-9", + "unknown-10", + "unknown-11", + "unknown-12", + "unknown-13", + "unknown-14", + "unknown-15", + "unknown-16", + "unknown-17", + "unknown-18", + "unknown-19", + "unknown-20", + "unknown-21", + "unknown-22", + "unknown-23", + "unknown-24", + "unknown-25", + "unknown-26", + "unknown-27", + "unknown-28", + "unknown-29", + "unknown-30", + "unknown-31", + "unknown-32", + "unknown-33", + "unknown-34", + "unknown-35", + "unknown-36", + "unknown-37", + "unknown-38", + "unknown-39", + "unknown-40", + "unknown-41", + "unknown-42", + "unknown-43", + "unknown-44", + "unknown-45", + "unknown-46", + "unknown-47", + "unknown-48", + "unknown-49", + "unknown-50", + "unknown-51", + "unknown-52", + "unknown-53", + "unknown-54", + "unknown-55", + "unknown-56", + "unknown-57", + "unknown-58", + "unknown-59", + "unknown-60", + "unknown-61", + "unknown-62", + "unknown-63", + "unknown-64", + "unknown-65", + "unknown-66", + "unknown-67", + "unknown-68", + "unknown-69", + "unknown-70", + "unknown-71", + "unknown-72", + "unknown-73", + "unknown-74", + "unknown-75", + "unknown-76", + "unknown-77", + "unknown-78", + "unknown-79", + "unknown-80", + "unknown-81", + "unknown-82", + "unknown-83", + "unknown-84", + "unknown-85", + "unknown-86", + "unknown-87", + "unknown-88", + "unknown-89", + "unknown-90", + "unknown-91", + "unknown-92", + "unknown-93", + "unknown-94", + "unknown-95", + "unknown-96", + "unknown-97", + "unknown-98", + "unknown-99", + "unknown-100", + "unknown-101", + "unknown-102", + "unknown-103", + "unknown-104", + "unknown-105", + "unknown-106", + "unknown-107", + "unknown-108", + "unknown-109", + "unknown-110", + "unknown-111", + "unknown-112", + "unknown-113", + "unknown-114", + "unknown-115", + "unknown-116", + "unknown-117", + "unknown-118", + "unknown-119", + "unknown-120", + "unknown-121", + "unknown-122", + "unknown-123", + "unknown-124", + "unknown-125", + "unknown-126", + "unknown-127", + "unknown-128", + "unknown-129", + "unknown-130", + "unknown-131", + "unknown-132", + "unknown-133", + "unknown-134", + "unknown-135", + "unknown-136", + "unknown-137", + "unknown-138", + "unknown-139", + "unknown-140", + "unknown-141", + "unknown-142", + "unknown-143", + "unknown-144", + "unknown-145", + "unknown-146", + "unknown-147", + "unknown-148", + "unknown-149", + "unknown-150", + "unknown-151", + "unknown-152", + "unknown-153", + "unknown-154", + "unknown-155", + "unknown-156", + "unknown-157", + "unknown-158", + "unknown-159", + "unknown-160", + "unknown-161", + "unknown-162", + "unknown-163", + "unknown-164", + "unknown-165", + "unknown-166", + "unknown-167", + "unknown-168", + "unknown-169", + "unknown-170", + "unknown-171", + "unknown-172", + "unknown-173", + "unknown-174", + "unknown-175", + "unknown-176", + "unknown-177", + "unknown-178", + "unknown-179", + "unknown-180", + "unknown-181", + "unknown-182", + "unknown-183", + "unknown-184", + "unknown-185", + "unknown-186", + "unknown-187", + "unknown-188", + "unknown-189", + "unknown-190", + "unknown-191", + "unknown-192", + "unknown-193", + "unknown-194", + "unknown-195", + "unknown-196", + "unknown-197", + "unknown-198", + "unknown-199", + "unknown-200", + "unknown-201", + "unknown-202", + "unknown-203", + "unknown-204", + "unknown-205", + "unknown-206", + "unknown-207", + "unknown-208", + "unknown-209", + "unknown-210", + "unknown-211", + "unknown-212", + "unknown-213", + "unknown-214", + "unknown-215", + "unknown-216", + "unknown-217", + "unknown-218", + "unknown-219", + "unknown-220", + "unknown-221", + "unknown-222", + "unknown-223", + "unknown-224", + "unknown-225", + "unknown-226", + "unknown-227", + "unknown-228", + "unknown-229", + "unknown-230", + "unknown-231", + "unknown-232", + "unknown-233", + "unknown-234", + "unknown-235", + "unknown-236", + "unknown-237", + "unknown-238", + "unknown-239", + "unknown-240", + "unknown-241", + "unknown-242", + "unknown-243", + "unknown-244", + "unknown-245", + "unknown-246", + "unknown-247", + "unknown-248", + "unknown-249", + "unknown-250", + "unknown-251", + "unknown-252", + "unknown-253", + "unknown-254", + "unknown-255" }; + + + +struct hash_table universe_hash; + +void initialize_universes() +{ + int i; + + dhcp_universe.name = "dhcp"; + dhcp_universe.hash = new_hash (); + if (!dhcp_universe.hash) + 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, + (unsigned char *)&dhcp_options [i]); + } + universe_hash.hash_count = DEFAULT_HASH_SIZE; + add_hash (&universe_hash, dhcp_universe.name, 0, + (unsigned char *)&dhcp_universe); +} diff --git a/usr.sbin/dhcp/common/tree.c b/usr.sbin/dhcp/common/tree.c new file mode 100644 index 00000000000..aeb48d13026 --- /dev/null +++ b/usr.sbin/dhcp/common/tree.c @@ -0,0 +1,412 @@ +/* tree.c + + Routines for manipulating parse trees... */ + +/* + * 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 <mellon@fugue.com> 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: 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 *, + struct tree *)); +static TIME do_host_lookup PROTO ((int *, unsigned char **, int *, + struct dns_host_entry *)); +static void do_data_copy PROTO ((int *, unsigned char **, int *, + unsigned char *, int)); + +pair cons (car, cdr) + caddr_t car; + pair cdr; +{ + pair foo = (pair)dmalloc (sizeof *foo, "cons"); + if (!foo) + error ("no memory for cons."); + foo -> car = car; + foo -> cdr = cdr; + return foo; +} + +struct tree_cache *tree_cache (tree) + struct tree *tree; +{ + struct tree_cache *tc; + + tc = new_tree_cache ("tree_cache"); + if (!tc) + return 0; + tc -> value = (unsigned char *)0; + tc -> len = tc -> buf_size = 0; + tc -> timeout = 0; + tc -> tree = tree; + return tc; +} + +struct tree *tree_host_lookup (name) + char *name; +{ + struct tree *nt; + nt = new_tree ("tree_host_lookup"); + if (!nt) + error ("No memory for host lookup tree node."); + nt -> op = TREE_HOST_LOOKUP; + nt -> data.host_lookup.host = enter_dns_host (name); + return nt; +} + +struct dns_host_entry *enter_dns_host (name) + char *name; +{ + struct dns_host_entry *dh; + + if (!(dh = (struct dns_host_entry *)dmalloc + (sizeof (struct dns_host_entry), "enter_dns_host")) + || !(dh -> hostname = dmalloc (strlen (name) + 1, + "enter_dns_host"))) + error ("Can't allocate space for new host."); + strcpy (dh -> hostname, name); + dh -> data = (unsigned char *)0; + dh -> data_len = 0; + dh -> buf_len = 0; + dh -> timeout = 0; + return dh; +} + +struct tree *tree_const (data, len) + unsigned char *data; + int len; +{ + struct tree *nt; + if (!(nt = new_tree ("tree_const")) + || !(nt -> data.const_val.data = + (unsigned char *)dmalloc (len, "tree_const"))) + error ("No memory for constant data tree node."); + nt -> op = TREE_CONST; + memcpy (nt -> data.const_val.data, data, len); + nt -> data.const_val.len = len; + return nt; +} + +struct tree *tree_concat (left, right) + struct tree *left, *right; +{ + struct tree *nt; + + /* If we're concatenating a null tree to a non-null tree, just + return the non-null tree; if both trees are null, return + a null tree. */ + if (!left) + return right; + if (!right) + return left; + + /* If both trees are constant, combine them. */ + if (left -> op == TREE_CONST && right -> op == TREE_CONST) { + unsigned char *buf = dmalloc (left -> data.const_val.len + + right -> data.const_val.len, + "tree_concat"); + if (!buf) + error ("No memory to concatenate constants."); + memcpy (buf, left -> data.const_val.data, + left -> data.const_val.len); + memcpy (buf + left -> data.const_val.len, + right -> data.const_val.data, + right -> data.const_val.len); + dfree (left -> data.const_val.data, "tree_concat"); + dfree (right -> data.const_val.data, "tree_concat"); + left -> data.const_val.data = buf; + left -> data.const_val.len += right -> data.const_val.len; + free_tree (right, "tree_concat"); + return left; + } + + /* Otherwise, allocate a new node to concatenate the two. */ + if (!(nt = new_tree ("tree_concat"))) + error ("No memory for data tree concatenation node."); + nt -> op = TREE_CONCAT; + nt -> data.concat.left = left; + nt -> data.concat.right = right; + return nt; +} + +struct tree *tree_limit (tree, limit) + struct tree *tree; + int limit; +{ + struct tree *rv; + + /* If the tree we're limiting is constant, limit it now. */ + if (tree -> op == TREE_CONST) { + if (tree -> data.const_val.len > limit) + tree -> data.const_val.len = limit; + return tree; + } + + /* Otherwise, put in a node which enforces the limit on evaluation. */ + rv = new_tree ("tree_limit"); + if (!rv) + return (struct tree *)0; + rv -> op = TREE_LIMIT; + rv -> data.limit.tree = tree; + rv -> data.limit.limit = limit; + return rv; +} + +int tree_evaluate (tree_cache) + struct tree_cache *tree_cache; +{ + unsigned char *bp = tree_cache -> value; + int bc = tree_cache -> buf_size; + int bufix = 0; + + /* If there's no tree associated with this cache, it evaluates + to a constant and that was detected at startup. */ + if (!tree_cache -> tree) + return 1; + + /* Try to evaluate the tree without allocating more memory... */ + tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc, + tree_cache -> tree); + + /* No additional allocation needed? */ + if (bufix <= bc) { + tree_cache -> len = bufix; + return 1; + } + + /* If we can't allocate more memory, return with what we + have (maybe nothing). */ + if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate"))) + return 0; + + /* Record the change in conditions... */ + bc = bufix; + bufix = 0; + + /* Note that the size of the result shouldn't change on the + second call to tree_evaluate_recurse, since we haven't + changed the ``current'' time. */ + tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree); + + /* Free the old buffer if needed, then store the new buffer + location and size and return. */ + if (tree_cache -> value) + dfree (tree_cache -> value, "tree_evaluate"); + tree_cache -> value = bp; + tree_cache -> len = bufix; + tree_cache -> buf_size = bc; + return 1; +} + +static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree) + int *bufix; + unsigned char **bufp; + int *bufcount; + struct tree *tree; +{ + int limit; + TIME t1, t2; + + switch (tree -> op) { + case TREE_CONCAT: + t1 = tree_evaluate_recurse (bufix, bufp, bufcount, + tree -> data.concat.left); + t2 = tree_evaluate_recurse (bufix, bufp, bufcount, + tree -> data.concat.right); + if (t1 > t2) + return t2; + return t1; + + case TREE_HOST_LOOKUP: + return do_host_lookup (bufix, bufp, bufcount, + tree -> data.host_lookup.host); + + case TREE_CONST: + do_data_copy (bufix, bufp, bufcount, + tree -> data.const_val.data, + tree -> data.const_val.len); + t1 = MAX_TIME; + return t1; + + case TREE_LIMIT: + limit = *bufix + tree -> data.limit.limit; + t1 = tree_evaluate_recurse (bufix, bufp, bufcount, + tree -> data.limit.tree); + *bufix = limit; + return t1; + + default: + warn ("Bad node id in tree: %d."); + t1 = MAX_TIME; + return t1; + } +} + +static TIME do_host_lookup (bufix, bufp, bufcount, dns) + int *bufix; + unsigned char **bufp; + int *bufcount; + struct dns_host_entry *dns; +{ + struct hostent *h; + int i; + int new_len; + +#ifdef DEBUG_EVAL + debug ("time: now = %d dns = %d %d diff = %d", + cur_time, dns -> timeout, cur_time - dns -> timeout); +#endif + + /* If the record hasn't timed out, just copy the data and return. */ + if (cur_time <= dns -> timeout) { +#ifdef DEBUG_EVAL + debug ("easy copy: %x %d %x", + dns -> data, dns -> data_len, + dns -> data ? *(int *)(dns -> data) : 0); +#endif + do_data_copy (bufix, bufp, bufcount, + dns -> data, dns -> data_len); + return dns -> timeout; + } +#ifdef DEBUG_EVAL + debug ("Looking up %s", dns -> hostname); +#endif + + /* Otherwise, look it up... */ + h = gethostbyname (dns -> hostname); + if (!h) { +#ifndef NO_H_ERRNO + switch (h_errno) { + case HOST_NOT_FOUND: +#endif + warn ("%s: host unknown.", dns -> hostname); +#ifndef NO_H_ERRNO + break; + case TRY_AGAIN: + warn ("%s: temporary name server failure", + dns -> hostname); + break; + case NO_RECOVERY: + warn ("%s: name server failed", dns -> hostname); + break; + case NO_DATA: + 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; + } + +#ifdef DEBUG_EVAL + debug ("Lookup succeeded; first address is %x", + h -> h_addr_list [0]); +#endif + + /* Count the number of addresses we got... */ + for (i = 0; h -> h_addr_list [i]; i++) + ; + + /* Do we need to allocate more memory? */ + new_len = i * h -> h_length; + if (dns -> buf_len < i) { + unsigned char *buf = + (unsigned char *)dmalloc (new_len, "do_host_lookup"); + /* If we didn't get more memory, use what we have. */ + if (!buf) { + new_len = dns -> buf_len; + if (!dns -> buf_len) { + dns -> timeout = cur_time + 60; + return dns -> timeout; + } + } else { + if (dns -> data) + dfree (dns -> data, "do_host_lookup"); + dns -> data = buf; + dns -> buf_len = new_len; + } + } + + /* Addresses are conveniently stored one to the buffer, so we + have to copy them out one at a time... :'( */ + for (i = 0; i < new_len / h -> h_length; i++) { + memcpy (dns -> data + h -> h_length * i, + h -> h_addr_list [i], h -> h_length); + } +#ifdef DEBUG_EVAL + debug ("dns -> data: %x h -> h_addr_list [0]: %x", + *(int *)(dns -> data), h -> h_addr_list [0]); +#endif + dns -> data_len = new_len; + + /* Set the timeout for an hour from now. + XXX This should really use the time on the DNS reply. */ + dns -> timeout = cur_time + 3600; + +#ifdef DEBUG_EVAL + debug ("hard copy: %x %d %x", + dns -> data, dns -> data_len, *(int *)(dns -> data)); +#endif + do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len); + return dns -> timeout; +} + +static void do_data_copy (bufix, bufp, bufcount, data, len) + int *bufix; + unsigned char **bufp; + int *bufcount; + unsigned char *data; + int len; +{ + int space = *bufcount - *bufix; + + /* If there's more space than we need, use only what we need. */ + if (space > len) + space = len; + + /* Copy as much data as will fit, then increment the buffer index + by the amount we actually had to copy, which could be more. */ + if (space > 0) + memcpy (*bufp + *bufix, data, space); + *bufix += len; +} diff --git a/usr.sbin/dhcp/common/upf.c b/usr.sbin/dhcp/common/upf.c new file mode 100644 index 00000000000..6b4897b742b --- /dev/null +++ b/usr.sbin/dhcp/common/upf.c @@ -0,0 +1,298 @@ +/* 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 <mellon@fugue.com> 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.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_UPF_SEND) || defined (USE_UPF_RECEIVE) +#include <sys/ioctl.h> +#include <sys/uio.h> + +#include <net/pfilt.h> +#include <netinet/in_systm.h> +#include "includes/netinet/ip.h" +#include "includes/netinet/udp.h" +#include "includes/netinet/if_ether.h" + +/* Reinitializes the specified interface after an address change. This + is not required for packet-filter APIs. */ + +#ifdef USE_UPF_SEND +void if_reinitialize_send (info) + struct interface_info *info; +{ +} +#endif + +#ifdef USE_UPF_RECEIVE +void if_reinitialize_receive (info) + struct interface_info *info; +{ +} +#endif + +/* Called by get_interface_list for each interface that's discovered. + Opens a packet filter for each interface and adds it to the select + mask. */ + +int if_register_upf (info) + struct interface_info *info; +{ + int sock; + char filename[50]; + int b; + struct endevp param; + + /* Open a UPF device */ + for (b = 0; 1; b++) { +#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/doc/rfc2131.txt b/usr.sbin/dhcp/doc/rfc2131.txt new file mode 100644 index 00000000000..f45d9b864a2 --- /dev/null +++ b/usr.sbin/dhcp/doc/rfc2131.txt @@ -0,0 +1,2523 @@ + + + + + + +Network Working Group R. Droms +Request for Comments: 2131 Bucknell University +Obsoletes: 1541 March 1997 +Category: Standards Track + + Dynamic Host Configuration Protocol + +Status of this memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Abstract + + The Dynamic Host Configuration Protocol (DHCP) provides a framework + for passing configuration information to hosts on a TCPIP network. + DHCP is based on the Bootstrap Protocol (BOOTP) [7], adding the + capability of automatic allocation of reusable network addresses and + additional configuration options [19]. DHCP captures the behavior of + BOOTP relay agents [7, 21], and DHCP participants can interoperate + with BOOTP participants [9]. + +Table of Contents + + 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . 2 + 1.1 Changes to RFC1541. . . . . . . . . . . . . . . . . . . . . . 3 + 1.2 Related Work. . . . . . . . . . . . . . . . . . . . . . . . . 4 + 1.3 Problem definition and issues . . . . . . . . . . . . . . . . 4 + 1.4 Requirements. . . . . . . . . . . . . . . . . . . . . . . . . 5 + 1.5 Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 6 + 1.6 Design goals. . . . . . . . . . . . . . . . . . . . . . . . . 6 + 2. Protocol Summary. . . . . . . . . . . . . . . . . . . . . . . 8 + 2.1 Configuration parameters repository . . . . . . . . . . . . . 11 + 2.2 Dynamic allocation of network addresses . . . . . . . . . . . 12 + 3. The Client-Server Protocol. . . . . . . . . . . . . . . . . . 13 + 3.1 Client-server interaction - allocating a network address. . . 13 + 3.2 Client-server interaction - reusing a previously allocated + network address . . . . . . . . . . . . . . . . . . . . . . . 17 + 3.3 Interpretation and representation of time values. . . . . . . 20 + 3.4 Obtaining parameters with externally configured network + address . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 + 3.5 Client parameters in DHCP . . . . . . . . . . . . . . . . . . 21 + 3.6 Use of DHCP in clients with multiple interfaces . . . . . . . 22 + 3.7 When clients should use DHCP. . . . . . . . . . . . . . . . . 22 + 4. Specification of the DHCP client-server protocol. . . . . . . 22 + + + +Droms Standards Track [Page 1] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + 4.1 Constructing and sending DHCP messages. . . . . . . . . . . . 22 + 4.2 DHCP server administrative controls . . . . . . . . . . . . . 25 + 4.3 DHCP server behavior. . . . . . . . . . . . . . . . . . . . . 26 + 4.4 DHCP client behavior. . . . . . . . . . . . . . . . . . . . . 34 + 5. Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . .42 + 6. References . . . . . . . . . . . . . . . . . . . . . . . . . .42 + 7. Security Considerations. . . . . . . . . . . . . . . . . . . .43 + 8. Author's Address . . . . . . . . . . . . . . . . . . . . . . .44 + A. Host Configuration Parameters . . . . . . . . . . . . . . . .45 +List of Figures + 1. Format of a DHCP message . . . . . . . . . . . . . . . . . . . 9 + 2. Format of the 'flags' field. . . . . . . . . . . . . . . . . . 11 + 3. Timeline diagram of messages exchanged between DHCP client and + servers when allocating a new network address. . . . . . . . . 15 + 4. Timeline diagram of messages exchanged between DHCP client and + servers when reusing a previously allocated network address. . 18 + 5. State-transition diagram for DHCP clients. . . . . . . . . . . 34 +List of Tables + 1. Description of fields in a DHCP message. . . . . . . . . . . . 10 + 2. DHCP messages. . . . . . . . . . . . . . . . . . . . . . . . . 14 + 3. Fields and options used by DHCP servers. . . . . . . . . . . . 28 + 4. Client messages from various states. . . . . . . . . . . . . . 33 + 5. Fields and options used by DHCP clients. . . . . . . . . . . . 37 + +1. Introduction + + The Dynamic Host Configuration Protocol (DHCP) provides configuration + parameters to Internet hosts. DHCP consists of two components: a + protocol for delivering host-specific configuration parameters from a + DHCP server to a host and a mechanism for allocation of network + addresses to hosts. + + DHCP is built on a client-server model, where designated DHCP server + hosts allocate network addresses and deliver configuration parameters + to dynamically configured hosts. Throughout the remainder of this + document, the term "server" refers to a host providing initialization + parameters through DHCP, and the term "client" refers to a host + requesting initialization parameters from a DHCP server. + + A host should not act as a DHCP server unless explicitly configured + to do so by a system administrator. The diversity of hardware and + protocol implementations in the Internet would preclude reliable + operation if random hosts were allowed to respond to DHCP requests. + For example, IP requires the setting of many parameters within the + protocol implementation software. Because IP can be used on many + dissimilar kinds of network hardware, values for those parameters + cannot be guessed or assumed to have correct defaults. Also, + distributed address allocation schemes depend on a polling/defense + + + +Droms Standards Track [Page 2] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + mechanism for discovery of addresses that are already in use. IP + hosts may not always be able to defend their network addresses, so + that such a distributed address allocation scheme cannot be + guaranteed to avoid allocation of duplicate network addresses. + + DHCP supports three mechanisms for IP address allocation. In + "automatic allocation", DHCP assigns a permanent IP address to a + client. In "dynamic allocation", DHCP assigns an IP address to a + client for a limited period of time (or until the client explicitly + relinquishes the address). In "manual allocation", a client's IP + address is assigned by the network administrator, and DHCP is used + simply to convey the assigned address to the client. A particular + network will use one or more of these mechanisms, depending on the + policies of the network administrator. + + Dynamic allocation is the only one of the three mechanisms that + allows automatic reuse of an address that is no longer needed by the + client to which it was assigned. Thus, dynamic allocation is + particularly useful for assigning an address to a client that will be + connected to the network only temporarily or for sharing a limited + pool of IP addresses among a group of clients that do not need + permanent IP addresses. Dynamic allocation may also be a good choice + for assigning an IP address to a new client being permanently + connected to a network where IP addresses are sufficiently scarce + that it is important to reclaim them when old clients are retired. + Manual allocation allows DHCP to be used to eliminate the error-prone + process of manually configuring hosts with IP addresses in + environments where (for whatever reasons) it is desirable to manage + IP address assignment outside of the DHCP mechanisms. + + The format of DHCP messages is based on the format of BOOTP messages, + to capture the BOOTP relay agent behavior described as part of the + BOOTP specification [7, 21] and to allow interoperability of existing + BOOTP clients with DHCP servers. Using BOOTP relay agents eliminates + the necessity of having a DHCP server on each physical network + segment. + +1.1 Changes to RFC 1541 + + This document updates the DHCP protocol specification that appears in + RFC1541. A new DHCP message type, DHCPINFORM, has been added; see + section 3.4, 4.3 and 4.4 for details. The classing mechanism for + identifying DHCP clients to DHCP servers has been extended to include + "vendor" classes as defined in sections 4.2 and 4.3. The minimum + lease time restriction has been removed. Finally, many editorial + changes have been made to clarify the text as a result of experience + gained in DHCP interoperability tests. + + + + +Droms Standards Track [Page 3] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +1.2 Related Work + + There are several Internet protocols and related mechanisms that + address some parts of the dynamic host configuration problem. The + Reverse Address Resolution Protocol (RARP) [10] (through the + extensions defined in the Dynamic RARP (DRARP) [5]) explicitly + addresses the problem of network address discovery, and includes an + automatic IP address assignment mechanism. The Trivial File Transfer + Protocol (TFTP) [20] provides for transport of a boot image from a + boot server. The Internet Control Message Protocol (ICMP) [16] + provides for informing hosts of additional routers via "ICMP + redirect" messages. ICMP also can provide subnet mask information + through the "ICMP mask request" message and other information through + the (obsolete) "ICMP information request" message. Hosts can locate + routers through the ICMP router discovery mechanism [8]. + + BOOTP is a transport mechanism for a collection of configuration + information. BOOTP is also extensible, and official extensions [17] + have been defined for several configuration parameters. Morgan has + proposed extensions to BOOTP for dynamic IP address assignment [15]. + The Network Information Protocol (NIP), used by the Athena project at + MIT, is a distributed mechanism for dynamic IP address assignment + [19]. The Resource Location Protocol RLP [1] provides for location + of higher level services. Sun Microsystems diskless workstations use + a boot procedure that employs RARP, TFTP and an RPC mechanism called + "bootparams" to deliver configuration information and operating + system code to diskless hosts. (Sun Microsystems, Sun Workstation + and SunOS are trademarks of Sun Microsystems, Inc.) Some Sun + networks also use DRARP and an auto-installation mechanism to + automate the configuration of new hosts in an existing network. + + In other related work, the path minimum transmission unit (MTU) + discovery algorithm can determine the MTU of an arbitrary internet + path [14]. The Address Resolution Protocol (ARP) has been proposed + as a transport protocol for resource location and selection [6]. + Finally, the Host Requirements RFCs [3, 4] mention specific + requirements for host reconfiguration and suggest a scenario for + initial configuration of diskless hosts. + +1.3 Problem definition and issues + + DHCP is designed to supply DHCP clients with the configuration + parameters defined in the Host Requirements RFCs. After obtaining + parameters via DHCP, a DHCP client should be able to exchange packets + with any other host in the Internet. The TCP/IP stack parameters + supplied by DHCP are listed in Appendix A. + + + + + +Droms Standards Track [Page 4] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + Not all of these parameters are required for a newly initialized + client. A client and server may negotiate for the transmission of + only those parameters required by the client or specific to a + particular subnet. + + DHCP allows but does not require the configuration of client + parameters not directly related to the IP protocol. DHCP also does + not address registration of newly configured clients with the Domain + Name System (DNS) [12, 13]. + + DHCP is not intended for use in configuring routers. + +1.4 Requirements + + Throughout this document, the words that are used to define the + significance of particular requirements are capitalized. These words + are: + + o "MUST" + + This word or the adjective "REQUIRED" means that the + item is an absolute requirement of this specification. + + o "MUST NOT" + + This phrase means that the item is an absolute prohibition + of this specification. + + o "SHOULD" + + This word or the adjective "RECOMMENDED" means that there + may exist valid reasons in particular circumstances to ignore + this item, but the full implications should be understood and + the case carefully weighed before choosing a different course. + + o "SHOULD NOT" + + This phrase means that there may exist valid reasons in + particular circumstances when the listed behavior is acceptable + or even useful, but the full implications should be understood + and the case carefully weighed before implementing any behavior + described with this label. + + + + + + + + + +Droms Standards Track [Page 5] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + o "MAY" + + This word or the adjective "OPTIONAL" means that this item is + truly optional. One vendor may choose to include the item + because a particular marketplace requires it or because it + enhances the product, for example; another vendor may omit the + same item. + +1.5 Terminology + + This document uses the following terms: + + o "DHCP client" + + A DHCP client is an Internet host using DHCP to obtain + configuration parameters such as a network address. + + o "DHCP server" + + A DHCP server is an Internet host that returns configuration + parameters to DHCP clients. + + o "BOOTP relay agent" + + A BOOTP relay agent or relay agent is an Internet host or router + that passes DHCP messages between DHCP clients and DHCP servers. + DHCP is designed to use the same relay agent behavior as specified + in the BOOTP protocol specification. + + o "binding" + + A binding is a collection of configuration parameters, including + at least an IP address, associated with or "bound to" a DHCP + client. Bindings are managed by DHCP servers. + +1.6 Design goals + + The following list gives general design goals for DHCP. + + o DHCP should be a mechanism rather than a policy. DHCP must + allow local system administrators control over configuration + parameters where desired; e.g., local system administrators + should be able to enforce local policies concerning allocation + and access to local resources where desired. + + + + + + + +Droms Standards Track [Page 6] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + o Clients should require no manual configuration. Each client + should be able to discover appropriate local configuration + parameters without user intervention and incorporate those + parameters into its own configuration. + + o Networks should require no manual configuration for individual + clients. Under normal circumstances, the network manager + should not have to enter any per-client configuration + parameters. + + o DHCP should not require a server on each subnet. To allow for + scale and economy, DHCP must work across routers or through the + intervention of BOOTP relay agents. + + o A DHCP client must be prepared to receive multiple responses + to a request for configuration parameters. Some installations + may include multiple, overlapping DHCP servers to enhance + reliability and increase performance. + + o DHCP must coexist with statically configured, non-participating + hosts and with existing network protocol implementations. + + o DHCP must interoperate with the BOOTP relay agent behavior as + described by RFC 951 and by RFC 1542 [21]. + + o DHCP must provide service to existing BOOTP clients. + + The following list gives design goals specific to the transmission of + the network layer parameters. DHCP must: + + o Guarantee that any specific network address will not be in + use by more than one DHCP client at a time, + + o Retain DHCP client configuration across DHCP client reboot. A + DHCP client should, whenever possible, be assigned the same + configuration parameters (e.g., network address) in response + to each request, + + o Retain DHCP client configuration across server reboots, and, + whenever possible, a DHCP client should be assigned the same + configuration parameters despite restarts of the DHCP mechanism, + + o Allow automated assignment of configuration parameters to new + clients to avoid hand configuration for new clients, + + o Support fixed or permanent allocation of configuration + parameters to specific clients. + + + + +Droms Standards Track [Page 7] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +2. Protocol Summary + + From the client's point of view, DHCP is an extension of the BOOTP + mechanism. This behavior allows existing BOOTP clients to + interoperate with DHCP servers without requiring any change to the + clients' initialization software. RFC 1542 [2] details the + interactions between BOOTP and DHCP clients and servers [9]. There + are some new, optional transactions that optimize the interaction + between DHCP clients and servers that are described in sections 3 and + 4. + + Figure 1 gives the format of a DHCP message and table 1 describes + each of the fields in the DHCP message. The numbers in parentheses + indicate the size of each field in octets. The names for the fields + given in the figure will be used throughout this document to refer to + the fields in DHCP messages. + + There are two primary differences between DHCP and BOOTP. First, + DHCP defines mechanisms through which clients can be assigned a + network address for a finite lease, allowing for serial reassignment + of network addresses to different clients. Second, DHCP provides the + mechanism for a client to acquire all of the IP configuration + parameters that it needs in order to operate. + + DHCP introduces a small change in terminology intended to clarify the + meaning of one of the fields. What was the "vendor extensions" field + in BOOTP has been re-named the "options" field in DHCP. Similarly, + the tagged data items that were used inside the BOOTP "vendor + extensions" field, which were formerly referred to as "vendor + extensions," are now termed simply "options." + + + + + + + + + + + + + + + + + + + + + +Droms Standards Track [Page 8] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | op (1) | htype (1) | hlen (1) | hops (1) | + +---------------+---------------+---------------+---------------+ + | xid (4) | + +-------------------------------+-------------------------------+ + | secs (2) | flags (2) | + +-------------------------------+-------------------------------+ + | ciaddr (4) | + +---------------------------------------------------------------+ + | yiaddr (4) | + +---------------------------------------------------------------+ + | siaddr (4) | + +---------------------------------------------------------------+ + | giaddr (4) | + +---------------------------------------------------------------+ + | | + | chaddr (16) | + | | + | | + +---------------------------------------------------------------+ + | | + | sname (64) | + +---------------------------------------------------------------+ + | | + | file (128) | + +---------------------------------------------------------------+ + | | + | options (variable) | + +---------------------------------------------------------------+ + + Figure 1: Format of a DHCP message + + DHCP defines a new 'client identifier' option that is used to pass an + explicit client identifier to a DHCP server. This change eliminates + the overloading of the 'chaddr' field in BOOTP messages, where + 'chaddr' is used both as a hardware address for transmission of BOOTP + reply messages and as a client identifier. The 'client identifier' + is an opaque key, not to be interpreted by the server; for example, + the 'client identifier' may contain a hardware address, identical to + the contents of the 'chaddr' field, or it may contain another type of + identifier, such as a DNS name. The 'client identifier' chosen by a + DHCP client MUST be unique to that client within the subnet to which + the client is attached. If the client uses a 'client identifier' in + one message, it MUST use that same identifier in all subsequent + messages, to ensure that all servers correctly identify the client. + + + + +Droms Standards Track [Page 9] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + DHCP clarifies the interpretation of the 'siaddr' field as the + address of the server to use in the next step of the client's + bootstrap process. A DHCP server may return its own address in the + 'siaddr' field, if the server is prepared to supply the next + bootstrap service (e.g., delivery of an operating system executable + image). A DHCP server always returns its own address in the 'server + identifier' option. + + FIELD OCTETS DESCRIPTION + ----- ------ ----------- + + op 1 Message op code / message type. + 1 = BOOTREQUEST, 2 = BOOTREPLY + htype 1 Hardware address type, see ARP section in "Assigned + Numbers" RFC; e.g., '1' = 10mb ethernet. + hlen 1 Hardware address length (e.g. '6' for 10mb + ethernet). + hops 1 Client sets to zero, optionally used by relay agents + when booting via a relay agent. + xid 4 Transaction ID, a random number chosen by the + client, used by the client and server to associate + messages and responses between a client and a + server. + secs 2 Filled in by client, seconds elapsed since client + began address acquisition or renewal process. + flags 2 Flags (see figure 2). + ciaddr 4 Client IP address; only filled in if client is in + BOUND, RENEW or REBINDING state and can respond + to ARP requests. + yiaddr 4 'your' (client) IP address. + siaddr 4 IP address of next server to use in bootstrap; + returned in DHCPOFFER, DHCPACK by server. + giaddr 4 Relay agent IP address, used in booting via a + relay agent. + chaddr 16 Client hardware address. + sname 64 Optional server host name, null terminated string. + file 128 Boot file name, null terminated string; "generic" + name or null in DHCPDISCOVER, fully qualified + directory-path name in DHCPOFFER. + options var Optional parameters field. See the options + documents for a list of defined options. + + Table 1: Description of fields in a DHCP message + + The 'options' field is now variable length. A DHCP client must be + prepared to receive DHCP messages with an 'options' field of at least + length 312 octets. This requirement implies that a DHCP client must + be prepared to receive a message of up to 576 octets, the minimum IP + + + +Droms Standards Track [Page 10] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + datagram size an IP host must be prepared to accept [3]. DHCP + clients may negotiate the use of larger DHCP messages through the + 'maximum DHCP message size' option. The options field may be further + extended into the 'file' and 'sname' fields. + + In the case of a client using DHCP for initial configuration (before + the client's TCP/IP software has been completely configured), DHCP + requires creative use of the client's TCP/IP software and liberal + interpretation of RFC 1122. The TCP/IP software SHOULD accept and + forward to the IP layer any IP packets delivered to the client's + hardware address before the IP address is configured; DHCP servers + and BOOTP relay agents may not be able to deliver DHCP messages to + clients that cannot accept hardware unicast datagrams before the + TCP/IP software is configured. + + To work around some clients that cannot accept IP unicast datagrams + before the TCP/IP software is configured as discussed in the previous + paragraph, DHCP uses the 'flags' field [21]. The leftmost bit is + defined as the BROADCAST (B) flag. The semantics of this flag are + discussed in section 4.1 of this document. The remaining bits of the + flags field are reserved for future use. They MUST be set to zero by + clients and ignored by servers and relay agents. Figure 2 gives the + format of the 'flags' field. + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |B| MBZ | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + B: BROADCAST flag + + MBZ: MUST BE ZERO (reserved for future use) + + Figure 2: Format of the 'flags' field + +2.1 Configuration parameters repository + + The first service provided by DHCP is to provide persistent storage + of network parameters for network clients. The model of DHCP + persistent storage is that the DHCP service stores a key-value entry + for each client, where the key is some unique identifier (for + example, an IP subnet number and a unique identifier within the + subnet) and the value contains the configuration parameters for the + client. + + For example, the key might be the pair (IP-subnet-number, hardware- + address) (note that the "hardware-address" should be typed by the + + + +Droms Standards Track [Page 11] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + type of hardware to accommodate possible duplication of hardware + addresses resulting from bit-ordering problems in a mixed-media, + bridged network) allowing for serial or concurrent reuse of a + hardware address on different subnets, and for hardware addresses + that may not be globally unique. Alternately, the key might be the + pair (IP-subnet-number, hostname), allowing the server to assign + parameters intelligently to a DHCP client that has been moved to a + different subnet or has changed hardware addresses (perhaps because + the network interface failed and was replaced). The protocol defines + that the key will be (IP-subnet-number, hardware-address) unless the + client explicitly supplies an identifier using the 'client + identifier' option. A client can query the DHCP service to + retrieve its configuration parameters. The client interface to the + configuration parameters repository consists of protocol messages to + request configuration parameters and responses from the server + carrying the configuration parameters. + +2.2 Dynamic allocation of network addresses + + The second service provided by DHCP is the allocation of temporary or + permanent network (IP) addresses to clients. The basic mechanism for + the dynamic allocation of network addresses is simple: a client + requests the use of an address for some period of time. The + allocation mechanism (the collection of DHCP servers) guarantees not + to reallocate that address within the requested time and attempts to + return the same network address each time the client requests an + address. In this document, the period over which a network address + is allocated to a client is referred to as a "lease" [11]. The + client may extend its lease with subsequent requests. The client may + issue a message to release the address back to the server when the + client no longer needs the address. The client may ask for a + permanent assignment by asking for an infinite lease. Even when + assigning "permanent" addresses, a server may choose to give out + lengthy but non-infinite leases to allow detection of the fact that + the client has been retired. + + In some environments it will be necessary to reassign network + addresses due to exhaustion of available addresses. In such + environments, the allocation mechanism will reuse addresses whose + lease has expired. The server should use whatever information is + available in the configuration information repository to choose an + address to reuse. For example, the server may choose the least + recently assigned address. As a consistency check, the allocating + server SHOULD probe the reused address before allocating the address, + e.g., with an ICMP echo request, and the client SHOULD probe the + newly received address, e.g., with ARP. + + + + + +Droms Standards Track [Page 12] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +3. The Client-Server Protocol + + DHCP uses the BOOTP message format defined in RFC 951 and given in + table 1 and figure 1. The 'op' field of each DHCP message sent from + a client to a server contains BOOTREQUEST. BOOTREPLY is used in the + 'op' field of each DHCP message sent from a server to a client. + + The first four octets of the 'options' field of the DHCP message + contain the (decimal) values 99, 130, 83 and 99, respectively (this + is the same magic cookie as is defined in RFC 1497 [17]). The + remainder of the 'options' field consists of a list of tagged + parameters that are called "options". All of the "vendor extensions" + listed in RFC 1497 are also DHCP options. RFC 1533 gives the + complete set of options defined for use with DHCP. + + Several options have been defined so far. One particular option - + the "DHCP message type" option - must be included in every DHCP + message. This option defines the "type" of the DHCP message. + Additional options may be allowed, required, or not allowed, + depending on the DHCP message type. + + Throughout this document, DHCP messages that include a 'DHCP message + type' option will be referred to by the type of the message; e.g., a + DHCP message with 'DHCP message type' option type 1 will be referred + to as a "DHCPDISCOVER" message. + +3.1 Client-server interaction - allocating a network address + + The following summary of the protocol exchanges between clients and + servers refers to the DHCP messages described in table 2. The + timeline diagram in figure 3 shows the timing relationships in a + typical client-server interaction. If the client already knows its + address, some steps may be omitted; this abbreviated interaction is + described in section 3.2. + + 1. The client broadcasts a DHCPDISCOVER message on its local physical + subnet. The DHCPDISCOVER message MAY include options that suggest + values for the network address and lease duration. BOOTP relay + agents may pass the message on to DHCP servers not on the same + physical subnet. + + 2. Each server may respond with a DHCPOFFER message that includes an + available network address in the 'yiaddr' field (and other + configuration parameters in DHCP options). Servers need not + reserve the offered network address, although the protocol will + work more efficiently if the server avoids allocating the offered + network address to another client. When allocating a new address, + servers SHOULD check that the offered network address is not + + + +Droms Standards Track [Page 13] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + already in use; e.g., the server may probe the offered address + with an ICMP Echo Request. Servers SHOULD be implemented so that + network administrators MAY choose to disable probes of newly + allocated addresses. The server transmits the DHCPOFFER message + to the client, using the BOOTP relay agent if necessary. + + Message Use + ------- --- + + DHCPDISCOVER - Client broadcast to locate available servers. + + DHCPOFFER - Server to client in response to DHCPDISCOVER with + offer of configuration parameters. + + DHCPREQUEST - Client message to servers either (a) requesting + offered parameters from one server and implicitly + declining offers from all others, (b) confirming + correctness of previously allocated address after, + e.g., system reboot, or (c) extending the lease on a + particular network address. + + DHCPACK - Server to client with configuration parameters, + including committed network address. + + DHCPNAK - Server to client indicating client's notion of network + address is incorrect (e.g., client has moved to new + subnet) or client's lease as expired + + DHCPDECLINE - Client to server indicating network address is already + in use. + + DHCPRELEASE - Client to server relinquishing network address and + cancelling remaining lease. + + DHCPINFORM - Client to server, asking only for local configuration + parameters; client already has externally configured + network address. + + Table 2: DHCP messages + + + + + + + + + + + + +Droms Standards Track [Page 14] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + Server Client Server + (not selected) (selected) + + v v v + | | | + | Begins initialization | + | | | + | _____________/|\____________ | + |/DHCPDISCOVER | DHCPDISCOVER \| + | | | + Determines | Determines + configuration | configuration + | | | + |\ | ____________/ | + | \________ | /DHCPOFFER | + | DHCPOFFER\ |/ | + | \ | | + | Collects replies | + | \| | + | Selects configuration | + | | | + | _____________/|\____________ | + |/ DHCPREQUEST | DHCPREQUEST\ | + | | | + | | Commits configuration + | | | + | | _____________/| + | |/ DHCPACK | + | | | + | Initialization complete | + | | | + . . . + . . . + | | | + | Graceful shutdown | + | | | + | |\ ____________ | + | | DHCPRELEASE \| + | | | + | | Discards lease + | | | + v v v + Figure 3: Timeline diagram of messages exchanged between DHCP + client and servers when allocating a new network address + + + + + + + +Droms Standards Track [Page 15] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + 3. The client receives one or more DHCPOFFER messages from one or more + servers. The client may choose to wait for multiple responses. + The client chooses one server from which to request configuration + parameters, based on the configuration parameters offered in the + DHCPOFFER messages. The client broadcasts a DHCPREQUEST message + that MUST include the 'server identifier' option to indicate which + server it has selected, and that MAY include other options + specifying desired configuration values. The 'requested IP + address' option MUST be set to the value of 'yiaddr' in the + DHCPOFFER message from the server. This DHCPREQUEST message is + broadcast and relayed through DHCP/BOOTP relay agents. To help + ensure that any BOOTP relay agents forward the DHCPREQUEST message + to the same set of DHCP servers that received the original + DHCPDISCOVER message, the DHCPREQUEST message MUST use the same + value in the DHCP message header's 'secs' field and be sent to the + same IP broadcast address as the original DHCPDISCOVER message. + The client times out and retransmits the DHCPDISCOVER message if + the client receives no DHCPOFFER messages. + + 4. The servers receive the DHCPREQUEST broadcast from the client. + Those servers not selected by the DHCPREQUEST message use the + message as notification that the client has declined that server's + offer. The server selected in the DHCPREQUEST message commits the + binding for the client to persistent storage and responds with a + DHCPACK message containing the configuration parameters for the + requesting client. The combination of 'client identifier' or + 'chaddr' and assigned network address constitute a unique + identifier for the client's lease and are used by both the client + and server to identify a lease referred to in any DHCP messages. + Any configuration parameters in the DHCPACK message SHOULD NOT + conflict with those in the earlier DHCPOFFER message to which the + client is responding. The server SHOULD NOT check the offered + network address at this point. The 'yiaddr' field in the DHCPACK + messages is filled in with the selected network address. + + If the selected server is unable to satisfy the DHCPREQUEST message + (e.g., the requested network address has been allocated), the + server SHOULD respond with a DHCPNAK message. + + A server MAY choose to mark addresses offered to clients in + DHCPOFFER messages as unavailable. The server SHOULD mark an + address offered to a client in a DHCPOFFER message as available if + the server receives no DHCPREQUEST message from that client. + + 5. The client receives the DHCPACK message with configuration + parameters. The client SHOULD perform a final check on the + parameters (e.g., ARP for allocated network address), and notes the + duration of the lease specified in the DHCPACK message. At this + + + +Droms Standards Track [Page 16] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + point, the client is configured. If the client detects that the + address is already in use (e.g., through the use of ARP), the + client MUST send a DHCPDECLINE message to the server and restarts + the configuration process. The client SHOULD wait a minimum of ten + seconds before restarting the configuration process to avoid + excessive network traffic in case of looping. + + If the client receives a DHCPNAK message, the client restarts the + configuration process. + + The client times out and retransmits the DHCPREQUEST message if the + client receives neither a DHCPACK or a DHCPNAK message. The client + retransmits the DHCPREQUEST according to the retransmission + algorithm in section 4.1. The client should choose to retransmit + the DHCPREQUEST enough times to give adequate probability of + contacting the server without causing the client (and the user of + that client) to wait overly long before giving up; e.g., a client + retransmitting as described in section 4.1 might retransmit the + DHCPREQUEST message four times, for a total delay of 60 seconds, + before restarting the initialization procedure. If the client + receives neither a DHCPACK or a DHCPNAK message after employing the + retransmission algorithm, the client reverts to INIT state and + restarts the initialization process. The client SHOULD notify the + user that the initialization process has failed and is restarting. + + 6. The client may choose to relinquish its lease on a network address + by sending a DHCPRELEASE message to the server. The client + identifies the lease to be released with its 'client identifier', + or 'chaddr' and network address in the DHCPRELEASE message. If the + client used a 'client identifier' when it obtained the lease, it + MUST use the same 'client identifier' in the DHCPRELEASE message. + +3.2 Client-server interaction - reusing a previously allocated network + address + + If a client remembers and wishes to reuse a previously allocated + network address, a client may choose to omit some of the steps + described in the previous section. The timeline diagram in figure 4 + shows the timing relationships in a typical client-server interaction + for a client reusing a previously allocated network address. + + + + + + + + + + + +Droms Standards Track [Page 17] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + 1. The client broadcasts a DHCPREQUEST message on its local subnet. + The message includes the client's network address in the + 'requested IP address' option. As the client has not received its + network address, it MUST NOT fill in the 'ciaddr' field. BOOTP + relay agents pass the message on to DHCP servers not on the same + subnet. If the client used a 'client identifier' to obtain its + address, the client MUST use the same 'client identifier' in the + DHCPREQUEST message. + + 2. Servers with knowledge of the client's configuration parameters + respond with a DHCPACK message to the client. Servers SHOULD NOT + check that the client's network address is already in use; the + client may respond to ICMP Echo Request messages at this point. + + Server Client Server + + v v v + | | | + | Begins | + | initialization | + | | | + | /|\ | + | _________ __/ | \__________ | + | /DHCPREQU EST | DHCPREQUEST\ | + |/ | \| + | | | + Locates | Locates + configuration | configuration + | | | + |\ | /| + | \ | ___________/ | + | \ | / DHCPACK | + | \ _______ |/ | + | DHCPACK\ | | + | Initialization | + | complete | + | \| | + | | | + | (Subsequent | + | DHCPACKS | + | ignored) | + | | | + | | | + v v v + + Figure 4: Timeline diagram of messages exchanged between DHCP + client and servers when reusing a previously allocated + network address + + + +Droms Standards Track [Page 18] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + If the client's request is invalid (e.g., the client has moved + to a new subnet), servers SHOULD respond with a DHCPNAK message to + the client. Servers SHOULD NOT respond if their information is not + guaranteed to be accurate. For example, a server that identifies a + request for an expired binding that is owned by another server SHOULD + NOT respond with a DHCPNAK unless the servers are using an explicit + mechanism to maintain coherency among the servers. + + If 'giaddr' is 0x0 in the DHCPREQUEST message, the client is on + the same subnet as the server. The server MUST + broadcast the DHCPNAK message to the 0xffffffff broadcast address + because the client may not have a correct network address or subnet + mask, and the client may not be answering ARP requests. + Otherwise, the server MUST send the DHCPNAK message to the IP + address of the BOOTP relay agent, as recorded in 'giaddr'. The + relay agent will, in turn, forward the message directly to the + client's hardware address, so that the DHCPNAK can be delivered even + if the client has moved to a new network. + + 3. The client receives the DHCPACK message with configuration + parameters. The client performs a final check on the parameters + (as in section 3.1), and notes the duration of the lease specified + in the DHCPACK message. The specific lease is implicitly identified + by the 'client identifier' or 'chaddr' and the network address. At + this point, the client is configured. + + If the client detects that the IP address in the DHCPACK message + is already in use, the client MUST send a DHCPDECLINE message to the + server and restarts the configuration process by requesting a + new network address. This action corresponds to the client + moving to the INIT state in the DHCP state diagram, which is + described in section 4.4. + + If the client receives a DHCPNAK message, it cannot reuse its + remembered network address. It must instead request a new + address by restarting the configuration process, this time + using the (non-abbreviated) procedure described in section + 3.1. This action also corresponds to the client moving to + the INIT state in the DHCP state diagram. + + The client times out and retransmits the DHCPREQUEST message if + the client receives neither a DHCPACK nor a DHCPNAK message. The + client retransmits the DHCPREQUEST according to the retransmission + algorithm in section 4.1. The client should choose to retransmit + the DHCPREQUEST enough times to give adequate probability of + contacting the server without causing the client (and the user of + that client) to wait overly long before giving up; e.g., a client + retransmitting as described in section 4.1 might retransmit the + + + +Droms Standards Track [Page 19] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + DHCPREQUEST message four times, for a total delay of 60 seconds, + before restarting the initialization procedure. If the client + receives neither a DHCPACK or a DHCPNAK message after employing + the retransmission algorithm, the client MAY choose to use the + previously allocated network address and configuration parameters + for the remainder of the unexpired lease. This corresponds to + moving to BOUND state in the client state transition diagram shown + in figure 5. + + 4. The client may choose to relinquish its lease on a network + address by sending a DHCPRELEASE message to the server. The + client identifies the lease to be released with its + 'client identifier', or 'chaddr' and network address in the + DHCPRELEASE message. + + Note that in this case, where the client retains its network + address locally, the client will not normally relinquish its + lease during a graceful shutdown. Only in the case where the + client explicitly needs to relinquish its lease, e.g., the client + is about to be moved to a different subnet, will the client send + a DHCPRELEASE message. + +3.3 Interpretation and representation of time values + + A client acquires a lease for a network address for a fixed period of + time (which may be infinite). Throughout the protocol, times are to + be represented in units of seconds. The time value of 0xffffffff is + reserved to represent "infinity". + + As clients and servers may not have synchronized clocks, times are + represented in DHCP messages as relative times, to be interpreted + with respect to the client's local clock. Representing relative + times in units of seconds in an unsigned 32 bit word gives a range of + relative times from 0 to approximately 100 years, which is sufficient + for the relative times to be measured using DHCP. + + The algorithm for lease duration interpretation given in the previous + paragraph assumes that client and server clocks are stable relative + to each other. If there is drift between the two clocks, the server + may consider the lease expired before the client does. To + compensate, the server may return a shorter lease duration to the + client than the server commits to its local database of client + information. + +3.4 Obtaining parameters with externally configured network address + + If a client has obtained a network address through some other means + (e.g., manual configuration), it may use a DHCPINFORM request message + + + +Droms Standards Track [Page 20] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + to obtain other local configuration parameters. Servers receiving a + DHCPINFORM message construct a DHCPACK message with any local + configuration parameters appropriate for the client without: + allocating a new address, checking for an existing binding, filling + in 'yiaddr' or including lease time parameters. The servers SHOULD + unicast the DHCPACK reply to the address given in the 'ciaddr' field + of the DHCPINFORM message. + + The server SHOULD check the network address in a DHCPINFORM message + for consistency, but MUST NOT check for an existing lease. The + server forms a DHCPACK message containing the configuration + parameters for the requesting client and sends the DHCPACK message + directly to the client. + +3.5 Client parameters in DHCP + + Not all clients require initialization of all parameters listed in + Appendix A. Two techniques are used to reduce the number of + parameters transmitted from the server to the client. First, most of + the parameters have defaults defined in the Host Requirements RFCs; + if the client receives no parameters from the server that override + the defaults, a client uses those default values. Second, in its + initial DHCPDISCOVER or DHCPREQUEST message, a client may provide the + server with a list of specific parameters the client is interested + in. If the client includes a list of parameters in a DHCPDISCOVER + message, it MUST include that list in any subsequent DHCPREQUEST + messages. + + The client SHOULD include the 'maximum DHCP message size' option to + let the server know how large the server may make its DHCP messages. + The parameters returned to a client may still exceed the space + allocated to options in a DHCP message. In this case, two additional + options flags (which must appear in the 'options' field of the + message) indicate that the 'file' and 'sname' fields are to be used + for options. + + The client can inform the server which configuration parameters the + client is interested in by including the 'parameter request list' + option. The data portion of this option explicitly lists the options + requested by tag number. + + In addition, the client may suggest values for the network address + and lease time in the DHCPDISCOVER message. The client may include + the 'requested IP address' option to suggest that a particular IP + address be assigned, and may include the 'IP address lease time' + option to suggest the lease time it would like. Other options + representing "hints" at configuration parameters are allowed in a + DHCPDISCOVER or DHCPREQUEST message. However, additional options may + + + +Droms Standards Track [Page 21] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + be ignored by servers, and multiple servers may, therefore, not + return identical values for some options. The 'requested IP address' + option is to be filled in only in a DHCPREQUEST message when the + client is verifying network parameters obtained previously. The + client fills in the 'ciaddr' field only when correctly configured + with an IP address in BOUND, RENEWING or REBINDING state. + + If a server receives a DHCPREQUEST message with an invalid 'requested + IP address', the server SHOULD respond to the client with a DHCPNAK + message and may choose to report the problem to the system + administrator. The server may include an error message in the + 'message' option. + +3.6 Use of DHCP in clients with multiple interfaces + + A client with multiple network interfaces must use DHCP through each + interface independently to obtain configuration information + parameters for those separate interfaces. + +3.7 When clients should use DHCP + + A client SHOULD use DHCP to reacquire or verify its IP address and + network parameters whenever the local network parameters may have + changed; e.g., at system boot time or after a disconnection from the + local network, as the local network configuration may change without + the client's or user's knowledge. + + If a client has knowledge of a previous network address and is unable + to contact a local DHCP server, the client may continue to use the + previous network address until the lease for that address expires. + If the lease expires before the client can contact a DHCP server, the + client must immediately discontinue use of the previous network + address and may inform local users of the problem. + +4. Specification of the DHCP client-server protocol + + In this section, we assume that a DHCP server has a block of network + addresses from which it can satisfy requests for new addresses. Each + server also maintains a database of allocated addresses and leases in + local permanent storage. + +4.1 Constructing and sending DHCP messages + + DHCP clients and servers both construct DHCP messages by filling in + fields in the fixed format section of the message and appending + tagged data items in the variable length option area. The options + area includes first a four-octet 'magic cookie' (which was described + in section 3), followed by the options. The last option must always + + + +Droms Standards Track [Page 22] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + be the 'end' option. + + DHCP uses UDP as its transport protocol. DHCP messages from a client + to a server are sent to the 'DHCP server' port (67), and DHCP + messages from a server to a client are sent to the 'DHCP client' port + (68). A server with multiple network address (e.g., a multi-homed + host) MAY use any of its network addresses in outgoing DHCP messages. + + The 'server identifier' field is used both to identify a DHCP server + in a DHCP message and as a destination address from clients to + servers. A server with multiple network addresses MUST be prepared + to to accept any of its network addresses as identifying that server + in a DHCP message. To accommodate potentially incomplete network + connectivity, a server MUST choose an address as a 'server + identifier' that, to the best of the server's knowledge, is reachable + from the client. For example, if the DHCP server and the DHCP client + are connected to the same subnet (i.e., the 'giaddr' field in the + message from the client is zero), the server SHOULD select the IP + address the server is using for communication on that subnet as the + 'server identifier'. If the server is using multiple IP addresses on + that subnet, any such address may be used. If the server has + received a message through a DHCP relay agent, the server SHOULD + choose an address from the interface on which the message was + recieved as the 'server identifier' (unless the server has other, + better information on which to make its choice). DHCP clients MUST + use the IP address provided in the 'server identifier' option for any + unicast requests to the DHCP server. + + DHCP messages broadcast by a client prior to that client obtaining + its IP address must have the source address field in the IP header + set to 0. + + If the 'giaddr' field in a DHCP message from a client is non-zero, + the server sends any return messages to the 'DHCP server' port on the + BOOTP relay agent whose address appears in 'giaddr'. If the 'giaddr' + field is zero and the 'ciaddr' field is nonzero, then the server + unicasts DHCPOFFER and DHCPACK messages to the address in 'ciaddr'. + If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is + set, then the server broadcasts DHCPOFFER and DHCPACK messages to + 0xffffffff. If the broadcast bit is not set and 'giaddr' is zero and + 'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK + messages to the client's hardware address and 'yiaddr' address. In + all cases, when 'giaddr' is zero, the server broadcasts any DHCPNAK + messages to 0xffffffff. + + If the options in a DHCP message extend into the 'sname' and 'file' + fields, the 'option overload' option MUST appear in the 'options' + field, with value 1, 2 or 3, as specified in RFC 1533. If the + + + +Droms Standards Track [Page 23] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + 'option overload' option is present in the 'options' field, the + options in the 'options' field MUST be terminated by an 'end' option, + and MAY contain one or more 'pad' options to fill the options field. + The options in the 'sname' and 'file' fields (if in use as indicated + by the 'options overload' option) MUST begin with the first octet of + the field, MUST be terminated by an 'end' option, and MUST be + followed by 'pad' options to fill the remainder of the field. Any + individual option in the 'options', 'sname' and 'file' fields MUST be + entirely contained in that field. The options in the 'options' field + MUST be interpreted first, so that any 'option overload' options may + be interpreted. The 'file' field MUST be interpreted next (if the + 'option overload' option indicates that the 'file' field contains + DHCP options), followed by the 'sname' field. + + The values to be passed in an 'option' tag may be too long to fit in + the 255 octets available to a single option (e.g., a list of routers + in a 'router' option [21]). Options may appear only once, unless + otherwise specified in the options document. The client concatenates + the values of multiple instances of the same option into a single + parameter list for configuration. + + DHCP clients are responsible for all message retransmission. The + client MUST adopt a retransmission strategy that incorporates a + randomized exponential backoff algorithm to determine the delay + between retransmissions. The delay between retransmissions SHOULD be + chosen to allow sufficient time for replies from the server to be + delivered based on the characteristics of the internetwork between + the client and the server. For example, in a 10Mb/sec Ethernet + internetwork, the delay before the first retransmission SHOULD be 4 + seconds randomized by the value of a uniform random number chosen + from the range -1 to +1. Clients with clocks that provide resolution + granularity of less than one second may choose a non-integer + randomization value. The delay before the next retransmission SHOULD + be 8 seconds randomized by the value of a uniform number chosen from + the range -1 to +1. The retransmission delay SHOULD be doubled with + subsequent retransmissions up to a maximum of 64 seconds. The client + MAY provide an indication of retransmission attempts to the user as + an indication of the progress of the configuration process. + + The 'xid' field is used by the client to match incoming DHCP messages + with pending requests. A DHCP client MUST choose 'xid's in such a + way as to minimize the chance of using an 'xid' identical to one used + by another client. For example, a client may choose a different, + random initial 'xid' each time the client is rebooted, and + subsequently use sequential 'xid's until the next reboot. Selecting + a new 'xid' for each retransmission is an implementation decision. A + client may choose to reuse the same 'xid' or select a new 'xid' for + each retransmitted message. + + + +Droms Standards Track [Page 24] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + Normally, DHCP servers and BOOTP relay agents attempt to deliver + DHCPOFFER, DHCPACK and DHCPNAK messages directly to the client using + uicast delivery. The IP destination address (in the IP header) is + set to the DHCP 'yiaddr' address and the link-layer destination + address is set to the DHCP 'chaddr' address. Unfortunately, some + client implementations are unable to receive such unicast IP + datagrams until the implementation has been configured with a valid + IP address (leading to a deadlock in which the client's IP address + cannot be delivered until the client has been configured with an IP + address). + + A client that cannot receive unicast IP datagrams until its protocol + software has been configured with an IP address SHOULD set the + BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or + DHCPREQUEST messages that client sends. The BROADCAST bit will + provide a hint to the DHCP server and BOOTP relay agent to broadcast + any messages to the client on the client's subnet. A client that can + receive unicast IP datagrams before its protocol software has been + configured SHOULD clear the BROADCAST bit to 0. The BOOTP + clarifications document discusses the ramifications of the use of the + BROADCAST bit [21]. + + A server or relay agent sending or relaying a DHCP message directly + to a DHCP client (i.e., not to a relay agent specified in the + 'giaddr' field) SHOULD examine the BROADCAST bit in the 'flags' + field. If this bit is set to 1, the DHCP message SHOULD be sent as + an IP broadcast using an IP broadcast address (preferably 0xffffffff) + as the IP destination address and the link-layer broadcast address as + the link-layer destination address. If the BROADCAST bit is cleared + to 0, the message SHOULD be sent as an IP unicast to the IP address + specified in the 'yiaddr' field and the link-layer address specified + in the 'chaddr' field. If unicasting is not possible, the message + MAY be sent as an IP broadcast using an IP broadcast address + (preferably 0xffffffff) as the IP destination address and the link- + layer broadcast address as the link-layer destination address. + +4.2 DHCP server administrative controls + + DHCP servers are not required to respond to every DHCPDISCOVER and + DHCPREQUEST message they receive. For example, a network + administrator, to retain stringent control over the clients attached + to the network, may choose to configure DHCP servers to respond only + to clients that have been previously registered through some external + mechanism. The DHCP specification describes only the interactions + between clients and servers when the clients and servers choose to + interact; it is beyond the scope of the DHCP specification to + describe all of the administrative controls that system + administrators might want to use. Specific DHCP server + + + +Droms Standards Track [Page 25] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + implementations may incorporate any controls or policies desired by a + network administrator. + + In some environments, a DHCP server will have to consider the values + of the vendor class options included in DHCPDISCOVER or DHCPREQUEST + messages when determining the correct parameters for a particular + client. + + A DHCP server needs to use some unique identifier to associate a + client with its lease. The client MAY choose to explicitly provide + the identifier through the 'client identifier' option. If the client + supplies a 'client identifier', the client MUST use the same 'client + identifier' in all subsequent messages, and the server MUST use that + identifier to identify the client. If the client does not provide a + 'client identifier' option, the server MUST use the contents of the + 'chaddr' field to identify the client. It is crucial for a DHCP + client to use an identifier unique within the subnet to which the + client is attached in the 'client identifier' option. Use of + 'chaddr' as the client's unique identifier may cause unexpected + results, as that identifier may be associated with a hardware + interface that could be moved to a new client. Some sites may choose + to use a manufacturer's serial number as the 'client identifier', to + avoid unexpected changes in a clients network address due to transfer + of hardware interfaces among computers. Sites may also choose to use + a DNS name as the 'client identifier', causing address leases to be + associated with the DNS name rather than a specific hardware box. + + DHCP clients are free to use any strategy in selecting a DHCP server + among those from which the client receives a DHCPOFFER message. The + client implementation of DHCP SHOULD provide a mechanism for the user + to select directly the 'vendor class identifier' values. + +4.3 DHCP server behavior + + A DHCP server processes incoming DHCP messages from a client based on + the current state of the binding for that client. A DHCP server can + receive the following messages from a client: + + o DHCPDISCOVER + + o DHCPREQUEST + + o DHCPDECLINE + + o DHCPRELEASE + + o DHCPINFORM + + + + +Droms Standards Track [Page 26] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + Table 3 gives the use of the fields and options in a DHCP message by + a server. The remainder of this section describes the action of the + DHCP server for each possible incoming message. + +4.3.1 DHCPDISCOVER message + + When a server receives a DHCPDISCOVER message from a client, the + server chooses a network address for the requesting client. If no + address is available, the server may choose to report the problem to + the system administrator. If an address is available, the new address + SHOULD be chosen as follows: + + o The client's current address as recorded in the client's current + binding, ELSE + + o The client's previous address as recorded in the client's (now + expired or released) binding, if that address is in the server's + pool of available addresses and not already allocated, ELSE + + o The address requested in the 'Requested IP Address' option, if that + address is valid and not already allocated, ELSE + + o A new address allocated from the server's pool of available + addresses; the address is selected based on the subnet from which + the message was received (if 'giaddr' is 0) or on the address of + the relay agent that forwarded the message ('giaddr' when not 0). + + As described in section 4.2, a server MAY, for administrative + reasons, assign an address other than the one requested, or may + refuse to allocate an address to a particular client even though free + addresses are available. + + Note that, in some network architectures (e.g., internets with more + than one IP subnet assigned to a physical network segment), it may be + the case that the DHCP client should be assigned an address from a + different subnet than the address recorded in 'giaddr'. Thus, DHCP + does not require that the client be assigned as address from the + subnet in 'giaddr'. A server is free to choose some other subnet, + and it is beyond the scope of the DHCP specification to describe ways + in which the assigned IP address might be chosen. + + While not required for correct operation of DHCP, the server SHOULD + NOT reuse the selected network address before the client responds to + the server's DHCPOFFER message. The server may choose to record the + address as offered to the client. + + The server must also choose an expiration time for the lease, as + follows: + + + +Droms Standards Track [Page 27] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + o IF the client has not requested a specific lease in the + DHCPDISCOVER message and the client already has an assigned network + address, the server returns the lease expiration time previously + assigned to that address (note that the client must explicitly + request a specific lease to extend the expiration time on a + previously assigned address), ELSE + + o IF the client has not requested a specific lease in the + DHCPDISCOVER message and the client does not have an assigned + network address, the server assigns a locally configured default + lease time, ELSE + + o IF the client has requested a specific lease in the DHCPDISCOVER + message (regardless of whether the client has an assigned network + address), the server may choose either to return the requested + lease (if the lease is acceptable to local policy) or select + another lease. + +Field DHCPOFFER DHCPACK DHCPNAK +----- --------- ------- ------- +'op' BOOTREPLY BOOTREPLY BOOTREPLY +'htype' (From "Assigned Numbers" RFC) +'hlen' (Hardware address length in octets) +'hops' 0 0 0 +'xid' 'xid' from client 'xid' from client 'xid' from client + DHCPDISCOVER DHCPREQUEST DHCPREQUEST + message message message +'secs' 0 0 0 +'ciaddr' 0 'ciaddr' from 0 + DHCPREQUEST or 0 +'yiaddr' IP address offered IP address 0 + to client assigned to client +'siaddr' IP address of next IP address of next 0 + bootstrap server bootstrap server +'flags' 'flags' from 'flags' from 'flags' from + client DHCPDISCOVER client DHCPREQUEST client DHCPREQUEST + message message message +'giaddr' 'giaddr' from 'giaddr' from 'giaddr' from + client DHCPDISCOVER client DHCPREQUEST client DHCPREQUEST + message message message +'chaddr' 'chaddr' from 'chaddr' from 'chaddr' from + client DHCPDISCOVER client DHCPREQUEST client DHCPREQUEST + message message message +'sname' Server host name Server host name (unused) + or options or options +'file' Client boot file Client boot file (unused) + name or options name or options +'options' options options + + + +Droms Standards Track [Page 28] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +Option DHCPOFFER DHCPACK DHCPNAK +------ --------- ------- ------- +Requested IP address MUST NOT MUST NOT MUST NOT +IP address lease time MUST MUST (DHCPREQUEST) MUST NOT + MUST NOT (DHCPINFORM) +Use 'file'/'sname' fields MAY MAY MUST NOT +DHCP message type DHCPOFFER DHCPACK DHCPNAK +Parameter request list MUST NOT MUST NOT MUST NOT +Message SHOULD SHOULD SHOULD +Client identifier MUST NOT MUST NOT MAY +Vendor class identifier MAY MAY MAY +Server identifier MUST MUST MUST +Maximum message size MUST NOT MUST NOT MUST NOT +All others MAY MAY MUST NOT + + Table 3: Fields and options used by DHCP servers + + Once the network address and lease have been determined, the server + constructs a DHCPOFFER message with the offered configuration + parameters. It is important for all DHCP servers to return the same + parameters (with the possible exception of a newly allocated network + address) to ensure predictable client behavior regardless of which + server the client selects. The configuration parameters MUST be + selected by applying the following rules in the order given below. + The network administrator is responsible for configuring multiple + DHCP servers to ensure uniform responses from those servers. The + server MUST return to the client: + + o The client's network address, as determined by the rules given + earlier in this section, + + o The expiration time for the client's lease, as determined by the + rules given earlier in this section, + + o Parameters requested by the client, according to the following + rules: + + -- IF the server has been explicitly configured with a default + value for the parameter, the server MUST include that value + in an appropriate option in the 'option' field, ELSE + + -- IF the server recognizes the parameter as a parameter + defined in the Host Requirements Document, the server MUST + include the default value for that parameter as given in the + Host Requirements Document in an appropriate option in the + 'option' field, ELSE + + -- The server MUST NOT return a value for that parameter, + + + +Droms Standards Track [Page 29] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + The server MUST supply as many of the requested parameters as + possible and MUST omit any parameters it cannot provide. The + server MUST include each requested parameter only once unless + explicitly allowed in the DHCP Options and BOOTP Vendor + Extensions document. + + o Any parameters from the existing binding that differ from the Host + Requirements Document defaults, + + o Any parameters specific to this client (as identified by + the contents of 'chaddr' or 'client identifier' in the DHCPDISCOVER + or DHCPREQUEST message), e.g., as configured by the network + administrator, + + o Any parameters specific to this client's class (as identified + by the contents of the 'vendor class identifier' + option in the DHCPDISCOVER or DHCPREQUEST message), + e.g., as configured by the network administrator; the parameters + MUST be identified by an exact match between the client's vendor + class identifiers and the client's classes identified in the + server, + + o Parameters with non-default values on the client's subnet. + + The server MAY choose to return the 'vendor class identifier' used to + determine the parameters in the DHCPOFFER message to assist the + client in selecting which DHCPOFFER to accept. The server inserts + the 'xid' field from the DHCPDISCOVER message into the 'xid' field of + the DHCPOFFER message and sends the DHCPOFFER message to the + requesting client. + +4.3.2 DHCPREQUEST message + + A DHCPREQUEST message may come from a client responding to a + DHCPOFFER message from a server, from a client verifying a previously + allocated IP address or from a client extending the lease on a + network address. If the DHCPREQUEST message contains a 'server + identifier' option, the message is in response to a DHCPOFFER + message. Otherwise, the message is a request to verify or extend an + existing lease. If the client uses a 'client identifier' in a + DHCPREQUEST message, it MUST use that same 'client identifier' in all + subsequent messages. If the client included a list of requested + parameters in a DHCPDISCOVER message, it MUST include that list in + all subsequent messages. + + + + + + + +Droms Standards Track [Page 30] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + Any configuration parameters in the DHCPACK message SHOULD NOT + conflict with those in the earlier DHCPOFFER message to which the + client is responding. The client SHOULD use the parameters in the + DHCPACK message for configuration. + + Clients send DHCPREQUEST messages as follows: + + o DHCPREQUEST generated during SELECTING state: + + Client inserts the address of the selected server in 'server + identifier', 'ciaddr' MUST be zero, 'requested IP address' MUST be + filled in with the yiaddr value from the chosen DHCPOFFER. + + Note that the client may choose to collect several DHCPOFFER + messages and select the "best" offer. The client indicates its + selection by identifying the offering server in the DHCPREQUEST + message. If the client receives no acceptable offers, the client + may choose to try another DHCPDISCOVER message. Therefore, the + servers may not receive a specific DHCPREQUEST from which they can + decide whether or not the client has accepted the offer. Because + the servers have not committed any network address assignments on + the basis of a DHCPOFFER, servers are free to reuse offered + network addresses in response to subsequent requests. As an + implementation detail, servers SHOULD NOT reuse offered addresses + and may use an implementation-specific timeout mechanism to decide + when to reuse an offered address. + + o DHCPREQUEST generated during INIT-REBOOT state: + + 'server identifier' MUST NOT be filled in, 'requested IP address' + option MUST be filled in with client's notion of its previously + assigned address. 'ciaddr' MUST be zero. The client is seeking to + verify a previously allocated, cached configuration. Server SHOULD + send a DHCPNAK message to the client if the 'requested IP address' + is incorrect, or is on the wrong network. + + Determining whether a client in the INIT-REBOOT state is on the + correct network is done by examining the contents of 'giaddr', the + 'requested IP address' option, and a database lookup. If the DHCP + server detects that the client is on the wrong net (i.e., the + result of applying the local subnet mask or remote subnet mask (if + 'giaddr' is not zero) to 'requested IP address' option value + doesn't match reality), then the server SHOULD send a DHCPNAK + message to the client. + + + + + + + +Droms Standards Track [Page 31] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + If the network is correct, then the DHCP server should check if + the client's notion of its IP address is correct. If not, then the + server SHOULD send a DHCPNAK message to the client. If the DHCP + server has no record of this client, then it MUST remain silent, + and MAY output a warning to the network administrator. This + behavior is necessary for peaceful coexistence of non- + communicating DHCP servers on the same wire. + + If 'giaddr' is 0x0 in the DHCPREQUEST message, the client is on + the same subnet as the server. The server MUST broadcast the + DHCPNAK message to the 0xffffffff broadcast address because the + client may not have a correct network address or subnet mask, and + the client may not be answering ARP requests. + + If 'giaddr' is set in the DHCPREQUEST message, the client is on a + different subnet. The server MUST set the broadcast bit in the + DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the + client, because the client may not have a correct network address + or subnet mask, and the client may not be answering ARP requests. + + o DHCPREQUEST generated during RENEWING state: + + 'server identifier' MUST NOT be filled in, 'requested IP address' + option MUST NOT be filled in, 'ciaddr' MUST be filled in with + client's IP address. In this situation, the client is completely + configured, and is trying to extend its lease. This message will + be unicast, so no relay agents will be involved in its + transmission. Because 'giaddr' is therefore not filled in, the + DHCP server will trust the value in 'ciaddr', and use it when + replying to the client. + + A client MAY choose to renew or extend its lease prior to T1. The + server may choose not to extend the lease (as a policy decision by + the network administrator), but should return a DHCPACK message + regardless. + + o DHCPREQUEST generated during REBINDING state: + + 'server identifier' MUST NOT be filled in, 'requested IP address' + option MUST NOT be filled in, 'ciaddr' MUST be filled in with + client's IP address. In this situation, the client is completely + configured, and is trying to extend its lease. This message MUST + be broadcast to the 0xffffffff IP broadcast address. The DHCP + server SHOULD check 'ciaddr' for correctness before replying to + the DHCPREQUEST. + + + + + + +Droms Standards Track [Page 32] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + The DHCPREQUEST from a REBINDING client is intended to accommodate + sites that have multiple DHCP servers and a mechanism for + maintaining consistency among leases managed by multiple servers. + A DHCP server MAY extend a client's lease only if it has local + administrative authority to do so. + +4.3.3 DHCPDECLINE message + + If the server receives a DHCPDECLINE message, the client has + discovered through some other means that the suggested network + address is already in use. The server MUST mark the network address + as not available and SHOULD notify the local system administrator of + a possible configuration problem. + +4.3.4 DHCPRELEASE message + + Upon receipt of a DHCPRELEASE message, the server marks the network + address as not allocated. The server SHOULD retain a record of the + client's initialization parameters for possible reuse in response to + subsequent requests from the client. + +4.3.5 DHCPINFORM message + + The server responds to a DHCPINFORM message by sending a DHCPACK + message directly to the address given in the 'ciaddr' field of the + DHCPINFORM message. The server MUST NOT send a lease expiration time + to the client and SHOULD NOT fill in 'yiaddr'. The server includes + other parameters in the DHCPACK message as defined in section 4.3.1. + +4.3.6 Client messages + + Table 4 details the differences between messages from clients in + various states. + + --------------------------------------------------------------------- + | |INIT-REBOOT |SELECTING |RENEWING |REBINDING | + --------------------------------------------------------------------- + |broad/unicast |broadcast |broadcast |unicast |broadcast | + |server-ip |MUST NOT |MUST |MUST NOT |MUST NOT | + |requested-ip |MUST |MUST |MUST NOT |MUST NOT | + |ciaddr |zero |zero |IP address |IP address| + --------------------------------------------------------------------- + + Table 4: Client messages from different states + + + + + + + +Droms Standards Track [Page 33] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +4.4 DHCP client behavior + + Figure 5 gives a state-transition diagram for a DHCP client. A + client can receive the following messages from a server: + + o DHCPOFFER + + o DHCPACK + + o DHCPNAK + + The DHCPINFORM message is not shown in figure 5. A client simply + sends the DHCPINFORM and waits for DHCPACK messages. Once the client + has selected its parameters, it has completed the configuration + process. + + Table 5 gives the use of the fields and options in a DHCP message by + a client. The remainder of this section describes the action of the + DHCP client for each possible incoming message. The description in + the following section corresponds to the full configuration procedure + previously described in section 3.1, and the text in the subsequent + section corresponds to the abbreviated configuration procedure + described in section 3.2. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Droms Standards Track [Page 34] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + -------- ------- +| | +-------------------------->| |<-------------------+ +| INIT- | | +-------------------->| INIT | | +| REBOOT |DHCPNAK/ +---------->| |<---+ | +| |Restart| | ------- | | + -------- | DHCPNAK/ | | | + | Discard offer | -/Send DHCPDISCOVER | +-/Send DHCPREQUEST | | | + | | | DHCPACK v | | + ----------- | (not accept.)/ ----------- | | +| | | Send DHCPDECLINE | | | +| REBOOTING | | | | SELECTING |<----+ | +| | | / | | |DHCPOFFER/ | + ----------- | / ----------- | |Collect | + | | / | | | replies | +DHCPACK/ | / +----------------+ +-------+ | +Record lease, set| | v Select offer/ | +timers T1, T2 ------------ send DHCPREQUEST | | + | +----->| | DHCPNAK, Lease expired/ | + | | | REQUESTING | Halt network | + DHCPOFFER/ | | | | + Discard ------------ | | + | | | | ----------- | + | +--------+ DHCPACK/ | | | + | Record lease, set -----| REBINDING | | + | timers T1, T2 / | | | + | | DHCPACK/ ----------- | + | v Record lease, set ^ | + +----------------> ------- /timers T1,T2 | | + +----->| |<---+ | | + | | BOUND |<---+ | | + DHCPOFFER, DHCPACK, | | | T2 expires/ DHCPNAK/ + DHCPNAK/Discard ------- | Broadcast Halt network + | | | | DHCPREQUEST | + +-------+ | DHCPACK/ | | + T1 expires/ Record lease, set | | + Send DHCPREQUEST timers T1, T2 | | + to leasing server | | | + | ---------- | | + | | |------------+ | + +->| RENEWING | | + | |----------------------------+ + ---------- + Figure 5: State-transition diagram for DHCP clients + + + + + + + +Droms Standards Track [Page 35] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +4.4.1 Initialization and allocation of network address + + The client begins in INIT state and forms a DHCPDISCOVER message. + The client SHOULD wait a random time between one and ten seconds to + desynchronize the use of DHCP at startup. The client sets 'ciaddr' + to 0x00000000. The client MAY request specific parameters by + including the 'parameter request list' option. The client MAY + suggest a network address and/or lease time by including the + 'requested IP address' and 'IP address lease time' options. The + client MUST include its hardware address in the 'chaddr' field, if + necessary for delivery of DHCP reply messages. The client MAY + include a different unique identifier in the 'client identifier' + option, as discussed in section 4.2. If the client included a list + of requested parameters in a DHCPDISCOVER message, it MUST include + that list in all subsequent messages. + + The client generates and records a random transaction identifier and + inserts that identifier into the 'xid' field. The client records its + own local time for later use in computing the lease expiration. The + client then broadcasts the DHCPDISCOVER on the local hardware + broadcast address to the 0xffffffff IP broadcast address and 'DHCP + server' UDP port. + + If the 'xid' of an arriving DHCPOFFER message does not match the + 'xid' of the most recent DHCPDISCOVER message, the DHCPOFFER message + must be silently discarded. Any arriving DHCPACK messages must be + silently discarded. + + The client collects DHCPOFFER messages over a period of time, selects + one DHCPOFFER message from the (possibly many) incoming DHCPOFFER + messages (e.g., the first DHCPOFFER message or the DHCPOFFER message + from the previously used server) and extracts the server address from + the 'server identifier' option in the DHCPOFFER message. The time + over which the client collects messages and the mechanism used to + select one DHCPOFFER are implementation dependent. + + + + + + + + + + + + + + + + +Droms Standards Track [Page 36] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +Field DHCPDISCOVER DHCPREQUEST DHCPDECLINE, + DHCPINFORM DHCPRELEASE +----- ------------ ----------- ----------- +'op' BOOTREQUEST BOOTREQUEST BOOTREQUEST +'htype' (From "Assigned Numbers" RFC) +'hlen' (Hardware address length in octets) +'hops' 0 0 0 +'xid' selected by client 'xid' from server selected by + DHCPOFFER message client +'secs' 0 or seconds since 0 or seconds since 0 + DHCP process started DHCP process started +'flags' Set 'BROADCAST' Set 'BROADCAST' 0 + flag if client flag if client + requires broadcast requires broadcast + reply reply +'ciaddr' 0 (DHCPDISCOVER) 0 or client's 0 (DHCPDECLINE) + client's network address client's network + network address (BOUND/RENEW/REBIND) address + (DHCPINFORM) (DHCPRELEASE) +'yiaddr' 0 0 0 +'siaddr' 0 0 0 +'giaddr' 0 0 0 +'chaddr' client's hardware client's hardware client's hardware + address address address +'sname' options, if options, if (unused) + indicated in indicated in + 'sname/file' 'sname/file' + option; otherwise option; otherwise + unused unused +'file' options, if options, if (unused) + indicated in indicated in + 'sname/file' 'sname/file' + option; otherwise option; otherwise + unused unused +'options' options options (unused) + + + + + + + + + + + + + + + + +Droms Standards Track [Page 37] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +Option DHCPDISCOVER DHCPREQUEST DHCPDECLINE, + DHCPINFORM DHCPRELEASE +------ ------------ ----------- ----------- +Requested IP address MAY MUST (in MUST + (DISCOVER) SELECTING or (DHCPDECLINE), + MUST NOT INIT-REBOOT) MUST NOT + (INFORM) MUST NOT (in (DHCPRELEASE) + BOUND or + RENEWING) +IP address lease time MAY MAY MUST NOT + (DISCOVER) + MUST NOT + (INFORM) +Use 'file'/'sname' fields MAY MAY MAY +DHCP message type DHCPDISCOVER/ DHCPREQUEST DHCPDECLINE/ + DHCPINFORM DHCPRELEASE +Client identifier MAY MAY MAY +Vendor class identifier MAY MAY MUST NOT +Server identifier MUST NOT MUST (after MUST + SELECTING) + MUST NOT (after + INIT-REBOOT, + BOUND, RENEWING + or REBINDING) +Parameter request list MAY MAY MUST NOT +Maximum message size MAY MAY MUST NOT +Message SHOULD NOT SHOULD NOT SHOULD +Site-specific MAY MAY MUST NOT +All others MAY MAY MUST NOT + + Table 5: Fields and options used by DHCP clients + + If the parameters are acceptable, the client records the address of + the server that supplied the parameters from the 'server identifier' + field and sends that address in the 'server identifier' field of a + DHCPREQUEST broadcast message. Once the DHCPACK message from the + server arrives, the client is initialized and moves to BOUND state. + The DHCPREQUEST message contains the same 'xid' as the DHCPOFFER + message. The client records the lease expiration time as the sum of + the time at which the original request was sent and the duration of + the lease from the DHCPACK message. The client SHOULD perform a + check on the suggested address to ensure that the address is not + already in use. For example, if the client is on a network that + supports ARP, the client may issue an ARP request for the suggested + request. When broadcasting an ARP request for the suggested address, + the client must fill in its own hardware address as the sender's + hardware address, and 0 as the sender's IP address, to avoid + confusing ARP caches in other hosts on the same subnet. If the + + + +Droms Standards Track [Page 38] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + network address appears to be in use, the client MUST send a + DHCPDECLINE message to the server. The client SHOULD broadcast an ARP + reply to announce the client's new IP address and clear any outdated + ARP cache entries in hosts on the client's subnet. + +4.4.2 Initialization with known network address + + The client begins in INIT-REBOOT state and sends a DHCPREQUEST + message. The client MUST insert its known network address as a + 'requested IP address' option in the DHCPREQUEST message. The client + may request specific configuration parameters by including the + 'parameter request list' option. The client generates and records a + random transaction identifier and inserts that identifier into the + 'xid' field. The client records its own local time for later use in + computing the lease expiration. The client MUST NOT include a + 'server identifier' in the DHCPREQUEST message. The client then + broadcasts the DHCPREQUEST on the local hardware broadcast address to + the 'DHCP server' UDP port. + + Once a DHCPACK message with an 'xid' field matching that in the + client's DHCPREQUEST message arrives from any server, the client is + initialized and moves to BOUND state. The client records the lease + expiration time as the sum of the time at which the DHCPREQUEST + message was sent and the duration of the lease from the DHCPACK + message. + +4.4.3 Initialization with an externally assigned network address + + The client sends a DHCPINFORM message. The client may request + specific configuration parameters by including the 'parameter request + list' option. The client generates and records a random transaction + identifier and inserts that identifier into the 'xid' field. The + client places its own network address in the 'ciaddr' field. The + client SHOULD NOT request lease time parameters. + + The client then unicasts the DHCPINFORM to the DHCP server if it + knows the server's address, otherwise it broadcasts the message to + the limited (all 1s) broadcast address. DHCPINFORM messages MUST be + directed to the 'DHCP server' UDP port. + + Once a DHCPACK message with an 'xid' field matching that in the + client's DHCPINFORM message arrives from any server, the client is + initialized. + + If the client does not receive a DHCPACK within a reasonable period + of time (60 seconds or 4 tries if using timeout suggested in section + 4.1), then it SHOULD display a message informing the user of the + problem, and then SHOULD begin network processing using suitable + + + +Droms Standards Track [Page 39] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + defaults as per Appendix A. + +4.4.4 Use of broadcast and unicast + + The DHCP client broadcasts DHCPDISCOVER, DHCPREQUEST and DHCPINFORM + messages, unless the client knows the address of a DHCP server. The + client unicasts DHCPRELEASE messages to the server. Because the + client is declining the use of the IP address supplied by the server, + the client broadcasts DHCPDECLINE messages. + + When the DHCP client knows the address of a DHCP server, in either + INIT or REBOOTING state, the client may use that address in the + DHCPDISCOVER or DHCPREQUEST rather than the IP broadcast address. + The client may also use unicast to send DHCPINFORM messages to a + known DHCP server. If the client receives no response to DHCP + messages sent to the IP address of a known DHCP server, the DHCP + client reverts to using the IP broadcast address. + +4.4.5 Reacquisition and expiration + + The client maintains two times, T1 and T2, that specify the times at + which the client tries to extend its lease on its network address. + T1 is the time at which the client enters the RENEWING state and + attempts to contact the server that originally issued the client's + network address. T2 is the time at which the client enters the + REBINDING state and attempts to contact any server. T1 MUST be + earlier than T2, which, in turn, MUST be earlier than the time at + which the client's lease will expire. + + To avoid the need for synchronized clocks, T1 and T2 are expressed in + options as relative times [2]. + + At time T1 the client moves to RENEWING state and sends (via unicast) + a DHCPREQUEST message to the server to extend its lease. The client + sets the 'ciaddr' field in the DHCPREQUEST to its current network + address. The client records the local time at which the DHCPREQUEST + message is sent for computation of the lease expiration time. The + client MUST NOT include a 'server identifier' in the DHCPREQUEST + message. + + Any DHCPACK messages that arrive with an 'xid' that does not match + the 'xid' of the client's DHCPREQUEST message are silently discarded. + When the client receives a DHCPACK from the server, the client + computes the lease expiration time as the sum of the time at which + the client sent the DHCPREQUEST message and the duration of the lease + in the DHCPACK message. The client has successfully reacquired its + network address, returns to BOUND state and may continue network + processing. + + + +Droms Standards Track [Page 40] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + If no DHCPACK arrives before time T2, the client moves to REBINDING + state and sends (via broadcast) a DHCPREQUEST message to extend its + lease. The client sets the 'ciaddr' field in the DHCPREQUEST to its + current network address. The client MUST NOT include a 'server + identifier' in the DHCPREQUEST message. + + Times T1 and T2 are configurable by the server through options. T1 + defaults to (0.5 * duration_of_lease). T2 defaults to (0.875 * + duration_of_lease). Times T1 and T2 SHOULD be chosen with some + random "fuzz" around a fixed value, to avoid synchronization of + client reacquisition. + + A client MAY choose to renew or extend its lease prior to T1. The + server MAY choose to extend the client's lease according to policy + set by the network administrator. The server SHOULD return T1 and + T2, and their values SHOULD be adjusted from their original values to + take account of the time remaining on the lease. + + In both RENEWING and REBINDING states, if the client receives no + response to its DHCPREQUEST message, the client SHOULD wait one-half + of the remaining time until T2 (in RENEWING state) and one-half of + the remaining lease time (in REBINDING state), down to a minimum of + 60 seconds, before retransmitting the DHCPREQUEST message. + + If the lease expires before the client receives a DHCPACK, the client + moves to INIT state, MUST immediately stop any other network + processing and requests network initialization parameters as if the + client were uninitialized. If the client then receives a DHCPACK + allocating that client its previous network address, the client + SHOULD continue network processing. If the client is given a new + network address, it MUST NOT continue using the previous network + address and SHOULD notify the local users of the problem. + +4.4.6 DHCPRELEASE + + If the client no longer requires use of its assigned network address + (e.g., the client is gracefully shut down), the client sends a + DHCPRELEASE message to the server. Note that the correct operation + of DHCP does not depend on the transmission of DHCPRELEASE messages. + + + + + + + + + + + + +Droms Standards Track [Page 41] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +5. Acknowledgments + + The author thanks the many (and too numerous to mention!) members of + the DHC WG for their tireless and ongoing efforts in the development + of DHCP and this document. + + The efforts of J Allard, Mike Carney, Dave Lapp, Fred Lien and John + Mendonca in organizing DHCP interoperability testing sessions are + gratefully acknowledged. + + The development of this document was supported in part by grants from + the Corporation for National Research Initiatives (CNRI), Bucknell + University and Sun Microsystems. + +6. References + + [1] Acetta, M., "Resource Location Protocol", RFC 887, CMU, December + 1983. + + [2] Alexander, S., and R. Droms, "DHCP Options and BOOTP Vendor + Extensions", RFC 1533, Lachman Technology, Inc., Bucknell + University, October 1993. + + [3] Braden, R., Editor, "Requirements for Internet Hosts -- + Communication Layers", STD 3, RFC 1122, USC/Information Sciences + Institute, October 1989. + + [4] Braden, R., Editor, "Requirements for Internet Hosts -- + Application and Support, STD 3, RFC 1123, USC/Information + Sciences Institute, October 1989. + + [5] Brownell, D, "Dynamic Reverse Address Resolution Protocol + (DRARP)", Work in Progress. + + [6] Comer, D., and R. Droms, "Uniform Access to Internet Directory + Services", Proc. of ACM SIGCOMM '90 (Special issue of Computer + Communications Review), 20(4):50--59, 1990. + + [7] Croft, B., and J. Gilmore, "Bootstrap Protocol (BOOTP)", RFC 951, + Stanford and SUN Microsystems, September 1985. + + [8] Deering, S., "ICMP Router Discovery Messages", RFC 1256, Xerox + PARC, September 1991. + + [9] Droms, D., "Interoperation between DHCP and BOOTP", RFC 1534, + Bucknell University, October 1993. + + + + + +Droms Standards Track [Page 42] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + [10] Finlayson, R., Mann, T., Mogul, J., and M. Theimer, "A Reverse + Address Resolution Protocol", RFC 903, Stanford, June 1984. + + [11] Gray C., and D. Cheriton, "Leases: An Efficient Fault-Tolerant + Mechanism for Distributed File Cache Consistency", In Proc. of + the Twelfth ACM Symposium on Operating Systems Design, 1989. + + [12] Mockapetris, P., "Domain Names -- Concepts and Facilities", STD + 13, RFC 1034, USC/Information Sciences Institute, November 1987. + + [13] Mockapetris, P., "Domain Names -- Implementation and + Specification", STD 13, RFC 1035, USC/Information Sciences + Institute, November 1987. + + [14] Mogul J., and S. Deering, "Path MTU Discovery", RFC 1191, + November 1990. + + [15] Morgan, R., "Dynamic IP Address Assignment for Ethernet Attached + Hosts", Work in Progress. + + [16] Postel, J., "Internet Control Message Protocol", STD 5, RFC 792, + USC/Information Sciences Institute, September 1981. + + [17] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497, + USC/Information Sciences Institute, August 1993. + + [18] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700, + USC/Information Sciences Institute, October 1994. + + [19] Jeffrey Schiller and Mark Rosenstein. A Protocol for the Dynamic + Assignment of IP Addresses for use on an Ethernet. (Available + from the Athena Project, MIT), 1989. + + [20] Sollins, K., "The TFTP Protocol (Revision 2)", RFC 783, NIC, + June 1981. + + [21] Wimer, W., "Clarifications and Extensions for the Bootstrap + Protocol", RFC 1542, Carnegie Mellon University, October 1993. + +7. Security Considerations + + DHCP is built directly on UDP and IP which are as yet inherently + insecure. Furthermore, DHCP is generally intended to make + maintenance of remote and/or diskless hosts easier. While perhaps + not impossible, configuring such hosts with passwords or keys may be + difficult and inconvenient. Therefore, DHCP in its current form is + quite insecure. + + + + +Droms Standards Track [Page 43] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + + Unauthorized DHCP servers may be easily set up. Such servers can + then send false and potentially disruptive information to clients + such as incorrect or duplicate IP addresses, incorrect routing + information (including spoof routers, etc.), incorrect domain + nameserver addresses (such as spoof nameservers), and so on. + Clearly, once this seed information is in place, an attacker can + further compromise affected systems. + + Malicious DHCP clients could masquerade as legitimate clients and + retrieve information intended for those legitimate clients. Where + dynamic allocation of resources is used, a malicious client could + claim all resources for itself, thereby denying resources to + legitimate clients. + +8. Author's Address + + Ralph Droms + Computer Science Department + 323 Dana Engineering + Bucknell University + Lewisburg, PA 17837 + + Phone: (717) 524-1145 + EMail: droms@bucknell.edu + + + + + + + + + + + + + + + + + + + + + + + + + + + +Droms Standards Track [Page 44] + +RFC 2131 Dynamic Host Configuration Protocol March 1997 + + +A. Host Configuration Parameters + + IP-layer_parameters,_per_host:_ + + Be a router on/off HRC 3.1 + Non-local source routing on/off HRC 3.3.5 + Policy filters for + non-local source routing (list) HRC 3.3.5 + Maximum reassembly size integer HRC 3.3.2 + Default TTL integer HRC 3.2.1.7 + PMTU aging timeout integer MTU 6.6 + MTU plateau table (list) MTU 7 + IP-layer_parameters,_per_interface:_ + IP address (address) HRC 3.3.1.6 + Subnet mask (address mask) HRC 3.3.1.6 + MTU integer HRC 3.3.3 + All-subnets-MTU on/off HRC 3.3.3 + Broadcast address flavor 0x00000000/0xffffffff HRC 3.3.6 + Perform mask discovery on/off HRC 3.2.2.9 + Be a mask supplier on/off HRC 3.2.2.9 + Perform router discovery on/off RD 5.1 + Router solicitation address (address) RD 5.1 + Default routers, list of: + router address (address) HRC 3.3.1.6 + preference level integer HRC 3.3.1.6 + Static routes, list of: + destination (host/subnet/net) HRC 3.3.1.2 + destination mask (address mask) HRC 3.3.1.2 + type-of-service integer HRC 3.3.1.2 + first-hop router (address) HRC 3.3.1.2 + ignore redirects on/off HRC 3.3.1.2 + PMTU integer MTU 6.6 + perform PMTU discovery on/off MTU 6.6 + + Link-layer_parameters,_per_interface:_ + Trailers on/off HRC 2.3.1 + ARP cache timeout integer HRC 2.3.2.1 + Ethernet encapsulation (RFC 894/RFC 1042) HRC 2.3.3 + + TCP_parameters,_per_host:_ + TTL integer HRC 4.2.2.19 + Keep-alive interval integer HRC 4.2.3.6 + Keep-alive data size 0/1 HRC 4.2.3.6 + +Key: + + MTU = Path MTU Discovery (RFC 1191, Proposed Standard) + RD = Router Discovery (RFC 1256, Proposed Standard) + + + +Droms Standards Track [Page 45] + diff --git a/usr.sbin/dhcp/doc/rfc2132.txt b/usr.sbin/dhcp/doc/rfc2132.txt new file mode 100644 index 00000000000..e9c4f4b30ac --- /dev/null +++ b/usr.sbin/dhcp/doc/rfc2132.txt @@ -0,0 +1,1907 @@ + + + + + + +Network Working Group S. Alexander +Request for Comments: 2132 Silicon Graphics, Inc. +Obsoletes: 1533 R. Droms +Category: Standards Track Bucknell University + March 1997 + + DHCP Options and BOOTP Vendor Extensions + +Status of this memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Abstract + + The Dynamic Host Configuration Protocol (DHCP) [1] provides a + framework for passing configuration information to hosts on a TCP/IP + network. Configuration parameters and other control information are + carried in tagged data items that are stored in the 'options' field + of the DHCP message. The data items themselves are also called + "options." + + This document specifies the current set of DHCP options. Future + options will be specified in separate RFCs. The current list of + valid options is also available in ftp://ftp.isi.edu/in- + notes/iana/assignments [22]. + + All of the vendor information extensions defined in RFC 1497 [2] may + be used as DHCP options. The definitions given in RFC 1497 are + included in this document, which supersedes RFC 1497. All of the + DHCP options defined in this document, except for those specific to + DHCP as defined in section 9, may be used as BOOTP vendor information + extensions. + +Table of Contents + + 1. Introduction .............................................. 2 + 2. BOOTP Extension/DHCP Option Field Format .................. 4 + 3. RFC 1497 Vendor Extensions ................................ 5 + 4. IP Layer Parameters per Host .............................. 11 + 5. IP Layer Parameters per Interface ........................ 13 + 6. Link Layer Parameters per Interface ....................... 16 + 7. TCP Parameters ............................................ 17 + 8. Application and Service Parameters ........................ 18 + 9. DHCP Extensions ........................................... 25 + + + +Alexander & Droms Standards Track [Page 1] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + 10. Defining new extensions ................................... 31 + 11. Acknowledgements .......................................... 31 + 12. References ................................................ 32 + 13. Security Considerations ................................... 33 + 14. Authors' Addresses ........................................ 34 + +1. Introduction + + This document specifies options for use with both the Dynamic Host + Configuration Protocol and the Bootstrap Protocol. + + The full description of DHCP packet formats may be found in the DHCP + specification document [1], and the full description of BOOTP packet + formats may be found in the BOOTP specification document [3]. This + document defines the format of information in the last field of DHCP + packets ('options') and of BOOTP packets ('vend'). The remainder of + this section defines a generalized use of this area for giving + information useful to a wide class of machines, operating systems and + configurations. Sites with a single DHCP or BOOTP server that is + shared among heterogeneous clients may choose to define other, site- + specific formats for the use of the 'options' field. + + Section 2 of this memo describes the formats of DHCP options and + BOOTP vendor extensions. Section 3 describes options defined in + previous documents for use with BOOTP (all may also be used with + DHCP). Sections 4-8 define new options intended for use with both + DHCP and BOOTP. Section 9 defines options used only in DHCP. + + References further describing most of the options defined in sections + 2-6 can be found in section 12. The use of the options defined in + section 9 is described in the DHCP specification [1]. + + Information on registering new options is contained in section 10. + + This document updates the definition of DHCP/BOOTP options that + appears in RFC1533. The classing mechanism has been extended to + include vendor classes as described in section 8.4 and 9.13. The new + procedure for defining new DHCP/BOOTP options in described in section + 10. Several new options, including NIS+ domain and servers, Mobile + IP home agent, SMTP server, TFTP server and Bootfile server, have + been added. Text giving definitions used throughout the document has + been added in section 1.1. Text emphasizing the need for uniqueness + of client-identifiers has been added to section 9.14. + + + + + + + + +Alexander & Droms Standards Track [Page 2] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +1.1 Requirements + + Throughout this document, the words that are used to define the + significance of particular requirements are capitalized. These words + are: + + o "MUST" + + This word or the adjective "REQUIRED" means that the item is an + absolute requirement of this specification. + + o "MUST NOT" + + This phrase means that the item is an absolute prohibition of + this specification. + + o "SHOULD" + + This word or the adjective "RECOMMENDED" means that there may + exist valid reasons in particular circumstances to ignore this + item, but the full implications should be understood and the case + carefully weighed before choosing a different course. + + o "SHOULD NOT" + + This phrase means that there may exist valid reasons in + particular circumstances when the listed behavior is acceptable + or even useful, but the full implications should be understood + and the case carefully weighed before implementing any behavior + described with this label. + + o "MAY" + + This word or the adjective "OPTIONAL" means that this item is + truly optional. One vendor may choose to include the item + because a particular marketplace requires it or because it + enhances the product, for example; another vendor may omit the + same item. + +1.2 Terminology + + This document uses the following terms: + + o "DHCP client" + + A DHCP client or "client" is an Internet host using DHCP to + obtain configuration parameters such as a network address. + + + + +Alexander & Droms Standards Track [Page 3] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + o "DHCP server" + + A DHCP server of "server"is an Internet host that returns + configuration parameters to DHCP clients. + + o "binding" + + A binding is a collection of configuration parameters, including + at least an IP address, associated with or "bound to" a DHCP + client. Bindings are managed by DHCP servers. + +2. BOOTP Extension/DHCP Option Field Format + + + DHCP options have the same format as the BOOTP 'vendor extensions' + defined in RFC 1497 [2]. Options may be fixed length or variable + length. All options begin with a tag octet, which uniquely + identifies the option. Fixed-length options without data consist of + only a tag octet. Only options 0 and 255 are fixed length. All + other options are variable-length with a length octet following the + tag octet. The value of the length octet does not include the two + octets specifying the tag and length. The length octet is followed + by "length" octets of data. Options containing NVT ASCII data SHOULD + NOT include a trailing NULL; however, the receiver of such options + MUST be prepared to delete trailing nulls if they exist. The + receiver MUST NOT require that a trailing null be included in the + data. In the case of some variable-length options the length field + is a constant but must still be specified. + + Any options defined subsequent to this document MUST contain a length + octet even if the length is fixed or zero. + + All multi-octet quantities are in network byte-order. + + When used with BOOTP, the first four octets of the vendor information + field have been assigned to the "magic cookie" (as suggested in RFC + 951). This field identifies the mode in which the succeeding data is + to be interpreted. The value of the magic cookie is the 4 octet + dotted decimal 99.130.83.99 (or hexadecimal number 63.82.53.63) in + network byte order. + + All of the "vendor extensions" defined in RFC 1497 are also DHCP + options. + + Option codes 128 to 254 (decimal) are reserved for site-specific + options. + + + + + +Alexander & Droms Standards Track [Page 4] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Except for the options in section 9, all options may be used with + either DHCP or BOOTP. + + Many of these options have their default values specified in other + documents. In particular, RFC 1122 [4] specifies default values for + most IP and TCP configuration parameters. + + Many options supply one or more 32-bit IP address. Use of IP + addresses rather than fully-qualified Domain Names (FQDNs) may make + future renumbering of IP hosts more difficult. Use of these + addresses is discouraged at sites that may require renumbering. + +3. RFC 1497 Vendor Extensions + + This section lists the vendor extensions as defined in RFC 1497. + They are defined here for completeness. + +3.1. Pad Option + + The pad option can be used to cause subsequent fields to align on + word boundaries. + + The code for the pad option is 0, and its length is 1 octet. + + Code + +-----+ + | 0 | + +-----+ + +3.2. End Option + + The end option marks the end of valid information in the vendor + field. Subsequent octets should be filled with pad options. + + The code for the end option is 255, and its length is 1 octet. + + Code + +-----+ + | 255 | + +-----+ + +3.3. Subnet Mask + + The subnet mask option specifies the client's subnet mask as per RFC + 950 [5]. + + If both the subnet mask and the router option are specified in a DHCP + reply, the subnet mask option MUST be first. + + + +Alexander & Droms Standards Track [Page 5] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for the subnet mask option is 1, and its length is 4 octets. + + Code Len Subnet Mask + +-----+-----+-----+-----+-----+-----+ + | 1 | 4 | m1 | m2 | m3 | m4 | + +-----+-----+-----+-----+-----+-----+ + +3.4. Time Offset + + The time offset field specifies the offset of the client's subnet in + seconds from Coordinated Universal Time (UTC). The offset is + expressed as a two's complement 32-bit integer. A positive offset + indicates a location east of the zero meridian and a negative offset + indicates a location west of the zero meridian. + + The code for the time offset option is 2, and its length is 4 octets. + + Code Len Time Offset + +-----+-----+-----+-----+-----+-----+ + | 2 | 4 | n1 | n2 | n3 | n4 | + +-----+-----+-----+-----+-----+-----+ + +3.5. Router Option + + The router option specifies a list of IP addresses for routers on the + client's subnet. Routers SHOULD be listed in order of preference. + + The code for the router option is 3. The minimum length for the + router option is 4 octets, and the length MUST always be a multiple + of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 3 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.6. Time Server Option + + The time server option specifies a list of RFC 868 [6] time servers + available to the client. Servers SHOULD be listed in order of + preference. + + The code for the time server option is 4. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + + + + + +Alexander & Droms Standards Track [Page 6] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 4 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.7. Name Server Option + + The name server option specifies a list of IEN 116 [7] name servers + available to the client. Servers SHOULD be listed in order of + preference. + + The code for the name server option is 5. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 5 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.8. Domain Name Server Option + + The domain name server option specifies a list of Domain Name System + (STD 13, RFC 1035 [8]) name servers available to the client. Servers + SHOULD be listed in order of preference. + + The code for the domain name server option is 6. The minimum length + for this option is 4 octets, and the length MUST always be a multiple + of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.9. Log Server Option + + 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. + + The code for the log server option is 7. The minimum length for this + option is 4 octets, and the length MUST always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 7 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + + + +Alexander & Droms Standards Track [Page 7] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +3.10. Cookie Server Option + + The cookie server option specifies a list of RFC 865 [9] cookie + servers available to the client. Servers SHOULD be listed in order + of preference. + + The code for the log server option is 8. The minimum length for this + option is 4 octets, and the length MUST always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 8 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.11. LPR Server Option + + The LPR server option specifies a list of RFC 1179 [10] line printer + servers available to the client. Servers SHOULD be listed in order + of preference. + + The code for the LPR server option is 9. The minimum length for this + option is 4 octets, and the length MUST always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 9 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.12. Impress Server Option + + The Impress server option specifies a list of Imagen Impress servers + available to the client. Servers SHOULD be listed in order of + preference. + + The code for the Impress server option is 10. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 10 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.13. Resource Location Server Option + + This option specifies a list of RFC 887 [11] Resource Location + servers available to the client. Servers SHOULD be listed in order + of preference. + + + +Alexander & Droms Standards Track [Page 8] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for this option is 11. The minimum length for this option + is 4 octets, and the length MUST always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 11 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.14. Host Name Option + + This option specifies the name of the client. The name may or may + not be qualified with the local domain name (see section 3.17 for the + preferred way to retrieve the domain name). See RFC 1035 for + character set restrictions. + + The code for this option is 12, and its minimum length is 1. + + Code Len Host Name + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 12 | n | h1 | h2 | h3 | h4 | h5 | h6 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +3.15. Boot File Size Option + + This option specifies the length in 512-octet blocks of the default + boot image for the client. The file length is specified as an + unsigned 16-bit integer. + + The code for this option is 13, and its length is 2. + + Code Len File Size + +-----+-----+-----+-----+ + | 13 | 2 | l1 | l2 | + +-----+-----+-----+-----+ + +3.16. Merit Dump File + + 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. + + The code for this option is 14. Its minimum length is 1. + + Code Len Dump File Pathname + +-----+-----+-----+-----+-----+-----+--- + | 14 | n | n1 | n2 | n3 | n4 | ... + +-----+-----+-----+-----+-----+-----+--- + + + +Alexander & Droms Standards Track [Page 9] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +3.17. Domain Name + + This option specifies the domain name that client should use when + resolving hostnames via the Domain Name System. + + The code for this option is 15. Its minimum length is 1. + + Code Len Domain Name + +-----+-----+-----+-----+-----+-----+-- + | 15 | n | d1 | d2 | d3 | d4 | ... + +-----+-----+-----+-----+-----+-----+-- + +3.18. Swap Server + + This specifies the IP address of the client's swap server. + + The code for this option is 16 and its length is 4. + + Code Len Swap Server Address + +-----+-----+-----+-----+-----+-----+ + | 16 | n | a1 | a2 | a3 | a4 | + +-----+-----+-----+-----+-----+-----+ + +3.19. Root Path + + 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. + + The code for this option is 17. Its minimum length is 1. + + Code Len Root Disk Pathname + +-----+-----+-----+-----+-----+-----+--- + | 17 | n | n1 | n2 | n3 | n4 | ... + +-----+-----+-----+-----+-----+-----+--- + +3.20. Extensions Path + + A string to specify a file, retrievable via TFTP, which contains + information which can be interpreted in the same way as the 64-octet + vendor-extension field within the BOOTP response, with the following + exceptions: + + - the length of the file is unconstrained; + - all references to Tag 18 (i.e., instances of the + BOOTP Extensions Path field) within the file are + ignored. + + + + +Alexander & Droms Standards Track [Page 10] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for this option is 18. Its minimum length is 1. + + Code Len Extensions Pathname + +-----+-----+-----+-----+-----+-----+--- + | 18 | n | n1 | n2 | n3 | n4 | ... + +-----+-----+-----+-----+-----+-----+--- + +4. IP Layer Parameters per Host + + This section details the options that affect the operation of the IP + layer on a per-host basis. + +4.1. IP Forwarding Enable/Disable Option + + 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. + + The code for this option is 19, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 19 | 1 | 0/1 | + +-----+-----+-----+ + +4.2. Non-Local Source Routing Enable/Disable Option + + 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. + + The code for this option is 20, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 20 | 1 | 0/1 | + +-----+-----+-----+ + +4.3. Policy Filter Option + + This option specifies policy filters for non-local source routing. + The filters consist of a list of IP addresses and masks which specify + destination/mask pairs with which to filter incoming source routes. + + Any source routed datagram whose next-hop address does not match one + of the filters should be discarded by the client. + + + +Alexander & Droms Standards Track [Page 11] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + See [4] for further information. + + The code for this option is 21. The minimum length of this option is + 8, and the length MUST be a multiple of 8. + + Code Len Address 1 Mask 1 + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ + | 21 | n | a1 | a2 | a3 | a4 | m1 | m2 | m3 | m4 | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ + Address 2 Mask 2 + +-----+-----+-----+-----+-----+-----+-----+-----+--- + | a1 | a2 | a3 | a4 | m1 | m2 | m3 | m4 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+--- + +4.4. Maximum Datagram Reassembly Size + + This option specifies the maximum size datagram that the client + should be prepared to reassemble. The size is specified as a 16-bit + unsigned integer. The minimum value legal value is 576. + + The code for this option is 22, and its length is 2. + + Code Len Size + +-----+-----+-----+-----+ + | 22 | 2 | s1 | s2 | + +-----+-----+-----+-----+ + +4.5. Default IP Time-to-live + + This option specifies the default time-to-live that the client should + use on outgoing datagrams. The TTL is specified as an octet with a + value between 1 and 255. + + The code for this option is 23, and its length is 1. + + Code Len TTL + +-----+-----+-----+ + | 23 | 1 | ttl | + +-----+-----+-----+ + +4.6. Path MTU Aging Timeout Option + + This option specifies the timeout (in seconds) to use when aging Path + MTU values discovered by the mechanism defined in RFC 1191 [12]. The + timeout is specified as a 32-bit unsigned integer. + + The code for this option is 24, and its length is 4. + + + + +Alexander & Droms Standards Track [Page 12] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Code Len Timeout + +-----+-----+-----+-----+-----+-----+ + | 24 | 4 | t1 | t2 | t3 | t4 | + +-----+-----+-----+-----+-----+-----+ + +4.7. Path MTU Plateau Table Option + + 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. + + The code for this option is 25. Its minimum length is 2, and the + length MUST be a multiple of 2. + + Code Len Size 1 Size 2 + +-----+-----+-----+-----+-----+-----+--- + | 25 | n | s1 | s2 | s1 | s2 | ... + +-----+-----+-----+-----+-----+-----+--- + +5. IP Layer Parameters per Interface + + This section details the options that affect the operation of the IP + layer on a per-interface basis. It is expected that a client can + issue multiple requests, one per interface, in order to configure + interfaces with their specific parameters. + +5.1. Interface MTU Option + + This option specifies the MTU to use on this interface. The MTU is + specified as a 16-bit unsigned integer. The minimum legal value for + the MTU is 68. + + The code for this option is 26, and its length is 2. + + Code Len MTU + +-----+-----+-----+-----+ + | 26 | 2 | m1 | m2 | + +-----+-----+-----+-----+ + +5.2. All Subnets are Local Option + + This option specifies whether or not the client may assume that all + subnets of the IP network to which the client is connected use the + same MTU as the subnet of that network to which the client is + directly connected. A value of 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. + + + +Alexander & Droms Standards Track [Page 13] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for this option is 27, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 27 | 1 | 0/1 | + +-----+-----+-----+ + +5.3. Broadcast Address Option + + 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 [4]. + + The code for this option is 28, and its length is 4. + + Code Len Broadcast Address + +-----+-----+-----+-----+-----+-----+ + | 28 | 4 | b1 | b2 | b3 | b4 | + +-----+-----+-----+-----+-----+-----+ + +5.4. Perform Mask Discovery Option + + 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. + + The code for this option is 29, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 29 | 1 | 0/1 | + +-----+-----+-----+ + +5.5. Mask Supplier Option + + 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. + + The code for this option is 30, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 30 | 1 | 0/1 | + +-----+-----+-----+ + + + + +Alexander & Droms Standards Track [Page 14] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +5.6. Perform Router Discovery Option + + This option specifies whether or not the client should solicit + routers using the Router Discovery mechanism defined in RFC 1256 + [13]. 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. + + The code for this option is 31, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 31 | 1 | 0/1 | + +-----+-----+-----+ + +5.7. Router Solicitation Address Option + + This option specifies the address to which the client should transmit + router solicitation requests. + + The code for this option is 32, and its length is 4. + + Code Len Address + +-----+-----+-----+-----+-----+-----+ + | 32 | 4 | a1 | a2 | a3 | a4 | + +-----+-----+-----+-----+-----+-----+ + +5.8. Static Route Option + + This option specifies a list of static routes that the client should + install in its routing cache. If multiple routes to the same + destination are specified, they are listed in descending order of + priority. + + The routes consist of a list of IP address pairs. The first address + is the destination address, and the second address is the router for + the destination. + + The default route (0.0.0.0) is an illegal destination for a static + route. See section 3.5 for information about the router option. + + The code for this option is 33. The minimum length of this option is + 8, and the length MUST be a multiple of 8. + + + + + + + + +Alexander & Droms Standards Track [Page 15] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Code Len Destination 1 Router 1 + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ + | 33 | n | d1 | d2 | d3 | d4 | r1 | r2 | r3 | r4 | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ + Destination 2 Router 2 + +-----+-----+-----+-----+-----+-----+-----+-----+--- + | d1 | d2 | d3 | d4 | r1 | r2 | r3 | r4 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+--- + +6. Link Layer Parameters per Interface + + This section lists the options that affect the operation of the data + link layer on a per-interface basis. + +6.1. Trailer Encapsulation Option + + 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. + + The code for this option is 34, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 34 | 1 | 0/1 | + +-----+-----+-----+ + +6.2. ARP Cache Timeout Option + + This option specifies the timeout in seconds for ARP cache entries. + The time is specified as a 32-bit unsigned integer. + + The code for this option is 35, and its length is 4. + + Code Len Time + +-----+-----+-----+-----+-----+-----+ + | 35 | 4 | t1 | t2 | t3 | t4 | + +-----+-----+-----+-----+-----+-----+ + +6.3. Ethernet Encapsulation Option + + This option specifies whether or not the client should use Ethernet + Version 2 (RFC 894 [15]) or IEEE 802.3 (RFC 1042 [16]) 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. + + + + +Alexander & Droms Standards Track [Page 16] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for this option is 36, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 36 | 1 | 0/1 | + +-----+-----+-----+ + +7. TCP Parameters + + This section lists the options that affect the operation of the TCP + layer on a per-interface basis. + +7.1. TCP Default TTL Option + + This option specifies the default TTL that the client should use when + sending TCP segments. The value is represented as an 8-bit unsigned + integer. The minimum value is 1. + + The code for this option is 37, and its length is 1. + + Code Len TTL + +-----+-----+-----+ + | 37 | 1 | n | + +-----+-----+-----+ + +7.2. TCP Keepalive Interval Option + + 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. + + The code for this option is 38, and its length is 4. + + Code Len Time + +-----+-----+-----+-----+-----+-----+ + | 38 | 4 | t1 | t2 | t3 | t4 | + +-----+-----+-----+-----+-----+-----+ + +7.3. TCP Keepalive Garbage Option + + 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. + + + + +Alexander & Droms Standards Track [Page 17] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for this option is 39, and its length is 1. + + Code Len Value + +-----+-----+-----+ + | 39 | 1 | 0/1 | + +-----+-----+-----+ + +8. Application and Service Parameters + + This section details some miscellaneous options used to configure + miscellaneous applications and services. + +8.1. Network Information Service Domain Option + + This option specifies the name of the client's NIS [17] domain. The + domain is formatted as a character string consisting of characters + from the NVT ASCII character set. + + The code for this option is 40. Its minimum length is 1. + + Code Len NIS Domain Name + +-----+-----+-----+-----+-----+-----+--- + | 40 | n | n1 | n2 | n3 | n4 | ... + +-----+-----+-----+-----+-----+-----+--- + +8.2. Network Information Servers Option + + This option specifies a list of IP addresses indicating NIS servers + available to the client. Servers SHOULD be listed in order of + preference. + + The code for this option is 41. Its minimum length is 4, and the + length MUST be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 41 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.3. Network Time Protocol Servers Option + + This option specifies a list of IP addresses indicating NTP [18] + servers available to the client. Servers SHOULD be listed in order + of preference. + + The code for this option is 42. Its minimum length is 4, and the + length MUST be a multiple of 4. + + + + +Alexander & Droms Standards Track [Page 18] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 42 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.4. Vendor Specific Information + + This option is used by clients and servers to exchange vendor- + specific information. The information is an opaque object of n + octets, presumably interpreted by vendor-specific code on the clients + and servers. The definition of this information is vendor specific. + The vendor is indicated in the vendor class identifier option. + Servers not equipped to interpret the vendor-specific information + sent by a client MUST ignore it (although it may be reported). + Clients which do not receive desired vendor-specific information + SHOULD make an attempt to operate without it, although they may do so + (and announce they are doing so) in a degraded mode. + + If a vendor potentially encodes more than one item of information in + this option, then the vendor SHOULD encode the option using + "Encapsulated vendor-specific options" as described below: + + The Encapsulated vendor-specific options field SHOULD be encoded as a + sequence of code/length/value fields of identical syntax to the DHCP + options field with the following exceptions: + + 1) There SHOULD NOT be a "magic cookie" field in the encapsulated + vendor-specific extensions field. + + 2) Codes other than 0 or 255 MAY be redefined by the vendor within + the encapsulated vendor-specific extensions field, but SHOULD + conform to the tag-length-value syntax defined in section 2. + + 3) Code 255 (END), if present, signifies the end of the + encapsulated vendor extensions, not the end of the vendor + extensions field. If no code 255 is present, then the end of + the enclosing vendor-specific information field is taken as the + end of the encapsulated vendor-specific extensions field. + + The code for this option is 43 and its minimum length is 1. + + Code Len Vendor-specific information + +-----+-----+-----+-----+--- + | 43 | n | i1 | i2 | ... + +-----+-----+-----+-----+--- + + + + + + +Alexander & Droms Standards Track [Page 19] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + When encapsulated vendor-specific extensions are used, the + information bytes 1-n have the following format: + + Code Len Data item Code Len Data item Code + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ + | T1 | n | d1 | d2 | ... | T2 | n | D1 | D2 | ... | ... | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ + +8.5. NetBIOS over TCP/IP Name Server Option + + The NetBIOS name server (NBNS) option specifies a list of RFC + 1001/1002 [19] [20] NBNS name servers listed in order of preference. + + The code for this option is 44. The minimum length of the option is + 4 octets, and the length must always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + | 44 | n | a1 | a2 | a3 | a4 | b1 | b2 | b3 | b4 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + +8.6. NetBIOS over TCP/IP Datagram Distribution Server Option + + The NetBIOS datagram distribution server (NBDD) option specifies a + list of RFC 1001/1002 NBDD servers listed in order of preference. The + code for this option is 45. The minimum length of the option is 4 + octets, and the length must always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + | 45 | n | a1 | a2 | a3 | a4 | b1 | b2 | b3 | b4 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + +8.7. NetBIOS over TCP/IP Node Type Option + + 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 + as follows: + + Value Node Type + ----- --------- + 0x1 B-node + 0x2 P-node + 0x4 M-node + 0x8 H-node + + + + + +Alexander & Droms Standards Track [Page 20] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + In the above chart, the notation '0x' indicates a number in base-16 + (hexadecimal). + + The code for this option is 46. The length of this option is always + 1. + + Code Len Node Type + +-----+-----+-----------+ + | 46 | 1 | see above | + +-----+-----+-----------+ + +8.8. NetBIOS over TCP/IP Scope Option + + The NetBIOS scope option specifies the NetBIOS over TCP/IP scope + parameter for the client as specified in RFC 1001/1002. See [19], + [20], and [8] for character-set restrictions. + + The code for this option is 47. The minimum length of this option is + 1. + + Code Len NetBIOS Scope + +-----+-----+-----+-----+-----+-----+---- + | 47 | n | s1 | s2 | s3 | s4 | ... + +-----+-----+-----+-----+-----+-----+---- + +8.9. X Window System Font Server Option + + This option specifies a list of X Window System [21] Font servers + available to the client. Servers SHOULD be listed in order of + preference. + + The code for this option is 48. The minimum length of this option is + 4 octets, and the length MUST be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+--- + | 48 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+--- + +8.10. X Window System Display Manager Option + + This option specifies a list of IP addresses 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. + + + + + +Alexander & Droms Standards Track [Page 21] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for the this option is 49. The minimum length of this option + is 4, and the length MUST be a multiple of 4. + + Code Len Address 1 Address 2 + + +-----+-----+-----+-----+-----+-----+-----+-----+--- + | 49 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+--- + +8.11. Network Information Service+ Domain Option + + This option specifies the name of the client's NIS+ [17] domain. The + domain is formatted as a character string consisting of characters + from the NVT ASCII character set. + + The code for this option is 64. Its minimum length is 1. + + Code Len NIS Client Domain Name + +-----+-----+-----+-----+-----+-----+--- + | 64 | n | n1 | n2 | n3 | n4 | ... + +-----+-----+-----+-----+-----+-----+--- + +8.12. Network Information Service+ Servers Option + + This option specifies a list of IP addresses indicating NIS+ servers + available to the client. Servers SHOULD be listed in order of + preference. + + The code for this option is 65. Its minimum length is 4, and the + length MUST be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 65 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.13. Mobile IP Home Agent option + + 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. + + The code for this option is 68. Its minimum length is 0 (indicating + no home agents are available) and the length MUST be a multiple of 4. + It is expected that the usual length will be four octets, containing + a single home agent's address. + + + + + +Alexander & Droms Standards Track [Page 22] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Code Len Home Agent Addresses (zero or more) + +-----+-----+-----+-----+-----+-----+-- + | 68 | n | a1 | a2 | a3 | a4 | ... + +-----+-----+-----+-----+-----+-----+-- + +8.14. Simple Mail Transport Protocol (SMTP) Server Option + + The SMTP server option specifies a list of SMTP servers available to + the client. Servers SHOULD be listed in order of preference. + + The code for the SMTP server option is 69. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 69 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.15. Post Office Protocol (POP3) Server Option + + The POP3 server option specifies a list of POP3 available to the + client. Servers SHOULD be listed in order of preference. + + The code for the POP3 server option is 70. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 70 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.16. Network News Transport Protocol (NNTP) Server Option + + The NNTP server option specifies a list of NNTP available to the + client. Servers SHOULD be listed in order of preference. + + The code for the NNTP server option is 71. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 71 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + + + + + +Alexander & Droms Standards Track [Page 23] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +8.17. Default World Wide Web (WWW) Server Option + + The WWW server option specifies a list of WWW available to the + client. Servers SHOULD be listed in order of preference. + + The code for the WWW server option is 72. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 72 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.18. Default Finger Server Option + + The Finger server option specifies a list of Finger available to the + client. Servers SHOULD be listed in order of preference. + + The code for the Finger server option is 73. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 73 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.19. Default Internet Relay Chat (IRC) Server Option + + The IRC server option specifies a list of IRC available to the + client. Servers SHOULD be listed in order of preference. + + The code for the IRC server option is 74. The minimum length for + this option is 4 octets, and the length MUST always be a multiple of + 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 74 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.20. StreetTalk Server Option + + The StreetTalk server option specifies a list of StreetTalk servers + available to the client. Servers SHOULD be listed in order of + preference. + + + + +Alexander & Droms Standards Track [Page 24] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for the StreetTalk server option is 75. The minimum length + for this option is 4 octets, and the length MUST always be a multiple + of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 75 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +8.21. StreetTalk Directory Assistance (STDA) Server Option + + 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. + + The code for the StreetTalk Directory Assistance server option is 76. + The minimum length for this option is 4 octets, and the length MUST + always be a multiple of 4. + + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 76 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + +9. DHCP Extensions + + This section details the options that are specific to DHCP. + +9.1. Requested IP Address + + This option is used in a client request (DHCPDISCOVER) to allow the + client to request that a particular IP address be assigned. + + The code for this option is 50, and its length is 4. + + Code Len Address + +-----+-----+-----+-----+-----+-----+ + | 50 | 4 | a1 | a2 | a3 | a4 | + +-----+-----+-----+-----+-----+-----+ + +9.2. IP Address Lease Time + + This option is used in a client request (DHCPDISCOVER or DHCPREQUEST) + to allow the client to request a lease time for the IP address. In a + server reply (DHCPOFFER), a DHCP server uses this option to specify + the lease time it is willing to offer. + + + + + +Alexander & Droms Standards Track [Page 25] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The time is in units of seconds, and is specified as a 32-bit + unsigned integer. + + The code for this option is 51, and its length is 4. + + Code Len Lease Time + +-----+-----+-----+-----+-----+-----+ + | 51 | 4 | t1 | t2 | t3 | t4 | + +-----+-----+-----+-----+-----+-----+ + +9.3. Option Overload + + This option is used to indicate that the DHCP 'sname' or 'file' + fields are being overloaded by using them to carry DHCP options. A + DHCP server inserts this option if the returned parameters will + exceed the usual space allotted for options. + + If this option is present, the client interprets the specified + additional fields after it concludes interpretation of the standard + option fields. + + The code for this option is 52, and its length is 1. Legal values + for this option are: + + Value Meaning + ----- -------- + 1 the 'file' field is used to hold options + 2 the 'sname' field is used to hold options + 3 both fields are used to hold options + + Code Len Value + +-----+-----+-----+ + | 52 | 1 |1/2/3| + +-----+-----+-----+ + +9.4 TFTP server name + + This option is used to identify a TFTP server when the 'sname' field + in the DHCP header has been used for DHCP options. + + The code for this option is 66, and its minimum length is 1. + + Code Len TFTP server + +-----+-----+-----+-----+-----+--- + | 66 | n | c1 | c2 | c3 | ... + +-----+-----+-----+-----+-----+--- + + + + + +Alexander & Droms Standards Track [Page 26] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +9.5 Bootfile name + + This option is used to identify a bootfile when the 'file' field in + the DHCP header has been used for DHCP options. + + The code for this option is 67, and its minimum length is 1. + + Code Len Bootfile name + +-----+-----+-----+-----+-----+--- + | 67 | n | c1 | c2 | c3 | ... + +-----+-----+-----+-----+-----+--- + +9.6. DHCP Message Type + + This option is used to convey the type of the DHCP message. The code + for this option is 53, and its length is 1. Legal values for this + option are: + + Value Message Type + ----- ------------ + 1 DHCPDISCOVER + 2 DHCPOFFER + 3 DHCPREQUEST + 4 DHCPDECLINE + 5 DHCPACK + 6 DHCPNAK + 7 DHCPRELEASE + 8 DHCPINFORM + + Code Len Type + +-----+-----+-----+ + | 53 | 1 | 1-9 | + +-----+-----+-----+ + +9.7. Server Identifier + + This option is used in DHCPOFFER and DHCPREQUEST messages, and may + optionally be included in the DHCPACK and DHCPNAK messages. DHCP + servers include this option in the DHCPOFFER in order to allow the + client to distinguish between lease offers. DHCP clients use the + contents of the 'server identifier' field as the destination address + for any DHCP messages unicast to the DHCP server. DHCP clients also + indicate which of several lease offers is being accepted by including + this option in a DHCPREQUEST message. + + The identifier is the IP address of the selected server. + + The code for this option is 54, and its length is 4. + + + +Alexander & Droms Standards Track [Page 27] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + Code Len Address + +-----+-----+-----+-----+-----+-----+ + | 54 | 4 | a1 | a2 | a3 | a4 | + +-----+-----+-----+-----+-----+-----+ + +9.8. Parameter Request List + + This option is used by a DHCP client to request values for specified + configuration parameters. The list of requested parameters is + specified as n octets, where each octet is a valid DHCP option code + as defined in this document. + + The client MAY list the options in order of preference. The DHCP + server is not required to return the options in the requested order, + but MUST try to insert the requested options in the order requested + by the client. + + The code for this option is 55. Its minimum length is 1. + + Code Len Option Codes + +-----+-----+-----+-----+--- + | 55 | n | c1 | c2 | ... + +-----+-----+-----+-----+--- + +9.9. Message + + This option is used by a DHCP server to provide an error message to a + DHCP client in a DHCPNAK message in the event of a failure. A client + may use this option in a DHCPDECLINE message to indicate the why the + client declined the offered parameters. The message consists of n + octets of NVT ASCII text, which the client may display on an + available output device. + + The code for this option is 56 and its minimum length is 1. + + Code Len Text + +-----+-----+-----+-----+--- + | 56 | n | c1 | c2 | ... + +-----+-----+-----+-----+--- + +9.10. Maximum DHCP Message Size + + This option specifies the maximum length DHCP message that it is + willing to accept. The length is specified as an unsigned 16-bit + integer. A client may use the maximum DHCP message size option in + DHCPDISCOVER or DHCPREQUEST messages, but should not use the option + in DHCPDECLINE messages. + + + + +Alexander & Droms Standards Track [Page 28] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The code for this option is 57, and its length is 2. The minimum + legal value is 576 octets. + + Code Len Length + +-----+-----+-----+-----+ + | 57 | 2 | l1 | l2 | + +-----+-----+-----+-----+ + +9.11. Renewal (T1) Time Value + + This option specifies the time interval from address assignment until + the client transitions to the RENEWING state. + + The value is in units of seconds, and is specified as a 32-bit + unsigned integer. + + The code for this option is 58, and its length is 4. + + Code Len T1 Interval + +-----+-----+-----+-----+-----+-----+ + | 58 | 4 | t1 | t2 | t3 | t4 | + +-----+-----+-----+-----+-----+-----+ + +9.12. Rebinding (T2) Time Value + + This option specifies the time interval from address assignment until + the client transitions to the REBINDING state. + + The value is in units of seconds, and is specified as a 32-bit + unsigned integer. + + The code for this option is 59, and its length is 4. + + Code Len T2 Interval + +-----+-----+-----+-----+-----+-----+ + | 59 | 4 | t1 | t2 | t3 | t4 | + +-----+-----+-----+-----+-----+-----+ + +9.13. Vendor class identifier + + This option is used by DHCP clients to optionally identify the vendor + type and configuration of a DHCP client. The information is a string + of n octets, interpreted by servers. Vendors may choose to define + specific vendor class identifiers to convey particular configuration + or other identification information about a client. For example, the + identifier may encode the client's hardware configuration. Servers + not equipped to interpret the class-specific information sent by a + client MUST ignore it (although it may be reported). Servers that + + + +Alexander & Droms Standards Track [Page 29] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + respond SHOULD only use option 43 to return the vendor-specific + information to the client. + + The code for this option is 60, and its minimum length is 1. + + Code Len Vendor class Identifier + +-----+-----+-----+-----+--- + | 60 | n | i1 | i2 | ... + +-----+-----+-----+-----+--- + +9.14. Client-identifier + + This option is used by DHCP clients to specify their unique + identifier. DHCP servers use this value to index their database of + address bindings. This value is expected to be unique for all + clients in an administrative domain. + + Identifiers SHOULD be treated as opaque objects by DHCP servers. + + The client identifier MAY consist of type-value pairs similar to the + 'htype'/'chaddr' fields defined in [3]. For instance, it MAY consist + of a hardware type and hardware address. In this case the type field + SHOULD be one of the ARP hardware types defined in STD2 [22]. A + hardware type of 0 (zero) should be used when the value field + contains an identifier other than a hardware address (e.g. a fully + qualified domain name). + + For correct identification of clients, each client's client- + identifier MUST be unique among the client-identifiers used on the + subnet to which the client is attached. Vendors and system + administrators are responsible for choosing client-identifiers that + meet this requirement for uniqueness. + + The code for this option is 61, and its minimum length is 2. + + Code Len Type Client-Identifier + +-----+-----+-----+-----+-----+--- + | 61 | n | t1 | i1 | i2 | ... + +-----+-----+-----+-----+-----+--- + + + + + + + + + + + + +Alexander & Droms Standards Track [Page 30] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +10. Defining new extensions + + The author of a new DHCP option will follow these steps to obtain + acceptance of the option as a part of the DHCP Internet Standard: + + 1. The author devises the new option. + 2. The author requests a number for the new option from IANA by + contacting: + Internet Assigned Numbers Authority (IANA) + USC/Information Sciences Institute + 4676 Admiralty Way + Marina del Rey, California 90292-6695 + + or by email as: iana@iana.org + + 3. The author documents the new option, using the newly obtained + option number, as an Internet Draft. + 4. The author submits the Internet Draft for review through the IETF + standards process as defined in "Internet Official Protocol + Standards" (STD 1). The new option will be submitted for eventual + acceptance as an Internet Standard. + 5. The new option progresses through the IETF standards process; the + new option will be reviewed by the Dynamic Host Configuration + Working Group (if that group still exists), or as an Internet + Draft not submitted by an IETF working group. + 6. If the new option fails to gain acceptance as an Internet + Standard, the assigned option number will be returned to IANA for + reassignment. + + This procedure for defining new extensions will ensure that: + + * allocation of new option numbers is coordinated from a single + authority, + * new options are reviewed for technical correctness and + appropriateness, and + * documentation for new options is complete and published. + +11. Acknowledgements + + The author thanks the many (and too numerous to mention!) members of + the DHC WG for their tireless and ongoing efforts in the development + of DHCP and this document. + + The efforts of J Allard, Mike Carney, Dave Lapp, Fred Lien and John + Mendonca in organizing DHCP interoperability testing sessions are + gratefully acknowledged. + + + + + +Alexander & Droms Standards Track [Page 31] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + The development of this document was supported in part by grants from + the Corporation for National Research Initiatives (CNRI), Bucknell + University and Sun Microsystems. + +12. References + + [1] Droms, R., "Dynamic Host Configuration Protocol", RFC 2131, + Bucknell University, March 1997. + + [2] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497, + USC/Information Sciences Institute, August 1993. + + [3] Croft, W., and J. Gilmore, "Bootstrap Protocol", RFC 951, + Stanford University and Sun Microsystems, September 1985. + + [4] Braden, R., Editor, "Requirements for Internet Hosts - + Communication Layers", STD 3, RFC 1122, USC/Information Sciences + Institute, October 1989. + + [5] Mogul, J., and J. Postel, "Internet Standard Subnetting + Procedure", STD 5, RFC 950, USC/Information Sciences Institute, + August 1985. + + [6] Postel, J., and K. Harrenstien, "Time Protocol", STD 26, RFC + 868, USC/Information Sciences Institute, SRI, May 1983. + + [7] Postel, J., "Name Server", IEN 116, USC/Information Sciences + Institute, August 1979. + + [8] Mockapetris, P., "Domain Names - Implementation and + Specification", STD 13, RFC 1035, USC/Information Sciences + Institute, November 1987. + + [9] Postel, J., "Quote of the Day Protocol", STD 23, RFC 865, + USC/Information Sciences Institute, May 1983. + + [10] McLaughlin, L., "Line Printer Daemon Protocol", RFC 1179, The + Wollongong Group, August 1990. + + [11] Accetta, M., "Resource Location Protocol", RFC 887, CMU, + December 1983. + + [12] Mogul, J. and S. Deering, "Path MTU Discovery", RFC 1191, + DECWRL, Stanford University, November 1990. + + [13] Deering, S., "ICMP Router Discovery Messages", RFC 1256, + Xerox PARC, September 1991. + + + + +Alexander & Droms Standards Track [Page 32] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + + [14] Leffler, S. and M. Karels, "Trailer Encapsulations", RFC 893, + U. C. Berkeley, April 1984. + + [15] Hornig, C., "Standard for the Transmission of IP Datagrams over + Ethernet Networks", RFC 894, Symbolics, April 1984. + + [16] Postel, J. and J. Reynolds, "Standard for the Transmission of + IP Datagrams Over IEEE 802 Networks", RFC 1042, USC/Information + Sciences Institute, February 1988. + + [17] Sun Microsystems, "System and Network Administration", March + 1990. + + [18] Mills, D., "Internet Time Synchronization: The Network Time + Protocol", RFC 1305, UDEL, March 1992. + + [19] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service + on a TCP/UDP transport: Concepts and Methods", STD 19, RFC 1001, + March 1987. + + [20] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service + on a TCP/UDP transport: Detailed Specifications", STD 19, RFC + 1002, March 1987. + + [21] Scheifler, R., "FYI On the X Window System", FYI 6, RFC 1198, + MIT Laboratory for Computer Science, January 1991. + + [22] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700, + USC/Information Sciences Institute, July 1992. + +13. Security Considerations + + Security issues are not discussed in this memo. + + + + + + + + + + + + + + + + + + +Alexander & Droms Standards Track [Page 33] + +RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 + + +14. Authors' Addresses + + Steve Alexander + Silicon Graphics, Inc. + 2011 N. Shoreline Boulevard + Mailstop 510 + Mountain View, CA 94043-1389 + + Phone: (415) 933-6172 + EMail: sca@engr.sgi.com + + + Ralph Droms + Bucknell University + Lewisburg, PA 17837 + + Phone: (717) 524-1145 + EMail: droms@bucknell.edu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Alexander & Droms Standards Track [Page 34] + diff --git a/usr.sbin/dhcp/doc/rfc951.txt b/usr.sbin/dhcp/doc/rfc951.txt new file mode 100644 index 00000000000..86cd69e63c5 --- /dev/null +++ b/usr.sbin/dhcp/doc/rfc951.txt @@ -0,0 +1,684 @@ + + +Network Working Group Bill Croft (Stanford University) +Request for Comments: 951 John Gilmore (Sun Microsystems) + September 1985 + + BOOTSTRAP PROTOCOL (BOOTP) + + +1. Status of this Memo + + This RFC suggests a proposed protocol for the ARPA-Internet + community, and requests discussion and suggestions for improvements. + Distribution of this memo is unlimited. + +2. Overview + + This RFC describes an IP/UDP bootstrap protocol (BOOTP) which allows + a diskless client machine to discover its own IP address, the address + of a server host, and the name of a file to be loaded into memory and + executed. The bootstrap operation can be thought of as consisting of + TWO PHASES. This RFC describes the first phase, which could be + labeled 'address determination and bootfile selection'. After this + address and filename information is obtained, control passes to the + second phase of the bootstrap where a file transfer occurs. The file + transfer will typically use the TFTP protocol [9], since it is + intended that both phases reside in PROM on the client. However + BOOTP could also work with other protocols such as SFTP [3] or + FTP [6]. + + We suggest that the client's PROM software provide a way to do a + complete bootstrap without 'user' interaction. This is the type of + boot that would occur during an unattended power-up. A mechanism + should be provided for the user to manually supply the necessary + address and filename information to bypass the BOOTP protocol and + enter the file transfer phase directly. If non-volatile storage is + available, we suggest keeping default settings there and bypassing + the BOOTP protocol unless these settings cause the file transfer + phase to fail. If the cached information fails, the bootstrap should + fall back to phase 1 and use BOOTP. + + Here is a brief outline of the protocol: + + 1. A single packet exchange is performed. Timeouts are used to + retransmit until a reply is received. The same packet field + layout is used in both directions. Fixed length fields of maximum + reasonable length are used to simplify structure definition and + parsing. + + 2. An 'opcode' field exists with two values. The client + broadcasts a 'bootrequest' packet. The server then answers with a + 'bootreply' packet. The bootrequest contains the client's + hardware address and its IP address, if known. + + +Croft & Gilmore [Page 1] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + 3. The request can optionally contain the name of the server the + client wishes to respond. This is so the client can force the + boot to occur from a specific host (e.g. if multiple versions of + the same bootfile exist or if the server is in a far distant + net/domain). The client does not have to deal with name / domain + services; instead this function is pushed off to the BOOTP server. + + 4. The request can optionally contain the 'generic' filename to be + booted. For example 'unix' or 'ethertip'. When the server sends + the bootreply, it replaces this field with the fully qualified + path name of the appropriate boot file. In determining this name, + the server may consult his own database correlating the client's + address and filename request, with a particular boot file + customized for that client. If the bootrequest filename is a null + string, then the server returns a filename field indicating the + 'default' file to be loaded for that client. + + 5. In the case of clients who do not know their IP addresses, the + server must also have a database relating hardware address to IP + address. This client IP address is then placed into a field in + the bootreply. + + 6. Certain network topologies (such as Stanford's) may be such + that a given physical cable does not have a TFTP server directly + attached to it (e.g. all the gateways and hosts on a certain cable + may be diskless). With the cooperation of neighboring gateways, + BOOTP can allow clients to boot off of servers several hops away, + through these gateways. See the section 'Booting Through + Gateways' below. This part of the protocol requires no special + action on the part of the client. Implementation is optional and + requires a small amount of additional code in gateways and + servers. + +3. Packet Format + + All numbers shown are decimal, unless indicated otherwise. The BOOTP + packet is enclosed in a standard IP [8] UDP [7] datagram. For + simplicity it is assumed that the BOOTP packet is never fragmented. + Any numeric fields shown are packed in 'standard network byte order', + i.e. high order bits are sent first. + + In the IP header of a bootrequest, the client fills in its own IP + source address if known, otherwise zero. When the server address is + unknown, the IP destination address will be the 'broadcast address' + 255.255.255.255. This address means 'broadcast on the local cable, + (I don't know my net number)' [4]. + + + +Croft & Gilmore [Page 2] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + The UDP header contains source and destination port numbers. The + BOOTP protocol uses two reserved port numbers, 'BOOTP client' (68) + and 'BOOTP server' (67). The client sends requests using 'BOOTP + server' as the destination port; this is usually a broadcast. The + server sends replies using 'BOOTP client' as the destination port; + depending on the kernel or driver facilities in the server, this may + or may not be a broadcast (this is explained further in the section + titled 'Chicken/Egg issues' below). The reason TWO reserved ports + are used, is to avoid 'waking up' and scheduling the BOOTP server + daemons, when a bootreply must be broadcast to a client. Since the + server and other hosts won't be listening on the 'BOOTP client' port, + any such incoming broadcasts will be filtered out at the kernel + level. We could not simply allow the client to pick a 'random' port + number for the UDP source port field; since the server reply may be + broadcast, a randomly chosen port number could confuse other hosts + that happened to be listening on that port. + + The UDP length field is set to the length of the UDP plus BOOTP + portions of the packet. The UDP checksum field can be set to zero by + the client (or server) if desired, to avoid this extra overhead in a + PROM implementation. In the 'Packet Processing' section below the + phrase '[UDP checksum.]' is used whenever the checksum might be + verified/computed. + + FIELD BYTES DESCRIPTION + ----- ----- ----------- + + op 1 packet op code / message type. + 1 = BOOTREQUEST, 2 = BOOTREPLY + + htype 1 hardware address type, + see ARP section in "Assigned Numbers" RFC. + '1' = 10mb ethernet + + hlen 1 hardware address length + (eg '6' for 10mb ethernet). + + hops 1 client sets to zero, + optionally used by gateways + in cross-gateway booting. + + xid 4 transaction ID, a random number, + used to match this boot request with the + responses it generates. + + secs 2 filled in by client, seconds elapsed since + client started trying to boot. + + +Croft & Gilmore [Page 3] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + -- 2 unused + + ciaddr 4 client IP address; + filled in by client in bootrequest if known. + + yiaddr 4 'your' (client) IP address; + filled by server if client doesn't + know its own address (ciaddr was 0). + + siaddr 4 server IP address; + returned in bootreply by server. + + giaddr 4 gateway IP address, + used in optional cross-gateway booting. + + chaddr 16 client hardware address, + filled in by client. + + sname 64 optional server host name, + null terminated string. + + file 128 boot file name, null terminated string; + 'generic' name or null in bootrequest, + fully qualified directory-path + name in bootreply. + + vend 64 optional vendor-specific area, + e.g. could be hardware type/serial on request, + or 'capability' / remote file system handle + on reply. This info may be set aside for use + by a third phase bootstrap or kernel. + +4. Chicken / Egg Issues + + How can the server send an IP datagram to the client, if the client + doesnt know its own IP address (yet)? Whenever a bootreply is being + sent, the transmitting machine performs the following operations: + + 1. If the client knows its own IP address ('ciaddr' field is + nonzero), then the IP can be sent 'as normal', since the client + will respond to ARPs [5]. + + 2. If the client does not yet know its IP address (ciaddr zero), + then the client cannot respond to ARPs sent by the transmitter of + the bootreply. There are two options: + + a. If the transmitter has the necessary kernel or driver hooks + + +Croft & Gilmore [Page 4] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + to 'manually' construct an ARP address cache entry, then it can + fill in an entry using the 'chaddr' and 'yiaddr' fields. Of + course, this entry should have a timeout on it, just like any + other entry made by the normal ARP code itself. The + transmitter of the bootreply can then simply send the bootreply + to the client's IP address. UNIX (4.2 BSD) has this + capability. + + b. If the transmitter lacks these kernel hooks, it can simply + send the bootreply to the IP broadcast address on the + appropriate interface. This is only one additional broadcast + over the previous case. + +5. Client Use of ARP + + The client PROM must contain a simple implementation of ARP, e.g. the + address cache could be just one entry in size. This will allow a + second-phase-only boot (TFTP) to be performed when the client knows + the IP addresses and bootfile name. + + Any time the client is expecting to receive a TFTP or BOOTP reply, it + should be prepared to answer an ARP request for its own IP to + hardware address mapping (if known). + + Since the bootreply will contain (in the hardware encapsulation) the + hardware source address of the server/gateway, the client MAY be able + to avoid sending an ARP request for the server/gateway IP address to + be used in the following TFTP phase. However this should be treated + only as a special case, since it is desirable to still allow a + second-phase-only boot as described above. + +6. Comparison to RARP + + An earlier protocol, Reverse Address Resolution Protocol (RARP) [1] + was proposed to allow a client to determine its IP address, given + that it knew its hardware address. However RARP had the disadvantage + that it was a hardware link level protocol (not IP/UDP based). This + means that RARP could only be implemented on hosts containing special + kernel or driver modifications to access these 'raw' packets. Since + there are many network kernels existent now, with each source + maintained by different organizations, a boot protocol that does not + require kernel modifications is a decided advantage. + + BOOTP provides this hardware to IP address lookup function, in + addition to the other useful features described in the sections + above. + + + +Croft & Gilmore [Page 5] + + + +RFC 951 September 1985 +Bootstrap Protocol + + +7. Packet Processing + + 7.1. Client Transmission + + Before setting up the packet for the first time, it is a good idea + to clear the entire packet buffer to all zeros; this will place + all fields in their default state. The client then creates a + packet with the following fields. + + The IP destination address is set to 255.255.255.255. (the + broadcast address) or to the server's IP address (if known). The + IP source address and 'ciaddr' are set to the client's IP address + if known, else 0. The UDP header is set with the proper length; + source port = 'BOOTP client' port destination port = 'BOOTP + server' port. + + 'op' is set to '1', BOOTREQUEST. 'htype' is set to the hardware + address type as assigned in the ARP section of the "Assigned + Numbers" RFC. 'hlen' is set to the length of the hardware address, + e.g. '6' for 10mb ethernet. + + 'xid' is set to a 'random' transaction id. 'secs' is set to the + number of seconds that have elapsed since the client has started + booting. This will let the servers know how long a client has + been trying. As the number gets larger, certain servers may feel + more 'sympathetic' towards a client they don't normally service. + If a client lacks a suitable clock, it could construct a rough + estimate using a loop timer. Or it could choose to simply send + this field as always a fixed value, say 100 seconds. + + If the client knows its IP address, 'ciaddr' (and the IP source + address) are set to this value. 'chaddr' is filled in with the + client's hardware address. + + If the client wishes to restrict booting to a particular server + name, it may place a null-terminated string in 'sname'. The name + used should be any of the allowable names or nicknames of the + desired host. + + The client has several options for filling the 'file' name field. + If left null, the meaning is 'I want to boot the default file for + my machine'. A null file name can also mean 'I am only interested + in finding out client/server/gateway IP addresses, I dont care + about file names'. + + The field can also be a 'generic' name such as 'unix' or + + + +Croft & Gilmore [Page 6] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + 'gateway'; this means 'boot the named program configured for my + machine'. Finally the field can be a fully directory qualified + path name. + + The 'vend' field can be filled in by the client with + vendor-specific strings or structures. For example the machine + hardware type or serial number may be placed here. However the + operation of the BOOTP server should not DEPEND on this + information existing. + + If the 'vend' field is used, it is recommended that a 4 byte + 'magic number' be the first item within 'vend'. This lets a + server determine what kind of information it is seeing in this + field. Numbers can be assigned by the usual 'magic number' + process --you pick one and it's magic. A different magic number + could be used for bootreply's than bootrequest's to allow the + client to take special action with the reply information. + + [UDP checksum.] + + 7.2. Client Retransmission Strategy + + If no reply is received for a certain length of time, the client + should retransmit the request. The time interval must be chosen + carefully so as not to flood the network. Consider the case of a + cable containing 100 machines that are just coming up after a + power failure. Simply retransmitting the request every four + seconds will inundate the net. + + As a possible strategy, you might consider backing off + exponentially, similar to the way ethernet backs off on a + collision. So for example if the first packet is at time 0:00, + the second would be at :04, then :08, then :16, then :32, then + :64. You should also randomize each time; this would be done + similar to the ethernet specification by starting with a mask and + 'and'ing that with with a random number to get the first backoff. + On each succeeding backoff, the mask is increased in length by one + bit. This doubles the average delay on each backoff. + + After the 'average' backoff reaches about 60 seconds, it should be + increased no further, but still randomized. + + Before each retransmission, the client should update the 'secs' + field. [UDP checksum.] + + + + + +Croft & Gilmore [Page 7] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + 7.3. Server Receives BOOTREQUEST + + [UDP checksum.] If the UDP destination port does not match the + 'BOOTP server' port, discard the packet. + + If the server name field (sname) is null (no particular server + specified), or sname is specified and matches our name or + nickname, then continue with packet processing. + + If the sname field is specified, but does not match 'us', then + there are several options: + + 1. You may choose to simply discard this packet. + + 2. If a name lookup on sname shows it to be on this same cable, + discard the packet. + + 3. If sname is on a different net, you may choose to forward + the packet to that address. If so, check the 'giaddr' (gateway + address) field. If 'giaddr' is zero, fill it in with my + address or the address of a gateway that can be used to get to + that net. Then forward the packet. + + If the client IP address (ciaddr) is zero, then the client does + not know its own IP address. Attempt to lookup the client + hardware address (chaddr, hlen, htype) in our database. If no + match is found, discard the packet. Otherwise we now have an IP + address for this client; fill it into the 'yiaddr' (your IP + address) field. + + We now check the boot file name field (file). The field will be + null if the client is not interested in filenames, or wants the + default bootfile. If the field is non-null, it is used as a + lookup key in a database, along with the client's IP address. If + there is a default file or generic file (possibly indexed by the + client address) or a fully-specified path name that matches, then + replace the 'file' field with the fully-specified path name of the + selected boot file. If the field is non-null and no match was + found, then the client is asking for a file we dont have; discard + the packet, perhaps some other BOOTP server will have it. + + The 'vend' vendor-specific data field should now be checked and if + a recognized type of data is provided, client-specific actions + should be taken, and a response placed in the 'vend' data field of + the reply packet. For example, a workstation client could provide + + + + +Croft & Gilmore [Page 8] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + an authentication key and receive from the server a capability for + remote file access, or a set of configuration options, which can + be passed to the operating system that will shortly be booted in. + + Place my (server) IP address in the 'siaddr' field. Set the 'op' + field to BOOTREPLY. The UDP destination port is set to 'BOOTP + client'. If the client address 'ciaddr' is nonzero, send the + packet there; else if the gateway address 'giaddr' is nonzero, set + the UDP destination port to 'BOOTP server' and send the packet to + 'giaddr'; else the client is on one of our cables but it doesnt + know its own IP address yet --use a method described in the 'Egg' + section above to send it to the client. If 'Egg' is used and we + have multiple interfaces on this host, use the 'yiaddr' (your IP + address) field to figure out which net (cable/interface) to send + the packet to. [UDP checksum.] + + 7.4. Server/Gateway Receives BOOTREPLY + + [UDP checksum.] If 'yiaddr' (your [the client's] IP address) + refers to one of our cables, use one of the 'Egg' methods above to + forward it to the client. Be sure to send it to the 'BOOTP + client' UDP destination port. + + 7.5. Client Reception + + Don't forget to process ARP requests for my own IP address (if I + know it). [UDP checksum.] The client should discard incoming + packets that: are not IP/UDPs addressed to the boot port; are not + BOOTREPLYs; do not match my IP address (if I know it) or my + hardware address; do not match my transaction id. Otherwise we + have received a successful reply. 'yiaddr' will contain my IP + address, if I didnt know it before. 'file' is the name of the + file name to TFTP 'read request'. The server address is in + 'siaddr'. If 'giaddr' (gateway address) is nonzero, then the + packets should be forwarded there first, in order to get to the + server. + +8. Booting Through Gateways + + This part of the protocol is optional and requires some additional + code in cooperating gateways and servers, but it allows cross-gateway + booting. This is mainly useful when gateways are diskless machines. + Gateways containing disks (e.g. a UNIX machine acting as a gateway), + might as well run their own BOOTP/TFTP servers. + + Gateways listening to broadcast BOOTREQUESTs may decide to forward or + rebroadcast these requests 'when appropriate'. For example, the + + +Croft & Gilmore [Page 9] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + gateway could have, as part of his configuration tables, a list of + other networks or hosts to receive a copy of any broadcast + BOOTREQUESTs. Even though a 'hops' field exists, it is a poor idea + to simply globally rebroadcast the requests, since broadcast loops + will almost certainly occur. + + The forwarding could begin immediately, or wait until the 'secs' + (seconds client has been trying) field passes a certain threshold. + + If a gateway does decide to forward the request, it should look at + the 'giaddr' (gateway IP address) field. If zero, it should plug its + own IP address (on the receiving cable) into this field. It may also + use the 'hops' field to optionally control how far the packet is + reforwarded. Hops should be incremented on each forwarding. For + example, if hops passes '3', the packet should probably be discarded. + [UDP checksum.] + + Here we have recommended placing this special forwarding function in + the gateways. But that does not have to be the case. As long as + some 'BOOTP forwarding agent' exists on the net with the booting + client, the agent can do the forwarding when appropriate. Thus this + service may or may not be co-located with the gateway. + + In the case of a forwarding agent not located in the gateway, the + agent could save himself some work by plugging the broadcast address + of the interface receiving the bootrequest into the 'giaddr' field. + Thus the reply would get forwarded using normal gateways, not + involving the forwarding agent. Of course the disadvantage here is + that you lose the ability to use the 'Egg' non-broadcast method of + sending the reply, causing extra overhead for every host on the + client cable. + +9. Sample BOOTP Server Database + + As a suggestion, we show a sample text file database that the BOOTP + server program might use. The database has two sections, delimited + by a line containing an percent in column 1. The first section + contains a 'default directory' and mappings from generic names to + directory/pathnames. The first generic name in this section is the + 'default file' you get when the bootrequest contains a null 'file' + string. + + The second section maps hardware addresstype/address into an + ipaddress. Optionally you can also overide the default generic name + by supplying a ipaddress specific genericname. A 'suffix' item is + also an option; if supplied, any generic names specified by the + client will be accessed by first appending 'suffix' to the 'pathname' + + +Croft & Gilmore [Page 10] + + + +RFC 951 September 1985 +Bootstrap Protocol + + + appropriate to that generic name. If that file is not found, then + the plain 'pathname' will be tried. This 'suffix' option allows a + whole set of custom generics to be setup without a lot of effort. + Below is shown the general format; fields are delimited by one or + more spaces or tabs; trailing empty fields may be omitted; blank + lines and lines beginning with '#' are ignored. + + # comment line + + homedirectory + genericname1 pathname1 + genericname2 pathname2 + ... + + % end of generic names, start of address mappings + + hostname1 hardwaretype hardwareaddr1 ipaddr1 genericname suffix + hostname2 hardwaretype hardwareaddr2 ipaddr2 genericname suffix + ... + + Here is a specific example. Note the 'hardwaretype' number is the + same as that shown in the ARP section of the 'Assigned Numbers' RFC. + The 'hardwaretype' and 'ipaddr' numbers are in decimal; + 'hardwareaddr' is in hex. + + # last updated by smith + + /usr/boot + vmunix vmunix + tip ethertip + watch /usr/diag/etherwatch + gate gate. + + % end of generic names, start of address mappings + + hamilton 1 02.60.8c.06.34.98 36.19.0.5 + burr 1 02.60.8c.34.11.78 36.44.0.12 + 101-gateway 1 02.60.8c.23.ab.35 36.44.0.32 gate 101 + mjh-gateway 1 02.60.8c.12.32.bc 36.42.0.64 gate mjh + welch-tipa 1 02.60.8c.22.65.32 36.47.0.14 tip + welch-tipb 1 02.60.8c.12.15.c8 36.46.0.12 tip + + In the example above, if 'mjh-gateway' does a default boot, it will + get the file '/usr/boot/gate.mjh'. + + + + + +Croft & Gilmore [Page 11] + + + +RFC 951 September 1985 +Bootstrap Protocol + + +10. Acknowledgements + + Ross Finlayson (et. al.) produced two earlier RFC's discussing TFTP + bootstraping [2] using RARP [1]. + + We would also like to acknowledge the previous work and comments of + Noel Chiappa, Bob Lyon, Jeff Mogul, Mark Lewis, and David Plummer. + +REFERENCES + + 1. Ross Finlayson, Timothy Mann, Jeffrey Mogul, Marvin Theimer. A + Reverse Address Resolution Protocol. RFC 903, NIC, June, 1984. + + 2. Ross Finlayson. Bootstrap Loading using TFTP. RFC 906, NIC, + June, 1984. + + 3. Mark Lottor. Simple File Transfer Protocol. RFC 913, NIC, + September, 1984. + + 4. Jeffrey Mogul. Broadcasting Internet Packets. RFC 919, NIC, + October, 1984. + + 5. David Plummer. An Ethernet Address Resolution Protocol. RFC + 826, NIC, September, 1982. + + 6. Jon Postel. File Transfer Protocol. RFC 765, NIC, June, 1980. + + 7. Jon Postel. User Datagram Protocol. RFC 768, NIC, August, 1980. + + 8. Jon Postel. Internet Protocol. RFC 791, NIC, September, 1981. + + 9. K. R. Sollins, Noel Chiappa. The TFTP Protocol. RFC 783, NIC, + June, 1981. + + + + + + + + + + + + + + + + +Croft & Gilmore [Page 12] + diff --git a/usr.sbin/dhcp/includes/arpa/nameser.h b/usr.sbin/dhcp/includes/arpa/nameser.h new file mode 100644 index 00000000000..5b38997aba0 --- /dev/null +++ b/usr.sbin/dhcp/includes/arpa/nameser.h @@ -0,0 +1,237 @@ +/* + * ++Copyright++ 1983, 1989, 1993 + * - + * Copyright (c) 1983, 1989, 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. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)nameser.h 8.1 (Berkeley) 6/2/93 + * $Id: nameser.h,v 8.3 1995/08/21 01:27:12 vixie Exp + */ + +#ifndef _NAMESER_H_ +#define _NAMESER_H_ + +/* + * Define constants based on rfc883 + */ +#define PACKETSZ 512 /* maximum packet size */ +#define MAXDNAME 256 /* maximum domain name */ +#define MAXCDNAME 255 /* maximum compressed domain name */ +#define MAXLABEL 63 /* maximum length of domain label */ +#define HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define INT32SZ 4 /* for systems without 32-bit ints */ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#define INADDRSZ 4 /* for sizeof(struct inaddr) != 4 */ + +/* + * Internet nameserver port number + */ +#define NAMESERVER_PORT 53 + +/* + * Currently defined opcodes + */ +#define QUERY 0x0 /* standard query */ +#define IQUERY 0x1 /* inverse query */ +#define STATUS 0x2 /* nameserver status query */ +/*#define xxx 0x3*/ /* 0x3 reserved */ +#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ +#ifdef ALLOW_UPDATES + /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */ +# define UPDATEA 0x9 /* add resource record */ +# define UPDATED 0xa /* delete a specific resource record */ +# define UPDATEDA 0xb /* delete all named resource record */ +# define UPDATEM 0xc /* modify a specific resource record */ +# define UPDATEMA 0xd /* modify all named resource record */ +# define ZONEINIT 0xe /* initial zone transfer */ +# define ZONEREF 0xf /* incremental zone referesh */ +#endif + +/* + * Currently defined response codes + */ +#define NOERROR 0 /* no error */ +#define FORMERR 1 /* format error */ +#define SERVFAIL 2 /* server failure */ +#define NXDOMAIN 3 /* non existent domain */ +#define NOTIMP 4 /* not implemented */ +#define REFUSED 5 /* query refused */ +#ifdef ALLOW_UPDATES + /* non standard */ +# define NOCHANGE 0xf /* update failed to change db */ +#endif + +/* + * Type values for resources and queries + */ +#define T_A 1 /* host address */ +#define T_NS 2 /* authoritative server */ +#define T_MD 3 /* mail destination */ +#define T_MF 4 /* mail forwarder */ +#define T_CNAME 5 /* canonical name */ +#define T_SOA 6 /* start of authority zone */ +#define T_MB 7 /* mailbox domain name */ +#define T_MG 8 /* mail group member */ +#define T_MR 9 /* mail rename name */ +#define T_NULL 10 /* null resource record */ +#define T_WKS 11 /* well known service */ +#define T_PTR 12 /* domain name pointer */ +#define T_HINFO 13 /* host information */ +#define T_MINFO 14 /* mailbox information */ +#define T_MX 15 /* mail routing information */ +#define T_TXT 16 /* text strings */ +#define T_RP 17 /* responsible person */ +#define T_AFSDB 18 /* AFS cell database */ +#define T_X25 19 /* X_25 calling address */ +#define T_ISDN 20 /* ISDN calling address */ +#define T_RT 21 /* router */ +#define T_NSAP 22 /* NSAP address */ +#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ +#define T_SIG 24 /* security signature */ +#define T_KEY 25 /* security key */ +#define T_PX 26 /* X.400 mail mapping */ +#define T_GPOS 27 /* geographical position (withdrawn) */ +#define T_AAAA 28 /* IP6 Address */ +#define T_LOC 29 /* Location Information */ + /* non standard */ +#define T_UINFO 100 /* user (finger) information */ +#define T_UID 101 /* user ID */ +#define T_GID 102 /* group ID */ +#define T_UNSPEC 103 /* Unspecified format (binary data) */ + /* Query type values which do not appear in resource records */ +#define T_AXFR 252 /* transfer zone of authority */ +#define T_MAILB 253 /* transfer mailbox records */ +#define T_MAILA 254 /* transfer mail agent records */ +#define T_ANY 255 /* wildcard match */ + +/* + * Values for class field + */ + +#define C_IN 1 /* the arpa internet */ +#define C_CHAOS 3 /* for chaos net (MIT) */ +#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ + /* Query class values which do not appear in resource records */ +#define C_ANY 255 /* wildcard match */ + +/* + * Status return codes for T_UNSPEC conversion routines + */ +#define CONV_SUCCESS 0 +#define CONV_OVERFLOW (-1) +#define CONV_BADFMT (-2) +#define CONV_BADCKSUM (-3) +#define CONV_BADBUFLEN (-4) + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned pr:1; /* primary server required (non standard) */ + unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned rcode :4; /* response code */ +#endif +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned pr:1; /* primary server required (non standard) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +/* + * Defines for handling compressed domain names + */ +#define INDIR_MASK 0xc0 + +/* + * Structure for passing resource records around. + */ +struct rrec { + int16_t r_zone; /* zone number */ + int16_t r_class; /* class number */ + int16_t r_type; /* type number */ + u_int32_t r_ttl; /* time to live */ + int r_size; /* size of data area */ + char *r_data; /* pointer to data */ +}; + +#endif /* !_NAMESER_H_ */ diff --git a/usr.sbin/dhcp/includes/cdefs.h b/usr.sbin/dhcp/includes/cdefs.h new file mode 100644 index 00000000000..2bc67a5251a --- /dev/null +++ b/usr.sbin/dhcp/includes/cdefs.h @@ -0,0 +1,57 @@ +/* cdefs.h + + Standard C definitions... */ + +/* + * Copyright (c) 1996 The Internet Software Consortium. + * All Rights Reserved. + * Copyright (c) 1995 RadioMail Corporation. 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 RadioMail Corporation, 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 RADIOMAIL CORPORATION, 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 RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon + * under a contract with Vixie Enterprises. Further modifications have + * been made for the Internet Software Consortium under a contract + * with Vixie Laboratories. + */ + +#if (defined (__GNUC__) || defined (__STDC__)) && !defined (BROKEN_ANSI) +#define PROTO(x) x +#define KandR(x) +#define ANSI_DECL(x) x +#if defined (__GNUC__) +#define INLINE inline +#else +#define INLINE +#endif /* __GNUC__ */ +#else +#define PROTO(x) () +#define KandR(x) x +#define ANSI_DECL(x) +#define INLINE +#endif /* __GNUC__ || __STDC__ */ diff --git a/usr.sbin/dhcp/includes/cf/alphaosf.h b/usr.sbin/dhcp/includes/cf/alphaosf.h new file mode 100644 index 00000000000..e8298ba3d14 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/alphaosf.h @@ -0,0 +1,104 @@ +/* alphaosf.h + + System dependencies for DEC Alpha/OSF1... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * 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 <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <malloc.h> +#include <unistd.h> +#include <setjmp.h> +#include <limits.h> + +#include <sys/wait.h> +#include <signal.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_dl.h> + +/* Varargs stuff... */ +#include <varargs.h> +#define VA_DOTDOTDOT va_alist +#define VA_start(list, last) va_start (list) + +#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" +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#include <sys/time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) + +/* The jmp_buf type is an array on OSF/1, so we can't dereference it + and must declare it differently. */ +#define jbp_decl(x) jmp_buf x +#define jref(x) (x) +#define jdref(x) (x) +#define jrefproto jmp_buf + +/* OSF/1 doesn't support limited sprintfs. */ +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +#define NEED_OSF_PFILT_HACKS +#define BPF_FORMAT "/dev/pf/pfilt%d" + +#if defined (USE_DEFAULT_NETWORK) +# define USE_BPF +#endif + +#define PTRSIZE_64BIT diff --git a/usr.sbin/dhcp/includes/cf/bsdos.h b/usr.sbin/dhcp/includes/cf/bsdos.h new file mode 100644 index 00000000000..7039c5b3035 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/bsdos.h @@ -0,0 +1,87 @@ +/* bsdos.h + + System dependencies for BSDI BSD/OS... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#include <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <unistd.h> +#include <setjmp.h> +#include <limits.h> + +#include <sys/wait.h> +#include <signal.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_dl.h> +#define INADDR_LOOPBACK ((u_int32_t)0x7f000001) + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define va_dcl +#define VA_start(list, last) va_start (list, last) + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/var/run/dhcpd.pid" +#endif +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "/var/db/dhcpd.leases" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" +#endif +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#include <sys/time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#define HAVE_SA_LEN + +#if defined (USE_DEFAULT_NETWORK) +# define USE_BPF +#endif diff --git a/usr.sbin/dhcp/includes/cf/cygwin32.h b/usr.sbin/dhcp/includes/cf/cygwin32.h new file mode 100644 index 00000000000..d9ccfaa6af0 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/cygwin32.h @@ -0,0 +1,123 @@ +/* cygwin32.h + + System dependencies for Win32, compiled with Cygwin32... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#include <sys/time.h> + +#define IN +#define OUT +#undef fd_set +#undef FD_SET +#undef FD_CLR +#undef FD_ZERO +#undef FD_ISSET +#undef FD_ISCLR +#undef FD_SETSIZE +#define IFNAMSIZ 16 +#include <winsock.h> + +#include <syslog.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <setjmp.h> +#include <limits.h> + +#include <sys/wait.h> +#include <signal.h> + +#define NO_H_ERRNO + +#include <sys/param.h> + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define va_dcl +#define VA_start(list, last) va_start (list, last) +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "//e/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "//e/etc/dhcpd.leases" +#endif +#ifndef _PATH_DHCPD_CONF +#define _PATH_DHCPD_CONF "//e/etc/dhcpd.conf" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "//e/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "//e/etc/dhclient.leases" +#endif +#ifndef _PATH_DHCLIENT_CONF +#define _PATH_DHCLIENT_CONF "//e/etc/dhclient.conf" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "//e/etc/dhcrelay.pid" +#endif + +#ifndef _PATH_RESOLV_CONF +#define _PATH_RESOLV_CONF "//e/etc/resolv.conf" +#endif + +#define int8_t char +#define int16_t short +#define int32_t long + +#define u_int8_t unsigned char /* Not quite POSIX... */ +#define u_int16_t unsigned short +#define u_int32_t unsigned long + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#if defined (USE_DEFAULT_NETWORK) +# define USE_SOCKETS +#endif + +#ifdef __alpha__ +#define PTRSIZE_64BIT +#endif diff --git a/usr.sbin/dhcp/includes/cf/freebsd.h b/usr.sbin/dhcp/includes/cf/freebsd.h new file mode 100644 index 00000000000..965d33236f2 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/freebsd.h @@ -0,0 +1,89 @@ +/* freebsd.h + + System dependencies for FreeBSD... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#define _ANSI_SOURCE + +#include <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <unistd.h> +#include <setjmp.h> +#include <limits.h> + +#include <sys/wait.h> +#include <signal.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_dl.h> +#define INADDR_LOOPBACK ((u_int32_t)0x7f000001) + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define va_dcl +#define VA_start(list, last) va_start (list, last) + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/var/run/dhcpd.pid" +#endif +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "/var/db/dhcpd.leases" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" +#endif +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#include <sys/time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#define HAVE_SA_LEN + +#if defined (USE_DEFAULT_NETWORK) +# define USE_BPF +#endif diff --git a/usr.sbin/dhcp/includes/cf/hpux.h b/usr.sbin/dhcp/includes/cf/hpux.h new file mode 100644 index 00000000000..7271931fa6d --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/hpux.h @@ -0,0 +1,84 @@ +/* hpux.h */ +/* + * 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 + * 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. + * + */ + +#define int8_t char +#define int16_t short +#define int32_t long + +#define u_int8_t unsigned char +#define u_int16_t unsigned short +#define u_int32_t unsigned long + +#include <sys/types.h> + +#include <syslog.h> + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_arp.h> + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +#include <varargs.h> +#define VA_DOTDOTDOT va_alist +#define VA_start(list, last) va_start (list) + +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +#define USE_SOCKETS 1 +#define EOL '\n' +#define VOIDPTR void * + +#include <time.h> + +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#define random rand diff --git a/usr.sbin/dhcp/includes/cf/linux.h b/usr.sbin/dhcp/includes/cf/linux.h new file mode 100644 index 00000000000..4386a7e2ff8 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/linux.h @@ -0,0 +1,111 @@ +/* linux.h + + System dependencies for Linux. + + Based on a configuration originally supplied by Jonathan Stone. */ + +/* + * 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 + * 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. + */ + +#include <features.h> +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +#undef __USE_BSD +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned long u_int32_t; +#endif /* __BIT_TYPES_DEFINED__ */ + +#include <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/route.h> + +#if defined (LINUX_1_X) +# include <linux/if_arp.h> +# include <linux/time.h> /* also necessary */ +#else +# include <net/if_arp.h> +#endif + +#include <sys/time.h> /* 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" +#endif +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" +#endif + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl + +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +#define VOIDPTR void * + +#define EOL '\n' + +/* Time stuff... */ + +#include <time.h> + +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#if defined (USE_DEFAULT_NETWORK) +# define USE_SOCKETS +# define IGNORE_HOSTUNREACH +#endif + +#define ALIAS_NAMES_PERMUTED +#define SKIP_DUMMY_INTERFACES diff --git a/usr.sbin/dhcp/includes/cf/netbsd.h b/usr.sbin/dhcp/includes/cf/netbsd.h new file mode 100644 index 00000000000..14aa77f839f --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/netbsd.h @@ -0,0 +1,96 @@ +/* netbsd.h + + System dependencies for NetBSD... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#include <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <malloc.h> +#include <unistd.h> +#include <setjmp.h> +#include <limits.h> + +#include <sys/wait.h> +#include <signal.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/route.h> +#include <sys/sockio.h> + +#define ifr_netmask ifr_addr + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define va_dcl +#define VA_start(list, last) va_start (list, last) + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/var/run/dhcpd.pid" +#endif +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "/var/db/dhcpd.leases" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" +#endif +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#include <sys/time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#define HAVE_SA_LEN +#define HAVE_MKSTEMP + +#if defined (USE_DEFAULT_NETWORK) +# define USE_BPF +#endif + +#ifdef __alpha__ +#define PTRSIZE_64BIT +#endif diff --git a/usr.sbin/dhcp/includes/cf/nextstep.h b/usr.sbin/dhcp/includes/cf/nextstep.h new file mode 100644 index 00000000000..c1e88e1d205 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/nextstep.h @@ -0,0 +1,109 @@ +/* sample.h + System dependencies for NEXTSTEP 3 & 4 (tested on 4.2PR2)... */ +/* + * 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 + * 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. + * + */ +/* NeXT needs BSD44 ssize_t */ +typedef int ssize_t; +/* NeXT doesn't have BSD setsid() */ +#define setsid getpid +#import <sys/types.h> +/* Porting:: + The jmp_buf type as declared in <setjmp.h> is sometimes a structure + and sometimes an array. By default, we assume it's a structure. + If it's an array on your system, you may get compile warnings or errors + as a result in confpars.c. If so, try including the following definitions, + which treat jmp_buf as an array: */ +#if 0 +#define jbp_decl(x) jmp_buf x +#define jref(x) (x) +#define jdref(x) (x) +#define jrefproto jmp_buf +#endif +#import <syslog.h> +#import <string.h> +#import <errno.h> +#import <unistd.h> +#import <sys/wait.h> +#import <signal.h> +#import <setjmp.h> +#import <limits.h> +extern int h_errno; +#import <net/if.h> +#import <net/if_arp.h> +/* Porting:: + Some older systems do not have defines for IP type-of-service, + or don't define them the way we expect. If you get undefined + symbol errors on the following symbols, they probably need to be + defined here. */ +#if 0 +#define IPTOS_LOWDELAY 0x10 +#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" +/* Stdarg definitions for ANSI-compliant C compilers. */ +#import <stdarg.h> +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl +/* NeXT lacks snprintf */ +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF +/* Porting:: + You must define the default network API for your port. This + will depend on whether one of the existing APIs will work for + you, or whether you need to implement support for a new API. + Currently, the following APIs are supported: + The BSD socket API: define USE_SOCKETS. + The Berkeley Packet Filter: define USE_BPF. + The Streams Network Interface Tap (NIT): define USE_NIT. + Raw sockets: define USE_RAW_SOCKETS + If your system supports the BSD socket API and doesn't provide + one of the supported interfaces to the physical packet layer, + you can either provide support for the low-level API that your + system does support (if any) or just use the BSD socket interface. + The BSD socket interface doesn't support multiple network interfaces, + and on many systems, it does not support the all-ones broadcast + address, which can cause problems with some DHCP clients (e.g. + Microsoft Windows 95). */ +#define USE_BPF +#if 0 +#if defined (USE_DEFAULT_NETWORK) +# define USE_SOCKETS +#endif +#endif +#define EOL '\n' +#define VOIDPTR void * +#import <time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) diff --git a/usr.sbin/dhcp/includes/cf/openbsd.h b/usr.sbin/dhcp/includes/cf/openbsd.h new file mode 100644 index 00000000000..a70d4b6f063 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/openbsd.h @@ -0,0 +1,96 @@ +/* OpenBSD.h + + System dependencies for OpenBSD... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#include <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <setjmp.h> +#include <limits.h> + +#include <sys/wait.h> +#include <signal.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/route.h> +#include <sys/sockio.h> + +#define ifr_netmask ifr_addr + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define va_dcl +#define VA_start(list, last) va_start (list, last) + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/var/run/dhcpd.pid" +#endif +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "/var/db/dhcpd.leases" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" +#endif +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#include <sys/time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#define HAVE_SA_LEN +#define HAVE_MKSTEMP + +#if defined (USE_DEFAULT_NETWORK) +# define USE_BPF +#endif + +#ifdef __alpha__ +#define PTRSIZE_64BIT +#endif diff --git a/usr.sbin/dhcp/includes/cf/qnx.h b/usr.sbin/dhcp/includes/cf/qnx.h new file mode 100644 index 00000000000..0e78582dc44 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/qnx.h @@ -0,0 +1,112 @@ +/* qnx.h + + System dependencies for QNX... +*/ + +/* + * 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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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 + * RADIOMAIL CORPORATION 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Labs. + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <setjmp.h> +#include <limits.h> +#include <syslog.h> +#include <sys/select.h> + +#include <sys/wait.h> +#include <signal.h> + +#include <netdb.h> +extern int h_errno; + +#include <net/if.h> +#define INADDR_LOOPBACK ((u_long)0x7f000001) + +/* Varargs stuff... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define va_dcl +#define VA_start(list, last) va_start (list, last) + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ +#include <sys/time.h> +#define TIME time_t +#define GET_TIME(x) time ((x)) +#define TIME_DIFF(high, low) (*(high) - *(low)) +#define SET_TIME(x, y) (*(x) = (y)) +#define ADD_TIME(d, s1, s2) (*(d) = *(s1) + *(s2)) +#define SET_MAX_TIME(x) (*(x) = INT_MAX) + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned long u_int32_t; +typedef signed short int16_t; +typedef signed long int32_t; + +#define strcasecmp( s1, s2 ) stricmp( s1, s2 ) +#define strncasecmp( s1, s2, n ) strnicmp( s1, s2, n ) +#define vsnprintf( buf, size, fmt, list ) vsprintf( buf, fbuf, list ) +#define random() rand() + +#define HAVE_SA_LEN +#define BROKEN_TM_GMT +#define USE_SOCKETS +#define NO_SNPRINTF +#undef AF_LINK + +/* + 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 + the daemon: + + route add -interface 255.255.255.0 <hostname> + + where <hostname> is replaced by the hostname or IP number of the + machine that dhcpd is running on. +*/ diff --git a/usr.sbin/dhcp/includes/cf/sample.h b/usr.sbin/dhcp/includes/cf/sample.h new file mode 100644 index 00000000000..892303b977e --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/sample.h @@ -0,0 +1,298 @@ +/* sample.h + + Sample config file for clients. + + This file is provided as a sample in case the system you want to run + on is not currently supported. If that is the case, follow the Porting:: + comments here and in other files as guides for what to change. */ + +/* + * 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 + * 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. + * + */ + +/* Porting:: + + Some systems do not define basic integer types as shown below. + On some systems, you need to include <bitypes.h> or <sys/bitypes.h>. + If you get parse errors in dhcpd.h while compiling dhcpd.conf, try + including bitypes.h, and if that fails, use the hard-coded definitions + shown below. */ + +#if 0 +#include <sys/bitypes.h> +#endif + +#if 0 +#define int8_t char +#define int16_t short +#define int32_t long + +#define u_int8_t unsigned char +#define u_int16_t unsigned short +#define u_int32_t unsigned long +#endif + +#include <sys/types.h> + +/* Porting:: + + The jmp_buf type as declared in <setjmp.h> is sometimes a structure + and sometimes an array. By default, we assume it's a structure. + If it's an array on your system, you may get compile warnings or errors + as a result in confpars.c. If so, try including the following definitions, + which treat jmp_buf as an array: */ + +#if 0 +#define jbp_decl(x) jmp_buf x +#define jref(x) (x) +#define jdref(x) (x) +#define jrefproto jmp_buf +#endif + +/* Porting:: + + Some older systems (e.g., Ultrix) still use the 4.2BSD-style syslog + API. These differ from later versions of the syslog API in that the + openlog system call takes two arguments instead of three, and the + facility code (the third argument to modern versions of openlog()) + is ORed into the log priority in the syslog() call. + + If you are running with the 4.2BSD-style syslog interface, define + SYSLOG_4_2. */ + +/* #define SYSLOG_4_2 */ + +#include <syslog.h> + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_arp.h> + +/* Porting:: + + Some older systems do not have defines for IP type-of-service, + or don't define them the way we expect. If you get undefined + symbol errors on the following symbols, they probably need to be + defined here. */ + +#if 0 +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#endif + +/* Porting:: + + Newer BSD derivatives store non-permanent daemon files in a + directory called /var/run. If your system has a /var/run, + use it; otherwise, use /etc. */ + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +/* Porting:: + + If your system supports standard ANSI C, it should provide the file + /usr/include/stdarg.h. This contains the ANSI standard declarations + for functions which take a variable number of arguments. + + Older systems with non-ANSI compilers cannot support this interface, + and generally use the older varargs interface, defined in <varargs.h>. + Some systems only support varargs, but define the interface in + <stdarg.h> anyway. + + You must choose one of the two sets of definitions below. Try + stdarg.h first, unless you know it won't work. If you have + trouble compiling errwarn.c, try switching to the varargs.h definitions. + If that fails, try using stdarg.h with the varargs definitions. */ + +#if 0 +/* Stdarg definitions for ANSI-compliant C compilers. */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl +#endif + +#if 0 +/* Varargs definitions, for non-ANSI-compliant C compilers. */ +#include <varargs.h> +#define VA_DOTDOTDOT va_alist +#define VA_start(list, last) va_start (list) +#endif + +/* Porting:: + + Some systems (notably 4.4BSD derivatives) support versions of the + sprintf functions which will deposit a limited number of characters + into the buffer; that limit is provided in an extra argument. + If your system doesn't support this functionality, you must include + the definitions below: */ + +#if 0 +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF +#endif + +/* Porting:: + + Some systems provide a function, strerror(), which takes the unix + error number (see errno) and returns a pointer to a static buffer + containing the corresponding error message. + + If your system doesn't provide strerror(), define NO_STRERROR + as shown below: */ + +#if 0 +#define NO_STRERROR +char *strerror PROTO ((int)); +#endif + +/* Porting:: + + Once dhcpd has initialized itself, it loops forever waiting for + packets to come in. Since we need to support multiple input streams + in order to support multiple interfaces, dhcpd needs to be able to + do a syscall to determine which descriptors have input waiting on + them. + + Normally, dhcpd uses the select() system call, which is a 4.2BSD + syscall invented precisely for this purpose. Unfortunately, some + System V-based systems do not support select() properly when it + operates on streams. The System V interface which does (largely) + the same thing as select is called poll(). In some cases, this may + work better than select() - if you find that dhcpd is hanging and not + responding to packets very consistently, you might try defining + USE_POLL and including <poll.h>. */ + +#if 0 +#define USE_POLL +#include <poll.h> +#endif + +/* Porting:: + + You must define the default network API for your port. This + will depend on whether one of the existing APIs will work for + you, or whether you need to implement support for a new API. + Currently, the following APIs are supported: + + The BSD socket API: define USE_SOCKETS. + The Berkeley Packet Filter: define USE_BPF. + The Streams Network Interface Tap (NIT): define USE_NIT. + Raw sockets: define USE_RAW_SOCKETS + + If your system supports the BSD socket API and doesn't provide + one of the supported interfaces to the physical packet layer, + you can either provide support for the low-level API that your + system does support (if any) or just use the BSD socket interface. + The BSD socket interface doesn't support multiple network interfaces, + and on many systems, it does not support the all-ones broadcast + address, which can cause problems with some DHCP clients (e.g. + Microsoft Windows 95). */ + +#if defined (USE_DEFAULT_NETWORK) +# define USE_SOCKETS +#endif + +/* Porting:: + + Recent versions of BSD added a new element to the sockaddr structure: + sa_len. This indicates the length of the structure, and is used + in a variety of places, not the least of which is the SIOCGIFCONF + ioctl, which is used to figure out what interfaces are attached to + the system. + + You should be able to determine if your system has an sa_len element + by looking at the struct sockaddr definition in /usr/include/sys/socket.h. + If it does, you must define HAVE_SA_LEN. Otherwise, you must not. + The most obvious symptom that you've got this wrong is either a compile + error complaining about the use of the sa_len structure element, or + the failure of dhcpd to find any interfaces. */ + +/* #define HAVE_SA_LEN */ + +/* 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 + 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. */ + +#define EOL '\n' + +/* Some older C compilers don't support the void pointer type. + ANSI C defines void * to be a pointer type that matches + any other pointer type. This is handy for returning a pointer + which will always need to be cast to a different value. For + example, malloc() on an ANSI C-compliant system returns void *. + + If your compiler doesn't support void pointers, you may need to + define VOIDPTR to be char *; otherwise, define it to be void *. */ + +#define VOIDPTR void * + +/* Porting:: + + The following definitions for time should work on any unix machine. + They may not work (or at least, may not work well) on a variety of + non-unix machines. If you are porting to a non-unix machine, you + probably need to change the definitions below and perhaps include + different headers. + + I should note that dhcpd is not yet entirely clean of unix-specific + time references, so the list of defines shown below probably isn't + good enough if you're porting to a system that really doesn't support + unix time. It's probably a reasonable place to start, though. */ + +#include <time.h> + +#define TIME time_t +#define GET_TIME(x) time ((x)) diff --git a/usr.sbin/dhcp/includes/cf/sco.h b/usr.sbin/dhcp/includes/cf/sco.h new file mode 100644 index 00000000000..e8be0903761 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/sco.h @@ -0,0 +1,118 @@ +/* sco.h + + System dependencies for SCO ODT 3.0... + + Based on changes contributed by Gerald Rosenberg. */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#include <syslog.h> +#include <sys/types.h> + +/* Basic Integer Types not defined in SCO headers... */ + +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned long u_int32_t; + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_arp.h> + +/* XXX dunno if this is required for SCO... */ +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +/* IPTOS_LOWCOST 0x02 XXX */ + +/* SCO doesn't have /var/run. */ +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +#define INADDR_LOOPBACK ((u_int32_t)0x7f000001) + +/* Varargs stuff: use stdarg.h instead ... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl + +/* SCO doesn't support limited sprintfs. */ +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +/* 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 +#endif + +#define EOL '\n' +#define VOIDPTR void * + +/* + * Time stuff... + * + * Definitions for an ISC DHCPD system that uses time_t + * to represent time internally as opposed to, for example, struct timeval.) + */ + +#include <time.h> + +#define TIME time_t +#define GET_TIME(x) time ((x)) diff --git a/usr.sbin/dhcp/includes/cf/sunos4.h b/usr.sbin/dhcp/includes/cf/sunos4.h new file mode 100644 index 00000000000..55d98e4d7d4 --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/sunos4.h @@ -0,0 +1,141 @@ +/* sunos4.h + + System dependencies for SunOS 4 (tested on 4.1.4)... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +/* Basic Integer Types not defined in SunOS headers... */ + +#define int8_t char +#define int16_t short +#define int32_t int + +#define u_int8_t unsigned char +#define u_int16_t unsigned short +#define u_int32_t unsigned int + +#define ssize_t int + +/* No endian.h either. */ +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define BYTE_ORDER BIG_ENDIAN + +/* The jmp_buf type is an array on SunOS, so we can't dereference it + and must declare it differently. */ +#define jbp_decl(x) jmp_buf x +#define jref(x) (x) +#define jdref(x) (x) +#define jrefproto jmp_buf + +#include <syslog.h> +#include <sys/types.h> + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> +#include <poll.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_arp.h> + +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +/* IPTOS_LOWCOST 0x02 XXX */ + +/* SunOS systems don't have /var/run, but some sites have added it. + If you want to put dhcpd.pid in /var/run, define _PATH_DHCPD_PID + in site.h. */ +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +#ifdef __GNUC__ +/* Varargs stuff: use stdarg.h instead ... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl +#else /* !__GNUC__*/ +/* Varargs stuff... */ +#include <varargs.h> +#define VA_DOTDOTDOT va_alist +#define VA_start(list, last) va_start (list) +#endif /* !__GNUC__*/ + +/* SunOS doesn't support limited sprintfs. */ +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +/* SunOS doesn't supply strerror... */ +#define NO_STRERROR +char *strerror PROTO ((int)); + +#define NEED_INET_ATON + +/* By default, use NIT API for receiving and sending packets... */ +#if defined (USE_DEFAULT_NETWORK) +# define USE_NIT +#endif + +#define EOL '\n' +#define VOIDPTR void * + +#include <time.h> +#include <sys/time.h> + +#define TIME time_t +#define GET_TIME(x) time ((x)) diff --git a/usr.sbin/dhcp/includes/cf/sunos5-5.h b/usr.sbin/dhcp/includes/cf/sunos5-5.h new file mode 100644 index 00000000000..f88084f6d9e --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/sunos5-5.h @@ -0,0 +1,154 @@ +/* sunos5-5.h + + System dependencies for Solaris 2.x (tested on 2.5 with gcc)... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +/* Basic Integer Types not defined in SunOS headers... */ + +#define int8_t char +#define int16_t short +#define int32_t long + +#define u_int8_t unsigned char +#define u_int16_t unsigned short +#define u_int32_t unsigned long + +/* The jmp_buf type is an array on Solaris, so we can't dereference it + and must declare it differently. */ + +#define jbp_decl(x) jmp_buf x +#define jref(x) (x) +#define jdref(x) (x) +#define jrefproto jmp_buf + +#include <syslog.h> +#include <sys/types.h> +#include <sys/sockio.h> + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> + +extern int h_errno; + +#include <net/if.h> +#include <net/if_arp.h> + +/* Solaris 2.6 defines AF_LINK, so we need the rest of the baggage that + comes with it, but of course Solaris 2.5 and previous do not. */ +#if defined (AF_LINK) +#include <net/if_dl.h> +#endif + +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +/* IPTOS_LOWCOST 0x02 XXX */ + +/* Solaris systems don't have /var/run, but some sites have added it. + If you want to put dhcpd.pid in /var/run, define _PATH_DHCPD_PID + in site.h. */ +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +#if defined (__GNUC__) || defined (__SVR4) +/* Varargs stuff: use stdarg.h instead ... */ +#include <stdarg.h> +#define VA_DOTDOTDOT ... +#define VA_start(list, last) va_start (list, last) +#define va_dcl +#else /* !__GNUC__*/ +/* Varargs stuff... */ +#include <varargs.h> +#define VA_DOTDOTDOT va_alist +#define VA_start(list, last) va_start (list) +#endif /* !__GNUC__*/ + +/* Solaris doesn't support limited sprintfs. */ +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +#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 +#endif + +#define USE_POLL + +#define EOL '\n' +#define VOIDPTR void * + +/* Time stuff... */ + +#include <time.h> + +#define TIME time_t +#define GET_TIME(x) time ((x)) + +#define random() rand() + +/* Solaris doesn't provide an endian.h, so we have to do it. */ + +#define BIG_ENDIAN 1 +#define LITTLE_ENDIAN 2 +#if defined (__i386) || defined (i386) +# define BYTE_ORDER LITTLE_ENDIAN +#else +# if defined (__sparc) || defined (sparc) +# define BYTE_ORDER BIG_ENDIAN +# else +@@@ ERROR @@@ Unable to determine byte order! +# endif +#endif + +#define ALIAS_NAMES_PERMUTED diff --git a/usr.sbin/dhcp/includes/cf/ultrix.h b/usr.sbin/dhcp/includes/cf/ultrix.h new file mode 100644 index 00000000000..da7c35c6c1a --- /dev/null +++ b/usr.sbin/dhcp/includes/cf/ultrix.h @@ -0,0 +1,112 @@ +/* ultrix.h + + System dependencies for Ultrix 4.2 (tested on 4.2a+multicast)... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +/* Ultrix uses the old 4.2BSD-style syslog(). */ +#include <sys/syslog.h> +#define SYSLOG_4_2 + +#include <sys/types.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <setjmp.h> +#include <limits.h> + +extern int h_errno; + +#include <net/if.h> + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/etc/dhcpd.pid" +#endif +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/etc/dhclient.pid" +#endif +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/etc/dhcrelay.pid" +#endif + +#define int8_t char +#define int16_t short +#define int32_t long + +#define u_int8_t unsigned char /* Not quite POSIX... */ +#define u_int16_t unsigned short +#define u_int32_t unsigned long + +/* 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 +#define jref(x) (x) +#define jdref(x) (x) +#define jrefproto jmp_buf + +#define IPTOS_LOWDELAY 0x10 +/* IPTOS_LOWCOST 0x02 XXX */ + +/* Varargs stuff... */ +#include <varargs.h> +#define VA_DOTDOTDOT va_alist +#define VA_start(list, last) va_start (list) +#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list) +#define NO_SNPRINTF + +#define INADDR_LOOPBACK ((u_int32_t)0x7f000001) +#define EOL '\n' +#define VOIDPTR void * + +/* + * Time stuff... + * + * Definitions for an ISC DHCPD system that uses time_t + * to represent time internally as opposed to, for example, struct timeval.) + */ + +#define TIME time_t +#define GET_TIME(x) time ((x)) + +/* Ultrix doesn't provide an endian.h, but it only runs on little-endian + machines, so we'll just hack around the issue. */ +#define BIG_ENDIAN 1 +#define LITTLE_ENDIAN 2 +#define BYTE_ORDER LITTLE_ENDIAN + +#if defined (USE_DEFAULT_NETWORK) +# define USE_UPF +#endif diff --git a/usr.sbin/dhcp/includes/dhcp.h b/usr.sbin/dhcp/includes/dhcp.h new file mode 100644 index 00000000000..18127757952 --- /dev/null +++ b/usr.sbin/dhcp/includes/dhcp.h @@ -0,0 +1,167 @@ +/* dhcp.h + + Protocol structures... */ + +/* + * 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 <mellon@fugue.com> 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''. + */ + +#define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \ + 20 + /* IP header */ \ + 8) /* UDP header */ +#define DHCP_SNAME_LEN 64 +#define DHCP_FILE_LEN 128 +#define DHCP_FIXED_NON_UDP 236 +#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD) + /* Everything but options. */ +#define DHCP_MTU_MAX 1500 +#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN) + +#define BOOTP_MIN_LEN 300 +#define DHCP_MIN_LEN 548 + +struct dhcp_packet { + u_int8_t op; /* Message opcode/type */ + u_int8_t htype; /* Hardware addr type (see net/if_types.h) */ + u_int8_t hlen; /* Hardware addr length */ + u_int8_t hops; /* Number of relay agent hops from client */ + u_int32_t xid; /* Transaction ID */ + u_int16_t secs; /* Seconds since client started looking */ + u_int16_t flags; /* Flag bits */ + struct in_addr ciaddr; /* Client IP address (if already in use) */ + struct in_addr yiaddr; /* Client IP address */ + struct in_addr siaddr; /* IP address of next server to talk to */ + struct in_addr giaddr; /* DHCP relay agent IP address */ + unsigned char chaddr [16]; /* Client hardware address */ + char sname [DHCP_SNAME_LEN]; /* Server name */ + char file [DHCP_FILE_LEN]; /* Boot filename */ + unsigned char options [DHCP_OPTION_LEN]; + /* Optional parameters + (actual length dependent on MTU). */ +}; + +/* BOOTP (rfc951) message types */ +#define BOOTREQUEST 1 +#define BOOTREPLY 2 + +/* Possible values for flags field... */ +#define BOOTP_BROADCAST 32768L + +/* Possible values for hardware type (htype) field... */ +#define HTYPE_ETHER 1 /* Ethernet 10Mbps */ +#define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */ + +/* Magic cookie validating dhcp options field (and bootp vendor + extensions field). */ +#define DHCP_OPTIONS_COOKIE "\143\202\123\143" + +/* DHCP Option codes: */ + +#define DHO_PAD 0 +#define DHO_SUBNET_MASK 1 +#define DHO_TIME_OFFSET 2 +#define DHO_ROUTERS 3 +#define DHO_TIME_SERVERS 4 +#define DHO_NAME_SERVERS 5 +#define DHO_DOMAIN_NAME_SERVERS 6 +#define DHO_LOG_SERVERS 7 +#define DHO_COOKIE_SERVERS 8 +#define DHO_LPR_SERVERS 9 +#define DHO_IMPRESS_SERVERS 10 +#define DHO_RESOURCE_LOCATION_SERVERS 11 +#define DHO_HOST_NAME 12 +#define DHO_BOOT_SIZE 13 +#define DHO_MERIT_DUMP 14 +#define DHO_DOMAIN_NAME 15 +#define DHO_SWAP_SERVER 16 +#define DHO_ROOT_PATH 17 +#define DHO_EXTENSIONS_PATH 18 +#define DHO_IP_FORWARDING 19 +#define DHO_NON_LOCAL_SOURCE_ROUTING 20 +#define DHO_POLICY_FILTER 21 +#define DHO_MAX_DGRAM_REASSEMBLY 22 +#define DHO_DEFAULT_IP_TTL 23 +#define DHO_PATH_MTU_AGING_TIMEOUT 24 +#define DHO_PATH_MTU_PLATEAU_TABLE 25 +#define DHO_INTERFACE_MTU 26 +#define DHO_ALL_SUBNETS_LOCAL 27 +#define DHO_BROADCAST_ADDRESS 28 +#define DHO_PERFORM_MASK_DISCOVERY 29 +#define DHO_MASK_SUPPLIER 30 +#define DHO_ROUTER_DISCOVERY 31 +#define DHO_ROUTER_SOLICITATION_ADDRESS 32 +#define DHO_STATIC_ROUTES 33 +#define DHO_TRAILER_ENCAPSULATION 34 +#define DHO_ARP_CACHE_TIMEOUT 35 +#define DHO_IEEE802_3_ENCAPSULATION 36 +#define DHO_DEFAULT_TCP_TTL 37 +#define DHO_TCP_KEEPALIVE_INTERVAL 38 +#define DHO_TCP_KEEPALIVE_GARBAGE 39 +#define DHO_NIS_DOMAIN 40 +#define DHO_NIS_SERVERS 41 +#define DHO_NTP_SERVERS 42 +#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43 +#define DHO_NETBIOS_NAME_SERVERS 44 +#define DHO_NETBIOS_DD_SERVER 45 +#define DHO_NETBIOS_NODE_TYPE 46 +#define DHO_NETBIOS_SCOPE 47 +#define DHO_FONT_SERVERS 48 +#define DHO_X_DISPLAY_MANAGER 49 +#define DHO_DHCP_REQUESTED_ADDRESS 50 +#define DHO_DHCP_LEASE_TIME 51 +#define DHO_DHCP_OPTION_OVERLOAD 52 +#define DHO_DHCP_MESSAGE_TYPE 53 +#define DHO_DHCP_SERVER_IDENTIFIER 54 +#define DHO_DHCP_PARAMETER_REQUEST_LIST 55 +#define DHO_DHCP_MESSAGE 56 +#define DHO_DHCP_MAX_MESSAGE_SIZE 57 +#define DHO_DHCP_RENEWAL_TIME 58 +#define DHO_DHCP_REBINDING_TIME 59 +#define DHO_DHCP_CLASS_IDENTIFIER 60 +#define DHO_DHCP_CLIENT_IDENTIFIER 61 +#define DHO_DHCP_USER_CLASS_ID 77 +#define DHO_END 255 + +/* DHCP message types. */ +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 +#define DHCPINFORM 8 diff --git a/usr.sbin/dhcp/includes/dhcpd.h b/usr.sbin/dhcp/includes/dhcpd.h new file mode 100644 index 00000000000..e9ea614e594 --- /dev/null +++ b/usr.sbin/dhcp/includes/dhcpd.h @@ -0,0 +1,945 @@ +/* dhcpd.h + + Definitions for dhcpd... */ + +/* + * 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 <mellon@fugue.com> 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 __CYGWIN32__ +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <arpa/inet.h> +#include <netdb.h> +#else +#define fd_set cygwin_fd_set +#include <sys/types.h> +#endif +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <ctype.h> +#include <time.h> + +#include "cdefs.h" +#include "osdep.h" +#include "dhcp.h" +#include "tree.h" +#include "hash.h" +#include "inet.h" +#include "sysconf.h" + +struct option_data { + int len; + u_int8_t *data; +}; + +struct string_list { + struct string_list *next; + char string [1]; +}; + +/* A name server, from /etc/resolv.conf. */ +struct name_server { + struct name_server *next; + struct sockaddr_in addr; + TIME rcdate; +}; + +/* A domain search list element. */ +struct domain_search_list { + struct domain_search_list *next; + char *domain; + TIME rcdate; +}; + +/* A dhcp packet and the pointers to its option values. */ +struct packet { + struct dhcp_packet *raw; + int packet_length; + int packet_type; + int options_valid; + int client_port; + struct iaddr client_addr; + struct interface_info *interface; /* Interface on which packet + was received. */ + struct hardware *haddr; /* Physical link address + of local sender (maybe gateway). */ + struct shared_network *shared_network; + struct option_data options [256]; +}; + +struct hardware { + u_int8_t htype; + u_int8_t hlen; + u_int8_t haddr [16]; +}; + +/* A dhcp lease declaration structure. */ +struct lease { + struct lease *next; + struct lease *prev; + struct lease *n_uid, *n_hw; + struct lease *waitq_next; + + struct iaddr ip_addr; + TIME starts, ends, timestamp; + unsigned char *uid; + int uid_len; + int uid_max; + unsigned char uid_buf [32]; + char *hostname; + char *client_hostname; + struct host_decl *host; + struct subnet *subnet; + struct shared_network *shared_network; + struct hardware hardware_addr; + + int flags; +# define STATIC_LEASE 1 +# define BOOTP_LEASE 2 +# define DYNAMIC_BOOTP_OK 4 +# define PERSISTENT_FLAGS (DYNAMIC_BOOTP_OK) +# define EPHEMERAL_FLAGS (BOOTP_LEASE) +# define MS_NULL_TERMINATION 8 +# define ABANDONED_LEASE 16 + + struct lease_state *state; +}; + +struct lease_state { + struct lease_state *next; + + struct interface_info *ip; + + TIME offered_expiry; + + struct tree_cache *options [256]; + u_int32_t expiry, renewal, rebind; + char *filename, *server_name; + + u_int32_t xid; + u_int16_t secs; + u_int16_t bootp_flags; + struct in_addr ciaddr; + struct in_addr giaddr; + u_int8_t hops; + u_int8_t offer; +}; + +#define ROOT_GROUP 0 +#define HOST_DECL 1 +#define SHARED_NET_DECL 2 +#define SUBNET_DECL 3 +#define CLASS_DECL 4 +#define GROUP_DECL 5 + +/* Possible modes in which discover_interfaces can run. */ + +#define DISCOVER_RUNNING 0 +#define DISCOVER_SERVER 1 +#define DISCOVER_UNCONFIGURED 2 +#define DISCOVER_RELAY 3 +#define DISCOVER_REQUESTED 4 + +/* Group of declarations that share common parameters. */ +struct group { + struct group *next; + + struct subnet *subnet; + struct shared_network *shared_network; + + TIME default_lease_time; + TIME max_lease_time; + TIME bootp_lease_cutoff; + TIME bootp_lease_length; + + char *filename; + char *server_name; + struct iaddr next_server; + + int boot_unknown_clients; + int dynamic_bootp; + int allow_bootp; + int allow_booting; + int one_lease_per_client; + int get_lease_hostnames; + int use_host_decl_names; + + struct tree_cache *options [256]; +}; + +/* A dhcp host declaration structure. */ +struct host_decl { + struct host_decl *n_ipaddr; + char *name; + struct hardware interface; + struct tree_cache *fixed_addr; + struct group *group; +}; + +struct shared_network { + struct shared_network *next; + char *name; + struct subnet *subnets; + struct interface_info *interface; + struct lease *leases; + struct lease *insertion_point; + struct lease *last_lease; + + struct group *group; +}; + +struct subnet { + struct subnet *next_subnet; + struct subnet *next_sibling; + struct shared_network *shared_network; + struct interface_info *interface; + struct iaddr interface_address; + struct iaddr net; + struct iaddr netmask; + + struct group *group; +}; + +struct class { + char *name; + + struct group *group; +}; + +/* DHCP client lease structure... */ +struct client_lease { + struct client_lease *next; /* Next lease in list. */ + TIME expiry, renewal, rebind; /* Lease timeouts. */ + struct iaddr address; /* Address being leased. */ + char *server_name; /* Name of boot server. */ + char *filename; /* Name of file we're supposed to boot. */ + struct string_list *medium; /* Network medium. */ + + unsigned int is_static : 1; /* If set, lease is from config file. */ + unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */ + + struct option_data options [256]; /* Options supplied with lease. */ +}; + +/* Possible states in which the client can be. */ +enum dhcp_state { + S_REBOOTING, + S_INIT, + S_SELECTING, + S_REQUESTING, + S_BOUND, + S_RENEWING, + S_REBINDING +}; + +/* Configuration information from the config file... */ +struct client_config { + struct option_data defaults [256]; /* Default values for options. */ + enum { + ACTION_DEFAULT, /* Use server value if present, + otherwise default. */ + ACTION_SUPERSEDE, /* Always use default. */ + ACTION_PREPEND, /* Prepend default to server. */ + ACTION_APPEND, /* Append default to server. */ + } default_actions [256]; + + struct option_data send_options [256]; /* Send these to server. */ + u_int8_t required_options [256]; /* Options server must supply. */ + u_int8_t requested_options [256]; /* Options to request from server. */ + int requested_option_count; /* Number of requested options. */ + TIME timeout; /* Start to panic if we don't get a + lease in this time period when + SELECTING. */ + TIME initial_interval; /* All exponential backoff intervals + start here. */ + TIME retry_interval; /* If the protocol failed to produce + an address before the timeout, + try the protocol again after this + many seconds. */ + TIME select_interval; /* Wait this many seconds from the + first DHCPDISCOVER before + picking an offered lease. */ + TIME reboot_timeout; /* When in INIT-REBOOT, wait this + long before giving up and going + to INIT. */ + TIME backoff_cutoff; /* When doing exponential backoff, + never back off to an interval + longer than this amount. */ + struct string_list *media; /* Possible network media values. */ + char *script_name; /* Name of config script. */ + enum { IGNORE, ACCEPT, PREFER } bootp_policy; + /* Ignore, accept or prefer BOOTP + responses. */ + struct string_list *medium; /* Current network medium. */ + + struct iaddrlist *reject_list; /* Servers to reject. */ +}; + +/* Per-interface state used in the dhcp client... */ +struct client_state { + struct client_lease *active; /* Currently active lease. */ + struct client_lease *new; /* New lease. */ + struct client_lease *offered_leases; /* Leases offered to us. */ + struct client_lease *leases; /* Leases we currently hold. */ + struct client_lease *alias; /* Alias lease. */ + + enum dhcp_state state; /* Current state for this interface. */ + struct iaddr destination; /* Where to send packet. */ + u_int32_t xid; /* Transaction ID. */ + TIME first_sending; /* When was first copy sent? */ + TIME interval; /* What's the current resend interval? */ + struct string_list *medium; /* Last media type tried. */ + + struct dhcp_packet packet; /* Outgoing DHCP packet. */ + int packet_length; /* Actual length of generated packet. */ + + struct iaddr requested_address; /* Address we would like to get. */ + + struct client_config *config; /* Information from config file. */ +}; + +/* Information about each network interface. */ + +struct interface_info { + struct interface_info *next; /* Next interface in list... */ + struct shared_network *shared_network; + /* Networks connected to this interface. */ + struct hardware hw_address; /* Its physical address. */ + struct in_addr primary_address; /* Primary interface address. */ + char name [IFNAMSIZ]; /* Its name... */ + int rfdesc; /* Its read file descriptor. */ + int wfdesc; /* Its write file descriptor, if + different. */ + unsigned char *rbuf; /* Read buffer, if required. */ + size_t rbuf_max; /* Size of read buffer. */ + size_t rbuf_offset; /* Current offset into buffer. */ + size_t rbuf_len; /* Length of data in buffer. */ + + struct ifreq *ifp; /* Pointer to ifreq struct. */ + u_int32_t flags; /* Control flags... */ +#define INTERFACE_REQUESTED 1 +#define INTERFACE_AUTOMATIC 2 + + /* Only used by DHCP client code. */ + struct client_state *client; +}; + +struct hardware_link { + struct hardware_link *next; + char name [IFNAMSIZ]; + struct hardware address; +}; + +struct timeout { + struct timeout *next; + TIME when; + void (*func) PROTO ((void *)); + void *what; +}; + +struct protocol { + struct protocol *next; + int fd; + void (*handler) PROTO ((struct protocol *)); + void *local; +}; + +/* Bitmask of dhcp option codes. */ +typedef unsigned char option_mask [16]; + +/* DHCP Option mask manipulation macros... */ +#define OPTION_ZERO(mask) (memset (mask, 0, 16)) +#define OPTION_SET(mask, bit) (mask [bit >> 8] |= (1 << (bit & 7))) +#define OPTION_CLR(mask, bit) (mask [bit >> 8] &= ~(1 << (bit & 7))) +#define OPTION_ISSET(mask, bit) (mask [bit >> 8] & (1 << (bit & 7))) +#define OPTION_ISCLR(mask, bit) (!OPTION_ISSET (mask, bit)) + +/* An option occupies its length plus two header bytes (code and + length) for every 255 bytes that must be stored. */ +#define OPTION_SPACE(x) ((x) + 2 * ((x) / 255 + 1)) + +/* Default path to dhcpd config file. */ +#ifdef DEBUG +#undef _PATH_DHCPD_CONF +#define _PATH_DHCPD_CONF "dhcpd.conf" +#undef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "dhcpd.leases" +#else +#ifndef _PATH_DHCPD_CONF +#define _PATH_DHCPD_CONF "/etc/dhcpd.conf" +#endif + +#ifndef _PATH_DHCPD_DB +#define _PATH_DHCPD_DB "/etc/dhcpd.leases" +#endif + +#ifndef _PATH_DHCPD_PID +#define _PATH_DHCPD_PID "/var/run/dhcpd.pid" +#endif +#endif + +#ifndef _PATH_DHCLIENT_CONF +#define _PATH_DHCLIENT_CONF "/etc/dhclient.conf" +#endif + +#ifndef _PATH_DHCLIENT_PID +#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" +#endif + +#ifndef _PATH_DHCLIENT_DB +#define _PATH_DHCLIENT_DB "/etc/dhclient.leases" +#endif + +#ifndef _PATH_RESOLV_CONF +#define _PATH_RESOLV_CONF "/etc/resolv.conf" +#endif + +#ifndef _PATH_DHCRELAY_PID +#define _PATH_DHCRELAY_PID "/var/run/dhcrelay.pid" +#endif + +#ifndef DHCPD_LOG_FACILITY +#define DHCPD_LOG_FACILITY LOG_DAEMON +#endif + +#define MAX_TIME 0x7fffffff +#define MIN_TIME 0 + +/* External definitions... */ + +/* options.c */ + +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 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 *)); + +/* errwarn.c */ +extern int warnings_occurred; +void error PROTO ((char *, ...)); +int warn PROTO ((char *, ...)); +int note PROTO ((char *, ...)); +int debug PROTO ((char *, ...)); +int parse_warn PROTO ((char *, ...)); + +/* dhcpd.c */ +extern TIME cur_time; +extern struct group root_group; + +extern u_int16_t local_port; +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; + +int main PROTO ((int, char **, char **)); +void cleanup PROTO ((void)); +void lease_pinged PROTO ((struct iaddr, u_int8_t *, int)); +void lease_ping_timeout PROTO ((void *)); + +/* conflex.c */ +extern int lexline, lexchar; +extern char *token_line, *tlname; +extern char comments [4096]; +extern int comment_index; +extern int eol_token; +void new_parse PROTO ((char *)); +int next_token PROTO ((char **, FILE *)); +int peek_token PROTO ((char **, FILE *)); + +/* confpars.c */ +int readconf PROTO ((void)); +void read_leases PROTO ((void)); +int parse_statement PROTO ((FILE *, + struct group *, int, struct host_decl *, int)); +void parse_allow_deny PROTO ((FILE *, struct group *, int)); +void skip_to_semi PROTO ((FILE *)); +int parse_boolean PROTO ((FILE *)); +int parse_semi PROTO ((FILE *)); +int parse_lbrace PROTO ((FILE *)); +void parse_host_declaration PROTO ((FILE *, struct group *)); +char *parse_host_name PROTO ((FILE *)); +void parse_class_declaration PROTO ((FILE *, struct group *, int)); +void parse_lease_time PROTO ((FILE *, TIME *)); +void parse_shared_net_declaration PROTO ((FILE *, struct group *)); +void parse_subnet_declaration PROTO ((FILE *, struct shared_network *)); +void parse_group_declaration PROTO ((FILE *, struct group *)); +void parse_hardware_param PROTO ((FILE *, struct hardware *)); +char *parse_string PROTO ((FILE *)); +struct tree *parse_ip_addr_or_hostname PROTO ((FILE *, int)); +struct tree_cache *parse_fixed_addr_param PROTO ((FILE *)); +void parse_option_param PROTO ((FILE *, struct group *)); +TIME parse_timestamp PROTO ((FILE *)); +struct lease *parse_lease_declaration PROTO ((FILE *)); +void parse_address_range PROTO ((FILE *, struct subnet *)); +TIME parse_date PROTO ((FILE *)); +unsigned char *parse_numeric_aggregate PROTO ((FILE *, + unsigned char *, int *, + int, int, int)); +void convert_num PROTO ((unsigned char *, char *, int, int)); + +/* tree.c */ +pair cons PROTO ((caddr_t, pair)); +struct tree_cache *tree_cache PROTO ((struct tree *)); +struct tree *tree_host_lookup PROTO ((char *)); +struct dns_host_entry *enter_dns_host PROTO ((char *)); +struct tree *tree_const PROTO ((unsigned char *, int)); +struct tree *tree_concat PROTO ((struct tree *, struct tree *)); +struct tree *tree_limit PROTO ((struct tree *, int)); +int tree_evaluate PROTO ((struct tree_cache *)); + +/* dhcp.c */ +extern int outstanding_pings; + +void dhcp PROTO ((struct packet *)); +void dhcpdiscover PROTO ((struct packet *)); +void dhcprequest PROTO ((struct packet *)); +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 dhcp_reply PROTO ((struct lease *)); +struct lease *find_lease PROTO ((struct packet *, + struct shared_network *, int *)); +struct lease *mockup_lease PROTO ((struct packet *, + struct shared_network *, + struct host_decl *)); + +/* bootp.c */ +void bootp PROTO ((struct packet *)); + +/* memory.c */ +void enter_host PROTO ((struct host_decl *)); +struct host_decl *find_hosts_by_haddr PROTO ((int, unsigned char *, int)); +struct host_decl *find_hosts_by_uid PROTO ((unsigned char *, int)); +struct subnet *find_host_for_network PROTO ((struct host_decl **, + struct iaddr *, + struct shared_network *)); +void new_address_range PROTO ((struct iaddr, struct iaddr, + struct subnet *, int)); +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 *)); +void enter_subnet PROTO ((struct subnet *)); +void enter_lease PROTO ((struct lease *)); +int supersede_lease PROTO ((struct lease *, struct lease *, int)); +void release_lease PROTO ((struct lease *)); +void abandon_lease PROTO ((struct lease *, char *)); +struct lease *find_lease_by_uid PROTO ((unsigned char *, int)); +struct lease *find_lease_by_hw_addr PROTO ((unsigned char *, int)); +struct lease *find_lease_by_ip_addr PROTO ((struct iaddr)); +void uid_hash_add PROTO ((struct lease *)); +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 group *clone_group PROTO ((struct group *, char *)); +void write_leases PROTO ((void)); +void dump_subnets PROTO ((void)); + +/* alloc.c */ +VOIDPTR dmalloc PROTO ((int, char *)); +void dfree PROTO ((VOIDPTR, char *)); +struct packet *new_packet PROTO ((char *)); +struct dhcp_packet *new_dhcp_packet PROTO ((char *)); +struct tree *new_tree PROTO ((char *)); +struct tree_cache *new_tree_cache PROTO ((char *)); +struct hash_table *new_hash_table PROTO ((int, char *)); +struct hash_bucket *new_hash_bucket PROTO ((char *)); +struct lease *new_lease PROTO ((char *)); +struct lease *new_leases PROTO ((int, char *)); +struct subnet *new_subnet PROTO ((char *)); +struct class *new_class PROTO ((char *)); +struct shared_network *new_shared_network PROTO ((char *)); +struct group *new_group PROTO ((char *)); +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 *)); +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 *)); +void free_protocol PROTO ((struct protocol *, char *)); +void free_group PROTO ((struct group *, char *)); +void free_shared_network PROTO ((struct shared_network *, char *)); +void free_class PROTO ((struct class *, char *)); +void free_subnet PROTO ((struct subnet *, char *)); +void free_lease PROTO ((struct lease *, char *)); +void free_hash_bucket PROTO ((struct hash_bucket *, char *)); +void free_hash_table PROTO ((struct hash_table *, char *)); +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 *)); + +/* print.c */ +char *print_hw_addr PROTO ((int, int, unsigned char *)); +void print_lease PROTO ((struct lease *)); +void dump_raw PROTO ((unsigned char *, int)); +void dump_packet PROTO ((struct packet *)); +void hash_dump PROTO ((struct hash_table *)); + +/* socket.c */ +#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \ + || defined (USE_SOCKET_FALLBACK) +int if_register_socket PROTO ((struct interface_info *)); +#endif + +#ifdef USE_SOCKET_FALLBACK +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 +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_SOCKET_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_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK) +void if_enable PROTO ((struct interface_info *)); +#endif + +/* bpf.c */ +#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) +int if_register_bpf PROTO ( (struct interface_info *)); +#endif +#ifdef USE_BPF_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_BPF_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_BPF_SEND) +void if_enable PROTO ((struct interface_info *)); +#endif + +/* nit.c */ +#if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE) +int if_register_nit PROTO ( (struct interface_info *)); +#endif + +#ifdef USE_NIT_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_NIT_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_BPF_SEND) +void if_enable PROTO ((struct interface_info *)); +#endif + +/* raw.c */ +#ifdef USE_RAW_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 + +/* dispatch.c */ +extern struct interface_info *interfaces, *dummy_interfaces; +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 *)); +extern struct timeout *timeouts; +void discover_interfaces PROTO ((int)); +void reinitialize_interfaces PROTO ((void)); +void dispatch PROTO ((void)); +int locate_network PROTO ((struct packet *)); +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 *)); + +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)); + +/* tables.c */ +extern struct option dhcp_options [256]; +extern unsigned char dhcp_option_default_priority_list []; +extern int sizeof_dhcp_option_default_priority_list; +extern char *hardware_types [256]; +extern struct hash_table universe_hash; +extern struct universe dhcp_universe; +void initialize_universes PROTO ((void)); + +/* convert.c */ +u_int32_t getULong PROTO ((unsigned char *)); +int32_t getLong PROTO ((unsigned char *)); +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)); + +/* inet.c */ +struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr)); +struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, u_int32_t)); +struct iaddr broadcast_addr PROTO ((struct iaddr, struct iaddr)); +u_int32_t host_addr PROTO ((struct iaddr, struct iaddr)); +int addr_eq PROTO ((struct iaddr, struct iaddr)); +char *piaddr PROTO ((struct iaddr)); + +/* dhclient.c */ +extern char *path_dhclient_conf; +extern char *path_dhclient_db; +extern char *path_dhclient_pid; +extern int interfaces_requested; + +extern struct client_config top_level_config; + +void dhcpoffer PROTO ((struct packet *)); +void dhcpack PROTO ((struct packet *)); +void dhcpnak PROTO ((struct packet *)); + +void send_discover PROTO ((void *)); +void send_request PROTO ((void *)); +void send_release PROTO ((void *)); +void send_decline PROTO ((void *)); + +void state_reboot PROTO ((void *)); +void state_init PROTO ((void *)); +void state_selecting PROTO ((void *)); +void state_requesting PROTO ((void *)); +void state_bound PROTO ((void *)); +void state_panic PROTO ((void *)); + +void bind_lease PROTO ((struct interface_info *)); + +void make_discover PROTO ((struct interface_info *, struct client_lease *)); +void make_request PROTO ((struct interface_info *, struct client_lease *)); +void make_decline PROTO ((struct interface_info *, struct client_lease *)); +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 *)); + +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 *)); + +struct client_lease *packet_to_lease PROTO ((struct packet *)); +void go_daemon PROTO ((void)); +void write_client_pid_file PROTO ((void)); +void status_message PROTO ((struct sysconf_header *, void *)); +void client_location_changed PROTO ((void)); + +/* db.c */ +int write_lease PROTO ((struct lease *)); +int commit_leases PROTO ((void)); +void db_startup PROTO ((void)); +void new_lease_file PROTO ((void)); + +/* packet.c */ +u_int32_t checksum PROTO ((unsigned char *, int, u_int32_t)); +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, + unsigned char *, int)); +ssize_t decode_hw_header PROTO ((struct interface_info *, unsigned char *, + int, struct hardware *)); +ssize_t decode_udp_ip_header PROTO ((struct interface_info *, unsigned char *, + int, struct sockaddr_in *, + unsigned char *, int)); + +/* dhxpxlt.c */ +void convert_statement PROTO ((FILE *)); +void convert_host_statement PROTO ((FILE *, jrefproto)); +void convert_host_name PROTO ((FILE *, jrefproto)); +void convert_class_statement PROTO ((FILE *, jrefproto, int)); +void convert_class_decl PROTO ((FILE *, jrefproto)); +void convert_lease_time PROTO ((FILE *, jrefproto, char *)); +void convert_shared_net_statement PROTO ((FILE *, jrefproto)); +void convert_subnet_statement PROTO ((FILE *, jrefproto)); +void convert_subnet_decl PROTO ((FILE *, jrefproto)); +void convert_host_decl PROTO ((FILE *, jrefproto)); +void convert_hardware_decl PROTO ((FILE *, jrefproto)); +void convert_hardware_addr PROTO ((FILE *, jrefproto)); +void convert_filename_decl PROTO ((FILE *, jrefproto)); +void convert_servername_decl PROTO ((FILE *, jrefproto)); +void convert_ip_addr_or_hostname PROTO ((FILE *, jrefproto, int)); +void convert_fixed_addr_decl PROTO ((FILE *, jrefproto)); +void convert_option_decl PROTO ((FILE *, jrefproto)); +void convert_timestamp PROTO ((FILE *, jrefproto)); +void convert_lease_statement PROTO ((FILE *, jrefproto)); +void convert_address_range PROTO ((FILE *, jrefproto)); +void convert_date PROTO ((FILE *, jrefproto, char *)); +void convert_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, int)); +void indent PROTO ((int)); + +/* route.c */ +void add_route_direct PROTO ((struct interface_info *, struct in_addr)); +void add_route_net PROTO ((struct interface_info *, struct in_addr, + struct in_addr)); +void add_route_default_gateway PROTO ((struct interface_info *, + struct in_addr)); +void remove_routes PROTO ((struct in_addr)); +void remove_if_route PROTO ((struct interface_info *, struct in_addr)); +void remove_all_if_routes PROTO ((struct interface_info *)); +void set_netmask PROTO ((struct interface_info *, struct in_addr)); +void set_broadcast_addr PROTO ((struct interface_info *, struct in_addr)); +void set_ip_address PROTO ((struct interface_info *, struct in_addr)); + +/* clparse.c */ +int read_client_conf PROTO ((void)); +void read_client_leases PROTO ((void)); +void parse_client_statement PROTO ((FILE *, struct interface_info *, + struct client_config *)); +int parse_X PROTO ((FILE *, u_int8_t *, int)); +int parse_option_list PROTO ((FILE *, u_int8_t *)); +void parse_interface_declaration PROTO ((FILE *, struct client_config *)); +struct interface_info *interface_or_dummy PROTO ((char *)); +void make_client_state PROTO ((struct interface_info *)); +void make_client_config PROTO ((struct interface_info *, + struct client_config *)); +void parse_client_lease_statement PROTO ((FILE *, int)); +void parse_client_lease_declaration PROTO ((FILE *, struct client_lease *, + struct interface_info **)); +struct option *parse_option_decl PROTO ((FILE *, struct option_data *)); +void parse_string_list PROTO ((FILE *, struct string_list **, int)); +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 *)); + +/* icmp.c */ +void icmp_startup PROTO ((int, void (*) PROTO ((struct iaddr, + u_int8_t *, int)))); +int icmp_echorequest PROTO ((struct iaddr *)); +void icmp_echoreply PROTO ((struct protocol *)); + +/* dns.c */ +void dns_startup PROTO ((void)); +int ns_inaddr_lookup PROTO ((u_int16_t, struct iaddr)); +void dns_packet PROTO ((struct protocol *)); + +/* resolv.c */ +extern char path_resolv_conf []; +struct name_server *name_servers; +struct domain_search_list *domains; + +void read_resolv_conf PROTO ((TIME)); +struct sockaddr_in *pick_name_server PROTO ((void)); + +/* inet_addr.c */ +#ifdef NEED_INET_ATON +int inet_aton PROTO ((char *, struct in_addr *)); +#endif + +/* sysconf.c */ +void sysconf_startup PROTO ((void (*) (struct sysconf_header *, void *))); +void sysconf_restart PROTO ((void *)); +void sysconf_message PROTO ((struct protocol *proto)); diff --git a/usr.sbin/dhcp/includes/dhctoken.h b/usr.sbin/dhcp/includes/dhctoken.h new file mode 100644 index 00000000000..88acd162298 --- /dev/null +++ b/usr.sbin/dhcp/includes/dhctoken.h @@ -0,0 +1,131 @@ +/* dhctoken.h + + Tokens for config file lexer and parser. */ + +/* + * 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 <mellon@fugue.com> 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''. + */ + +#define SEMI ';' +#define DOT '.' +#define COLON ':' +#define COMMA ',' +#define SLASH '/' +#define LBRACE '{' +#define RBRACE '}' + +#define FIRST_TOKEN HOST +#define HOST 256 +#define HARDWARE 257 +#define FILENAME 258 +#define FIXED_ADDR 259 +#define OPTION 260 +#define ETHERNET 261 +#define STRING 262 +#define NUMBER 263 +#define NUMBER_OR_NAME 264 +#define NAME 265 +#define TIMESTAMP 266 +#define STARTS 267 +#define ENDS 268 +#define UID 269 +#define CLASS 270 +#define LEASE 271 +#define RANGE 272 +#define PACKET 273 +#define CIADDR 274 +#define YIADDR 275 +#define SIADDR 276 +#define GIADDR 277 +#define SUBNET 278 +#define NETMASK 279 +#define DEFAULT_LEASE_TIME 280 +#define MAX_LEASE_TIME 281 +#define VENDOR_CLASS 282 +#define USER_CLASS 283 +#define SHARED_NETWORK 284 +#define SERVER_NAME 285 +#define DYNAMIC_BOOTP 286 +#define SERVER_IDENTIFIER 287 +#define DYNAMIC_BOOTP_LEASE_CUTOFF 288 +#define DYNAMIC_BOOTP_LEASE_LENGTH 289 +#define BOOT_UNKNOWN_CLIENTS 290 +#define NEXT_SERVER 291 +#define TOKEN_RING 292 +#define GROUP 293 +#define ONE_LEASE_PER_CLIENT 294 +#define GET_LEASE_HOSTNAMES 295 +#define USE_HOST_DECL_NAMES 296 +#define SEND 297 +#define CLIENT_IDENTIFIER 298 +#define REQUEST 299 +#define REQUIRE 300 +#define TIMEOUT 301 +#define RETRY 302 +#define SELECT_TIMEOUT 303 +#define SCRIPT 304 +#define INTERFACE 305 +#define RENEW 306 +#define REBIND 307 +#define EXPIRE 308 +#define UNKNOWN_CLIENTS 309 +#define ALLOW 310 +#define BOOTP 311 +#define DENY 312 +#define BOOTING 313 +#define DEFAULT 314 +#define MEDIA 315 +#define MEDIUM 316 +#define ALIAS 317 +#define REBOOT 318 +#define ABANDONED 319 +#define BACKOFF_CUTOFF 320 +#define INITIAL_INTERVAL 321 +#define NAMESERVER 322 +#define DOMAIN 323 +#define SEARCH 324 +#define SUPERSEDE 325 +#define APPEND 326 +#define PREPEND 327 +#define HOSTNAME 328 +#define CLIENT_HOSTNAME 329 +#define REJECT 330 + +#define is_identifier(x) ((x) >= FIRST_TOKEN && \ + (x) != STRING && \ + (x) != NUMBER && \ + (x) != EOF) diff --git a/usr.sbin/dhcp/includes/hash.h b/usr.sbin/dhcp/includes/hash.h new file mode 100644 index 00000000000..d30072b3c12 --- /dev/null +++ b/usr.sbin/dhcp/includes/hash.h @@ -0,0 +1,55 @@ +/* hash.h + + Definitions for hashing... */ + +/* + * Copyright (c) 1995 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 <mellon@fugue.com> 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''. + */ + +#define DEFAULT_HASH_SIZE 97 + +struct hash_bucket { + struct hash_bucket *next; + char *name; + int len; + unsigned char *value; +}; + +struct hash_table { + int hash_count; + struct hash_bucket *buckets [DEFAULT_HASH_SIZE]; +}; + diff --git a/usr.sbin/dhcp/includes/inet.h b/usr.sbin/dhcp/includes/inet.h new file mode 100644 index 00000000000..1cedc2331a2 --- /dev/null +++ b/usr.sbin/dhcp/includes/inet.h @@ -0,0 +1,52 @@ +/* inet.h + + Portable definitions for internet addresses */ + +/* + * 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 <mellon@fugue.com> 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''. + */ + +/* An internet address of up to 128 bits. */ + +struct iaddr { + int len; + unsigned char iabuf [16]; +}; + +struct iaddrlist { + struct iaddrlist *next; + struct iaddr addr; +}; diff --git a/usr.sbin/dhcp/includes/netinet/if_ether.h b/usr.sbin/dhcp/includes/netinet/if_ether.h new file mode 100644 index 00000000000..2af9198e542 --- /dev/null +++ b/usr.sbin/dhcp/includes/netinet/if_ether.h @@ -0,0 +1,74 @@ +/* $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 new file mode 100644 index 00000000000..bb02d2eaf0a --- /dev/null +++ b/usr.sbin/dhcp/includes/netinet/ip.h @@ -0,0 +1,171 @@ +/* $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 new file mode 100644 index 00000000000..e8cd0eda204 --- /dev/null +++ b/usr.sbin/dhcp/includes/netinet/ip_icmp.h @@ -0,0 +1,182 @@ +/* $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 new file mode 100644 index 00000000000..8ad181b390f --- /dev/null +++ b/usr.sbin/dhcp/includes/netinet/udp.h @@ -0,0 +1,47 @@ +/* $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 new file mode 100644 index 00000000000..801eba5223a --- /dev/null +++ b/usr.sbin/dhcp/includes/osdep.h @@ -0,0 +1,203 @@ +/* osdep.h + + Operating system dependencies... */ + +/* + * 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 was written for the Internet Software Consortium by Ted Lemon + * under a contract with Vixie Laboratories. + */ + +#include "site.h" + +/* Porting:: + + If you add a new network API, you must add a check for it below: */ + +#if !defined (USE_SOCKETS) && \ + !defined (USE_SOCKET_SEND) && \ + !defined (USE_SOCKET_RECEIVE) && \ + !defined (USE_RAW_SOCKETS) && \ + !defined (USE_RAW_SEND) && \ + !defined (USE_SOCKET_RECEIVE) && \ + !defined (USE_BPF) && \ + !defined (USE_BPF_SEND) && \ + !defined (USE_BPF_RECEIVE) && \ + !defined (USE_NIT) && \ + !defined (USE_NIT_SEND) && \ + !defined (USE_NIT_RECEIVE) +# define USE_DEFAULT_NETWORK +#endif + + +/* Porting:: + + If you add a new system configuration file, include it here: */ + +#if defined (sun) +# if defined (__svr4__) || defined (__SVR4) +# include "cf/sunos5-5.h" +# else +# include "cf/sunos4.h" +# endif +#endif + +#ifdef bsdi +# include "cf/bsdos.h" +#endif + +#ifdef __NetBSD__ +# include "cf/netbsd.h" +#endif + +#ifdef __OpenBSD__ +# include "cf/openbsd.h" +#endif + +#ifdef __FreeBSD__ +# include "cf/freebsd.h" +#endif + +#if defined (__osf__) && defined (__alpha) +# include "cf/alphaosf.h" +#endif + +#ifdef ultrix +# include "cf/ultrix.h" +#endif + +#ifdef linux +# include "cf/linux.h" +#endif + +#ifdef SCO +# include "cf/sco.h" +#endif + +#ifdef hpux +# include "cf/hpux.h" +#endif + +#ifdef __QNX__ +# include "cf/qnx.h" +#endif + +#ifdef __CYGWIN32__ +# include "cf/cygwin32.h" +#endif + +#ifdef NeXT +# include "cf/nextstep.h" +#endif + +/* Porting:: + + If you add a new network API, and have it set up so that it can be + used for sending or receiving, but doesn't have to be used for both, + then set up an ifdef like the ones below: */ + +#ifdef USE_SOCKETS +# define USE_SOCKET_SEND +# define USE_SOCKET_RECEIVE +#endif + +#ifdef USE_RAW_SOCKETS +# define USE_RAW_SEND +# define USE_SOCKET_RECEIVE +#endif + +#ifdef USE_BPF +# define USE_BPF_SEND +# define USE_BPF_RECEIVE +#endif + +#ifdef USE_NIT +# define USE_NIT_SEND +# define USE_NIT_RECEIVE +#endif + +#ifdef USE_UPF +# define USE_UPF_SEND +# define USE_UPF_RECEIVE +#endif + +/* Porting:: + + If you add support for sending packets directly out an interface, + and your support does not do ARP or routing, you must use a fallback + mechanism to deal with packets that need to be sent to routers. + 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) +# define USE_SOCKET_FALLBACK +# define USE_FALLBACK +#endif + +/* Porting:: + + If you add support for sending packets directly out an interface + and need to be able to assemble packets, add the USE_XXX_SEND + 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) +# define PACKET_ASSEMBLY +#endif + +/* Porting:: + + If you add support for receiving packets directly from an interface + and need to be able to decode raw packets, add the USE_XXX_RECEIVE + 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) +# define PACKET_DECODING +#endif + +/* jmp_buf is assumed to be a struct unless otherwise defined in the + system header. */ +#ifndef jbp_decl +# define jbp_decl(x) jmp_buf *x +#endif +#ifndef jref +# define jref(x) (&(x)) +#endif +#ifndef jdref +# define jdref(x) (*(x)) +#endif +#ifndef jrefproto +# define jrefproto jmp_buf * +#endif + +#ifndef BPF_FORMAT +# define BPF_FORMAT "/dev/bpf%d" +#endif diff --git a/usr.sbin/dhcp/includes/site.h b/usr.sbin/dhcp/includes/site.h new file mode 100644 index 00000000000..30fdb703005 --- /dev/null +++ b/usr.sbin/dhcp/includes/site.h @@ -0,0 +1,100 @@ +/* Site-specific definitions. + + For supported systems, you shouldn't need to make any changes here. + However, you may want to, in order to deal with site-specific + differences. */ + +/* Add any site-specific definitions and inclusions here... */ + +/* #include <site-foo-bar.h> */ +/* #define SITE_FOOBAR */ + +/* Define this if you don't want dhcpd to run as a daemon and do want + to see all its output printed to stdout instead of being logged via + syslog(). This also makes dhcpd use the dhcpd.conf in its working + directory and write the dhcpd.leases file there. */ + +/* #define DEBUG */ + +/* Define this to see what the parser is parsing. You probably don't + want to see this. */ + +/* #define DEBUG_TOKENS */ + +/* Define this to see dumps of incoming and outgoing packets. This + slows things down quite a bit... */ + +/* #define DEBUG_PACKET */ + +/* Define this if you want to see dumps of tree evaluations. The most + common reason for doing this is to watch what happens with DNS name + lookups. */ + +/* #define DEBUG_EVAL */ + +/* Define this if you want the dhcpd.pid file to go somewhere other than + the default (which varies from system to system, but is usually either + /etc or /var/run. */ + +/* #define _PATH_DHCPD_PID "/var/run/dhcpd.pid" */ + +/* Define this if you want the dhcpd.leases file (the dynamic lease database) + to go somewhere other than the default location, which is normally + /etc/dhcpd.leases. */ + +/* #define _PATH_DHCPD_DB "/etc/dhcpd.leases" */ + +/* Define this if you want the dhcpd.conf file to go somewhere other than + the default location. By default, it goes in /etc/dhcpd.conf. */ + +/* #define _PATH_DHCPD_CONF "/etc/dhcpd.conf" */ + +/* Network API definitions. You do not need to choose one of these - if + you don't choose, one will be chosen for you in your system's config + header. DON'T MESS WITH THIS UNLESS YOU KNOW WHAT YOU'RE DOING!!! */ + +/* Define this to use the standard BSD socket API. + + On many systems, the BSD socket API does not provide the ability to + send packets to the 255.255.255.255 broadcast address, which can + prevent some clients (e.g., Win95) from seeing replies. This is + not a problem on Solaris. + + In addition, the BSD socket API will not work when more than one + network interface is configured on the server. + + However, the BSD socket API is about as efficient as you can get, so if + the aforementioned problems do not matter to you, or if no other + API is supported for your system, you may want to go with it. */ + +/* #define USE_SOCKETS */ + +/* Define this to use the Sun Streams NIT API. + + The Sun Streams NIT API is only supported on SunOS 4.x releases. */ + +/* #define USE_NIT */ + +/* Define this to use the Berkeley Packet Filter API. + + The BPF API is available on all 4.4-BSD derivatives, including + 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. */ + +/* #define USE_BPF */ + +/* Define this to use the raw socket API. + + The raw socket API is provided on many BSD derivatives, and provides + a way to send out raw IP packets. It is only supported for sending + packets - packets must be received with the regular socket API. + This code is experimental - I've never gotten it to actually transmit + a packet to the 255.255.255.255 broadcast address - so use it at your + own risk. */ + +/* #define USE_RAW_SOCKETS */ + +/* Define this to change the logging facility used by dhcpd. */ + +/* #define DHCPD_LOG_FACILITY LOG_DAEMON */ diff --git a/usr.sbin/dhcp/includes/sysconf.h b/usr.sbin/dhcp/includes/sysconf.h new file mode 100644 index 00000000000..5feb4c75c70 --- /dev/null +++ b/usr.sbin/dhcp/includes/sysconf.h @@ -0,0 +1,52 @@ +/* systat.h + + Definitions for systat protocol... */ + +/* + * 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 <mellon@fugue.com> 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''. + */ + +#define SYSCONF_SOCKET "/var/run/sysconf" + +struct sysconf_header { + u_int32_t type; /* Type of status message... */ + u_int32_t length; /* Length of message. */ +}; + +/* Message types... */ +#define NETWORK_LOCATION_CHANGED 1 + diff --git a/usr.sbin/dhcp/includes/tree.h b/usr.sbin/dhcp/includes/tree.h new file mode 100644 index 00000000000..c2df41f52b1 --- /dev/null +++ b/usr.sbin/dhcp/includes/tree.h @@ -0,0 +1,107 @@ +/* tree.h + + Definitions for address trees... */ + +/* + * Copyright (c) 1995 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 <mellon@fugue.com> 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''. + */ + +/* A pair of pointers, suitable for making a linked list. */ +typedef struct _pair { + caddr_t car; + struct _pair *cdr; +} *pair; + +/* Tree node types... */ +#define TREE_CONCAT 1 +#define TREE_HOST_LOOKUP 2 +#define TREE_CONST 3 +#define TREE_LIMIT 4 + +/* Tree structure for deferred evaluation of changing values. */ +struct tree { + int op; + union { + struct concat { + struct tree *left; + struct tree *right; + } concat; + struct host_lookup { + struct dns_host_entry *host; + } host_lookup; + struct const_val { + unsigned char *data; + int len; + } const_val; + struct limit { + struct tree *tree; + int limit; + } limit; + } data; +}; + +/* DNS host entry structure... */ +struct dns_host_entry { + char *hostname; + unsigned char *data; + int data_len; + int buf_len; + TIME timeout; +}; + +struct tree_cache { + unsigned char *value; + int len; + int buf_size; + TIME timeout; + struct tree *tree; + int flags; +#define TC_AWAITING_RESOLUTION 1 +#define TC_TEMPORARY 2 +}; + +struct universe { + char *name; + struct hash_table *hash; + struct option *options [256]; +}; + +struct option { + char *name; + char *format; + struct universe *universe; + unsigned char code; +}; diff --git a/usr.sbin/dhcp/relay/Makefile b/usr.sbin/dhcp/relay/Makefile new file mode 100644 index 00000000000..dcbb5650e50 --- /dev/null +++ b/usr.sbin/dhcp/relay/Makefile @@ -0,0 +1,37 @@ +# Makefile +# +# Copyright (c) 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. +# + +SRCS = dhcrelay.c +PROG = dhcrelay +MAN = dhcrelay.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/dhcp/relay/dhcrelay.8 b/usr.sbin/dhcp/relay/dhcrelay.8 new file mode 100644 index 00000000000..8e9463db6f2 --- /dev/null +++ b/usr.sbin/dhcp/relay/dhcrelay.8 @@ -0,0 +1,139 @@ +.\" dhcrelay.8 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 dhcrelay 8 +.SH NAME +dhcrelay - Dynamic Host Configuration Protocol Relay Agent +.SH SYNOPSIS +.B dhcrelay +[ +.B -p +.I port +] +[ +.B -d +] +[ +.B -q +] +[ +.B -i +.I if0 +[ +.B ... +.B -i +.I ifN +] +] +.I server0 +[ +.I ...serverN +] +.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 +subnets. +.SH SYSTEM REQUIREMENTS +You must have the Berkeley +Packet Filter (bpf) configured in your NetBSD 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 +attached to a host, unless one or more interfaces are specified on the +command line with the +.I -i +flag. +.PP +When a query is received, dhcrelay forwards it to the list of DHCP +servers specified on the command line. When a reply is received, it +is broadcast or unicast on the network from whence the original +request came. +.PP +It is possible to specify a set of interfaces on which dhcrelay will +listen, so that if dhcrelay is connected through one interface to a +network on which there is no DHCP server, but is connected on another +interface to a network on which there is a DHCP server, it will not +relay DHCP and BOOTP requests from the network on which the server +exists to that server. This is an imperfect solution. +.SH COMMAND LINE +.PP +The names of the network interfaces that dhcrelay should attempt to +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, 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 +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. +.PP +Dhcrelay will normally run in the foreground until it has configured +an interface, and then will revert to running in the background. +To run force dhcrelay to always run as a foreground process, the +.B -d +flag should be specified. This is useful when running dhcrelay under +a debugger, or when running it out of inittab on System V systems. +.PP +Dhcrelay will normally print its network configuration on startup. +This can be annoying in a system startup script - to disable this +behaviour, specify the +.I -q +flag. +.PP +The name of at least one DHCP server to which DHCP and BOOTP requests +should be relayed must be specified on the command line. +.PP +.SH SEE ALSO +dhclient(8), dhcpd(8), RFC2132, RFC2131. +.SH AUTHOR +.B dhcrelay(8) +has been written for the Internet Software Consortium +by Ted Lemon <mellon@fugue.com> in cooperation with Vixie +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 diff --git a/usr.sbin/dhcp/relay/dhcrelay.c b/usr.sbin/dhcp/relay/dhcrelay.c new file mode 100644 index 00000000000..12e40d2eb50 --- /dev/null +++ b/usr.sbin/dhcp/relay/dhcrelay.c @@ -0,0 +1,359 @@ +/* dhcrelay.c + + DHCP/BOOTP Relay Agent. */ + +/* + * 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 <mellon@fugue.com> 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: dhcrelay.c,v 1.1 1998/08/18 03:43:34 deraadt Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" + +static void usage PROTO ((void)); + +TIME cur_time; +TIME default_lease_time = 43200; /* 12 hours... */ +TIME max_lease_time = 86400; /* 24 hours... */ +struct tree_cache *global_options [256]; + +int log_perror = 1; + +char *path_dhcrelay_pid = _PATH_DHCRELAY_PID; + +#ifdef USE_FALLBACK +struct interface_info fallback_interface; +#endif + +u_int16_t local_port; +u_int16_t remote_port; +int log_priority; + +struct server_list { + struct server_list *next; + struct sockaddr_in to; +} *servers; + +int main (argc, argv, envp) + int argc; + char **argv, **envp; +{ + int i; + struct servent *ent; + struct server_list *sp = (struct server_list *)0; + int no_daemon = 0; + int quiet = 0; + +#ifdef SYSLOG_4_2 + openlog ("dhcrelay", LOG_NDELAY); + log_priority = LOG_DAEMON; +#else + openlog ("dhcrelay", LOG_NDELAY, LOG_DAEMON); +#endif + +#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 (); + 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], "-i")) { + struct interface_info *tmp = + ((struct interface_info *) + dmalloc (sizeof *tmp, "specified_interface")); + if (!tmp) + error ("Insufficient memory to %s %s", + "record interface", argv [i]); + if (++i == argc) { + usage (); + } + memset (tmp, 0, sizeof *tmp); + strcpy (tmp -> name, argv [i]); + tmp -> next = interfaces; + tmp -> flags = INTERFACE_REQUESTED; + interfaces = tmp; + } else if (!strcmp (argv [i], "-q")) { + quiet = 1; + quiet_interface_discovery = 1; + } else if (argv [i][0] == '-') { + usage (); + } else { + struct hostent *he; + struct in_addr ia, *iap = (struct in_addr *)0; + if (inet_aton (argv [i], &ia)) { + iap = &ia; + } else { + he = gethostbyname (argv [i]); + if (!he) { + warn ("%s: host unknown", argv [i]); + } else { + iap = ((struct in_addr *) + he -> h_addr_list [0]); + } + } + if (iap) { + sp = (struct server_list *)malloc (sizeof *sp); + if (!sp) + error ("no memory for server.\n"); + sp -> next = servers; + servers = sp; + memcpy (&sp -> to.sin_addr, + iap, sizeof *iap); + } + } + } + + /* Default to the DHCP/BOOTP port. */ + if (!local_port) { + ent = getservbyname ("dhcps", "udp"); + if (!ent) + local_port = htons (67); + else + local_port = ent -> s_port; + endservent (); + } + remote_port = htons (ntohs (local_port) + 1); + + /* We need at least one server. */ + if (!sp) { + usage (); + } + + /* 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... */ + GET_TIME (&cur_time); + + /* Discover all the network interfaces. */ + discover_interfaces (DISCOVER_RELAY); + + /* Set up the bootp packet handler... */ + bootp_packet_handler = relay; + + /* Become a daemon... */ + if (!no_daemon) { + int pid; + FILE *pf; + int pfdesc; + + log_perror = 0; + + if ((pid = fork()) < 0) + error ("can't fork daemon: %m"); + else if (pid) + exit (0); + + 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); + close (2); + pid = setsid (); + } + + /* Start dispatching packets and timeouts... */ + dispatch (); + + /*NOTREACHED*/ + return 0; +} + +void relay (ip, packbuf, length, from_port, from, hfrom) + struct interface_info *ip; + u_int8_t *packbuf; + int length; + u_int16_t 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 it's a bootreply, forward it to the client. */ + if (packet -> op == BOOTREPLY) { +#ifndef USE_FALLBACK + if (!(packet -> flags & htons (BOOTP_BROADCAST))) { + to.sin_addr = packet -> yiaddr; + to.sin_port = remote_port; + } else +#endif + { + 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)); + hto.htype = packet -> htype; + + /* Find the interface that corresponds to the giaddr + in the packet. */ + for (out = interfaces; out; out = out -> next) { + if (!memcmp (&out -> primary_address, + &packet -> giaddr, + sizeof packet -> giaddr)) + break; + } + if (!out) { + warn ("packet to bogus giaddr %s.\n", + inet_ntoa (packet -> giaddr)); + return; + } + + if (send_packet (out, + (struct packet *)0, + packet, length, out -> primary_address, + &to, &hto) < 0) + debug ("sendpkt: %m"); + else + debug ("forwarded BOOTREPLY for %s to %s", + print_hw_addr (packet -> htype, packet -> hlen, + packet -> chaddr), + inet_ntoa (to.sin_addr)); + + return; + } + + /* If giaddr is set on a BOOTREQUEST, ignore it - it's already + been gatewayed. */ + if (packet -> giaddr.s_addr) { + note ("ignoring BOOTREQUEST with giaddr of %s\n", + inet_ntoa (packet -> giaddr)); + return; + } + + /* Set the giaddr so the server can figure out what net it's + from and so that we can later forward the response to the + correct net. */ + packet -> giaddr = ip -> primary_address; + + /* 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 { + debug ("forwarded BOOTREQUEST for %s to %s", + print_hw_addr (packet -> htype, packet -> hlen, + packet -> chaddr), + inet_ntoa (sp -> to.sin_addr)); + } + } + +} + +static void usage () +{ + error ("Usage: dhcrelay [-c] [-p <port>] [server1 [... serverN]]"); +} + +void cleanup () +{ +} + +int write_lease (lease) + struct lease *lease; +{ + return 1; +} + +int commit_leases () +{ + return 1; +} + +void bootp (packet) + struct packet *packet; +{ +} + +void dhcp (packet) + struct packet *packet; +{ +} diff --git a/usr.sbin/dhcp/server/Makefile b/usr.sbin/dhcp/server/Makefile new file mode 100644 index 00000000000..583c892219e --- /dev/null +++ b/usr.sbin/dhcp/server/Makefile @@ -0,0 +1,37 @@ +# Makefile +# +# Copyright (c) 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. +# + +SRCS = dhcpd.c dhcp.c bootp.c confpars.c db.c +PROG = dhcpd +MAN = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5 + +.include <bsd.prog.mk> diff --git a/usr.sbin/dhcp/server/bootp.c b/usr.sbin/dhcp/server/bootp.c new file mode 100644 index 00000000000..9694f6a15e3 --- /dev/null +++ b/usr.sbin/dhcp/server/bootp.c @@ -0,0 +1,346 @@ +/* bootp.c + + BOOTP Protocol support. */ + +/* + * 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 <mellon@fugue.com> 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: 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) + struct packet *packet; +{ + int result; + struct host_decl *hp; + struct host_decl *host = (struct host_decl *)0; + struct packet outgoing; + struct dhcp_packet raw; + struct sockaddr_in to; + struct in_addr from; + struct hardware hto; + struct tree_cache *options [256]; + struct subnet *subnet; + struct lease *lease; + struct iaddr ip_address; + int i; + + if (packet -> raw -> op != BOOTREQUEST) + return; + + note ("BOOTREQUEST from %s via %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); + + + + if (!locate_network (packet)) + return; + + hp = find_hosts_by_haddr (packet -> raw -> htype, + packet -> raw -> chaddr, + packet -> raw -> hlen); + + lease = find_lease (packet, packet -> shared_network, 0); + + /* Find an IP address in the host_decl that matches the + specified network. */ + if (hp) + subnet = find_host_for_network (&hp, &ip_address, + packet -> shared_network); + else + subnet = (struct subnet *)0; + + if (!subnet) { + /* We didn't find an applicable host declaration. + Just in case we may be able to dynamically assign + an address, see if there's a host declaration + that doesn't have an ip address associated with it. */ + if (hp) { + for (; hp; hp = hp -> n_ipaddr) { + if (!hp -> fixed_addr) { + host = hp; + break; + } + } + } + + if (host && (!host -> group -> allow_booting)) { + note ("Ignoring excluded BOOTP client %s", + host -> name); + return; + } + + if (host && (!host -> group -> allow_bootp)) { + note ("Ignoring BOOTP request from client %s", + host -> name); + return; + } + + /* If we've been told not to boot unknown clients, + and we didn't find any host record for this client, + ignore it. */ + if (!host && !(packet -> shared_network -> + group -> boot_unknown_clients)) { + note ("Ignoring unknown BOOTP client %s via %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); + return; + } + + /* If we've been told not to boot with bootp on this + network, ignore it. */ + if (!host && + !(packet -> shared_network -> group -> allow_bootp)) { + note ("Ignoring BOOTP request from client %s via %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); + return; + } + + /* If the packet is from a host we don't know and there + are no dynamic bootp addresses on the network it came + in on, drop it on the floor. */ + if (!(packet -> shared_network -> group -> dynamic_bootp)) { + lose: + note ("No applicable record for BOOTP host %s via %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); + return; + } + + /* If a lease has already been assigned to this client + and it's still okay to use dynamic bootp on + that lease, reassign it. */ + if (lease) { + /* If this lease can be used for dynamic bootp, + do so. */ + if ((lease -> flags & DYNAMIC_BOOTP_OK)) { + + /* If it's not a DYNAMIC_BOOTP lease, + release it before reassigning it + so that we don't get a lease + conflict. */ + if (!(lease -> flags & BOOTP_LEASE)) + release_lease (lease); + + lease -> host = host; + ack_lease (packet, lease, 0, 0); + return; + } + + /* If dynamic BOOTP is no longer allowed for + this lease, set it free. */ + release_lease (lease); + } + + /* If there are dynamic bootp addresses that might be + available, try to snag one. */ + for (lease = packet -> shared_network -> last_lease; + lease && lease -> ends <= cur_time; + lease = lease -> prev) { + if ((lease -> flags & DYNAMIC_BOOTP_OK)) { + lease -> host = host; + ack_lease (packet, lease, 0, 0); + return; + } + } + goto lose; + } + + /* Make sure we're allowed to boot this client. */ + if (hp && (!hp -> group -> allow_booting)) { + note ("Ignoring excluded BOOTP client %s", + hp -> name); + return; + } + + /* Make sure we're allowed to boot this client with bootp. */ + if (hp && (!hp -> group -> allow_bootp)) { + note ("Ignoring BOOTP request from client %s", + hp -> name); + return; + } + + /* Set up the outgoing packet... */ + memset (&outgoing, 0, sizeof outgoing); + memset (&raw, 0, sizeof raw); + outgoing.raw = &raw; + + /* 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) { + memcpy (outgoing.raw -> options, + packet -> raw -> options, DHCP_OPTION_LEN); + outgoing.packet_length = BOOTP_MIN_LEN; + } else { + /* 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 + options. */ + + memcpy (options, subnet -> group -> options, sizeof options); + + for (i = 0; i < 256; i++) { + if (hp -> group -> options [i]) + options [i] = hp -> group -> options [i]; + } + + /* 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); + if (outgoing.packet_length < BOOTP_MIN_LEN) + outgoing.packet_length = BOOTP_MIN_LEN; + } + + /* Take the fields that we care about... */ + 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); + raw.hops = packet -> raw -> hops; + raw.xid = packet -> raw -> xid; + raw.secs = packet -> raw -> secs; + raw.flags = 0; + raw.ciaddr = packet -> raw -> ciaddr; + memcpy (&raw.yiaddr, ip_address.iabuf, sizeof raw.yiaddr); + + /* Figure out the address of the next server. */ + if (hp && hp -> group -> next_server.len) + memcpy (&raw.siaddr, hp -> group -> next_server.iabuf, 4); + else if (subnet -> group -> next_server.len) + memcpy (&raw.siaddr, subnet -> group -> next_server.iabuf, 4); + else if (subnet -> interface_address.len) + memcpy (&raw.siaddr, subnet -> interface_address.iabuf, 4); + else + raw.siaddr = packet -> interface -> primary_address; + + raw.giaddr = packet -> raw -> giaddr; + if (hp -> group -> server_name) { + strncpy (raw.sname, hp -> group -> server_name, + (sizeof raw.sname) - 1); + raw.sname [(sizeof raw.sname) - 1] = 0; + } + + /* 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) { + strncpy (raw.file, hp -> group -> filename, + (sizeof raw.file) - 1); + raw.file [(sizeof raw.file) - 1] = 0; + } + + /* Set up the hardware destination address... */ + hto.htype = packet -> raw -> htype; + hto.hlen = packet -> raw -> hlen; + memcpy (hto.haddr, packet -> raw -> chaddr, hto.hlen); + + from = packet -> interface -> primary_address; + + /* Report what we're doing... */ + note ("BOOTREPLY for %s to %s (%s) via %s", + piaddr (ip_address), hp -> name, + 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); + + /* Set up the parts of the address that are in common. */ + to.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + to.sin_len = sizeof to; +#endif + memset (to.sin_zero, 0, sizeof to.sin_zero); + + /* If this was gatewayed, send it back to the gateway... */ + if (raw.giaddr.s_addr) { + 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 + /* Otherwise, broadcast it on the local network. */ + } else { + to.sin_addr.s_addr = INADDR_BROADCAST; + to.sin_port = remote_port; /* XXX */ + } + + errno = 0; + 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 new file mode 100644 index 00000000000..c595680ce6f --- /dev/null +++ b/usr.sbin/dhcp/server/confpars.c @@ -0,0 +1,1321 @@ +/* confpars.c + + Parser for dhcpd config 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 <mellon@fugue.com> 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: confpars.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" +#include "dhctoken.h" + +static TIME parsed_time; + +/* conf-file :== parameters declarations EOF + parameters :== <nil> | parameter | parameters parameter + declarations :== <nil> | declaration | declarations declaration */ + +int readconf () +{ + FILE *cfile; + char *val; + int token; + int declaration = 0; + + new_parse (path_dhcpd_conf); + + /* Set up the initial dhcp option universe. */ + initialize_universes (); + + /* Set up the global defaults... */ + root_group.default_lease_time = 43200; /* 12 hours. */ + root_group.max_lease_time = 86400; /* 24 hours. */ + root_group.bootp_lease_cutoff = MAX_TIME; + root_group.boot_unknown_clients = 1; + root_group.allow_bootp = 1; + root_group.allow_booting = 1; + + 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) + break; + declaration = parse_statement (cfile, &root_group, + ROOT_GROUP, + (struct host_decl *)0, + declaration); + } while (1); + token = next_token (&val, cfile); /* Clear the peek buffer */ + + return !warnings_occurred; +} + +/* lease-file :== lease-declarations EOF + lease-statments :== <nil> + | lease-declaration + | lease-declarations lease-declaration */ + +void read_leases () +{ + FILE *cfile; + char *val; + int token; + + new_parse (path_dhcpd_db); + + /* Open the lease file. If we can't open it, fail. The reason + for this is that although on initial startup, the absence of + a lease file is perfectly benign, if dhcpd has been running + and this file is absent, it means that dhcpd tried and failed + to rewrite the lease database. If we proceed and the + problem which caused the rewrite to fail has been fixed, but no + 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!"); + do { + token = next_token (&val, cfile); + if (token == EOF) + break; + if (token != LEASE) { + warn ("Corrupt lease file - possible data loss!"); + skip_to_semi (cfile); + } else { + struct lease *lease; + lease = parse_lease_declaration (cfile); + if (lease) + enter_lease (lease); + else + parse_warn ("possibly corrupt lease file"); + } + + } while (1); +} + +/* statement :== parameter | declaration + + parameter :== timestamp + | DEFAULT_LEASE_TIME lease_time + | MAX_LEASE_TIME lease_time + | DYNAMIC_BOOTP_LEASE_CUTOFF date + | DYNAMIC_BOOTP_LEASE_LENGTH lease_time + | BOOT_UNKNOWN_CLIENTS boolean + | ONE_LEASE_PER_CLIENT boolean + | GET_LEASE_HOSTNAMES boolean + | USE_HOST_DECL_NAME boolean + | NEXT_SERVER ip-addr-or-hostname SEMI + | option_parameter + | SERVER-IDENTIFIER ip-addr-or-hostname SEMI + | FILENAME string-parameter + | SERVER_NAME string-parameter + | hardware-parameter + | fixed-address-parameter + | ALLOW allow-deny-keyword + | DENY allow-deny-keyword + + declaration :== host-declaration + | group-declaration + | shared-network-declaration + | subnet-declaration + | VENDOR_CLASS class-declaration + | USER_CLASS class-declaration + | RANGE address-range-declaration */ + +int parse_statement (cfile, group, type, host_decl, declaration) + FILE *cfile; + struct group *group; + int type; + struct host_decl *host_decl; + int declaration; +{ + int token; + char *val; + struct shared_network *share; + char *t, *n; + struct tree *tree; + struct tree_cache *cache; + struct hardware hardware; + + switch (next_token (&val, cfile)) { + case HOST: + if (type != HOST_DECL) + parse_host_declaration (cfile, group); + else { + parse_warn ("host declarations not allowed here."); + skip_to_semi (cfile); + } + return 1; + + case GROUP: + if (type != HOST_DECL) + parse_group_declaration (cfile, group); + else { + parse_warn ("host declarations not allowed here."); + skip_to_semi (cfile); + } + return 1; + + case TIMESTAMP: + parsed_time = parse_timestamp (cfile); + break; + + case SHARED_NETWORK: + if (type == SHARED_NET_DECL || + type == HOST_DECL || + type == SUBNET_DECL) { + parse_warn ("shared-network parameters not %s.", + "allowed here"); + skip_to_semi (cfile); + break; + } + + parse_shared_net_declaration (cfile, group); + return 1; + + case SUBNET: + if (type == HOST_DECL || type == SUBNET_DECL) { + parse_warn ("subnet declarations not allowed here."); + skip_to_semi (cfile); + return 1; + } + + /* If we're in a subnet declaration, just do the parse. */ + if (group -> shared_network) { + parse_subnet_declaration (cfile, + group -> shared_network); + break; + } + + /* Otherwise, cons up a fake shared network structure + and populate it with the lone subnet... */ + + share = new_shared_network ("parse_statement"); + if (!share) + error ("No memory for shared subnet"); + share -> group = clone_group (group, "parse_statement:subnet"); + share -> group -> shared_network = share; + + parse_subnet_declaration (cfile, share); + if (share -> subnets) { + share -> interface = + share -> subnets -> interface; + + n = piaddr (share -> subnets -> net); + t = malloc (strlen (n) + 1); + if (!t) + error ("no memory for subnet name"); + strcpy (t, n); + share -> name = t; + enter_shared_network (share); + } + return 1; + + case VENDOR_CLASS: + parse_class_declaration (cfile, group, 0); + return 1; + + case USER_CLASS: + parse_class_declaration (cfile, group, 1); + return 1; + + case DEFAULT_LEASE_TIME: + parse_lease_time (cfile, &group -> default_lease_time); + break; + + case MAX_LEASE_TIME: + parse_lease_time (cfile, &group -> max_lease_time); + break; + + case DYNAMIC_BOOTP_LEASE_CUTOFF: + group -> bootp_lease_cutoff = parse_date (cfile); + break; + + case DYNAMIC_BOOTP_LEASE_LENGTH: + parse_lease_time (cfile, &group -> bootp_lease_length); + break; + + case BOOT_UNKNOWN_CLIENTS: + if (type == HOST_DECL) + parse_warn ("boot-unknown-clients not allowed here."); + group -> boot_unknown_clients = parse_boolean (cfile); + break; + + case ONE_LEASE_PER_CLIENT: + if (type == HOST_DECL) + parse_warn ("one-lease-per-client not allowed here."); + group -> one_lease_per_client = parse_boolean (cfile); + break; + + case GET_LEASE_HOSTNAMES: + if (type == HOST_DECL) + parse_warn ("get-lease-hostnames not allowed here."); + group -> get_lease_hostnames = 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 NEXT_SERVER: + tree = parse_ip_addr_or_hostname (cfile, 0); + if (!tree) + break; + cache = tree_cache (tree); + if (!tree_evaluate (cache)) + error ("next-server is not known"); + group -> next_server.len = 4; + memcpy (group -> next_server.iabuf, + cache -> value, group -> next_server.len); + parse_semi (cfile); + break; + + case OPTION: + parse_option_param (cfile, group); + 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"); + } + token = next_token (&val, cfile); + break; + + case FILENAME: + group -> filename = parse_string (cfile); + break; + + case SERVER_NAME: + group -> server_name = parse_string (cfile); + break; + + case HARDWARE: + parse_hardware_param (cfile, &hardware); + if (host_decl) + host_decl -> interface = hardware; + else + parse_warn ("hardware address parameter %s", + "not allowed here."); + break; + + case FIXED_ADDR: + cache = parse_fixed_addr_param (cfile); + if (host_decl) + host_decl -> fixed_addr = cache; + else + parse_warn ("fixed-address parameter not %s", + "allowed here."); + break; + + case RANGE: + if (type != SUBNET_DECL || !group -> subnet) { + parse_warn ("range declaration not allowed here."); + skip_to_semi (cfile); + return declaration; + } + parse_address_range (cfile, group -> subnet); + return declaration; + + case ALLOW: + parse_allow_deny (cfile, group, 1); + break; + + case DENY: + parse_allow_deny (cfile, group, 0); + break; + + default: + if (declaration) + parse_warn ("expecting a declaration."); + else + parse_warn ("expecting a parameter or declaration."); + skip_to_semi (cfile); + return declaration; + } + + if (declaration) { + parse_warn ("parameters not allowed after first declaration."); + return 1; + } + + return 0; +} + +/* allow-deny-keyword :== BOOTP + | BOOTING + | DYNAMIC_BOOTP + | UNKNOWN_CLIENTS */ + +void parse_allow_deny (cfile, group, flag) + FILE *cfile; + struct group *group; + int flag; +{ + int token; + char *val; + + token = next_token (&val, cfile); + switch (token) { + case BOOTP: + group -> allow_bootp = flag; + break; + + case BOOTING: + group -> allow_booting = flag; + break; + + case DYNAMIC_BOOTP: + group -> dynamic_bootp = flag; + break; + + case UNKNOWN_CLIENTS: + group -> boot_unknown_clients = flag; + break; + + default: + parse_warn ("expecting allow/deny key"); + skip_to_semi (cfile); + return; + } + parse_semi (cfile); +} + +/* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */ + +int parse_boolean (cfile) + FILE *cfile; +{ + int token; + char *val; + int rv; + + token = next_token (&val, cfile); + if (!strcasecmp (val, "true") + || !strcasecmp (val, "on")) + rv = 1; + else if (!strcasecmp (val, "false") + || !strcasecmp (val, "off")) + rv = 0; + else { + parse_warn ("boolean value (true/false/on/off) expected"); + skip_to_semi (cfile); + return 0; + } + parse_semi (cfile); + return rv; +} + +/* Expect a left brace; if there isn't one, skip over the rest of the + statement and return zero; otherwise, return 1. */ + +int parse_lbrace (cfile) + FILE *cfile; +{ + int token; + char *val; + + token = next_token (&val, cfile); + if (token != LBRACE) { + parse_warn ("expecting left brace."); + skip_to_semi (cfile); + return 0; + } + return 1; +} + + +/* host-declaration :== hostname RBRACE parameters declarations LBRACE */ + +void parse_host_declaration (cfile, group) + FILE *cfile; + struct group *group; +{ + char *val; + int token; + struct host_decl *host; + char *name = parse_host_name (cfile); + int declaration = 0; + + if (!name) + return; + + host = (struct host_decl *)dmalloc (sizeof (struct host_decl), + "parse_host_declaration"); + if (!host) + error ("can't allocate host decl struct %s.", name); + + host -> name = name; + host -> group = clone_group (group, "parse_host_declaration"); + + if (!parse_lbrace (cfile)) + return; + + do { + token = peek_token (&val, cfile); + if (token == RBRACE) { + token = next_token (&val, cfile); + break; + } + if (token == EOF) { + token = next_token (&val, cfile); + parse_warn ("unexpected end of file"); + break; + } + declaration = parse_statement (cfile, host -> group, + HOST_DECL, host, + declaration); + } while (1); + + if (!host -> group -> options [DHO_HOST_NAME] && + host -> group -> use_host_decl_names) { + host -> group -> options [DHO_HOST_NAME] = + new_tree_cache ("parse_host_declaration"); + if (!host -> group -> options [DHO_HOST_NAME]) + error ("can't allocate a tree cache for hostname."); + host -> group -> options [DHO_HOST_NAME] -> len = + strlen (name); + host -> group -> options [DHO_HOST_NAME] -> value = + (unsigned char *)name; + host -> group -> options [DHO_HOST_NAME] -> buf_size = + host -> group -> options [DHO_HOST_NAME] -> len; + host -> group -> options [DHO_HOST_NAME] -> timeout = + 0xFFFFFFFF; + host -> group -> options [DHO_HOST_NAME] -> tree = + (struct tree *)0; + } + + enter_host (host); +} + +/* class-declaration :== STRING LBRACE parameters declarations RBRACE +*/ + +void parse_class_declaration (cfile, group, type) + FILE *cfile; + struct group *group; + int type; +{ + char *val; + int token; + struct class *class; + int declaration = 0; + + token = next_token (&val, cfile); + if (token != STRING) { + parse_warn ("Expecting class name"); + skip_to_semi (cfile); + return; + } + + class = add_class (type, val); + if (!class) + error ("No memory for class %s.", val); + class -> group = clone_group (group, "parse_class_declaration"); + + if (!parse_lbrace (cfile)) + return; + + do { + token = peek_token (&val, cfile); + if (token == RBRACE) { + token = next_token (&val, cfile); + break; + } else if (token == EOF) { + token = next_token (&val, cfile); + parse_warn ("unexpected end of file"); + break; + } else { + declaration = parse_statement (cfile, class -> group, + CLASS_DECL, + (struct host_decl *)0, + declaration); + } + } while (1); +} + +/* shared-network-declaration :== + hostname LBRACE declarations parameters RBRACE */ + +void parse_shared_net_declaration (cfile, group) + FILE *cfile; + struct group *group; +{ + char *val; + int token; + struct shared_network *share; + char *name; + int declaration = 0; + + share = new_shared_network ("parse_shared_net_declaration"); + if (!share) + error ("No memory for shared subnet"); + share -> leases = (struct lease *)0; + share -> last_lease = (struct lease *)0; + share -> insertion_point = (struct lease *)0; + share -> next = (struct shared_network *)0; + share -> interface = (struct interface_info *)0; + share -> group = clone_group (group, "parse_shared_net_declaration"); + share -> group -> shared_network = share; + + /* Get the name of the shared network... */ + token = peek_token (&val, cfile); + if (token == STRING) { + token = next_token (&val, cfile); + + if (val [0] == 0) { + parse_warn ("zero-length shared network name"); + val = "<no-name-given>"; + } + name = malloc (strlen (val) + 1); + if (!name) + error ("no memory for shared network name"); + strcpy (name, val); + } else { + name = parse_host_name (cfile); + if (!name) + return; + } + share -> name = name; + + if (!parse_lbrace (cfile)) + return; + + do { + token = peek_token (&val, cfile); + if (token == RBRACE) { + token = next_token (&val, cfile); + if (!share -> subnets) { + parse_warn ("empty shared-network decl"); + return; + } + enter_shared_network (share); + return; + } else if (token == EOF) { + token = next_token (&val, cfile); + parse_warn ("unexpected end of file"); + break; + } + + declaration = parse_statement (cfile, share -> group, + SHARED_NET_DECL, + (struct host_decl *)0, + declaration); + } while (1); +} + +/* subnet-declaration :== + net NETMASK netmask RBRACE parameters declarations LBRACE */ + +void parse_subnet_declaration (cfile, share) + FILE *cfile; + struct shared_network *share; +{ + char *val; + int token; + struct subnet *subnet, *t; + struct iaddr iaddr; + unsigned char addr [4]; + int len = sizeof addr; + int declaration = 0; + + subnet = new_subnet ("parse_subnet_declaration"); + if (!subnet) + error ("No memory for new subnet"); + subnet -> shared_network = share; + subnet -> group = clone_group (share -> group, + "parse_subnet_declaration"); + subnet -> group -> subnet = subnet; + + /* Get the network number... */ + if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) + return; + memcpy (iaddr.iabuf, addr, len); + iaddr.len = len; + subnet -> net = iaddr; + + token = next_token (&val, cfile); + if (token != NETMASK) { + parse_warn ("Expecting netmask"); + skip_to_semi (cfile); + return; + } + + /* Get the netmask... */ + if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) + return; + memcpy (iaddr.iabuf, addr, len); + iaddr.len = len; + subnet -> netmask = iaddr; + + enter_subnet (subnet); + + if (!parse_lbrace (cfile)) + return; + + do { + token = peek_token (&val, cfile); + if (token == RBRACE) { + token = next_token (&val, cfile); + break; + } else if (token == EOF) { + token = next_token (&val, cfile); + parse_warn ("unexpected end of file"); + break; + } + declaration = parse_statement (cfile, subnet -> group, + SUBNET_DECL, + (struct host_decl *)0, + declaration); + } while (1); + + /* If this subnet supports dynamic bootp, flag it so in the + shared_network containing it. */ + if (subnet -> group -> dynamic_bootp) + share -> group -> dynamic_bootp = 1; + if (subnet -> group -> one_lease_per_client) + share -> group -> one_lease_per_client = 1; + + /* Add the subnet to the list of subnets in this shared net. */ + if (!share -> subnets) + share -> subnets = subnet; + else { + for (t = share -> subnets; + t -> next_sibling; t = t -> next_sibling) + ; + t -> next_sibling = subnet; + } +} + +/* group-declaration :== RBRACE parameters declarations LBRACE */ + +void parse_group_declaration (cfile, group) + FILE *cfile; + struct group *group; +{ + char *val; + int token; + struct group *g; + int declaration = 0; + + g = clone_group (group, "parse_group_declaration"); + + if (!parse_lbrace (cfile)) + return; + + do { + token = peek_token (&val, cfile); + if (token == RBRACE) { + token = next_token (&val, cfile); + break; + } else if (token == EOF) { + token = next_token (&val, cfile); + parse_warn ("unexpected end of file"); + break; + } + declaration = parse_statement (cfile, g, GROUP_DECL, + (struct host_decl *)0, + declaration); + } while (1); +} + +/* ip-addr-or-hostname :== ip-address | hostname + ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER + + Parse an ip address or a hostname. If uniform is zero, put in + a TREE_LIMIT node to catch hostnames that evaluate to more than + one IP address. */ + +struct tree *parse_ip_addr_or_hostname (cfile, uniform) + FILE *cfile; + int uniform; +{ + char *val; + int token; + unsigned char addr [4]; + int len = sizeof addr; + char *name; + struct tree *rv; + + token = peek_token (&val, cfile); + if (is_identifier (token)) { + name = parse_host_name (cfile); + if (!name) + return (struct tree *)0; + rv = tree_host_lookup (name); + if (!uniform) + rv = tree_limit (rv, 4); + } else if (token == NUMBER) { + if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) + return (struct tree *)0; + rv = tree_const (addr, len); + } else { + if (token != RBRACE && token != LBRACE) + token = next_token (&val, cfile); + parse_warn ("%s (%d): expecting IP address or hostname", + val, token); + if (token != SEMI) + skip_to_semi (cfile); + return (struct tree *)0; + } + + return rv; +} + + +/* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI + ip-addrs-or-hostnames :== ip-addr-or-hostname + | ip-addrs-or-hostnames ip-addr-or-hostname */ + +struct tree_cache *parse_fixed_addr_param (cfile) + FILE *cfile; +{ + char *val; + int token; + struct tree *tree = (struct tree *)0; + struct tree *tmp; + + do { + tmp = parse_ip_addr_or_hostname (cfile, 0); + if (tree) + tree = tree_concat (tree, tmp); + else + tree = tmp; + token = peek_token (&val, cfile); + if (token == COMMA) + token = next_token (&val, cfile); + } while (token == COMMA); + + if (!parse_semi (cfile)) + return (struct tree_cache *)0; + return tree_cache (tree); +} + +/* option_parameter :== identifier DOT identifier <syntax> SEMI + | identifier <syntax> SEMI + + Option syntax is handled specially through format strings, so it + would be painful to come up with BNF for it. However, it always + starts as above and ends in a SEMI. */ + +void parse_option_param (cfile, group) + FILE *cfile; + struct group *group; +{ + char *val; + int token; + unsigned char buf [4]; + char *vendor; + char *fmt; + struct universe *universe; + struct option *option; + struct tree *tree = (struct tree *)0; + struct tree *t; + + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier after option keyword."); + if (token != SEMI) + skip_to_semi (cfile); + return; + } + vendor = malloc (strlen (val) + 1); + if (!vendor) + error ("no memory for vendor token."); + strcpy (vendor, val); + token = peek_token (&val, cfile); + if (token == DOT) { + /* Go ahead and take the DOT token... */ + token = next_token (&val, cfile); + + /* The next token should be an identifier... */ + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier after '.'"); + if (token != SEMI) + skip_to_semi (cfile); + return; + } + + /* Look up the option name hash table for the specified + vendor. */ + universe = (struct universe *)hash_lookup (&universe_hash, + vendor, 0); + /* If it's not there, we can't parse the rest of the + declaration. */ + if (!universe) { + parse_warn ("no vendor named %s.", vendor); + skip_to_semi (cfile); + return; + } + } else { + /* Use the default hash table, which contains all the + standard dhcp option names. */ + val = vendor; + universe = &dhcp_universe; + } + + /* Look up the actual option info... */ + option = (struct option *)hash_lookup (universe -> hash, val, 0); + + /* If we didn't get an option structure, it's an undefined option. */ + if (!option) { + if (val == vendor) + parse_warn ("no option named %s", val); + else + parse_warn ("no option named %s for vendor %s", + val, vendor); + skip_to_semi (cfile); + return; + } + + /* Free the initial identifier token. */ + free (vendor); + + /* Parse the option data... */ + do { + /* Set a flag if this is an array of a simple type (i.e., + not an array of pairs of IP addresses, or something + like that. */ + int uniform = option -> format [1] == 'A'; + + for (fmt = option -> format; *fmt; fmt++) { + if (*fmt == 'A') + break; + switch (*fmt) { + case 'X': + token = peek_token (&val, cfile); + if (token == NUMBER_OR_NAME || + token == NUMBER) { + do { + token = next_token + (&val, cfile); + if (token != NUMBER + && token != NUMBER_OR_NAME) + goto need_number; + convert_num (buf, val, 16, 8); + tree = tree_concat + (tree, + tree_const (buf, 1)); + token = peek_token + (&val, cfile); + if (token == COLON) + token = next_token + (&val, cfile); + } while (token == COLON); + } else if (token == STRING) { + token = next_token (&val, cfile); + tree = tree_concat + (tree, + tree_const (val, + strlen (val))); + } else { + parse_warn ("expecting string %s.", + "or hexadecimal data"); + skip_to_semi (cfile); + return; + } + break; + + case 't': /* Text string... */ + token = next_token (&val, cfile); + if (token != STRING + && !is_identifier (token)) { + parse_warn ("expecting string."); + if (token != SEMI) + skip_to_semi (cfile); + return; + } + tree = tree_concat (tree, + tree_const (val, + strlen (val))); + break; + + case 'I': /* IP address or hostname. */ + t = parse_ip_addr_or_hostname (cfile, uniform); + if (!t) + return; + tree = tree_concat (tree, t); + break; + + case 'L': /* Unsigned 32-bit integer... */ + case 'l': /* Signed 32-bit integer... */ + token = next_token (&val, cfile); + if (token != NUMBER) { + need_number: + parse_warn ("expecting number."); + if (token != SEMI) + skip_to_semi (cfile); + return; + } + convert_num (buf, val, 0, 32); + tree = tree_concat (tree, tree_const (buf, 4)); + break; + case 's': /* Signed 16-bit integer. */ + case 'S': /* Unsigned 16-bit integer. */ + token = next_token (&val, cfile); + if (token != NUMBER) + goto need_number; + convert_num (buf, val, 0, 16); + tree = tree_concat (tree, tree_const (buf, 2)); + break; + case 'b': /* Signed 8-bit integer. */ + case 'B': /* Unsigned 8-bit integer. */ + token = next_token (&val, cfile); + if (token != NUMBER) + goto need_number; + convert_num (buf, val, 0, 8); + tree = tree_concat (tree, tree_const (buf, 1)); + break; + case 'f': /* Boolean flag. */ + token = next_token (&val, cfile); + if (!is_identifier (token)) { + parse_warn ("expecting identifier."); + bad_flag: + if (token != SEMI) + skip_to_semi (cfile); + return; + } + if (!strcasecmp (val, "true") + || !strcasecmp (val, "on")) + buf [0] = 1; + else if (!strcasecmp (val, "false") + || !strcasecmp (val, "off")) + buf [0] = 0; + else { + parse_warn ("expecting boolean."); + goto bad_flag; + } + tree = tree_concat (tree, tree_const (buf, 1)); + break; + default: + warn ("Bad format %c in parse_option_param.", + *fmt); + skip_to_semi (cfile); + return; + } + } + if (*fmt == 'A') { + token = peek_token (&val, cfile); + if (token == COMMA) { + token = next_token (&val, cfile); + continue; + } + break; + } + } while (*fmt == 'A'); + + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + return; + } + group -> options [option -> code] = tree_cache (tree); +} + +/* timestamp :== date + + Timestamps are actually not used in dhcpd.conf, which is a static file, + but rather in the database file and the journal file. (Okay, actually + they're not even used there yet). */ + +TIME parse_timestamp (cfile) + FILE *cfile; +{ + TIME rv; + + rv = parse_date (cfile); + return rv; +} + +/* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE + + lease_parameters :== <nil> + | lease_parameter + | lease_parameters lease_parameter + + lease_parameter :== STARTS date + | ENDS date + | TIMESTAMP date + | HARDWARE hardware-parameter + | UID hex_numbers SEMI + | HOSTNAME hostname SEMI + | CLIENT_HOSTNAME hostname SEMI + | CLASS identifier SEMI + | DYNAMIC_BOOTP SEMI */ + +struct lease *parse_lease_declaration (cfile) + FILE *cfile; +{ + char *val; + int token; + unsigned char addr [4]; + int len = sizeof addr; + int seenmask = 0; + int seenbit; + char tbuf [32]; + static struct lease lease; + + /* Zap the lease structure... */ + memset (&lease, 0, sizeof lease); + + /* Get the address for which the lease has been issued. */ + if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) + return (struct lease *)0; + memcpy (lease.ip_addr.iabuf, addr, len); + lease.ip_addr.len = len; + + if (!parse_lbrace (cfile)) + return (struct lease *)0; + + do { + token = next_token (&val, cfile); + if (token == RBRACE) + break; + else if (token == EOF) { + parse_warn ("unexpected end of file"); + break; + } + strncpy (val, tbuf, sizeof tbuf); + tbuf [(sizeof tbuf) - 1] = 0; + + /* Parse any of the times associated with the lease. */ + if (token == STARTS || token == ENDS || token == TIMESTAMP) { + TIME t; + t = parse_date (cfile); + switch (token) { + case STARTS: + seenbit = 1; + lease.starts = t; + break; + + case ENDS: + seenbit = 2; + lease.ends = t; + break; + + case TIMESTAMP: + seenbit = 4; + lease.timestamp = t; + break; + + default: + /*NOTREACHED*/ + seenbit = 0; + break; + } + } else { + switch (token) { + /* 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 = (unsigned char *) + malloc (lease.uid_len); + if (!lease.uid) { + warn ("no space for uid"); + return (struct lease *)0; + } + memcpy (lease.uid, val, lease.uid_len); + } else { + lease.uid_len = 0; + lease.uid = parse_numeric_aggregate + (cfile, (unsigned char *)0, + &lease.uid_len, ':', 16, 8); + if (!lease.uid) { + warn ("no space for uid"); + return (struct lease *)0; + } + if (lease.uid_len == 0) { + lease.uid = (unsigned char *)0; + parse_warn ("zero-length uid"); + seenbit = 0; + break; + } + } + if (!lease.uid) { + error ("No memory for lease uid"); + } + break; + + case CLASS: + seenbit = 32; + token = next_token (&val, cfile); + if (!is_identifier (token)) { + if (token != SEMI) + skip_to_semi (cfile); + return (struct lease *)0; + } + /* for now, we aren't using this. */ + break; + + case HARDWARE: + seenbit = 64; + parse_hardware_param (cfile, + &lease.hardware_addr); + break; + + case DYNAMIC_BOOTP: + seenbit = 128; + lease.flags |= BOOTP_LEASE; + break; + + case ABANDONED: + seenbit = 256; + lease.flags |= ABANDONED_LEASE; + break; + + case HOSTNAME: + seenbit = 512; + token = peek_token (&val, cfile); + if (token == STRING) + lease.hostname = parse_string (cfile); + else + lease.hostname = + parse_host_name (cfile); + if (!lease.hostname) { + seenbit = 0; + return (struct lease *)0; + } + break; + + case CLIENT_HOSTNAME: + seenbit = 1024; + token = peek_token (&val, cfile); + if (token == STRING) + lease.client_hostname = + parse_string (cfile); + else + lease.client_hostname = + parse_host_name (cfile); + break; + + default: + skip_to_semi (cfile); + seenbit = 0; + return (struct lease *)0; + } + + if (token != HARDWARE && token != STRING) { + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + return (struct lease *)0; + } + } + } + if (seenmask & seenbit) { + parse_warn ("Too many %s parameters in lease %s\n", + tbuf, piaddr (lease.ip_addr)); + } else + seenmask |= seenbit; + + } while (1); + return &lease; +} + +/* address-range-declaration :== ip-address ip-address SEMI + | DYNAMIC_BOOTP ip-address ip-address SEMI */ + +void parse_address_range (cfile, subnet) + FILE *cfile; + struct subnet *subnet; +{ + struct iaddr low, high; + unsigned char addr [4]; + int len = sizeof addr; + int token; + char *val; + int dynamic = 0; + + if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) { + token = next_token (&val, cfile); + subnet -> group -> dynamic_bootp = dynamic = 1; + } + + /* Get the bottom address in the range... */ + if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) + return; + memcpy (low.iabuf, addr, len); + low.len = len; + + /* Only one address? */ + token = peek_token (&val, cfile); + if (token == SEMI) + high = low; + else { + /* Get the top address in the range... */ + if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) + return; + memcpy (high.iabuf, addr, len); + high.len = len; + } + + token = next_token (&val, cfile); + if (token != SEMI) { + parse_warn ("semicolon expected."); + skip_to_semi (cfile); + return; + } + + /* Create the new address range... */ + new_address_range (low, high, subnet, dynamic); +} + + diff --git a/usr.sbin/dhcp/server/db.c b/usr.sbin/dhcp/server/db.c new file mode 100644 index 00000000000..538adc39c43 --- /dev/null +++ b/usr.sbin/dhcp/server/db.c @@ -0,0 +1,241 @@ +/* db.c + + Persistent database management routines for DHCPD... */ + +/* + * 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 <mellon@fugue.com> 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: 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; + +static int counting = 0; +static int count = 0; +TIME write_time; + +/* Write the specified lease to the current lease database file. */ + +int write_lease (lease) + struct lease *lease; +{ + struct tm *t; + char tbuf [64]; + int errors = 0; + + if (counting) + ++count; + errno = 0; + fprintf (db_file, "lease %s {\n", piaddr (lease -> ip_addr)); + if (errno) { + ++errors; + } + + t = gmtime (&lease -> starts); + sprintf (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); + errno = 0; + fprintf (db_file, "\tstarts %s\n", tbuf); + if (errno) { + ++errors; + } + + t = gmtime (&lease -> ends); + sprintf (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); + errno = 0; + fprintf (db_file, "\tends %s", tbuf); + if (errno) { + ++errors; + } + + if (lease -> hardware_addr.hlen) { + errno = 0; + fprintf (db_file, "\n\thardware %s %s;", + hardware_types [lease -> hardware_addr.htype], + print_hw_addr (lease -> hardware_addr.htype, + lease -> hardware_addr.hlen, + lease -> hardware_addr.haddr)); + if (errno) { + ++errors; + } + } + if (lease -> uid_len) { + int i; + errno = 0; + fprintf (db_file, "\n\tuid %2.2x", lease -> uid [0]); + if (errno) { + ++errors; + } + for (i = 1; i < lease -> uid_len; i++) { + errno = 0; + fprintf (db_file, ":%2.2x", lease -> uid [i]); + if (errno) { + ++errors; + } + } + putc (';', db_file); + } + if (lease -> flags & BOOTP_LEASE) { + errno = 0; + fprintf (db_file, "\n\tdynamic-bootp;"); + if (errno) { + ++errors; + } + } + if (lease -> flags & ABANDONED_LEASE) { + errno = 0; + fprintf (db_file, "\n\tabandoned;"); + if (errno) { + ++errors; + } + } + if (lease -> client_hostname) { + errno = 0; + fprintf (db_file, "\n\tclient-hostname \"%s\";", + lease -> client_hostname); + if (errno) { + ++errors; + } + } + if (lease -> hostname) { + errno = 0; + fprintf (db_file, "\n\thostname \"%s\";", + lease -> hostname); + if (errno) { + ++errors; + } + } + errno = 0; + fputs ("\n}\n", db_file); + if (errno) { + ++errors; + } + if (errors) + note ("write_lease: unable to write lease %s", + piaddr (lease -> ip_addr)); + return !errors; +} + +/* Commit any leases that have been written out... */ + +int commit_leases () +{ + /* Commit any outstanding writes to the lease database file. + We need to do this even if we're rewriting the file below, + just in case the rewrite fails. */ + if (fflush (db_file) == EOF) { + note ("commit_leases: unable to commit: %m"); + return 0; + } + if (fsync (fileno (db_file)) < 0) { + note ("commit_leases: unable to commit: %m"); + return 0; + } + + /* If we've written more than a thousand leases or if + we haven't rewritten the lease database in over an + hour, rewrite it now. */ + if (count > 1000 || (count && cur_time - write_time > 3600)) { + count = 0; + write_time = cur_time; + new_lease_file (); + } + return 1; +} + +void db_startup () +{ + /* Read in the existing lease file... */ + read_leases (); + + GET_TIME (&write_time); + new_lease_file (); +} + +void new_lease_file () +{ + char newfname [512]; + char backfname [512]; + TIME t; + int db_fd; + + /* If we already have an open database, close it. */ + if (db_file) { + fclose (db_file); + } + + /* Make a temporary lease file... */ + GET_TIME (&t); + sprintf (newfname, "%s.%d", path_dhcpd_db, (int)t); + db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664); + if (db_fd < 0) { + error ("Can't create new lease file: %m"); + } + if ((db_file = fdopen (db_fd, "w")) == NULL) { + error ("Can't fdopen new lease file!"); + } + + /* 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) + error ("Can't remove old lease database backup %s: %m", + backfname); + if (link (path_dhcpd_db, backfname) < 0) + 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) + error ("Can't install new lease database %s to %s: %m", + newfname, path_dhcpd_db); + + counting = 1; +} diff --git a/usr.sbin/dhcp/server/dhcp.c b/usr.sbin/dhcp/server/dhcp.c new file mode 100644 index 00000000000..6cd75f2a654 --- /dev/null +++ b/usr.sbin/dhcp/server/dhcp.c @@ -0,0 +1,1415 @@ +/* dhcp.c + + DHCP Protocol engine. */ + +/* + * 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 <mellon@fugue.com> 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: dhcp.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" + +int outstanding_pings; + +static unsigned char dhcp_message [256]; + +void dhcp (packet) + struct packet *packet; +{ + if (!locate_network (packet) && packet -> packet_type != DHCPREQUEST) + return; + + switch (packet -> packet_type) { + case DHCPDISCOVER: + dhcpdiscover (packet); + break; + + case DHCPREQUEST: + dhcprequest (packet); + break; + + case DHCPRELEASE: + dhcprelease (packet); + break; + + case DHCPDECLINE: + dhcpdecline (packet); + break; + + case DHCPINFORM: + dhcpinform (packet); + break; + + default: + break; + } +} + +void dhcpdiscover (packet) + struct packet *packet; +{ + struct lease *lease = find_lease (packet, packet -> shared_network, 0); + struct host_decl *hp; + + note ("DHCPDISCOVER from %s via %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); + + /* Sourceless packets don't make sense here. */ + if (!packet -> shared_network) { + note ("Packet from unknown subnet: %s", + inet_ntoa (packet -> raw -> giaddr)); + return; + } + + /* If we didn't find a lease, try to allocate one... */ + if (!lease) { + lease = packet -> shared_network -> last_lease; + + /* If there are no leases in that subnet that have + expired, we have nothing to offer this client. */ + if (!lease || lease -> ends > cur_time) { + note ("no free leases on subnet %s", + packet -> shared_network -> name); + return; + } + + /* 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; + } + + /* Try to find a host_decl that matches the client + identifier or hardware address on the packet, and + has no fixed IP address. If there is one, hang + it off the lease so that its option definitions + can be used. */ + if (((packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len + != 0) && + ((hp = find_hosts_by_uid + (packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].data, + packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len)) + != (struct host_decl *)0)) || + ((hp = find_hosts_by_haddr (packet -> raw -> htype, + packet -> raw -> chaddr, + packet -> raw -> hlen)) + != (struct host_decl *)0)) { + for (; hp; hp = hp -> n_ipaddr) { + if (!hp -> fixed_addr) { + lease -> host = hp; + break; + } + } + } else { + lease -> host = (struct host_decl *)0; + } + } + + /* If this subnet won't boot unknown clients, ignore the + request. */ + if (!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)); + } else if (lease -> host && + !lease -> host -> group -> allow_booting) { + note ("Declining to boot client %s", + lease -> host -> name); + } else + ack_lease (packet, lease, DHCPOFFER, cur_time + 120); +} + +void dhcprequest (packet) + struct packet *packet; +{ + struct lease *lease; + struct iaddr cip; + struct subnet *subnet; + int ours = 0; + + if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) { + cip.len = 4; + memcpy (cip.iabuf, + packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data, + 4); + } else { + cip.len = 4; + memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4); + } + subnet = find_subnet (cip); + + /* Find the lease that matches the address requested by the + client. */ + + if (subnet) + lease = find_lease (packet, subnet -> shared_network, &ours); + else + lease = (struct lease *)0; + + note ("DHCPREQUEST for %s from %s via %s", + piaddr (cip), + 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 a client on a given network REQUESTs a lease on an + address on a different network, NAK it. If the Requested + Address option was used, the protocol says that it must + have been broadcast, so we can trust the source network + information. + + If ciaddr was specified and Requested Address was not, then + we really only know for sure what network a packet came from + if it came through a BOOTP gateway - if it came through an + IP router, we'll just have to assume that it's cool. + + If we don't think we know where the packet came from, it + came through a gateway from an unknown network, so it's not + from a RENEWING client. If we recognize the network it + *thinks* it's on, we can NAK it even though we don't + recognize the network it's *actually* on; otherwise we just + have to ignore it. + + We don't currently try to take advantage of access to the + raw packet, because it's not available on all platforms. + So a packet that was unicast to us through a router from a + RENEWING client is going to look exactly like a packet that + was broadcast to us from an INIT-REBOOT client. + + Since we can't tell the difference between these two kinds + of packets, if the packet appears to have come in off the + local wire, we have to treat it as if it's a RENEWING + client. This means that we can't NAK a RENEWING client on + the local wire that has a bogus address. The good news is + that we won't ACK it either, so it should revert to INIT + state and send us a DHCPDISCOVER, which we *can* work with. + + Because we can't detect that a RENEWING client is on the + wrong wire, it's going to sit there trying to renew until + it gets to the REBIND state, when we *can* NAK it because + the packet will get to us through a BOOTP gateway. We + shouldn't actually see DHCPREQUEST packets from RENEWING + clients on the wrong wire anyway, since their idea of their + local router will be wrong. In any case, the protocol + doesn't really allow us to NAK a DHCPREQUEST from a + RENEWING client, so we can punt on this issue. */ + + if (!packet -> shared_network || + (packet -> raw -> ciaddr.s_addr && + packet -> raw -> giaddr.s_addr) || + packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) { + + /* 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) { + nak_lease (packet, &cip); + return; + } + /* Otherwise, ignore it. */ + return; + } + + /* If we do know where it came from and it asked for an + address that is not on that shared network, nak it. */ + subnet = find_grouped_subnet (packet -> shared_network, cip); + if (!subnet) { + nak_lease (packet, &cip); + return; + } + } + + /* If we found a lease for the client but it's not the one the + client asked for, don't send it - some other server probably + made the cut. */ + 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. */ + if (ours) + nak_lease (packet, &cip); + return; + } + + /* If the address the client asked for is ours, but it wasn't + available for the client, NAK it. */ + if (!lease && ours) { + nak_lease (packet, &cip); + 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 && + ((lease -> uid_len && lease -> uid_len == + packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len && + !memcmp (packet -> options + [DHO_DHCP_CLIENT_IDENTIFIER].data, + lease -> uid, lease -> uid_len)) || + (lease -> hardware_addr.hlen == packet -> raw -> hlen && + lease -> hardware_addr.htype == packet -> raw -> htype && + !memcmp (lease -> hardware_addr.haddr, + packet -> raw -> chaddr, + packet -> raw -> hlen)))) { + ack_lease (packet, lease, DHCPACK, 0); + return; + } +} + +void dhcprelease (packet) + struct packet *packet; +{ + struct lease *lease; + struct iaddr cip; + int i; + + /* DHCPRELEASE must not specify address in requested-address + option, but old protocol specs weren't explicit about this, + so let it go. */ + if (packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) { + note ("DHCPRELEASE from %s specified requested-address.", + print_hw_addr (packet -> raw -> htype, + packet -> raw -> hlen, + packet -> raw -> chaddr)); + } + + i = DHO_DHCP_CLIENT_IDENTIFIER; + 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) { + 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) { + release_lease (lease); + } +} + +void dhcpdecline (packet) + struct packet *packet; +{ + struct lease *lease; + struct iaddr cip; + + /* DHCPDECLINE must specify address. */ + if (!packet -> options [DHO_DHCP_REQUESTED_ADDRESS].len) { + return; + } + + cip.len = 4; + memcpy (cip.iabuf, + packet -> options [DHO_DHCP_REQUESTED_ADDRESS].data, 4); + lease = find_lease_by_ip_addr (cip); + + note ("DHCPDECLINE on %s from %s via %s", + piaddr (cip), + 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 we found a lease, mark it as unusable and complain. */ + if (lease) { + abandon_lease (lease, "declined."); + } +} + +void dhcpinform (packet) + struct packet *packet; +{ + note ("DHCPINFORM from %s", + inet_ntoa (packet -> raw -> ciaddr)); +} + +void nak_lease (packet, cip) + struct packet *packet; + struct iaddr *cip; +{ + struct sockaddr_in to; + struct in_addr from; + int result; + struct dhcp_packet raw; + unsigned char nak = DHCPNAK; + struct packet outgoing; + struct hardware hto; + + struct tree_cache *options [256]; + struct tree_cache dhcpnak_tree; + struct tree_cache dhcpmsg_tree; + + memset (options, 0, sizeof options); + memset (&outgoing, 0, sizeof outgoing); + memset (&raw, 0, sizeof raw); + outgoing.raw = &raw; + + /* Set DHCP_MESSAGE_TYPE to DHCPNAK */ + options [DHO_DHCP_MESSAGE_TYPE] = &dhcpnak_tree; + options [DHO_DHCP_MESSAGE_TYPE] -> value = &nak; + options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof nak; + options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof nak; + options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF; + options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0; + + /* 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] -> 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; + + /* Set up the option buffer... */ + outgoing.packet_length = + cons_options (packet, outgoing.raw, options, 0, 0, 0); + +/* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ + raw.siaddr = packet -> interface -> primary_address; + raw.giaddr = packet -> raw -> giaddr; + memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr); + raw.hlen = packet -> raw -> hlen; + raw.htype = packet -> raw -> htype; + + raw.xid = packet -> raw -> xid; + raw.secs = packet -> raw -> secs; + raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST); + raw.hops = packet -> raw -> hops; + raw.op = BOOTREPLY; + + /* Report what we're sending... */ + note ("DHCPNAK on %s to %s via %s", + piaddr (*cip), + 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); + + + +#ifdef DEBUG_PACKET + dump_packet (packet); + dump_raw ((unsigned char *)packet -> raw, packet -> packet_length); + dump_packet (&outgoing); + dump_raw ((unsigned char *)&raw, outgoing.packet_length); +#endif + + hto.htype = packet -> raw -> htype; + hto.hlen = packet -> raw -> hlen; + memcpy (hto.haddr, packet -> raw -> chaddr, hto.hlen); + + /* 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; + + /* Make sure that the packet is at least as big as a BOOTP packet. */ + if (outgoing.packet_length < BOOTP_MIN_LEN) + outgoing.packet_length = BOOTP_MIN_LEN; + + /* If this was gatewayed, send it back to the gateway. + Otherwise, broadcast it on the local network. */ + if (raw.giaddr.s_addr) { + 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 + } else { + to.sin_addr.s_addr = htonl (INADDR_BROADCAST); + to.sin_port = remote_port; + } + + errno = 0; + 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; + TIME when; +{ + struct lease lt; + struct lease_state *state; + TIME lease_time; + TIME offered_lease_time; + + struct class *vendor_class, *user_class; + int i; + + /* If we're already acking this lease, don't do it again. */ + if (lease -> state) { + note ("already acking lease %s", piaddr (lease -> ip_addr)); + return; + } + + if (packet -> options [DHO_DHCP_CLASS_IDENTIFIER].len) { + vendor_class = + find_class (0, + packet -> + options [DHO_DHCP_CLASS_IDENTIFIER].data, + packet -> + options [DHO_DHCP_CLASS_IDENTIFIER].len); + } else { + vendor_class = (struct class *)0; + } + + if (packet -> options [DHO_DHCP_USER_CLASS_ID].len) { + user_class = + find_class (1, + packet -> + options [DHO_DHCP_USER_CLASS_ID].data, + packet -> + options [DHO_DHCP_USER_CLASS_ID].len); + } else { + user_class = (struct class *)0; + } + + /* + * If there is not a specific host entry, and either the + * vendor class or user class (if they exist) deny booting, + * then bug out. + */ + if (!lease -> host) { + if (vendor_class && !vendor_class -> group -> allow_booting) { + debug ("Booting denied by vendor class"); + return; + } + + if (user_class && !user_class -> group -> allow_booting) { + debug ("Booting denied by user class"); + return; + } + } + + /* Allocate a lease state structure... */ + state = new_lease_state ("ack_lease"); + if (!state) + error ("unable to allocate lease state!"); + memset (state, 0, sizeof *state); + + /* Replace the old lease hostname with the new one, if it's changed. */ + if (packet -> options [DHO_HOST_NAME].len && + lease -> client_hostname && + (strlen (lease -> client_hostname) == + packet -> options [DHO_HOST_NAME].len) && + !memcmp (lease -> client_hostname, + packet -> options [DHO_HOST_NAME].data, + packet -> options [DHO_HOST_NAME].len)) { + } else if (packet -> options [DHO_HOST_NAME].len) { + if (lease -> client_hostname) + free (lease -> client_hostname); + lease -> client_hostname = + malloc (packet -> options [DHO_HOST_NAME].len + 1); + if (!lease -> client_hostname) + error ("no memory for client hostname.\n"); + memcpy (lease -> client_hostname, + packet -> options [DHO_HOST_NAME].data, + packet -> options [DHO_HOST_NAME].len); + lease -> client_hostname + [packet -> options [DHO_HOST_NAME].len] = 0; + } else if (lease -> client_hostname) { + free (lease -> client_hostname); + lease -> client_hostname = 0; + } + + /* 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; + else if (user_class && user_class -> group -> filename) + state -> filename = user_class -> group -> filename; + else if (vendor_class && vendor_class -> group -> filename) + state -> filename = vendor_class -> group -> filename; + else state -> filename = (char *)0; + + /* Choose a server name as above. */ + if (lease -> host && lease -> host -> group -> server_name) + state -> server_name = lease -> host -> group -> server_name; + else if (user_class && user_class -> group -> server_name) + 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 state -> server_name = (char *)0; + + /* At this point, we have a lease that we can offer the client. + Now we construct a lease structure that contains what we want, + and call supersede_lease to do the right thing with it. */ + + memset (<, 0, sizeof lt); + + /* Use the ip address of the lease that we finally found in + the database. */ + lt.ip_addr = lease -> ip_addr; + + /* Start now. */ + lt.starts = cur_time; + + /* Figure out how long a lease to assign. If this is a + dynamic BOOTP lease, its duration must be infinite. */ + if (offer) { + if (packet -> options [DHO_DHCP_LEASE_TIME].len == 4) { + lease_time = getULong + (packet -> options [DHO_DHCP_LEASE_TIME].data); + + /* 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); + } + + state -> offered_expiry = cur_time + lease_time; + if (when) + lt.ends = when; + else + lt.ends = state -> offered_expiry; + } else { + if (lease -> host && + lease -> host -> group -> bootp_lease_length) + lt.ends = (cur_time + + lease -> host -> + group -> bootp_lease_length); + else if (lease -> subnet -> group -> bootp_lease_length) + lt.ends = (cur_time + + lease -> subnet -> + group -> bootp_lease_length); + else if (lease -> host && + lease -> host -> group -> bootp_lease_cutoff) + lt.ends = lease -> host -> group -> bootp_lease_cutoff; + else + lt.ends = (lease -> subnet -> + group -> bootp_lease_cutoff); + state -> offered_expiry = lt.ends; + lt.flags = BOOTP_LEASE; + } + + lt.timestamp = cur_time; + + /* Record the uid, if given... */ + i = DHO_DHCP_CLIENT_IDENTIFIER; + if (packet -> options [i].len) { + if (packet -> options [i].len <= sizeof lt.uid_buf) { + memcpy (lt.uid_buf, packet -> options [i].data, + packet -> options [i].len); + lt.uid = lt.uid_buf; + lt.uid_max = sizeof lt.uid_buf; + lt.uid_len = packet -> options [i].len; + } else { + lt.uid_max = lt.uid_len = packet -> options [i].len; + lt.uid = (unsigned char *)malloc (lt.uid_max); + if (!lt.uid) + error ("can't allocate memory for large uid."); + memcpy (lt.uid, + packet -> options [i].data, lt.uid_len); + } + } + + lt.host = lease -> host; + lt.subnet = lease -> subnet; + lt.shared_network = lease -> shared_network; + + /* Don't call supersede_lease on a mocked-up lease. */ + if (lease -> flags & STATIC_LEASE) { + /* Copy the hardware address into the static lease + structure. */ + 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); + } 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); + + /* Install the new information about this lease in the + database. If this is a DHCPACK or a dynamic BOOTREPLY + and we can't write the lease, don't ACK it (or BOOTREPLY + it) either. */ + + if (!(supersede_lease (lease, <, !offer || offer == DHCPACK) + || (offer && offer != DHCPACK))) + return; + } + + /* Remember the interface on which the packet arrived. */ + state -> ip = packet -> interface; + + /* Set a flag if this client is a lame Microsoft client that NUL + terminates string options and expects us to do likewise. */ + if (packet -> options [DHO_HOST_NAME].data && + packet -> options [DHO_HOST_NAME].data + [packet -> options [DHO_HOST_NAME].len - 1] == '\0') + lease -> flags |= MS_NULL_TERMINATION; + else + lease -> flags &= ~MS_NULL_TERMINATION; + + /* Remember the giaddr, xid, secs, flags and hops. */ + state -> giaddr = packet -> raw -> giaddr; + state -> ciaddr = packet -> raw -> ciaddr; + state -> xid = packet -> raw -> xid; + state -> secs = packet -> raw -> secs; + state -> bootp_flags = packet -> raw -> flags; + state -> hops = packet -> raw -> hops; + state -> offer = offer; + + /* Figure out what options to send to the client: */ + + /* Start out with the subnet options... */ + memcpy (state -> options, + lease -> subnet -> group -> options, + sizeof state -> options); + + /* Vendor and user classes are only supported for DHCP clients. */ + if (state -> offer) { + /* If we have a vendor class, install those options, + superseding any subnet options. */ + if (vendor_class) { + for (i = 0; i < 256; i++) + if (vendor_class -> group -> options [i]) + state -> options [i] = + (vendor_class -> group -> + options [i]); + } + + /* If we have a user class, install those options, + superseding any subnet and vendor class options. */ + if (user_class) { + for (i = 0; i < 256; i++) + if (user_class -> group -> options [i]) + state -> options [i] = + (user_class -> group -> + options [i]); + } + + } + + /* If we have a host_decl structure, install the associated + options, superseding anything that's in the way. */ + if (lease -> host) { + for (i = 0; i < 256; i++) + if (lease -> host -> group -> options [i]) + state -> options [i] = (lease -> host -> + group -> options [i]); + } + + /* If we didn't get a hostname from an option somewhere, see if + we can get one from the lease. */ + i = DHO_HOST_NAME; + if (!state -> options [i] && lease -> hostname) { + state -> options [i] = new_tree_cache ("hostname"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + (unsigned char *)lease -> hostname; + state -> options [i] -> len = strlen (lease -> hostname); + state -> options [i] -> buf_size = state -> options [i] -> len; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + } + + /* Now, if appropriate, put in DHCP-specific options that + override those. */ + if (state -> offer) { + i = DHO_DHCP_MESSAGE_TYPE; + state -> options [i] = new_tree_cache ("message-type"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = &state -> offer; + state -> options [i] -> len = sizeof state -> offer; + state -> options [i] -> buf_size = sizeof state -> offer; + state -> options [i] -> timeout = 0xFFFFFFFF; + 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; + + /* 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); + else + offered_lease_time = + state -> offered_expiry - cur_time; + + putULong ((unsigned char *)&state -> expiry, + offered_lease_time); + i = DHO_DHCP_LEASE_TIME; + state -> options [i] = new_tree_cache ("lease-expiry"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + (unsigned char *)&state -> expiry; + state -> options [i] -> len = sizeof state -> expiry; + state -> options [i] -> buf_size = sizeof state -> expiry; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + + /* Renewal time is lease time * 0.5. */ + offered_lease_time /= 2; + putULong ((unsigned char *)&state -> renewal, + offered_lease_time); + i = DHO_DHCP_RENEWAL_TIME; + state -> options [i] = new_tree_cache ("renewal-time"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + (unsigned char *)&state -> renewal; + state -> options [i] -> len = sizeof state -> renewal; + state -> options [i] -> buf_size = sizeof state -> renewal; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + + + /* Rebinding time is lease time * 0.875. */ + offered_lease_time += (offered_lease_time / 2 + + offered_lease_time / 4); + putULong ((unsigned char *)&state -> rebind, + offered_lease_time); + i = DHO_DHCP_REBINDING_TIME; + state -> options [i] = new_tree_cache ("rebind-time"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + (unsigned char *)&state -> rebind; + state -> options [i] -> len = sizeof state -> rebind; + state -> options [i] -> buf_size = sizeof state -> rebind; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + + /* If we used the vendor class the client specified, we + have to return it. */ + if (vendor_class) { + i = DHO_DHCP_CLASS_IDENTIFIER; + state -> options [i] = + new_tree_cache ("class-identifier"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + (unsigned char *)vendor_class -> name; + state -> options [i] -> len = + strlen (vendor_class -> name); + state -> options [i] -> buf_size = + state -> options [i] -> len; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + } + + /* If we used the user class the client specified, we + have to return it. */ + if (user_class) { + i = DHO_DHCP_USER_CLASS_ID; + state -> options [i] = new_tree_cache ("user-class"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + (unsigned char *)user_class -> name; + state -> options [i] -> len = + strlen (user_class -> name); + state -> options [i] -> buf_size = + state -> options [i] -> len; + state -> options [i] -> timeout = 0xFFFFFFFF; + state -> options [i] -> tree = (struct tree *)0; + } + } + + /* Use the subnet mask from the subnet declaration if no other + mask has been provided. */ + i = DHO_SUBNET_MASK; + if (!state -> options [i]) { + state -> options [i] = new_tree_cache ("subnet-mask"); + state -> options [i] -> flags = TC_TEMPORARY; + state -> options [i] -> value = + lease -> subnet -> netmask.iabuf; + state -> options [i] -> len = lease -> subnet -> netmask.len; + state -> options [i] -> buf_size = + lease -> subnet -> netmask.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); +#endif + + lease -> state = state; + + /* If this is a DHCPOFFER, ping the lease address before actually + sending the offer. */ + if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE)) { + icmp_echorequest (&lease -> ip_addr); + add_timeout (cur_time + 1, lease_ping_timeout, lease); + ++outstanding_pings; + } else { + dhcp_reply (lease); + } +} + +void dhcp_reply (lease) + struct lease *lease; +{ + int bufs = 0; + int packet_length; + struct dhcp_packet raw; + struct sockaddr_in to; + struct in_addr from; + struct hardware hto; + int result; + int i; + struct lease_state *state = lease -> state; + int nulltp, bootpp; + + if (!state) + error ("dhcp_reply was supplied lease with no state!"); + + /* Compose a response for the client... */ + memset (&raw, 0, sizeof raw); + + /* 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); + 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); + else + bufs |= 2; /* XXX */ + + memcpy (raw.chaddr, lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen); + raw.hlen = lease -> hardware_addr.hlen; + raw.htype = lease -> hardware_addr.htype; + + /* See if this is a Microsoft client that NUL-terminates its + strings and expects us to do likewise... */ + if (lease -> flags & MS_NULL_TERMINATION) + nulltp = 1; + else + nulltp = 0; + + /* See if this is a bootp client... */ + if (state -> offer) + bootpp = 0; + else + bootpp = 1; + + /* Insert such options as will fit into the buffer. */ + packet_length = cons_options ((struct packet *)0, &raw, + state -> options, bufs, nulltp, bootpp); + + /* Having done the cons_options(), we can release the tree_cache + entries. */ + for (i = 0; i < 256; i++) { + if (state -> options [i] && + state -> options [i] -> flags & TC_TEMPORARY) + free_tree_cache (state -> options [i], "dhcp_reply"); + } + + memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr); + memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4); + + /* Figure out the address of the next server. */ + if (lease -> host && lease -> host -> group -> next_server.len) + memcpy (&raw.siaddr, + lease -> host -> group -> next_server.iabuf, 4); + else if (lease -> subnet -> group -> next_server.len) + memcpy (&raw.siaddr, + lease -> subnet -> group -> next_server.iabuf, 4); + else if (lease -> subnet -> interface_address.len) + memcpy (&raw.siaddr, + lease -> subnet -> interface_address.iabuf, 4); + else + raw.siaddr = state -> ip -> primary_address; + + raw.giaddr = state -> giaddr; + + raw.xid = state -> xid; + raw.secs = state -> secs; + raw.flags = state -> bootp_flags; + raw.hops = state -> hops; + raw.op = BOOTREPLY; + + /* Say what we're doing... */ + note ("%s on %s to %s via %s", + (state -> offer + ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER") + : "BOOTREPLY"), + piaddr (lease -> ip_addr), + print_hw_addr (lease -> hardware_addr.htype, + lease -> hardware_addr.hlen, + lease -> hardware_addr.haddr), + state -> giaddr.s_addr + ? inet_ntoa (state -> giaddr) + : state -> ip -> name); + + /* Set up the hardware address... */ + hto.htype = lease -> hardware_addr.htype; + hto.hlen = lease -> hardware_addr.hlen; + memcpy (hto.haddr, lease -> hardware_addr.haddr, hto.hlen); + + 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 = state -> ip -> primary_address; + +#ifdef DEBUG_PACKET + dump_raw ((unsigned char *)&raw, packet_length); +#endif + + /* Make sure outgoing packets are at least as big + as a BOOTP packet. */ + if (packet_length < BOOTP_MIN_LEN) + packet_length = BOOTP_MIN_LEN; + + /* If this was gatewayed, send it back to the gateway... */ + if (raw.giaddr.s_addr) { + 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"); + + free_lease_state (state, "dhcp_reply fallback 1"); + lease -> state = (struct lease_state *)0; + return; +#endif + + /* 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 + + /* Otherwise, broadcast it on the local network. */ + } else { + to.sin_addr.s_addr = htonl (INADDR_BROADCAST); + to.sin_port = remote_port; /* XXX */ + } + + + result = send_packet (state -> ip, + (struct packet *)0, &raw, packet_length, + raw.siaddr, &to, &hto); + if (result < 0) + warn ("sendpkt: %m"); + + free_lease_state (state, "dhcp_reply"); + lease -> state = (struct lease_state *)0; +} + +struct lease *find_lease (packet, share, ours) + struct packet *packet; + struct shared_network *share; + int *ours; +{ + struct lease *uid_lease, *ip_lease, *hw_lease; + struct lease *lease = (struct lease *)0; + struct iaddr cip; + struct host_decl *hp, *host = (struct host_decl *)0; + struct lease *fixed_lease; + int i; + + /* 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) { + /* First, try to find a fixed host entry for the specified + client identifier... */ + hp = find_hosts_by_uid (packet -> options + [DHO_DHCP_CLIENT_IDENTIFIER].data, + packet -> options + [DHO_DHCP_CLIENT_IDENTIFIER].len); + if (hp) { + host = hp; + fixed_lease = mockup_lease (packet, share, hp); + uid_lease = (struct lease *)0; + } else { + uid_lease = find_lease_by_uid + (packet -> options + [DHO_DHCP_CLIENT_IDENTIFIER].data, + packet -> options + [DHO_DHCP_CLIENT_IDENTIFIER].len); + /* Find the lease matching this uid that's on the + network the packet came from (if any). */ + for (; uid_lease; uid_lease = uid_lease -> n_uid) + if (uid_lease -> shared_network == share) + break; + fixed_lease = (struct lease *)0; + if (uid_lease && + (uid_lease -> flags & ABANDONED_LEASE)) + uid_lease = (struct lease *)0; + } + } else { + uid_lease = (struct lease *)0; + fixed_lease = (struct lease *)0; + } + + /* If we didn't find a fixed lease using the uid, try doing + it with the hardware address... */ + if (!fixed_lease) { + hp = find_hosts_by_haddr (packet -> raw -> htype, + packet -> raw -> chaddr, + packet -> raw -> hlen); + if (hp) { + host = hp; /* Save it for later. */ + fixed_lease = mockup_lease (packet, share, hp); + } + } + + /* 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, + packet -> raw -> hlen); + /* Find the lease that's on the network the packet came from + (if any). */ + for (; hw_lease; hw_lease = hw_lease -> n_hw) { + if (hw_lease -> shared_network == share) { + if (hw_lease -> flags & ABANDONED_LEASE) + continue; + if (packet -> packet_type) + break; + if (hw_lease -> flags & + (BOOTP_LEASE | DYNAMIC_BOOTP_OK)) + break; + } + } + + /* 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); + 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 + ip_lease = (struct lease *)0; + + /* If ip_lease is valid at this point, set ours to one, so that + even if we choose a different lease, we know that the address + the client was requesting was ours, and thus we can NAK it. */ + if (ip_lease && 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))) + ip_lease = (struct lease *)0; + + /* Toss ip_lease if it hasn't yet expired and the uid doesn't + match */ + if (ip_lease && + ip_lease -> ends >= cur_time && + ip_lease -> uid && 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; + } + ip_lease = (struct lease *)0; + } + + /* 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 + a uid) we let the client get away with it. */ + if (hw_lease && + hw_lease -> ends >= cur_time && + hw_lease -> uid && + packet -> options [DHO_DHCP_CLIENT_IDENTIFIER].len && + hw_lease != uid_lease) + 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 == 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; + + /* 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"); + } + + /* Now eliminate leases that are on the wrong network... */ + if (ip_lease && + (share != ip_lease -> shared_network)) { + release_lease (ip_lease); + ip_lease = (struct lease *)0; + } + if (uid_lease && + (share != uid_lease -> shared_network)) { + release_lease (uid_lease); + uid_lease = (struct lease *)0; + } + if (hw_lease && + (share != hw_lease -> shared_network)) { + release_lease (hw_lease); + hw_lease = (struct lease *)0; + } + + /* At this point, if fixed_lease is nonzero, we can assign it to + this client. */ + if (fixed_lease) { + lease = fixed_lease; + } + + /* If we got a lease that matched the ip address and don't have + a better offer, use that; otherwise, release it. */ + if (ip_lease) { + if (lease) { + release_lease (ip_lease); + } else { + lease = ip_lease; + lease -> host = (struct host_decl *)0; + } + } + + /* If we got a lease that matched the client identifier, we may want + to use it, but if we already have a lease we like, we must free + the lease that matched the client identifier. */ + if (uid_lease) { + if (lease) { + release_lease (uid_lease); + } else { + lease = uid_lease; + lease -> host = (struct host_decl *)0; + } + } + + /* The lease that matched the hardware address is treated likewise. */ + if (hw_lease) { + if (lease) { + release_lease (hw_lease); + } else { + lease = hw_lease; + lease -> host = (struct host_decl *)0; + } + } + + /* If we found a host_decl but no matching address, try to + find a host_decl that has no address, and if there is one, + hang it off the lease so that we can use the supplied + options. */ + if (lease && host && !lease -> host) { + for (; host; host = host -> n_ipaddr) { + if (!host -> fixed_addr) { + lease -> host = host; + break; + } + } + } + + return lease; +} + +/* Search the provided host_decl structure list for an address that's on + the specified shared network. If one is found, mock up and return a + lease structure for it; otherwise return the null pointer. */ + +struct lease *mockup_lease (packet, share, hp) + struct packet *packet; + struct shared_network *share; + struct host_decl *hp; +{ + static struct lease mock; + + mock.subnet = find_host_for_network (&hp, &mock.ip_addr, share); + if (!mock.subnet) + return (struct lease *)0; + mock.next = mock.prev = (struct lease *)0; + mock.shared_network = mock.subnet -> shared_network; + mock.host = hp; + + if (hp -> group -> options [DHO_DHCP_CLIENT_IDENTIFIER]) { + mock.uid = hp -> group -> + options [DHO_DHCP_CLIENT_IDENTIFIER] -> value; + mock.uid_len = hp -> group -> + options [DHO_DHCP_CLIENT_IDENTIFIER] -> len; + } else { + mock.uid = (unsigned char *)0; + mock.uid_len = 0; + } + + mock.hardware_addr = hp -> interface; + mock.starts = mock.timestamp = mock.ends = MIN_TIME; + mock.flags = STATIC_LEASE; + return &mock; +} diff --git a/usr.sbin/dhcp/server/dhcpd.8 b/usr.sbin/dhcp/server/dhcpd.8 new file mode 100644 index 00000000000..77d3641fa70 --- /dev/null +++ b/usr.sbin/dhcp/server/dhcpd.8 @@ -0,0 +1,333 @@ +.\" dhcpd.8 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 dhcpd 8 +.SH NAME +dhcpd - Dynamic Host Configuration Protocol Server +.SH SYNOPSIS +.B dhcpd +[ +.B -p +.I port +] +[ +.B -f +] +[ +.B -d +] +[ +.B -q +] +[ +.B -cf +.I config-file +] +[ +.B -lf +.I lease-file +] +[ +.I if0 +[ +.I ...ifN +] +] +.SH DESCRIPTION +The Internet Software Consortium DHCP Server, dhcpd, implements the +Dynamic Host Configuration Protocol (DHCP) and the Internet Bootstrap +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 NetBSD 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 +administrator to be automatically assigned a new IP address out of a +pool of IP addresses for its network. In order for this to work, the +network administrator allocates address pools in each subnet and +enters them into the dhcpd.conf(5) file. +.PP +On startup, dhcpd reads the +.IR dhcpd.conf +file and stores a list of available addresses on each subnet in +memory. When a client requests an address using the DHCP protocol, +dhcpd allocates an address for it. Each client is assigned a lease, +which expires after an amount of time chosen by the administrator (by +default, one day). Before leases expire, the clients to which leases +are assigned are expected to renew them in order to continue to use +the addresses. Once a lease has expired, the client to which that +lease was assigned is no longer permitted to use the leased IP +address. +.PP +In order to keep track of leases across system reboots and server +restarts, dhcpd keeps a list of leases it has assigned in the +dhcpd.leases(5) file. Before dhcpd grants a lease to a host, it +records the lease in this file and makes sure that the contents of the +file are flushed to disk. This ensures that even in the event of a +system crash, dhcpd will not forget about a lease that it has +assigned. On startup, after reading the dhcpd.conf file, dhcpd +reads the dhcpd.leases file to refresh its memory about what leases +have been assigned. +.PP +New leases are appended to the end of the dhcpd.leases +file. In order to prevent the file from becoming arbitrarily large, +from time to time dhcpd creates a new dhcpd.leases file from its +in-core lease database. Once this file has been written to disk, the +old file is renamed +.IR dhcpd.leases~ , +and the new file is renamed dhcpd.leases. If the system crashes in +the middle of this process, whichever dhcpd.leases file remains will +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 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 +the network administrator may set an earlier cutoff date or a shorter +lease length for BOOTP leases if that makes sense. +.PP +BOOTP clients may also be served in the old standard way, which is to +simply provide a declaration in the dhcpd.conf file for each +BOOTP client, permanently assigning an address to each client. +.PP +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 , +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. +.PP +Note: We get a lot of complaints about this. We realize that it would +be nice if one could send a SIGHUP to the server and have it reload +the database. This is not technically impossible, but it would +require a great deal of work, our resources are extremely limited, and +they can be better spent elsewhere. So please don't complain about +this on the mailing list unless you're prepared to fund a project to +implement this feature, or prepared to do it yourself. +.SH COMMAND LINE +.PP +The names of the network interfaces on which dhcpd should listen for +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, 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), +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. +.PP +To run dhcpd as a foreground process, rather than allowing it to run +as a daemon in the background, the +.B -f +flag should be specified. This is useful when running dhcpd under a +debugger, or when running it out of inittab on System V systems. +.PP +To have dhcpd log to the standard error descriptor, specify the +.B -d +flag. This can be useful for debugging, and also at sites where a +complete log of all dhcp activity must be kept but syslogd is not +reliable or otherwise cannot be used. Normally, dhcpd will log all +output using the syslog(3) function with the log facility set to +LOG_DAEMON. +.PP +Dhcpd can be made to use an alternate configuration file with the +.B -cf +flag, or an alternate lease file with the +.B -lf +flag. Because of the importance of using the same lease database at +all times when running dhcpd in production, these options should be +used \fBonly\fR for testing lease files or database files in a +non-production environment. +.PP +When starting dhcpd up from a system startup script (e.g., /etc/rc), +it may not be desirable to print out the entire copyright message on +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 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. +.PP +.SH Subnets +dhcpd needs to know the subnet numbers and netmasks of all subnets for +which it will be providing service. In addition, in order to +dynamically allocate addresses, it must be assigned one or more ranges +of addresses on each subnet which it can in turn assign to client +hosts as they boot. Thus, a very simple configuration providing DHCP +support might look like this: +.nf +.sp 1 + subnet 239.252.197.0 netmask 255.255.255.0 { + range 239.252.197.10 239.252.197.250; + } +.fi +.PP +Multiple address ranges may be specified like this: +.nf +.sp 1 + subnet 239.252.197.0 netmask 255.255.255.0 { + range 239.252.197.10 239.252.197.107; + range 239.252.197.113 239.252.197.250; + } +.fi +.PP +If a subnet will only be provided with BOOTP service and no dynamic +address assignment, the range clause can be left out entirely, but the +subnet statement must appear. +.PP +.SH Lease Lengths +DHCP leases can be assigned almost any length from zero seconds to +infinity. What lease length makes sense for any given subnet, or for +any given installation, will vary depending on the kinds of hosts +being served. +.PP +For example, in an office environment where systems are added from +time to time and removed from time to time, but move relatively +infrequently, it might make sense to allow lease times of a month of +more. In a final test environment on a manufacturing floor, it may +make more sense to assign a maximum lease length of 30 minutes - +enough time to go through a simple test procedure on a network +appliance before packaging it up for delivery. +.PP +It is possible to specify two lease lengths: the default length that +will be assigned if a client doesn't ask for any particular lease +length, and a maximum lease length. These are specified as clauses +to the subnet command: +.nf +.sp 1 + subnet 239.252.197.0 netmask 255.255.255.0 { + range 239.252.197.10 239.252.197.107; + default-lease-time 600; + max-lease-time 7200; + | +.fi +.PP +This particular subnet declaration specifies a default lease time of +600 seconds (ten minutes), and a maximum lease time of 7200 seconds +(two hours). Other common values would be 86400 (one day), 604800 +(one week) and 2592000 (30 days). +.PP +Each subnet need not have the same lease\(emin the case of an office +environment and a manufacturing environment served by the same DHCP +server, it might make sense to have widely disparate values for +default and maximum lease times on each subnet. +.SH BOOTP Support +Each BOOTP client must be explicitly declared in the dhcpd.conf +file. A very basic client declaration will specify the client +network interface's hardware address and the IP address to assign to +that client. If the client needs to be able to load a boot file from +the server, that file's name must be specified. A simple bootp +client declaration might look like this: +.nf +.sp 1 + host haagen { + hardware ethernet 08:00:2b:4c:59:23; + fixed-address 239.252.197.9; + filename "/tftpboot/haagen.boot"; + } +.fi +.SH Options +DHCP (and also BOOTP with Vendor Extensions) provide 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, +and so on). +.PP +These options can be specified on a per-subnet basis, and, for BOOTP +clients, also on a per-client basis. In the event that a BOOTP +client declaration specifies options that are also specified in its +subnet declaration, the options specified in the client declaration +take precedence. An reasonably complete DHCP configuration might +look something like this: +.nf +.sp 1 + subnet 239.252.197.0 netmask 255.255.255.0 { + range 239.252.197.10 239.252.197.250; + default-lease-time 600 max-lease-time 7200; + option subnet-mask 255.255.255.0; + option broadcast-address 239.252.197.255; + option routers 239.252.197.1; + option domain-name-servers 239.252.197.2, 239.252.197.3; + option domain-name "isc.org"; + } +.fi +.PP +A bootp host on that subnet that needs to be in a different domain and +use a different name server might be declared as follows: +.nf +.sp 1 + host haagen { + hardware ethernet 08:00:2b:4c:59:23; + fixed-address 239.252.197.9; + filename "/tftpboot/haagen.boot"; + option domain-name-servers 192.5.5.1; + option domain-name "vix.com"; + } +.fi +.PP +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~. +.SH SEE ALSO +dhclient(8), dhcrelay(8), dhcpd.conf(5), dhcpd.leases(5), bpf(4) +.SH AUTHOR +.B dhcpd(8) +was written by Ted Lemon <mellon@vix.com> +under a contract with Vixie Labs. Funding +for this project was provided by the Internet Software Corporation. +Information about the Internet Software Consortium can be found at +.B http://www.isc.org/isc. diff --git a/usr.sbin/dhcp/server/dhcpd.c b/usr.sbin/dhcp/server/dhcpd.c new file mode 100644 index 00000000000..a4dfe5052cc --- /dev/null +++ b/usr.sbin/dhcp/server/dhcpd.c @@ -0,0 +1,344 @@ +/* dhcpd.c + + DHCP Server Daemon. */ + +/* + * 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 <mellon@fugue.com> 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 ocopyright[] = +"$Id: dhcpd.c,v 1.1 1998/08/18 03:43:34 deraadt Exp $ Copyright 1995, 1996 The Internet Software Consortium."; +#endif + +static char copyright[] = +"Copyright 1995, 1996 The Internet Software Consortium."; +static char arr [] = "All rights reserved."; +static char message [] = "Internet Software Consortium DHCPD $Name: $"; + +#include "dhcpd.h" + +static void usage PROTO ((void)); + +TIME cur_time; +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; + +int log_priority; +#ifdef DEBUG +int log_perror = -1; +#else +int log_perror = 1; +#endif + +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; + char **argv, **envp; +{ + int i, status; + struct servent *ent; + char *s; + int cftest = 0; +#ifndef DEBUG + int pidfilewritten = 0; + 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 + +#ifndef DEBUG +#ifndef SYSLOG_4_2 +#ifndef __CYGWIN32__ /* XXX */ + setlogmask (LOG_UPTO (LOG_INFO)); +#endif +#endif +#endif + + for (i = 1; i < argc; i++) { + if (!strcmp (argv [i], "-p")) { + if (++i == argc) + usage (); + for (s = argv [i]; *s; s++) + if (!isdigit (*s)) + error ("%s: not a valid UDP port", + argv [i]); + status = atoi (argv [i]); + if (status < 1 || status > 65535) + error ("%s: not a valid UDP port", + argv [i]); + local_port = htons (status); + debug ("binding to user-specified port %d", + ntohs (local_port)); + } else if (!strcmp (argv [i], "-f")) { +#ifndef DEBUG + daemon = 0; +#endif + } else if (!strcmp (argv [i], "-d")) { +#ifndef DEBUG + daemon = 0; +#endif + log_perror = -1; + } else if (!strcmp (argv [i], "-cf")) { + if (++i == argc) + usage (); + path_dhcpd_conf = argv [i]; + } else if (!strcmp (argv [i], "-lf")) { + if (++i == argc) + usage (); + path_dhcpd_db = argv [i]; + } else if (!strcmp (argv [i], "-t")) { + /* test configurations only */ +#ifndef DEBUG + daemon = 0; +#endif + cftest = 1; + log_perror = -1; + } else if (!strcmp (argv [i], "-q")) { + quiet = 1; + quiet_interface_discovery = 1; + } else if (argv [i][0] == '-') { + usage (); + } else { + struct interface_info *tmp = + ((struct interface_info *) + dmalloc (sizeof *tmp, "get_interface_list")); + if (!tmp) + error ("Insufficient memory to %s %s", + "record interface", argv [i]); + memset (tmp, 0, sizeof *tmp); + strcpy (tmp -> name, argv [i]); + tmp -> next = interfaces; + tmp -> flags = INTERFACE_REQUESTED; + interfaces = tmp; + } + } + + if (!quiet) { + note (message); + note (copyright); + note (arr); + } + + /* Default to the DHCP/BOOTP port. */ + if (!local_port) + { + ent = getservbyname ("dhcp", "udp"); + if (!ent) + local_port = htons (67); + else + local_port = ent -> s_port; +#ifndef __CYGWIN32__ /* XXX */ + endservent (); +#endif + } + + remote_port = htons (ntohs (local_port) + 1); + + /* Get the current time... */ + GET_TIME (&cur_time); + + /* Read the dhcpd.conf file... */ + if (!readconf ()) + error ("Configuration file errors encountered -- exiting"); + + /* test option should cause an early exit */ + if (cftest) + exit(0); + + /* Start up the database... */ + db_startup (); + + /* Discover all the network interfaces and initialize them. */ + discover_interfaces (1); + + /* Initialize icmp support... */ + icmp_startup (1, lease_pinged); + +#ifndef DEBUG + if (daemon) { + /* First part of becoming a daemon... */ + if ((pid = fork ()) < 0) + error ("Can't fork daemon: %m"); + else if (pid) + exit (0); + } + + /* Read previous pid file. */ + if ((i = open (path_dhcpd_pid, O_RDONLY)) >= 0) { + status = read (i, pbuf, (sizeof pbuf) - 1); + close (i); + pbuf [status] = 0; + pid = atoi (pbuf); + + /* If the previous server process is not still running, + write a new pid file immediately. */ + if (pid && kill (pid, 0) < 0) { + unlink (path_dhcpd_pid); + if ((i = open (path_dhcpd_pid, + O_WRONLY | O_CREAT, 0640)) >= 0) { + sprintf (pbuf, "%d\n", (int)getpid ()); + write (i, pbuf, strlen (pbuf)); + close (i); + pidfilewritten = 1; + } + } + } + + /* If we were requested to log to stdout on the command line, + keep doing so; otherwise, stop. */ + if (log_perror == -1) + log_perror = 1; + else + log_perror = 0; + + if (daemon) { + /* Become session leader and get pid... */ + close (0); + close (1); + close (2); + pid = setsid (); + } + + /* If we didn't write the pid file earlier because we found a + process running the logged pid, but we made it to here, + meaning nothing is listening on the bootp port, then write + the pid file out - what's in it now is bogus anyway. */ + if (!pidfilewritten) { + unlink (path_dhcpd_pid); + if ((i = open (path_dhcpd_pid, + O_WRONLY | O_CREAT, 0640)) >= 0) { + sprintf (pbuf, "%d\n", (int)getpid ()); + write (i, pbuf, strlen (pbuf)); + close (i); + pidfilewritten = 1; + } + } +#endif /* !DEBUG */ + + /* Set up the bootp packet handler... */ + bootp_packet_handler = do_packet; + + /* Receive packets and dispatch them... */ + dispatch (); + + /* Not reached */ + return 0; +} + +/* Print usage message. */ + +static void usage () +{ + note (message); + note (copyright); + note (arr); + + error ("Usage: dhcpd [-p <UDP port #>] [-d] [-f] [-cf config-file]%s", + "\n [-lf lease-file] [if0 [...ifN]]"); +} + +void cleanup () +{ +} + +void lease_pinged (from, packet, length) + struct iaddr from; + u_int8_t *packet; + int length; +{ + struct lease *lp; + + /* Don't try to look up a pinged lease if we aren't trying to + ping one - otherwise somebody could easily make us churn by + just forging repeated ICMP EchoReply packets for us to look + up. */ + if (!outstanding_pings) + return; + + lp = find_lease_by_ip_addr (from); + + if (!lp) { + note ("unexpected ICMP Echo Reply from %s", piaddr (from)); + return; + } + + if (!lp -> state) { + warn ("ICMP Echo Reply for %s arrived late or is spurious.\n", + piaddr (from)); + return; + } + + /* At this point it looks like we pinged a lease and got a + response, which shouldn't have happened. */ + 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); + --outstanding_pings; +} + +void lease_ping_timeout (vlp) + void *vlp; +{ + struct lease *lp = vlp; + + --outstanding_pings; + dhcp_reply (lp); +} diff --git a/usr.sbin/dhcp/server/dhcpd.conf b/usr.sbin/dhcp/server/dhcpd.conf new file mode 100644 index 00000000000..a50dee0751d --- /dev/null +++ b/usr.sbin/dhcp/server/dhcpd.conf @@ -0,0 +1,128 @@ +# dhcpd.conf +# +# 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; + +# 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; + } + +# 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; + } +} + +# 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; + option domain-name "vix.com"; + option routers 192.5.5.1; + option subnet-mask 255.255.255.224; + option broadcast-address 192.5.5.31; + default-lease-time 600; + max-lease-time 7200; +} + +# Hosts which require special configuration options can be listed in +# host statements. If no address is specified, the address will be +# allocated dynamically (if possible), but the host-specific information +# will still come from the host declaration. + +host passacaglia { + hardware ethernet 0:0:c0:5d:bd:95; + filename "vmunix.passacaglia"; + server-name "toccata.fugue.com"; +} + +# Fixed IP addresses can also be specified for hosts. These addresses +# should not also be listed as being available for dynamic assignment. +# Hosts for which fixed IP addresses have been specified can boot using +# BOOTP or DHCP. Hosts for which no fixed address is specified can only +# be booted with DHCP, unless there is an address range on the subnet +# to which a BOOTP client is connected which has the dynamic-bootp flag +# set. +host fantasia { + hardware ethernet 08:00:07:26:c0:a5; + fixed-address fantasia.fugue.com; +} + +# If a DHCP or BOOTP client is mobile and might be connected to a variety +# of networks, more than one fixed address for that host can be specified. +# Hosts can have fixed addresses on some networks, but receive dynamically +# allocated address on other subnets; in order to support this, a host +# declaration for that client must be given which does not have a fixed +# address. If a client should get different parameters depending on +# what subnet it boots on, host declarations for each such network should +# be given. Finally, if a domain name is given for a host's fixed address +# and that domain name evaluates to more than one address, the address +# corresponding to the network to which the client is attached, if any, +# will be assigned. +host confusia { + hardware ethernet 02:03:04:05:06:07; + fixed-address confusia-1.fugue.com, confusia-2.fugue.com; + filename "vmunix.confusia"; + server-name "toccata.fugue.com"; +} + +host confusia { + hardware ethernet 02:03:04:05:06:07; + fixed-address confusia-3.fugue.com; + filename "vmunix.confusia"; + server-name "snarg.fugue.com"; +} + +host confusia { + hardware ethernet 02:03:04:05:06:07; + filename "vmunix.confusia"; + server-name "bb.home.vix.com"; +} diff --git a/usr.sbin/dhcp/server/dhcpd.conf.5 b/usr.sbin/dhcp/server/dhcpd.conf.5 new file mode 100644 index 00000000000..ef6044c390d --- /dev/null +++ b/usr.sbin/dhcp/server/dhcpd.conf.5 @@ -0,0 +1,686 @@ +.\" dhcpd.conf.5 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 dhcpd.conf 5 +.SH NAME +dhcpd.conf - dhcpd configuration file +.SH DESCRIPTION +The dhcpd.conf file contains configuration information for +.IR dhcpd, +the Internet Software Consortium DHCP Server. +.PP +The dhcpd.conf file is a free-form ASCII text file. It is parsed by +the recursive-descent parser built into dhcpd. The file may contain +extra tabs and newlines for formatting purposes. Keywords in the file +are case-insensitive. Comments may be placed anywhere within the +file (except within quotes). Comments begin with the # character and +end at the end of the line. +.PP +The file essentially consists of a list of statements. Statements +fall into two broad categories - parameters and declarations. +.PP +Parameter statements either say how to do something (e.g., how long a +lease to offer), whether to do something (e.g., should dhcpd provide +addresses to unknown clients), or what parameters to provide to the +client (e.g., use gateway 220.177.244.7). +.PP +Declarations are used to describe the topology of the +network, to describe clients on the network, to provide addresses that +can be assigned to clients, or to apply a group of parameters to a +group of declarations. In any group of parameters and declarations, +all parameters must be specified before any declarations which depend +on those parameters may be specified. +.PP +Declarations about network topology include the + \fIshared-network\fR and the \fIsubnet\fR +declarations. If clients on a subnet are to be assigned addresses +dynamically, a \fIrange\fR declaration must appear within the +\fIsubnet\fR declaration. For clients with statically assigned +addresses, or for installations where only known clients will be +served, each such client must have a \fIhost\fR declaration. If +parameters are to be applied to a group of declarations which are not +related strictly on a per-subnet basis, the \fIgroup\fR declaration +can be used. +.PP +For every subnet which will be served, and for every subnet +to which the dhcp server is connected, there must be one \fIsubnet\fR +declaration, which tells dhcpd how to recognize that an address is on +that subnet. A \fIsubnet\fR declaration is required for each subnet +even if no addresses will be dynamically allocated on that subnet. +.PP +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 +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 +this case, the \fIsubnet\fR declarations for these two networks may be +enclosed in a \fIshared-network\fR declaration. +.PP +Some sites may have departments which have clients on more than one +subnet, but it may be desirable to offer those clients a uniform set +of parameters which are different than what would be offered to +clients from other departments on the same subnet. For clients which +will be declared explicitly with \fIhost\fR declarations, these +declarations can be enclosed in a \fIgroup\fR declaration along with +the parameters which are common to that department. For clients +whose addresses will be dynamically assigned, there is currently no +way to group parameter assignments other than by network topology. +.PP +When a client is to be booted, its boot parameters are determined by +first consulting that client's \fIhost\fR declaration (if any), then +consulting the \fIgroup\fR declaration (if any) which enclosed that +\fIhost\fR declaration, then consulting the \fIsubnet\fR declaration +for the subnet on which the client is booting, then consulting the +\fIshared-network\fR declaration (if any) containing that subnet, and +finally consulting the top-level parameters which may be specified +outside of any declaration. +.PP +When dhcpd tries to find a \fIhost\fR declaration for a client, it +first looks for a \fIhost\fR declaration which has a +\fIfixed-address\fR parameter which matches the subnet or shared +network on which the client is booting. If it doesn't find any such +entry, it then tries to find an entry which has no \fIfixed-address\fR +parameter. If no such entry is found, then dhcpd acts as if there is +no entry in the dhcpd.conf file for that client, even if there is an +entry for that client on a different subnet or shared network. +.SH EXAMPLES +.PP +A typical dhcpd.conf file will look something like this: +.nf + +.I global parameters... + +shared-network ISC-BIGGIE { + \fIshared-network-specific parameters...\fR + subnet 204.254.239.0 netmask 255.255.255.224 { + \fIsubnet-specific parameters...\fR + range 204.254.239.10 204.254.239.30; + } + subnet 204.254.239.32 netmask 255.255.255.224 { + \fIsubnet-specific parameters...\fR + range 204.254.239.42 204.254.239.62; + } +} + +subnet 204.254.239.64 netmask 255.255.255.224 { + \fIsubnet-specific parameters...\fR + range 204.254.239.74 204.254.239.94; +} + +group { + \fIgroup-specific parameters...\fR + host zappo.test.isc.org { + \fIhost-specific parameters...\fR + } + host beppo.test.isc.org { + \fIhost-specific parameters...\fR + } + host harpo.test.isc.org { + \fIhost-specific parameters...\fR + } +} + +.ce 1 +Figure 1 + +.fi +.PP +Notice that at the beginning of the file, there's a place +for global parameters. These might be things like the organization's +domain name, the addresses of the name servers (if they are common to +the entire organization), and so on. So, for example: +.nf + + option domain-name "isc.org"; + option domain-name-servers ns1.isc.org, ns2.isc.org; + +.ce 1 +Figure 2 +.fi +.PP +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 +the client. +.PP +In Figure 1, you can see that both the shared-network statement and +the subnet statements can have parameters. Let us say that the +shared network \fIISC-BIGGIE\fR supports an entire department - +perhaps the accounting department. If accounting has its own domain, +then a shared-network-specific parameter might be: +.nf + + option domain-name "accounting.isc.org"; +.fi +.PP +All subnet declarations appearing in the shared-network declaration +would then have the domain-name option set to "accounting.isc.org" +instead of just "isc.org". +.PP +The most obvious reason for having subnet-specific parameters as +shown in Figure 1 is that each subnet, of necessity, has its own +router. So for the first subnet, for example, there should be +something like: +.nf + + option routers 204.254.239.1; +.fi +.PP +Note that the address here is specified numerically. This is not +required - if you have a different domain name for each interface on +your router, it's perfectly legitimate to use the domain name for that +interface instead of the numeric address. However, in many cases +there may be only one domain name for all of a router's IP addresses, and +it would not be appropriate to use that name here. +.PP +In Figure 1 there is also a \fIgroup\fR statement, which provides +common parameters for a set of three hosts - zappo, beppo and harpo. +As you can see, these hosts are all in the test.isc.org domain, so it +might make sense for a group-specific parameter to override the domain +name supplied to these hosts: +.nf + + option domain-name "test.isc.org"; +.fi +.PP +Also, given the domain they're in, these are probably test machines. +If we wanted to test the DHCP leasing mechanism, we might set the +lease timeout somewhat shorter than the default: + +.nf + max-lease-time 120; + default-lease-time 120; +.fi +.PP +You may have noticed that while some parameters start with the +\fIoption\fR keyword, some do not. Parameters starting with the +\fIoption\fR keyword correspond to actual DHCP options, while +parameters that do not start with the option keyword either control +the behaviour of the DHCP server (e.g., how long a lease dhcpd will +give out), or specify client parameters that are not optional in the +DHCP protocol (for example, server-name and filename). +.PP +In Figure 1, each host had \fIhost-specific parameters\fR. These +could include such things as the \fIhostname\fR option, the name of a +file to upload (the \fIfilename parameter) and the address of the +server from which to upload the file (the \fInext-server\fR +parameter). In general, any parameter can appear anywhere that +parameters are allowed, and will be applied according to the scope in +which the parameter appears. +.PP +Imagine that you have a site with a lot of NCD X-Terminals. These +terminals come in a variety of models, and you want to specify the +boot files for each models. One way to do this would be to have host +declarations for each server and group them by model: +.nf + +group { + filename "Xncd19r"; + next-server ncd-booter; + + host ncd1 { hardware ethernet 0:c0:c3:49:2b:57; } + host ncd4 { hardware ethernet 0:c0:c3:80:fc:32; } + host ncd8 { hardware ethernet 0:c0:c3:22:46:81; } +} + +group { + filename "Xncd19c"; + next-server ncd-booter; + + host ncd2 { hardware ethernet 0:c0:c3:88:2d:81; } + host ncd3 { hardware ethernet 0:c0:c3:00:14:11; } +} + +group { + filename "XncdHMX"; + next-server ncd-booter; + + host ncd1 { hardware ethernet 0:c0:c3:11:90:23; } + host ncd4 { hardware ethernet 0:c0:c3:91:a7:8; } + host ncd8 { hardware ethernet 0:c0:c3:cc:a:8f; } +} +.fi +.SH REFERENCE: DECLARATIONS +.PP +.B The +.I shared-network +.B statement +.PP +.nf + \fBshared-network\fR \fIname\fR \fB{\fR + [ \fIparameters\fR ] + [ \fIdeclarations\fR ] + \fB}\fR +.fi +.PP +The \fIshared-network\fR statement is used to inform the DHCP server +that some IP subnets actually share the same physical network. Any +subnets in a shared network should be declared within a +\fIshared-network\fR statement. Parameters specified in the +\fIshared-network\fR statement will be used when booting clients on +those subnets unless parameters provided at the subnet or host level +override them. If any subnet in a shared network has addresses +available for dynamic allocation, those addresses are collected into a +common pool for that shared network and assigned to clients as needed. +There is no way to distinguish on which subnet of a shared network a +client should boot. +.PP +.I Name +should be the name of the shared network. This name is used when +printing debugging messages, so it should be descriptive for the +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 +.I subnet +.B statement +.PP +.nf + \fBsubnet\fR \fIsubnet-number\fR \fBnetmask\fR \fInetmask\fR \fB{\fR + [ \fIparameters\fR ] + [ \fIdeclarations\fR ] + \fB}\fR +.fi +.PP +The \fIsubnet\fR statement is used to provide dhcpd with enough +information to tell whether or not an IP address is on that subnet. +It may also be used to provide subnet-specific parameters and to +specify what addresses may be dynamically allocated to clients booting +on that subnet. Such addresses are specified using the \fIrange\fR +declaration. +.PP +The +.I subnet-number +should be an IP address or domain name which resolves to the subnet +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 +netmask, are sufficient to determine whether any given IP address is +on the specified subnet. +.PP +Although a netmask must be given with every subnet declaration, it is +recommended that if there is any variance in subnet masks at a site, a +subnet-mask option statement be used in each subnet declaration to set +the desired subnet mask, since any subnet-mask option statement will +override the subnet mask declared in the subnet statement. +.PP +.B The +.I range +.B statement +.PP +.nf + \fBrange\fR [ \fBdynamic-bootp\fR ] \fIlow-address\fR [ \fIhigh-address\fR]\fB;\fR +.fi +.PP +For any subnet on which addresses will be assigned dynamically, there +must be at least one \fIrange\fR statement. The range statement +gives the lowest and highest IP addresses in a range. All IP +addresses in the range should be in the subnet in which the +\fIrange\fR statement is declared. The \fIdynamic-bootp\fR flag may +be specified if addresses in the specified range may be dynamically +assigned to BOOTP clients as well as DHCP clients. When specifying a +single address, \fIhigh-address\fR can be omitted. +.PP +.B The +.I host +.B statement +.PP +.nf + \fBhost\fR \fIhostname\fR { + [ \fIparameters\fR ] + [ \fIdeclarations\fR ] + \fB}\fR +.fi +.PP +There must be at least one +.B host +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. +.PP +If it is desirable to be able to boot a DHCP or BOOTP +client on more than one subnet with fixed addresses, more than one +address may be specified in the +.I fixed-address +parameter, or more than one +.B host +statement may be specified. +.PP +If client-specific boot parameters must change based on the network +to which the client is attached, then multiple +.B host +statements should +be used. +.PP +If a client is to be booted using a fixed address if it's +possible, but should be allocated a dynamic address otherwise, then a +.B host +statement must be specified without a +.B fixed-address +clause. +.I hostname +should be a name identifying the host. If a \fIhostname\fR option is +not specified for the host, \fIhostname\fR is used. +.PP +\fIHost\fR declarations are matched to actual DHCP or BOOTP clients +by matching the \fRdhcp-client-identifier\fR option specified in the +\fIhost\fR declaration to the one supplied by the client, or, if the +\fIhost\fR declaration or the client does not provide a +\fRdhcp-client-identifier\fR option, by matching the \fIhardware\fR +parameter in the \fIhost\fR declaration to the network hardware +address supplied by the client. BOOTP clients do not normally +provide a \fIdhcp-client-identifier\fR, so the hardware address must +be used for all clients that may boot using the BOOTP protocol. +.PP +.B The +.I group +.B statement +.PP +.nf + \fBgroup\fR { + [ \fIparameters\fR ] + [ \fIdeclarations\fR ] + \fB}\fR +.fi +.PP +The group statement is used simply to apply one or more parameters to +a group of declarations. It can be used to group hosts, shared +networks, subnets, or even other groups. +.SH REFERENCE: ALLOW and DENY +.PP +The +.I allow +and +.I deny +statements can be used to control the behaviour of dhcpd to various +sorts of requests. +.PP +.PP +.B The +.I unknown-clients +.B keyword +.PP + \fBallow unknown-clients;\fR + \fBdeny unknown-clients;\fR +.PP +The \fBunknown-clients\fR flag is used to tell dhcpd whether +or not to dynamically assign addresses to unknown clients. Dynamic +address assignment to unknown clients is \fBallow\fRed by default. +.PP +.B The +.I bootp +.B keyword +.PP + \fBallow bootp;\fR + \fBdeny bootp;\fR +.PP +The \fBbootp\fR flag is used to tell dhcpd whether +or not to respond to bootp queries. Bootp queries are \fBallow\fRed +by default. +.PP +.B The +.I booting +.B keyword +.PP + \fBallow booting;\fR + \fBdeny booting;\fR +.PP +The \fBbooting\fR flag is used to tell dhcpd whether or not to respond +to queries from a particular client. This keyword only has meaning +when it appears in a host declaration. By default, booting is +\fBallow\fRed, but if it is disabled for a particular client, then +that client will not be able to get and address from the DHCP server. +.SH REFERENCE: PARAMETERS +.PP +.B The +.I default-lease-time +.B statement +.PP + \fBdefault-lease-time\fR \fItime\fR\fB;\fR +.PP +.I Time +should be the length in seconds that will be assigned to a lease if +the client requesting the lease does not ask for a specific expiration +time. +.PP +.B The +.I max-lease-time +.B statement +.PP + \fBmax-lease-time\fR \fItime\fR\fB;\fR +.PP +.I Time +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 +.I hardware +.B statement +.PP + \fBhardware\fR \fIhardware-type\fR \fIhardware-address\fR\fB;\fR +.PP +In order for a BOOTP client to be recognized, its network hardware +address must be declared using a \fIhardware\fR clause in the +.I host +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 +and +.B fddi +hardware types would also be desirable. +The +.I hardware-address +should be a set of hexadecimal octets (numbers from 0 through ff) +seperated by colons. The \fIhardwarefR statement may also be used +for DHCP clients. +.PP +.B The +.I filename +.B statement +.PP + \fBfilename\fR \fB"\fR\fIfilename\fR\fB";\fR +.PP +The \fIfilename\fR statement can be used to specify the name of the +initial boot file which is to be loaded by a client. The +.I filename +should be a filename recognizable to whatever file transfer protocol +the client can be expected to use to load the file. +.PP +.B The +.I server-name +.B statement +.PP + \fBserver-name\fR \fB"\fR\fIname\fR\fB";\fR +.PP +The \fIserver-name\fR statement can be used to inform the client of +the name of the server from which it is booting. \fIName\fR should +be the name that will be provided to the client. +.PP +.B The +.I next-server +.B statement +.PP + \fBnext-server\fR \fIserver-name\fR\fB;\fR +.PP +The \fInext-server\fR statement is used to specify the host address of +the server from which the initial boot file (specified in the +\fIfilename\fR statement) is to be loaded. \fIServer-name\fR should +be a numeric IP address or a domain name. If no \fInext-server\fR +parameter applies to a given client, the DHCP server's IP address is +used. +.PP +.B The +.I fixed-address +.B statement +.PP + \fBfixed-address\fR \fIaddress\fR [\fB,\fR \fIaddress\fR ... ]\fB;\fR +.PP +The \fIfixed-address\fR statement is used to assign one or more fixed +IP addresses to a client. It should only appear in a \fIhost\fR +declaration. If more than one address is supplied, then when the +client boots, it will be assigned the address which corresponds to the +network on which it is booting. If none of the addresses in the +\fIfixed-address\fR statement are on the network on which the client +is booting, that client will not match the \fIhost\fR declaration +containing that \fIfixed-address\fR statement. Each \fIaddress\fR +should be either an IP address or a domain name which resolves to one +or more IP addresses. +.PP +.B The +.I dynamic-bootp-lease-cutoff +.B statement +.PP + \fBdynamic-bootp-lease-cutoff\fR \fIdate\fR\fB;\fR +.PP +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 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 +machines are required to be powered off. +.PP +.I Date +should be the date on which all assigned BOOTP leases will end. The +date is specified in the form: +.PP +.ce 1 +W YYYY/MM/DD HH:MM:SS +.PP +W is the day of the week expressed as a number +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. +.PP +.B The +.I dynamic-bootp-lease-length +.B statement +.PP + \fBdynamic-bootp-lease-length\fR \fIlength\fR\fB;\fR +.PP +The \fIdynamic-bootp-lease-length\fR statement is used to set the +length of leases dynamically assigned to BOOTP clients. At some +sites, it may be possible to assume that a lease is no longer in +use if its holder has not used BOOTP or DHCP to get its address within +a certain time period. The period is specified in \fIlength\fR as a +number of seconds. If a client reboots using BOOTP during the +timeout period, the lease duration is reset to \fIlength\fR, so a +BOOTP client that boots frequently enough will never lose its lease. +Needless to say, this parameter should be adjusted with extreme +caution. +.PP +.B The +.I get-lease-hostnames +.B statement +.PP + \fBget-lease-hostnames\fR \fIflag\fR\fB;\fR +.PP +The \fIget-lease-hostnames\fR statement is used to tell dhcpd whether +or not to look up the domain name corresponding to the IP address of +each address in the lease pool and use that address for the DHCP +\fIhostname\fR option. If \fIflag\fR is true, then this lookup is +done for all addresses in the current scope. By default, or if +\fIflag\fR is false, no lookups are done. +.PP +.B The +.I use-host-decl-names +.B statement +.PP + \fBuse-host-decl-names\fR \fIflag\fR\fB;\fR +.PP +If the \fIuse-host-decl-names\fR parameter is true in a given scope, +then for every host declaration within that scope, the name provided +for the host declaration will be supplied to the client as its +hostname. So, for example, +.PP +.nf + group { + use-host-decl-names on; + + host joe { + hardware ethernet 08:00:2b:4c:29:32; + fixed-address joe.fugue.com; + } + } + +is equivalent to + + host joe { + hardware ethernet 08:00:2b:4c:29:32; + fixed-address joe.fugue.com; + option host-name "joe"; + } +.fi +.PP +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 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. +.SH REFERENCE: OPTION STATEMENTS +.PP +DHCP option statements are documented in the +.B dhcp-options(5) +manual page. +.SH SEE ALSO +dhcpd.conf(5), dhcpd.leases(5), RFC2132, RFC2131. +.SH AUTHOR +.B dhcpd(8) +was written by Ted Lemon <mellon@vix.com> +under a contract with Vixie Labs. Funding +for this project was provided by the Internet Software Corporation. +Information about the Internet Software Consortium can be found at +.B http://www.isc.org/isc. diff --git a/usr.sbin/dhcp/server/dhcpd.leases.5 b/usr.sbin/dhcp/server/dhcpd.leases.5 new file mode 100644 index 00000000000..5a6c6632e34 --- /dev/null +++ b/usr.sbin/dhcp/server/dhcpd.leases.5 @@ -0,0 +1,82 @@ +.\" dhcpd.conf.5 +.\" +.\" 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 <mellon@fugue.com> in cooperation with Vixie +.\" 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 dhcpd.leases 5 +.SH NAME +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 +occurrance. +.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. +.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 +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, +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 +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. +.SH FILES +.B /var/db/dhcpd.leases +.SH SEE ALSO +dhcpd(8), dhcp-options(5), dhcpd.conf(5), RFC2132, RFC2131. +.SH AUTHOR +.B dhcpd(8) +was written by Ted Lemon <mellon@vix.com> +under a contract with Vixie Labs. Funding +for this project was provided by the Internet Software Corporation. +Information about the Internet Software Consortium can be found at +.B http://www.isc.org/isc. diff --git a/usr.sbin/dhcp/statmsg/Makefile b/usr.sbin/dhcp/statmsg/Makefile new file mode 100644 index 00000000000..336bbc8b943 --- /dev/null +++ b/usr.sbin/dhcp/statmsg/Makefile @@ -0,0 +1,37 @@ +# Makefile +# +# Copyright (c) 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. +# + +SRCS = main.c +PROG = statmsg +MAN = statmsg.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/dhcp/statmsg/Makefile.dist b/usr.sbin/dhcp/statmsg/Makefile.dist new file mode 100644 index 00000000000..8a2498fa129 --- /dev/null +++ b/usr.sbin/dhcp/statmsg/Makefile.dist @@ -0,0 +1,77 @@ +# Makefile.dist +# +# 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. +# + +CATMANPAGES = +SRCS = main.c +OBJS = main.o +PROG = statmsg +MAN = + +DEBUG = -g +INCLUDES = -I.. -I../includes +DHCPLIB = ../common/libdhcp.a +CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) + +all: $(PROG) $(CATMANPAGES) + +install: $(PROG) $(CATMANPAGES) + $(INSTALL) statmsg $(BINDIR) + $(CHMOD) 755 $(BINDIR)/statmsg + if [ ! -d $(ADMMANDIR) ]; then \ + mkdir $(ADMMANDIR); \ + chmod 755 $(ADMMANDIR); \ + fi +# $(MANINSTALL) $(MANFROM) statmsg.cat8 $(MANTO) \ +# $(ADMMANDIR)/statmsg$(ADMMANEXT) + +clean: + -rm -f $(OBJS) + +realclean: clean + -rm -f $(PROG) $(CATMANPAGES) *~ #* + +distclean: realclean + -rm -f Makefile + +# These should only be done on 4.4 BSD-based systems, since the mandoc +# macros aren't available on older unices. Catted man pages are +# provided in the distribution so that this doesn't become a problem. + +statmsg.cat8: statmsg.8 + sed -e "s#ETCDIR#$(ETC)#" -e "s#DBDIR#$(VARDB)#" \ + -e "s#RUNDIR#$(VARRUN)#" < statmsg.8 \ + | nroff -man >statmsg.cat8 + +$(PROG): $(OBJS) $(DHCPLIB) + $(CC) $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS) + +# Dependencies (semi-automatically-generated) diff --git a/usr.sbin/dhcp/statmsg/main.c b/usr.sbin/dhcp/statmsg/main.c new file mode 100644 index 00000000000..0c267a0d9c5 --- /dev/null +++ b/usr.sbin/dhcp/statmsg/main.c @@ -0,0 +1,118 @@ +/* main.c + + System status updater... + + !!!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 <mellon@fugue.com> 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: main.c,v 1.1 1998/08/18 03:43:36 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" + +int log_priority; +int log_perror = 1; + +int main (argc, argv, envp) + int argc; + char **argv; + char **envp; +{ + struct sockaddr_un name; + int sysconf_fd; + struct sysconf_header hdr; + int status; + char *buf; + +#ifdef SYSLOG_4_2 + openlog ("statmsg", LOG_NDELAY); + log_priority = LOG_DAEMON; +#else + openlog ("statmsg", LOG_NDELAY, LOG_DAEMON); +#endif + +#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__)) + setlogmask (LOG_UPTO (LOG_INFO)); +#endif + + if (argc < 2) + error ("usage: statmsg type [data]"); + + hdr.length = 0; + if (!strcmp (argv [1], "network-location-changed")) + hdr.type = NETWORK_LOCATION_CHANGED; + else + error ("unknown status message type %s", argv [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) + error ("can't connect to sysconf socket: %m"); + + status = write (sysconf_fd, &hdr, sizeof hdr); + if (status < 0) + error ("sysconf: %m"); + if (status < sizeof (hdr)) + error ("sysconf: short write"); + + if (hdr.length) { + status = write (sysconf_fd, buf, hdr.length); + if (status < 0) + error ("sysconf payload write: %m"); + if (status != hdr.length) + error ("sysconf payload: short write"); + } + + exit (0); +} + +void cleanup () +{ +} diff --git a/usr.sbin/dhcp/sysconfd/Makefile b/usr.sbin/dhcp/sysconfd/Makefile new file mode 100644 index 00000000000..99ef75848e3 --- /dev/null +++ b/usr.sbin/dhcp/sysconfd/Makefile @@ -0,0 +1,37 @@ +# Makefile +# +# Copyright (c) 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. +# + +SRCS = sysconfd.c +PROG = sysconfd +MAN = sysconfd.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/dhcp/sysconfd/Makefile.dist b/usr.sbin/dhcp/sysconfd/Makefile.dist new file mode 100644 index 00000000000..169e8ed9ed4 --- /dev/null +++ b/usr.sbin/dhcp/sysconfd/Makefile.dist @@ -0,0 +1,77 @@ +# Makefile.dist +# +# 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. +# + +CATMANPAGES = +SRCS = sysconfd.c +OBJS = sysconfd.o +PROG = sysconfd +MAN = + +DEBUG = -g +INCLUDES = -I.. -I../includes +DHCPLIB = ../common/libdhcp.a +CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) + +all: $(PROG) $(CATMANPAGES) + +install: $(PROG) $(CATMANPAGES) + $(INSTALL) sysconfd $(BINDIR) + $(CHMOD) 755 $(BINDIR)/sysconfd + if [ ! -d $(ADMMANDIR) ]; then \ + mkdir $(ADMMANDIR); \ + chmod 755 $(ADMMANDIR); \ + fi +# $(MANINSTALL) $(MANFROM) sysconfd.cat8 $(MANTO) \ +# $(ADMMANDIR)/sysconfd$(ADMMANEXT) + +clean: + -rm -f $(OBJS) + +realclean: clean + -rm -f $(PROG) $(CATMANPAGES) *~ #* + +distclean: realclean + -rm -f Makefile + +# These should only be done on 4.4 BSD-based systems, since the mandoc +# macros aren't available on older unices. Catted man pages are +# provided in the distribution so that this doesn't become a problem. + +sysconfd.cat8: sysconfd.8 + sed -e "s#ETCDIR#$(ETC)#" -e "s#DBDIR#$(VARDB)#" \ + -e "s#RUNDIR#$(VARRUN)#" < sysconfd.8 \ + | nroff -man >sysconfd.cat8 + +$(PROG): $(OBJS) $(DHCPLIB) + $(CC) $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS) + +# Dependencies (semi-automatically-generated) diff --git a/usr.sbin/dhcp/sysconfd/sysconfd.c b/usr.sbin/dhcp/sysconfd/sysconfd.c new file mode 100644 index 00000000000..2529ccd2abd --- /dev/null +++ b/usr.sbin/dhcp/sysconfd/sysconfd.c @@ -0,0 +1,258 @@ +/* main.c + + System configuration status daemon... + + !!!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 <mellon@fugue.com> 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: sysconfd.c,v 1.1 1998/08/18 03:43:36 deraadt Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" + +int sysconf_fd; + +struct sysconf_client { + struct sysconf_client *next; + int fd; +} *clients; + +static void new_connection PROTO ((struct protocol *)); +static void client_input PROTO ((struct protocol *)); + +int log_priority; +int log_perror; + +struct interface_info fallback_interface; +TIME cur_time; +u_int16_t local_port; + + +int main (argc, argv, envp) + int argc; + char **argv; + char **envp; +{ + struct sockaddr_un name; + int sysconf_fd; + int pid; + +#ifdef SYSLOG_4_2 + openlog ("sysconfd", LOG_NDELAY); + log_priority = LOG_DAEMON; +#else + openlog ("sysconfd", LOG_NDELAY, LOG_DAEMON); +#endif + +#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__)) + setlogmask (LOG_UPTO (LOG_INFO)); +#endif + + /* Make a socket... */ + 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)); + unlink (name.sun_path); + + /* Bind to it... */ + if (bind (sysconf_fd, (struct sockaddr *)&name, name.sun_len) < 0) + error ("can't bind to sysconf socket: %m"); + + /* Listen for connections... */ + if (listen (sysconf_fd, 1) < 0) + error ("can't listen on sysconf socket: %m"); + + /* Stop logging to stderr... */ + log_perror = 0; + + /* Become a daemon... */ + if ((pid = fork ()) < 0) + error ("Can't fork daemon: %m"); + else if (pid) + exit (0); + + /* Become session leader... */ + (void)setsid (); + + /* Set up a protocol structure for it... */ + add_protocol ("listener", sysconf_fd, new_connection, 0); + + /* Kernel status stuff goes here... */ + + /* Wait for something to happen... */ + dispatch (); + + exit (0); +} + +void new_connection (proto) + struct protocol *proto; +{ + struct sockaddr_un name; + int namelen; + struct sysconf_client *tmp; + int new_fd; + + tmp = (struct sysconf_client *)malloc (sizeof *tmp); + if (tmp < 0) + error ("Can't find memory for new client!"); + memset (tmp, 0, sizeof *tmp); + + namelen = sizeof name; + new_fd = accept (proto -> fd, (struct sockaddr *)&name, &namelen); + if (new_fd < 0) + warn ("accept: %m"); + + tmp -> next = clients; + tmp -> fd = new_fd; + clients = tmp; + + add_protocol ("aclient", new_fd, client_input, 0); +} + +void client_input (proto) + struct protocol *proto; +{ + struct sysconf_header hdr; + int status; + char *buf; + void (*handler) PROTO ((struct sysconf_header *, void *)); + struct sysconf_client *client; + + status = read (proto -> fd, &hdr, sizeof hdr); + if (status < 0) { + blow: + warn ("client_input: %m"); + close (proto -> fd); + remove_protocol (proto); + return; + } + if (status < sizeof (hdr)) { + warn ("client_input: short message"); + goto blow; + } + + if (hdr.length) { + buf = malloc (hdr.length); + if (!buf) { + warn ("client_input: can't buffer payload"); + goto blow; + } + status = read (proto -> fd, buf, hdr.length); + if (status < 0) { + warn ("client_input payload read: %m"); + goto blow; + } + if (status != hdr.length) { + warn ("client_input payload: short read"); + goto blow; + } + } else + buf = (char *)0; + + for (client = clients; client; client = client -> next) { + if (client -> fd == proto -> fd) + continue; + + status = write (client -> fd, &hdr, sizeof hdr); + if (status < 0) { + warn ("client_input: %m"); + continue; + } + if (status < sizeof (hdr)) { + warn ("client_input: short write"); + continue; + } + + if (hdr.length) { + status = write (client -> fd, buf, hdr.length); + if (status < 0) { + warn ("client_input payload write: %m"); + continue; + } + if (status != hdr.length) { + warn ("client_input payload: short write"); + continue; + } + } + } + + if (buf) + free (buf); +} + +void cleanup () +{ +} + +int commit_leases () +{ + return 0; +} + +int write_lease (lease) + struct lease *lease; +{ + return 0; +} + +void db_startup () +{ +} + +void bootp (packet) + struct packet *packet; +{ +} + +void dhcp (packet) + struct packet *packet; +{ +} + + |