1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <syslog.h>
22
23#define WANT_PIDFILE 1
24#include "common.h"
25#include "dhcpd.h"
26#include "dhcpc.h"
27
28#include <asm/types.h>
29#if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION)
30# include <netpacket/packet.h>
31# include <net/ethernet.h>
32#else
33# include <linux/if_packet.h>
34# include <linux/if_ether.h>
35#endif
36#include <linux/filter.h>
37
38
39
40
41
42
43
44static const uint8_t len_of_option_as_string[] = {
45 [OPTION_IP ] = sizeof("255.255.255.255 "),
46 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
47 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
48 [OPTION_STRING ] = 1,
49#if ENABLE_FEATURE_UDHCP_RFC3397
50 [OPTION_DNS_STRING ] = 1,
51
52
53
54
55 [OPTION_SIP_SERVERS ] = sizeof("255.255.255.255 "),
56#endif
57
58 [OPTION_U8 ] = sizeof("255 "),
59 [OPTION_U16 ] = sizeof("65535 "),
60
61 [OPTION_U32 ] = sizeof("4294967295 "),
62 [OPTION_S32 ] = sizeof("-2147483684 "),
63};
64
65
66static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
67{
68 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
69}
70
71
72static int mton(uint32_t mask)
73{
74 int i = 0;
75 mask = ntohl(mask);
76 while (mask) {
77 i++;
78 mask <<= 1;
79 }
80 return i;
81}
82
83
84static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name)
85{
86 unsigned upper_length;
87 int len, type, optlen;
88 char *dest, *ret;
89
90
91 len = option[OPT_LEN - OPT_DATA];
92 type = optflag->flags & OPTION_TYPE_MASK;
93 optlen = dhcp_option_lengths[type];
94 upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen);
95
96 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
97 dest += sprintf(ret, "%s=", opt_name);
98
99 while (len >= optlen) {
100 switch (type) {
101 case OPTION_IP_PAIR:
102 dest += sprint_nip(dest, "", option);
103 *dest++ = '/';
104 option += 4;
105 optlen = 4;
106 case OPTION_IP:
107 dest += sprint_nip(dest, "", option);
108
109
110
111 break;
112
113
114
115 case OPTION_U8:
116 dest += sprintf(dest, "%u", *option);
117 break;
118
119 case OPTION_U16: {
120 uint16_t val_u16;
121 move_from_unaligned16(val_u16, option);
122 dest += sprintf(dest, "%u", ntohs(val_u16));
123 break;
124 }
125 case OPTION_S32:
126 case OPTION_U32: {
127 uint32_t val_u32;
128 move_from_unaligned32(val_u32, option);
129 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32));
130 break;
131 }
132 case OPTION_STRING:
133 memcpy(dest, option, len);
134 dest[len] = '\0';
135 return ret;
136 case OPTION_STATIC_ROUTES: {
137
138
139
140
141
142
143
144
145 const char *pfx = "";
146
147 while (len >= 1 + 4) {
148 uint32_t nip;
149 uint8_t *p;
150 unsigned mask;
151 int bytes;
152
153 mask = *option++;
154 if (mask > 32)
155 break;
156 len--;
157
158 nip = 0;
159 p = (void*) &nip;
160 bytes = (mask + 7) / 8;
161 while (--bytes >= 0) {
162 *p++ = *option++;
163 len--;
164 }
165 if (len < 4)
166 break;
167
168
169 dest += sprint_nip(dest, pfx, (void*) &nip);
170 pfx = " ";
171 dest += sprintf(dest, "/%u ", mask);
172
173 dest += sprint_nip(dest, "", option);
174 option += 4;
175 len -= 4;
176 }
177
178 return ret;
179 }
180#if ENABLE_FEATURE_UDHCP_RFC3397
181 case OPTION_DNS_STRING:
182
183 dest = dname_dec(option, len, ret);
184 if (dest) {
185 free(ret);
186 return dest;
187 }
188
189 return ret;
190 case OPTION_SIP_SERVERS:
191
192
193
194
195
196 option++;
197 len--;
198 if (option[-1] == 0) {
199 dest = dname_dec(option, len, ret);
200 if (dest) {
201 free(ret);
202 return dest;
203 }
204 } else
205 if (option[-1] == 1) {
206 const char *pfx = "";
207 while (1) {
208 len -= 4;
209 if (len < 0)
210 break;
211 dest += sprint_nip(dest, pfx, option);
212 pfx = " ";
213 option += 4;
214 }
215 }
216 return ret;
217#endif
218 }
219 option += optlen;
220 len -= optlen;
221 if (len <= 0)
222 break;
223 *dest++ = ' ';
224 *dest = '\0';
225 }
226 return ret;
227}
228
229
230static char **fill_envp(struct dhcp_packet *packet)
231{
232 int envc;
233 int i;
234 char **envp, **curr;
235 const char *opt_name;
236 uint8_t *temp;
237 uint8_t overload = 0;
238
239
240
241
242
243
244
245
246
247 envc = 6;
248
249 if (packet) {
250 for (i = 0; dhcp_optflags[i].code; i++) {
251 if (udhcp_get_option(packet, dhcp_optflags[i].code)) {
252 if (dhcp_optflags[i].code == DHCP_SUBNET)
253 envc++;
254 envc++;
255 }
256 }
257 temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD);
258 if (temp)
259 overload = *temp;
260 }
261 curr = envp = xzalloc(sizeof(char *) * envc);
262
263 *curr = xasprintf("interface=%s", client_config.interface);
264 putenv(*curr++);
265
266 if (!packet)
267 return envp;
268
269 *curr = xmalloc(sizeof("ip=255.255.255.255"));
270 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr);
271 putenv(*curr++);
272
273 opt_name = dhcp_option_strings;
274 i = 0;
275 while (*opt_name) {
276 temp = udhcp_get_option(packet, dhcp_optflags[i].code);
277 if (!temp)
278 goto next;
279 *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);
280 putenv(*curr++);
281 if (dhcp_optflags[i].code == DHCP_SUBNET) {
282
283 uint32_t subnet;
284 move_from_unaligned32(subnet, temp);
285 *curr = xasprintf("mask=%d", mton(subnet));
286 putenv(*curr++);
287 }
288 next:
289 opt_name += strlen(opt_name) + 1;
290 i++;
291 }
292 if (packet->siaddr_nip) {
293 *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
294 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
295 putenv(*curr++);
296 }
297 if (!(overload & FILE_FIELD) && packet->file[0]) {
298
299 *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
300 putenv(*curr++);
301 }
302 if (!(overload & SNAME_FIELD) && packet->sname[0]) {
303
304 *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
305 putenv(*curr++);
306 }
307 return envp;
308}
309
310
311static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
312{
313 char **envp, **curr;
314 char *argv[3];
315
316 if (client_config.script == NULL)
317 return;
318
319 envp = fill_envp(packet);
320
321
322 log1("Executing %s %s", client_config.script, name);
323 argv[0] = (char*) client_config.script;
324 argv[1] = (char*) name;
325 argv[2] = NULL;
326 spawn_and_wait(argv);
327
328 for (curr = envp; *curr; curr++) {
329 log2(" %s", *curr);
330 bb_unsetenv_and_free(*curr);
331 }
332 free(envp);
333}
334
335
336
337
338static ALWAYS_INLINE uint32_t random_xid(void)
339{
340 return rand();
341}
342
343
344static void init_packet(struct dhcp_packet *packet, char type)
345{
346 udhcp_init_header(packet, type);
347 memcpy(packet->chaddr, client_config.client_mac, 6);
348 if (client_config.clientid)
349 udhcp_add_binary_option(packet, client_config.clientid);
350 if (client_config.hostname)
351 udhcp_add_binary_option(packet, client_config.hostname);
352 if (client_config.fqdn)
353 udhcp_add_binary_option(packet, client_config.fqdn);
354 if (type != DHCPDECLINE
355 && type != DHCPRELEASE
356 && client_config.vendorclass
357 ) {
358 udhcp_add_binary_option(packet, client_config.vendorclass);
359 }
360}
361
362static void add_client_options(struct dhcp_packet *packet)
363{
364
365
366
367 uint8_t c;
368 int end = udhcp_end_option(packet->options);
369 int i, len = 0;
370
371 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) {
372 if (( (dhcp_optflags[i].flags & OPTION_REQ)
373 && !client_config.no_default_options
374 )
375 || (client_config.opt_mask[c >> 3] & (1 << (c & 7)))
376 ) {
377 packet->options[end + OPT_DATA + len] = c;
378 len++;
379 }
380 }
381 if (len) {
382 packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
383 packet->options[end + OPT_LEN] = len;
384 packet->options[end + OPT_DATA + len] = DHCP_END;
385 }
386
387
388 {
389 struct option_set *curr = client_config.options;
390 while (curr) {
391 udhcp_add_binary_option(packet, curr->data);
392 curr = curr->next;
393 }
394
395
396
397
398 }
399}
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet)
420{
421 return udhcp_send_raw_packet(packet,
422 INADDR_ANY, CLIENT_PORT,
423 INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
424 client_config.ifindex);
425}
426
427
428static int send_discover(uint32_t xid, uint32_t requested)
429{
430 struct dhcp_packet packet;
431
432 init_packet(&packet, DHCPDISCOVER);
433 packet.xid = xid;
434 if (requested)
435 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
436
437
438 udhcp_add_simple_option(&packet, DHCP_MAX_SIZE, htons(576));
439 add_client_options(&packet);
440
441 bb_info_msg("Sending discover...");
442 return raw_bcast_from_client_config_ifindex(&packet);
443}
444
445
446
447
448
449static int send_select(uint32_t xid, uint32_t server, uint32_t requested)
450{
451 struct dhcp_packet packet;
452 struct in_addr addr;
453
454 init_packet(&packet, DHCPREQUEST);
455 packet.xid = xid;
456 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
457 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
458 add_client_options(&packet);
459
460 addr.s_addr = requested;
461 bb_info_msg("Sending select for %s...", inet_ntoa(addr));
462 return raw_bcast_from_client_config_ifindex(&packet);
463}
464
465
466static int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
467{
468 struct dhcp_packet packet;
469
470 init_packet(&packet, DHCPREQUEST);
471 packet.xid = xid;
472 packet.ciaddr = ciaddr;
473 add_client_options(&packet);
474
475 bb_info_msg("Sending renew...");
476 if (server)
477 return udhcp_send_kernel_packet(&packet,
478 ciaddr, CLIENT_PORT,
479 server, SERVER_PORT);
480 return raw_bcast_from_client_config_ifindex(&packet);
481}
482
483#if ENABLE_FEATURE_UDHCPC_ARPING
484
485static int send_decline(uint32_t xid, uint32_t server, uint32_t requested)
486{
487 struct dhcp_packet packet;
488
489 init_packet(&packet, DHCPDECLINE);
490 packet.xid = xid;
491 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
492 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
493
494 bb_info_msg("Sending decline...");
495 return raw_bcast_from_client_config_ifindex(&packet);
496}
497#endif
498
499
500static int send_release(uint32_t server, uint32_t ciaddr)
501{
502 struct dhcp_packet packet;
503
504 init_packet(&packet, DHCPRELEASE);
505 packet.xid = random_xid();
506 packet.ciaddr = ciaddr;
507
508 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
509
510 bb_info_msg("Sending release...");
511 return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
512}
513
514
515static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
516{
517 int bytes;
518 struct ip_udp_dhcp_packet packet;
519 uint16_t check;
520
521 memset(&packet, 0, sizeof(packet));
522 bytes = safe_read(fd, &packet, sizeof(packet));
523 if (bytes < 0) {
524 log1("Packet read error, ignoring");
525
526 return bytes;
527 }
528
529 if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
530 log1("Packet is too short, ignoring");
531 return -2;
532 }
533
534 if (bytes < ntohs(packet.ip.tot_len)) {
535
536 log1("Oversized packet, ignoring");
537 return -2;
538 }
539
540
541 bytes = ntohs(packet.ip.tot_len);
542
543
544 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION
545 || packet.ip.ihl != (sizeof(packet.ip) >> 2)
546 || packet.udp.dest != htons(CLIENT_PORT)
547
548 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip))
549 ) {
550 log1("Unrelated/bogus packet, ignoring");
551 return -2;
552 }
553
554
555 check = packet.ip.check;
556 packet.ip.check = 0;
557 if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) {
558 log1("Bad IP header checksum, ignoring");
559 return -2;
560 }
561
562
563 memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
564
565 packet.ip.tot_len = packet.udp.len;
566 check = packet.udp.check;
567 packet.udp.check = 0;
568 if (check && check != udhcp_checksum(&packet, bytes)) {
569 log1("Packet with bad UDP checksum received, ignoring");
570 return -2;
571 }
572
573 memcpy(dhcp_pkt, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp)));
574
575 if (dhcp_pkt->cookie != htonl(DHCP_MAGIC)) {
576 bb_info_msg("Packet with bad magic, ignoring");
577 return -2;
578 }
579 log1("Got valid DHCP packet");
580 udhcp_dump_packet(dhcp_pkt);
581 return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
582}
583
584
585
586
587static int sockfd = -1;
588
589#define LISTEN_NONE 0
590#define LISTEN_KERNEL 1
591#define LISTEN_RAW 2
592static smallint listen_mode;
593
594
595#define INIT_SELECTING 0
596
597#define REQUESTING 1
598
599#define BOUND 2
600
601#define RENEWING 3
602
603#define REBINDING 4
604
605#define RENEW_REQUESTED 5
606
607#define RELEASED 6
608static smallint state;
609
610static int udhcp_raw_socket(int ifindex)
611{
612 int fd;
613 struct sockaddr_ll sock;
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636#define SERVER_AND_CLIENT_PORTS ((67 << 16) + 68)
637 static const struct sock_filter filter_instr[] = {
638
639 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
640 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 2, 0),
641
642 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),
643 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x08000604, 3, 4),
644
645 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
646
647 BPF_STMT(BPF_LD|BPF_W|BPF_IND, 0),
648 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SERVER_AND_CLIENT_PORTS, 0, 1),
649
650 BPF_STMT(BPF_RET|BPF_K, 0x0fffffff ),
651 BPF_STMT(BPF_RET|BPF_K, 0),
652 };
653 static const struct sock_fprog filter_prog = {
654 .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
655
656 .filter = (struct sock_filter *) filter_instr,
657 };
658
659 log1("Opening raw socket on ifindex %d", ifindex);
660
661 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
662 log1("Got raw socket fd %d", fd);
663
664 if (SERVER_PORT == 67 && CLIENT_PORT == 68) {
665
666
667 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
668 sizeof(filter_prog)) >= 0)
669 log1("Attached filter to raw socket fd %d", fd);
670 }
671
672 sock.sll_family = AF_PACKET;
673 sock.sll_protocol = htons(ETH_P_IP);
674 sock.sll_ifindex = ifindex;
675 xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
676 log1("Created raw socket");
677
678 return fd;
679}
680
681static void change_listen_mode(int new_mode)
682{
683 log1("Entering listen mode: %s",
684 new_mode != LISTEN_NONE
685 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
686 : "none"
687 );
688
689 listen_mode = new_mode;
690 if (sockfd >= 0) {
691 close(sockfd);
692 sockfd = -1;
693 }
694 if (new_mode == LISTEN_KERNEL)
695 sockfd = udhcp_listen_socket( CLIENT_PORT, client_config.interface);
696 else if (new_mode != LISTEN_NONE)
697 sockfd = udhcp_raw_socket(client_config.ifindex);
698
699}
700
701static void perform_renew(void)
702{
703 bb_info_msg("Performing a DHCP renew");
704 switch (state) {
705 case BOUND:
706 change_listen_mode(LISTEN_KERNEL);
707 case RENEWING:
708 case REBINDING:
709 state = RENEW_REQUESTED;
710 break;
711 case RENEW_REQUESTED:
712 udhcp_run_script(NULL, "deconfig");
713 case REQUESTING:
714 case RELEASED:
715 change_listen_mode(LISTEN_RAW);
716 state = INIT_SELECTING;
717 break;
718 case INIT_SELECTING:
719 break;
720 }
721}
722
723static void perform_release(uint32_t requested_ip, uint32_t server_addr)
724{
725 char buffer[sizeof("255.255.255.255")];
726 struct in_addr temp_addr;
727
728
729 if (state == BOUND || state == RENEWING || state == REBINDING) {
730 temp_addr.s_addr = server_addr;
731 strcpy(buffer, inet_ntoa(temp_addr));
732 temp_addr.s_addr = requested_ip;
733 bb_info_msg("Unicasting a release of %s to %s",
734 inet_ntoa(temp_addr), buffer);
735 send_release(server_addr, requested_ip);
736 udhcp_run_script(NULL, "deconfig");
737 }
738 bb_info_msg("Entering released state");
739
740 change_listen_mode(LISTEN_NONE);
741 state = RELEASED;
742}
743
744static uint8_t* alloc_dhcp_option(int code, const char *str, int extra)
745{
746 uint8_t *storage;
747 int len = strnlen(str, 255);
748 storage = xzalloc(len + extra + OPT_DATA);
749 storage[OPT_CODE] = code;
750 storage[OPT_LEN] = len + extra;
751 memcpy(storage + extra + OPT_DATA, str, len);
752 return storage;
753}
754
755#if BB_MMU
756static void client_background(void)
757{
758 bb_daemonize(0);
759 logmode &= ~LOGMODE_STDIO;
760
761 write_pidfile(client_config.pidfile);
762}
763#endif
764
765int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
766int udhcpc_main(int argc UNUSED_PARAM, char **argv)
767{
768 uint8_t *temp, *message;
769 const char *str_c, *str_V, *str_h, *str_F, *str_r;
770 IF_FEATURE_UDHCP_PORT(char *str_P;)
771 llist_t *list_O = NULL;
772 llist_t *list_x = NULL;
773 int tryagain_timeout = 20;
774 int discover_timeout = 3;
775 int discover_retries = 3;
776 uint32_t server_addr = server_addr;
777 uint32_t requested_ip = 0;
778 uint32_t xid = 0;
779 uint32_t lease_seconds = 0;
780 int packet_num;
781 int timeout;
782 unsigned already_waited_sec;
783 unsigned opt;
784 int max_fd;
785 int retval;
786 struct timeval tv;
787 struct dhcp_packet packet;
788 fd_set rfds;
789
790#if ENABLE_LONG_OPTS
791 static const char udhcpc_longopts[] ALIGN1 =
792 "clientid\0" Required_argument "c"
793 "clientid-none\0" No_argument "C"
794 "vendorclass\0" Required_argument "V"
795 "hostname\0" Required_argument "H"
796 "fqdn\0" Required_argument "F"
797 "interface\0" Required_argument "i"
798 "now\0" No_argument "n"
799 "pidfile\0" Required_argument "p"
800 "quit\0" No_argument "q"
801 "release\0" No_argument "R"
802 "request\0" Required_argument "r"
803 "script\0" Required_argument "s"
804 "timeout\0" Required_argument "T"
805 "version\0" No_argument "v"
806 "retries\0" Required_argument "t"
807 "tryagain\0" Required_argument "A"
808 "syslog\0" No_argument "S"
809 "request-option\0" Required_argument "O"
810 "no-default-options\0" No_argument "o"
811 "foreground\0" No_argument "f"
812 "background\0" No_argument "b"
813 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")
814 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
815 ;
816#endif
817 enum {
818 OPT_c = 1 << 0,
819 OPT_C = 1 << 1,
820 OPT_V = 1 << 2,
821 OPT_H = 1 << 3,
822 OPT_h = 1 << 4,
823 OPT_F = 1 << 5,
824 OPT_i = 1 << 6,
825 OPT_n = 1 << 7,
826 OPT_p = 1 << 8,
827 OPT_q = 1 << 9,
828 OPT_R = 1 << 10,
829 OPT_r = 1 << 11,
830 OPT_s = 1 << 12,
831 OPT_T = 1 << 13,
832 OPT_t = 1 << 14,
833 OPT_S = 1 << 15,
834 OPT_A = 1 << 16,
835 OPT_O = 1 << 17,
836 OPT_o = 1 << 18,
837 OPT_x = 1 << 19,
838 OPT_f = 1 << 20,
839
840 OPTBIT_f = 20,
841 USE_FOR_MMU( OPTBIT_b,)
842 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
843 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
844 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,)
845 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
846 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
847 };
848
849
850 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
851 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
852 client_config.interface = "eth0";
853 client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT;
854 str_V = "udhcp "BB_VER;
855
856
857
858 opt_complementary = "c--C:C--c:O::x::T+:t+:A+"
859#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
860 ":vv"
861#endif
862 ;
863 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
864 opt = getopt32(argv, "c:CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f"
865 USE_FOR_MMU("b")
866 IF_FEATURE_UDHCPC_ARPING("a")
867 IF_FEATURE_UDHCP_PORT("P:")
868 "v"
869 , &str_c, &str_V, &str_h, &str_h, &str_F
870 , &client_config.interface, &client_config.pidfile, &str_r
871 , &client_config.script
872 , &discover_timeout, &discover_retries, &tryagain_timeout
873 , &list_O
874 , &list_x
875 IF_FEATURE_UDHCP_PORT(, &str_P)
876#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
877 , &dhcp_verbose
878#endif
879 );
880 if (opt & (OPT_h|OPT_H))
881 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
882 if (opt & OPT_F) {
883
884 client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
885
886
887
888
889
890
891
892
893 client_config.fqdn[OPT_DATA + 0] = 0x1;
894
895
896 }
897 if (opt & OPT_r)
898 requested_ip = inet_addr(str_r);
899#if ENABLE_FEATURE_UDHCP_PORT
900 if (opt & OPT_P) {
901 CLIENT_PORT = xatou16(str_P);
902 SERVER_PORT = CLIENT_PORT - 1;
903 }
904#endif
905 if (opt & OPT_o)
906 client_config.no_default_options = 1;
907 while (list_O) {
908 char *optstr = llist_pop(&list_O);
909 unsigned n = udhcp_option_idx(optstr);
910 n = dhcp_optflags[n].code;
911 client_config.opt_mask[n >> 3] |= 1 << (n & 7);
912 }
913 while (list_x) {
914 char *optstr = llist_pop(&list_x);
915 char *colon = strchr(optstr, ':');
916 if (colon)
917 *colon = ' ';
918
919
920 udhcp_str2optset(optstr, &client_config.options);
921 }
922
923 if (udhcp_read_interface(client_config.interface,
924 &client_config.ifindex,
925 NULL,
926 client_config.client_mac)
927 ) {
928 return 1;
929 }
930
931 if (opt & OPT_c) {
932 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
933 } else if (!(opt & OPT_C)) {
934
935 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
936 client_config.clientid[OPT_DATA] = 1;
937 memcpy(client_config.clientid + OPT_DATA+1, client_config.client_mac, 6);
938 }
939 if (str_V[0] != '\0')
940 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
941#if !BB_MMU
942
943 if (!(opt & OPT_f)) {
944 bb_daemonize_or_rexec(0 , argv);
945 logmode = LOGMODE_NONE;
946 }
947#endif
948 if (opt & OPT_S) {
949 openlog(applet_name, LOG_PID, LOG_DAEMON);
950 logmode |= LOGMODE_SYSLOG;
951 }
952
953
954 bb_sanitize_stdio();
955
956 setlinebuf(stdout);
957
958 write_pidfile(client_config.pidfile);
959
960 bb_info_msg("%s (v"BB_VER") started", applet_name);
961
962 udhcp_sp_setup();
963
964 srand(monotonic_us());
965
966 state = INIT_SELECTING;
967 udhcp_run_script(NULL, "deconfig");
968 change_listen_mode(LISTEN_RAW);
969 packet_num = 0;
970 timeout = 0;
971 already_waited_sec = 0;
972
973
974
975
976
977 for (;;) {
978
979 unsigned timestamp_before_wait = timestamp_before_wait;
980
981
982
983
984
985
986
987
988
989
990 max_fd = udhcp_sp_fd_set(&rfds, sockfd);
991
992 tv.tv_sec = timeout - already_waited_sec;
993 tv.tv_usec = 0;
994 retval = 0;
995
996 if ((int)tv.tv_sec > 0) {
997 timestamp_before_wait = (unsigned)monotonic_sec();
998 log1("Waiting on select...");
999 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
1000 if (retval < 0) {
1001
1002 if (errno == EINTR) {
1003 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1004 continue;
1005 }
1006
1007 bb_perror_msg_and_die("select");
1008 }
1009 }
1010
1011
1012
1013
1014 if (retval == 0) {
1015
1016 already_waited_sec = 0;
1017
1018 switch (state) {
1019 case INIT_SELECTING:
1020 if (packet_num < discover_retries) {
1021 if (packet_num == 0)
1022 xid = random_xid();
1023
1024 send_discover(xid, requested_ip);
1025 timeout = discover_timeout;
1026 packet_num++;
1027 continue;
1028 }
1029 leasefail:
1030 udhcp_run_script(NULL, "leasefail");
1031#if BB_MMU
1032 if (opt & OPT_b) {
1033 bb_info_msg("No lease, forking to background");
1034 client_background();
1035
1036 opt = ((opt & ~OPT_b) | OPT_f);
1037 } else
1038#endif
1039 if (opt & OPT_n) {
1040 bb_info_msg("No lease, failing");
1041 retval = 1;
1042 goto ret;
1043 }
1044
1045 timeout = tryagain_timeout;
1046 packet_num = 0;
1047 continue;
1048 case REQUESTING:
1049 if (packet_num < discover_retries) {
1050
1051 send_select(xid, server_addr, requested_ip);
1052 timeout = discover_timeout;
1053 packet_num++;
1054 continue;
1055 }
1056
1057
1058
1059
1060 change_listen_mode(LISTEN_RAW);
1061 state = INIT_SELECTING;
1062 goto leasefail;
1063 case BOUND:
1064
1065 state = RENEWING;
1066 change_listen_mode(LISTEN_KERNEL);
1067 log1("Entering renew state");
1068
1069 case RENEW_REQUESTED:
1070 case_RENEW_REQUESTED:
1071 case RENEWING:
1072 if (timeout > 60) {
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 send_renew(xid, server_addr, requested_ip);
1083 timeout >>= 1;
1084 continue;
1085 }
1086
1087 log1("Entering rebinding state");
1088 state = REBINDING;
1089
1090 case REBINDING:
1091
1092 change_listen_mode(LISTEN_RAW);
1093
1094
1095 if (timeout > 0) {
1096
1097 send_renew(xid, 0 , requested_ip);
1098 timeout >>= 1;
1099 continue;
1100 }
1101
1102 bb_info_msg("Lease lost, entering init state");
1103 udhcp_run_script(NULL, "deconfig");
1104 state = INIT_SELECTING;
1105
1106 packet_num = 0;
1107 continue;
1108
1109 }
1110
1111 timeout = INT_MAX;
1112 continue;
1113 }
1114
1115
1116
1117
1118
1119 switch (udhcp_sp_read(&rfds)) {
1120 case SIGUSR1:
1121 perform_renew();
1122 if (state == RENEW_REQUESTED)
1123 goto case_RENEW_REQUESTED;
1124
1125 packet_num = 0;
1126
1127 timeout = 0;
1128 continue;
1129 case SIGUSR2:
1130 perform_release(requested_ip, server_addr);
1131 timeout = INT_MAX;
1132 continue;
1133 case SIGTERM:
1134 bb_info_msg("Received SIGTERM");
1135 if (opt & OPT_R)
1136 perform_release(requested_ip, server_addr);
1137 goto ret0;
1138 }
1139
1140
1141 if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds))
1142 continue;
1143
1144 {
1145 int len;
1146
1147
1148 if (listen_mode == LISTEN_KERNEL)
1149 len = udhcp_recv_kernel_packet(&packet, sockfd);
1150 else
1151 len = udhcp_recv_raw_packet(&packet, sockfd);
1152 if (len == -1) {
1153
1154 bb_info_msg("Read error: %s, reopening socket", strerror(errno));
1155 sleep(discover_timeout);
1156 change_listen_mode(listen_mode);
1157 }
1158
1159
1160
1161 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1162 if (len < 0)
1163 continue;
1164 }
1165
1166 if (packet.xid != xid) {
1167 log1("xid %x (our is %x), ignoring packet",
1168 (unsigned)packet.xid, (unsigned)xid);
1169 continue;
1170 }
1171
1172
1173 if (packet.hlen != 6
1174 || memcmp(packet.chaddr, client_config.client_mac, 6)
1175 ) {
1176
1177 log1("chaddr does not match, ignoring packet");
1178 continue;
1179 }
1180
1181 message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
1182 if (message == NULL) {
1183 bb_error_msg("no message type option, ignoring packet");
1184 continue;
1185 }
1186
1187 switch (state) {
1188 case INIT_SELECTING:
1189
1190 if (*message == DHCPOFFER) {
1191
1192 temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1193 if (!temp) {
1194 bb_error_msg("no server ID in message");
1195 continue;
1196
1197 }
1198
1199 move_from_unaligned32(server_addr, temp);
1200 xid = packet.xid;
1201 requested_ip = packet.yiaddr;
1202
1203
1204 state = REQUESTING;
1205 timeout = 0;
1206 packet_num = 0;
1207 already_waited_sec = 0;
1208 }
1209 continue;
1210 case REQUESTING:
1211 case RENEWING:
1212 case RENEW_REQUESTED:
1213 case REBINDING:
1214 if (*message == DHCPACK) {
1215 temp = udhcp_get_option(&packet, DHCP_LEASE_TIME);
1216 if (!temp) {
1217 bb_error_msg("no lease time with ACK, using 1 hour lease");
1218 lease_seconds = 60 * 60;
1219 } else {
1220
1221 move_from_unaligned32(lease_seconds, temp);
1222 lease_seconds = ntohl(lease_seconds);
1223 lease_seconds &= 0x0fffffff;
1224 if (lease_seconds < 10)
1225 lease_seconds = 10;
1226 }
1227#if ENABLE_FEATURE_UDHCPC_ARPING
1228 if (opt & OPT_a) {
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 if (!arpping(packet.yiaddr,
1239 NULL,
1240 (uint32_t) 0,
1241 client_config.client_mac,
1242 client_config.interface)
1243 ) {
1244 bb_info_msg("Offered address is in use "
1245 "(got ARP reply), declining");
1246 send_decline(xid, server_addr, packet.yiaddr);
1247
1248 if (state != REQUESTING)
1249 udhcp_run_script(NULL, "deconfig");
1250 change_listen_mode(LISTEN_RAW);
1251 state = INIT_SELECTING;
1252 requested_ip = 0;
1253 timeout = tryagain_timeout;
1254 packet_num = 0;
1255 already_waited_sec = 0;
1256 continue;
1257 }
1258 }
1259#endif
1260
1261 timeout = lease_seconds / 2;
1262 {
1263 struct in_addr temp_addr;
1264 temp_addr.s_addr = packet.yiaddr;
1265 bb_info_msg("Lease of %s obtained, lease time %u",
1266 inet_ntoa(temp_addr), (unsigned)lease_seconds);
1267 }
1268 requested_ip = packet.yiaddr;
1269 udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew");
1270
1271 state = BOUND;
1272 change_listen_mode(LISTEN_NONE);
1273 if (opt & OPT_q) {
1274 if (opt & OPT_R)
1275 perform_release(requested_ip, server_addr);
1276 goto ret0;
1277 }
1278
1279 opt &= ~OPT_n;
1280#if BB_MMU
1281 if (!(opt & OPT_f)) {
1282 client_background();
1283
1284 opt = ((opt & ~OPT_b) | OPT_f);
1285 }
1286#endif
1287 already_waited_sec = 0;
1288 continue;
1289 }
1290 if (*message == DHCPNAK) {
1291
1292 bb_info_msg("Received DHCP NAK");
1293 udhcp_run_script(&packet, "nak");
1294 if (state != REQUESTING)
1295 udhcp_run_script(NULL, "deconfig");
1296 change_listen_mode(LISTEN_RAW);
1297 sleep(3);
1298 state = INIT_SELECTING;
1299 requested_ip = 0;
1300 timeout = 0;
1301 packet_num = 0;
1302 already_waited_sec = 0;
1303 }
1304 continue;
1305
1306
1307 }
1308
1309 }
1310
1311 ret0:
1312 retval = 0;
1313 ret:
1314
1315 remove_pidfile(client_config.pidfile);
1316 return retval;
1317}
1318