udhcp6: fix releasing
[oweals/busybox.git] / networking / udhcp / d6_dhcpc.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * DHCPv6 client.
4  *
5  * 2011-11.
6  * WARNING: THIS CODE IS INCOMPLETE. IT IS NOWHERE NEAR
7  * TO BE READY FOR PRODUCTION USE.
8  *
9  * Copyright (C) 2011 Denys Vlasenko.
10  *
11  * Licensed under GPLv2, see file LICENSE in this source tree.
12  */
13
14 //config:config UDHCPC6
15 //config:       bool "udhcpc6 (DHCPv6 client, NOT READY)"
16 //config:       default n  # not yet ready
17 //config:       depends on FEATURE_IPV6
18 //config:       help
19 //config:         udhcpc6 is a DHCPv6 client
20
21 //applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP))
22
23 //kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o socket.o signalpipe.o
24
25
26 #include <syslog.h>
27 /* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */
28 #define WANT_PIDFILE 1
29 #include "common.h"
30 #include "dhcpd.h"
31 #include "dhcpc.h"
32 #include "d6_common.h"
33
34 #include <netinet/if_ether.h>
35 #include <netpacket/packet.h>
36 #include <linux/filter.h>
37
38 /* "struct client_config_t client_config" is in bb_common_bufsiz1 */
39
40
41 #if ENABLE_LONG_OPTS
42 static const char udhcpc6_longopts[] ALIGN1 =
43         "interface\0"      Required_argument "i"
44         "now\0"            No_argument       "n"
45         "pidfile\0"        Required_argument "p"
46         "quit\0"           No_argument       "q"
47         "release\0"        No_argument       "R"
48         "request\0"        Required_argument "r"
49         "script\0"         Required_argument "s"
50         "timeout\0"        Required_argument "T"
51         "retries\0"        Required_argument "t"
52         "tryagain\0"       Required_argument "A"
53         "syslog\0"         No_argument       "S"
54         "request-option\0" Required_argument "O"
55         "no-default-options\0" No_argument   "o"
56         "foreground\0"     No_argument       "f"
57         "background\0"     No_argument       "b"
58 ///     IF_FEATURE_UDHCPC_ARPING("arping\0"     No_argument       "a")
59         IF_FEATURE_UDHCP_PORT("client-port\0"   Required_argument "P")
60         ;
61 #endif
62 /* Must match getopt32 option string order */
63 enum {
64         OPT_i = 1 << 0,
65         OPT_n = 1 << 1,
66         OPT_p = 1 << 2,
67         OPT_q = 1 << 3,
68         OPT_R = 1 << 4,
69         OPT_r = 1 << 5,
70         OPT_s = 1 << 6,
71         OPT_T = 1 << 7,
72         OPT_t = 1 << 8,
73         OPT_S = 1 << 9,
74         OPT_A = 1 << 10,
75         OPT_O = 1 << 11,
76         OPT_o = 1 << 12,
77         OPT_x = 1 << 13,
78         OPT_f = 1 << 14,
79 /* The rest has variable bit positions, need to be clever */
80         OPTBIT_f = 14,
81         USE_FOR_MMU(             OPTBIT_b,)
82         ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
83         IF_FEATURE_UDHCP_PORT(   OPTBIT_P,)
84         USE_FOR_MMU(             OPT_b = 1 << OPTBIT_b,)
85         ///IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
86         IF_FEATURE_UDHCP_PORT(   OPT_P = 1 << OPTBIT_P,)
87 };
88
89 static const char opt_req[] = {
90         (D6_OPT_ORO >> 8), (D6_OPT_ORO & 0xff),
91         0, 6,
92         (D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xff),
93         (D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xff),
94         (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff)
95 };
96
97 static const char opt_fqdn_req[] = {
98         (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff),
99         0, 2,
100         0, 0
101 };
102
103 /*** Utility functions ***/
104
105 static void *d6_find_option(uint8_t *option, uint8_t *option_end, unsigned code)
106 {
107         /* "length minus 4" */
108         int len_m4 = option_end - option - 4;
109         while (len_m4 >= 0) {
110                 /* Next option's len is too big? */
111                 if (option[3] > len_m4)
112                         return NULL; /* yes. bogus packet! */
113                 /* So far we treat any opts with code >255
114                  * or len >255 as bogus, and stop at once.
115                  * This simplifies big-endian handling.
116                  */
117                 if (option[0] != 0 || option[2] != 0)
118                         return NULL;
119                 /* Option seems to be valid */
120                 /* Does its code match? */
121                 if (option[1] == code)
122                         return option; /* yes! */
123                 len_m4 -= option[3] + 4;
124                 option += option[3] + 4;
125         }
126         return NULL;
127 }
128
129 static void *d6_copy_option(uint8_t *option, uint8_t *option_end, unsigned code)
130 {
131         uint8_t *opt = d6_find_option(option, option_end, code);
132         if (!opt)
133                 return opt;
134         return xmemdup(opt, opt[3] + 4);
135 }
136
137 static void *d6_store_blob(void *dst, const void *src, unsigned len)
138 {
139         memcpy(dst, src, len);
140         return dst + len;
141 }
142
143
144 /*** Script execution code ***/
145
146 static char** new_env(void)
147 {
148         client6_data.env_ptr = xrealloc_vector(client6_data.env_ptr, 3, client6_data.env_idx);
149         return &client6_data.env_ptr[client6_data.env_idx++];
150 }
151
152 /* put all the parameters into the environment */
153 static void option_to_env(uint8_t *option, uint8_t *option_end)
154 {
155         /* "length minus 4" */
156         char *dlist, *ptr;
157         int len_m4 = option_end - option - 4;
158         int olen, ooff;
159         while (len_m4 >= 0) {
160                 uint32_t v32;
161                 char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
162
163                 if (option[0] != 0 || option[2] != 0)
164                         break;
165
166                 switch (option[1]) {
167                 //case D6_OPT_CLIENTID:
168                 //case D6_OPT_SERVERID:
169                 case D6_OPT_IA_NA:
170                 case D6_OPT_IA_PD:
171                         option_to_env(option + 16, option + 4 + option[3]);
172                         break;
173                 //case D6_OPT_IA_TA:
174                 case D6_OPT_IAADDR:
175 /*   0                   1                   2                   3
176  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
177  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178  * |          OPTION_IAADDR        |          option-len           |
179  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180  * |                                                               |
181  * |                         IPv6 address                          |
182  * |                                                               |
183  * |                                                               |
184  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
185  * |                      preferred-lifetime                       |
186  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187  * |                        valid-lifetime                         |
188  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
189  */
190                         sprint_nip6(ipv6str, option + 4);
191                         *new_env() = xasprintf("ipv6=%s", ipv6str);
192
193                         move_from_unaligned32(v32, option + 4 + 16 + 4);
194                         *new_env() = xasprintf("lease=%u", (unsigned)v32);
195                         break;
196
197                 //case D6_OPT_ORO:
198                 //case D6_OPT_PREFERENCE:
199                 //case D6_OPT_ELAPSED_TIME:
200                 //case D6_OPT_RELAY_MSG:
201                 //case D6_OPT_AUTH:
202                 //case D6_OPT_UNICAST:
203                 //case D6_OPT_STATUS_CODE:
204                 //case D6_OPT_RAPID_COMMIT:
205                 //case D6_OPT_USER_CLASS:
206                 //case D6_OPT_VENDOR_CLASS:
207                 //case D6_OPT_VENDOR_OPTS:
208                 //case D6_OPT_INTERFACE_ID:
209                 //case D6_OPT_RECONF_MSG:
210                 //case D6_OPT_RECONF_ACCEPT:
211
212                 case D6_OPT_IAPREFIX:
213 /*  0                   1                   2                   3
214  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
215  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216  * |        OPTION_IAPREFIX        |         option-length         |
217  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
218  * |                      preferred-lifetime                       |
219  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
220  * |                        valid-lifetime                         |
221  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
222  * | prefix-length |                                               |
223  * +-+-+-+-+-+-+-+-+          IPv6 prefix                          |
224  * |                           (16 octets)                         |
225  * |                                                               |
226  * |               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
227  * |               |
228  * +-+-+-+-+-+-+-+-+
229  */
230                         //move_from_unaligned32(v32, option + 4 + 4);
231                         //*new_env() = xasprintf("lease=%u", (unsigned)v32);
232
233                         sprint_nip6(ipv6str, option + 4 + 4 + 1);
234                         *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
235                         break;
236                 case D6_OPT_DNS_SERVERS:
237                         olen = ((option[2] << 8) | option[3]) / 16;
238                         dlist = ptr = malloc (4 + olen * 40 - 1);
239
240                         memcpy (ptr, "dns=", 4);
241                         ptr += 4;
242                         ooff = 0;
243
244                         while (olen--) {
245                                 sprint_nip6(ptr, option + 4 + ooff);
246                                 ptr += 39;
247                                 ooff += 16;
248                                 if (olen)
249                                         *ptr++ = ' ';
250                         }
251
252                         *new_env() = dlist;
253
254                         break;
255                 case D6_OPT_DOMAIN_LIST:
256                         dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search=");
257                         if (!dlist)
258                                 break;
259                         *new_env() = dlist;
260                         break;
261                 case D6_OPT_CLIENT_FQDN:
262                         // Work around broken ISC DHCPD6
263                         if (option[4] & 0xf8) {
264                                 olen = ((option[2] << 8) | option[3]);
265                                 dlist = xmalloc(olen);
266 //fixme:
267 //- explain
268 //- add len error check
269 //- merge two allocs into one
270                                 memcpy(dlist, option + 4, olen);
271                                 *new_env() = xasprintf("fqdn=%s", dlist);
272                                 free(dlist);
273                                 break;
274                         }
275                         dlist = dname_dec(option + 5, ((option[2] << 8) | option[3]) - 1, "fqdn=");
276                         if (!dlist)
277                                 break;
278                         *new_env() = dlist;
279                         break;
280                 }
281                 len_m4 -= 4 + option[3];
282                 option += 4 + option[3];
283         }
284 }
285
286 static char **fill_envp(struct d6_packet *packet)
287 {
288         char **envp, **curr;
289
290         client6_data.env_ptr = NULL;
291         client6_data.env_idx = 0;
292
293         *new_env() = xasprintf("interface=%s", client_config.interface);
294
295         if (packet)
296                 option_to_env(packet->d6_options, packet->d6_options + sizeof(packet->d6_options));
297
298         envp = curr = client6_data.env_ptr;
299         while (*curr)
300                 putenv(*curr++);
301
302         return envp;
303 }
304
305 /* Call a script with a par file and env vars */
306 static void d6_run_script(struct d6_packet *packet, const char *name)
307 {
308         char **envp, **curr;
309         char *argv[3];
310
311         envp = fill_envp(packet);
312
313         /* call script */
314         log1("executing %s %s", client_config.script, name);
315         argv[0] = (char*) client_config.script;
316         argv[1] = (char*) name;
317         argv[2] = NULL;
318         spawn_and_wait(argv);
319
320         for (curr = envp; *curr; curr++) {
321                 log2(" %s", *curr);
322                 bb_unsetenv_and_free(*curr);
323         }
324         free(envp);
325 }
326
327
328 /*** Sending/receiving packets ***/
329
330 static ALWAYS_INLINE uint32_t random_xid(void)
331 {
332         uint32_t t = rand() & htonl(0x00ffffff);
333         return t;
334 }
335
336 /* Initialize the packet with the proper defaults */
337 static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid)
338 {
339         struct d6_option *clientid;
340
341         memset(packet, 0, sizeof(*packet));
342
343         packet->d6_xid32 = xid;
344         packet->d6_msg_type = type;
345
346         clientid = (void*)client_config.clientid;
347         return d6_store_blob(packet->d6_options, clientid, clientid->len + 2+2);
348 }
349
350 static uint8_t *add_d6_client_options(uint8_t *ptr)
351 {
352         return ptr;
353         //uint8_t c;
354         //int i, end, len;
355
356         /* Add a "param req" option with the list of options we'd like to have
357          * from stubborn DHCP servers. Pull the data from the struct in common.c.
358          * No bounds checking because it goes towards the head of the packet. */
359         //...
360
361         /* Add -x options if any */
362         //...
363 }
364
365 static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t *end)
366 {
367         static const uint8_t FF02__1_2[16] = {
368                 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369                 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
370         };
371
372         return d6_send_raw_packet(
373                 packet, (end - (uint8_t*) packet),
374                 /*src*/ &client6_data.ll_ip6, CLIENT_PORT6,
375                 /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR,
376                 client_config.ifindex
377         );
378 }
379
380 /* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP.
381  *
382  * RFC 3315 17.1.1. Creation of Solicit Messages
383  *
384  * The client MUST include a Client Identifier option to identify itself
385  * to the server.  The client includes IA options for any IAs to which
386  * it wants the server to assign addresses.  The client MAY include
387  * addresses in the IAs as a hint to the server about addresses for
388  * which the client has a preference. ...
389  *
390  * The client uses IA_NA options to request the assignment of non-
391  * temporary addresses and uses IA_TA options to request the assignment
392  * of temporary addresses.  Either IA_NA or IA_TA options, or a
393  * combination of both, can be included in DHCP messages.
394  *
395  * The client SHOULD include an Option Request option (see section 22.7)
396  * to indicate the options the client is interested in receiving.  The
397  * client MAY additionally include instances of those options that are
398  * identified in the Option Request option, with data values as hints to
399  * the server about parameter values the client would like to have
400  * returned.
401  *
402  * The client includes a Reconfigure Accept option (see section 22.20)
403  * if the client is willing to accept Reconfigure messages from the
404  * server.
405       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
406       |        OPTION_CLIENTID        |          option-len           |
407       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408       .                                                               .
409       .                              DUID                             .
410       .                        (variable length)                      .
411       .                                                               .
412       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
413
414
415       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416       |          OPTION_IA_NA         |          option-len           |
417       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
418       |                        IAID (4 octets)                        |
419       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420       |                              T1                               |
421       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
422       |                              T2                               |
423       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
424       |                                                               |
425       .                         IA_NA-options                         .
426       .                                                               .
427       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
428
429
430       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
431       |          OPTION_IAADDR        |          option-len           |
432       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
433       |                                                               |
434       |                         IPv6 address                          |
435       |                                                               |
436       |                                                               |
437       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
438       |                      preferred-lifetime                       |
439       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
440       |                        valid-lifetime                         |
441       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
442       .                                                               .
443       .                        IAaddr-options                         .
444       .                                                               .
445       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
446
447
448       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
449       |           OPTION_ORO          |           option-len          |
450       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
451       |    requested-option-code-1    |    requested-option-code-2    |
452       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
453       |                              ...                              |
454       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
455
456
457       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458       |     OPTION_RECONF_ACCEPT      |               0               |
459       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460  */
461 /* NOINLINE: limit stack usage in caller */
462 static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ipv6)
463 {
464         struct d6_packet packet;
465         uint8_t *opt_ptr;
466         unsigned len;
467
468         /* Fill in: msg type, client id */
469         opt_ptr = init_d6_packet(&packet, D6_MSG_SOLICIT, xid);
470
471         /* Create new IA_NA, optionally with included IAADDR with requested IP */
472         free(client6_data.ia_na);
473         len = requested_ipv6 ? 2+2+4+4+4 + 2+2+16+4+4 : 2+2+4+4+4;
474         client6_data.ia_na = xzalloc(len);
475         client6_data.ia_na->code = D6_OPT_IA_NA;
476         client6_data.ia_na->len = len - 4;
477         *(uint32_t*)client6_data.ia_na->data = rand(); /* IAID */
478         if (requested_ipv6) {
479                 struct d6_option *iaaddr = (void*)(client6_data.ia_na->data + 4+4+4);
480                 iaaddr->code = D6_OPT_IAADDR;
481                 iaaddr->len = 16+4+4;
482                 memcpy(iaaddr->data, requested_ipv6, 16);
483         }
484         opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, len);
485
486         /* Request additional options */
487         opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
488         opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
489
490         /* Add options:
491          * "param req" option according to -O, options specified with -x
492          */
493         opt_ptr = add_d6_client_options(opt_ptr);
494
495         bb_error_msg("sending %s", "discover");
496         return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
497 }
498
499 /* Multicast a DHCPv6 request message
500  *
501  * RFC 3315 18.1.1. Creation and Transmission of Request Messages
502  *
503  * The client uses a Request message to populate IAs with addresses and
504  * obtain other configuration information.  The client includes one or
505  * more IA options in the Request message.  The server then returns
506  * addresses and other information about the IAs to the client in IA
507  * options in a Reply message.
508  *
509  * The client generates a transaction ID and inserts this value in the
510  * "transaction-id" field.
511  *
512  * The client places the identifier of the destination server in a
513  * Server Identifier option.
514  *
515  * The client MUST include a Client Identifier option to identify itself
516  * to the server.  The client adds any other appropriate options,
517  * including one or more IA options (if the client is requesting that
518  * the server assign it some network addresses).
519  *
520  * The client MUST include an Option Request option (see section 22.7)
521  * to indicate the options the client is interested in receiving.  The
522  * client MAY include options with data values as hints to the server
523  * about parameter values the client would like to have returned.
524  *
525  * The client includes a Reconfigure Accept option (see section 22.20)
526  * indicating whether or not the client is willing to accept Reconfigure
527  * messages from the server.
528  */
529 /* NOINLINE: limit stack usage in caller */
530 static NOINLINE int send_d6_select(uint32_t xid)
531 {
532         struct d6_packet packet;
533         uint8_t *opt_ptr;
534
535         /* Fill in: msg type, client id */
536         opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid);
537
538         /* server id */
539         opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
540         /* IA NA (contains requested IP) */
541         opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
542
543         /* Request additional options */
544         opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
545         opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
546
547         /* Add options:
548          * "param req" option according to -O, options specified with -x
549          */
550         opt_ptr = add_d6_client_options(opt_ptr);
551
552         bb_error_msg("sending %s", "select");
553         return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
554 }
555
556 /* Unicast or broadcast a DHCP renew message
557  *
558  * RFC 3315 18.1.3. Creation and Transmission of Renew Messages
559  *
560  * To extend the valid and preferred lifetimes for the addresses
561  * associated with an IA, the client sends a Renew message to the server
562  * from which the client obtained the addresses in the IA containing an
563  * IA option for the IA.  The client includes IA Address options in the
564  * IA option for the addresses associated with the IA.  The server
565  * determines new lifetimes for the addresses in the IA according to the
566  * administrative configuration of the server.  The server may also add
567  * new addresses to the IA.  The server may remove addresses from the IA
568  * by setting the preferred and valid lifetimes of those addresses to
569  * zero.
570  *
571  * The server controls the time at which the client contacts the server
572  * to extend the lifetimes on assigned addresses through the T1 and T2
573  * parameters assigned to an IA.
574  *
575  * At time T1 for an IA, the client initiates a Renew/Reply message
576  * exchange to extend the lifetimes on any addresses in the IA.  The
577  * client includes an IA option with all addresses currently assigned to
578  * the IA in its Renew message.
579  *
580  * If T1 or T2 is set to 0 by the server (for an IA_NA) or there are no
581  * T1 or T2 times (for an IA_TA), the client may send a Renew or Rebind
582  * message, respectively, at the client's discretion.
583  *
584  * The client sets the "msg-type" field to RENEW.  The client generates
585  * a transaction ID and inserts this value in the "transaction-id"
586  * field.
587  *
588  * The client places the identifier of the destination server in a
589  * Server Identifier option.
590  *
591  * The client MUST include a Client Identifier option to identify itself
592  * to the server.  The client adds any appropriate options, including
593  * one or more IA options.  The client MUST include the list of
594  * addresses the client currently has associated with the IAs in the
595  * Renew message.
596  *
597  * The client MUST include an Option Request option (see section 22.7)
598  * to indicate the options the client is interested in receiving.  The
599  * client MAY include options with data values as hints to the server
600  * about parameter values the client would like to have returned.
601  */
602 /* NOINLINE: limit stack usage in caller */
603 static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
604 {
605         struct d6_packet packet;
606         uint8_t *opt_ptr;
607
608         /* Fill in: msg type, client id */
609         opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid);
610
611         /* server id */
612         opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
613         /* IA NA (contains requested IP) */
614         opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
615
616         /* Add options:
617          * "param req" option according to -O, options specified with -x
618          */
619         opt_ptr = add_d6_client_options(opt_ptr);
620
621         bb_error_msg("sending %s", "renew");
622         if (server_ipv6)
623                 return d6_send_kernel_packet(
624                         &packet, (opt_ptr - (uint8_t*) &packet),
625                         our_cur_ipv6, CLIENT_PORT6,
626                         server_ipv6, SERVER_PORT6,
627                         client_config.ifindex
628                 );
629         return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
630 }
631
632 /* Unicast a DHCP release message */
633 static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
634 {
635         struct d6_packet packet;
636         uint8_t *opt_ptr;
637
638         /* Fill in: msg type, client id */
639         opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid());
640         /* server id */
641         opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
642         /* IA NA (contains our current IP) */
643         opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
644
645         bb_error_msg("sending %s", "release");
646         return d6_send_kernel_packet(
647                 &packet, (opt_ptr - (uint8_t*) &packet),
648                 our_cur_ipv6, CLIENT_PORT6,
649                 server_ipv6, SERVER_PORT6,
650                 client_config.ifindex
651         );
652 }
653
654 /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
655 /* NOINLINE: limit stack usage in caller */
656 static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct d6_packet *d6_pkt, int fd)
657 {
658         int bytes;
659         struct ip6_udp_d6_packet packet;
660
661         bytes = safe_read(fd, &packet, sizeof(packet));
662         if (bytes < 0) {
663                 log1("packet read error, ignoring");
664                 /* NB: possible down interface, etc. Caller should pause. */
665                 return bytes; /* returns -1 */
666         }
667
668         if (bytes < (int) (sizeof(packet.ip6) + sizeof(packet.udp))) {
669                 log1("packet is too short, ignoring");
670                 return -2;
671         }
672
673         if (bytes < sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen)) {
674                 /* packet is bigger than sizeof(packet), we did partial read */
675                 log1("oversized packet, ignoring");
676                 return -2;
677         }
678
679         /* ignore any extra garbage bytes */
680         bytes = sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen);
681
682         /* make sure its the right packet for us, and that it passes sanity checks */
683         if (packet.ip6.ip6_nxt != IPPROTO_UDP
684          || (packet.ip6.ip6_vfc >> 4) != 6
685          || packet.udp.dest != htons(CLIENT_PORT6)
686         /* || bytes > (int) sizeof(packet) - can't happen */
687          || packet.udp.len != packet.ip6.ip6_plen
688         ) {
689                 log1("unrelated/bogus packet, ignoring");
690                 return -2;
691         }
692
693 //How to do this for ipv6?
694 //      /* verify UDP checksum. IP header has to be modified for this */
695 //      memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
696 //      /* ip.xx fields which are not memset: protocol, check, saddr, daddr */
697 //      packet.ip.tot_len = packet.udp.len; /* yes, this is needed */
698 //      check = packet.udp.check;
699 //      packet.udp.check = 0;
700 //      if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
701 //              log1("packet with bad UDP checksum received, ignoring");
702 //              return -2;
703 //      }
704
705         if (peer_ipv6)
706                 *peer_ipv6 = packet.ip6.ip6_src; /* struct copy */
707
708         log1("received %s", "a packet");
709         d6_dump_packet(&packet.data);
710
711         bytes -= sizeof(packet.ip6) + sizeof(packet.udp);
712         memcpy(d6_pkt, &packet.data, bytes);
713         return bytes;
714 }
715
716
717 /*** Main ***/
718
719 static int sockfd = -1;
720
721 #define LISTEN_NONE   0
722 #define LISTEN_KERNEL 1
723 #define LISTEN_RAW    2
724 static smallint listen_mode;
725
726 /* initial state: (re)start DHCP negotiation */
727 #define INIT_SELECTING  0
728 /* discover was sent, DHCPOFFER reply received */
729 #define REQUESTING      1
730 /* select/renew was sent, DHCPACK reply received */
731 #define BOUND           2
732 /* half of lease passed, want to renew it by sending unicast renew requests */
733 #define RENEWING        3
734 /* renew requests were not answered, lease is almost over, send broadcast renew */
735 #define REBINDING       4
736 /* manually requested renew (SIGUSR1) */
737 #define RENEW_REQUESTED 5
738 /* release, possibly manually requested (SIGUSR2) */
739 #define RELEASED        6
740 static smallint state;
741
742 static int d6_raw_socket(int ifindex)
743 {
744         int fd;
745         struct sockaddr_ll sock;
746
747         /*
748          * Comment:
749          *
750          *      I've selected not to see LL header, so BPF doesn't see it, too.
751          *      The filter may also pass non-IP and non-ARP packets, but we do
752          *      a more complete check when receiving the message in userspace.
753          *
754          * and filter shamelessly stolen from:
755          *
756          *      http://www.flamewarmaster.de/software/dhcpclient/
757          *
758          * There are a few other interesting ideas on that page (look under
759          * "Motivation").  Use of netlink events is most interesting.  Think
760          * of various network servers listening for events and reconfiguring.
761          * That would obsolete sending HUP signals and/or make use of restarts.
762          *
763          * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>.
764          * License: GPL v2.
765          *
766          * TODO: make conditional?
767          */
768 #if 0
769         static const struct sock_filter filter_instr[] = {
770                 /* load 9th byte (protocol) */
771                 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
772                 /* jump to L1 if it is IPPROTO_UDP, else to L4 */
773                 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
774                 /* L1: load halfword from offset 6 (flags and frag offset) */
775                 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
776                 /* jump to L4 if any bits in frag offset field are set, else to L2 */
777                 BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
778                 /* L2: skip IP header (load index reg with header len) */
779                 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
780                 /* load udp destination port from halfword[header_len + 2] */
781                 BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
782                 /* jump to L3 if udp dport is CLIENT_PORT6, else to L4 */
783                 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
784                 /* L3: accept packet */
785                 BPF_STMT(BPF_RET|BPF_K, 0x7fffffff),
786                 /* L4: discard packet */
787                 BPF_STMT(BPF_RET|BPF_K, 0),
788         };
789         static const struct sock_fprog filter_prog = {
790                 .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
791                 /* casting const away: */
792                 .filter = (struct sock_filter *) filter_instr,
793         };
794 #endif
795
796         log1("opening raw socket on ifindex %d", ifindex); //log2?
797
798         fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
799         log1("got raw socket fd %d", fd); //log2?
800
801         sock.sll_family = AF_PACKET;
802         sock.sll_protocol = htons(ETH_P_IPV6);
803         sock.sll_ifindex = ifindex;
804         xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
805
806 #if 0
807         if (CLIENT_PORT6 == 546) {
808                 /* Use only if standard port is in use */
809                 /* Ignoring error (kernel may lack support for this) */
810                 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
811                                 sizeof(filter_prog)) >= 0)
812                         log1("attached filter to raw socket fd %d", fd); // log?
813         }
814 #endif
815
816         log1("created raw socket");
817
818         return fd;
819 }
820
821 static void change_listen_mode(int new_mode)
822 {
823         log1("entering listen mode: %s",
824                 new_mode != LISTEN_NONE
825                         ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
826                         : "none"
827         );
828
829         listen_mode = new_mode;
830         if (sockfd >= 0) {
831                 close(sockfd);
832                 sockfd = -1;
833         }
834         if (new_mode == LISTEN_KERNEL)
835                 sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_config.interface);
836         else if (new_mode != LISTEN_NONE)
837                 sockfd = d6_raw_socket(client_config.ifindex);
838         /* else LISTEN_NONE: sockfd stays closed */
839 }
840
841 /* Called only on SIGUSR1 */
842 static void perform_renew(void)
843 {
844         bb_error_msg("performing DHCP renew");
845         switch (state) {
846         case BOUND:
847                 change_listen_mode(LISTEN_KERNEL);
848         case RENEWING:
849         case REBINDING:
850                 state = RENEW_REQUESTED;
851                 break;
852         case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
853                 d6_run_script(NULL, "deconfig");
854         case REQUESTING:
855         case RELEASED:
856                 change_listen_mode(LISTEN_RAW);
857                 state = INIT_SELECTING;
858                 break;
859         case INIT_SELECTING:
860                 break;
861         }
862 }
863
864 static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
865 {
866         /* send release packet */
867         if (state == BOUND
868          || state == RENEWING
869          || state == REBINDING
870          || state == RENEW_REQUESTED
871         ) {
872                 bb_error_msg("unicasting a release");
873                 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */
874         }
875         bb_error_msg("entering released state");
876 /*
877  * We can be here on: SIGUSR2,
878  * or on exit (SIGTERM) and -R "release on quit" is specified.
879  * Users requested to be notified in all cases, even if not in one
880  * of the states above.
881  */
882         d6_run_script(NULL, "deconfig");
883         change_listen_mode(LISTEN_NONE);
884         state = RELEASED;
885 }
886
887 ///static uint8_t* alloc_dhcp_option(int code, const char *str, int extra)
888 ///{
889 ///     uint8_t *storage;
890 ///     int len = strnlen(str, 255);
891 ///     storage = xzalloc(len + extra + OPT_DATA);
892 ///     storage[OPT_CODE] = code;
893 ///     storage[OPT_LEN] = len + extra;
894 ///     memcpy(storage + extra + OPT_DATA, str, len);
895 ///     return storage;
896 ///}
897
898 #if BB_MMU
899 static void client_background(void)
900 {
901         bb_daemonize(0);
902         logmode &= ~LOGMODE_STDIO;
903         /* rewrite pidfile, as our pid is different now */
904         write_pidfile(client_config.pidfile);
905 }
906 #endif
907
908 //usage:#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
909 //usage:# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
910 //usage:#else
911 //usage:# define IF_UDHCP_VERBOSE(...)
912 //usage:#endif
913 //usage:#define udhcpc6_trivial_usage
914 //usage:       "[-fbnq"IF_UDHCP_VERBOSE("v")"oR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
915 //usage:       "        [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
916 //usage:#define udhcpc6_full_usage "\n"
917 //usage:        IF_LONG_OPTS(
918 //usage:     "\n        -i,--interface IFACE    Interface to use (default eth0)"
919 //usage:     "\n        -p,--pidfile FILE       Create pidfile"
920 //usage:     "\n        -s,--script PROG        Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
921 //usage:     "\n        -B,--broadcast          Request broadcast replies"
922 //usage:     "\n        -t,--retries N          Send up to N discover packets"
923 //usage:     "\n        -T,--timeout N          Pause between packets (default 3 seconds)"
924 //usage:     "\n        -A,--tryagain N         Wait N seconds after failure (default 20)"
925 //usage:     "\n        -f,--foreground         Run in foreground"
926 //usage:        USE_FOR_MMU(
927 //usage:     "\n        -b,--background         Background if lease is not obtained"
928 //usage:        )
929 //usage:     "\n        -n,--now                Exit if lease is not obtained"
930 //usage:     "\n        -q,--quit               Exit after obtaining lease"
931 //usage:     "\n        -R,--release            Release IP on exit"
932 //usage:     "\n        -S,--syslog             Log to syslog too"
933 //usage:        IF_FEATURE_UDHCP_PORT(
934 //usage:     "\n        -P,--client-port N      Use port N (default 546)"
935 //usage:        )
936 ////usage:      IF_FEATURE_UDHCPC_ARPING(
937 ////usage:     "\n      -a,--arping             Use arping to validate offered address"
938 ////usage:      )
939 //usage:     "\n        -O,--request-option OPT Request option OPT from server (cumulative)"
940 //usage:     "\n        -o,--no-default-options Don't request any options (unless -O is given)"
941 //usage:     "\n        -r,--request IP         Request this IP address"
942 //usage:     "\n        -x OPT:VAL              Include option OPT in sent packets (cumulative)"
943 //usage:     "\n                                Examples of string, numeric, and hex byte opts:"
944 //usage:     "\n                                -x hostname:bbox - option 12"
945 //usage:     "\n                                -x lease:3600 - option 51 (lease time)"
946 //usage:     "\n                                -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
947 //usage:        IF_UDHCP_VERBOSE(
948 //usage:     "\n        -v                      Verbose"
949 //usage:        )
950 //usage:        )
951 //usage:        IF_NOT_LONG_OPTS(
952 //usage:     "\n        -i IFACE        Interface to use (default eth0)"
953 //usage:     "\n        -p FILE         Create pidfile"
954 //usage:     "\n        -s PROG         Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
955 //usage:     "\n        -B              Request broadcast replies"
956 //usage:     "\n        -t N            Send up to N discover packets"
957 //usage:     "\n        -T N            Pause between packets (default 3 seconds)"
958 //usage:     "\n        -A N            Wait N seconds (default 20) after failure"
959 //usage:     "\n        -f              Run in foreground"
960 //usage:        USE_FOR_MMU(
961 //usage:     "\n        -b              Background if lease is not obtained"
962 //usage:        )
963 //usage:     "\n        -n              Exit if lease is not obtained"
964 //usage:     "\n        -q              Exit after obtaining lease"
965 //usage:     "\n        -R              Release IP on exit"
966 //usage:     "\n        -S              Log to syslog too"
967 //usage:        IF_FEATURE_UDHCP_PORT(
968 //usage:     "\n        -P N            Use port N (default 546)"
969 //usage:        )
970 ////usage:      IF_FEATURE_UDHCPC_ARPING(
971 ////usage:     "\n      -a              Use arping to validate offered address"
972 ////usage:      )
973 //usage:     "\n        -O OPT          Request option OPT from server (cumulative)"
974 //usage:     "\n        -o              Don't request any options (unless -O is given)"
975 //usage:     "\n        -r IP           Request this IP address"
976 //usage:     "\n        -x OPT:VAL      Include option OPT in sent packets (cumulative)"
977 //usage:     "\n                        Examples of string, numeric, and hex byte opts:"
978 //usage:     "\n                        -x hostname:bbox - option 12"
979 //usage:     "\n                        -x lease:3600 - option 51 (lease time)"
980 //usage:     "\n                        -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
981 //usage:        IF_UDHCP_VERBOSE(
982 //usage:     "\n        -v              Verbose"
983 //usage:        )
984 //usage:        )
985 //usage:     "\nSignals:"
986 //usage:     "\n        USR1    Renew lease"
987 //usage:     "\n        USR2    Release lease"
988
989
990 int udhcpc6_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
991 int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
992 {
993         const char *str_r;
994         IF_FEATURE_UDHCP_PORT(char *str_P;)
995         void *clientid_mac_ptr;
996         llist_t *list_O = NULL;
997         llist_t *list_x = NULL;
998         int tryagain_timeout = 20;
999         int discover_timeout = 3;
1000         int discover_retries = 3;
1001         struct in6_addr srv6_buf;
1002         struct in6_addr ipv6_buf;
1003         struct in6_addr *requested_ipv6;
1004         uint32_t xid = 0;
1005         int packet_num;
1006         int timeout; /* must be signed */
1007         unsigned already_waited_sec;
1008         unsigned opt;
1009         int retval;
1010
1011         setup_common_bufsiz();
1012
1013         /* Default options */
1014         IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;)
1015         IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;)
1016         client_config.interface = "eth0";
1017         client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT;
1018
1019         /* Parse command line */
1020         /* O,x: list; -T,-t,-A take numeric param */
1021         IF_UDHCP_VERBOSE(opt_complementary = "vv";)
1022         IF_LONG_OPTS(applet_long_options = udhcpc6_longopts;)
1023         opt = getopt32(argv, "i:np:qRr:s:T:+t:+SA:+O:*ox:*f"
1024                 USE_FOR_MMU("b")
1025                 ///IF_FEATURE_UDHCPC_ARPING("a")
1026                 IF_FEATURE_UDHCP_PORT("P:")
1027                 "v"
1028                 , &client_config.interface, &client_config.pidfile, &str_r /* i,p */
1029                 , &client_config.script /* s */
1030                 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
1031                 , &list_O
1032                 , &list_x
1033                 IF_FEATURE_UDHCP_PORT(, &str_P)
1034                 IF_UDHCP_VERBOSE(, &dhcp_verbose)
1035         );
1036         requested_ipv6 = NULL;
1037         if (opt & OPT_r) {
1038                 if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
1039                         bb_error_msg_and_die("bad IPv6 address '%s'", str_r);
1040                 requested_ipv6 = &ipv6_buf;
1041         }
1042 #if ENABLE_FEATURE_UDHCP_PORT
1043         if (opt & OPT_P) {
1044                 CLIENT_PORT6 = xatou16(str_P);
1045                 SERVER_PORT6 = CLIENT_PORT6 + 1;
1046         }
1047 #endif
1048         while (list_O) {
1049                 char *optstr = llist_pop(&list_O);
1050                 unsigned n = bb_strtou(optstr, NULL, 0);
1051                 if (errno || n > 254) {
1052                         n = udhcp_option_idx(optstr);
1053                         n = dhcp_optflags[n].code;
1054                 }
1055                 client_config.opt_mask[n >> 3] |= 1 << (n & 7);
1056         }
1057         if (!(opt & OPT_o)) {
1058                 /*
1059                 unsigned i, n;
1060                 for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) {
1061                         if (dhcp_optflags[i].flags & OPTION_REQ) {
1062                                 client_config.opt_mask[n >> 3] |= 1 << (n & 7);
1063                         }
1064                 }
1065                 */
1066         }
1067         while (list_x) {
1068                 char *optstr = llist_pop(&list_x);
1069                 char *colon = strchr(optstr, ':');
1070                 if (colon)
1071                         *colon = ' ';
1072                 /* now it looks similar to udhcpd's config file line:
1073                  * "optname optval", using the common routine: */
1074                 udhcp_str2optset(optstr, &client_config.options);
1075         }
1076
1077         if (d6_read_interface(client_config.interface,
1078                         &client_config.ifindex,
1079                         &client6_data.ll_ip6,
1080                         client_config.client_mac)
1081         ) {
1082                 return 1;
1083         }
1084
1085         /* Create client ID based on mac, set clientid_mac_ptr */
1086         {
1087                 struct d6_option *clientid;
1088                 clientid = xzalloc(2+2+2+2+6);
1089                 clientid->code = D6_OPT_CLIENTID;
1090                 clientid->len = 2+2+6;
1091                 clientid->data[1] = 3; /* DUID-LL */
1092                 clientid->data[3] = 1; /* ethernet */
1093                 clientid_mac_ptr = clientid->data + 2+2;
1094                 memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1095                 client_config.clientid = (void*)clientid;
1096         }
1097
1098 #if !BB_MMU
1099         /* on NOMMU reexec (i.e., background) early */
1100         if (!(opt & OPT_f)) {
1101                 bb_daemonize_or_rexec(0 /* flags */, argv);
1102                 logmode = LOGMODE_NONE;
1103         }
1104 #endif
1105         if (opt & OPT_S) {
1106                 openlog(applet_name, LOG_PID, LOG_DAEMON);
1107                 logmode |= LOGMODE_SYSLOG;
1108         }
1109
1110         /* Make sure fd 0,1,2 are open */
1111         bb_sanitize_stdio();
1112         /* Equivalent of doing a fflush after every \n */
1113         setlinebuf(stdout);
1114         /* Create pidfile */
1115         write_pidfile(client_config.pidfile);
1116         /* Goes to stdout (unless NOMMU) and possibly syslog */
1117         bb_error_msg("started, v"BB_VER);
1118         /* Set up the signal pipe */
1119         udhcp_sp_setup();
1120         /* We want random_xid to be random... */
1121         srand(monotonic_us());
1122
1123         state = INIT_SELECTING;
1124         d6_run_script(NULL, "deconfig");
1125         change_listen_mode(LISTEN_RAW);
1126         packet_num = 0;
1127         timeout = 0;
1128         already_waited_sec = 0;
1129
1130         /* Main event loop. select() waits on signal pipe and possibly
1131          * on sockfd.
1132          * "continue" statements in code below jump to the top of the loop.
1133          */
1134         for (;;) {
1135                 int tv;
1136                 struct pollfd pfds[2];
1137                 struct d6_packet packet;
1138                 uint8_t *packet_end;
1139                 /* silence "uninitialized!" warning */
1140                 unsigned timestamp_before_wait = timestamp_before_wait;
1141
1142                 //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode);
1143
1144                 /* Was opening raw or udp socket here
1145                  * if (listen_mode != LISTEN_NONE && sockfd < 0),
1146                  * but on fast network renew responses return faster
1147                  * than we open sockets. Thus this code is moved
1148                  * to change_listen_mode(). Thus we open listen socket
1149                  * BEFORE we send renew request (see "case BOUND:"). */
1150
1151                 udhcp_sp_fd_set(pfds, sockfd);
1152
1153                 tv = timeout - already_waited_sec;
1154                 retval = 0;
1155                 /* If we already timed out, fall through with retval = 0, else... */
1156                 if (tv > 0) {
1157                         log1("waiting on select %u seconds", tv);
1158                         timestamp_before_wait = (unsigned)monotonic_sec();
1159                         retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX);
1160                         if (retval < 0) {
1161                                 /* EINTR? A signal was caught, don't panic */
1162                                 if (errno == EINTR) {
1163                                         already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1164                                         continue;
1165                                 }
1166                                 /* Else: an error occured, panic! */
1167                                 bb_perror_msg_and_die("select");
1168                         }
1169                 }
1170
1171                 /* If timeout dropped to zero, time to become active:
1172                  * resend discover/renew/whatever
1173                  */
1174                 if (retval == 0) {
1175                         /* When running on a bridge, the ifindex may have changed
1176                          * (e.g. if member interfaces were added/removed
1177                          * or if the status of the bridge changed).
1178                          * Refresh ifindex and client_mac:
1179                          */
1180                         if (d6_read_interface(client_config.interface,
1181                                         &client_config.ifindex,
1182                                         &client6_data.ll_ip6,
1183                                         client_config.client_mac)
1184                         ) {
1185                                 goto ret0; /* iface is gone? */
1186                         }
1187
1188                         memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1189
1190                         /* We will restart the wait in any case */
1191                         already_waited_sec = 0;
1192
1193                         switch (state) {
1194                         case INIT_SELECTING:
1195                                 if (!discover_retries || packet_num < discover_retries) {
1196                                         if (packet_num == 0)
1197                                                 xid = random_xid();
1198                                         /* multicast */
1199                                         send_d6_discover(xid, requested_ipv6);
1200                                         timeout = discover_timeout;
1201                                         packet_num++;
1202                                         continue;
1203                                 }
1204  leasefail:
1205                                 d6_run_script(NULL, "leasefail");
1206 #if BB_MMU /* -b is not supported on NOMMU */
1207                                 if (opt & OPT_b) { /* background if no lease */
1208                                         bb_error_msg("no lease, forking to background");
1209                                         client_background();
1210                                         /* do not background again! */
1211                                         opt = ((opt & ~OPT_b) | OPT_f);
1212                                 } else
1213 #endif
1214                                 if (opt & OPT_n) { /* abort if no lease */
1215                                         bb_error_msg("no lease, failing");
1216                                         retval = 1;
1217                                         goto ret;
1218                                 }
1219                                 /* wait before trying again */
1220                                 timeout = tryagain_timeout;
1221                                 packet_num = 0;
1222                                 continue;
1223                         case REQUESTING:
1224                                 if (!discover_retries || packet_num < discover_retries) {
1225                                         /* send multicast select packet */
1226                                         send_d6_select(xid);
1227                                         timeout = discover_timeout;
1228                                         packet_num++;
1229                                         continue;
1230                                 }
1231                                 /* Timed out, go back to init state.
1232                                  * "discover...select...discover..." loops
1233                                  * were seen in the wild. Treat them similarly
1234                                  * to "no response to discover" case */
1235                                 change_listen_mode(LISTEN_RAW);
1236                                 state = INIT_SELECTING;
1237                                 goto leasefail;
1238                         case BOUND:
1239                                 /* 1/2 lease passed, enter renewing state */
1240                                 state = RENEWING;
1241                                 client_config.first_secs = 0; /* make secs field count from 0 */
1242                                 change_listen_mode(LISTEN_KERNEL);
1243                                 log1("entering renew state");
1244                                 /* fall right through */
1245                         case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1246                         case_RENEW_REQUESTED:
1247                         case RENEWING:
1248                                 if (timeout > 60) {
1249                                         /* send an unicast renew request */
1250                         /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1251                          * a new UDP socket for sending inside send_renew.
1252                          * I hazard to guess existing listening socket
1253                          * is somehow conflicting with it, but why is it
1254                          * not deterministic then?! Strange.
1255                          * Anyway, it does recover by eventually failing through
1256                          * into INIT_SELECTING state.
1257                          */
1258                                         send_d6_renew(xid, &srv6_buf, requested_ipv6);
1259                                         timeout >>= 1;
1260                                         continue;
1261                                 }
1262                                 /* Timed out, enter rebinding state */
1263                                 log1("entering rebinding state");
1264                                 state = REBINDING;
1265                                 /* fall right through */
1266                         case REBINDING:
1267                                 /* Switch to bcast receive */
1268                                 change_listen_mode(LISTEN_RAW);
1269                                 /* Lease is *really* about to run out,
1270                                  * try to find DHCP server using broadcast */
1271                                 if (timeout > 0) {
1272                                         /* send a broadcast renew request */
1273                                         send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
1274                                         timeout >>= 1;
1275                                         continue;
1276                                 }
1277                                 /* Timed out, enter init state */
1278                                 bb_error_msg("lease lost, entering init state");
1279                                 d6_run_script(NULL, "deconfig");
1280                                 state = INIT_SELECTING;
1281                                 client_config.first_secs = 0; /* make secs field count from 0 */
1282                                 /*timeout = 0; - already is */
1283                                 packet_num = 0;
1284                                 continue;
1285                         /* case RELEASED: */
1286                         }
1287                         /* yah, I know, *you* say it would never happen */
1288                         timeout = INT_MAX;
1289                         continue; /* back to main loop */
1290                 } /* if select timed out */
1291
1292                 /* select() didn't timeout, something happened */
1293
1294                 /* Is it a signal? */
1295                 /* note: udhcp_sp_read checks poll result before reading */
1296                 switch (udhcp_sp_read(pfds)) {
1297                 case SIGUSR1:
1298                         client_config.first_secs = 0; /* make secs field count from 0 */
1299                         already_waited_sec = 0;
1300                         perform_renew();
1301                         if (state == RENEW_REQUESTED) {
1302                                 /* We might be either on the same network
1303                                  * (in which case renew might work),
1304                                  * or we might be on a completely different one
1305                                  * (in which case renew won't ever succeed).
1306                                  * For the second case, must make sure timeout
1307                                  * is not too big, or else we can send
1308                                  * futile renew requests for hours.
1309                                  * (Ab)use -A TIMEOUT value (usually 20 sec)
1310                                  * as a cap on the timeout.
1311                                  */
1312                                 if (timeout > tryagain_timeout)
1313                                         timeout = tryagain_timeout;
1314                                 goto case_RENEW_REQUESTED;
1315                         }
1316                         /* Start things over */
1317                         packet_num = 0;
1318                         /* Kill any timeouts, user wants this to hurry along */
1319                         timeout = 0;
1320                         continue;
1321                 case SIGUSR2:
1322                         perform_d6_release(&srv6_buf, requested_ipv6);
1323                         timeout = INT_MAX;
1324                         continue;
1325                 case SIGTERM:
1326                         bb_error_msg("received %s", "SIGTERM");
1327                         goto ret0;
1328                 }
1329
1330                 /* Is it a packet? */
1331                 if (listen_mode == LISTEN_NONE || !pfds[1].revents)
1332                         continue; /* no */
1333
1334                 {
1335                         int len;
1336
1337                         /* A packet is ready, read it */
1338                         if (listen_mode == LISTEN_KERNEL)
1339                                 len = d6_recv_kernel_packet(&srv6_buf, &packet, sockfd);
1340                         else
1341                                 len = d6_recv_raw_packet(&srv6_buf, &packet, sockfd);
1342                         if (len == -1) {
1343                                 /* Error is severe, reopen socket */
1344                                 bb_error_msg("read error: %s, reopening socket", strerror(errno));
1345                                 sleep(discover_timeout); /* 3 seconds by default */
1346                                 change_listen_mode(listen_mode); /* just close and reopen */
1347                         }
1348                         /* If this packet will turn out to be unrelated/bogus,
1349                          * we will go back and wait for next one.
1350                          * Be sure timeout is properly decreased. */
1351                         already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1352                         if (len < 0)
1353                                 continue;
1354                         packet_end = (uint8_t*)&packet + len;
1355                 }
1356
1357                 if ((packet.d6_xid32 & htonl(0x00ffffff)) != xid) {
1358                         log1("xid %x (our is %x), ignoring packet",
1359                                 (unsigned)(packet.d6_xid32 & htonl(0x00ffffff)), (unsigned)xid);
1360                         continue;
1361                 }
1362
1363                 switch (state) {
1364                 case INIT_SELECTING:
1365                         if (packet.d6_msg_type == D6_MSG_ADVERTISE)
1366                                 goto type_is_ok;
1367                         /* DHCPv6 has "Rapid Commit", when instead of Advertise,
1368                          * server sends Reply right away.
1369                          * Fall through to check for this case.
1370                          */
1371                 case REQUESTING:
1372                 case RENEWING:
1373                 case RENEW_REQUESTED:
1374                 case REBINDING:
1375                         if (packet.d6_msg_type == D6_MSG_REPLY) {
1376                                 uint32_t lease_seconds;
1377                                 struct d6_option *option, *iaaddr;
1378  type_is_ok:
1379                                 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
1380                                 if (option && (option->data[0] | option->data[1]) != 0) {
1381                                         /* return to init state */
1382                                         bb_error_msg("received DHCP NAK (%u)", option->data[4]);
1383                                         d6_run_script(&packet, "nak");
1384                                         if (state != REQUESTING)
1385                                                 d6_run_script(NULL, "deconfig");
1386                                         change_listen_mode(LISTEN_RAW);
1387                                         sleep(3); /* avoid excessive network traffic */
1388                                         state = INIT_SELECTING;
1389                                         client_config.first_secs = 0; /* make secs field count from 0 */
1390                                         requested_ipv6 = NULL;
1391                                         timeout = 0;
1392                                         packet_num = 0;
1393                                         already_waited_sec = 0;
1394                                         continue;
1395                                 }
1396                                 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID);
1397                                 if (!option) {
1398                                         bb_error_msg("no server ID, ignoring packet");
1399                                         continue;
1400                                         /* still selecting - this server looks bad */
1401                                 }
1402 //Note: we do not bother comparing server IDs in Advertise and Reply msgs.
1403 //server_id variable is used solely for creation of proper server_id option
1404 //in outgoing packets. (why DHCPv6 even introduced it is a mystery).
1405                                 free(client6_data.server_id);
1406                                 client6_data.server_id = option;
1407                                 if (packet.d6_msg_type == D6_MSG_ADVERTISE) {
1408                                         /* enter requesting state */
1409                                         state = REQUESTING;
1410                                         timeout = 0;
1411                                         packet_num = 0;
1412                                         already_waited_sec = 0;
1413                                         continue;
1414                                 }
1415                                 /* It's a D6_MSG_REPLY */
1416 /*
1417  * RFC 3315 18.1.8. Receipt of Reply Messages
1418  *
1419  * Upon the receipt of a valid Reply message in response to a Solicit
1420  * (with a Rapid Commit option), Request, Confirm, Renew, Rebind or
1421  * Information-request message, the client extracts the configuration
1422  * information contained in the Reply.  The client MAY choose to report
1423  * any status code or message from the status code option in the Reply
1424  * message.
1425  *
1426  * The client SHOULD perform duplicate address detection [17] on each of
1427  * the addresses in any IAs it receives in the Reply message before
1428  * using that address for traffic.  If any of the addresses are found to
1429  * be in use on the link, the client sends a Decline message to the
1430  * server as described in section 18.1.7.
1431  *
1432  * If the Reply was received in response to a Solicit (with a Rapid
1433  * Commit option), Request, Renew or Rebind message, the client updates
1434  * the information it has recorded about IAs from the IA options
1435  * contained in the Reply message:
1436  *
1437  * -  Record T1 and T2 times.
1438  *
1439  * -  Add any new addresses in the IA option to the IA as recorded by
1440  *    the client.
1441  *
1442  * -  Update lifetimes for any addresses in the IA option that the
1443  *    client already has recorded in the IA.
1444  *
1445  * -  Discard any addresses from the IA, as recorded by the client, that
1446  *    have a valid lifetime of 0 in the IA Address option.
1447  *
1448  * -  Leave unchanged any information about addresses the client has
1449  *    recorded in the IA but that were not included in the IA from the
1450  *    server.
1451  *
1452  * Management of the specific configuration information is detailed in
1453  * the definition of each option in section 22.
1454  *
1455  * If the client receives a Reply message with a Status Code containing
1456  * UnspecFail, the server is indicating that it was unable to process
1457  * the message due to an unspecified failure condition.  If the client
1458  * retransmits the original message to the same server to retry the
1459  * desired operation, the client MUST limit the rate at which it
1460  * retransmits the message and limit the duration of the time during
1461  * which it retransmits the message.
1462  *
1463  * When the client receives a Reply message with a Status Code option
1464  * with the value UseMulticast, the client records the receipt of the
1465  * message and sends subsequent messages to the server through the
1466  * interface on which the message was received using multicast.  The
1467  * client resends the original message using multicast.
1468  *
1469  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1470  * |          OPTION_IA_NA         |          option-len           |
1471  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1472  * |                        IAID (4 octets)                        |
1473  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1474  * |                              T1                               |
1475  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1476  * |                              T2                               |
1477  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1478  * |                                                               |
1479  * .                         IA_NA-options                         .
1480  * .                                                               .
1481  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1482  *
1483  *
1484  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1485  * |          OPTION_IAADDR        |          option-len           |
1486  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1487  * |                                                               |
1488  * |                         IPv6 address                          |
1489  * |                                                               |
1490  * |                                                               |
1491  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1492  * |                      preferred-lifetime                       |
1493  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1494  * |                        valid-lifetime                         |
1495  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1496  * .                                                               .
1497  * .                        IAaddr-options                         .
1498  * .                                                               .
1499  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1500  */
1501                                 free(client6_data.ia_na);
1502                                 client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA);
1503                                 if (!client6_data.ia_na) {
1504                                         bb_error_msg("no %s option, ignoring packet", "IA_NA");
1505                                         continue;
1506                                 }
1507                                 if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) {
1508                                         bb_error_msg("IA_NA option is too short:%d bytes", client6_data.ia_na->len);
1509                                         continue;
1510                                 }
1511                                 iaaddr = d6_find_option(client6_data.ia_na->data + 4 + 4 + 4,
1512                                                 client6_data.ia_na->data + client6_data.ia_na->len,
1513                                                 D6_OPT_IAADDR
1514                                 );
1515                                 if (!iaaddr) {
1516                                         bb_error_msg("no %s option, ignoring packet", "IAADDR");
1517                                         continue;
1518                                 }
1519                                 if (iaaddr->len < (16 + 4 + 4)) {
1520                                         bb_error_msg("IAADDR option is too short:%d bytes", iaaddr->len);
1521                                         continue;
1522                                 }
1523                                 /* Note: the address is sufficiently aligned for cast:
1524                                  * we _copied_ IA-NA, and copy is always well-aligned.
1525                                  */
1526                                 requested_ipv6 = (struct in6_addr*) iaaddr->data;
1527                                 move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4);
1528                                 lease_seconds = ntohl(lease_seconds);
1529                                 /* paranoia: must not be too small and not prone to overflows */
1530                                 if (lease_seconds < 0x10)
1531                                         lease_seconds = 0x10;
1532 /// TODO: check for 0 lease time?
1533                                 if (lease_seconds > 0x7fffffff / 1000)
1534                                         lease_seconds = 0x7fffffff / 1000;
1535                                 /* enter bound state */
1536                                 timeout = lease_seconds / 2;
1537                                 bb_error_msg("lease obtained, lease time %u",
1538                                         /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds);
1539                                 d6_run_script(&packet, state == REQUESTING ? "bound" : "renew");
1540
1541                                 state = BOUND;
1542                                 change_listen_mode(LISTEN_NONE);
1543                                 if (opt & OPT_q) { /* quit after lease */
1544                                         goto ret0;
1545                                 }
1546                                 /* future renew failures should not exit (JM) */
1547                                 opt &= ~OPT_n;
1548 #if BB_MMU /* NOMMU case backgrounded earlier */
1549                                 if (!(opt & OPT_f)) {
1550                                         client_background();
1551                                         /* do not background again! */
1552                                         opt = ((opt & ~OPT_b) | OPT_f);
1553                                 }
1554 #endif
1555                                 already_waited_sec = 0;
1556                                 continue; /* back to main loop */
1557                         }
1558                         continue;
1559                 /* case BOUND: - ignore all packets */
1560                 /* case RELEASED: - ignore all packets */
1561                 }
1562                 /* back to main loop */
1563         } /* for (;;) - main loop ends */
1564
1565  ret0:
1566         if (opt & OPT_R) /* release on quit */
1567                 perform_d6_release(&srv6_buf, requested_ipv6);
1568         retval = 0;
1569  ret:
1570         /*if (client_config.pidfile) - remove_pidfile has its own check */
1571                 remove_pidfile(client_config.pidfile);
1572         return retval;
1573 }