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