Start flushing out the IPI routines and do some clean-up.
[dragonfly/vkernel-mp.git] / sbin / dhclient / client / dhclient.c.patch
blob5d1da84ff1e1589800f74d26637232e0f713750e
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
4 @@ -38,6 +38,13 @@
5 #include "dhcpd.h"
6 #include "version.h"
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>
13 +#endif
15 TIME default_lease_time = 43200; /* 12 hours... */
16 TIME max_lease_time = 86400; /* 24 hours... */
18 @@ -73,8 +80,11 @@
19 struct string_list *client_env=NULL;
20 int client_env_count=0;
21 int onetry=0;
22 -int quiet=0;
23 +int quiet=1;
24 int nowait=0;
25 +#ifdef ENABLE_POLLING_MODE
26 +int polling_interval = 5;
27 +#endif
29 static void usage PROTO ((void));
31 @@ -175,6 +185,9 @@
32 } else if (!strcmp (argv [i], "-q")) {
33 quiet = 1;
34 quiet_interface_discovery = 1;
35 + } else if (!strcmp (argv [i], "-v")) {
36 + quiet = 0;
37 + quiet_interface_discovery = 0;
38 } else if (!strcmp (argv [i], "-s")) {
39 if (++i == argc)
40 usage ();
41 @@ -188,6 +201,19 @@
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")) {
47 + if (++i == argc)
48 + usage ();
49 + polling_interval = (int)strtol (argv [i],
50 + (char **)NULL, 10);
51 + if (polling_interval <= 0) {
52 + log_info ("Incorrect polling interval %d",
53 + polling_interval);
54 + log_info ("Using a default of 5 seconds");
55 + polling_interval = 5;
56 + }
57 +#endif
58 } else if (!strcmp (argv [i], "-w")) {
59 /* do not exit if there are no broadcast interfaces. */
60 persist = 1;
61 @@ -216,7 +242,17 @@
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);
69 +#endif
70 + /* Init some interface vars, enable polling */
71 +#ifdef ENABLE_POLLING_MODE
72 + tmp -> forcediscover = 0;
73 + tmp -> linkstate = HAVELINK;
74 + tmp -> polling = 1;
75 +#endif /* ifdef ENABLE_POLLING_MODE */
77 if (interfaces) {
78 interface_reference (&tmp -> next,
79 interfaces, MDL);
80 @@ -376,6 +412,16 @@
81 INTERFACE_AUTOMATIC)) !=
82 INTERFACE_REQUESTED))
83 continue;
84 +#if defined(DRAGONFLY_FUTURE)
85 + set_ieee80211 (ip);
86 +#endif
87 +#ifdef ENABLE_POLLING_MODE
88 + ip -> forcediscover = 0;
89 + if (ip -> client -> config -> media != NULL)
90 + ip -> havemedia = 1;
91 + else
92 + ip -> havemedia = 0;
93 +#endif
94 script_init (ip -> client,
95 "PREINIT", (struct string_list *)0);
96 if (ip -> client -> alias)
97 @@ -418,8 +464,13 @@
98 client -> state = S_INIT;
99 /* Set up a timeout to start the initialization
100 process. */
101 +#ifdef ENABLE_POLLING_MODE
102 + add_timeout (cur_time + random () % 5 + 2,
103 + state_polling, client, 0, 0);
104 +#else
105 add_timeout (cur_time + random () % 5,
106 state_reboot, client, 0, 0);
107 +#endif
111 @@ -477,9 +528,9 @@
112 log_info (arr);
113 log_info (url);
115 - log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
116 - "[-s server]");
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]");
124 @@ -882,6 +933,15 @@
125 /* Write out the new lease. */
126 write_client_lease (client, client -> new, 0, 0);
128 + /*
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
132 + * them.
133 + */
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);
140 @@ -896,6 +956,12 @@
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 ();
151 go_daemon ();
152 if (client -> config -> do_forward_update) {
153 @@ -1358,6 +1424,11 @@
154 int interval;
155 int increase = 1;
157 +#ifdef ENABLE_POLLING_MODE
158 + /* Disable polling for this interface */
159 + client -> interface -> polling = 0;
160 +#endif
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)
170 + return;
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;
182 +#endif
183 add_timeout (client -> active -> renewal,
184 state_bound, client, 0, 0);
185 } else {
186 @@ -1502,6 +1580,11 @@
187 log_info ("bound: immediate renewal.");
188 state_bound (client);
190 + /*
191 + * Set the link status back to nolink, even
192 + * if we have media settings.
193 + */
194 + client -> interface -> linkstate = NOLINK;
195 reinitialize_interfaces ();
196 go_daemon ();
197 return;
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;
206 +#endif
208 script_init (client, "FAIL", (struct string_list *)0);
209 if (client -> alias)
210 script_write_params (client, "alias_", client -> alias);
211 @@ -1687,6 +1776,18 @@
212 client -> packet.secs = htons (65535);
215 + /*
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.
219 + */
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 &&
223 + interval >= 10)
224 + goto cancel;
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 @@
231 from, &destination,
232 (struct hardware *)0);
234 + /*
235 + * If sendto() for a direct request fails, fall back to use
236 + * state_reboot with INADDR_BROADCAST.
237 + */
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)
241 + goto cancel;
244 add_timeout (cur_time + client -> interval,
245 send_request, client, 0, 0);
247 @@ -2603,6 +2714,13 @@
248 wstatus = 0;
250 } else {
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)
256 + close(i);
258 execve (scriptName, argv, envp);
259 log_error ("execve (%s, ...): %m", scriptName);
260 exit (0);
261 @@ -2789,8 +2907,10 @@
262 case S_STOPPED:
263 break;
265 +#ifndef ENABLE_POLLING_MODE
266 client -> state = S_INIT;
267 state_reboot (client);
268 +#endif
272 @@ -3016,7 +3136,9 @@
273 break;
275 case server_awaken:
276 +#ifndef ENABLE_POLLING_MODE
277 state_reboot (client);
278 +#endif
279 break;
282 @@ -3153,3 +3275,256 @@
283 data_string_forget (&ddns_dhcid, MDL);
284 return rcode;
287 +/* Check to see if there's a wire plugged in */
288 +int
289 +interface_active(struct interface_info *ip) {
290 + struct ifmediareq ifmr;
291 + int *media_list, i;
292 + char *ifname;
293 + int sock;
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) {
304 + /*
305 + * Interface doesn't support SIOCGIFMEDIA, presume okay
306 + */
307 + close (sock);
308 + return (HAVELINK);
310 + close (sock);
312 + if (ifmr.ifm_count == 0) {
313 + /*
314 + * Assume that this means interface
315 + * does not support SIOCGIFMEDIA
316 + */
317 + log_fatal ("%s: no media types?", ifname);
318 + return (HAVELINK);
321 + if (ifmr.ifm_status & IFM_AVALID) {
322 + if (ip -> ieee80211) {
323 + /*
324 + * Wavelan devices need to be checked if they are
325 + * associated.
326 + */
327 + if ((IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) &&
328 + (ifmr.ifm_status & IFM_ACTIVE)) {
329 + return (HAVELINK);
331 + } else {
332 + if (ifmr.ifm_status & IFM_ACTIVE) {
333 + return (HAVELINK);
336 + /*
337 + * We really have no link.
338 + */
339 + return (NOLINK);
341 + /*
342 + * IFM_AVALID is not set. We cannot check
343 + * the link state. Assume HAVELINK.
344 + */
346 + return (HAVELINK);
349 +#if defined(DRAGONFLY_FUTURE)
350 +void
351 +set_ieee80211 (struct interface_info *ip) {
352 + struct ieee80211req ireq;
353 + u_int8_t data[32];
354 + int associated = 0;
355 + int *media_list, i;
356 + char *ifname;
357 + int sock;
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;
368 + ireq.i_val = -1;
369 + /*
370 + * If we can't get the SSID,
371 + * this isn't an 802.11 device.
372 + */
373 + if (ioctl (sock, SIOCG80211, &ireq) < 0)
374 + ip -> ieee80211 = 0;
375 + else {
376 +#ifdef DEBUG
377 + printf ("Device %s has 802.11\n", ifname);
378 +#endif
379 + ip -> ieee80211 = 1;
381 + close (sock);
383 +#endif
385 +#ifdef ENABLE_POLLING_MODE
386 +/* Go to background after some time */
387 +void state_background (void *cpp)
389 + go_daemon ();
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;
398 + int result;
400 + for (ip = interfaces; ip; ip = ip -> next) {
401 + if (! ip -> polling)
402 + continue;
403 +#ifdef DEBUG
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);
410 +#endif
412 + result = interface_active (ip);
413 + /*
414 + * If dhclient.conf contains media settings, we cannot
415 + * abort if the interface is not set to active mode.
416 + */
417 + if (ip -> havemedia && ip -> client -> state != S_BOUND) {
418 + if (result == HAVELINK)
419 + ip -> forcediscover = 1;
420 + result = HAVELINK;
423 + /*
424 + * The last status of the interface tells us
425 + * the we've got no link ...
426 + */
427 + if (ip -> linkstate == NOLINK || ! doinitcheck) {
428 + /*
429 + * ... but we have now link. Let's send
430 + * requests.
431 + */
432 + if (result == HAVELINK) {
433 +#ifdef DEBUG
434 + if (ip -> havemedia)
435 + printf ("%s: Trying media settings on interface\n",
436 + ip -> name);
437 + else
438 + printf ("%s: Found Link on interface\n", ip -> name);
439 +#endif
440 + /*
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.
444 + */
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);
453 + } else {
454 + add_timeout (cur_time + random () % 5,
455 + state_reboot, client, 0, 0);
458 + ip -> linkstate = HAVELINK;
459 + } else {
460 +#ifdef DEBUG
461 + printf ("%s: No link on interface\n", ip -> name);
462 +#endif
463 + for (client = ip -> client;
464 + client; client = client -> next) {
465 + /*
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.
473 + */
474 + if (client -> state == S_INIT) {
475 + add_timeout (cur_time + (polling_interval + 1),
476 + state_polling, client, 0, 0);
479 + ip -> linkstate = NOLINK;
480 + /*
481 + * Automatically go into the background after
482 + * some time. Do this only if there are no
483 + * media options available for a interface.
484 + */
485 + if (! ip -> havemedia && ! doinitcheck) {
486 + add_timeout (cur_time + (polling_interval * 2),
487 + state_background, client, 0, 0);
492 + /*
493 + * The last status of the interface tells us
494 + * the we previously had link.
495 + */
496 + if (ip -> linkstate == HAVELINK && doinitcheck) {
497 + if (result == NOLINK) {
498 + /*
499 + * We lost link on the interface, or it isn't
500 + * associated anymore.
501 + */
502 +#ifdef DEBUG
503 + printf ("%s: Lost Link on interface\n", ip -> name);
504 +#endif
505 + /*
506 + * After we lost link, cycle again through the
507 + * different media settings if available. Else
508 + * set NOLINK.
509 + */
510 + if (ip -> havemedia)
511 + ip -> forcediscover = 1;
512 + else
513 + ip -> linkstate = NOLINK;
515 + /*
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
519 + * are available.
520 + */
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. */
536 + doinitcheck = 1;
538 +#endif /* ifdef ENABLE_POLLING_MODE */