1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <syslog.h>
28
29#define WANT_PIDFILE 1
30#include "common.h"
31#include "dhcpd.h"
32#include "dhcpc.h"
33
34#include <netinet/if_ether.h>
35#include <linux/filter.h>
36#include <linux/if_packet.h>
37
38#ifndef PACKET_AUXDATA
39# define PACKET_AUXDATA 8
40struct tpacket_auxdata {
41 uint32_t tp_status;
42 uint32_t tp_len;
43 uint32_t tp_snaplen;
44 uint16_t tp_mac;
45 uint16_t tp_net;
46 uint16_t tp_vlan_tci;
47 uint16_t tp_padding;
48};
49#endif
50
51
52
53
54
55#if ENABLE_LONG_OPTS
56static const char udhcpc_longopts[] ALIGN1 =
57 "clientid-none\0" No_argument "C"
58 "vendorclass\0" Required_argument "V"
59 "fqdn\0" Required_argument "F"
60 "interface\0" Required_argument "i"
61 "now\0" No_argument "n"
62 "pidfile\0" Required_argument "p"
63 "quit\0" No_argument "q"
64 "release\0" No_argument "R"
65 "request\0" Required_argument "r"
66 "script\0" Required_argument "s"
67 "timeout\0" Required_argument "T"
68 "retries\0" Required_argument "t"
69 "tryagain\0" Required_argument "A"
70 "syslog\0" No_argument "S"
71 "request-option\0" Required_argument "O"
72 "no-default-options\0" No_argument "o"
73 "foreground\0" No_argument "f"
74 USE_FOR_MMU(
75 "background\0" No_argument "b"
76 )
77 "broadcast\0" No_argument "B"
78 IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a")
79 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
80 ;
81#endif
82
83enum {
84 OPT_C = 1 << 0,
85 OPT_V = 1 << 1,
86 OPT_F = 1 << 2,
87 OPT_i = 1 << 3,
88 OPT_n = 1 << 4,
89 OPT_p = 1 << 5,
90 OPT_q = 1 << 6,
91 OPT_R = 1 << 7,
92 OPT_r = 1 << 8,
93 OPT_s = 1 << 9,
94 OPT_T = 1 << 10,
95 OPT_t = 1 << 11,
96 OPT_S = 1 << 12,
97 OPT_A = 1 << 13,
98 OPT_O = 1 << 14,
99 OPT_o = 1 << 15,
100 OPT_x = 1 << 16,
101 OPT_f = 1 << 17,
102 OPT_B = 1 << 18,
103
104 OPTBIT_B = 18,
105 USE_FOR_MMU( OPTBIT_b,)
106 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
107 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
108 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,)
109 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
110 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
111};
112
113
114
115struct dhcp_optitem {
116 unsigned len;
117 uint8_t code;
118 uint8_t malloced;
119 uint8_t *data;
120 char *env;
121};
122
123
124static const uint8_t len_of_option_as_string[] ALIGN1 = {
125 [OPTION_IP ] = sizeof("255.255.255.255 "),
126 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
127 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
128 [OPTION_6RD ] = sizeof("132 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
129 [OPTION_STRING ] = 1,
130 [OPTION_STRING_HOST ] = 1,
131#if ENABLE_FEATURE_UDHCP_RFC3397
132 [OPTION_DNS_STRING ] = 1,
133
134
135
136
137 [OPTION_SIP_SERVERS ] = sizeof("255.255.255.255 "),
138#endif
139
140 [OPTION_U8 ] = sizeof("255 "),
141 [OPTION_U16 ] = sizeof("65535 "),
142
143 [OPTION_U32 ] = sizeof("4294967295 "),
144 [OPTION_S32 ] = sizeof("-2147483684 "),
145};
146
147
148static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
149{
150 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
151}
152
153
154static int mton(uint32_t mask)
155{
156 int i = 0;
157 mask = ntohl(mask);
158 while (mask) {
159 i++;
160 mask <<= 1;
161 }
162 return i;
163}
164
165#if ENABLE_FEATURE_UDHCPC_SANITIZEOPT
166
167
168
169
170
171
172
173static int good_hostname(const char *name)
174{
175 if (*name == '-')
176 return 0;
177
178 while (*name) {
179 unsigned char ch = *name++;
180 if (!isalnum(ch))
181
182 if (ch != '-' && ch != '_' && ch != '.')
183 return 0;
184
185 }
186 return 1;
187}
188#else
189# define good_hostname(name) 1
190#endif
191
192
193static NOINLINE char *xmalloc_optname_optval(const struct dhcp_optitem *opt_item, const struct dhcp_optflag *optflag, const char *opt_name)
194{
195 unsigned upper_length;
196 int len, type, optlen;
197 char *dest, *ret;
198 uint8_t *option;
199
200 option = opt_item->data;
201 len = opt_item->len;
202 type = optflag->flags & OPTION_TYPE_MASK;
203 optlen = dhcp_option_lengths[type];
204 upper_length = len_of_option_as_string[type]
205 * ((unsigned)(len + optlen) / (unsigned)optlen);
206
207 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
208 dest += sprintf(ret, "%s=", opt_name);
209
210 while (len >= optlen) {
211 switch (type) {
212 case OPTION_IP:
213 case OPTION_IP_PAIR:
214 dest += sprint_nip(dest, "", option);
215 if (type == OPTION_IP_PAIR)
216 dest += sprint_nip(dest, "/", option + 4);
217 break;
218
219
220
221 case OPTION_U8:
222 dest += sprintf(dest, "%u", *option);
223 break;
224
225 case OPTION_U16: {
226 uint16_t val_u16;
227 move_from_unaligned16(val_u16, option);
228 dest += sprintf(dest, "%u", ntohs(val_u16));
229 break;
230 }
231 case OPTION_S32:
232 case OPTION_U32: {
233 uint32_t val_u32;
234 move_from_unaligned32(val_u32, option);
235 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32));
236 break;
237 }
238
239
240
241
242 case OPTION_STRING:
243 case OPTION_STRING_HOST:
244 memcpy(dest, option, len);
245 dest[len] = '\0';
246
247
248
249
250
251
252 if (type == OPTION_STRING_HOST && !good_hostname(dest))
253 safe_strncpy(dest, "bad", len);
254 return ret;
255 case OPTION_STATIC_ROUTES: {
256
257
258
259
260
261
262
263
264 const char *pfx = "";
265
266 while (len >= 1 + 4) {
267 uint32_t nip;
268 uint8_t *p;
269 unsigned mask;
270 int bytes;
271
272 mask = *option++;
273 if (mask > 32)
274 break;
275 len--;
276
277 nip = 0;
278 p = (void*) &nip;
279 bytes = (mask + 7) / 8;
280 while (--bytes >= 0) {
281 *p++ = *option++;
282 len--;
283 }
284 if (len < 4)
285 break;
286
287
288 dest += sprint_nip(dest, pfx, (void*) &nip);
289 pfx = " ";
290 dest += sprintf(dest, "/%u ", mask);
291
292 dest += sprint_nip(dest, "", option);
293 option += 4;
294 len -= 4;
295 }
296
297 return ret;
298 }
299 case OPTION_6RD:
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321 if (len >= (1 + 1 + 16 + 4)
322 && option[0] <= 32
323 && (option[1] + 32 - option[0]) <= 128
324 ) {
325
326 dest += sprintf(dest, "%u ", *option++);
327
328 dest += sprintf(dest, "%u ", *option++);
329
330 dest += sprint_nip6(dest, option);
331 option += 16;
332 len -= 1 + 1 + 16;
333 *dest++ = ' ';
334
335 type = OPTION_IP;
336 optlen = 4;
337 continue;
338 }
339
340 return ret;
341#if ENABLE_FEATURE_UDHCP_RFC3397
342 case OPTION_DNS_STRING:
343
344 dest = dname_dec(option, len, ret);
345 if (dest) {
346 free(ret);
347 return dest;
348 }
349
350 return ret;
351 case OPTION_SIP_SERVERS:
352
353
354
355
356
357 option++;
358 len--;
359 if (option[-1] == 1) {
360
361 type = OPTION_IP;
362 optlen = 4;
363 continue;
364 }
365 if (option[-1] == 0) {
366 dest = dname_dec(option, len, ret);
367 if (dest) {
368 free(ret);
369 return dest;
370 }
371 }
372 return ret;
373#endif
374 }
375
376
377
378
379 option += optlen;
380 len -= optlen;
381
382
383
384 if (len < optlen )
385 break;
386 *dest++ = ' ';
387 *dest = '\0';
388 }
389
390 return ret;
391}
392
393static void optitem_unset_env_and_free(void *item)
394{
395 struct dhcp_optitem *opt_item = item;
396 bb_unsetenv_and_free(opt_item->env);
397 if (opt_item->malloced)
398 free(opt_item->data);
399 free(opt_item);
400}
401
402
403static void putenvp(char *new_opt)
404{
405 struct dhcp_optitem *opt_item;
406
407 opt_item = xzalloc(sizeof(*opt_item));
408
409
410
411 opt_item->env = new_opt;
412 llist_add_to(&client_data.envp, opt_item);
413 log2(" %s", new_opt);
414 putenv(new_opt);
415}
416
417
418static struct dhcp_optitem *concat_option(uint8_t *data, uint8_t len, uint8_t code)
419{
420 llist_t *item;
421 struct dhcp_optitem *opt_item;
422
423
424
425
426
427
428
429 for (item = client_data.envp; item != NULL; item = item->link) {
430 opt_item = (struct dhcp_optitem *)item->data;
431 if (opt_item->code == code) {
432
433 uint8_t *new_data;
434
435 new_data = xmalloc(len + opt_item->len);
436 memcpy(
437 mempcpy(new_data, opt_item->data, opt_item->len),
438 data, len
439 );
440 opt_item->len += len;
441 if (opt_item->malloced)
442 free(opt_item->data);
443 opt_item->malloced = 1;
444 opt_item->data = new_data;
445 return opt_item;
446 }
447 }
448
449
450 opt_item = xzalloc(sizeof(*opt_item));
451 opt_item->code = code;
452
453 opt_item->data = data;
454 opt_item->len = len;
455 llist_add_to(&client_data.envp, opt_item);
456 return opt_item;
457}
458
459static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh)
460{
461
462
463
464
465
466
467
468 for (*dh = dhcp_optflags; (*dh)->code && (*dh)->code < code; (*dh)++)
469 continue;
470
471 if ((*dh)->code == code)
472 return nth_string(dhcp_option_strings, (*dh - dhcp_optflags));
473
474 return NULL;
475}
476
477
478static void fill_envp(struct dhcp_packet *packet)
479{
480 uint8_t *optptr;
481 struct dhcp_scan_state scan_state;
482 char *new_opt;
483
484 putenvp(xasprintf("interface=%s", client_data.interface));
485
486 if (!packet)
487 return;
488
489 init_scan_state(packet, &scan_state);
490
491
492
493
494
495 while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) {
496 const struct dhcp_optflag *dh;
497 const char *opt_name;
498 struct dhcp_optitem *opt_item;
499 uint8_t code = optptr[OPT_CODE];
500 uint8_t len = optptr[OPT_LEN];
501 uint8_t *data = optptr + OPT_DATA;
502
503 opt_item = concat_option(data, len, code);
504 opt_name = get_optname(code, &dh);
505 if (opt_name) {
506 new_opt = xmalloc_optname_optval(opt_item, dh, opt_name);
507 if (opt_item->code == DHCP_SUBNET && opt_item->len == 4) {
508
509 uint32_t subnet;
510 move_from_unaligned32(subnet, opt_item->data);
511 putenvp(xasprintf("mask=%u", mton(subnet)));
512 }
513 } else {
514 unsigned ofs;
515 new_opt = xmalloc(sizeof("optNNN=") + 1 + opt_item->len*2);
516 ofs = sprintf(new_opt, "opt%u=", opt_item->code);
517 bin2hex(new_opt + ofs, (char *)opt_item->data, opt_item->len)[0] = '\0';
518 }
519 log2(" %s", new_opt);
520 putenv(new_opt);
521
522
523
524 free(opt_item->env);
525 opt_item->env = new_opt;
526 }
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541 new_opt = xmalloc(sizeof("ip=255.255.255.255"));
542 sprint_nip(new_opt, "ip=", (uint8_t *) &packet->yiaddr);
543 putenvp(new_opt);
544
545 if (packet->siaddr_nip) {
546
547 new_opt = xmalloc(sizeof("siaddr=255.255.255.255"));
548 sprint_nip(new_opt, "siaddr=", (uint8_t *) &packet->siaddr_nip);
549 putenvp(new_opt);
550 }
551 if (packet->gateway_nip) {
552
553 new_opt = xmalloc(sizeof("giaddr=255.255.255.255"));
554 sprint_nip(new_opt, "giaddr=", (uint8_t *) &packet->gateway_nip);
555 putenvp(new_opt);
556 }
557 if (!(scan_state.overload & FILE_FIELD) && packet->file[0]) {
558
559 new_opt = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
560 putenvp(new_opt);
561 }
562 if (!(scan_state.overload & SNAME_FIELD) && packet->sname[0]) {
563
564 new_opt = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
565 putenvp(new_opt);
566 }
567}
568
569
570static void d4_run_script(struct dhcp_packet *packet, const char *name)
571{
572 char *argv[3];
573
574 fill_envp(packet);
575
576
577 log1("executing %s %s", client_data.script, name);
578 argv[0] = (char*) client_data.script;
579 argv[1] = (char*) name;
580 argv[2] = NULL;
581 spawn_and_wait(argv);
582
583
584 llist_free(client_data.envp, optitem_unset_env_and_free);
585 client_data.envp = NULL;
586}
587
588static void d4_run_script_deconfig(void)
589{
590 d4_run_script(NULL, "deconfig");
591}
592
593
594
595static ALWAYS_INLINE uint32_t random_xid(void)
596{
597 return rand();
598}
599
600
601static void init_packet(struct dhcp_packet *packet, char type)
602{
603 unsigned secs;
604
605
606 udhcp_init_header(packet, type);
607
608 packet->xid = client_data.xid;
609
610 client_data.last_secs = monotonic_sec();
611 if (client_data.first_secs == 0)
612 client_data.first_secs = client_data.last_secs;
613 secs = client_data.last_secs - client_data.first_secs;
614 packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff;
615
616 memcpy(packet->chaddr, client_data.client_mac, 6);
617}
618
619static void add_client_options(struct dhcp_packet *packet)
620{
621 int i, end, len;
622
623 udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE));
624
625
626
627
628 end = udhcp_end_option(packet->options);
629 len = 0;
630 for (i = 1; i < DHCP_END; i++) {
631 if (client_data.opt_mask[i >> 3] & (1 << (i & 7))) {
632 packet->options[end + OPT_DATA + len] = i;
633 len++;
634 }
635 }
636 if (len) {
637 packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
638 packet->options[end + OPT_LEN] = len;
639 packet->options[end + OPT_DATA + len] = DHCP_END;
640 }
641
642
643 if ((option_mask32 & OPT_B) && packet->ciaddr == 0)
644 packet->flags |= htons(BROADCAST_FLAG);
645
646
647 {
648 struct option_set *curr = client_data.options;
649 while (curr) {
650 udhcp_add_binary_option(packet, curr->data);
651 curr = curr->next;
652 }
653
654
655
656
657 }
658
659
660
661
662
663
664}
665
666static void add_serverid_and_clientid_options(struct dhcp_packet *packet, uint32_t server)
667{
668 struct option_set *ci;
669
670 udhcp_add_simple_option(packet, DHCP_SERVER_ID, server);
671
672
673
674
675
676
677
678
679 ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID, 0);
680 if (ci)
681 udhcp_add_binary_option(packet, ci->data);
682}
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702static int raw_bcast_from_client_data_ifindex(struct dhcp_packet *packet, uint32_t src_nip)
703{
704 return udhcp_send_raw_packet(packet,
705 src_nip, CLIENT_PORT,
706 INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
707 client_data.ifindex);
708}
709
710static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server)
711{
712 if (server)
713 return udhcp_send_kernel_packet(packet,
714 ciaddr, CLIENT_PORT,
715 server, SERVER_PORT,
716 client_data.interface);
717 return raw_bcast_from_client_data_ifindex(packet, ciaddr);
718}
719
720
721
722static NOINLINE int send_discover(uint32_t requested)
723{
724 struct dhcp_packet packet;
725
726
727
728
729 init_packet(&packet, DHCPDISCOVER);
730
731 if (requested)
732 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
733
734
735
736
737 add_client_options(&packet);
738
739 bb_simple_info_msg("broadcasting discover");
740 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
741}
742
743
744
745
746
747
748static NOINLINE int send_select(uint32_t server, uint32_t requested)
749{
750 struct dhcp_packet packet;
751 struct in_addr temp_addr;
752 char server_str[sizeof("255.255.255.255")];
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769 init_packet(&packet, DHCPREQUEST);
770
771 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
772
773 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
774
775
776
777
778 add_client_options(&packet);
779
780 temp_addr.s_addr = server;
781 strcpy(server_str, inet_ntoa(temp_addr));
782 temp_addr.s_addr = requested;
783 bb_info_msg("broadcasting select for %s, server %s",
784 inet_ntoa(temp_addr),
785 server_str
786 );
787 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
788}
789
790
791
792static NOINLINE int send_renew(uint32_t server, uint32_t ciaddr)
793{
794 struct dhcp_packet packet;
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813 init_packet(&packet, DHCPREQUEST);
814
815 packet.ciaddr = ciaddr;
816
817
818
819
820 add_client_options(&packet);
821
822 if (server) {
823 struct in_addr temp_addr;
824 temp_addr.s_addr = server;
825 bb_info_msg("sending renew to server %s", inet_ntoa(temp_addr));
826 } else {
827 bb_simple_info_msg("broadcasting renew");
828 }
829
830 return bcast_or_ucast(&packet, ciaddr, server);
831}
832
833#if ENABLE_FEATURE_UDHCPC_ARPING
834
835
836static NOINLINE int send_decline(uint32_t server, uint32_t requested)
837{
838 struct dhcp_packet packet;
839
840
841
842
843 init_packet(&packet, DHCPDECLINE);
844
845
846 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
847
848 add_serverid_and_clientid_options(&packet, server);
849
850 bb_simple_info_msg("broadcasting decline");
851 return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY);
852}
853#endif
854
855
856static
857ALWAYS_INLINE
858int send_release(uint32_t server, uint32_t ciaddr)
859{
860 struct dhcp_packet packet;
861
862
863
864
865 init_packet(&packet, DHCPRELEASE);
866
867
868 packet.ciaddr = ciaddr;
869
870 add_serverid_and_clientid_options(&packet, server);
871
872 bb_info_msg("sending %s", "release");
873
874
875
876
877 return bcast_or_ucast(&packet, ciaddr, server);
878}
879
880
881
882static NOINLINE int d4_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
883{
884 int bytes;
885 struct ip_udp_dhcp_packet packet;
886 uint16_t check;
887 unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
888 struct iovec iov;
889 struct msghdr msg;
890 struct cmsghdr *cmsg;
891
892
893
894
895 iov.iov_base = &packet;
896 iov.iov_len = sizeof(packet);
897 memset(&msg, 0, sizeof(msg));
898 msg.msg_iov = &iov;
899 msg.msg_iovlen = 1;
900 msg.msg_control = cmsgbuf;
901 msg.msg_controllen = sizeof(cmsgbuf);
902 for (;;) {
903 bytes = recvmsg(fd, &msg, 0);
904 if (bytes < 0) {
905 if (errno == EINTR)
906 continue;
907 log1s("packet read error, ignoring");
908
909 return bytes;
910 }
911 break;
912 }
913
914 if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
915 log1s("packet is too short, ignoring");
916 return -2;
917 }
918
919 if (bytes < ntohs(packet.ip.tot_len)) {
920
921 log1s("oversized packet, ignoring");
922 return -2;
923 }
924
925
926 bytes = ntohs(packet.ip.tot_len);
927
928
929 if (packet.ip.protocol != IPPROTO_UDP
930 || packet.ip.version != IPVERSION
931 || packet.ip.ihl != (sizeof(packet.ip) >> 2)
932 || packet.udp.dest != htons(CLIENT_PORT)
933
934 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip))
935 ) {
936 log1s("unrelated/bogus packet, ignoring");
937 return -2;
938 }
939
940
941 check = packet.ip.check;
942 packet.ip.check = 0;
943 if (check != inet_cksum(&packet.ip, sizeof(packet.ip))) {
944 log1s("bad IP header checksum, ignoring");
945 return -2;
946 }
947
948 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
949 if (cmsg->cmsg_level == SOL_PACKET
950 && cmsg->cmsg_type == PACKET_AUXDATA
951 ) {
952
953
954
955
956 struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
957 if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
958 goto skip_udp_sum_check;
959 }
960 }
961
962
963 memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
964
965 packet.ip.tot_len = packet.udp.len;
966 check = packet.udp.check;
967 packet.udp.check = 0;
968 if (check && check != inet_cksum(&packet, bytes)) {
969 log1s("packet with bad UDP checksum received, ignoring");
970 return -2;
971 }
972 skip_udp_sum_check:
973
974 if (packet.data.cookie != htonl(DHCP_MAGIC)) {
975 log1s("packet with bad magic, ignoring");
976 return -2;
977 }
978
979 log2("received %s", "a packet");
980
981 udhcp_dump_packet(&packet.data);
982
983 bytes -= sizeof(packet.ip) + sizeof(packet.udp);
984 memcpy(dhcp_pkt, &packet.data, bytes);
985 return bytes;
986}
987
988
989
990
991
992#define LISTEN_NONE 0
993#define LISTEN_KERNEL 1
994#define LISTEN_RAW 2
995
996
997
998#define INIT_SELECTING 0
999
1000#define REQUESTING 1
1001
1002#define BOUND 2
1003
1004#define RENEWING 3
1005
1006#define REBINDING 4
1007
1008#define RENEW_REQUESTED 5
1009
1010#define RELEASED 6
1011
1012static int udhcp_raw_socket(int ifindex)
1013{
1014 int fd;
1015 struct sockaddr_ll sock;
1016
1017 log2("opening raw socket on ifindex %d", ifindex);
1018
1019 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
1020
1021
1022
1023
1024
1025 memset(&sock, 0, sizeof(sock));
1026 sock.sll_family = AF_PACKET;
1027 sock.sll_protocol = htons(ETH_P_IP);
1028 sock.sll_ifindex = ifindex;
1029
1030
1031
1032
1033 xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
1034
1035#if 0
1036 if (CLIENT_PORT == 68) {
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 static const struct sock_filter filter_instr[] = {
1056
1057 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
1058
1059 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
1060
1061 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
1062
1063 BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
1064
1065 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
1066
1067 BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
1068
1069 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
1070
1071
1072 BPF_STMT(BPF_RET|BPF_K, 0x7fffffff),
1073
1074 BPF_STMT(BPF_RET|BPF_K, 0),
1075 };
1076 static const struct sock_fprog filter_prog = {
1077 .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
1078
1079 .filter = (struct sock_filter *) filter_instr,
1080 };
1081
1082 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
1083 sizeof(filter_prog)) >= 0)
1084 log1("attached filter to raw socket fd");
1085 }
1086#endif
1087
1088 if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) {
1089 if (errno != ENOPROTOOPT)
1090 log1s("can't set PACKET_AUXDATA on raw socket");
1091 }
1092
1093 return fd;
1094}
1095
1096static void change_listen_mode(int new_mode)
1097{
1098 log1("entering listen mode: %s",
1099 new_mode != LISTEN_NONE
1100 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
1101 : "none"
1102 );
1103
1104 client_data.listen_mode = new_mode;
1105 if (client_data.sockfd >= 0) {
1106 close(client_data.sockfd);
1107 client_data.sockfd = -1;
1108 }
1109 if (new_mode == LISTEN_KERNEL)
1110 client_data.sockfd = udhcp_listen_socket( CLIENT_PORT, client_data.interface);
1111 else if (new_mode != LISTEN_NONE)
1112 client_data.sockfd = udhcp_raw_socket(client_data.ifindex);
1113
1114}
1115
1116static void perform_release(uint32_t server_id, uint32_t requested_ip)
1117{
1118 char buffer[sizeof("255.255.255.255")];
1119 struct in_addr temp_addr;
1120
1121 change_listen_mode(LISTEN_NONE);
1122
1123
1124 if (client_data.state == BOUND
1125 || client_data.state == RENEWING
1126 || client_data.state == REBINDING
1127 || client_data.state == RENEW_REQUESTED
1128 ) {
1129 temp_addr.s_addr = server_id;
1130 strcpy(buffer, inet_ntoa(temp_addr));
1131 temp_addr.s_addr = requested_ip;
1132 bb_info_msg("unicasting a release of %s to %s",
1133 inet_ntoa(temp_addr), buffer);
1134 client_data.xid = random_xid();
1135 send_release(server_id, requested_ip);
1136 }
1137 bb_simple_info_msg("entering released state");
1138
1139
1140
1141
1142
1143
1144 d4_run_script_deconfig();
1145 client_data.state = RELEASED;
1146}
1147
1148#if BB_MMU
1149static void client_background(void)
1150{
1151 bb_daemonize(0);
1152 logmode &= ~LOGMODE_STDIO;
1153
1154 write_pidfile(client_data.pidfile);
1155}
1156#endif
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1209int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1210{
1211 uint8_t *message;
1212 const char *str_V, *str_F, *str_r;
1213 IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";)
1214 IF_FEATURE_UDHCP_PORT(char *str_P;)
1215 uint8_t *clientid_mac_ptr;
1216 llist_t *list_O = NULL;
1217 llist_t *list_x = NULL;
1218 int tryagain_timeout = 20;
1219 int discover_timeout = 3;
1220 int discover_retries = 3;
1221 uint32_t server_id = server_id;
1222 uint32_t requested_ip = 0;
1223 int packet_num;
1224 int timeout;
1225 int lease_remaining;
1226 unsigned opt;
1227 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1228 int retval;
1229
1230 setup_common_bufsiz();
1231
1232
1233 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
1234 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
1235 client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE;
1236 client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT;
1237 client_data.sockfd = -1;
1238 str_V = "udhcp "BB_VER;
1239
1240
1241
1242 udhcp_sp_setup();
1243
1244
1245 opt = getopt32long(argv, "^"
1246
1247 "CV:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB"
1248 USE_FOR_MMU("b")
1249 IF_FEATURE_UDHCPC_ARPING("a::")
1250 IF_FEATURE_UDHCP_PORT("P:")
1251 "v"
1252 "\0" IF_UDHCP_VERBOSE("vv")
1253 , udhcpc_longopts
1254 , &str_V, &str_F
1255 , &client_data.interface, &client_data.pidfile
1256 , &str_r
1257 , &client_data.script
1258 , &discover_timeout, &discover_retries, &tryagain_timeout
1259 , &list_O
1260 , &list_x
1261 IF_FEATURE_UDHCPC_ARPING(, &str_a)
1262 IF_FEATURE_UDHCP_PORT(, &str_P)
1263 IF_UDHCP_VERBOSE(, &dhcp_verbose)
1264 );
1265 if (opt & OPT_F) {
1266 char *p;
1267 unsigned len;
1268
1269 len = strlen(str_F);
1270 p = udhcp_insert_new_option(
1271 &client_data.options, DHCP_FQDN,
1272 len + 3, 0);
1273
1274
1275
1276
1277
1278
1279
1280
1281 p[OPT_DATA + 0] = 0x1;
1282
1283
1284 memcpy(p + OPT_DATA + 3, str_F, len);
1285 }
1286 if (opt & OPT_r)
1287 if (!inet_aton(str_r, (void*)&requested_ip))
1288 bb_show_usage();
1289#if ENABLE_FEATURE_UDHCP_PORT
1290 if (opt & OPT_P) {
1291 CLIENT_PORT = xatou16(str_P);
1292 SERVER_PORT = CLIENT_PORT - 1;
1293 }
1294#endif
1295 IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);)
1296 while (list_O) {
1297 char *optstr = llist_pop(&list_O);
1298 unsigned n = bb_strtou(optstr, NULL, 0);
1299 if (errno || n > 254) {
1300 n = udhcp_option_idx(optstr, dhcp_option_strings);
1301 n = dhcp_optflags[n].code;
1302 }
1303 client_data.opt_mask[n >> 3] |= 1 << (n & 7);
1304 }
1305 if (!(opt & OPT_o)) {
1306 unsigned i, n;
1307 for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) {
1308 if (dhcp_optflags[i].flags & OPTION_REQ) {
1309 client_data.opt_mask[n >> 3] |= 1 << (n & 7);
1310 }
1311 }
1312 }
1313 while (list_x) {
1314 char *optstr = xstrdup(llist_pop(&list_x));
1315 udhcp_str2optset(optstr, &client_data.options,
1316 dhcp_optflags, dhcp_option_strings,
1317 0
1318 );
1319 free(optstr);
1320 }
1321 if (str_V[0] != '\0') {
1322 char *p;
1323 unsigned len = strnlen(str_V, 254);
1324 p = udhcp_insert_new_option(
1325 &client_data.options, DHCP_VENDOR,
1326 len, 0);
1327 memcpy(p + OPT_DATA, str_V, len);
1328 }
1329
1330 clientid_mac_ptr = NULL;
1331 if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID, 0)) {
1332
1333 clientid_mac_ptr = udhcp_insert_new_option(
1334 &client_data.options, DHCP_CLIENT_ID,
1335 1 + 6, 0);
1336 clientid_mac_ptr[OPT_DATA] = 1;
1337 clientid_mac_ptr += OPT_DATA + 1;
1338 }
1339
1340
1341
1342
1343
1344 if (udhcp_read_interface(client_data.interface,
1345 &client_data.ifindex,
1346 NULL,
1347 client_data.client_mac)
1348 ) {
1349 return 1;
1350 }
1351
1352#if !BB_MMU
1353
1354 if (!(opt & OPT_f)) {
1355 bb_daemonize_or_rexec(0 , argv);
1356 logmode = LOGMODE_NONE;
1357 }
1358#endif
1359 if (opt & OPT_S) {
1360 openlog(applet_name, LOG_PID, LOG_DAEMON);
1361 logmode |= LOGMODE_SYSLOG;
1362 }
1363
1364
1365 write_pidfile(client_data.pidfile);
1366
1367 bb_simple_info_msg("started, v"BB_VER);
1368
1369 srand(monotonic_us());
1370
1371 client_data.state = INIT_SELECTING;
1372 d4_run_script_deconfig();
1373 packet_num = 0;
1374 timeout = 0;
1375 lease_remaining = 0;
1376
1377
1378
1379
1380
1381 for (;;) {
1382 struct pollfd pfds[2];
1383 struct dhcp_packet packet;
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394 udhcp_sp_fd_set(pfds, client_data.sockfd);
1395
1396 retval = 0;
1397
1398 if (timeout > 0) {
1399 unsigned diff;
1400
1401 if (timeout > INT_MAX/1000)
1402 timeout = INT_MAX/1000;
1403 log1("waiting %u seconds", timeout);
1404 diff = (unsigned)monotonic_sec();
1405 retval = poll(pfds, 2, timeout * 1000);
1406 diff = (unsigned)monotonic_sec() - diff;
1407 lease_remaining -= diff;
1408 if (lease_remaining < 0)
1409 lease_remaining = 0;
1410 timeout -= diff;
1411 if (timeout < 0)
1412 timeout = 0;
1413
1414 if (retval < 0) {
1415
1416 if (errno == EINTR) {
1417 continue;
1418 }
1419
1420 bb_simple_perror_msg_and_die("poll");
1421 }
1422 }
1423
1424
1425
1426
1427 if (retval == 0) {
1428
1429
1430
1431
1432
1433 if (udhcp_read_interface(client_data.interface,
1434 &client_data.ifindex,
1435 NULL,
1436 client_data.client_mac)
1437 ) {
1438 goto ret0;
1439 }
1440 if (clientid_mac_ptr)
1441 memcpy(clientid_mac_ptr, client_data.client_mac, 6);
1442
1443 switch (client_data.state) {
1444 case INIT_SELECTING:
1445 if (!discover_retries || packet_num < discover_retries) {
1446 if (packet_num == 0) {
1447 change_listen_mode(LISTEN_RAW);
1448 client_data.xid = random_xid();
1449 }
1450
1451 send_discover(requested_ip);
1452 timeout = discover_timeout;
1453 packet_num++;
1454 continue;
1455 }
1456 leasefail:
1457 change_listen_mode(LISTEN_NONE);
1458 d4_run_script(NULL, "leasefail");
1459#if BB_MMU
1460 if (opt & OPT_b) {
1461 bb_simple_info_msg("no lease, forking to background");
1462 client_background();
1463
1464 opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f);
1465
1466
1467
1468
1469
1470
1471 } else
1472#endif
1473 if (opt & OPT_n) {
1474 bb_simple_info_msg("no lease, failing");
1475 retval = 1;
1476 goto ret;
1477 }
1478
1479 timeout = tryagain_timeout;
1480 packet_num = 0;
1481 continue;
1482 case REQUESTING:
1483 if (packet_num < 3) {
1484
1485 send_select(server_id, requested_ip);
1486 timeout = discover_timeout;
1487 packet_num++;
1488 continue;
1489 }
1490
1491
1492
1493
1494 client_data.state = INIT_SELECTING;
1495 goto leasefail;
1496 case BOUND:
1497
1498 client_data.state = RENEWING;
1499 client_data.first_secs = 0;
1500 got_SIGUSR1:
1501 log1s("entering renew state");
1502 change_listen_mode(LISTEN_KERNEL);
1503
1504 case RENEW_REQUESTED:
1505 case RENEWING:
1506 if (packet_num == 0) {
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516 if (send_renew(server_id, requested_ip) >= 0) {
1517 timeout = discover_timeout;
1518 packet_num++;
1519 continue;
1520 }
1521
1522
1523
1524
1525
1526 }
1527 log1s("no response to renew");
1528 if (lease_remaining > 30) {
1529
1530 change_listen_mode(LISTEN_NONE);
1531 goto BOUND_for_half_lease;
1532 }
1533
1534 client_data.state = REBINDING;
1535 log1s("entering rebinding state");
1536
1537 change_listen_mode(LISTEN_RAW);
1538 packet_num = 0;
1539
1540 case REBINDING:
1541
1542
1543 if (lease_remaining > 0 && packet_num < 3) {
1544
1545 send_renew(0 , requested_ip);
1546 timeout = discover_timeout;
1547 packet_num++;
1548 continue;
1549 }
1550
1551 change_listen_mode(LISTEN_NONE);
1552 bb_simple_info_msg("lease lost, entering init state");
1553 d4_run_script_deconfig();
1554 client_data.state = INIT_SELECTING;
1555 client_data.first_secs = 0;
1556 timeout = 0;
1557 packet_num = 0;
1558 continue;
1559
1560 }
1561
1562
1563
1564 timeout = INT_MAX;
1565 continue;
1566 }
1567
1568
1569
1570
1571 switch (udhcp_sp_read()) {
1572 case SIGUSR1:
1573 if (client_data.state <= REQUESTING)
1574
1575 break;
1576 if (client_data.state == REBINDING)
1577
1578 break;
1579
1580 if (lease_remaining > 30)
1581 lease_remaining = 30;
1582 client_data.first_secs = 0;
1583 packet_num = 0;
1584
1585 switch (client_data.state) {
1586 case BOUND:
1587 case RENEWING:
1588
1589 client_data.state = RENEW_REQUESTED;
1590 goto got_SIGUSR1;
1591
1592 case RENEW_REQUESTED:
1593
1594 change_listen_mode(LISTEN_NONE);
1595 d4_run_script_deconfig();
1596
1597 default:
1598
1599
1600 change_listen_mode(LISTEN_NONE);
1601 }
1602 client_data.state = INIT_SELECTING;
1603
1604 timeout = 0;
1605 continue;
1606 case SIGUSR2:
1607 perform_release(server_id, requested_ip);
1608
1609 timeout = INT_MAX;
1610 continue;
1611 case SIGTERM:
1612 bb_info_msg("received %s", "SIGTERM");
1613 goto ret0;
1614 }
1615
1616
1617 if (!pfds[1].revents)
1618 continue;
1619
1620 {
1621 int len;
1622
1623
1624 if (client_data.listen_mode == LISTEN_KERNEL)
1625 len = udhcp_recv_kernel_packet(&packet, client_data.sockfd);
1626 else
1627 len = d4_recv_raw_packet(&packet, client_data.sockfd);
1628 if (len == -1) {
1629
1630 bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO);
1631 sleep(discover_timeout);
1632 change_listen_mode(client_data.listen_mode);
1633 }
1634 if (len < 0)
1635 continue;
1636 }
1637
1638 if (packet.xid != client_data.xid) {
1639 log1("xid %x (our is %x)%s",
1640 (unsigned)packet.xid, (unsigned)client_data.xid,
1641 ", ignoring packet"
1642 );
1643 continue;
1644 }
1645
1646
1647 if (packet.hlen != 6
1648 || memcmp(packet.chaddr, client_data.client_mac, 6) != 0
1649 ) {
1650
1651 log1("chaddr does not match%s", ", ignoring packet");
1652 continue;
1653 }
1654
1655 message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
1656 if (message == NULL) {
1657 log1("no message type option%s", ", ignoring packet");
1658 continue;
1659 }
1660
1661 switch (client_data.state) {
1662 case INIT_SELECTING:
1663
1664 if (*message == DHCPOFFER) {
1665 struct in_addr temp_addr;
1666 uint8_t *temp;
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692 server_id = 0;
1693 temp = udhcp_get_option32(&packet, DHCP_SERVER_ID);
1694 if (!temp) {
1695 bb_simple_info_msg("no server ID, using 0.0.0.0");
1696 } else {
1697
1698 move_from_unaligned32(server_id, temp);
1699 }
1700
1701 temp_addr.s_addr = requested_ip = packet.yiaddr;
1702 log1("received offer of %s", inet_ntoa(temp_addr));
1703
1704
1705 client_data.state = REQUESTING;
1706 timeout = 0;
1707 packet_num = 0;
1708 }
1709 continue;
1710 case REQUESTING:
1711 case RENEWING:
1712 case RENEW_REQUESTED:
1713 case REBINDING:
1714 if (*message == DHCPACK) {
1715 unsigned start;
1716 struct in_addr temp_addr;
1717 char server_str[sizeof("255.255.255.255")];
1718 uint8_t *temp;
1719
1720 change_listen_mode(LISTEN_NONE);
1721
1722 temp_addr.s_addr = server_id;
1723 strcpy(server_str, inet_ntoa(temp_addr));
1724 temp_addr.s_addr = packet.yiaddr;
1725
1726 lease_remaining = 60 * 60;
1727 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
1728 if (temp) {
1729 uint32_t lease;
1730
1731 move_from_unaligned32(lease, temp);
1732 lease_remaining = ntohl(lease);
1733 }
1734
1735 bb_info_msg("lease of %s obtained from %s, lease time %u%s",
1736 inet_ntoa(temp_addr), server_str, (unsigned)lease_remaining,
1737 temp ? "" : " (default)"
1738 );
1739
1740
1741
1742
1743
1744 if (lease_remaining < 0)
1745 lease_remaining = INT_MAX;
1746 if (lease_remaining < 30)
1747 lease_remaining = 30;
1748 requested_ip = packet.yiaddr;
1749#if ENABLE_FEATURE_UDHCPC_ARPING
1750 if (opt & OPT_a) {
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760 if (!arpping(requested_ip,
1761 NULL,
1762 (uint32_t) 0,
1763 client_data.client_mac,
1764 client_data.interface,
1765 arpping_ms)
1766 ) {
1767 bb_simple_info_msg("offered address is in use "
1768 "(got ARP reply), declining");
1769 client_data.xid = random_xid();
1770 send_decline(server_id, packet.yiaddr);
1771
1772 if (client_data.state != REQUESTING)
1773 d4_run_script_deconfig();
1774 client_data.state = INIT_SELECTING;
1775 client_data.first_secs = 0;
1776 requested_ip = 0;
1777 timeout = tryagain_timeout;
1778 packet_num = 0;
1779 continue;
1780 }
1781 }
1782#endif
1783
1784 start = monotonic_sec();
1785 d4_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
1786 lease_remaining -= (unsigned)monotonic_sec() - start;
1787 if (lease_remaining < 0)
1788 lease_remaining = 0;
1789 if (opt & OPT_q) {
1790 goto ret0;
1791 }
1792
1793 opt &= ~OPT_n;
1794#if BB_MMU
1795 if (!(opt & OPT_f)) {
1796 client_background();
1797
1798 opt = ((opt & ~OPT_b) | OPT_f);
1799 }
1800#endif
1801 BOUND_for_half_lease:
1802 timeout = (unsigned)lease_remaining / 2;
1803 client_data.state = BOUND;
1804
1805
1806 packet_num = 0;
1807 continue;
1808 }
1809 if (*message == DHCPNAK) {
1810
1811
1812
1813
1814 uint32_t svid = 0;
1815 uint8_t *temp = udhcp_get_option32(&packet, DHCP_SERVER_ID);
1816 if (temp)
1817 move_from_unaligned32(svid, temp);
1818 if (svid != server_id) {
1819 log1("received DHCP NAK with wrong"
1820 " server ID%s", ", ignoring packet");
1821 continue;
1822 }
1823
1824 change_listen_mode(LISTEN_NONE);
1825 bb_info_msg("received %s", "DHCP NAK");
1826 d4_run_script(&packet, "nak");
1827 if (client_data.state != REQUESTING)
1828 d4_run_script_deconfig();
1829 sleep(3);
1830 client_data.state = INIT_SELECTING;
1831 client_data.first_secs = 0;
1832 requested_ip = 0;
1833 timeout = 0;
1834 packet_num = 0;
1835 }
1836 continue;
1837
1838
1839 }
1840
1841 }
1842
1843 ret0:
1844 if (opt & OPT_R)
1845 perform_release(server_id, requested_ip);
1846 retval = 0;
1847 ret:
1848
1849 remove_pidfile(client_data.pidfile);
1850 return retval;
1851}
1852