1 $DragonFly: src/sbin/dhclient/client/dhclient.c.patch,v 1.2 2006/12/31 21:18:35 dillon Exp $
2 --- dhclient.c.orig 2004-06-10 19:59:12.000000000 +0200
3 +++ dhclient.c 2004-06-24 17:02:09.000000000 +0200
8 +#include <sys/ioctl.h>
9 +#include <net/if_media.h>
10 +#if defined(DRAGONFLY_FUTURE)
11 +#include <net80211/ieee80211_ioctl.h>
12 +#include <net80211/ieee80211.h>
15 TIME default_lease_time = 43200; /* 12 hours... */
16 TIME max_lease_time = 86400; /* 24 hours... */
19 struct string_list *client_env=NULL;
20 int client_env_count=0;
25 +#ifdef ENABLE_POLLING_MODE
26 +int polling_interval = 5;
29 static void usage PROTO ((void));
32 } else if (!strcmp (argv [i], "-q")) {
34 quiet_interface_discovery = 1;
35 + } else if (!strcmp (argv [i], "-v")) {
37 + quiet_interface_discovery = 0;
38 } else if (!strcmp (argv [i], "-s")) {
42 } else if (!strcmp (argv [i], "-n")) {
43 /* do not start up any interfaces */
44 interfaces_requested = 1;
45 +#ifdef ENABLE_POLLING_MODE
46 + } else if (!strcmp (argv [i], "-i")) {
49 + polling_interval = (int)strtol (argv [i],
51 + if (polling_interval <= 0) {
52 + log_info ("Incorrect polling interval %d",
54 + log_info ("Using a default of 5 seconds");
55 + polling_interval = 5;
58 } else if (!strcmp (argv [i], "-w")) {
59 /* do not exit if there are no broadcast interfaces. */
62 if (strlen (argv [i]) > sizeof tmp -> name)
63 log_fatal ("%s: interface name too long (max %ld)",
64 argv [i], (long)strlen (argv [i]));
65 - strcpy (tmp -> name, argv [i]);
66 + strlcpy (tmp -> name, argv [i], IFNAMSIZ);
67 +#if defined(DRAGONFLY_FUTURE)
68 + set_ieee80211 (tmp);
70 + /* Init some interface vars, enable polling */
71 +#ifdef ENABLE_POLLING_MODE
72 + tmp -> forcediscover = 0;
73 + tmp -> linkstate = HAVELINK;
75 +#endif /* ifdef ENABLE_POLLING_MODE */
78 interface_reference (&tmp -> next,
81 INTERFACE_AUTOMATIC)) !=
84 +#if defined(DRAGONFLY_FUTURE)
87 +#ifdef ENABLE_POLLING_MODE
88 + ip -> forcediscover = 0;
89 + if (ip -> client -> config -> media != NULL)
90 + ip -> havemedia = 1;
92 + ip -> havemedia = 0;
94 script_init (ip -> client,
95 "PREINIT", (struct string_list *)0);
96 if (ip -> client -> alias)
98 client -> state = S_INIT;
99 /* Set up a timeout to start the initialization
101 +#ifdef ENABLE_POLLING_MODE
102 + add_timeout (cur_time + random () % 5 + 2,
103 + state_polling, client, 0, 0);
105 add_timeout (cur_time + random () % 5,
106 state_reboot, client, 0, 0);
115 - log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
117 - log_error (" [-cf config-file] [-lf lease-file]%s",
118 + log_error ("Usage: dhclient [-1Ddqrv] [-i polling-interval] %s",
119 + "[-nw] [-p <port>] [-s server]");
120 + log_error (" [-cf config-file] [-lf lease-file] %s",
121 "[-pf pid-file] [-e VAR=val]");
122 log_fatal (" [-sf script-file] [interface]");
125 /* Write out the new lease. */
126 write_client_lease (client, client -> new, 0, 0);
129 + * It's now possible that state_reboot can be called
130 + * after a interface link went down and is up again.
131 + * To prevent tons of equal leases saved on disk, we rewrite
134 + read_client_leases ();
135 + rewrite_client_leases ();
137 /* Replace the old active lease with the new one. */
138 if (client -> active)
139 destroy_client_lease (client -> active);
141 piaddr (client -> active -> address),
142 (long)(client -> active -> renewal - cur_time));
143 client -> state = S_BOUND;
144 +#ifdef ENABLE_POLLING_MODE
145 + /* Init some interface vars, enable polling */
146 + client -> interface -> linkstate = HAVELINK;
147 + client -> interface -> forcediscover = 0;
148 + client -> interface -> polling = 1;
149 +#endif /* ifdef ENABLE_POLLING_MODE */
150 reinitialize_interfaces ();
152 if (client -> config -> do_forward_update) {
153 @@ -1358,6 +1424,11 @@
157 +#ifdef ENABLE_POLLING_MODE
158 + /* Disable polling for this interface */
159 + client -> interface -> polling = 0;
162 /* Figure out how long it's been since we started transmitting. */
163 interval = cur_time - client -> first_sending;
165 @@ -1463,6 +1534,9 @@
166 struct client_lease *loop;
167 struct client_lease *lp;
169 + if (client -> interface -> linkstate == NOLINK)
172 loop = lp = client -> active;
174 log_info ("No DHCPOFFERS received.");
175 @@ -1495,6 +1569,10 @@
176 log_info ("bound: renewal in %ld %s.",
177 (long)(client -> active -> renewal -
178 cur_time), "seconds");
179 +#ifdef ENABLE_POLLING_MODE
180 + /* Enable polling for this interface */
181 + client -> interface -> polling = 1;
183 add_timeout (client -> active -> renewal,
184 state_bound, client, 0, 0);
186 @@ -1502,6 +1580,11 @@
187 log_info ("bound: immediate renewal.");
188 state_bound (client);
191 + * Set the link status back to nolink, even
192 + * if we have media settings.
194 + client -> interface -> linkstate = NOLINK;
195 reinitialize_interfaces ();
198 @@ -1547,6 +1630,12 @@
201 log_info ("No working leases in persistent database - sleeping.");
203 +#ifdef ENABLE_POLLING_MODE
204 + /* Enable polling for this interface */
205 + client -> interface -> polling = 1;
208 script_init (client, "FAIL", (struct string_list *)0);
210 script_write_params (client, "alias_", client -> alias);
211 @@ -1687,6 +1776,18 @@
212 client -> packet.secs = htons (65535);
216 + * Only try the first ten seconds to renew a lease from a
217 + * given dhcp-server adress. After that, fall back to use
218 + * state_reboot with INADDR_BROADCAST.
220 + if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
221 + (client -> state == S_RENEWING || client -> state == S_REBINDING)) {
222 + if (client -> active && client -> active -> expiry > cur_time &&
227 log_info ("DHCPREQUEST on %s to %s port %d",
228 client -> name ? client -> name : client -> interface -> name,
229 inet_ntoa (destination.sin_addr),
230 @@ -1708,6 +1809,16 @@
232 (struct hardware *)0);
235 + * If sendto() for a direct request fails, fall back to use
236 + * state_reboot with INADDR_BROADCAST.
238 + if (result == -1 && destination.sin_addr.s_addr != INADDR_BROADCAST &&
239 + (client -> state == S_RENEWING || client -> state == S_REBINDING)) {
240 + if (client -> active && client -> active -> expiry > cur_time)
244 add_timeout (cur_time + client -> interval,
245 send_request, client, 0, 0);
247 @@ -2603,6 +2714,13 @@
251 + if ((i = open(_PATH_DEVNULL, O_RDWR)) != -1) {
252 + dup2(i, STDIN_FILENO);
253 + dup2(i, STDOUT_FILENO);
254 + dup2(i, STDERR_FILENO);
255 + if (i > STDERR_FILENO)
258 execve (scriptName, argv, envp);
259 log_error ("execve (%s, ...): %m", scriptName);
261 @@ -2789,8 +2907,10 @@
265 +#ifndef ENABLE_POLLING_MODE
266 client -> state = S_INIT;
267 state_reboot (client);
272 @@ -3016,7 +3136,9 @@
276 +#ifndef ENABLE_POLLING_MODE
277 state_reboot (client);
282 @@ -3153,3 +3275,256 @@
283 data_string_forget (&ddns_dhcid, MDL);
287 +/* Check to see if there's a wire plugged in */
289 +interface_active(struct interface_info *ip) {
290 + struct ifmediareq ifmr;
291 + int *media_list, i;
295 + ifname = ip -> name;
297 + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
298 + log_fatal ("Can't create interface_active socket");
300 + memset (&ifmr, 0, sizeof (ifmr));
301 + strncpy (ifmr.ifm_name, ifname, sizeof (ifmr.ifm_name));
303 + if (ioctl (sock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
305 + * Interface doesn't support SIOCGIFMEDIA, presume okay
312 + if (ifmr.ifm_count == 0) {
314 + * Assume that this means interface
315 + * does not support SIOCGIFMEDIA
317 + log_fatal ("%s: no media types?", ifname);
321 + if (ifmr.ifm_status & IFM_AVALID) {
322 + if (ip -> ieee80211) {
324 + * Wavelan devices need to be checked if they are
327 + if ((IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) &&
328 + (ifmr.ifm_status & IFM_ACTIVE)) {
332 + if (ifmr.ifm_status & IFM_ACTIVE) {
337 + * We really have no link.
342 + * IFM_AVALID is not set. We cannot check
343 + * the link state. Assume HAVELINK.
349 +#if defined(DRAGONFLY_FUTURE)
351 +set_ieee80211 (struct interface_info *ip) {
352 + struct ieee80211req ireq;
354 + int associated = 0;
355 + int *media_list, i;
359 + ifname = ip -> name;
361 + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
362 + log_fatal ("Can't create interface_active socket");
364 + memset (&ireq, 0, sizeof (ireq));
365 + strncpy (ireq.i_name, ifname, sizeof (ireq.i_name));
366 + ireq.i_data = &data;
367 + ireq.i_type = IEEE80211_IOC_SSID;
370 + * If we can't get the SSID,
371 + * this isn't an 802.11 device.
373 + if (ioctl (sock, SIOCG80211, &ireq) < 0)
374 + ip -> ieee80211 = 0;
377 + printf ("Device %s has 802.11\n", ifname);
379 + ip -> ieee80211 = 1;
385 +#ifdef ENABLE_POLLING_MODE
386 +/* Go to background after some time */
387 +void state_background (void *cpp)
392 +/* Check the state of the NICs if we have link */
393 +void state_polling (void *cpp)
395 + static int doinitcheck = 0;
396 + struct interface_info *ip;
397 + struct client_state *client;
400 + for (ip = interfaces; ip; ip = ip -> next) {
401 + if (! ip -> polling)
404 + printf ("%s: Polling interface state\n", ip -> name);
405 + for (client = ip -> client;
406 + client; client = client -> next) {
407 + printf ("%s: client state of %d\n", ip -> name, ip -> client -> state);
408 + printf ("%s: link = %d\n", ip -> name, ip -> linkstate);
412 + result = interface_active (ip);
414 + * If dhclient.conf contains media settings, we cannot
415 + * abort if the interface is not set to active mode.
417 + if (ip -> havemedia && ip -> client -> state != S_BOUND) {
418 + if (result == HAVELINK)
419 + ip -> forcediscover = 1;
424 + * The last status of the interface tells us
425 + * the we've got no link ...
427 + if (ip -> linkstate == NOLINK || ! doinitcheck) {
429 + * ... but we have now link. Let's send
432 + if (result == HAVELINK) {
434 + if (ip -> havemedia)
435 + printf ("%s: Trying media settings on interface\n",
438 + printf ("%s: Found Link on interface\n", ip -> name);
441 + * Set the interface to state_bound. We assume that we have
442 + * a working link. If we cannot reach the server directly,
443 + * INADDR_BROADCAST is used.
445 + for (client = ip -> client;
446 + client; client = client -> next) {
447 + cancel_timeout (state_init, client);
448 + cancel_timeout (state_reboot, client);
449 + cancel_timeout (state_selecting, client);
450 + if (client -> active) {
451 + add_timeout (cur_time + random () % 5,
452 + state_bound, client, 0, 0);
454 + add_timeout (cur_time + random () % 5,
455 + state_reboot, client, 0, 0);
458 + ip -> linkstate = HAVELINK;
461 + printf ("%s: No link on interface\n", ip -> name);
463 + for (client = ip -> client;
464 + client; client = client -> next) {
466 + * Without this add_timout(), dhclient does
467 + * not poll on a interface if there
468 + * is no cable plugged in at startup
469 + * time. Because we add one additional second
470 + * to the time of a normal timeout, we always
471 + * skip and block a running one. This prevents
472 + * that polling is done twice at the same time.
474 + if (client -> state == S_INIT) {
475 + add_timeout (cur_time + (polling_interval + 1),
476 + state_polling, client, 0, 0);
479 + ip -> linkstate = NOLINK;
481 + * Automatically go into the background after
482 + * some time. Do this only if there are no
483 + * media options available for a interface.
485 + if (! ip -> havemedia && ! doinitcheck) {
486 + add_timeout (cur_time + (polling_interval * 2),
487 + state_background, client, 0, 0);
493 + * The last status of the interface tells us
494 + * the we previously had link.
496 + if (ip -> linkstate == HAVELINK && doinitcheck) {
497 + if (result == NOLINK) {
499 + * We lost link on the interface, or it isn't
500 + * associated anymore.
503 + printf ("%s: Lost Link on interface\n", ip -> name);
506 + * After we lost link, cycle again through the
507 + * different media settings if available. Else
510 + if (ip -> havemedia)
511 + ip -> forcediscover = 1;
513 + ip -> linkstate = NOLINK;
516 + * If we happen to have a real link, but no
517 + * active lease, force the interface into
518 + * state_reboot. Do the same if media settings
521 + if (ip -> forcediscover) {
522 + for (client = ip -> client;
523 + client; client = client -> next) {
524 + if (client -> state != S_REBOOTING &&
525 + client -> state != S_SELECTING) {
526 + add_timeout (cur_time + random () % 5,
527 + state_reboot, client, 0, 0);
530 + ip -> forcediscover = 0;
531 + ip -> linkstate = HAVELINK;
533 + /* We still have link, do nothing. */
538 +#endif /* ifdef ENABLE_POLLING_MODE */