diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-03-23 23:44:29 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-03-23 23:44:29 +0000 |
commit | 787140df3992ccc3ebdc09f6d2dcb584f580f49f (patch) | |
tree | 666fdb071676c676f52bdc204f6df801b17e7196 /networking/udhcp/dhcpc.c | |
parent | e0fe93759339a9e043cd0489f5bfabd59b5fcb78 (diff) | |
download | busybox-w32-787140df3992ccc3ebdc09f6d2dcb584f580f49f.tar.gz busybox-w32-787140df3992ccc3ebdc09f6d2dcb584f580f49f.tar.bz2 busybox-w32-787140df3992ccc3ebdc09f6d2dcb584f580f49f.zip |
remove in place of external link
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 573 |
1 files changed, 0 insertions, 573 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c deleted file mode 100644 index fe2225a0c..000000000 --- a/networking/udhcp/dhcpc.c +++ /dev/null | |||
@@ -1,573 +0,0 @@ | |||
1 | /* dhcpc.c | ||
2 | * | ||
3 | * udhcp DHCP client | ||
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
6 | * | ||
7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
8 | */ | ||
9 | |||
10 | #include <sys/time.h> | ||
11 | #include <sys/file.h> | ||
12 | #include <unistd.h> | ||
13 | #include <getopt.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <sys/socket.h> | ||
16 | #include <netinet/in.h> | ||
17 | #include <arpa/inet.h> | ||
18 | #include <signal.h> | ||
19 | #include <time.h> | ||
20 | #include <string.h> | ||
21 | #include <sys/ioctl.h> | ||
22 | #include <net/if.h> | ||
23 | #include <errno.h> | ||
24 | |||
25 | #include "common.h" | ||
26 | #include "dhcpd.h" | ||
27 | #include "dhcpc.h" | ||
28 | #include "options.h" | ||
29 | #include "clientpacket.h" | ||
30 | #include "clientsocket.h" | ||
31 | #include "script.h" | ||
32 | #include "socket.h" | ||
33 | #include "signalpipe.h" | ||
34 | |||
35 | static int state; | ||
36 | static unsigned long requested_ip; /* = 0 */ | ||
37 | static unsigned long server_addr; | ||
38 | static unsigned long timeout; | ||
39 | static int packet_num; /* = 0 */ | ||
40 | static int fd = -1; | ||
41 | |||
42 | #define LISTEN_NONE 0 | ||
43 | #define LISTEN_KERNEL 1 | ||
44 | #define LISTEN_RAW 2 | ||
45 | static int listen_mode; | ||
46 | |||
47 | struct client_config_t client_config = { | ||
48 | /* Default options. */ | ||
49 | .abort_if_no_lease = 0, | ||
50 | .foreground = 0, | ||
51 | .quit_after_lease = 0, | ||
52 | .background_if_no_lease = 0, | ||
53 | .interface = "eth0", | ||
54 | .pidfile = NULL, | ||
55 | .script = DEFAULT_SCRIPT, | ||
56 | .clientid = NULL, | ||
57 | .vendorclass = NULL, | ||
58 | .hostname = NULL, | ||
59 | .fqdn = NULL, | ||
60 | .ifindex = 0, | ||
61 | .retries = 3, | ||
62 | .timeout = 3, | ||
63 | .arp = "\0\0\0\0\0\0", /* appease gcc-3.0 */ | ||
64 | }; | ||
65 | |||
66 | #ifndef IN_BUSYBOX | ||
67 | static void ATTRIBUTE_NORETURN show_usage(void) | ||
68 | { | ||
69 | printf( | ||
70 | "Usage: udhcpc [OPTIONS]\n\n" | ||
71 | " -c, --clientid=CLIENTID Set client identifier - type is first char\n" | ||
72 | " -C, --clientid-none Suppress default client identifier\n" | ||
73 | " -V, --vendorclass=CLASSID Set vendor class identifier\n" | ||
74 | " -H, --hostname=HOSTNAME Client hostname\n" | ||
75 | " -h Alias for -H\n" | ||
76 | " -F, --fqdn=FQDN Client fully qualified domain name\n" | ||
77 | " -f, --foreground Do not fork after getting lease\n" | ||
78 | " -b, --background Fork to background if lease cannot be\n" | ||
79 | " immediately negotiated.\n" | ||
80 | " -i, --interface=INTERFACE Interface to use (default: eth0)\n" | ||
81 | " -n, --now Exit with failure if lease cannot be\n" | ||
82 | " immediately negotiated.\n" | ||
83 | " -p, --pidfile=file Store process ID of daemon in file\n" | ||
84 | " -q, --quit Quit after obtaining lease\n" | ||
85 | " -r, --request=IP IP address to request (default: none)\n" | ||
86 | " -s, --script=file Run file at dhcp events (default:\n" | ||
87 | " " DEFAULT_SCRIPT ")\n" | ||
88 | " -T, --timeout=seconds Try to get the lease for the amount of\n" | ||
89 | " seconds (default: 3)\n" | ||
90 | " -v, --version Display version\n" | ||
91 | ); | ||
92 | exit(0); | ||
93 | } | ||
94 | #else | ||
95 | #define show_usage bb_show_usage | ||
96 | extern void show_usage(void) ATTRIBUTE_NORETURN; | ||
97 | #endif | ||
98 | |||
99 | |||
100 | /* just a little helper */ | ||
101 | static void change_mode(int new_mode) | ||
102 | { | ||
103 | DEBUG(LOG_INFO, "entering %s listen mode", | ||
104 | new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); | ||
105 | if (fd >= 0) close(fd); | ||
106 | fd = -1; | ||
107 | listen_mode = new_mode; | ||
108 | } | ||
109 | |||
110 | |||
111 | /* perform a renew */ | ||
112 | static void perform_renew(void) | ||
113 | { | ||
114 | LOG(LOG_INFO, "Performing a DHCP renew"); | ||
115 | switch (state) { | ||
116 | case BOUND: | ||
117 | change_mode(LISTEN_KERNEL); | ||
118 | case RENEWING: | ||
119 | case REBINDING: | ||
120 | state = RENEW_REQUESTED; | ||
121 | break; | ||
122 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ | ||
123 | run_script(NULL, "deconfig"); | ||
124 | case REQUESTING: | ||
125 | case RELEASED: | ||
126 | change_mode(LISTEN_RAW); | ||
127 | state = INIT_SELECTING; | ||
128 | break; | ||
129 | case INIT_SELECTING: | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | /* start things over */ | ||
134 | packet_num = 0; | ||
135 | |||
136 | /* Kill any timeouts because the user wants this to hurry along */ | ||
137 | timeout = 0; | ||
138 | } | ||
139 | |||
140 | |||
141 | /* perform a release */ | ||
142 | static void perform_release(void) | ||
143 | { | ||
144 | char buffer[16]; | ||
145 | struct in_addr temp_addr; | ||
146 | |||
147 | /* send release packet */ | ||
148 | if (state == BOUND || state == RENEWING || state == REBINDING) { | ||
149 | temp_addr.s_addr = server_addr; | ||
150 | sprintf(buffer, "%s", inet_ntoa(temp_addr)); | ||
151 | temp_addr.s_addr = requested_ip; | ||
152 | LOG(LOG_INFO, "Unicasting a release of %s to %s", | ||
153 | inet_ntoa(temp_addr), buffer); | ||
154 | send_release(server_addr, requested_ip); /* unicast */ | ||
155 | run_script(NULL, "deconfig"); | ||
156 | } | ||
157 | LOG(LOG_INFO, "Entering released state"); | ||
158 | |||
159 | change_mode(LISTEN_NONE); | ||
160 | state = RELEASED; | ||
161 | timeout = 0x7fffffff; | ||
162 | } | ||
163 | |||
164 | |||
165 | static void client_background(void) | ||
166 | { | ||
167 | background(client_config.pidfile); | ||
168 | client_config.foreground = 1; /* Do not fork again. */ | ||
169 | client_config.background_if_no_lease = 0; | ||
170 | } | ||
171 | |||
172 | |||
173 | #ifdef COMBINED_BINARY | ||
174 | int udhcpc_main(int argc, char *argv[]) | ||
175 | #else | ||
176 | int main(int argc, char *argv[]) | ||
177 | #endif | ||
178 | { | ||
179 | uint8_t *temp, *message; | ||
180 | unsigned long t1 = 0, t2 = 0, xid = 0; | ||
181 | unsigned long start = 0, lease; | ||
182 | fd_set rfds; | ||
183 | int retval; | ||
184 | struct timeval tv; | ||
185 | int c, len; | ||
186 | struct dhcpMessage packet; | ||
187 | struct in_addr temp_addr; | ||
188 | long now; | ||
189 | int max_fd; | ||
190 | int sig; | ||
191 | int no_clientid = 0; | ||
192 | |||
193 | static const struct option arg_options[] = { | ||
194 | {"clientid", required_argument, 0, 'c'}, | ||
195 | {"clientid-none", no_argument, 0, 'C'}, | ||
196 | {"vendorclass", required_argument, 0, 'V'}, | ||
197 | {"foreground", no_argument, 0, 'f'}, | ||
198 | {"background", no_argument, 0, 'b'}, | ||
199 | {"hostname", required_argument, 0, 'H'}, | ||
200 | {"hostname", required_argument, 0, 'h'}, | ||
201 | {"fqdn", required_argument, 0, 'F'}, | ||
202 | {"interface", required_argument, 0, 'i'}, | ||
203 | {"now", no_argument, 0, 'n'}, | ||
204 | {"pidfile", required_argument, 0, 'p'}, | ||
205 | {"quit", no_argument, 0, 'q'}, | ||
206 | {"request", required_argument, 0, 'r'}, | ||
207 | {"script", required_argument, 0, 's'}, | ||
208 | {"timeout", required_argument, 0, 'T'}, | ||
209 | {"version", no_argument, 0, 'v'}, | ||
210 | {"retries", required_argument, 0, 't'}, | ||
211 | {0, 0, 0, 0} | ||
212 | }; | ||
213 | |||
214 | /* get options */ | ||
215 | while (1) { | ||
216 | int option_index = 0; | ||
217 | c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qr:s:T:t:v", arg_options, &option_index); | ||
218 | if (c == -1) break; | ||
219 | |||
220 | switch (c) { | ||
221 | case 'c': | ||
222 | if (no_clientid) show_usage(); | ||
223 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
224 | free(client_config.clientid); | ||
225 | client_config.clientid = xmalloc(len + 2); | ||
226 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; | ||
227 | client_config.clientid[OPT_LEN] = len; | ||
228 | client_config.clientid[OPT_DATA] = '\0'; | ||
229 | strncpy((char*)client_config.clientid + OPT_DATA, optarg, len); | ||
230 | break; | ||
231 | case 'C': | ||
232 | if (client_config.clientid) show_usage(); | ||
233 | no_clientid = 1; | ||
234 | break; | ||
235 | case 'V': | ||
236 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
237 | free(client_config.vendorclass); | ||
238 | client_config.vendorclass = xmalloc(len + 2); | ||
239 | client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; | ||
240 | client_config.vendorclass[OPT_LEN] = len; | ||
241 | strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len); | ||
242 | break; | ||
243 | case 'f': | ||
244 | client_config.foreground = 1; | ||
245 | break; | ||
246 | case 'b': | ||
247 | client_config.background_if_no_lease = 1; | ||
248 | break; | ||
249 | case 'h': | ||
250 | case 'H': | ||
251 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
252 | free(client_config.hostname); | ||
253 | client_config.hostname = xmalloc(len + 2); | ||
254 | client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; | ||
255 | client_config.hostname[OPT_LEN] = len; | ||
256 | strncpy((char*)client_config.hostname + 2, optarg, len); | ||
257 | break; | ||
258 | case 'F': | ||
259 | len = strlen(optarg) > 255 ? 255 : strlen(optarg); | ||
260 | free(client_config.fqdn); | ||
261 | client_config.fqdn = xmalloc(len + 5); | ||
262 | client_config.fqdn[OPT_CODE] = DHCP_FQDN; | ||
263 | client_config.fqdn[OPT_LEN] = len + 3; | ||
264 | /* Flags: 0000NEOS | ||
265 | S: 1 => Client requests Server to update A RR in DNS as well as PTR | ||
266 | O: 1 => Server indicates to client that DNS has been updated regardless | ||
267 | E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" | ||
268 | N: 1 => Client requests Server to not update DNS | ||
269 | */ | ||
270 | client_config.fqdn[OPT_LEN + 1] = 0x1; | ||
271 | client_config.fqdn[OPT_LEN + 2] = 0; | ||
272 | client_config.fqdn[OPT_LEN + 3] = 0; | ||
273 | strncpy((char*)client_config.fqdn + 5, optarg, len); | ||
274 | break; | ||
275 | case 'i': | ||
276 | client_config.interface = optarg; | ||
277 | break; | ||
278 | case 'n': | ||
279 | client_config.abort_if_no_lease = 1; | ||
280 | break; | ||
281 | case 'p': | ||
282 | client_config.pidfile = optarg; | ||
283 | break; | ||
284 | case 'q': | ||
285 | client_config.quit_after_lease = 1; | ||
286 | break; | ||
287 | case 'r': | ||
288 | requested_ip = inet_addr(optarg); | ||
289 | break; | ||
290 | case 's': | ||
291 | client_config.script = optarg; | ||
292 | break; | ||
293 | case 'T': | ||
294 | client_config.timeout = atoi(optarg); | ||
295 | break; | ||
296 | case 't': | ||
297 | client_config.retries = atoi(optarg); | ||
298 | break; | ||
299 | case 'v': | ||
300 | printf("udhcpcd, version %s\n\n", VERSION); | ||
301 | return 0; | ||
302 | break; | ||
303 | default: | ||
304 | show_usage(); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | /* Start the log, sanitize fd's, and write a pid file */ | ||
309 | start_log_and_pid("udhcpc", client_config.pidfile); | ||
310 | |||
311 | if (read_interface(client_config.interface, &client_config.ifindex, | ||
312 | NULL, client_config.arp) < 0) | ||
313 | return 1; | ||
314 | |||
315 | /* if not set, and not suppressed, setup the default client ID */ | ||
316 | if (!client_config.clientid && !no_clientid) { | ||
317 | client_config.clientid = xmalloc(6 + 3); | ||
318 | client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; | ||
319 | client_config.clientid[OPT_LEN] = 7; | ||
320 | client_config.clientid[OPT_DATA] = 1; | ||
321 | memcpy(client_config.clientid + 3, client_config.arp, 6); | ||
322 | } | ||
323 | |||
324 | if (!client_config.vendorclass) { | ||
325 | client_config.vendorclass = xmalloc(sizeof("udhcp "VERSION) + 2); | ||
326 | client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; | ||
327 | client_config.vendorclass[OPT_LEN] = sizeof("udhcp "VERSION) - 1; | ||
328 | client_config.vendorclass[OPT_DATA] = 1; | ||
329 | memcpy(&client_config.vendorclass[OPT_DATA], | ||
330 | "udhcp "VERSION, sizeof("udhcp "VERSION) - 1); | ||
331 | } | ||
332 | |||
333 | |||
334 | /* setup the signal pipe */ | ||
335 | udhcp_sp_setup(); | ||
336 | |||
337 | state = INIT_SELECTING; | ||
338 | run_script(NULL, "deconfig"); | ||
339 | change_mode(LISTEN_RAW); | ||
340 | |||
341 | for (;;) { | ||
342 | |||
343 | tv.tv_sec = timeout - uptime(); | ||
344 | tv.tv_usec = 0; | ||
345 | |||
346 | if (listen_mode != LISTEN_NONE && fd < 0) { | ||
347 | if (listen_mode == LISTEN_KERNEL) | ||
348 | fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); | ||
349 | else | ||
350 | fd = raw_socket(client_config.ifindex); | ||
351 | if (fd < 0) { | ||
352 | LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m"); | ||
353 | return 0; | ||
354 | } | ||
355 | } | ||
356 | max_fd = udhcp_sp_fd_set(&rfds, fd); | ||
357 | |||
358 | if (tv.tv_sec > 0) { | ||
359 | DEBUG(LOG_INFO, "Waiting on select..."); | ||
360 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); | ||
361 | } else retval = 0; /* If we already timed out, fall through */ | ||
362 | |||
363 | now = uptime(); | ||
364 | if (retval == 0) { | ||
365 | /* timeout dropped to zero */ | ||
366 | switch (state) { | ||
367 | case INIT_SELECTING: | ||
368 | if (packet_num < client_config.retries) { | ||
369 | if (packet_num == 0) | ||
370 | xid = random_xid(); | ||
371 | |||
372 | /* send discover packet */ | ||
373 | send_discover(xid, requested_ip); /* broadcast */ | ||
374 | |||
375 | timeout = now + client_config.timeout; | ||
376 | packet_num++; | ||
377 | } else { | ||
378 | run_script(NULL, "leasefail"); | ||
379 | if (client_config.background_if_no_lease) { | ||
380 | LOG(LOG_INFO, "No lease, forking to background."); | ||
381 | client_background(); | ||
382 | } else if (client_config.abort_if_no_lease) { | ||
383 | LOG(LOG_INFO, "No lease, failing."); | ||
384 | return 1; | ||
385 | } | ||
386 | /* wait to try again */ | ||
387 | packet_num = 0; | ||
388 | timeout = now + 60; | ||
389 | } | ||
390 | break; | ||
391 | case RENEW_REQUESTED: | ||
392 | case REQUESTING: | ||
393 | if (packet_num < client_config.retries) { | ||
394 | /* send request packet */ | ||
395 | if (state == RENEW_REQUESTED) | ||
396 | send_renew(xid, server_addr, requested_ip); /* unicast */ | ||
397 | else send_selecting(xid, server_addr, requested_ip); /* broadcast */ | ||
398 | |||
399 | timeout = now + ((packet_num == 2) ? 10 : 2); | ||
400 | packet_num++; | ||
401 | } else { | ||
402 | /* timed out, go back to init state */ | ||
403 | if (state == RENEW_REQUESTED) run_script(NULL, "deconfig"); | ||
404 | state = INIT_SELECTING; | ||
405 | timeout = now; | ||
406 | packet_num = 0; | ||
407 | change_mode(LISTEN_RAW); | ||
408 | } | ||
409 | break; | ||
410 | case BOUND: | ||
411 | /* Lease is starting to run out, time to enter renewing state */ | ||
412 | state = RENEWING; | ||
413 | change_mode(LISTEN_KERNEL); | ||
414 | DEBUG(LOG_INFO, "Entering renew state"); | ||
415 | /* fall right through */ | ||
416 | case RENEWING: | ||
417 | /* Either set a new T1, or enter REBINDING state */ | ||
418 | if ((t2 - t1) <= (lease / 14400 + 1)) { | ||
419 | /* timed out, enter rebinding state */ | ||
420 | state = REBINDING; | ||
421 | timeout = now + (t2 - t1); | ||
422 | DEBUG(LOG_INFO, "Entering rebinding state"); | ||
423 | } else { | ||
424 | /* send a request packet */ | ||
425 | send_renew(xid, server_addr, requested_ip); /* unicast */ | ||
426 | |||
427 | t1 = (t2 - t1) / 2 + t1; | ||
428 | timeout = t1 + start; | ||
429 | } | ||
430 | break; | ||
431 | case REBINDING: | ||
432 | /* Either set a new T2, or enter INIT state */ | ||
433 | if ((lease - t2) <= (lease / 14400 + 1)) { | ||
434 | /* timed out, enter init state */ | ||
435 | state = INIT_SELECTING; | ||
436 | LOG(LOG_INFO, "Lease lost, entering init state"); | ||
437 | run_script(NULL, "deconfig"); | ||
438 | timeout = now; | ||
439 | packet_num = 0; | ||
440 | change_mode(LISTEN_RAW); | ||
441 | } else { | ||
442 | /* send a request packet */ | ||
443 | send_renew(xid, 0, requested_ip); /* broadcast */ | ||
444 | |||
445 | t2 = (lease - t2) / 2 + t2; | ||
446 | timeout = t2 + start; | ||
447 | } | ||
448 | break; | ||
449 | case RELEASED: | ||
450 | /* yah, I know, *you* say it would never happen */ | ||
451 | timeout = 0x7fffffff; | ||
452 | break; | ||
453 | } | ||
454 | } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) { | ||
455 | /* a packet is ready, read it */ | ||
456 | |||
457 | if (listen_mode == LISTEN_KERNEL) | ||
458 | len = get_packet(&packet, fd); | ||
459 | else len = get_raw_packet(&packet, fd); | ||
460 | |||
461 | if (len == -1 && errno != EINTR) { | ||
462 | DEBUG(LOG_INFO, "error on read, %m, reopening socket"); | ||
463 | change_mode(listen_mode); /* just close and reopen */ | ||
464 | } | ||
465 | if (len < 0) continue; | ||
466 | |||
467 | if (packet.xid != xid) { | ||
468 | DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)", | ||
469 | (unsigned long) packet.xid, xid); | ||
470 | continue; | ||
471 | } | ||
472 | |||
473 | /* Ignore packets that aren't for us */ | ||
474 | if (memcmp(packet.chaddr, client_config.arp, 6)) { | ||
475 | DEBUG(LOG_INFO, "packet does not have our chaddr -- ignoring"); | ||
476 | continue; | ||
477 | } | ||
478 | |||
479 | if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { | ||
480 | DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring"); | ||
481 | continue; | ||
482 | } | ||
483 | |||
484 | switch (state) { | ||
485 | case INIT_SELECTING: | ||
486 | /* Must be a DHCPOFFER to one of our xid's */ | ||
487 | if (*message == DHCPOFFER) { | ||
488 | if ((temp = get_option(&packet, DHCP_SERVER_ID))) { | ||
489 | memcpy(&server_addr, temp, 4); | ||
490 | xid = packet.xid; | ||
491 | requested_ip = packet.yiaddr; | ||
492 | |||
493 | /* enter requesting state */ | ||
494 | state = REQUESTING; | ||
495 | timeout = now; | ||
496 | packet_num = 0; | ||
497 | } else { | ||
498 | DEBUG(LOG_ERR, "No server ID in message"); | ||
499 | } | ||
500 | } | ||
501 | break; | ||
502 | case RENEW_REQUESTED: | ||
503 | case REQUESTING: | ||
504 | case RENEWING: | ||
505 | case REBINDING: | ||
506 | if (*message == DHCPACK) { | ||
507 | if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) { | ||
508 | LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease"); | ||
509 | lease = 60 * 60; | ||
510 | } else { | ||
511 | memcpy(&lease, temp, 4); | ||
512 | lease = ntohl(lease); | ||
513 | } | ||
514 | |||
515 | /* enter bound state */ | ||
516 | t1 = lease / 2; | ||
517 | |||
518 | /* little fixed point for n * .875 */ | ||
519 | t2 = (lease * 0x7) >> 3; | ||
520 | temp_addr.s_addr = packet.yiaddr; | ||
521 | LOG(LOG_INFO, "Lease of %s obtained, lease time %ld", | ||
522 | inet_ntoa(temp_addr), lease); | ||
523 | start = now; | ||
524 | timeout = t1 + start; | ||
525 | requested_ip = packet.yiaddr; | ||
526 | run_script(&packet, | ||
527 | ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); | ||
528 | |||
529 | state = BOUND; | ||
530 | change_mode(LISTEN_NONE); | ||
531 | if (client_config.quit_after_lease) | ||
532 | return 0; | ||
533 | if (!client_config.foreground) | ||
534 | client_background(); | ||
535 | |||
536 | } else if (*message == DHCPNAK) { | ||
537 | /* return to init state */ | ||
538 | LOG(LOG_INFO, "Received DHCP NAK"); | ||
539 | run_script(&packet, "nak"); | ||
540 | if (state != REQUESTING) | ||
541 | run_script(NULL, "deconfig"); | ||
542 | state = INIT_SELECTING; | ||
543 | timeout = now; | ||
544 | requested_ip = 0; | ||
545 | packet_num = 0; | ||
546 | change_mode(LISTEN_RAW); | ||
547 | sleep(3); /* avoid excessive network traffic */ | ||
548 | } | ||
549 | break; | ||
550 | /* case BOUND, RELEASED: - ignore all packets */ | ||
551 | } | ||
552 | } else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) { | ||
553 | switch (sig) { | ||
554 | case SIGUSR1: | ||
555 | perform_renew(); | ||
556 | break; | ||
557 | case SIGUSR2: | ||
558 | perform_release(); | ||
559 | break; | ||
560 | case SIGTERM: | ||
561 | LOG(LOG_INFO, "Received SIGTERM"); | ||
562 | return 0; | ||
563 | } | ||
564 | } else if (retval == -1 && errno == EINTR) { | ||
565 | /* a signal was caught */ | ||
566 | } else { | ||
567 | /* An error occured */ | ||
568 | DEBUG(LOG_ERR, "Error on select"); | ||
569 | } | ||
570 | |||
571 | } | ||
572 | return 0; | ||
573 | } | ||