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