diff options
author | Bob Beck <beck@cvs.openbsd.org> | 2001-06-24 06:05:12 +0000 |
---|---|---|
committer | Bob Beck <beck@cvs.openbsd.org> | 2001-06-24 06:05:12 +0000 |
commit | b05a03077c919111a1996bc750b5680d14414c50 (patch) | |
tree | 0e7ff68ba57f076be7c2acba2b531b69f097a762 /usr.sbin/dhcp/dhclient | |
parent | 31a8df16f90ba9044505180bdd3f03fb36c1ca39 (diff) |
dhcp 2.0pl5 merge/cleanup/deadcode slashing. still needs more eyes on this
but appears to work better than what's been in-tree before for dealing with
stupid dhcp servers.
Diffstat (limited to 'usr.sbin/dhcp/dhclient')
-rw-r--r-- | usr.sbin/dhcp/dhclient/clparse.c | 79 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient-script.8 | 61 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient.8 | 259 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient.c | 2016 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient.conf | 2 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient.conf.5 | 30 | ||||
-rw-r--r-- | usr.sbin/dhcp/dhclient/dhclient.leases.5 | 5 |
7 files changed, 1295 insertions, 1157 deletions
diff --git a/usr.sbin/dhcp/dhclient/clparse.c b/usr.sbin/dhcp/dhclient/clparse.c index 8bf65d1dd0f..5f112c10872 100644 --- a/usr.sbin/dhcp/dhclient/clparse.c +++ b/usr.sbin/dhcp/dhclient/clparse.c @@ -40,18 +40,12 @@ * Enterprises, see ``http://www.vix.com''. */ -#ifndef lint -static char copyright[] = -"$Id: clparse.c,v 1.7 2001/01/06 22:02:23 angelos Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" #include "dhctoken.h" -static TIME parsed_time; - struct client_config top_level_config; -u_int32_t requested_lease_time; + +char client_script_name [] = "/sbin/dhclient-script"; /* client-conf-file :== client-declarations EOF client-declarations :== <nil> @@ -63,9 +57,7 @@ int read_client_conf () FILE *cfile; char *val; int token; - int declaration = 0; struct client_config *config; - struct client_state *state; struct interface_info *ip; new_parse (path_dhclient_conf); @@ -81,10 +73,10 @@ int read_client_conf () top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; top_level_config.retry_interval = 300; - top_level_config.backoff_cutoff = 120; - top_level_config.initial_interval = 10; + top_level_config.backoff_cutoff = 15; + top_level_config.initial_interval = 3; top_level_config.bootp_policy = ACCEPT; - top_level_config.script_name = "/sbin/dhclient-script"; + top_level_config.script_name = client_script_name; top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_SUBNET_MASK; @@ -106,22 +98,19 @@ int read_client_conf () top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_HOST_NAME; - requested_lease_time = htonl(7200); - top_level_config.send_options [DHO_DHCP_LEASE_TIME].data - = (unsigned char *)&requested_lease_time; - top_level_config.send_options [DHO_DHCP_LEASE_TIME].len - = sizeof requested_lease_time; - - if ((cfile = fopen (path_dhclient_conf, "r")) == NULL) - error ("Can't open %s: %m", path_dhclient_conf); - do { - token = peek_token (&val, cfile); - if (token == EOF) - break; - parse_client_statement (cfile, (struct interface_info *)0, - &top_level_config); - } while (1); - token = next_token (&val, cfile); /* Clear the peek buffer */ + + if ((cfile = fopen (path_dhclient_conf, "r")) != NULL) { + do { + token = peek_token (&val, cfile); + if (token == EOF) + break; + parse_client_statement (cfile, + (struct interface_info *)0, + &top_level_config); + } while (1); + token = next_token (&val, cfile); /* Clear the peek buffer */ + fclose (cfile); + } /* Set up state and config structures for clients that don't have per-interface configuration declarations. */ @@ -331,7 +320,6 @@ int parse_X (cfile, buf, max) int token; char *val; int len; - u_int8_t *s; token = peek_token (&val, cfile); if (token == NUMBER_OR_NAME || token == NUMBER) { @@ -425,9 +413,7 @@ void parse_interface_declaration (cfile, outer_config) int token; char *val; - struct interface_info dummy_interface, *ip; - struct client_state dummy_state; - struct client_config dummy_config; + struct interface_info *ip; token = next_token (&val, cfile); if (token != STRING) { @@ -662,7 +648,6 @@ void parse_client_lease_declaration (cfile, lease, ipp) { int token; char *val; - char *t, *n; struct interface_info *ip; switch (next_token (&val, cfile)) { @@ -751,8 +736,10 @@ struct option *parse_option_decl (cfile, options) skip_to_semi (cfile); return (struct option *)0; } - if ((vendor = (char *)strdup (val)) == NULL) + vendor = malloc (strlen (val) + 1); + if (!vendor) error ("no memory for vendor information."); + strlcpy (vendor, val, strlen(val) + 1); token = peek_token (&val, cfile); if (token == DOT) { /* Go ahead and take the DOT token... */ @@ -769,8 +756,9 @@ struct option *parse_option_decl (cfile, options) /* Look up the option name hash table for the specified vendor. */ - universe = (struct universe *)hash_lookup (&universe_hash, - vendor, 0); + universe = ((struct universe *) + hash_lookup (&universe_hash, + (unsigned char *)vendor, 0)); /* If it's not there, we can't parse the rest of the declaration. */ if (!universe) { @@ -786,7 +774,8 @@ struct option *parse_option_decl (cfile, options) } /* Look up the actual option info... */ - option = (struct option *)hash_lookup (universe -> hash, val, 0); + option = (struct option *)hash_lookup (universe -> hash, + (unsigned char *)val, 0); /* If we didn't get an option structure, it's an undefined option. */ if (!option) { @@ -804,11 +793,6 @@ struct option *parse_option_decl (cfile, options) /* Parse the option data... */ do { - /* Set a flag if this is an array of a simple type (i.e., - not an array of pairs of IP addresses, or something - like that. */ - int uniform = option -> format [1] == 'A'; - for (fmt = option -> format; *fmt; fmt++) { if (*fmt == 'A') break; @@ -963,14 +947,17 @@ void parse_string_list (cfile, lp, multiple) return; } +#ifdef OH_THE_HORROR tmp = (struct string_list *)malloc (strlen (val) + 1 + sizeof (struct string_list *)); - if (!tmp) +#endif + tmp = new_string_list(strlen(val) + 1, "parse tmp"); + if (tmp == NULL) error ("no memory for string list entry."); - strcpy (tmp -> string, val); - tmp -> next = (struct string_list *)0; + strlcpy (tmp -> string, val, strlen(val) + 1); + tmp -> next = NULL; /* Store this medium at the end of the media list. */ if (cur) diff --git a/usr.sbin/dhcp/dhclient/dhclient-script.8 b/usr.sbin/dhcp/dhclient/dhclient-script.8 index 42f79a131fa..82212db6cf6 100644 --- a/usr.sbin/dhcp/dhclient/dhclient-script.8 +++ b/usr.sbin/dhcp/dhclient/dhclient-script.8 @@ -35,7 +35,7 @@ .\" Enterprises. To learn more about the Internet Software Consortium, .\" see ``http://www.isc.org/isc''. To learn more about Vixie .\" Enterprises, see ``http://www.vix.com''. -.TH dhclient 8 +.TH dhclient-script 8 .SH NAME dhclient-script - DHCP client network configuration script .SH DESCRIPTION @@ -47,15 +47,49 @@ interface's final configuration once a lease has been acquired. If no lease is acquired, the script is used to test predefined leases, if any, and also called once if no valid lease can be identified. .PP -This script is not meant to be customized by the end user. However, -the script may not work on particular versions of particular operating -systems (indeed, no standard script exists for some operating -systems), so a pioneering user may well need to create a new script or -modify an existing one. In general, customizations specific to a -particular computer should be done in the -.B /etc/dhclient.conf -script. If you find that you can't make such a customization without -customizing dhclient.conf, please submit a bug report. +This script is not meant to be customized by the end user. If local +customizations are needed, they should be possible using the enter and +exit hooks provided (see HOOKS for details). These hooks will allow the +user to override the default behaviour of the client in creating a +.B /etc/resolv.conf +file. +.PP +No standard client script exists for some operating systems, even though +the actual client may work, so a pioneering user may well need to create +a new script or modify an existing one. In general, customizations specific +to a particular computer should be done in the +.B ETCDIR/dhclient.conf +file. If you find that you can't make such a customization without +customizing +.B dhclient-script +or using the enter and exit hooks, please submit a bug report. +.SH HOOKS +When it starts, the client script first defines a shell function, +.B make_resolv_conf , +which is later used to create the +.B /etc/resolv.conf +file. To override the default behaviour, redefine this function in +the enter hook script. +.PP +On after defining the make_resolv_conf function, the client script checks +for the presence of an executable +.B ETCDIR/dhclient-enter-hooks +script, and if present, it invokes the script inline, using the Bourne +shell '.' command. The entire environment documented under OPERATION +is available to this script, which may modify the environment if needed +to change the behaviour of the script. If an error occurs during the +execution of the script, it can set the exit_status variable to a nonzero +value, and +.B ETCDIR/dhclient-script +will exit with that error code immediately after the client script exits. +.PP +After all processing has completed, +.B ETCDIR/dhclient-script +checks for the presence of an executable +.B ETCDIR/dhclient-exit-hooks +script, which if present is invoked using the '.' command. The exit status +is passed in the exit_status shell variable, and will always be zero if the +script succeeded at the task for which it was invoked. .SH OPERATION When dhclient needs to invoke the client configuration script, it writes a shell script into /tmp which defines a variety of variables. @@ -89,7 +123,7 @@ no examples exist yet. The IP address to check is passed in $new_ip_address, and the interface name is passed in $interface. .SH ARPCHECK The DHCP client wants to know if a response to the ARP request send -using ARPCHECK has been received. If one has, the script should exit +using ARPSEND has been received. If one has, the script should exit with a nonzero status, indicating that the offered address has already been requested and should be declined. $new_ip_address and $interface are set as with ARPSEND. @@ -107,9 +141,8 @@ When a binding has been completed, a lot of network parameters are likely to need to be set up. A new /etc/resolv.conf needs to be created, using the values of $new_domain_name and $new_domain_name_servers (which may list more than one server, -separated by spaces). If /etc/resolv.conf.tail exists, it is appended -to the newly-created /etc/resolv.conf file. A default route should -be set using $new_routers, and static routes may need to be set up using +seperated by spaces). A default route should be set using +$new_routers, and static routes may need to be set up using $new_static_routes. .PP If an IP alias has been declared, it must be set up here. The alias diff --git a/usr.sbin/dhcp/dhclient/dhclient.8 b/usr.sbin/dhcp/dhclient/dhclient.8 index 576f08f3c9f..eae843776c7 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.8 +++ b/usr.sbin/dhcp/dhclient/dhclient.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: dhclient.8,v 1.10 2000/10/30 02:35:33 deraadt Exp $ +.\" dhclient.8 .\" .\" Copyright (c) 1997 The Internet Software Consortium. .\" All rights reserved. @@ -35,178 +35,141 @@ .\" Enterprises. To learn more about the Internet Software Consortium, .\" see ``http://www.isc.org/isc''. To learn more about Vixie .\" Enterprises, see ``http://www.vix.com''. -.Dd October 1, 1999 -.Dt DHCLIENT 8 -.Os -.Sh NAME -.Nm dhclient -.Nd Dynamic Host Configuration Protocol (DHCP) Client -.Sh SYNOPSIS -.Nm -.Op Fl 1du -.Op Fl p Ar port -.Op Ar interface ... -.Sh DESCRIPTION -The -.Nm -utility provides a means for configuring network interfaces using DHCP, BOOTP, -or if these protocols fail, by statically assigning an address. -.Pp -The names of the network interfaces that -.Nm -should attempt to -configure may be specified on the command line. -If no interface names are given, -.Nm -will identify all network -interfaces, eliminating non-broadcast interfaces if possible, and -attempt to configure each one. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl 1 -Forces -.Nm -to exit if it failed to configure an interface. -.It Fl d -Forces -.Nm -to always run as a foreground process. -By default, -.Nm -runs in the foreground until it has configured an interface, and then -will revert to running in the background. -.It Fl u -Forces dhclient to reject leases with unknown options in them. The default -behaviour is to accept such lease offers -.It Fl p Ar port -Specifies the UDP -.Ar port -.Nm -should listen on, instead of the default (68). -.El -.Pp +.TH dhclient 8 +.SH NAME +dhclient - Dynamic Host Configuration Protocol Client +.SH SYNOPSIS +.B dhclient +[ +.B -p +.I port +] +[ +.B -d +] +[ +.I if0 +[ +.I ...ifN +] +] +.SH DESCRIPTION +The Internet Software Consortium DHCP Client, dhclient, provides a +means for configuring one or more network interfaces using the Dynamic +Host Configuration Protocol, BOOTP protocol, or if these protocols +fail, by statically assigning an address. +.SH OPERATION +.PP The DHCP protocol allows a host to contact a central server which maintains a list of IP addresses which may be assigned on one or more -subnets. -A DHCP client may request an address from this pool, and -then use it on a temporary basis for communication on the network. -The DHCP protocol also provides a mechanism whereby a client can learn +subnets. A DHCP client may request an address from this pool, and +then use it on a temporary basis for communication on network. The +DHCP protocol also provides a mechanism whereby a client can learn important details about the network to which it is attached, such as the location of a default router, the location of a name server, and so on. -.Pp -On startup, -.Nm -reads -.Pa /etc/dhclient.conf -for configuration instructions. -It then gets a list of all the -network interfaces that are configured in the current system. -It then attempts to configure each interface with DHCP. -.Pp +.PP +On startup, dhclient reads the +.IR dhclient.conf +for configuration instructions. It then gets a list of all the +network interfaces that are configured in the current system. For +each interface, it attempts to configure the interface using the DHCP +protocol. +.PP In order to keep track of leases across system reboots and server -restarts, -.Nm -keeps a list of leases it has been assigned in the -.Pa /var/db/dhclient.leases -file. -On startup, after reading the -.Pa dhclient.conf -file, -.Nm -reads the leases file to refresh its memory about what leases it has been -assigned. -.Pp -When a new lease is acquired, it is appended to the end of -.Pa /var/db/dhclient.leases . -In order to prevent the file from becoming arbitrarily large, from time to time -.Nm -creates a new -.Pa dhclient.leases -file from its in-core lease database. -The old version of is retained under the name -.Pa /var/db/dhcpd.leases~ -until the next time -.Nm -rewrites the database. -.Pp +restarts, dhclient keeps a list of leases it has been assigned in the +dhclient.leases(5) file. On startup, after reading the dhclient.conf +file, dhclient reads the dhclient.leases file to refresh its memory +about what leases it has been assigned. +.PP +When a new lease is acquired, it is appended to the end of the +dhclient.leases file. In order to prevent the file from becoming +arbitrarily large, from time to time dhclient creates a new +dhclient.leases file from its in-core lease database. The old version +of the dhclient.leases file is retained under the name +.IR dhcpd.leases~ +until the next time dhclient rewrites the database. +.PP Old leases are kept around in case the DHCP server is unavailable when -.Nm -is first invoked (generally during the initial system boot -process). -In that event, old leases from the -.Pa dhclient.leases -file which have not yet expired are tested, and if they are determined to +dhclient is first invoked (generally during the initial system boot +process). In that event, old leases from the dhclient.leases file +which have not yet expired are tested, and if they are determined to be valid, they are used until either they expire or the DHCP server becomes available. -.Pp +.PP A mobile host which may sometimes need to access a network on which no DHCP server exists may be preloaded with a lease for a fixed -address on that network. -When all attempts to contact a DHCP server have failed, -.Nm -will try to validate the static lease, and if it -succeeds, it will use that lease until it is restarted. -.Pp +address on that network. When all attempts to contact a DHCP server +have failed, dhclient will try to validate the static lease, and if it +succeeds, will use that lease until it is restarted. +.PP A mobile host may also travel to some networks on which DHCP is not -available but BOOTP is. -In that case, it may be advantageous to +available but BOOTP is. In that case, it may be advantageous to arrange with the network administrator for an entry on the BOOTP database, so that the host can boot quickly on that network rather than cycling through the list of old leases. -.Sh NOTES -You must have the Berkeley Packet Filter (BPF) configured in your kernel. -.Nm -requires at least one -.Pa /dev/bpf* -file for each broadcast network interface that is attached to your system. -See -.Xr bpf 4 -for more information. -.Sh FILES -.Bl -tag -width /var/db/dhclient.leases~ -compact -.It Pa /etc/dhclient.conf -DHCP client configuration file -.It Pa /var/db/dhclient.leases -database of acquired leases -.It Pa /var/db/dhclient.leases~ -backup of dhclient.leases -.It Pa /var/run/dhclient.pid -process ID of -.Nm -.El -.Sh SEE ALSO -.Xr dhclient.conf 5 , -.Xr dhclient.leases 5 , -.Xr dhclient-script 8 , -.Xr dhcp 8 , -.Xr dhcpd 8 , -.Xr dhcrelay 8 -.Sh AUTHOR -.Nm +.SH COMMAND LINE +.PP +The names of the network interfaces that dhclient should attempt to +configure may be specified on the command line. If no interface names +are specified on the command line dhclient will identify all network +interfaces, elimininating non-broadcast interfaces if possible, and +attempt to configure each interface. +.PP +If dhclient should listen and transmit on a port other than the +standard (port 68), the +.B -p +flag may used. It should be followed by the udp port number that +dhclient should use. This is mostly useful for debugging purposes. +If the +.B -p +flag is specified, the client will transmit responses to servers at a +port number that is one less than the one specified - i.e., if you +specify +.B -p +68, then the client will listen on port 68 and transmit to port 67. +Datagrams that must go through relay agents are sent to the port +number specified with the +.B -p +flag - if you wish to use alternate port numbers, you must configure +any relay agents you are using to use the same alternate port numbers. +.PP +Dhclient will normally run in the foreground until it has configured +an interface, and then will revert to running in the background. +To run force dhclient to always run as a foreground process, the +.B -d +flag should be specified. This is useful when running dhclient under +a debugger, or when running it out of inittab on System V systems. +.PP +.SH CONFIGURATION +The syntax of the dhclient.conf(8) file is discussed seperately. +.SH FILES +.B ETCDIR/dhclient.conf, DBDIR/dhclient.leases, RUNDIR/dhclient.pid, +.B DBDIR/dhclient.leases~. +.SH SEE ALSO +dhcpd(8), dhcrelay(8), dhclient.conf(5), dhclient.leases(5) +.SH AUTHOR +.B dhclient(8) has been written for the Internet Software Consortium by Ted Lemon <mellon@fugue.com> in cooperation with Vixie -Enterprises. -To learn more about the Internet Software Consortium, see -.Pp -.Dl http://www.vix.com/isc. -.Pp -To learn more about Vixie Enterprises, see -.Pp -.Dl http://www.vix.com. -.Pp +Enterprises. To learn more about the Internet Software Consortium, +see +.B http://www.vix.com/isc. +To learn more about Vixie +Enterprises, see +.B http://www.vix.com. +.PP This client was substantially modified and enhanced by Elliot Poger for use on Linux while he was working on the MosquitoNet project at Stanford. -.Pp +.PP The current version owes much to Elliot's Linux enhancements, but was substantially reorganized and partially rewritten by Ted Lemon so as to use the same networking framework that the Internet Software -Consortium DHCP server uses. -Much system-specific configuration code +Consortium DHCP server uses. Much system-specific configuration code was moved into a shell script so that as support for more operating systems is added, it will not be necessary to port and maintain system-specific configuration code to these operating systems - instead, the shell script can invoke the native tools to accomplish the same purpose. +.PP diff --git a/usr.sbin/dhcp/dhclient/dhclient.c b/usr.sbin/dhcp/dhclient/dhclient.c index 848b9d9fea3..50fdb0ba47d 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.c +++ b/usr.sbin/dhcp/dhclient/dhclient.c @@ -3,8 +3,8 @@ DHCP Client. */ /* - * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * The Internet Software Consortium. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -54,26 +54,21 @@ * purpose. */ -#ifndef lint -static char copyright[] = -"$Id: dhclient.c,v 1.17 2001/06/04 23:41:56 angelos Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - #include "dhcpd.h" - +#include "version.h" #define PERIOD 0x2e -#define hyphenchar(c) ((c) == 0x2d) +#define hyphenchar(c) ((c) == 0x2d) #define bslashchar(c) ((c) == 0x5c) #define periodchar(c) ((c) == PERIOD) #define asterchar(c) ((c) == 0x2a) #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ - || ((c) >= 0x61 && (c) <= 0x7a)) + || ((c) >= 0x61 && (c) <= 0x7a)) #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) #define borderchar(c) (alphachar(c) || digitchar(c)) #define middlechar(c) (borderchar(c) || hyphenchar(c)) -#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) TIME cur_time; TIME default_lease_time = 43200; /* 12 hours... */ @@ -82,6 +77,7 @@ struct tree_cache *global_options [256]; char *path_dhclient_conf = _PATH_DHCLIENT_CONF; char *path_dhclient_db = _PATH_DHCLIENT_DB; +char *path_dhclient_pid = _PATH_DHCLIENT_PID; int interfaces_requested = 0; @@ -96,23 +92,29 @@ struct sockaddr_in sockaddr_broadcast; assert (state_is == state_shouldbe). */ #define ASSERT_STATE(state_is, state_shouldbe) {} -#ifdef USE_FALLBACK -struct interface_info fallback_interface; -#endif - u_int16_t local_port; u_int16_t remote_port; int log_priority; int no_daemon; -int onetry; +int save_scripts; +int onetry = 0; int unknown_ok = 1; -static void usage PROTO ((void)); +static char copyright[] = +"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium."; +static char arr [] = "All rights reserved."; +static char message [] = "Internet Software Consortium DHCP Client"; +static char contrib [] = "Please contribute if you find this software useful."; +static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html"; + +static void usage PROTO ((char *)); static int check_option (struct client_lease *l, int option); static int ipv4addrs(char * buf); +static int res_hnok(const char *dn); + int main (argc, argv, envp) int argc; char **argv, **envp; @@ -120,24 +122,55 @@ int main (argc, argv, envp) int i, fd; struct servent *ent; struct interface_info *ip; + int seed; + int quiet = 0; + char *s; + + s = strrchr (argv [0], '/'); + if (!s) + s = argv [0]; + else + s++; + + /* Initially, log errors to stderr as well as to syslogd. */ + openlog (s, LOG_NDELAY, DHCPD_LOG_FACILITY); - openlog ("dhclient", LOG_NDELAY, LOG_DAEMON); +#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__)) + setlogmask (LOG_UPTO (LOG_INFO)); +#endif for (i = 1; i < argc; i++) { if (!strcmp (argv [i], "-p")) { if (++i == argc) - usage (); - local_port = htons (atoi (argv [i])); - debug ("binding to user-specified port %d", - ntohs (local_port)); + usage (s); + local_port = htons(atoi(argv [i])); + debug("binding to user-specified port %d", + ntohs(local_port)); } else if (!strcmp (argv [i], "-d")) { no_daemon = 1; + } else if (!strcmp (argv [i], "-D")) { + save_scripts = 1; + } else if (!strcmp (argv [i], "-cf")) { + if (++i == argc) + usage (s); + path_dhclient_conf = argv [i]; + } else if (!strcmp (argv [i], "-pf")) { + if (++i == argc) + usage (s); + path_dhclient_pid = argv [i]; + } else if (!strcmp (argv [i], "-lf")) { + if (++i == argc) + usage (s); + path_dhclient_db = argv [i]; + } else if (!strcmp (argv [i], "-q")) { + quiet = 1; + quiet_interface_discovery = 1; } else if (!strcmp (argv [i], "-u")) { unknown_ok = 0; } else if (!strcmp (argv [i], "-1")) { onetry = 1; } else if (argv [i][0] == '-') { - usage (); + usage (s); } else { struct interface_info *tmp = ((struct interface_info *) @@ -146,75 +179,83 @@ int main (argc, argv, envp) error ("Insufficient memory to %s %s", "record interface", argv [i]); memset (tmp, 0, sizeof *tmp); - strlcpy (tmp -> name, argv [i], IFNAMSIZ); - tmp -> next = interfaces; - tmp -> flags = INTERFACE_REQUESTED; + strlcpy (tmp->name, argv [i], IFNAMSIZ); + tmp->next = interfaces; + tmp->flags = INTERFACE_REQUESTED; interfaces_requested = 1; interfaces = tmp; } } + + if (!quiet) { + note("%s %s", message, DHCP_VERSION); + } else + log_perror = 0; + /* Default to the DHCP/BOOTP port. */ if (!local_port) { - ent = getservbyname ("dhcpc", "udp"); + ent = getservbyname("dhcpc", "udp"); if (!ent) - local_port = htons (68); + local_port = htons(68); else - local_port = ent -> s_port; + local_port = ent->s_port; } - remote_port = htons (ntohs (local_port) - 1); /* XXX */ + remote_port = htons(ntohs(local_port) - 1); /* XXX */ /* Get the current time... */ - GET_TIME (&cur_time); + GET_TIME(&cur_time); sockaddr_broadcast.sin_family = AF_INET; sockaddr_broadcast.sin_port = remote_port; sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; -#ifdef HAVE_SA_LEN sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast; -#endif inaddr_any.s_addr = INADDR_ANY; /* Discover all the network interfaces. */ - discover_interfaces (DISCOVER_UNCONFIGURED); + discover_interfaces(DISCOVER_UNCONFIGURED); /* Parse the dhclient.conf file. */ - read_client_conf (); + read_client_conf(); /* Lock the leases file */ - fd = open (path_dhclient_db, O_RDONLY | O_EXLOCK | O_CREAT, 0); + fd = open(path_dhclient_db, O_RDONLY | O_EXLOCK | O_CREAT, 0); if (fd < 0) - error ("can't open and lock %s: %m", path_dhclient_db); + error("can't open and lock %s: %m", path_dhclient_db); /* Parse the lease database. */ - read_client_leases (); + read_client_leases(); /* Rewrite the lease database... */ - rewrite_client_leases (); + rewrite_client_leases(); /* Close and unlock */ close(fd); - + /* If no broadcast interfaces were discovered, call the script and tell it so. */ if (!interfaces) { - script_init ((struct interface_info *)0, "NBI", + script_init((struct interface_info *)0, "NBI", (struct string_list *)0); - script_go ((struct interface_info *)0); + script_go((struct interface_info *)0); + note("No broadcast interfaces found - exiting."); /* Nothing more to do. */ - exit (0); + exit(0); } else { /* Call the script with the list of interfaces. */ - for (ip = interfaces; ip; ip = ip -> next) { - if ((interfaces_requested == 0) || - (ip->flags == INTERFACE_REQUESTED)) { - script_init (ip, "PREINIT", - (struct string_list *)0); - if (ip -> client -> alias) - script_write_params(ip, "alias_", - ip->client->alias); - script_go (ip); - } + for (ip = interfaces; ip; ip = ip->next) { + /* If interfaces were specified, don't configure + interfaces that weren't specified! */ + if (interfaces_requested && + ((ip->flags & (INTERFACE_REQUESTED | + INTERFACE_AUTOMATIC)) != + INTERFACE_REQUESTED)) + continue; + script_init(ip, "PREINIT", (struct string_list *)0); + if (ip->client->alias) + script_write_params(ip, "alias_", + ip->client->alias); + script_go(ip); } } @@ -222,44 +263,67 @@ int main (argc, argv, envp) are relevant should be running, so now we once again call discover_interfaces(), and this time ask it to actually set up the interfaces. */ - discover_interfaces (interfaces_requested + discover_interfaces(interfaces_requested ? DISCOVER_REQUESTED : DISCOVER_RUNNING); + /* Make up a seed for the random number generator from current + time plus the sum of the last four bytes of each + interface's hardware address interpreted as an integer. + Not much entropy, but we're booting, so we're not likely to + find anything better. */ + seed = 0; /* Unfortunately, what's on the stack isn't random. :') */ + for(ip = interfaces; ip; ip = ip->next) { + int junk; + memcpy(&junk, + &ip->hw_address.haddr [ip->hw_address.hlen - + sizeof seed], sizeof seed); + seed += junk; + } + srandom(seed + cur_time); + /* Start a configuration state machine for each interface. */ - for (ip = interfaces; ip; ip = ip -> next) { - ip -> client -> state = S_INIT; - state_reboot (ip); + for(ip = interfaces; ip; ip = ip->next) { + ip->client->state = S_INIT; + state_reboot(ip); } /* Set up the bootp packet handler... */ bootp_packet_handler = do_packet; /* Start dispatching packets and timeouts... */ - dispatch (); + dispatch(); /*NOTREACHED*/ return 0; } -static void usage () +static void usage (appname) + char *appname; { - error ("Usage: dhclient [-1] [-c] [-p <port>] [interface]"); + note("%s", message); + note("%s", copyright); + note("%s", arr); + note(""); + note("%s", contrib); + note("%s", url); + note(""); + + warn("Usage: %s [-c1u] [-p <port>] [-lf lease-file]", appname); + error(" [-pf pidfile] [interface]"); } void cleanup () { - /* Make sure the pidfile is gone. */ - (void) unlink (_PATH_DHCLIENT_PID); } /* Individual States: * * Each routine is called from the dhclient_state_machine() in one of * these conditions: - * -> entering INIT state - * -> recvpacket_flag == 0: timeout in this state - * -> otherwise: received a packet in this state + *->entering INIT state + *->recvpacket_flag == 0: timeout in this state + *->otherwise: received a packet in this state * * Return conditions as handled by dhclient_state_machine(): * Returns 1, sendpacket_flag = 1: send packet, reset timer. @@ -288,25 +352,29 @@ void state_reboot (ipp) struct interface_info *ip = ipp; /* If we don't remember an active lease, go straight to INIT. */ - if (!ip -> client -> active || - ip -> client -> active -> is_bootp) { + if (!ip->client->active || + ip->client->active->is_bootp) { state_init (ip); return; } /* We are in the rebooting state. */ - ip -> client -> state = S_REBOOTING; + ip->client->state = S_REBOOTING; + + /* make_request doesn't initialize xid because it normally comes + from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER, + so pick an xid now. */ + ip->client->xid = random (); /* Make a DHCPREQUEST packet, and set appropriate per-interface flags. */ - make_request (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; - ip -> client -> destination = iaddr_broadcast; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; + make_request (ip, ip->client->active); + ip->client->destination = iaddr_broadcast; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; /* Zap the medium list... */ - ip -> client -> medium = (struct string_list *)0; + ip->client->medium = (struct string_list *)0; /* Send out the first DHCPREQUEST packet. */ send_request (ip); @@ -324,12 +392,12 @@ void state_init (ipp) /* Make a DHCPDISCOVER packet, and set appropriate per-interface flags. */ - make_discover (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; - ip -> client -> destination = iaddr_broadcast; - ip -> client -> state = S_SELECTING; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; + make_discover (ip, ip->client->active); + ip->client->xid = ip->client->packet.xid; + ip->client->destination = iaddr_broadcast; + ip->client->state = S_SELECTING; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; /* Add an immediate timeout to cause the first DHCPDISCOVER packet to go out. */ @@ -357,13 +425,13 @@ void state_selecting (ipp) the only criterion by which we judge leases is whether or not we get a response when we arp for them. */ picked = (struct client_lease *)0; - for (lp = ip -> client -> offered_leases; lp; lp = next) { - next = lp -> next; + for (lp = ip->client->offered_leases; lp; lp = next) { + next = lp->next; /* Check to see if we got an ARPREPLY for the address in this particular lease. */ if (!picked) { - script_init (ip, "ARPCHECK", lp -> medium); + script_init (ip, "ARPCHECK", lp->medium); script_write_params (ip, "check_", lp); /* If the ARPCHECK code detects another @@ -376,33 +444,33 @@ void state_selecting (ipp) goto freeit; } picked = lp; - picked -> next = (struct client_lease *)0; + picked->next = (struct client_lease *)0; } else { freeit: free_client_lease (lp); } } - ip -> client -> offered_leases = (struct client_lease *)0; + ip->client->offered_leases = (struct client_lease *)0; /* If we just tossed all the leases we were offered, go back to square one. */ if (!picked) { - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; state_init (ip); return; } /* If it was a BOOTREPLY, we can just take the address right now. */ - if (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) { - ip -> client -> new = picked; + if (!picked->options [DHO_DHCP_MESSAGE_TYPE].len) { + ip->client->new = picked; /* Make up some lease expiry times XXX these should be configurable. */ - ip -> client -> new -> expiry = cur_time + 12000; - ip -> client -> new -> renewal += cur_time + 8000; - ip -> client -> new -> rebind += cur_time + 10000; + ip->client->new->expiry = cur_time + 12000; + ip->client->new->renewal += cur_time + 8000; + ip->client->new->rebind += cur_time + 10000; - ip -> client -> state = S_REQUESTING; + ip->client->state = S_REQUESTING; /* Bind to the address we received. */ bind_lease (ip); @@ -410,14 +478,14 @@ void state_selecting (ipp) } /* Go to the REQUESTING state. */ - ip -> client -> destination = iaddr_broadcast; - ip -> client -> state = S_REQUESTING; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; + ip->client->destination = iaddr_broadcast; + ip->client->state = S_REQUESTING; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; /* Make a DHCPREQUEST packet from the lease we picked. */ make_request (ip, picked); - ip -> client -> xid = ip -> client -> packet.xid; + ip->client->xid = ip->client->packet.xid; /* Toss the lease we picked - we'll get it back in a DHCPACK. */ free_client_lease (picked); @@ -432,26 +500,33 @@ void state_selecting (ipp) void dhcpack (packet) struct packet *packet; { - struct interface_info *ip = packet -> interface; + struct interface_info *ip = packet->interface; struct client_lease *lease; - int i; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ - if (packet -> interface -> client -> xid != packet -> raw -> xid) { + if (packet->interface->client->xid != packet->raw->xid || + (packet->interface->hw_address.hlen != + packet->raw->hlen) || + (memcmp (packet->interface->hw_address.haddr, + packet->raw->chaddr, packet->raw->hlen))) { +#if defined (DEBUG) debug ("DHCPACK in wrong transaction."); +#endif return; } - if (ip -> client -> state != S_REBOOTING && - ip -> client -> state != S_REQUESTING && - ip -> client -> state != S_RENEWING && - ip -> client -> state != S_REBINDING) { + if (ip->client->state != S_REBOOTING && + ip->client->state != S_REQUESTING && + ip->client->state != S_RENEWING && + ip->client->state != S_REBINDING) { +#if defined (DEBUG) debug ("DHCPACK in wrong state."); +#endif return; } - note ("DHCPACK from %s", piaddr (packet -> client_addr)); + note ("DHCPACK from %s", piaddr (packet->client_addr)); lease = packet_to_lease (packet); if (!lease) { @@ -459,43 +534,54 @@ void dhcpack (packet) return; } - ip -> client -> new = lease; + ip->client->new = lease; /* Stop resending DHCPREQUEST. */ cancel_timeout (send_request, ip); /* Figure out the lease time. */ - if (ip -> client -> new -> options [DHO_DHCP_LEASE_TIME].data) - ip -> client -> new -> expiry = - getULong (ip -> client -> - new -> options [DHO_DHCP_LEASE_TIME].data); + if (ip->client->new->options [DHO_DHCP_LEASE_TIME].data) + ip->client->new->expiry = + getULong (ip->client -> + new->options [DHO_DHCP_LEASE_TIME].data); else - ip -> client -> new -> expiry = default_lease_time; + ip->client->new->expiry = default_lease_time; + /* A number that looks negative here is really just very large, + because the lease expiry offset is unsigned. */ + if (ip->client->new->expiry < 0) + ip->client->new->expiry = TIME_MAX; /* Take the server-provided renewal time if there is one; otherwise figure it out according to the spec. */ - if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len) - ip -> client -> new -> renewal = - getULong (ip -> client -> - new -> options [DHO_DHCP_RENEWAL_TIME].data); + if (ip->client->new->options [DHO_DHCP_RENEWAL_TIME].len) + ip->client->new->renewal = + getULong (ip->client -> + new->options [DHO_DHCP_RENEWAL_TIME].data); else - ip -> client -> new -> renewal = - ip -> client -> new -> expiry / 2; + ip->client->new->renewal = + ip->client->new->expiry / 2; /* Same deal with the rebind time. */ - if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len) - ip -> client -> new -> rebind = - getULong (ip -> client -> new -> + if (ip->client->new->options [DHO_DHCP_REBINDING_TIME].len) + ip->client->new->rebind = + getULong (ip->client->new -> options [DHO_DHCP_REBINDING_TIME].data); else - ip -> client -> new -> rebind = - ip -> client -> new -> renewal + - ip -> client -> new -> renewal / 2 + - ip -> client -> new -> renewal / 4; - - ip -> client -> new -> expiry += cur_time; - ip -> client -> new -> renewal += cur_time; - ip -> client -> new -> rebind += cur_time; + ip->client->new->rebind = + ip->client->new->renewal + + ip->client->new->renewal / 2 + + ip->client->new->renewal / 4; + + ip->client->new->expiry += cur_time; + /* Lease lengths can never be negative. */ + if (ip->client->new->expiry < cur_time) + ip->client->new->expiry = TIME_MAX; + ip->client->new->renewal += cur_time; + if (ip->client->new->renewal < cur_time) + ip->client->new->renewal = TIME_MAX; + ip->client->new->rebind += cur_time; + if (ip->client->new->rebind < cur_time) + ip->client->new->rebind = TIME_MAX; bind_lease (ip); } @@ -503,51 +589,41 @@ void dhcpack (packet) void bind_lease (ip) struct interface_info *ip; { - int fd; - /* Remember the medium. */ - ip -> client -> new -> medium = ip -> client -> medium; - - /* Lock the leases file */ - fd = open (path_dhclient_db, O_RDONLY | O_EXLOCK | O_CREAT, 0); - if (fd < 0) - error ("can't open and lock %s: %m", path_dhclient_db); + ip->client->new->medium = ip->client->medium; /* Write out the new lease. */ - write_client_lease (ip, ip -> client -> new); - - /* Close and unlock lease file */ - close(fd); + write_client_lease (ip, ip->client->new, 0); /* Run the client script with the new parameters. */ - script_init (ip, (ip -> client -> state == S_REQUESTING + script_init (ip, (ip->client->state == S_REQUESTING ? "BOUND" - : (ip -> client -> state == S_RENEWING + : (ip->client->state == S_RENEWING ? "RENEW" - : (ip -> client -> state == S_REBOOTING + : (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))), - ip -> client -> new -> medium); - if (ip -> client -> active && ip -> client -> state != S_REBOOTING) - script_write_params (ip, "old_", ip -> client -> active); - script_write_params (ip, "new_", ip -> client -> new); - if (ip -> client -> alias) - script_write_params (ip, "alias_", ip -> client -> alias); + ip->client->new->medium); + if (ip->client->active && ip->client->state != S_REBOOTING) + script_write_params (ip, "old_", ip->client->active); + script_write_params (ip, "new_", ip->client->new); + if (ip->client->alias) + script_write_params (ip, "alias_", ip->client->alias); script_go (ip); /* Replace the old active lease with the new one. */ - if (ip -> client -> active) - free_client_lease (ip -> client -> active); - ip -> client -> active = ip -> client -> new; - ip -> client -> new = (struct client_lease *)0; + if (ip->client->active) + free_client_lease (ip->client->active); + ip->client->active = ip->client->new; + ip->client->new = (struct client_lease *)0; /* Set up a timeout to start the renewal process. */ - add_timeout (ip -> client -> active -> renewal, + add_timeout (ip->client->active->renewal, state_bound, ip); note ("bound to %s -- renewal in %d seconds.", - piaddr (ip -> client -> active -> address), - ip -> client -> active -> renewal - cur_time); - ip -> client -> state = S_BOUND; + piaddr (ip->client->active->address), + ip->client->active->renewal - cur_time); + ip->client->state = S_BOUND; reinitialize_interfaces (); go_daemon (); } @@ -565,21 +641,21 @@ void state_bound (ipp) ASSERT_STATE(state, S_BOUND); /* T1 has expired. */ - make_request (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; + make_request (ip, ip->client->active); + ip->client->xid = ip->client->packet.xid; - if (ip -> client -> active -> + if (ip->client->active -> options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) { - memcpy (ip -> client -> destination.iabuf, - ip -> client -> active -> + memcpy (ip->client->destination.iabuf, + ip->client->active -> options [DHO_DHCP_SERVER_IDENTIFIER].data, 4); - ip -> client -> destination.len = 4; + ip->client->destination.len = 4; } else - ip -> client -> destination = iaddr_broadcast; + ip->client->destination = iaddr_broadcast; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = ip -> client -> config -> initial_interval; - ip -> client -> state = S_RENEWING; + ip->client->first_sending = cur_time; + ip->client->interval = ip->client->config->initial_interval; + ip->client->state = S_RENEWING; /* Send the first packet immediately. */ send_request (ip); @@ -605,16 +681,16 @@ void bootp (packet) { struct iaddrlist *ap; - if (packet -> raw -> op != BOOTREPLY) + if (packet->raw->op != BOOTREPLY) return; /* If there's a reject list, make sure this packet's sender isn't on it. */ - for (ap = packet -> interface -> client -> config -> reject_list; - ap; ap = ap -> next) { - if (addr_eq (packet -> client_addr, ap -> addr)) { + for (ap = packet->interface->client->config->reject_list; + ap; ap = ap->next) { + if (addr_eq (packet->client_addr, ap->addr)) { note ("BOOTREPLY from %s rejected.", - piaddr (ap -> addr)); + piaddr (ap->addr)); return; } } @@ -630,7 +706,7 @@ void dhcp (packet) void (*handler) PROTO ((struct packet *)); char *type; - switch (packet -> packet_type) { + switch (packet->packet_type) { case DHCPOFFER: handler = dhcpoffer; type = "DHCPOFFER"; @@ -656,25 +732,24 @@ void dhcp (packet) * can set yiaddr to 0 on non-DHCPNAK packets * we ignore those here. */ - struct in_addr tmp; - memset(&tmp, 0, sizeof(struct in_addr)); - - if (memcmp(&tmp, &packet -> raw -> yiaddr, sizeof(tmp)) == 0) - { - note ( - "%s from %s rejected due to bogus yiaddr of 0.0.0.0.", - type, piaddr (packet->client_addr)); - return; - } + struct in_addr tmp; + memset(&tmp, 0, sizeof(struct in_addr)); + + if (memcmp(&tmp, &packet->raw->yiaddr, sizeof(tmp)) == 0) + { + note("%s from %s rejected due to bogus yiaddr of 0.0.0.0.", + type, piaddr (packet->client_addr)); + return; + } } /* If there's a reject list, make sure this packet's sender isn't on it. */ - for (ap = packet -> interface -> client -> config -> reject_list; - ap; ap = ap -> next) { - if (addr_eq (packet -> client_addr, ap -> addr)) { + for (ap = packet->interface->client->config->reject_list; + ap; ap = ap->next) { + if (addr_eq (packet->client_addr, ap->addr)) { note ("%s from %s rejected.", - type, piaddr (ap -> addr)); + type, piaddr (ap->addr)); return; } } @@ -684,13 +759,12 @@ void dhcp (packet) void dhcpoffer (packet) struct packet *packet; { - struct interface_info *ip = packet -> interface; + struct interface_info *ip = packet->interface; struct client_lease *lease, *lp; int i; int arp_timeout_needed, stop_selecting; - char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len + char *name = (packet->options [DHO_DHCP_MESSAGE_TYPE].len ? "DHCPOFFER" : "BOOTREPLY"); - struct iaddrlist *ap; #ifdef DEBUG_PACKET dump_packet (packet); @@ -698,19 +772,25 @@ void dhcpoffer (packet) /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ - if (ip -> client -> state != S_SELECTING || - packet -> interface -> client -> xid != packet -> raw -> xid) { + if (ip->client->state != S_SELECTING || + packet->interface->client->xid != packet->raw->xid || + (packet->interface->hw_address.hlen != + packet->raw->hlen) || + (memcmp (packet->interface->hw_address.haddr, + packet->raw->chaddr, packet->raw->hlen))) { +#if defined (DEBUG) debug ("%s in wrong transaction.", name); +#endif return; } - note ("%s from %s", name, piaddr (packet -> client_addr)); + note ("%s from %s", name, piaddr (packet->client_addr)); /* If this lease doesn't supply the minimum required parameters, blow it off. */ - for (i = 0; ip -> client -> config -> required_options [i]; i++) { - if (!packet -> options [ip -> client -> config -> + for (i = 0; ip->client->config->required_options [i]; i++) { + if (!packet->options [ip->client->config -> required_options [i]].len) { note ("%s isn't satisfactory.", name); return; @@ -718,11 +798,11 @@ void dhcpoffer (packet) } /* If we've already seen this lease, don't record it again. */ - for (lease = ip -> client -> offered_leases; - lease; lease = lease -> next) { - if (lease -> address.len == sizeof packet -> raw -> yiaddr && - !memcmp (lease -> address.iabuf, - &packet -> raw -> yiaddr, lease -> address.len)) { + for (lease = ip->client->offered_leases; + lease; lease = lease->next) { + if (lease->address.len == sizeof packet->raw->yiaddr && + !memcmp (lease->address.iabuf, + &packet->raw->yiaddr, lease->address.len)) { debug ("%s already seen.", name); return; } @@ -736,14 +816,14 @@ void dhcpoffer (packet) /* If this lease was acquired through a BOOTREPLY, record that fact. */ - if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len) - lease -> is_bootp = 1; + if (!packet->options [DHO_DHCP_MESSAGE_TYPE].len) + lease->is_bootp = 1; /* Record the medium under which this lease was offered. */ - lease -> medium = ip -> client -> medium; + lease->medium = ip->client->medium; /* Send out an ARP Request for the offered IP address. */ - script_init (ip, "ARPSEND", lease -> medium); + script_init (ip, "ARPSEND", lease->medium); script_write_params (ip, "check_", lease); /* If the script can't send an ARP request without waiting, we'll be waiting when we do the ARPCHECK, so don't wait now. */ @@ -753,35 +833,35 @@ void dhcpoffer (packet) arp_timeout_needed = 2; /* Figure out when we're supposed to stop selecting. */ - stop_selecting = (ip -> client -> first_sending + - ip -> client -> config -> select_interval); + stop_selecting = (ip->client->first_sending + + ip->client->config->select_interval); /* If this is the lease we asked for, put it at the head of the list, and don't mess with the arp request timeout. */ - if (lease -> address.len == ip -> client -> requested_address.len && - !memcmp (lease -> address.iabuf, - ip -> client -> requested_address.iabuf, - ip -> client -> requested_address.len)) { - lease -> next = ip -> client -> offered_leases; - ip -> client -> offered_leases = lease; + if (lease->address.len == ip->client->requested_address.len && + !memcmp (lease->address.iabuf, + ip->client->requested_address.iabuf, + ip->client->requested_address.len)) { + lease->next = ip->client->offered_leases; + ip->client->offered_leases = lease; } else { /* If we already have an offer, and arping for this offer would take us past the selection timeout, then don't extend the timeout - just hope for the best. */ - if (ip -> client -> offered_leases && + if (ip->client->offered_leases && (cur_time + arp_timeout_needed) > stop_selecting) arp_timeout_needed = 0; /* Put the lease at the end of the list. */ - lease -> next = (struct client_lease *)0; - if (!ip -> client -> offered_leases) - ip -> client -> offered_leases = lease; + lease->next = (struct client_lease *)0; + if (!ip->client->offered_leases) + ip->client->offered_leases = lease; else { - for (lp = ip -> client -> offered_leases; lp -> next; - lp = lp -> next) + for (lp = ip->client->offered_leases; lp->next; + lp = lp->next) ; - lp -> next = lease; + lp->next = lease; } } @@ -822,23 +902,23 @@ struct client_lease *packet_to_lease (packet) /* Copy the lease options. */ for (i = 0; i < 256; i++) { - if (packet -> options [i].len) { - lease -> options [i].data = + if (packet->options [i].len) { + lease->options [i].data = (unsigned char *) - malloc (packet -> options [i].len + 1); - if (!lease -> options [i].data) { + malloc (packet->options [i].len + 1); + if (!lease->options [i].data) { warn ("dhcpoffer: no memory for option %d\n", i); free_client_lease (lease); return (struct client_lease *)0; } else { - memcpy (lease -> options [i].data, - packet -> options [i].data, - packet -> options [i].len); - lease -> options [i].len = - packet -> options [i].len; - lease -> options [i].data - [lease -> options [i].len] = 0; + memcpy (lease->options [i].data, + packet->options [i].data, + packet->options [i].len); + lease->options [i].len = + packet->options [i].len; + lease->options [i].data + [lease->options [i].len] = 0; } if (!check_option(lease,i)) { /* ignore a bogus lease offer */ @@ -849,37 +929,37 @@ struct client_lease *packet_to_lease (packet) } } - lease -> address.len = sizeof (packet -> raw -> yiaddr); - memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr, - lease -> address.len); + lease->address.len = sizeof (packet->raw->yiaddr); + memcpy (lease->address.iabuf, &packet->raw->yiaddr, + lease->address.len); /* If the server name was filled out, copy it. */ - if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || - !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) && - packet -> raw -> sname [0]) { - /* Don't count on the NUL terminator. */ - lease->server_name = malloc(DHCP_SNAME_LEN + 1); - if (!lease -> server_name ) { - warn ("dhcpoffer: no memory for filename."); + if ((!packet->options [DHO_DHCP_OPTION_OVERLOAD].len || + !(packet->options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) && + packet->raw->sname [0]) { + lease->server_name = malloc (DHCP_SNAME_LEN + 1); + if (!lease->server_name) { + warn ("dhcpoffer: no memory for server name."); free_client_lease (lease); return (struct client_lease *)0; - } - memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); - lease->server_name[DHCP_SNAME_LEN]='\0'; + } + memcpy(lease->filename, packet->raw->sname, DHCP_SNAME_LEN); + lease->filename[DHCP_SNAME_LEN]='\0'; if (! res_hnok (lease->server_name) ) { warn ("Bogus server name %s", lease->server_name ); free_client_lease (lease); return (struct client_lease *)0; } + } /* Ditto for the filename. */ - if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || - !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) && - packet -> raw -> file [0]) { - /* Don't count on the NUL terminator. */ + if ((!packet->options [DHO_DHCP_OPTION_OVERLOAD].len || + !(packet->options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) && + packet->raw->file [0]) { + /* Don't count on the NUL terminator. */ lease->filename = malloc(DHCP_FILE_LEN + 1); - if (!lease -> filename) { + if (!lease->filename) { warn ("dhcpoffer: no memory for filename."); free_client_lease (lease); return (struct client_lease *)0; @@ -893,37 +973,45 @@ struct client_lease *packet_to_lease (packet) void dhcpnak (packet) struct packet *packet; { - struct interface_info *ip = packet -> interface; + struct interface_info *ip = packet->interface; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ - if (packet -> interface -> client -> xid != packet -> raw -> xid) { + if (packet->interface->client->xid != packet->raw->xid || + (packet->interface->hw_address.hlen != + packet->raw->hlen) || + (memcmp (packet->interface->hw_address.haddr, + packet->raw->chaddr, packet->raw->hlen))) { +#if defined (DEBUG) debug ("DHCPNAK in wrong transaction."); +#endif return; } - if (ip -> client -> state != S_REBOOTING && - ip -> client -> state != S_REQUESTING && - ip -> client -> state != S_RENEWING && - ip -> client -> state != S_REBINDING) { + if (ip->client->state != S_REBOOTING && + ip->client->state != S_REQUESTING && + ip->client->state != S_RENEWING && + ip->client->state != S_REBINDING) { +#if defined (DEBUG) debug ("DHCPNAK in wrong state."); +#endif return; } - note ("DHCPNAK from %s", piaddr (packet -> client_addr)); + note ("DHCPNAK from %s", piaddr (packet->client_addr)); - if (!ip -> client -> active) { + if (!ip->client->active) { note ("DHCPNAK with no active lease.\n"); return; } - free_client_lease (ip -> client -> active); - ip -> client -> active = (struct client_lease *)0; + free_client_lease (ip->client->active); + ip->client->active = (struct client_lease *)0; /* Stop sending DHCPREQUEST packets... */ cancel_timeout (send_request, ip); - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; state_init (ip); } @@ -941,11 +1029,11 @@ void send_discover (ipp) int increase = 1; /* Figure out how long it's been since we started transmitting. */ - interval = cur_time - ip -> client -> first_sending; + interval = cur_time - ip->client->first_sending; /* If we're past the panic timeout, call the script and tell it we haven't found anything for this interface yet. */ - if (interval > ip -> client -> config -> timeout) { + if (interval > ip->client->config->timeout) { state_panic (ip); return; } @@ -953,27 +1041,27 @@ void send_discover (ipp) /* If we're selecting media, try the whole list before doing the exponential backoff, but if we've already received an offer, stop looping, because we obviously have it right. */ - if (!ip -> client -> offered_leases && - ip -> client -> config -> media) { + if (!ip->client->offered_leases && + ip->client->config->media) { int fail = 0; again: - if (ip -> client -> medium) { - ip -> client -> medium = - ip -> client -> medium -> next; + if (ip->client->medium) { + ip->client->medium = + ip->client->medium->next; increase = 0; } - if (!ip -> client -> medium) { + if (!ip->client->medium) { if (fail) error ("No valid media types for %s!", - ip -> name); - ip -> client -> medium = - ip -> client -> config -> media; + ip->name); + ip->client->medium = + ip->client->config->media; increase = 1; } note ("Trying medium \"%s\" %d", - ip -> client -> medium -> string, increase); - script_init (ip, "MEDIUM", ip -> client -> medium); + ip->client->medium->string, increase); + script_init (ip, "MEDIUM", ip->client->medium); if (script_go (ip)) { goto again; } @@ -985,54 +1073,54 @@ void send_discover (ipp) zero and two times itself. On average, this means that it will double with every transmission. */ if (increase) { - if (!ip -> client -> interval) - ip -> client -> interval = - ip -> client -> config -> initial_interval; + if (!ip->client->interval) + ip->client->interval = + ip->client->config->initial_interval; else { - ip -> client -> interval += - ((arc4random () >> 2) % - (2 * ip -> client -> interval)); + ip->client->interval += + ((random () >> 2) % + (2 * ip->client->interval)); } /* Don't backoff past cutoff. */ - if (ip -> client -> interval > - ip -> client -> config -> backoff_cutoff) - ip -> client -> interval = - ((ip -> client -> config -> backoff_cutoff / 2) - + ((arc4random () >> 2) - % ip -> client -> interval)); - } else if (!ip -> client -> interval) - ip -> client -> interval = - ip -> client -> config -> initial_interval; + if (ip->client->interval > + ip->client->config->backoff_cutoff) + ip->client->interval = + ((ip->client->config->backoff_cutoff / 2) + + ((random () >> 2) % + ip->client->config->backoff_cutoff)); + } else if (!ip->client->interval) + ip->client->interval = + ip->client->config->initial_interval; /* If the backoff would take us to the panic timeout, just use that as the interval. */ - if (cur_time + ip -> client -> interval > - ip -> client -> first_sending + ip -> client -> config -> timeout) - ip -> client -> interval = - (ip -> client -> first_sending + - ip -> client -> config -> timeout) - cur_time + 1; + if (cur_time + ip->client->interval > + ip->client->first_sending + ip->client->config->timeout) + ip->client->interval = + (ip->client->first_sending + + ip->client->config->timeout) - cur_time + 1; /* Record the number of seconds since we started sending. */ - if (interval < 255) - ip -> client -> packet.secs = interval; + if (interval < 65536) + ip->client->packet.secs = htons (interval); else - ip -> client -> packet.secs = 255; + ip->client->packet.secs = htons (65535); + ip->client->secs = ip->client->packet.secs; note ("DHCPDISCOVER on %s to %s port %d interval %ld", - ip -> name, + ip->name, inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval); + ntohs (sockaddr_broadcast.sin_port), ip->client->interval); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); - if (result < 0) - warn ("send_discover/send_packet: %m"); - add_timeout (cur_time + ip -> client -> interval, send_discover, ip); + + add_timeout (cur_time + ip->client->interval, send_discover, ip); } /* state_panic gets called if we haven't received any offers in a preset @@ -1045,46 +1133,46 @@ void state_panic (ipp) { struct interface_info *ip = ipp; - struct client_lease *loop = ip -> client -> active; + struct client_lease *loop = ip->client->active; struct client_lease *lp; note ("No DHCPOFFERS received."); /* We may not have an active lease, but we may have some predefined leases that we can try. */ - if (!ip -> client -> active && ip -> client -> leases) + if (!ip->client->active && ip->client->leases) goto activate_next; /* Run through the list of leases and see if one can be used. */ - while (ip -> client -> active) { - if (ip -> client -> active -> expiry > cur_time) { + while (ip->client->active) { + if (ip->client->active->expiry > cur_time) { note ("Trying recorded lease %s", - piaddr (ip -> client -> active -> address)); + piaddr (ip->client->active->address)); /* Run the client script with the existing parameters. */ script_init (ip, "TIMEOUT", - ip -> client -> active -> medium); + ip->client->active->medium); script_write_params (ip, "new_", - ip -> client -> active); - if (ip -> client -> alias) + ip->client->active); + if (ip->client->alias) script_write_params (ip, "alias_", - ip -> client -> alias); + ip->client->alias); /* If the old lease is still good and doesn't yet need renewal, go into BOUND state and timeout at the renewal time. */ if (!script_go (ip)) { if (cur_time < - ip -> client -> active -> renewal) { - ip -> client -> state = S_BOUND; + ip->client->active->renewal) { + ip->client->state = S_BOUND; note ("bound: renewal in %d seconds.", - ip -> client -> active -> renewal + ip->client->active->renewal - cur_time); - add_timeout ((ip -> client -> - active -> renewal), + add_timeout ((ip->client -> + active->renewal), state_bound, ip); } else { - ip -> client -> state = S_BOUND; + ip->client->state = S_BOUND; note ("bound: immediate renewal."); state_bound (ip); } @@ -1095,31 +1183,31 @@ void state_panic (ipp) } /* If there are no other leases, give up. */ - if (!ip -> client -> leases) { - ip -> client -> leases = ip -> client -> active; - ip -> client -> active = (struct client_lease *)0; + if (!ip->client->leases) { + ip->client->leases = ip->client->active; + ip->client->active = (struct client_lease *)0; break; } activate_next: /* Otherwise, put the active lease at the end of the lease list, and try another lease.. */ - for (lp = ip -> client -> leases; lp -> next; lp = lp -> next) + for (lp = ip->client->leases; lp->next; lp = lp->next) ; - lp -> next = ip -> client -> active; - if (lp -> next) { - lp -> next -> next = (struct client_lease *)0; + lp->next = ip->client->active; + if (lp->next) { + lp->next->next = (struct client_lease *)0; } - ip -> client -> active = ip -> client -> leases; - ip -> client -> leases = ip -> client -> leases -> next; + ip->client->active = ip->client->leases; + ip->client->leases = ip->client->leases->next; /* If we already tried this lease, we've exhausted the set of leases, so we might as well give up for now. */ - if (ip -> client -> active == loop) + if (ip->client->active == loop) break; else if (!loop) - loop = ip -> client -> active; + loop = ip->client->active; } /* No leases were available, or what was available didn't work, so @@ -1129,11 +1217,11 @@ void state_panic (ipp) exit(1); note ("No working leases in persistent database - sleeping.\n"); script_init (ip, "FAIL", (struct string_list *)0); - if (ip -> client -> alias) - script_write_params (ip, "alias_", ip -> client -> alias); + if (ip->client->alias) + script_write_params (ip, "alias_", ip->client->alias); script_go (ip); - ip -> client -> state = S_INIT; - add_timeout (cur_time + ip -> client -> config -> retry_interval, + ip->client->state = S_INIT; + add_timeout (cur_time + ip->client->config->retry_interval, state_init, ip); go_daemon (); } @@ -1149,7 +1237,7 @@ void send_request (ipp) struct in_addr from; /* Figure out how long it's been since we started transmitting. */ - interval = cur_time - ip -> client -> first_sending; + interval = cur_time - ip->client->first_sending; /* If we're in the INIT-REBOOT or REQUESTING state and we're past the reboot timeout, go to INIT and see if we can @@ -1161,11 +1249,11 @@ void send_request (ipp) us a new address, but we could also have successfully reused our old address. In the former case, we're hosed anyway. This is not a win-prone situation. */ - if ((ip -> client -> state == S_REBOOTING || - ip -> client -> state == S_REQUESTING) && - interval > ip -> client -> config -> reboot_timeout) { + if ((ip->client->state == S_REBOOTING || + ip->client->state == S_REQUESTING) && + interval > ip->client->config->reboot_timeout) { cancel: - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; cancel_timeout (send_request, ip); state_init (ip); return; @@ -1173,114 +1261,121 @@ void send_request (ipp) /* If we're in the reboot state, make sure the media is set up correctly. */ - if (ip -> client -> state == S_REBOOTING && - !ip -> client -> medium && - ip -> client -> active -> medium ) { - script_init (ip, "MEDIUM", ip -> client -> active -> medium); + if (ip->client->state == S_REBOOTING && + !ip->client->medium && + ip->client->active->medium ) { + script_init (ip, "MEDIUM", ip->client->active->medium); /* If the medium we chose won't fly, go to INIT state. */ if (script_go (ip)) goto cancel; /* Record the medium. */ - ip -> client -> medium = ip -> client -> active -> medium; + ip->client->medium = ip->client->active->medium; } /* If the lease has expired, relinquish the address and go back to the INIT state. */ - if (ip -> client -> state != S_REQUESTING && - cur_time > ip -> client -> active -> expiry) { + if (ip->client->state != S_REQUESTING && + cur_time > ip->client->active->expiry) { /* Run the client script with the new parameters. */ script_init (ip, "EXPIRE", (struct string_list *)0); - script_write_params (ip, "old_", ip -> client -> active); - if (ip -> client -> alias) + script_write_params (ip, "old_", ip->client->active); + if (ip->client->alias) + script_write_params (ip, "alias_", + ip->client->alias); + script_go (ip); + + /* Now do a preinit on the interface so that we can + discover a new address. */ + script_init (ip, "PREINIT", (struct string_list *)0); + if (ip->client->alias) script_write_params (ip, "alias_", - ip -> client -> alias); + ip->client->alias); script_go (ip); - ip -> client -> state = S_INIT; + ip->client->state = S_INIT; state_init (ip); return; } /* Do the exponential backoff... */ - if (!ip -> client -> interval) - ip -> client -> interval = - ip -> client -> config -> initial_interval; + if (!ip->client->interval) + ip->client->interval = + ip->client->config->initial_interval; else { - ip -> client -> interval += - ((arc4random () >> 2) % - (2 * ip -> client -> interval)); + ip->client->interval += + ((random () >> 2) % + (2 * ip->client->interval)); } /* Don't backoff past cutoff. */ - if (ip -> client -> interval > - ip -> client -> config -> backoff_cutoff) - ip -> client -> interval = - ((ip -> client -> config -> backoff_cutoff / 2) - + ((arc4random () >> 2) - % ip -> client -> interval)); + if (ip->client->interval > + ip->client->config->backoff_cutoff) + ip->client->interval = + ((ip->client->config->backoff_cutoff / 2) + + ((random () >> 2) + % ip->client->interval)); /* If the backoff would take us to the expiry time, just set the timeout to the expiry time. */ - if (ip -> client -> state != S_REQUESTING && - cur_time + ip -> client -> interval > - ip -> client -> active -> expiry) - ip -> client -> interval = - ip -> client -> active -> expiry - cur_time + 1; + if (ip->client->state != S_REQUESTING && + cur_time + ip->client->interval > + ip->client->active->expiry) + ip->client->interval = + ip->client->active->expiry - cur_time + 1; /* If the lease T2 time has elapsed, or if we're not yet bound, broadcast the DHCPREQUEST rather than unicasting. */ - if (ip -> client -> state == S_REQUESTING || - cur_time > ip -> client -> active -> rebind) + if (ip->client->state == S_REQUESTING || + ip->client->state == S_REBOOTING || + cur_time > ip->client->active->rebind) destination.sin_addr.s_addr = INADDR_BROADCAST; else memcpy (&destination.sin_addr.s_addr, - ip -> client -> destination.iabuf, + ip->client->destination.iabuf, sizeof destination.sin_addr.s_addr); destination.sin_port = remote_port; destination.sin_family = AF_INET; -#ifdef HAVE_SA_LEN destination.sin_len = sizeof destination; -#endif - if (ip -> client -> state != S_REQUESTING) - memcpy (&from, ip -> client -> active -> address.iabuf, + if (ip->client->state != S_REQUESTING) + memcpy (&from, ip->client->active->address.iabuf, sizeof from); else from.s_addr = INADDR_ANY; /* Record the number of seconds since we started sending. */ - if (interval < 255) - ip -> client -> packet.secs = interval; - else - ip -> client -> packet.secs = 255; + if (ip->client->state == S_REQUESTING) + ip->client->packet.secs = ip->client->secs; + else { + if (interval < 65536) + ip->client->packet.secs = htons (interval); + else + ip->client->packet.secs = htons (65535); + } - note ("DHCPREQUEST on %s to %s port %d", ip -> name, + note ("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa (destination.sin_addr), ntohs (destination.sin_port)); -#ifdef USE_FALLBACK - if (destination.sin_addr.s_addr != INADDR_BROADCAST) - result = send_fallback (&fallback_interface, - (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - from, &destination, - (struct hardware *)0); + if (destination.sin_addr.s_addr != INADDR_BROADCAST && + fallback_interface) + result = send_packet (fallback_interface, + (struct packet *)0, + &ip->client->packet, + ip->client->packet_length, + from, &destination, + (struct hardware *)0); else -#endif /* USE_FALLBACK */ /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, from, &destination, (struct hardware *)0); - if (result < 0) - warn ("send_request/send_packet: %m"); - - add_timeout (cur_time + ip -> client -> interval, + add_timeout (cur_time + ip->client->interval, send_request, ip); } @@ -1291,18 +1386,16 @@ void send_decline (ipp) int result; - note ("DHCPDECLINE on %s to %s port %d", ip -> name, + note ("DHCPDECLINE on %s to %s port %d", ip->name, inet_ntoa (sockaddr_broadcast.sin_addr), ntohs (sockaddr_broadcast.sin_port)); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); - if (result < 0) - warn ("send_decline/send_packet: %m"); } void send_release (ipp) @@ -1312,25 +1405,22 @@ void send_release (ipp) int result; - note ("DHCPRELEASE on %s to %s port %d", ip -> name, + note ("DHCPRELEASE on %s to %s port %d", ip->name, inet_ntoa (sockaddr_broadcast.sin_addr), ntohs (sockaddr_broadcast.sin_port)); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, + &ip->client->packet, + ip->client->packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); - if (result < 0) - warn ("send_release/send_packet: %m"); } void make_discover (ip, lease) struct interface_info *ip; struct client_lease *lease; { - struct dhcp_packet *raw; unsigned char discover = DHCPDISCOVER; int i; @@ -1339,85 +1429,90 @@ void make_discover (ip, lease) memset (option_elements, 0, sizeof option_elements); memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &option_elements [i]; - options [i] -> value = &discover; - options [i] -> len = sizeof discover; - options [i] -> buf_size = sizeof discover; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &discover; + options [i]->len = sizeof discover; + options [i]->buf_size = sizeof discover; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Request the options we want */ i = DHO_DHCP_PARAMETER_REQUEST_LIST; options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> requested_options; - options [i] -> len = ip -> client -> config -> requested_option_count; - options [i] -> buf_size = - ip -> client -> config -> requested_option_count; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = ip->client->config->requested_options; + options [i]->len = ip->client->config->requested_option_count; + options [i]->buf_size = + ip->client->config->requested_option_count; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* If we had an address, try to get it again. */ if (lease) { - ip -> client -> requested_address = lease -> address; + ip->client->requested_address = lease->address; i = DHO_DHCP_REQUESTED_ADDRESS; options [i] = &option_elements [i]; - options [i] -> value = lease -> address.iabuf; - options [i] -> len = lease -> address.len; - options [i] -> buf_size = lease -> address.len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->address.iabuf; + options [i]->len = lease->address.len; + options [i]->buf_size = lease->address.len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } else { - ip -> client -> requested_address.len = 0; + ip->client->requested_address.len = 0; } /* Send any options requested in the config file. */ for (i = 0; i < 256; i++) { if (!options [i] && - ip -> client -> config -> send_options [i].data) { + ip->client->config->send_options [i].data) { options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> + options [i]->value = ip->client->config -> send_options [i].data; - options [i] -> len = ip -> client -> config -> + options [i]->len = ip->client->config -> send_options [i].len; - options [i] -> buf_size = ip -> client -> config -> + options [i]->buf_size = ip->client->config -> send_options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } } /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = arc4random (); - ip -> client -> packet.secs = 0; /* filled in by send_discover. */ - ip -> client -> packet.flags = 0; - memset (&(ip -> client -> packet.ciaddr), - 0, sizeof ip -> client -> packet.ciaddr); - memset (&(ip -> client -> packet.yiaddr), - 0, sizeof ip -> client -> packet.yiaddr); - memset (&(ip -> client -> packet.siaddr), - 0, sizeof ip -> client -> packet.siaddr); - memset (&(ip -> client -> packet.giaddr), - 0, sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = arc4random (); + ip->client->packet.secs = 0; /* filled in by send_discover. */ + + if (can_receive_unicast_unconfigured (ip)) + ip->client->packet.flags = 0; + else + ip->client->packet.flags = htons (BOOTP_BROADCAST); + + memset (&(ip->client->packet.ciaddr), + 0, sizeof ip->client->packet.ciaddr); + memset (&(ip->client->packet.yiaddr), + 0, sizeof ip->client->packet.yiaddr); + memset (&(ip->client->packet.siaddr), + 0, sizeof ip->client->packet.siaddr); + memset (&(ip->client->packet.giaddr), + 0, sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, + dump_raw ((unsigned char *)ip->client->packet, sendpkt->packet_length); #endif } @@ -1434,107 +1529,112 @@ void make_request (ip, lease) struct tree_cache option_elements [256]; memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &option_elements [i]; - options [i] -> value = &request; - options [i] -> len = sizeof request; - options [i] -> buf_size = sizeof request; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &request; + options [i]->len = sizeof request; + options [i]->buf_size = sizeof request; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Request the options we want */ i = DHO_DHCP_PARAMETER_REQUEST_LIST; options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> requested_options; - options [i] -> len = ip -> client -> config -> requested_option_count; - options [i] -> buf_size = - ip -> client -> config -> requested_option_count; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = ip->client->config->requested_options; + options [i]->len = ip->client->config->requested_option_count; + options [i]->buf_size = + ip->client->config->requested_option_count; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* If we are requesting an address that hasn't yet been assigned to us, use the DHCP Requested Address option. */ - if (ip -> client -> state == S_REQUESTING) { + if (ip->client->state == S_REQUESTING) { /* Send back the server identifier... */ i = DHO_DHCP_SERVER_IDENTIFIER; options [i] = &option_elements [i]; - options [i] -> value = lease -> options [i].data; - options [i] -> len = lease -> options [i].len; - options [i] -> buf_size = lease -> options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; - } - if (ip -> client -> state == S_REQUESTING || - ip -> client -> state == S_REBOOTING) { - ip -> client -> requested_address = lease -> address; + options [i]->value = lease->options [i].data; + options [i]->len = lease->options [i].len; + options [i]->buf_size = lease->options [i].len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; + } + if (ip->client->state == S_REQUESTING || + ip->client->state == S_REBOOTING) { + ip->client->requested_address = lease->address; i = DHO_DHCP_REQUESTED_ADDRESS; options [i] = &option_elements [i]; - options [i] -> value = lease -> address.iabuf; - options [i] -> len = lease -> address.len; - options [i] -> buf_size = lease -> address.len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->address.iabuf; + options [i]->len = lease->address.len; + options [i]->buf_size = lease->address.len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } else { - ip -> client -> requested_address.len = 0; + ip->client->requested_address.len = 0; } /* Send any options requested in the config file. */ for (i = 0; i < 256; i++) { if (!options [i] && - ip -> client -> config -> send_options [i].data) { + ip->client->config->send_options [i].data) { options [i] = &option_elements [i]; - options [i] -> value = ip -> client -> config -> + options [i]->value = ip->client->config -> send_options [i].data; - options [i] -> len = ip -> client -> config -> + options [i]->len = ip->client->config -> send_options [i].len; - options [i] -> buf_size = ip -> client -> config -> + options [i]->buf_size = ip->client->config -> send_options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } } /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> xid; - ip -> client -> packet.secs = 0; /* Filled in by send_request. */ - ip -> client -> packet.flags = 0; + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = ip->client->xid; + ip->client->packet.secs = 0; /* Filled in by send_request. */ /* If we own the address we're requesting, put it in ciaddr; otherwise set ciaddr to zero. */ - if (ip -> client -> state == S_BOUND || - ip -> client -> state == S_RENEWING || - ip -> client -> state == S_REBINDING) - memcpy (&ip -> client -> packet.ciaddr, - lease -> address.iabuf, lease -> address.len); - else - memset (&ip -> client -> packet.ciaddr, 0, - sizeof ip -> client -> packet.ciaddr); - - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + if (ip->client->state == S_BOUND || + ip->client->state == S_RENEWING || + ip->client->state == S_REBINDING) { + memcpy (&ip->client->packet.ciaddr, + lease->address.iabuf, lease->address.len); + ip->client->packet.flags = 0; + } else { + memset (&ip->client->packet.ciaddr, 0, + sizeof ip->client->packet.ciaddr); + if (can_receive_unicast_unconfigured (ip)) + ip->client->packet.flags = 0; + else + ip->client->packet.flags = htons (BOOTP_BROADCAST); + } + + memset (&ip->client->packet.yiaddr, 0, + sizeof ip->client->packet.yiaddr); + memset (&ip->client->packet.siaddr, 0, + sizeof ip->client->packet.siaddr); + memset (&ip->client->packet.giaddr, 0, + sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); + dump_raw ((unsigned char *)ip->client->packet, sendpkt->packet_length); #endif } @@ -1552,80 +1652,80 @@ void make_decline (ip, lease) struct tree_cache client_id_tree; memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &message_type_tree; - options [i] -> value = &decline; - options [i] -> len = sizeof decline; - options [i] -> buf_size = sizeof decline; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &decline; + options [i]->len = sizeof decline; + options [i]->buf_size = sizeof decline; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send back the server identifier... */ i = DHO_DHCP_SERVER_IDENTIFIER; options [i] = &server_id_tree; - options [i] -> value = lease -> options [i].data; - options [i] -> len = lease -> options [i].len; - options [i] -> buf_size = lease -> options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->options [i].data; + options [i]->len = lease->options [i].len; + options [i]->buf_size = lease->options [i].len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send back the address we're declining. */ i = DHO_DHCP_REQUESTED_ADDRESS; options [i] = &requested_address_tree; - options [i] -> value = lease -> address.iabuf; - options [i] -> len = lease -> address.len; - options [i] -> buf_size = lease -> address.len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->address.iabuf; + options [i]->len = lease->address.len; + options [i]->buf_size = lease->address.len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send the uid if the user supplied one. */ i = DHO_DHCP_CLIENT_IDENTIFIER; - if (ip -> client -> config -> send_options [i].len) { + if (ip->client->config->send_options [i].len) { options [i] = &client_id_tree; - options [i] -> value = ip -> client -> config -> + options [i]->value = ip->client->config -> send_options [i].data; - options [i] -> len = ip -> client -> config -> + options [i]->len = ip->client->config -> send_options [i].len; - options [i] -> buf_size = ip -> client -> config -> + options [i]->buf_size = ip->client->config -> send_options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; } /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> xid; - ip -> client -> packet.secs = 0; /* Filled in by send_request. */ - ip -> client -> packet.flags = 0; + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = ip->client->xid; + ip->client->packet.secs = 0; /* Filled in by send_request. */ + ip->client->packet.flags = 0; /* ciaddr must always be zero. */ - memset (&ip -> client -> packet.ciaddr, 0, - sizeof ip -> client -> packet.ciaddr); - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + memset (&ip->client->packet.ciaddr, 0, + sizeof ip->client->packet.ciaddr); + memset (&ip->client->packet.yiaddr, 0, + sizeof ip->client->packet.yiaddr); + memset (&ip->client->packet.siaddr, 0, + sizeof ip->client->packet.siaddr); + memset (&ip->client->packet.giaddr, 0, + sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); + dump_raw ((unsigned char *)ip->client->packet, sendpkt->packet_length); #endif } @@ -1638,59 +1738,59 @@ void make_release (ip, lease) struct tree_cache *options [256]; struct tree_cache message_type_tree; - struct tree_cache requested_address_tree; struct tree_cache server_id_tree; memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); + memset (&ip->client->packet, 0, sizeof (ip->client->packet)); /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */ i = DHO_DHCP_MESSAGE_TYPE; options [i] = &message_type_tree; - options [i] -> value = &request; - options [i] -> len = sizeof request; - options [i] -> buf_size = sizeof request; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = &request; + options [i]->len = sizeof request; + options [i]->buf_size = sizeof request; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Send back the server identifier... */ i = DHO_DHCP_SERVER_IDENTIFIER; options [i] = &server_id_tree; - options [i] -> value = lease -> options [i].data; - options [i] -> len = lease -> options [i].len; - options [i] -> buf_size = lease -> options [i].len; - options [i] -> timeout = 0xFFFFFFFF; - options [i] -> tree = (struct tree *)0; + options [i]->value = lease->options [i].data; + options [i]->len = lease->options [i].len; + options [i]->buf_size = lease->options [i].len; + options [i]->timeout = 0xFFFFFFFF; + options [i]->tree = (struct tree *)0; /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0, 0); - if (ip -> client -> packet_length < BOOTP_MIN_LEN) - ip -> client -> packet_length = BOOTP_MIN_LEN; - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = arc4random(); - ip -> client -> packet.secs = 0; - ip -> client -> packet.flags = 0; - memcpy (&ip -> client -> packet.ciaddr, - lease -> address.iabuf, lease -> address.len); - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); + ip->client->packet_length = + cons_options ((struct packet *)0, &ip->client->packet, 0, + options, 0, 0, 0, (u_int8_t *)0, 0); + if (ip->client->packet_length < BOOTP_MIN_LEN) + ip->client->packet_length = BOOTP_MIN_LEN; + + ip->client->packet.op = BOOTREQUEST; + ip->client->packet.htype = ip->hw_address.htype; + ip->client->packet.hlen = ip->hw_address.hlen; + ip->client->packet.hops = 0; + ip->client->packet.xid = random (); + ip->client->packet.secs = 0; + ip->client->packet.flags = 0; + + memset (&ip->client->packet.ciaddr, 0, + sizeof ip->client->packet.ciaddr); + memset (&ip->client->packet.yiaddr, 0, + sizeof ip->client->packet.yiaddr); + memset (&ip->client->packet.siaddr, 0, + sizeof ip->client->packet.siaddr); + memset (&ip->client->packet.giaddr, 0, + sizeof ip->client->packet.giaddr); + memcpy (ip->client->packet.chaddr, + ip->hw_address.haddr, ip->hw_address.hlen); #ifdef DEBUG_PACKET dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, - ip -> client -> packet_length); + dump_raw ((unsigned char *)ip->client->packet, + ip->client->packet_length); #endif } @@ -1699,13 +1799,13 @@ void free_client_lease (lease) { int i; - if (lease -> server_name) - free (lease -> server_name); - if (lease -> filename) - free (lease -> filename); + if (lease->server_name) + free (lease->server_name); + if (lease->filename) + free (lease->filename); for (i = 0; i < 256; i++) { - if (lease -> options [i].len) - free (lease -> options [i].data); + if (lease->options [i].len) + free (lease->options [i].data); } free (lease); } @@ -1725,36 +1825,45 @@ void rewrite_client_leases () /* Write out all the leases attached to configured interfaces that we know about. */ - for (ip = interfaces; ip; ip = ip -> next) { - for (lp = ip -> client -> leases; lp; lp = lp -> next) { - write_client_lease (ip, lp); + for (ip = interfaces; ip; ip = ip->next) { + for (lp = ip->client->leases; lp; lp = lp->next) { + write_client_lease (ip, lp, 1); } - if (ip -> client -> active) - write_client_lease (ip, ip -> client -> active); + if (ip->client->active) + write_client_lease (ip, ip->client->active, 1); } /* Write out any leases that are attached to interfaces that aren't currently configured. */ - for (ip = dummy_interfaces; ip; ip = ip -> next) { - for (lp = ip -> client -> leases; lp; lp = lp -> next) { - write_client_lease (ip, lp); + for (ip = dummy_interfaces; ip; ip = ip->next) { + for (lp = ip->client->leases; lp; lp = lp->next) { + write_client_lease (ip, lp, 1); } - if (ip -> client -> active) - write_client_lease (ip, ip -> client -> active); + if (ip->client->active) + write_client_lease (ip, ip->client->active, 1); } fflush (leaseFile); } -void write_client_lease (ip, lease) +void write_client_lease (ip, lease, rewrite) struct interface_info *ip; struct client_lease *lease; + int rewrite; { int i; struct tm *t; + static int leases_written; + + if (!rewrite) { + if (leases_written++ > 20) { + rewrite_client_leases (); + leases_written = 0; + } + } /* If the lease came from the config file, we don't need to stash a copy in the lease database. */ - if (lease -> is_static) + if (lease->is_static) return; if (!leaseFile) { /* XXX */ @@ -1764,48 +1873,52 @@ void write_client_lease (ip, lease) } fprintf (leaseFile, "lease {\n"); - if (lease -> is_bootp) + if (lease->is_bootp) fprintf (leaseFile, " bootp;\n"); - fprintf (leaseFile, " interface \"%s\";\n", ip -> name); + fprintf (leaseFile, " interface \"%s\";\n", ip->name); fprintf (leaseFile, " fixed-address %s;\n", - piaddr (lease -> address)); - if (lease -> filename) + piaddr (lease->address)); + if (lease->filename) fprintf (leaseFile, " filename \"%s\";\n", - lease -> filename); - if (lease -> server_name) + lease->filename); + if (lease->server_name) fprintf (leaseFile, " server-name \"%s\";\n", - lease -> filename); - if (lease -> medium) + lease->server_name); + if (lease->medium) fprintf (leaseFile, " medium \"%s\";\n", - lease -> medium -> string); + lease->medium->string); for (i = 0; i < 256; i++) { - if (lease -> options [i].len) { + if (lease->options [i].len) { fprintf (leaseFile, " option %s %s;\n", dhcp_options [i].name, pretty_print_option - (i, lease -> options [i].data, - lease -> options [i].len, 1, 1)); + (i, lease->options [i].data, + lease->options [i].len, 1, 1)); } } - t = gmtime (&lease -> renewal); + + /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until + somebody invents a time machine, I think we can safely disregard + it. */ + t = gmtime (&lease->renewal); fprintf (leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - t = gmtime (&lease -> rebind); + t->tm_wday, t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + t = gmtime (&lease->rebind); fprintf (leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - t = gmtime (&lease -> expiry); + t->tm_wday, t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + t = gmtime (&lease->expiry); fprintf (leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); + t->tm_wday, t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); fprintf (leaseFile, "}\n"); fflush (leaseFile); } @@ -1813,76 +1926,35 @@ void write_client_lease (ip, lease) /* Variables holding name of script and file pointer for writing to script. Needless to say, this is not reentrant - only one script can be invoked at a time. */ -char **scriptEnv = NULL; -int scriptEnvsize = 0; - -void script_set_env (name, value) - char *name; - char *value; -{ - int i, namelen; - - namelen = strlen(name); - - for (i = 0; scriptEnv[i]; i++) { - if (strncmp(scriptEnv[i], name, namelen) == 0 && - scriptEnv[i][namelen] == '=') - break; - } - if (scriptEnv[i]) { - /* Reuse the slot. */ - free(scriptEnv[i]); - } else { - /* New variable. Expand if necessary. */ - if (i >= scriptEnvsize - 1) { - scriptEnvsize += 50; - scriptEnv = realloc(scriptEnv, scriptEnvsize); - if (scriptEnv == NULL) - error("script_set_env: no memory for variable"); - } - /* Need to set the NULL pointer at end of array beyond - the new slot. */ - scriptEnv[i + 1] = NULL; - } - /* Allocate space and format the variable in the appropriate slot. */ - scriptEnv[i] = malloc(strlen(name) + 1 + strlen(value) + 1); - if (scriptEnv[i] == NULL) - error("script_set_env: no memory for variable assignment"); - - snprintf(scriptEnv[i], strlen(name) + 1 + strlen(value) + 1, - "%s=%s", name, value); -} - -void script_flush_env() -{ - int i; - - for (i = 0; scriptEnv[i]; i++) { - free(scriptEnv[i]); - scriptEnv[i] = NULL; - } -} +char scriptName [256]; +FILE *scriptFile; void script_init (ip, reason, medium) struct interface_info *ip; char *reason; struct string_list *medium; { - scriptEnvsize = 100; - scriptEnv = malloc(scriptEnvsize * sizeof(char *)); + if (ip) { + ip->client->scriptEnvsize = 100; + ip->client->scriptEnv = malloc(ip->client->scriptEnvsize + * sizeof(char *)); + if (ip->client->scriptEnv == NULL) + error ("script_init: no memory for environment initialization"); + + ip->client->scriptEnv[0]=strdup(CLIENT_PATH); + if (ip->client->scriptEnv[0] == NULL) + error ("script_init:n no memory for environment initialization"); - if (scriptEnv == NULL) - error ("script_init: no memory for environment initialization"); + ip->client->scriptEnv[1]=NULL; - scriptEnv[0] = NULL; + script_set_env(ip->client, "", "interface", ip->name); - if (ip) { - script_set_env ("interface", ip -> name); - } - if (medium) { - script_set_env ("medium", medium -> string); + if (medium) + script_set_env(ip->client, "", "medium", + medium->string); + + script_set_env(ip->client, "", "reason", reason); } - script_set_env ("reason", reason); } void script_write_params (ip, prefix, lease) @@ -1892,11 +1964,11 @@ void script_write_params (ip, prefix, lease) { int i; u_int8_t dbuf [1500]; - char name[1024], value[1024]; - int len; + int len = 0; + char tbuf[128]; - snprintf (name, sizeof(name), "%sip_address", prefix); - script_set_env (name, piaddr (lease -> address)); + script_set_env(ip->client, prefix, "ip_address", + piaddr(lease->address)); /* For the benefit of Linux (and operating systems which may have similar needs), compute the network address based on @@ -1905,65 +1977,58 @@ void script_write_params (ip, prefix, lease) broadcast address, not the host address all zeroes broadcast address). */ - if (lease -> options [DHO_SUBNET_MASK].len && - (lease -> options [DHO_SUBNET_MASK].len < - sizeof lease -> address.iabuf)) { + if (lease->options [DHO_SUBNET_MASK].len && + (lease->options [DHO_SUBNET_MASK].len < + sizeof lease->address.iabuf)) { struct iaddr netmask, subnet, broadcast; memcpy (netmask.iabuf, - lease -> options [DHO_SUBNET_MASK].data, - lease -> options [DHO_SUBNET_MASK].len); - netmask.len = lease -> options [DHO_SUBNET_MASK].len; - - subnet = subnet_number (lease -> address, netmask); + lease->options [DHO_SUBNET_MASK].data, + lease->options [DHO_SUBNET_MASK].len); + netmask.len = lease->options [DHO_SUBNET_MASK].len; + + subnet = subnet_number (lease->address, netmask); if (subnet.len) { - snprintf (name, sizeof(name), "%snetwork_number", - prefix); - script_set_env (name, piaddr (subnet)); - - if (!lease -> options [DHO_BROADCAST_ADDRESS].len) { + script_set_env(ip->client, prefix, "network_number", + piaddr(subnet)); + if (!lease->options [DHO_BROADCAST_ADDRESS].len) { broadcast = broadcast_addr (subnet, netmask); - if (broadcast.len) { - snprintf (name, sizeof(name), - "%sbroadcast_address", - prefix); - script_set_env (name, - piaddr (broadcast)); - } + if (broadcast.len) + script_set_env(ip->client, prefix, + "broadcast_address", + piaddr(broadcast)); } } } - - if (lease -> filename) { - snprintf (name, sizeof(name), "%sfilename", prefix); - script_set_env (name, lease -> filename); - } - if (lease -> server_name) { - snprintf (name, sizeof(name), "%sserver_name", prefix); - script_set_env (name, lease -> server_name); - } + + if (lease->filename) + script_set_env(ip->client, prefix, "filename", + lease->filename); + if (lease->server_name) + script_set_env(ip->client, prefix, "server_name", + lease->server_name); for (i = 0; i < 256; i++) { - u_int8_t *dp; - - if (ip -> client -> config -> defaults [i].len) { - if (lease -> options [i].len) { - switch (ip -> client -> - config -> default_actions [i]) { + u_int8_t *dp = NULL; + + if (ip->client->config->defaults [i].len) { + if (lease->options [i].len) { + switch (ip->client -> + config->default_actions [i]) { case ACTION_DEFAULT: - dp = lease -> options [i].data; - len = lease -> options [i].len; + dp = lease->options [i].data; + len = lease->options [i].len; break; case ACTION_SUPERSEDE: supersede: - dp = ip -> client -> - config -> defaults [i].data; - len = ip -> client -> - config -> defaults [i].len; + dp = ip->client -> + config->defaults [i].data; + len = ip->client -> + config->defaults [i].len; break; case ACTION_PREPEND: - len = (ip -> client -> - config -> defaults [i].len + - lease -> options [i].len); + len = (ip->client -> + config->defaults [i].len + + lease->options [i].len); if (len > sizeof dbuf) { warn ("no space to %s %s", "prepend option", @@ -1972,20 +2037,20 @@ void script_write_params (ip, prefix, lease) } dp = dbuf; memcpy (dp, - ip -> client -> - config -> defaults [i].data, - ip -> client -> - config -> defaults [i].len); - memcpy (dp + ip -> client -> - config -> defaults [i].len, - lease -> options [i].data, - lease -> options [i].len); - dp [len] = '\0'; + ip->client-> + config->defaults [i].data, + ip->client-> + config->defaults [i].len); + memcpy (dp + ip->client-> + config->defaults [i].len, + lease->options [i].data, + lease->options [i].len); + dp [len] = '\0'; break; case ACTION_APPEND: - len = (ip -> client -> - config -> defaults [i].len + - lease -> options [i].len); + len = (ip->client -> + config->defaults [i].len + + lease->options [i].len); if (len > sizeof dbuf) { warn ("no space to %s %s", "append option", @@ -1993,98 +2058,161 @@ void script_write_params (ip, prefix, lease) goto supersede; } dp = dbuf; - memcpy (dp, lease -> options [i].data, - lease -> options [i].len); - memcpy (dp + lease -> options [i].len, - ip -> client -> - config -> defaults [i].data, - ip -> client -> - config -> defaults [i].len); + memcpy (dp, + lease->options [i].data, + lease->options [i].len); + memcpy (dp + lease->options [i].len, + ip->client-> + config->defaults [i].data, + ip->client-> + config->defaults [i].len); dp [len] = '\0'; } } else { - dp = ip -> client -> - config -> defaults [i].data; - len = ip -> client -> - config -> defaults [i].len; + dp = ip->client -> + config->defaults [i].data; + len = ip->client -> + config->defaults [i].len; } - } else if (lease -> options [i].len) { - len = lease -> options [i].len; - dp = lease -> options [i].data; + } else if (lease->options [i].len) { + len = lease->options [i].len; + dp = lease->options [i].data; } else { len = 0; } if (len) { - char *s = dhcp_option_ev_name (&dhcp_options [i]); - - snprintf (name, sizeof(name), "%s%s", prefix, s); - script_set_env (name, pretty_print_option (i, dp, len, 0, 0)); + char name [256]; + if (dhcp_option_ev_name (name, sizeof name, + &dhcp_options [i])) + script_set_env(ip->client, prefix, name, + pretty_print_option (i, dp, len, 0, 0)); } } - snprintf (name, sizeof(name), "%sexpiry", prefix); - snprintf (value, sizeof(value), "%d", (int)lease -> expiry); /* XXX */ - script_set_env (name, value); + snprintf(tbuf, sizeof(tbuf), "%d", (int) lease->expiry); + script_set_env(ip->client, prefix, "expiry", tbuf); } int script_go (ip) struct interface_info *ip; { - char *p, *script_name, *script_argv[2]; - pid_t pid, wait_pid; - int status; - - if (ip) - script_name = ip -> client -> config -> script_name; - else - script_name = top_level_config.script_name; + char *scriptName; + char *argv [2]; + char **envp; + char *epp [3]; + char reason [] = "REASON=NBI"; + static char client_path [] = CLIENT_PATH; + int pid, wpid, wstatus; - if ((p = strrchr(script_name, '/')) != NULL) - p++; - else - p = script_name; - - script_argv[0] = p; - script_argv[1] = NULL; - - if ((pid = fork()) < 0) - error("Can't fork script: %m"); + if (ip) { + scriptName = ip->client->config->script_name; + envp = ip->client ->scriptEnv; + } else { + scriptName = top_level_config.script_name; + epp [0] = reason; + epp [1] = client_path; + epp [2] = (char *)0; + envp = epp; + } + + argv [0] = scriptName; + argv [1] = (char *)0; + + pid = fork (); + if (pid < 0) { + error ("fork: %m"); + wstatus = 0; + } else if (pid) { + do { + wpid = wait (&wstatus); + } while (wpid != pid && wpid > 0); + if (wpid < 0) { + error ("wait: %m"); + wstatus = 0; + } + } else { + execve (scriptName, argv, envp); + error ("execve (%s, ...): %m", scriptName); + exit (0); + } + + if (ip) { + script_flush_env(ip->client); + } + return wstatus & 0xff; +} + +void script_set_env (client, prefix, name, value) + struct client_state *client; + const char *prefix; + const char *name; + const char *value; +{ + int i, namelen; + + namelen = strlen(name); - if (pid == 0) { - execve(script_name, script_argv, scriptEnv); - error("script_go: exec: %m"); + for (i = 0; client->scriptEnv[i]; i++) { + if (strncmp(client->scriptEnv[i], name, namelen) == 0 && + client->scriptEnv[i][namelen] == '=') + break; + } + if (client->scriptEnv[i]) { + /* Reuse the slot. */ + free(client->scriptEnv[i]); + } else { + /* New variable. Expand if necessary. */ + if (i >= client->scriptEnvsize - 1) { + client->scriptEnvsize += 50; + client->scriptEnv = realloc(client->scriptEnv, + client->scriptEnvsize); + if (client->scriptEnv == NULL) + error("script_set_env: no memory for variable"); + } + /* need to set the NULL pointer at end of array beyond + the new slot. */ + client->scriptEnv[i + 1] = NULL; } - script_flush_env(); + /* Allocate space and format the variable in the appropriate slot. */ + client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 + + strlen(value) + 1); + if (client->scriptEnv[i] == NULL) + error("script_set_env: no memory for variable assignment"); - wait_pid = wait((int *) &status); + snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) + + 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value); +} + +void script_flush_env(struct client_state *client) +{ + int i; - if (wait_pid != -1) { - if (wait_pid != pid) - error ("got wrong pid"); - if (WIFEXITED(status) || WIFSIGNALED(status)) - return (WEXITSTATUS(status)); + for (i = 0; client->scriptEnv[i]; i++) { + free(client->scriptEnv[i]); + client->scriptEnv[i] = NULL; } - return (-1); + client->scriptEnvsize = 0; } -char *dhcp_option_ev_name (option) +int dhcp_option_ev_name (buf, buflen, option) + char *buf; + size_t buflen; struct option *option; { - static char evbuf [256]; int i; - if (strlen (option -> name) + 1 > sizeof evbuf) - error ("option %s name is larger than static buffer."); - for (i = 0; option -> name [i]; i++) { - if (option -> name [i] == '-') - evbuf [i] = '_'; + for (i = 0; option->name [i]; i++) { + if (i + 1 == buflen) + return 0; + if (option->name [i] == '-') + buf [i] = '_'; else - evbuf [i] = option -> name [i]; + buf [i] = option->name [i]; } - evbuf [i] = 0; - return evbuf; + buf [i] = 0; + return 1; } - + void go_daemon () { static int state = 0; @@ -2092,7 +2220,7 @@ void go_daemon () /* Don't become a daemon if the user requested otherwise. */ if (no_daemon) { - write_pidfile(_PATH_DHCLIENT_PID, getpid()); + write_client_pid_file (); return; } @@ -2112,101 +2240,127 @@ void go_daemon () /* Become session leader and get pid... */ pid = setsid (); - write_pidfile(_PATH_DHCLIENT_PID, getpid()); + /* Close standard I/O descriptors. */ + close(0); + close(1); + close(2); + + write_client_pid_file (); +} + +void write_client_pid_file () +{ + FILE *pf; + int pfdesc; + + pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644); + + if (pfdesc < 0) { + warn ("Can't create %s: %m", path_dhclient_pid); + return; + } + + pf = fdopen (pfdesc, "w"); + if (!pf) + warn ("Can't fdopen %s: %m", path_dhclient_pid); + else { + fprintf (pf, "%ld\n", (long)getpid ()); + fclose (pf); + } } int check_option (struct client_lease *l, int option) { - char *opbuf; - - /* we use this, since this is what gets passed to dhclient-script */ - - opbuf = pretty_print_option (option, l->options[option].data, - l->options[option].len, 0, 0); - switch(option) { - case DHO_SUBNET_MASK : - case DHO_TIME_SERVERS : - case DHO_NAME_SERVERS : - case DHO_ROUTERS : - case DHO_DOMAIN_NAME_SERVERS : - case DHO_LOG_SERVERS : - case DHO_COOKIE_SERVERS : - case DHO_LPR_SERVERS : - case DHO_IMPRESS_SERVERS : - case DHO_RESOURCE_LOCATION_SERVERS : - case DHO_SWAP_SERVER : - case DHO_BROADCAST_ADDRESS : - case DHO_NIS_SERVERS : - case DHO_NTP_SERVERS : - case DHO_NETBIOS_NAME_SERVERS : - case DHO_NETBIOS_DD_SERVER : - case DHO_FONT_SERVERS : - /* These should be a list of one or more IP addresses, separated - * by spaces. If they aren't, this lease is not valid. - */ - if (!ipv4addrs(opbuf)) { - warn("Invalid IP address in option: %s", opbuf); - return(0); - } - return(1) ; - case DHO_HOST_NAME : - case DHO_DOMAIN_NAME : - case DHO_NIS_DOMAIN : - case DHO_DHCP_SERVER_IDENTIFIER : - /* This has to be a valid internet domain name */ - if (!res_hnok(opbuf)) { - warn("Bogus name option: %s", opbuf); - return(0); - } - return(1); - case DHO_PAD : - case DHO_TIME_OFFSET : - case DHO_BOOT_SIZE : - case DHO_MERIT_DUMP : - case DHO_ROOT_PATH : - case DHO_EXTENSIONS_PATH : - case DHO_IP_FORWARDING : - case DHO_NON_LOCAL_SOURCE_ROUTING : - case DHO_POLICY_FILTER : - case DHO_MAX_DGRAM_REASSEMBLY : - case DHO_DEFAULT_IP_TTL : - case DHO_PATH_MTU_AGING_TIMEOUT : - case DHO_PATH_MTU_PLATEAU_TABLE : - case DHO_INTERFACE_MTU : - case DHO_ALL_SUBNETS_LOCAL : - case DHO_PERFORM_MASK_DISCOVERY : - case DHO_MASK_SUPPLIER : - case DHO_ROUTER_DISCOVERY : - case DHO_ROUTER_SOLICITATION_ADDRESS : - case DHO_STATIC_ROUTES : - case DHO_TRAILER_ENCAPSULATION : - case DHO_ARP_CACHE_TIMEOUT : - case DHO_IEEE802_3_ENCAPSULATION : - case DHO_DEFAULT_TCP_TTL : - case DHO_TCP_KEEPALIVE_INTERVAL : - case DHO_TCP_KEEPALIVE_GARBAGE : - case DHO_VENDOR_ENCAPSULATED_OPTIONS : - case DHO_NETBIOS_NODE_TYPE : - case DHO_NETBIOS_SCOPE : - case DHO_X_DISPLAY_MANAGER : - case DHO_DHCP_REQUESTED_ADDRESS : - case DHO_DHCP_LEASE_TIME : - case DHO_DHCP_OPTION_OVERLOAD : - case DHO_DHCP_MESSAGE_TYPE : - case DHO_DHCP_PARAMETER_REQUEST_LIST : - case DHO_DHCP_MESSAGE : - case DHO_DHCP_MAX_MESSAGE_SIZE : - case DHO_DHCP_RENEWAL_TIME : - case DHO_DHCP_REBINDING_TIME : - case DHO_DHCP_CLASS_IDENTIFIER : - case DHO_DHCP_CLIENT_IDENTIFIER : - case DHO_DHCP_USER_CLASS_ID : - case DHO_END : - /* do nothing */ - return(1); - default: - warn("unknown dhcp option value 0x%x", option); - return(unknown_ok); - } + char *opbuf; + + /* we use this, since this is what gets passed to dhclient-script */ + + opbuf = pretty_print_option (option, l->options[option].data, + l->options[option].len, 0, 0); + switch(option) { + case DHO_SUBNET_MASK : + case DHO_TIME_SERVERS : + case DHO_NAME_SERVERS : + case DHO_ROUTERS : + case DHO_DOMAIN_NAME_SERVERS : + case DHO_LOG_SERVERS : + case DHO_COOKIE_SERVERS : + case DHO_LPR_SERVERS : + case DHO_IMPRESS_SERVERS : + case DHO_RESOURCE_LOCATION_SERVERS : + case DHO_SWAP_SERVER : + case DHO_BROADCAST_ADDRESS : + case DHO_NIS_SERVERS : + case DHO_NTP_SERVERS : + case DHO_NETBIOS_NAME_SERVERS : + case DHO_NETBIOS_DD_SERVER : + case DHO_FONT_SERVERS : + /* These should be a list of one or more IP addresses, separated + * by spaces. If they aren't, this lease is not valid. + */ + if (!ipv4addrs(opbuf)) { + warn("Invalid IP address in option: %s", opbuf); + return(0); + } + return(1) ; + case DHO_HOST_NAME : + case DHO_DOMAIN_NAME : + case DHO_NIS_DOMAIN : + case DHO_DHCP_SERVER_IDENTIFIER : + /* This has to be a valid internet domain name */ + if (!res_hnok(opbuf)) { + warn("Bogus name option: %s", opbuf); + return(0); + } + return(1); + case DHO_PAD : + case DHO_TIME_OFFSET : + case DHO_BOOT_SIZE : + case DHO_MERIT_DUMP : + case DHO_ROOT_PATH : + case DHO_EXTENSIONS_PATH : + case DHO_IP_FORWARDING : + case DHO_NON_LOCAL_SOURCE_ROUTING : + case DHO_POLICY_FILTER : + case DHO_MAX_DGRAM_REASSEMBLY : + case DHO_DEFAULT_IP_TTL : + case DHO_PATH_MTU_AGING_TIMEOUT : + case DHO_PATH_MTU_PLATEAU_TABLE : + case DHO_INTERFACE_MTU : + case DHO_ALL_SUBNETS_LOCAL : + case DHO_PERFORM_MASK_DISCOVERY : + case DHO_MASK_SUPPLIER : + case DHO_ROUTER_DISCOVERY : + case DHO_ROUTER_SOLICITATION_ADDRESS : + case DHO_STATIC_ROUTES : + case DHO_TRAILER_ENCAPSULATION : + case DHO_ARP_CACHE_TIMEOUT : + case DHO_IEEE802_3_ENCAPSULATION : + case DHO_DEFAULT_TCP_TTL : + case DHO_TCP_KEEPALIVE_INTERVAL : + case DHO_TCP_KEEPALIVE_GARBAGE : + case DHO_VENDOR_ENCAPSULATED_OPTIONS : + case DHO_NETBIOS_NODE_TYPE : + case DHO_NETBIOS_SCOPE : + case DHO_X_DISPLAY_MANAGER : + case DHO_DHCP_REQUESTED_ADDRESS : + case DHO_DHCP_LEASE_TIME : + case DHO_DHCP_OPTION_OVERLOAD : + case DHO_DHCP_MESSAGE_TYPE : + case DHO_DHCP_PARAMETER_REQUEST_LIST : + case DHO_DHCP_MESSAGE : + case DHO_DHCP_MAX_MESSAGE_SIZE : + case DHO_DHCP_RENEWAL_TIME : + case DHO_DHCP_REBINDING_TIME : + case DHO_DHCP_CLASS_IDENTIFIER : + case DHO_DHCP_CLIENT_IDENTIFIER : + case DHO_DHCP_USER_CLASS_ID : + case DHO_END : + /* do nothing */ + return(1); + default: + warn("unknown dhcp option value 0x%x", option); + return(unknown_ok); + } } int @@ -2214,10 +2368,10 @@ res_hnok(dn) const char *dn; { int pch = PERIOD, ch = *dn++; - + while (ch != '\0') { int nch = *dn++; - + if (periodchar(ch)) { ; } else if (periodchar(pch)) { @@ -2240,17 +2394,17 @@ res_hnok(dn) * otherwise, return 0 */ int ipv4addrs(char * buf) { - struct in_addr jnk; - int count = 0; - - while (inet_aton(buf, &jnk) == 1){ - count++; - while (periodchar(*buf) || digitchar(*buf)) - buf++; - if (*buf == '\0') - return(count); - while (*buf == ' ') - buf++; - } - return(0); + struct in_addr jnk; + int count = 0; + + while (inet_aton(buf, &jnk) == 1){ + count++; + while (periodchar(*buf) || digitchar(*buf)) + buf++; + if (*buf == '\0') + return(count); + while (*buf == ' ') + buf++; + } + return(0); } diff --git a/usr.sbin/dhcp/dhclient/dhclient.conf b/usr.sbin/dhcp/dhclient/dhclient.conf index bb7b8f7f988..147e0045a5d 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.conf +++ b/usr.sbin/dhcp/dhclient/dhclient.conf @@ -11,7 +11,7 @@ retry 60; reboot 10; select-timeout 5; initial-interval 2; -script "/sbin/dhclient-script"; +script "/etc/dhclient-script"; media "-link0 -link1 -link2", "link0 link1"; reject 192.33.137.209; diff --git a/usr.sbin/dhcp/dhclient/dhclient.conf.5 b/usr.sbin/dhcp/dhclient/dhclient.conf.5 index 3386db8f354..691908193e0 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.conf.5 +++ b/usr.sbin/dhcp/dhclient/dhclient.conf.5 @@ -248,7 +248,7 @@ statement. .PP If for some set of options the client should always use its own value rather than any value supplied by the server, these values can be -defined in the +defined in the .B supersede statement. .PP @@ -259,14 +259,15 @@ statement. \fBprepend { [ \fIoption declaration\fR ] [\fB,\fI ... \fIoption declaration\fR ]\fB}\fR .PP -If for some set of options the client should first a value it -supplies, and then use the values supplied by +If for some set of options the client should use a value you +supply, and then use the values supplied by the server, if any, these values can be defined in the .B prepend statement. The .B prepend statement can only be used for options which -allow more than one value to be given. +allow more than one value to be given. This restriction is not +enforced - if violated, the results are unpredictable. .PP .I The .B append @@ -275,14 +276,15 @@ allow more than one value to be given. \fBappend { [ \fIoption declaration\fR ] [\fB,\fI ... \fIoption declaration\fR ]\fB}\fR .PP -If for some set of options the client should first a value it -supplies, and then use the values supplied by -the server, if any, these values can be defined in the +If for some set of options the client should first use the values +supplied by the server, if any, and then use values you supply, these +values can be defined in the .B append statement. The .B append statement can only be used for options which -allow more than one value to be given. +allow more than one value to be given. This restriction is not +enforced - if you ignore it, the behaviour will be unpredictable. .SH LEASE DECLARATIONS .PP .I The @@ -292,7 +294,7 @@ allow more than one value to be given. \fBlease {\fR \fIlease-declaration\fR [ ... \fIlease-declaration ] \fB}\fR .PP The DHCP client may decide after some period of time (see \fBPROTOCOL -TIMING\fR) that it is not going to succeed in contacting a +TIMING\fR) decide that it is not going to succeed in contacting a server. At that time, it consults its own database of old leases and tests each one that has not yet timed out by pinging the listed router for that lease to see if that lease could work. It is possible to @@ -378,7 +380,7 @@ interface's final configuration once a lease has been acquired. If no lease is acquired, the script is used to test predefined leases, if any, and also called once if no valid lease can be identified. For more information, see -.B dhclient-script(8). +.B dhclient-lease(8). .PP \fBmedium "\fImedia setup\fB";\fR .PP @@ -389,7 +391,7 @@ automatically determine the type of network to which they are connected. The media setup string is a system-dependent parameter which is passed to the dhcp client configuration script when initializing the interface. On Unix and Unix-like systems, the -argument is passed on the ifconfig command line when configuring the +argument is passed on the ifconfig command line when configuring te interface. .PP The dhcp client automatically declares this parameter if it used a @@ -430,8 +432,8 @@ specified as zero. The year is specified with the century, so it should generally be four digits except for really long leases. The month is specified as a number starting with 1 for January. The day of the month is likewise specified starting with 1. The hour is a -number between 0 and 23, the minute a number between 0 and 60, and the -second also a number between 0 and 60. +number between 0 and 23, the minute a number between 0 and 69, and the +second also a number between 0 and 69. .SH ALIAS DECLARATIONS \fBalias { \fI declarations ... \fB}\fR .PP @@ -518,7 +520,7 @@ interface "ep0" { request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, host-name; require subnet-mask, domain-name-servers; - script "/sbin/dhclient-script"; + script "/etc/dhclient-script"; media "media 10baseT/UTP", "media 10base2/BNC"; } diff --git a/usr.sbin/dhcp/dhclient/dhclient.leases.5 b/usr.sbin/dhcp/dhclient/dhclient.leases.5 index 1c61a60b1cc..e0da360524a 100644 --- a/usr.sbin/dhcp/dhclient/dhclient.leases.5 +++ b/usr.sbin/dhcp/dhclient/dhclient.leases.5 @@ -1,4 +1,3 @@ -.\" $OpenBSD: dhclient.leases.5,v 1.2 1999/05/30 02:42:22 pjanzen Exp $ .\" dhclient.conf.5 .\" .\" Copyright (c) 1997 The Internet Software Consortium. @@ -45,12 +44,12 @@ database of leases that it has acquired that are still valid. The database is a free-form ASCII file containing one valid declaration per lease. If more than one declaration appears for a given lease, the last one in the file is used. The file is written as a log, so -this is not an unusual occurrence. +this is not an unusual occurrance. .PP The format of the lease declarations is described in .B dhclient.conf(5). .SH FILES -.B /var/db/dhclient.leases +.B DBDIR/dhclient.leases .SH SEE ALSO dhclient(8), dhcp-options(5), dhclient.conf(5), dhcpd(8), dhcpd.conf(5), RFC2132, RFC2131. |