summaryrefslogtreecommitdiff
path: root/usr.sbin/dhcp/dhclient/dhclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/dhcp/dhclient/dhclient.c')
-rw-r--r--usr.sbin/dhcp/dhclient/dhclient.c2016
1 files changed, 1085 insertions, 931 deletions
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);
}