diff options
Diffstat (limited to 'net/isc-dhcp40-server/files/extra-patch-client::dhclient.c')
-rw-r--r-- | net/isc-dhcp40-server/files/extra-patch-client::dhclient.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/net/isc-dhcp40-server/files/extra-patch-client::dhclient.c b/net/isc-dhcp40-server/files/extra-patch-client::dhclient.c new file mode 100644 index 000000000000..6ad84bfa9e13 --- /dev/null +++ b/net/isc-dhcp40-server/files/extra-patch-client::dhclient.c @@ -0,0 +1,545 @@ +--- client/dhclient.c.orig Sat Apr 26 23:51:39 2003 ++++ client/dhclient.c Wed Mar 3 16:21:02 2004 +@@ -47,6 +47,13 @@ + #include "dhcpd.h" + #include "version.h" + ++#ifdef __FreeBSD__ ++#include <sys/ioctl.h> ++#include <net/if_media.h> ++#include <net80211/ieee80211_ioctl.h> ++#include <net80211/ieee80211.h> ++#endif ++ + TIME cur_time; + TIME default_lease_time = 43200; /* 12 hours... */ + TIME max_lease_time = 86400; /* 24 hours... */ +@@ -82,8 +89,11 @@ + struct string_list *client_env=NULL; + int client_env_count=0; + int onetry=0; +-int quiet=0; ++int quiet=1; + int nowait=0; ++#ifdef ENABLE_POLLING_MODE ++int polling_interval = 5; ++#endif + + static void usage PROTO ((void)); + +@@ -184,6 +194,9 @@ + } else if (!strcmp (argv [i], "-q")) { + quiet = 1; + quiet_interface_discovery = 1; ++ } else if (!strcmp (argv [i], "-v")) { ++ quiet = 0; ++ quiet_interface_discovery = 0; + } else if (!strcmp (argv [i], "-s")) { + if (++i == argc) + usage (); +@@ -197,6 +210,19 @@ + } else if (!strcmp (argv [i], "-n")) { + /* do not start up any interfaces */ + interfaces_requested = 1; ++#ifdef ENABLE_POLLING_MODE ++ } else if (!strcmp (argv [i], "-i")) { ++ if (++i == argc) ++ usage (); ++ polling_interval = (int)strtol (argv [i], ++ (char **)NULL, 10); ++ if (polling_interval <= 0) { ++ log_info ("Incorrect polling interval %d", ++ polling_interval); ++ log_info ("Using a default of 5 seconds"); ++ polling_interval = 5; ++ } ++#endif + } else if (!strcmp (argv [i], "-w")) { + /* do not exit if there are no broadcast interfaces. */ + persist = 1; +@@ -225,7 +251,16 @@ + if (strlen (argv [i]) > sizeof tmp -> name) + log_fatal ("%s: interface name too long (max %ld)", + argv [i], (long)strlen (argv [i])); +- strcpy (tmp -> name, argv [i]); ++ strlcpy (tmp -> name, argv [i], IFNAMSIZ); ++#ifdef __FreeBSD__ ++ set_ieee80211 (tmp); ++#endif ++ /* Init some interface vars, enable polling */ ++#ifdef ENABLE_POLLING_MODE ++ tmp -> forcediscover = 0; ++ tmp -> linkstate = HAVELINK; ++ tmp -> polling = 1; ++#endif /* ifdef ENABLE_POLLING_MODE */ + if (interfaces) { + interface_reference (&tmp -> next, + interfaces, MDL); +@@ -385,6 +420,16 @@ + INTERFACE_AUTOMATIC)) != + INTERFACE_REQUESTED)) + continue; ++#ifdef __FreeBSD__ ++ set_ieee80211 (ip); ++#endif ++#ifdef ENABLE_POLLING_MODE ++ ip -> forcediscover = 0; ++ if (ip -> client -> config -> media != NULL) ++ ip -> havemedia = 1; ++ else ++ ip -> havemedia = 0; ++#endif + script_init (ip -> client, + "PREINIT", (struct string_list *)0); + if (ip -> client -> alias) +@@ -427,8 +472,13 @@ + client -> state = S_INIT; + /* Set up a timeout to start the initialization + process. */ ++#ifdef ENABLE_POLLING_MODE ++ add_timeout (cur_time + random () % 5 + 2, ++ state_polling, client, 0, 0); ++#else + add_timeout (cur_time + random () % 5, + state_reboot, client, 0, 0); ++#endif + } + } + } +@@ -486,9 +536,9 @@ + log_info (arr); + log_info (url); + +- log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s", +- "[-s server]"); +- log_error (" [-cf config-file] [-lf lease-file]%s", ++ log_error ("Usage: dhclient [-1Ddqrv] [-i polling-interval] %s", ++ "[-nw] [-p <port>] [-s server]"); ++ log_error (" [-cf config-file] [-lf lease-file] %s", + "[-pf pid-file] [-e VAR=val]"); + log_fatal (" [-sf script-file] [interface]"); + } +@@ -876,6 +926,15 @@ + /* Write out the new lease. */ + write_client_lease (client, client -> new, 0, 0); + ++ /* ++ * It's now possible that state_reboot can be called ++ * after a interface link went down and is up again. ++ * To prevent tons of equal leases saved on disk, we rewrite ++ * them. ++ */ ++ read_client_leases (); ++ rewrite_client_leases (); ++ + /* Replace the old active lease with the new one. */ + if (client -> active) + destroy_client_lease (client -> active); +@@ -890,6 +949,12 @@ + piaddr (client -> active -> address), + (long)(client -> active -> renewal - cur_time)); + client -> state = S_BOUND; ++#ifdef ENABLE_POLLING_MODE ++ /* Init some interface vars, enable polling */ ++ client -> interface -> linkstate = HAVELINK; ++ client -> interface -> forcediscover = 0; ++ client -> interface -> polling = 1; ++#endif /* ifdef ENABLE_POLLING_MODE */ + reinitialize_interfaces (); + go_daemon (); + if (client -> config -> do_forward_update) { +@@ -1352,6 +1417,11 @@ + int interval; + int increase = 1; + ++#ifdef ENABLE_POLLING_MODE ++ /* Disable polling for this interface */ ++ client -> interface -> polling = 0; ++#endif ++ + /* Figure out how long it's been since we started transmitting. */ + interval = cur_time - client -> first_sending; + +@@ -1457,6 +1527,9 @@ + struct client_lease *loop; + struct client_lease *lp; + ++ if (client -> interface -> linkstate == NOLINK) ++ return; ++ + loop = lp = client -> active; + + log_info ("No DHCPOFFERS received."); +@@ -1489,6 +1562,10 @@ + log_info ("bound: renewal in %ld %s.", + (long)(client -> active -> renewal - + cur_time), "seconds"); ++#ifdef ENABLE_POLLING_MODE ++ /* Enable polling for this interface */ ++ client -> interface -> polling = 1; ++#endif + add_timeout (client -> active -> renewal, + state_bound, client, 0, 0); + } else { +@@ -1496,6 +1573,11 @@ + log_info ("bound: immediate renewal."); + state_bound (client); + } ++ /* ++ * Set the link status back to nolink, even ++ * if we have media settings. ++ */ ++ client -> interface -> linkstate = NOLINK; + reinitialize_interfaces (); + go_daemon (); + return; +@@ -1541,6 +1623,12 @@ + } + + log_info ("No working leases in persistent database - sleeping."); ++ ++#ifdef ENABLE_POLLING_MODE ++ /* Enable polling for this interface */ ++ client -> interface -> polling = 1; ++#endif ++ + script_init (client, "FAIL", (struct string_list *)0); + if (client -> alias) + script_write_params (client, "alias_", client -> alias); +@@ -1681,6 +1769,18 @@ + client -> packet.secs = htons (65535); + } + ++ /* ++ * Only try the first ten seconds to renew a lease from a ++ * given dhcp-server adress. After that, fall back to use ++ * state_reboot with INADDR_BROADCAST. ++ */ ++ if (destination.sin_addr.s_addr != INADDR_BROADCAST && ++ (client -> state == S_RENEWING || client -> state == S_REBINDING)) { ++ if (client -> active && client -> active -> expiry > cur_time && ++ interval >= 10) ++ goto cancel; ++ } ++ + log_info ("DHCPREQUEST on %s to %s port %d", + client -> name ? client -> name : client -> interface -> name, + inet_ntoa (destination.sin_addr), +@@ -1702,6 +1802,16 @@ + from, &destination, + (struct hardware *)0); + ++ /* ++ * If sendto() for a direct request fails, fall back to use ++ * state_reboot with INADDR_BROADCAST. ++ */ ++ if (result == -1 && destination.sin_addr.s_addr != INADDR_BROADCAST && ++ (client -> state == S_RENEWING || client -> state == S_REBINDING)) { ++ if (client -> active && client -> active -> expiry > cur_time) ++ goto cancel; ++ } ++ + add_timeout (cur_time + client -> interval, + send_request, client, 0, 0); + } +@@ -2597,6 +2707,13 @@ + wstatus = 0; + } + } else { ++ if ((i = open(_PATH_DEVNULL, O_RDWR)) != -1) { ++ dup2(i, STDIN_FILENO); ++ dup2(i, STDOUT_FILENO); ++ dup2(i, STDERR_FILENO); ++ if (i > STDERR_FILENO) ++ close(i); ++ } + execve (scriptName, argv, envp); + log_error ("execve (%s, ...): %m", scriptName); + exit (0); +@@ -2783,8 +2900,10 @@ + case S_STOPPED: + break; + } ++#ifndef ENABLE_POLLING_MODE + client -> state = S_INIT; + state_reboot (client); ++#endif + } + } + } +@@ -3010,7 +3129,9 @@ + break; + + case server_awaken: ++#ifndef ENABLE_POLLING_MODE + state_reboot (client); ++#endif + break; + } + } +@@ -3147,3 +3268,265 @@ + data_string_forget (&ddns_dhcid, MDL); + return rcode; + } ++ ++/* Check to see if there's a wire plugged in */ ++int ++interface_active(struct interface_info *ip) { ++#ifdef __FreeBSD__ ++ struct ifmediareq ifmr; ++ int *media_list, i; ++ char *ifname; ++ int sock; ++ ++ ifname = ip -> name; ++ ++ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) ++ log_fatal ("Can't create interface_active socket"); ++ ++ (void) memset (&ifmr, 0, sizeof (ifmr)); ++ (void) strncpy (ifmr.ifm_name, ifname, sizeof (ifmr.ifm_name)); ++ ++ if (ioctl (sock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { ++ /* ++ * Interface doesn't support SIOCGIFMEDIA, presume okay ++ */ ++ close (sock); ++ return (HAVELINK); ++ } ++ close (sock); ++ ++ if (ifmr.ifm_count == 0) { ++ /* ++ * Assume that this means interface ++ * does not support SIOCGIFMEDIA ++ */ ++ log_fatal ("%s: no media types?", ifname); ++ return (HAVELINK); ++ } ++ ++ if (ifmr.ifm_status & IFM_AVALID) { ++ if (ip -> ieee80211) { ++ /* ++ * Wavelan devices need to be checked if they are ++ * associated. ++ */ ++ if ((IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) && ++ (ifmr.ifm_status & IFM_ACTIVE)) { ++ return (HAVELINK); ++ } ++ } else { ++ if (ifmr.ifm_status & IFM_ACTIVE) { ++ return (HAVELINK); ++ } ++ } ++ /* ++ * We really have no link. ++ */ ++ return (NOLINK); ++ } ++ /* ++ * IFM_AVALID is not set. We cannot check ++ * the link state. Assume HAVELINK. ++ */ ++ ++#endif /* Other OSs */ ++ /* ++ * Always return a successful link if the OS ++ * is not supported. ++ */ ++ return (HAVELINK); ++} ++ ++#ifdef __FreeBSD__ ++void ++set_ieee80211 (struct interface_info *ip) { ++ ++ struct ieee80211req ireq; ++ u_int8_t data[32]; ++ int associated = 0; ++ int *media_list, i; ++ char *ifname; ++ int sock; ++ ++ ifname = ip -> name; ++ ++ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) ++ log_fatal ("Can't create interface_active socket"); ++ ++ (void) memset (&ireq, 0, sizeof (ireq)); ++ (void) strncpy (ireq.i_name, ifname, sizeof (ireq.i_name)); ++ ireq.i_data = &data; ++ ireq.i_type = IEEE80211_IOC_SSID; ++ ireq.i_val = -1; ++ /* ++ * If we can't get the SSID, ++ * this isn't an 802.11 device. ++ */ ++ if (ioctl (sock, SIOCG80211, &ireq) < 0) ++ ip -> ieee80211 = 0; ++ else { ++#ifdef DEBUG ++ printf ("Device %s has 802.11\n", ifname); ++#endif ++ ip -> ieee80211 = 1; ++ } ++ close (sock); ++ } ++#endif /* __FreeBSD__ */ ++ ++#ifdef ENABLE_POLLING_MODE ++/* Go to background after some time */ ++void state_background (cpp) ++ void *cpp; ++{ ++ go_daemon (); ++} ++ ++/* Check the state of the NICs if we have link */ ++void state_polling (cpp) ++ void *cpp; ++{ ++ static int doinitcheck = 0; ++ struct interface_info *ip; ++ struct client_state *client; ++ int result; ++ ++ for (ip = interfaces; ip; ip = ip -> next) { ++ if (! ip -> polling) ++ continue; ++#ifdef DEBUG ++ printf ("%s: Polling interface state\n", ip -> name); ++ for (client = ip -> client; ++ client; client = client -> next) { ++ printf ("%s: client state of %d\n", ip -> name, ip -> client -> state); ++ printf ("%s: link = %d\n", ip -> name, ip -> linkstate); ++ } ++#endif ++ ++ result = interface_active (ip); ++ /* ++ * If dhclient.conf contains media settings, we cannot ++ * abort if the interface is not set to active mode. ++ */ ++ if (ip -> havemedia && ip -> client -> state != S_BOUND) { ++ if (result == HAVELINK) ++ ip -> forcediscover = 1; ++ result = HAVELINK; ++ } ++ ++ /* ++ * The last status of the interface tells us ++ * the we've got no link ... ++ */ ++ if (ip -> linkstate == NOLINK || ! doinitcheck) { ++ /* ++ * ... but we have now link. Let's send ++ * requests. ++ */ ++ if (result == HAVELINK) { ++#ifdef DEBUG ++ if (ip -> havemedia) ++ printf ("%s: Trying media settings on interface\n", ++ ip -> name); ++ else ++ printf ("%s: Found Link on interface\n", ip -> name); ++#endif ++ /* ++ * Set the interface to state_bound. We assume that we have ++ * a working link. If we cannot reach the server directly, ++ * INADDR_BROADCAST is used. ++ */ ++ for (client = ip -> client; ++ client; client = client -> next) { ++ cancel_timeout (state_init, client); ++ cancel_timeout (state_reboot, client); ++ cancel_timeout (state_selecting, client); ++ if (client -> active) { ++ add_timeout (cur_time + random () % 5, ++ state_bound, client, 0, 0); ++ } else { ++ add_timeout (cur_time + random () % 5, ++ state_reboot, client, 0, 0); ++ } ++ } ++ ip -> linkstate = HAVELINK; ++ } else { ++#ifdef DEBUG ++ printf ("%s: No link on interface\n", ip -> name); ++#endif ++ for (client = ip -> client; ++ client; client = client -> next) { ++ /* ++ * Without this add_timout(), dhclient does ++ * not poll on a interface if there ++ * is no cable plugged in at startup ++ * time. Because we add one additional second ++ * to the time of a normal timeout, we always ++ * skip and block a running one. This prevents ++ * that polling is done twice at the same time. ++ */ ++ if (client -> state == S_INIT) { ++ add_timeout (cur_time + (polling_interval + 1), ++ state_polling, client, 0, 0); ++ } ++ } ++ ip -> linkstate = NOLINK; ++ /* ++ * Automatically go into the background after ++ * some time. Do this only if there are no ++ * media options available for a interface. ++ */ ++ if (! ip -> havemedia && ! doinitcheck) { ++ add_timeout (cur_time + (polling_interval * 2), ++ state_background, client, 0, 0); ++ } ++ } ++ } ++ ++ /* ++ * The last status of the interface tells us ++ * the we previously had link. ++ */ ++ if (ip -> linkstate == HAVELINK && doinitcheck) { ++ if (result == NOLINK) { ++ /* ++ * We lost link on the interface, or it isn't ++ * associated anymore. ++ */ ++#ifdef DEBUG ++ printf ("%s: Lost Link on interface\n", ip -> name); ++#endif ++ /* ++ * After we lost link, cycle again through the ++ * different media settings if available. Else ++ * set NOLINK. ++ */ ++ if (ip -> havemedia) ++ ip -> forcediscover = 1; ++ else ++ ip -> linkstate = NOLINK; ++ } ++ /* ++ * If we happen to have a real link, but no ++ * active lease, force the interface into ++ * state_reboot. Do the same if media settings ++ * are available. ++ */ ++ if (ip -> forcediscover) { ++ for (client = ip -> client; ++ client; client = client -> next) { ++ if (client -> state != S_REBOOTING && ++ client -> state != S_SELECTING) { ++ add_timeout (cur_time + random () % 5, ++ state_reboot, client, 0, 0); ++ } ++ } ++ ip -> forcediscover = 0; ++ ip -> linkstate = HAVELINK; ++ } ++ /* We still have link, do nothing. */ ++ } ++ } ++ doinitcheck = 1; ++} ++#endif /* ifdef ENABLE_POLLING_MODE */ |