From b8cf055d97c909e93260c3e7ca12fc12896a5487 Mon Sep 17 00:00:00 2001 From: Ted Lemon Date: Tue, 16 Sep 1997 18:09:41 +0000 Subject: [PATCH] Add support for interfaces_requested flag. NUL-terminate copied lease options. Add cons_option parameter. Support system status messages --- client/dhclient.c | 139 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 123 insertions(+), 16 deletions(-) diff --git a/client/dhclient.c b/client/dhclient.c index 809f9ff2..a64dc303 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -56,7 +56,7 @@ #ifndef lint static char copyright[] = -"$Id: dhclient.c,v 1.39 1997/06/03 01:40:58 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dhclient.c,v 1.40 1997/09/16 18:09:41 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -70,6 +70,8 @@ char *path_dhclient_conf = _PATH_DHCLIENT_CONF; char *path_dhclient_db = _PATH_DHCLIENT_DB; char *path_dhclient_pid = _PATH_DHCLIENT_PID; +int interfaces_requested = 0; + int log_perror = 1; struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; @@ -134,6 +136,7 @@ int main (argc, argv, envp) strcpy (tmp -> name, argv [i]); tmp -> next = interfaces; tmp -> flags = INTERFACE_REQUESTED; + interfaces_requested = 1; interfaces = tmp; } } @@ -197,7 +200,9 @@ 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 (DISCOVER_RUNNING); + 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 @@ -223,6 +228,9 @@ int main (argc, argv, envp) /* Set up the bootp packet handler... */ bootp_packet_handler = do_packet; + /* Start listening on the systat socket... */ + systat_startup (status_message); + /* Start dispatching packets and timeouts... */ dispatch (); @@ -291,8 +299,10 @@ void state_reboot (ipp) 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. */ + /* Zap the medium list... */ + ip -> client -> medium = (struct string_list *)0; + + /* Send out the first DHCPREQUEST packet. */ send_request (ip); } @@ -484,12 +494,12 @@ void dhcpack (packet) void bind_lease (ip) struct interface_info *ip; { - /* Write out the new lease. */ - write_client_lease (ip, ip -> client -> new); - /* Remember the medium. */ ip -> client -> new -> medium = ip -> client -> medium; + /* Write out the new lease. */ + write_client_lease (ip, ip -> client -> new); + /* Run the client script with the new parameters. */ script_init (ip, (ip -> client -> state == S_REQUESTING ? "BOUND" @@ -659,6 +669,7 @@ void dhcpoffer (packet) 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++) { @@ -777,7 +788,7 @@ struct client_lease *packet_to_lease (packet) if (packet -> options [i].len) { lease -> options [i].data = (unsigned char *) - malloc (packet -> options [i].len); + malloc (packet -> options [i].len + 1); if (!lease -> options [i].data) { warn ("dhcpoffer: no memory for option %d\n", i); @@ -789,6 +800,8 @@ struct client_lease *packet_to_lease (packet) packet -> options [i].len); lease -> options [i].len = packet -> options [i].len; + lease -> options [i].data + [lease -> options [i].len] = 0; } } } @@ -1114,12 +1127,28 @@ void send_request (ipp) if ((ip -> client -> state == S_REBOOTING || ip -> client -> state == S_REQUESTING) && interval > ip -> client -> config -> reboot_timeout) { + cancel: ip -> client -> state = S_INIT; cancel_timeout (send_request, ip); state_init (ip); return; } + /* If we're in the reboot state, make sure the media is set up + correctly. */ + if (ip -> client -> state == S_REBOOTING && + !ip -> client -> medium && + ip -> client -> active -> medium ) { + script_init (ip, "MEDIUM", ip -> client -> active -> medium); + + /* If the medium we chose won't fly, go to INIT state. */ + if (script_go (ip)) + goto cancel; + + /* Record the medium. */ + ip -> client -> medium = ip -> client -> active -> medium; + } + /* If the lease has expired, relinquish the address and go back to the INIT state. */ if (ip -> client -> state != S_REQUESTING && @@ -1327,7 +1356,7 @@ void make_discover (ip, lease) /* Set up the option buffer... */ ip -> client -> packet_length = cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); + options, 0, 0, 0); if (ip -> client -> packet_length < BOOTP_MIN_LEN) ip -> client -> packet_length = BOOTP_MIN_LEN; @@ -1434,7 +1463,7 @@ void make_request (ip, lease) /* Set up the option buffer... */ ip -> client -> packet_length = cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); + options, 0, 0, 0); if (ip -> client -> packet_length < BOOTP_MIN_LEN) ip -> client -> packet_length = BOOTP_MIN_LEN; @@ -1533,7 +1562,7 @@ void make_decline (ip, lease) /* Set up the option buffer... */ ip -> client -> packet_length = cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); + options, 0, 0, 0); if (ip -> client -> packet_length < BOOTP_MIN_LEN) ip -> client -> packet_length = BOOTP_MIN_LEN; @@ -1599,7 +1628,7 @@ void make_release (ip, lease) /* Set up the option buffer... */ ip -> client -> packet_length = cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); + options, 0, 0, 0); if (ip -> client -> packet_length < BOOTP_MIN_LEN) ip -> client -> packet_length = BOOTP_MIN_LEN; @@ -1755,10 +1784,21 @@ void script_init (ip, reason, medium) char *reason; struct string_list *medium; { - strcpy (scriptName, "/tmp/dcsXXXXXX"); - mktemp (scriptName); + int fd; +#ifndef HAVE_MKSTEMP - scriptFile = fopen (scriptName, "w"); + do { +#endif + strcpy (scriptName, "/tmp/dcsXXXXXX"); +#ifdef HAVE_MKSTEMP + fd = mkstemp (scriptName); +#else + mktemp (scriptName); + fd = creat (scriptName, 0600); + } while (fd < 0); +#endif + + scriptFile = fdopen (fd, "w"); if (!scriptFile) error ("can't write script file: %m"); fprintf (scriptFile, "#!/bin/sh\n\n"); @@ -1925,8 +1965,10 @@ void go_daemon () int pid; /* Don't become a daemon if the user requested otherwise. */ - if (no_daemon) + if (no_daemon) { + write_client_pid_file (); return; + } /* Only do it once. */ if (state) @@ -1943,5 +1985,70 @@ void go_daemon () exit (0); /* Become session leader and get pid... */ pid = setsid (); + + write_client_pid_file (); } +void write_client_pid_file () +{ + FILE *pf; + int pfdesc; + + pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644); + + if (pfdesc < 0) { + warn ("Can't create %s: %m", path_dhclient_pid); + return; + } + + pf = fdopen (pfdesc, "w"); + if (!pf) + warn ("Can't fdopen %s: %m", path_dhclient_pid); + else { + fprintf (pf, "%d\n", getpid ()); + fclose (pf); + } +} + +void status_message (header, data) + struct systat_header *header; + void *data; +{ + switch (header -> type) { + case NETWORK_LOCATION_CHANGED: + client_location_changed (); + break; + + default: + break; + } +} + +void client_location_changed () +{ + struct interface_info *ip; + + for (ip = interfaces; ip; ip = ip -> next) { + switch (ip -> client -> state) { + case S_SELECTING: + cancel_timeout (send_discover, ip); + break; + + case S_BOUND: + cancel_timeout (state_bound, ip); + break; + + case S_REBOOTING: + case S_REQUESTING: + case S_RENEWING: + cancel_timeout (send_request, ip); + break; + + case S_INIT: + case S_REBINDING: + break; + } + ip -> client -> state = S_INIT; + state_reboot (ip); + } +}