From 66f973e41ef6c68f2e11e5bf6c0e2eca8320eb31 Mon Sep 17 00:00:00 2001 From: Ted Lemon Date: Fri, 9 May 1997 07:54:14 +0000 Subject: [PATCH] Cygwin32 compatibility. Handle prepend, append and supersede option modifiers. Minimal BOOTP support. Handle seed generation differently. --- client/dhclient.c | 181 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 150 insertions(+), 31 deletions(-) diff --git a/client/dhclient.c b/client/dhclient.c index 5c3dbe73..eb9c3782 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -56,7 +56,7 @@ #ifndef lint static char copyright[] = -"$Id: dhclient.c,v 1.35 1997/03/29 01:24:30 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dhclient.c,v 1.36 1997/05/09 07:54:14 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -99,6 +99,7 @@ int main (argc, argv, envp) int i; struct servent *ent; struct interface_info *ip; + int seed; #ifdef SYSLOG_4_2 openlog ("dhclient", LOG_NDELAY); @@ -107,7 +108,7 @@ int main (argc, argv, envp) openlog ("dhclient", LOG_NDELAY, LOG_DAEMON); #endif -#if !(defined (DEBUG) || defined (SYSLOG_4_2)) +#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__)) setlogmask (LOG_UPTO (LOG_INFO)); #endif @@ -143,7 +144,9 @@ int main (argc, argv, envp) local_port = htons (68); else local_port = ent -> s_port; +#ifndef __CYGWIN32__ endservent (); +#endif } remote_port = htons (ntohs (local_port) - 1); /* XXX */ @@ -196,9 +199,23 @@ int main (argc, argv, envp) up the interfaces. */ discover_interfaces (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) { - srandom (cur_time + *(int *)(&ip -> hw_address.haddr [0])); ip -> client -> state = S_INIT; state_reboot (ip); } @@ -258,7 +275,8 @@ void state_reboot (ipp) /* If we don't remember an active lease, go straight to INIT. */ if (!ip -> client -> active || - ip -> client -> active -> rebind < cur_time) { + ip -> client -> active -> rebind < cur_time || + ip -> client -> active -> is_bootp) { state_init (ip); return; } @@ -359,6 +377,23 @@ void state_selecting (ipp) return; } + /* If it was a BOOTREPLY, we can just take the address right now. */ + if (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) { + ip -> client -> new = picked; + + /* Make up some lease expiry times + XXX these should be configurable. */ + ip -> client -> new -> expiry = cur_time + 12000; + ip -> client -> new -> renewal += cur_time + 8000; + ip -> client -> new -> rebind += cur_time + 10000; + + ip -> client -> state = S_REQUESTING; + + /* Bind to the address we received. */ + bind_lease (ip); + return; + } + /* Go to the REQUESTING state. */ ip -> client -> destination = iaddr_broadcast; ip -> client -> state = S_REQUESTING; @@ -447,6 +482,12 @@ void dhcpack (packet) ip -> client -> new -> renewal += cur_time; ip -> client -> new -> rebind += cur_time; + bind_lease (ip); +} + +void bind_lease (ip) + struct interface_info *ip; +{ /* Write out the new lease. */ write_client_lease (ip, ip -> client -> new); @@ -478,7 +519,8 @@ void dhcpack (packet) add_timeout (ip -> client -> active -> renewal, state_bound, ip); - note ("bound: renewal in %d seconds.", + note ("bound to %s -- renewal in %d seconds.", + piaddr (ip -> client -> active -> address), ip -> client -> active -> renewal - cur_time); ip -> client -> state = S_BOUND; reinitialize_interfaces (); @@ -536,10 +578,9 @@ void db_startup () void bootp (packet) struct packet *packet; { - note ("BOOTREPLY from %s", - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr)); + if (packet -> raw -> op == BOOTREPLY) + dhcpoffer (packet); + } void dhcp (packet) @@ -570,6 +611,8 @@ void dhcpoffer (packet) struct client_lease *lease, *lp; int i; int arp_timeout_needed, stop_selecting; + char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len + ? "DHCPOFFER" : "BOOTREPLY"); #ifdef DEBUG_PACKET dump_packet (packet); @@ -579,11 +622,11 @@ void dhcpoffer (packet) has an unrecognizable transaction id, then just drop it. */ if (ip -> client -> state != S_SELECTING || packet -> interface -> client -> xid != packet -> raw -> xid) { - debug ("DHCPOFFER in wrong transaction."); + debug ("%s in wrong transaction.", name); return; } - note ("DHCPOFFER from %s", + note ("%s from %s", name, print_hw_addr (packet -> raw -> htype, packet -> raw -> hlen, packet -> raw -> chaddr)); @@ -593,7 +636,7 @@ void dhcpoffer (packet) for (i = 0; ip -> client -> config -> required_options [i]; i++) { if (!packet -> options [ip -> client -> config -> required_options [i]].len) { - note ("DHCPOFFER isn't satisfactory."); + note ("%s isn't satisfactory.", name); return; } } @@ -604,7 +647,7 @@ void dhcpoffer (packet) if (lease -> address.len == sizeof packet -> raw -> yiaddr && !memcmp (lease -> address.iabuf, &packet -> raw -> yiaddr, lease -> address.len)) { - debug ("DHCPOFFER already seen."); + debug ("%s already seen.", name); return; } } @@ -615,6 +658,11 @@ void dhcpoffer (packet) return; } + /* If this lease was acquired through a BOOTREPLY, record that + fact. */ + if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len) + lease -> is_bootp = 1; + /* Record the medium under which this lease was offered. */ lease -> medium = ip -> client -> medium; @@ -806,10 +854,8 @@ void dhcpnak (packet) } /* Send out a DHCPDISCOVER packet, and set a timeout to send out another - one after the right interval has expired. If we are past the renewal - (T1) interval but not yet past the rebind (T2) interval, unicast - the message; otherwise broadcast it. If the lease expires, go back to - the INIT state. */ + one after the right interval has expired. If we don't get an offer by + the time we reach the panic interval, call the panic function. */ void send_discover (ipp) void *ipp; @@ -893,17 +939,17 @@ void send_discover (ipp) (ip -> client -> first_sending + ip -> client -> config -> timeout) - cur_time + 1; - note ("DHCPDISCOVER on %s to %s port %d interval %ld", - ip -> name, - inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval); - /* Record the number of seconds since we started sending. */ if (interval < 255) ip -> client -> packet.secs = interval; else ip -> client -> packet.secs = 255; + note ("DHCPDISCOVER on %s to %s port %d interval %ld", + ip -> name, + inet_ntoa (sockaddr_broadcast.sin_addr), + ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval); + /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, &ip -> client -> packet, @@ -933,10 +979,8 @@ void state_panic (ipp) /* 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) { - loop = 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) { @@ -1001,6 +1045,8 @@ void state_panic (ipp) now. */ if (ip -> client -> active == loop) break; + else if (!loop) + loop = ip -> client -> active; } /* No leases were available, or what was available didn't work, so @@ -1626,6 +1672,8 @@ void write_client_lease (ip, lease) } fprintf (leaseFile, "lease {\n"); + if (lease -> is_bootp) + fprintf (leaseFile, " bootp;\n"); fprintf (leaseFile, " interface \"%s\";\n", ip -> name); fprintf (leaseFile, " fixed-address %s;\n", piaddr (lease -> address)); @@ -1706,6 +1754,8 @@ void script_write_params (ip, prefix, lease) struct client_lease *lease; { int i; + u_int8_t dbuf [1500]; + int len; fprintf (scriptFile, "%sip_address=\"%s\"\n", prefix, piaddr (lease -> address)); @@ -1721,13 +1771,82 @@ void script_write_params (ip, prefix, lease) fprintf (scriptFile, "export %sserver_name\n", prefix); } for (i = 0; i < 256; i++) { - if (lease -> options [i].len) { + u_int8_t *dp; + + if (ip -> client -> config -> defaults [i].len) { + if (lease -> options [i].len) { + switch (ip -> client -> + config -> default_actions [i]) { + case ACTION_DEFAULT: + dp = lease -> options [i].data; + len = lease -> options [i].len; + break; + case ACTION_SUPERSEDE: + supersede: + dp = ip -> client -> + config -> defaults [i].data; + len = ip -> client -> + config -> defaults [i].len; + break; + case ACTION_PREPEND: + len = (ip -> client -> + config -> defaults [i].len + + lease -> options [i].len); + if (len > sizeof dbuf) { + warn ("no space to %s %s", + "prepend option", + dhcp_options [i].name); + goto supersede; + } + dp = dbuf; + memcpy (dp, + ip -> client -> + config -> defaults [i].data, + ip -> client -> + config -> defaults [i].len); + memcpy (dp + ip -> client -> + config -> defaults [i].len, + lease -> options [i].data, + lease -> options [i].len); + break; + case ACTION_APPEND: + len = (ip -> client -> + config -> defaults [i].len + + lease -> options [i].len); + if (len > sizeof dbuf) { + warn ("no space to %s %s", + "prepend option", + dhcp_options [i].name); + goto supersede; + } + dp = dbuf; + memcpy (dp, + ip -> client -> + config -> defaults [i].data, + ip -> client -> + config -> defaults [i].len); + memcpy (dp + ip -> client -> + config -> defaults [i].len, + lease -> options [i].data, + lease -> options [i].len); + } + } else { + dp = ip -> client -> + config -> defaults [i].data; + len = ip -> client -> + config -> defaults [i].len; + } + } else if (lease -> options [i].len) { + len = lease -> options [i].len; + dp = lease -> options [i].data; + } else { + len = 0; + } + if (len) { char *s = dhcp_option_ev_name (&dhcp_options [i]); - fprintf (scriptFile, - "%s%s=\"%s\"\n", prefix, s, - pretty_print_option - (i, lease -> options [i].data, - lease -> options [i].len, 0)); + + fprintf (scriptFile, "%s%s=\"%s\"\n", prefix, s, + pretty_print_option (i, dp, len, 0)); fprintf (scriptFile, "export %s%s\n", prefix, s); } }