diff options
author | Ted Lemon <source@isc.org> | 1997-02-22 08:44:15 +0000 |
---|---|---|
committer | Ted Lemon <source@isc.org> | 1997-02-22 08:44:15 +0000 |
commit | 9bdb9271f2d33dc7887cf183327fe4f2a3cbeeea (patch) | |
tree | cebe6affbfb530580375807343bef0c4bc442b9c /client/dhclient.c | |
parent | 99fd97cc5506395f3f08df5cb137755bc7925ad0 (diff) | |
download | isc-dhcp-9bdb9271f2d33dc7887cf183327fe4f2a3cbeeea.tar.gz |
Add media selection for interface cards that support more than one kind of network media; fix exponential backoff code; add parameter to control the use of commas in pretty printing - no commas in shell script arrays; add dummy relay() function
Diffstat (limited to 'client/dhclient.c')
-rw-r--r-- | client/dhclient.c | 150 |
1 files changed, 114 insertions, 36 deletions
diff --git a/client/dhclient.c b/client/dhclient.c index 8466ad27..922c4c24 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -1,6 +1,6 @@ /* dhclient.c - DHCP Client (less lame DHCP client). */ + DHCP Client. */ /* * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. @@ -56,7 +56,7 @@ #ifndef lint static char copyright[] = -"$Id: dhclient.c,v 1.24 1997/02/19 10:57:24 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dhclient.c,v 1.25 1997/02/22 08:44:15 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -175,7 +175,8 @@ int main (argc, argv, envp) /* 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); /* Nothing more to do. */ @@ -183,7 +184,7 @@ int main (argc, argv, envp) } else { /* Call the script with the list of interfaces. */ for (ip = interfaces; ip; ip = ip -> next) { - script_init (ip, "PREINIT"); + script_init (ip, "PREINIT", (struct string_list *)0); script_go (ip); } } @@ -202,7 +203,7 @@ int main (argc, argv, envp) } /* Start dispatching packets and timeouts... */ - dispatch (); + dispatch (1); /*NOTREACHED*/ return 0; } @@ -216,6 +217,13 @@ void cleanup () { } +void relay (ip, packet, length) + struct interface_info *ip; + struct dhcp_packet *packet; + int length; +{ +} + /* Individual States: * * Each routine is called from the dhclient_state_machine() in one of @@ -260,6 +268,7 @@ void state_init (ip) ip -> client -> destination = iaddr_broadcast; ip -> client -> state = S_SELECTING; ip -> client -> first_sending = cur_time; + ip -> client -> interval = 0; /* Add an immediate timeout to cause the first DHCPDISCOVER packet to go out. */ @@ -291,7 +300,7 @@ void state_selecting (ip) /* Check to see if we got an ARPREPLY for the address in this particular lease. */ if (!picked) { - script_init (ip, "ARPCHECK"); + script_init (ip, "ARPCHECK", lp -> medium); script_write_params (ip, "check_", lp); /* If the ARPCHECK code detects another @@ -323,6 +332,7 @@ void state_selecting (ip) ip -> client -> destination = iaddr_broadcast; ip -> client -> state = S_REQUESTING; ip -> client -> first_sending = cur_time; + ip -> client -> interval = 0; /* Make a DHCPREQUEST packet from the lease we picked. */ make_request (ip, picked); @@ -408,12 +418,15 @@ void dhcpack (packet) /* Write out the new lease. */ write_client_lease (ip, ip -> client -> new); + /* Remember the medium. */ + ip -> client -> new -> medium = ip -> client -> medium; + /* Run the client script with the new parameters. */ script_init (ip, (ip -> client -> state == S_REQUESTING ? "BOUND" : (ip -> client -> state == S_RENEWING ? "RENEW" - : "REBIND"))); + : "REBIND")), ip -> client -> new -> medium); if (ip -> client -> active) script_write_params (ip, "old_", ip -> client -> active); script_write_params (ip, "new_", ip -> client -> new); @@ -460,6 +473,7 @@ void state_bound (ip) ip -> client -> destination = iaddr_broadcast; ip -> client -> first_sending = cur_time; + ip -> client -> interval = 0; ip -> client -> state = S_RENEWING; /* Send the first packet immediately. */ @@ -564,8 +578,11 @@ void dhcpoffer (packet) return; } + /* Record the medium under which this lease was offered. */ + lease -> medium = ip -> client -> medium; + /* Send out an ARP Request for the offered IP address. */ - script_init (ip, "ARPSEND"); + 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. */ @@ -728,6 +745,7 @@ void send_discover (ip) { int result; int interval; + int increase = 1; /* Figure out how long it's been since we started transmitting. */ interval = cur_time - ip -> client -> first_sending; @@ -739,26 +757,67 @@ void send_discover (ip) return; } - /* Exponential backoff with random element. */ - if (!interval) - ++interval; - else - interval += random () % interval; + /* If we're selecting media, try the whole list before doing + the exponential backoff, but if we've already received an + offer, stop looping, because we obviously have it right. */ + if (!ip -> client -> offered_leases && + ip -> client -> config -> media) { + int fail = 0; + again: + if (ip -> client -> medium) { + ip -> client -> medium = + ip -> client -> medium -> next; + increase = 0; + } + if (!ip -> client -> medium) { + if (fail) + error ("No valid media types for %s!", + ip -> name); + ip -> client -> medium = + ip -> client -> config -> media; + increase = 1; + } + + note ("Trying medium \"%s\" %d", + ip -> client -> medium -> string, increase); + script_init (ip, "MEDIUM", ip -> client -> medium); + if (script_go (ip)) { + goto again; + } + } - /* Don't backoff past 30 seconds. */ - if (interval > 30) - interval = 20 + random () % interval; + /* If we're supposed to increase the interval, do so. If it's + currently zero (i.e., we haven't sent any packets yet), set + it to one; otherwise, add to it a random number between + zero and two times itself. On average, this means that it + will double with every transmission. */ + if (increase) { + if (!ip -> client -> interval) + ip -> client -> interval = 1; + else { + ip -> client -> interval += + random () % (2 * ip -> client -> interval); + } + /* Don't backoff past 30 seconds. */ + if (ip -> client -> interval > 30) + ip -> client -> interval = + 15 + random () % ip -> client -> interval; + } else if (!ip -> client -> interval) + ip -> client -> interval = 1; + /* If the backoff would take us to the panic timeout, just use that as the interval. */ - if (cur_time + interval > + if (cur_time + ip -> client -> interval > ip -> client -> first_sending + ip -> client -> config -> timeout) - interval = (ip -> client -> first_sending + - ip -> client -> config -> timeout) - cur_time + 1; + ip -> client -> interval = + (ip -> client -> first_sending + + ip -> client -> config -> timeout) - cur_time + 1; - note ("DHCPDISCOVER on %s to %s port %d", ip -> name, + note ("DHCPDISCOVER on %s to %s port %d interval %ld", + ip -> name, inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port)); + ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval); /* Send out a packet. */ result = send_packet (ip, (struct packet *)0, @@ -769,7 +828,7 @@ void send_discover (ip) if (result < 0) warn ("send_packet: %m"); - add_timeout (cur_time + 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 @@ -788,9 +847,12 @@ void state_panic (ip) /* Run through the list of leases and see if one can be used. */ while (ip -> client -> active) { if (ip -> client -> active -> expiry > cur_time) { + note ("Trying recorded lease %s", + piaddr (ip -> client -> active -> address)); /* Run the client script with the existing parameters. */ - script_init (ip, "TIMEOUT"); + script_init (ip, "TIMEOUT", + ip -> client -> active -> medium); script_write_params (ip, "new_", ip -> client -> active); @@ -830,6 +892,7 @@ void state_panic (ip) for (lp = ip -> client -> leases; lp -> next; lp = lp -> next) ; lp -> next = ip -> client -> active; + lp -> next -> next = (struct client_lease *)0; ip -> client -> active = ip -> client -> leases; ip -> client -> leases = ip -> client -> leases -> next; @@ -843,7 +906,8 @@ void state_panic (ip) /* No leases were available, or what was available didn't work, so tell the shell script that we failed to allocate an address, and try again later. */ - script_init (ip, "FAIL"); + note ("No working leases in persistent database - sleeping.\n"); + script_init (ip, "FAIL", (struct string_list *)0); script_go (ip); ip -> client -> state = S_INIT; add_timeout (cur_time + ip -> client -> config -> retry_interval, @@ -866,7 +930,7 @@ void send_request (ip) if (ip -> client -> state != S_REQUESTING && cur_time > ip -> client -> active -> expiry) { /* Run the client script with the new parameters. */ - script_init (ip, "EXPIRE"); + script_init (ip, "EXPIRE", (struct string_list *)0); script_write_params (ip, "old_", ip -> client -> active); script_go (ip); @@ -876,20 +940,24 @@ void send_request (ip) } /* Do the exponential backoff... */ - if (!interval) - ++interval; + if (!ip -> client -> interval) + ip -> client -> interval = 1; else - interval += random () % interval; + ip -> client -> interval += + random () % (2 * ip -> client -> interval); /* Don't backoff past 30 seconds. */ - if (interval > 30) - interval = 20 + random () % interval; + if (ip -> client -> interval > 30) + ip -> client -> interval = + 15 + random () % 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 + interval > ip -> client -> active -> expiry) - interval = ip -> client -> active -> expiry - cur_time + 1; + 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. */ @@ -936,7 +1004,8 @@ void send_request (ip) if (result < 0) warn ("send_packet: %m"); - add_timeout (cur_time + interval, send_request, ip); + add_timeout (cur_time + ip -> client -> interval, + send_request, ip); } void send_decline (ip) @@ -1367,6 +1436,9 @@ void write_client_lease (ip, lease) if (lease -> server_name) fprintf (leaseFile, " server-name \"%s\";\n", lease -> filename); + if (lease -> medium) + fprintf (leaseFile, " medium \"%s\";\n", + lease -> medium -> string); for (i = 0; i < 256; i++) { if (lease -> options [i].len) { fprintf (leaseFile, @@ -1374,7 +1446,7 @@ void write_client_lease (ip, lease) dhcp_options [i].name, pretty_print_option (i, lease -> options [i].data, - lease -> options [i].len)); + lease -> options [i].len, 1)); } } t = gmtime (&lease -> renewal); @@ -1405,9 +1477,10 @@ void write_client_lease (ip, lease) char scriptName [256]; FILE *scriptFile; -void script_init (ip, reason) +void script_init (ip, reason, medium) struct interface_info *ip; char *reason; + struct string_list *medium; { strcpy (scriptName, "/tmp/dcsXXXXXX"); mktemp (scriptName); @@ -1420,6 +1493,11 @@ void script_init (ip, reason) fprintf (scriptFile, "interface=\"%s\"\n", ip -> name); fprintf (scriptFile, "export interface\n"); } + if (medium) { + fprintf (scriptFile, "medium=\"%s\"\n", + ip -> client -> medium -> string); + fprintf (scriptFile, "export medium\n"); + } fprintf (scriptFile, "reason=\"%s\"\n", reason); fprintf (scriptFile, "export reason\n"); } @@ -1451,7 +1529,7 @@ void script_write_params (ip, prefix, lease) "%s%s=\"%s\"\n", prefix, s, pretty_print_option (i, lease -> options [i].data, - lease -> options [i].len)); + lease -> options [i].len, 0)); fprintf (scriptFile, "export %s%s\n", prefix, s); } } |