]> git.ipfire.org Git - thirdparty/dhcp.git/blame - client/dhc6.c
[master] dhclient (-6) skips confirm (INIT REBOOT) is all leases are expired
[thirdparty/dhcp.git] / client / dhc6.c
CommitLineData
98bd7ca0
DH
1/* dhc6.c - DHCPv6 client routines. */
2
3/*
251bb4b9 4 * Copyright (c) 2012-2017 by Internet Systems Consortium, Inc. ("ISC")
197c917e 5 * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
98bd7ca0 6 *
7512d88b
TM
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
98bd7ca0
DH
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * Internet Systems Consortium, Inc.
20 * 950 Charter Street
21 * Redwood City, CA 94063
22 * <info@isc.org>
2c85ac9b 23 * https://www.isc.org/
98bd7ca0
DH
24 */
25
98bd7ca0
DH
26#include "dhcpd.h"
27
fe5b0fdd
DH
28#ifdef DHCPv6
29
98bd7ca0 30struct sockaddr_in6 DHCPv6DestAddr;
0c20eab3 31
420d8b3f
FD
32/*
33 * Option definition structures that are used by the software - declared
0c20eab3
DH
34 * here once and assigned at startup to save lookups.
35 */
98bd7ca0 36struct option *clientid_option = NULL;
0c20eab3 37struct option *elapsed_option = NULL;
98bd7ca0 38struct option *ia_na_option = NULL;
1d9774ab
FD
39struct option *ia_ta_option = NULL;
40struct option *ia_pd_option = NULL;
98bd7ca0 41struct option *iaaddr_option = NULL;
1d9774ab 42struct option *iaprefix_option = NULL;
0c20eab3 43struct option *oro_option = NULL;
3dbe2246 44struct option *irt_option = NULL;
98bd7ca0
DH
45
46static struct dhc6_lease *dhc6_dup_lease(struct dhc6_lease *lease,
06eb8bab 47 const char *file, int line);
420d8b3f 48static struct dhc6_ia *dhc6_dup_ia(struct dhc6_ia *ia,
06eb8bab 49 const char *file, int line);
98bd7ca0 50static struct dhc6_addr *dhc6_dup_addr(struct dhc6_addr *addr,
06eb8bab 51 const char *file, int line);
e32529a5 52static void dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line);
98bd7ca0
DH
53static isc_result_t dhc6_parse_ia_na(struct dhc6_ia **pia,
54 struct packet *packet,
c88dfebd
SR
55 struct option_state *options,
56 unsigned code);
1d9774ab
FD
57static isc_result_t dhc6_parse_ia_ta(struct dhc6_ia **pia,
58 struct packet *packet,
c88dfebd
SR
59 struct option_state *options,
60 unsigned code);
1d9774ab
FD
61static isc_result_t dhc6_parse_ia_pd(struct dhc6_ia **pia,
62 struct packet *packet,
c88dfebd
SR
63 struct option_state *options,
64 unsigned code);
98bd7ca0
DH
65static isc_result_t dhc6_parse_addrs(struct dhc6_addr **paddr,
66 struct packet *packet,
67 struct option_state *options);
420d8b3f
FD
68static isc_result_t dhc6_parse_prefixes(struct dhc6_addr **ppref,
69 struct packet *packet,
70 struct option_state *options);
71static struct dhc6_ia *find_ia(struct dhc6_ia *head,
72 u_int16_t type, const char *id);
98bd7ca0
DH
73static struct dhc6_addr *find_addr(struct dhc6_addr *head,
74 struct iaddr *address);
420d8b3f
FD
75static struct dhc6_addr *find_pref(struct dhc6_addr *head,
76 struct iaddr *prefix, u_int8_t plen);
98bd7ca0 77void init_handler(struct packet *packet, struct client_state *client);
3dbe2246 78void info_request_handler(struct packet *packet, struct client_state *client);
6d7f9584 79void rapid_commit_handler(struct packet *packet, struct client_state *client);
98bd7ca0 80void do_init6(void *input);
3dbe2246 81void do_info_request6(void *input);
98bd7ca0
DH
82void do_confirm6(void *input);
83void reply_handler(struct packet *packet, struct client_state *client);
c88dfebd
SR
84static isc_result_t dhc6_create_iaid(struct client_state *client,
85 struct data_string *ia,
86 int idx,
87 unsigned len);
88static int dhc6_count_ia(struct dhc6_lease *lease,
89 u_int16_t ia_type);
90static isc_result_t dhc6_bare_ia_xx(struct client_state *client,
91 struct data_string *packet,
92 int wanted,
93 u_int16_t ia_type);
1d9774ab
FD
94static isc_result_t dhc6_add_ia_na(struct client_state *client,
95 struct data_string *packet,
96 struct dhc6_lease *lease,
c88dfebd
SR
97 u_int8_t message,
98 int wanted,
99 int *added);
420d8b3f
FD
100static isc_result_t dhc6_add_ia_ta(struct client_state *client,
101 struct data_string *packet,
102 struct dhc6_lease *lease,
c88dfebd
SR
103 u_int8_t message,
104 int wanted,
105 int *added);
420d8b3f
FD
106static isc_result_t dhc6_add_ia_pd(struct client_state *client,
107 struct data_string *packet,
108 struct dhc6_lease *lease,
c88dfebd
SR
109 u_int8_t message,
110 int wanted,
111 int *added);
87202683 112static isc_boolean_t stopping_finished(void);
98bd7ca0
DH
113static void dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst);
114void do_select6(void *input);
115void do_refresh6(void *input);
af5fa176 116static void do_release6(void *input);
98bd7ca0 117static void start_bound(struct client_state *client);
0f69ff73
TM
118static void start_decline6(struct client_state *client);
119static void do_decline6(void *input);
3dbe2246
FD
120static void start_informed(struct client_state *client);
121void informed_handler(struct packet *packet, struct client_state *client);
98bd7ca0
DH
122void bound_handler(struct packet *packet, struct client_state *client);
123void start_renew6(void *input);
124void start_rebind6(void *input);
125void do_depref(void *input);
126void do_expire(void *input);
127static void make_client6_options(struct client_state *client,
128 struct option_state **op,
129 struct dhc6_lease *lease, u_int8_t message);
420d8b3f 130static void script_write_params6(struct client_state *client,
06eb8bab 131 const char *prefix,
98bd7ca0 132 struct option_state *options);
10613724 133static void script_write_requested6(struct client_state *client);
420d8b3f 134static isc_boolean_t active_prefix(struct client_state *client);
98bd7ca0 135
c88dfebd
SR
136static int check_timing6(struct client_state *client, u_int8_t msg_type,
137 char *msg_str, struct dhc6_lease *lease,
138 struct data_string *ds);
139static isc_result_t dhc6_get_status_code(struct option_state *options,
140 unsigned *code,
141 struct data_string *msg);
142static isc_result_t dhc6_check_status(isc_result_t rval,
143 struct option_state *options,
144 const char *scope,
145 unsigned *code);
1d7fceeb 146static int dhc6_score_lease(struct client_state *client,
147 struct dhc6_lease *lease);
0f69ff73
TM
148static isc_result_t dhc6_add_ia_na_decline(struct client_state *client,
149 struct data_string *packet,
150 struct dhc6_lease *lease);
151static int drop_declined_addrs(struct dhc6_lease *lease);
f1fc5ede 152static isc_boolean_t unexpired_address_in_lease(struct dhc6_lease *lease);
0f69ff73 153
ffbaa880 154extern int onetry;
3dbe2246 155extern int stateless;
c0e9661e 156extern int prefix_len_hint;
140612c8 157extern int address_prefix_len;
3dbe2246 158
420d8b3f
FD
159/*
160 * Assign DHCPv6 port numbers as a client.
98bd7ca0
DH
161 */
162void
163dhcpv6_client_assignments(void)
164{
165 struct servent *ent;
166 unsigned code;
167
168 if (path_dhclient_pid == NULL)
169 path_dhclient_pid = _PATH_DHCLIENT6_PID;
170 if (path_dhclient_db == NULL)
171 path_dhclient_db = _PATH_DHCLIENT6_DB;
172
173 if (local_port == 0) {
174 ent = getservbyname("dhcpv6-client", "udp");
175 if (ent == NULL)
176 local_port = htons(546);
177 else
178 local_port = ent->s_port;
179 }
180
181 if (remote_port == 0) {
182 ent = getservbyname("dhcpv6-server", "udp");
183 if (ent == NULL)
184 remote_port = htons(547);
185 else
186 remote_port = ent->s_port;
187 }
188
189 memset(&DHCPv6DestAddr, 0, sizeof(DHCPv6DestAddr));
190 DHCPv6DestAddr.sin6_family = AF_INET6;
191 DHCPv6DestAddr.sin6_port = remote_port;
0f750c4f
SR
192 if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
193 &DHCPv6DestAddr.sin6_addr) <= 0) {
194 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers);
195 }
98bd7ca0
DH
196
197 code = D6O_CLIENTID;
198 if (!option_code_hash_lookup(&clientid_option,
199 dhcpv6_universe.code_hash, &code, 0, MDL))
200 log_fatal("Unable to find the CLIENTID option definition.");
201
0c20eab3
DH
202 code = D6O_ELAPSED_TIME;
203 if (!option_code_hash_lookup(&elapsed_option,
204 dhcpv6_universe.code_hash, &code, 0, MDL))
205 log_fatal("Unable to find the ELAPSED_TIME option definition.");
206
98bd7ca0
DH
207 code = D6O_IA_NA;
208 if (!option_code_hash_lookup(&ia_na_option, dhcpv6_universe.code_hash,
209 &code, 0, MDL))
210 log_fatal("Unable to find the IA_NA option definition.");
211
1d9774ab
FD
212 code = D6O_IA_TA;
213 if (!option_code_hash_lookup(&ia_ta_option, dhcpv6_universe.code_hash,
214 &code, 0, MDL))
215 log_fatal("Unable to find the IA_TA option definition.");
216
217 code = D6O_IA_PD;
218 if (!option_code_hash_lookup(&ia_pd_option, dhcpv6_universe.code_hash,
219 &code, 0, MDL))
220 log_fatal("Unable to find the IA_PD option definition.");
221
98bd7ca0
DH
222 code = D6O_IAADDR;
223 if (!option_code_hash_lookup(&iaaddr_option, dhcpv6_universe.code_hash,
224 &code, 0, MDL))
225 log_fatal("Unable to find the IAADDR option definition.");
226
1d9774ab
FD
227 code = D6O_IAPREFIX;
228 if (!option_code_hash_lookup(&iaprefix_option,
229 dhcpv6_universe.code_hash,
230 &code, 0, MDL))
231 log_fatal("Unable to find the IAPREFIX option definition.");
232
0c20eab3
DH
233 code = D6O_ORO;
234 if (!option_code_hash_lookup(&oro_option, dhcpv6_universe.code_hash,
235 &code, 0, MDL))
236 log_fatal("Unable to find the ORO option definition.");
98bd7ca0 237
3dbe2246
FD
238 code = D6O_INFORMATION_REFRESH_TIME;
239 if (!option_code_hash_lookup(&irt_option, dhcpv6_universe.code_hash,
240 &code, 0, MDL))
241 log_fatal("Unable to find the IRT option definition.");
242
98bd7ca0
DH
243#ifndef __CYGWIN32__ /* XXX */
244 endservent();
245#endif
246}
247
420d8b3f
FD
248/*
249 * Instead of implementing RFC3315 RAND (section 14) as a float "between"
98bd7ca0
DH
250 * -0.1 and 0.1 non-inclusive, we implement it as an integer.
251 *
252 * The result is expected to follow this table:
253 *
254 * split range answer
255 * - ERROR - base <= 0
256 * 0 1 0..0 1 <= base <= 10
257 * 1 3 -1..1 11 <= base <= 20
258 * 2 5 -2..2 21 <= base <= 30
259 * 3 7 -3..3 31 <= base <= 40
260 * ...
261 *
262 * XXX: For this to make sense, we really need to do timing on a
263 * XXX: usec scale...we currently can assume zero for any value less than
264 * XXX: 11, which are very common in early stages of transmission for most
265 * XXX: messages.
266 */
267static TIME
268dhc6_rand(TIME base)
269{
270 TIME rval;
271 TIME range;
272 TIME split;
273
420d8b3f
FD
274 /*
275 * A zero or less timeout is a bad thing...we don't want to
98bd7ca0
DH
276 * DHCP-flood anyone.
277 */
278 if (base <= 0)
279 log_fatal("Impossible condition at %s:%d.", MDL);
280
420d8b3f
FD
281 /*
282 * The first thing we do is count how many random integers we want
98bd7ca0
DH
283 * in either direction (best thought of as the maximum negative
284 * integer, as we will subtract this potentially from a random 0).
285 */
286 split = (base - 1) / 10;
287
288 /* Don't bother with the rest of the math if we know we'll get 0. */
289 if (split == 0)
290 return 0;
291
420d8b3f
FD
292 /*
293 * Then we count the total number of integers in this set. This
98bd7ca0
DH
294 * is twice the number of integers in positive and negative
295 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
296 */
297 range = (split * 2) + 1;
298
299 /* Take a random number from [0..(range-1)]. */
300 rval = random();
301 rval %= range;
302
303 /* Offset it to uncover potential negative values. */
304 rval -= split;
305
306 return rval;
307}
308
c0216cb7 309/* Initialize message exchange timers (set RT from Initial-RT). */
98bd7ca0 310static void
c0216cb7 311dhc6_retrans_init(struct client_state *client)
98bd7ca0
DH
312{
313 int xid;
314
c0216cb7 315 /* Initialize timers. */
c0216cb7
DH
316 client->txcount = 0;
317 client->RT = client->IRT + dhc6_rand(client->IRT);
318
319 /* Generate a new random 24-bit transaction ID for this exchange. */
320
321#if (RAND_MAX >= 0x00ffffff)
322 xid = random();
323#elif (RAND_MAX >= 0x0000ffff)
324 xid = (random() << 16) ^ random();
325#elif (RAND_MAX >= 0x000000ff)
326 xid = (random() << 16) ^ (random() << 8) ^ random();
327#else
328# error "Random number generator of less than 8 bits not supported."
329#endif
98bd7ca0
DH
330
331 client->dhcpv6_transaction_id[0] = (xid >> 16) & 0xff;
332 client->dhcpv6_transaction_id[1] = (xid >> 8) & 0xff;
333 client->dhcpv6_transaction_id[2] = xid & 0xff;
334}
335
98bd7ca0
DH
336/* Advance the DHCPv6 retransmission state once. */
337static void
338dhc6_retrans_advance(struct client_state *client)
339{
b6ab3f6c 340 struct timeval elapsed, elapsed_plus_rt;
98bd7ca0 341
be62cf06
FD
342 /* elapsed = cur - start */
343 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
344 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
345 if (elapsed.tv_usec < 0) {
346 elapsed.tv_sec -= 1;
347 elapsed.tv_usec += 1000000;
348 }
98bd7ca0 349 /* retrans_advance is called after consuming client->RT. */
be62cf06
FD
350 /* elapsed += RT */
351 elapsed.tv_sec += client->RT / 100;
352 elapsed.tv_usec += (client->RT % 100) * 10000;
353 if (elapsed.tv_usec >= 1000000) {
354 elapsed.tv_sec += 1;
355 elapsed.tv_usec -= 1000000;
356 }
b6ab3f6c
SR
357 /*
358 * Save what the time will be after the current RT to determine
359 * what the delta to MRD will be.
360 */
361 elapsed_plus_rt.tv_sec = elapsed.tv_sec;
362 elapsed_plus_rt.tv_usec = elapsed.tv_usec;
98bd7ca0 363
420d8b3f
FD
364 /*
365 * RT for each subsequent message transmission is based on the previous
366 * value of RT:
367 *
368 * RT = 2*RTprev + RAND*RTprev
369 */
370 client->RT += client->RT + dhc6_rand(client->RT);
371
372 /*
373 * MRT specifies an upper bound on the value of RT (disregarding the
374 * randomization added by the use of RAND). If MRT has a value of 0,
375 * there is no upper limit on the value of RT. Otherwise:
376 *
377 * if (RT > MRT)
378 * RT = MRT + RAND*MRT
379 */
380 if ((client->MRT != 0) && (client->RT > client->MRT))
381 client->RT = client->MRT + dhc6_rand(client->MRT);
382
383 /*
384 * Further, if there's an MRD, we should wake up upon reaching
98bd7ca0
DH
385 * the MRD rather than at some point after it.
386 */
be62cf06
FD
387 if (client->MRD == 0) {
388 /* Done. */
389 client->txcount++;
390 return;
391 }
392 /* elapsed += client->RT */
393 elapsed.tv_sec += client->RT / 100;
394 elapsed.tv_usec += (client->RT % 100) * 10000;
395 if (elapsed.tv_usec >= 1000000) {
396 elapsed.tv_sec += 1;
397 elapsed.tv_usec -= 1000000;
398 }
399 if (elapsed.tv_sec >= client->MRD) {
400 /*
b6ab3f6c 401 * The desired RT is the time that will be remaining in MRD
c88dfebd 402 * when the current timeout finishes. We then have
b6ab3f6c
SR
403 * desired RT = MRD - (elapsed time + previous RT); or
404 * desired RT = MRD - elapsed_plut_rt;
be62cf06 405 */
b6ab3f6c
SR
406 client->RT = client->MRD - elapsed_plus_rt.tv_sec;
407 client->RT = (client->RT * 100) -
408 (elapsed_plus_rt.tv_usec / 10000);
409 if (client->RT < 0)
410 client->RT = 0;
98bd7ca0 411 }
98bd7ca0
DH
412 client->txcount++;
413}
414
415/* Quick validation of DHCPv6 ADVERTISE packet contents. */
416static int
417valid_reply(struct packet *packet, struct client_state *client)
418{
419 struct data_string sid, cid;
420 struct option_cache *oc;
421 int rval = ISC_TRUE;
422
423 memset(&sid, 0, sizeof(sid));
424 memset(&cid, 0, sizeof(cid));
425
426 if (!lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID)) {
9ab0cc6a 427 log_error("Response without a server identifier received.");
98bd7ca0
DH
428 rval = ISC_FALSE;
429 }
430
431 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
432 if (!oc ||
433 !evaluate_option_cache(&sid, packet, NULL, client, packet->options,
434 client->sent_options, &global_scope, oc,
435 MDL)) {
9ab0cc6a 436 log_error("Response without a client identifier.");
98bd7ca0
DH
437 rval = ISC_FALSE;
438 }
439
440 oc = lookup_option(&dhcpv6_universe, client->sent_options,
441 D6O_CLIENTID);
442 if (!oc ||
443 !evaluate_option_cache(&cid, packet, NULL, client,
444 client->sent_options, NULL, &global_scope,
445 oc, MDL)) {
446 log_error("Local client identifier is missing!");
447 rval = ISC_FALSE;
448 }
449
450 if (sid.len == 0 ||
451 sid.len != cid.len ||
452 memcmp(sid.data, cid.data, sid.len)) {
453 log_error("Advertise with matching transaction ID, but "
454 "mismatching client id.");
455 rval = ISC_FALSE;
456 }
457
18ba0ff3
SR
458 /* clean up pointers to the strings */
459 if (sid.data != NULL)
460 data_string_forget(&sid, MDL);
461 if (cid.data != NULL)
462 data_string_forget(&cid, MDL);
463
98bd7ca0
DH
464 return rval;
465}
466
420d8b3f
FD
467/*
468 * Create a complete copy of a DHCPv6 lease structure.
98bd7ca0
DH
469 */
470static struct dhc6_lease *
06eb8bab 471dhc6_dup_lease(struct dhc6_lease *lease, const char *file, int line)
98bd7ca0
DH
472{
473 struct dhc6_lease *copy;
474 struct dhc6_ia **insert_ia, *ia;
475
476 copy = dmalloc(sizeof(*copy), file, line);
477 if (copy == NULL) {
478 log_error("Out of memory for v6 lease structure.");
479 return NULL;
480 }
481
482 data_string_copy(&copy->server_id, &lease->server_id, file, line);
483 copy->pref = lease->pref;
484
485 memcpy(copy->dhcpv6_transaction_id, lease->dhcpv6_transaction_id,
486 sizeof(copy->dhcpv6_transaction_id));
487
488 option_state_reference(&copy->options, lease->options, file, line);
489
490 insert_ia = &copy->bindings;
491 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
492 *insert_ia = dhc6_dup_ia(ia, file, line);
493
494 if (*insert_ia == NULL) {
e32529a5 495 dhc6_lease_destroy(&copy, file, line);
98bd7ca0
DH
496 return NULL;
497 }
498
499 insert_ia = &(*insert_ia)->next;
500 }
501
502 return copy;
503}
504
420d8b3f
FD
505/*
506 * Duplicate an IA structure.
98bd7ca0
DH
507 */
508static struct dhc6_ia *
06eb8bab 509dhc6_dup_ia(struct dhc6_ia *ia, const char *file, int line)
98bd7ca0
DH
510{
511 struct dhc6_ia *copy;
512 struct dhc6_addr **insert_addr, *addr;
513
514 copy = dmalloc(sizeof(*ia), file, line);
88c3ff5d
TM
515 if (copy == NULL) {
516 log_error("Out of memory for v6 duplicate IA structure.");
517 return NULL;
518 }
98bd7ca0
DH
519
520 memcpy(copy->iaid, ia->iaid, sizeof(copy->iaid));
521
1d9774ab 522 copy->ia_type = ia->ia_type;
98bd7ca0
DH
523 copy->starts = ia->starts;
524 copy->renew = ia->renew;
525 copy->rebind = ia->rebind;
526
527 insert_addr = &copy->addrs;
528 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
529 *insert_addr = dhc6_dup_addr(addr, file, line);
530
531 if (*insert_addr == NULL) {
e32529a5 532 dhc6_ia_destroy(&copy, file, line);
98bd7ca0
DH
533 return NULL;
534 }
535
536 insert_addr = &(*insert_addr)->next;
537 }
538
539 if (ia->options != NULL)
540 option_state_reference(&copy->options, ia->options,
541 file, line);
542
543 return copy;
544}
545
420d8b3f
FD
546/*
547 * Duplicate an IAADDR or IAPREFIX structure.
98bd7ca0
DH
548 */
549static struct dhc6_addr *
06eb8bab 550dhc6_dup_addr(struct dhc6_addr *addr, const char *file, int line)
98bd7ca0
DH
551{
552 struct dhc6_addr *copy;
553
554 copy = dmalloc(sizeof(*addr), file, line);
555
556 if (copy == NULL)
557 return NULL;
558
559 memcpy(&copy->address, &addr->address, sizeof(copy->address));
560
1d9774ab 561 copy->plen = addr->plen;
98bd7ca0
DH
562 copy->flags = addr->flags;
563 copy->starts = addr->starts;
564 copy->preferred_life = addr->preferred_life;
565 copy->max_life = addr->max_life;
566
567 if (addr->options != NULL)
568 option_state_reference(&copy->options, addr->options,
569 file, line);
570
571 return copy;
572}
573
420d8b3f
FD
574/*
575 * Form a DHCPv6 lease structure based upon packet contents. Creates and
1d9774ab 576 * populates IA's and any IAADDR/IAPREFIX's they contain.
cabdb9b1 577 * Parsed options are deleted in order to not save them in the lease file.
c88dfebd
SR
578 *
579 * If we get a status code of NoAddrs or NoPrefix we toss the affected
580 * IAs. If it as at the top level we toss all IAs of that type. If it
581 * is in an IA we only toss that one. According to the spec we shouldn't
582 * get a NoPrefix status at the top level but we will allow it.
583 *
98bd7ca0
DH
584 */
585static struct dhc6_lease *
a3471269 586dhc6_leaseify(struct packet *packet, struct client_state* client)
98bd7ca0
DH
587{
588 struct data_string ds;
589 struct dhc6_lease *lease;
590 struct option_cache *oc;
c88dfebd 591 unsigned code;
98bd7ca0
DH
592
593 lease = dmalloc(sizeof(*lease), MDL);
594 if (lease == NULL) {
595 log_error("Out of memory for v6 lease structure.");
596 return NULL;
597 }
598
599 memcpy(lease->dhcpv6_transaction_id, packet->dhcpv6_transaction_id, 3);
600 option_state_reference(&lease->options, packet->options, MDL);
601
602 memset(&ds, 0, sizeof(ds));
603
604 /* Determine preference (default zero). */
605 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
606 if (oc &&
607 evaluate_option_cache(&ds, packet, NULL, NULL, lease->options,
608 NULL, &global_scope, oc, MDL)) {
609 if (ds.len != 1) {
610 log_error("Invalid length of DHCPv6 Preference option "
611 "(%d != 1)", ds.len);
612 data_string_forget(&ds, MDL);
e32529a5 613 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
614 return NULL;
615 } else {
616 lease->pref = ds.data[0];
617 log_debug("RCV: X-- Preference %u.",
618 (unsigned)lease->pref);
619 }
620
621 data_string_forget(&ds, MDL);
622 }
cabdb9b1 623 delete_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
98bd7ca0 624
c88dfebd
SR
625 /* Get the top level status code. If the code is NoAddrsAvail
626 * or NoPrefixAvail strip it from the options as we don't
627 * want it to show up in check_[advertise reply]. We
628 * pass it along to the parse_ia_xx routines and they
629 * will drop the affected IAs for NoAddrs or NoPrefix,
630 * other status codes will be ignored and handled by
631 * the check_[advertise reply] routines.
632 */
633 code = STATUS_Success;
634 if ((dhc6_get_status_code(lease->options, &code, NULL) == ISC_R_SUCCESS)
635 &&
636 ((code == STATUS_NoAddrsAvail) || (code == STATUS_NoPrefixAvail))) {
637 delete_option(&dhcpv6_universe, lease->options,
638 D6O_STATUS_CODE);
639 }
640
420d8b3f
FD
641 /*
642 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
98bd7ca0
DH
643 * options.
644 */
645 if (dhc6_parse_ia_na(&lease->bindings, packet,
c88dfebd 646 lease->options, code) != ISC_R_SUCCESS) {
98bd7ca0 647 /* Error conditions are logged by the caller. */
e32529a5 648 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
649 return NULL;
650 }
420d8b3f
FD
651 /*
652 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
1d9774ab
FD
653 * options.
654 */
655 if (dhc6_parse_ia_ta(&lease->bindings, packet,
c88dfebd 656 lease->options, code) != ISC_R_SUCCESS) {
1d9774ab
FD
657 /* Error conditions are logged by the caller. */
658 dhc6_lease_destroy(&lease, MDL);
659 return NULL;
660 }
420d8b3f
FD
661 /*
662 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
1d9774ab
FD
663 * options.
664 */
665 if (dhc6_parse_ia_pd(&lease->bindings, packet,
c88dfebd 666 lease->options, code) != ISC_R_SUCCESS) {
1d9774ab
FD
667 /* Error conditions are logged by the caller. */
668 dhc6_lease_destroy(&lease, MDL);
669 return NULL;
670 }
98bd7ca0 671
420d8b3f
FD
672 /*
673 * This is last because in the future we may want to make a different
98bd7ca0
DH
674 * key based upon additional information from the packet (we may need
675 * to allow multiple leases in one client state per server, but we're
676 * not sure based on what additional keys now).
677 */
678 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
0f750c4f
SR
679 if ((oc == NULL) ||
680 !evaluate_option_cache(&lease->server_id, packet, NULL, NULL,
98bd7ca0
DH
681 lease->options, NULL, &global_scope,
682 oc, MDL) ||
683 lease->server_id.len == 0) {
684 /* This should be impossible due to validation checks earlier.
685 */
686 log_error("Invalid SERVERID option cache.");
e32529a5 687 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
688 return NULL;
689 } else {
690 log_debug("RCV: X-- Server ID: %s",
691 print_hex_1(lease->server_id.len,
692 lease->server_id.data, 52));
693 }
694
a3471269
TM
695 execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
696 client, lease->options, lease->options,
697 &global_scope, client->config->on_receipt,
698 NULL, NULL);
699
98bd7ca0
DH
700 return lease;
701}
702
703static isc_result_t
704dhc6_parse_ia_na(struct dhc6_ia **pia, struct packet *packet,
c88dfebd 705 struct option_state *options, unsigned code)
98bd7ca0
DH
706{
707 struct data_string ds;
708 struct dhc6_ia *ia;
709 struct option_cache *oc;
710 isc_result_t result;
c88dfebd 711 unsigned ia_code;
98bd7ca0
DH
712
713 memset(&ds, 0, sizeof(ds));
714
715 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_NA);
716 for ( ; oc != NULL ; oc = oc->next) {
717 ia = dmalloc(sizeof(*ia), MDL);
718 if (ia == NULL) {
719 log_error("Out of memory allocating IA_NA structure.");
720 return ISC_R_NOMEMORY;
721 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
722 options, NULL,
723 &global_scope, oc, MDL) &&
724 ds.len >= 12) {
725 memcpy(ia->iaid, ds.data, 4);
1d9774ab 726 ia->ia_type = D6O_IA_NA;
98bd7ca0
DH
727 ia->starts = cur_time;
728 ia->renew = getULong(ds.data + 4);
729 ia->rebind = getULong(ds.data + 8);
730
731 log_debug("RCV: X-- IA_NA %s",
732 print_hex_1(4, ia->iaid, 59));
733 /* XXX: This should be the printed time I think. */
734 log_debug("RCV: | X-- starts %u",
735 (unsigned)ia->starts);
736 log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
737 log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
738
420d8b3f
FD
739 /*
740 * RFC3315 section 22.4, discard IA_NA's that
98bd7ca0
DH
741 * have t1 greater than t2, and both not zero.
742 * Since RFC3315 defines this behaviour, it is not
743 * an error - just normal operation.
744 *
745 * Note that RFC3315 says we MUST honor these values
746 * if they are not zero. So insane values are
747 * totally OK.
748 */
749 if ((ia->renew > 0) && (ia->rebind > 0) &&
750 (ia->renew > ia->rebind)) {
751 log_debug("RCV: | !-- INVALID renew/rebind "
752 "times, IA_NA discarded.");
753 dfree(ia, MDL);
754 data_string_forget(&ds, MDL);
755 continue;
756 }
757
758 if (ds.len > 12) {
759 log_debug("RCV: | X-- [Options]");
760
761 if (!option_state_allocate(&ia->options,
762 MDL)) {
763 log_error("Out of memory allocating "
420d8b3f 764 "IA_NA option state.");
98bd7ca0
DH
765 dfree(ia, MDL);
766 data_string_forget(&ds, MDL);
767 return ISC_R_NOMEMORY;
768 }
769
770 if (!parse_option_buffer(ia->options,
771 ds.data + 12,
772 ds.len - 12,
773 &dhcpv6_universe)) {
774 log_error("Corrupt IA_NA options.");
775 option_state_dereference(&ia->options,
776 MDL);
777 dfree(ia, MDL);
778 data_string_forget(&ds, MDL);
98bf1607 779 return DHCP_R_BADPARSE;
98bd7ca0
DH
780 }
781 }
782 data_string_forget(&ds, MDL);
783
784 if (ia->options != NULL) {
785 result = dhc6_parse_addrs(&ia->addrs, packet,
786 ia->options);
787 if (result != ISC_R_SUCCESS) {
788 option_state_dereference(&ia->options,
789 MDL);
790 dfree(ia, MDL);
791 return result;
792 }
793 }
794
c88dfebd
SR
795 /* If we have no addresses or the top level status code
796 * or the status code in this IA indicate no addresses
797 * toss the IA.
798 */
799 ia_code = STATUS_Success;
800 if ((ia->addrs == NULL) ||
801 (code == STATUS_NoAddrsAvail) ||
802 ((ia->options != NULL) &&
803 (dhc6_get_status_code(ia->options, &ia_code, NULL)
804 == ISC_R_SUCCESS) &&
805 (ia_code == STATUS_NoAddrsAvail))) {
806 log_debug("RCV: | !-- Status code of "
807 "no addrs, IA_NA discarded.");
808 dhc6_ia_destroy(&ia, MDL);
809 continue;
810 }
811
420d8b3f
FD
812 while (*pia != NULL)
813 pia = &(*pia)->next;
98bd7ca0
DH
814 *pia = ia;
815 pia = &ia->next;
816 } else {
817 log_error("Invalid IA_NA option cache.");
818 dfree(ia, MDL);
819 if (ds.len != 0)
820 data_string_forget(&ds, MDL);
821 return ISC_R_UNEXPECTED;
822 }
823 }
cabdb9b1 824 delete_option(&dhcpv6_universe, options, D6O_IA_NA);
98bd7ca0
DH
825
826 return ISC_R_SUCCESS;
827}
828
1d9774ab
FD
829static isc_result_t
830dhc6_parse_ia_ta(struct dhc6_ia **pia, struct packet *packet,
c88dfebd 831 struct option_state *options, unsigned code)
1d9774ab
FD
832{
833 struct data_string ds;
834 struct dhc6_ia *ia;
835 struct option_cache *oc;
836 isc_result_t result;
c88dfebd 837 unsigned ia_code;
1d9774ab
FD
838
839 memset(&ds, 0, sizeof(ds));
840
841 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_TA);
842 for ( ; oc != NULL ; oc = oc->next) {
843 ia = dmalloc(sizeof(*ia), MDL);
844 if (ia == NULL) {
845 log_error("Out of memory allocating IA_TA structure.");
846 return ISC_R_NOMEMORY;
847 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
848 options, NULL,
849 &global_scope, oc, MDL) &&
850 ds.len >= 4) {
851 memcpy(ia->iaid, ds.data, 4);
852 ia->ia_type = D6O_IA_TA;
853 ia->starts = cur_time;
854
855 log_debug("RCV: X-- IA_TA %s",
856 print_hex_1(4, ia->iaid, 59));
857 /* XXX: This should be the printed time I think. */
858 log_debug("RCV: | X-- starts %u",
859 (unsigned)ia->starts);
860
861 if (ds.len > 4) {
862 log_debug("RCV: | X-- [Options]");
863
864 if (!option_state_allocate(&ia->options,
865 MDL)) {
866 log_error("Out of memory allocating "
420d8b3f 867 "IA_TA option state.");
1d9774ab
FD
868 dfree(ia, MDL);
869 data_string_forget(&ds, MDL);
870 return ISC_R_NOMEMORY;
871 }
872
873 if (!parse_option_buffer(ia->options,
874 ds.data + 4,
875 ds.len - 4,
876 &dhcpv6_universe)) {
877 log_error("Corrupt IA_TA options.");
878 option_state_dereference(&ia->options,
879 MDL);
880 dfree(ia, MDL);
881 data_string_forget(&ds, MDL);
98bf1607 882 return DHCP_R_BADPARSE;
1d9774ab
FD
883 }
884 }
885 data_string_forget(&ds, MDL);
886
887 if (ia->options != NULL) {
888 result = dhc6_parse_addrs(&ia->addrs, packet,
889 ia->options);
890 if (result != ISC_R_SUCCESS) {
891 option_state_dereference(&ia->options,
892 MDL);
893 dfree(ia, MDL);
894 return result;
895 }
896 }
897
c88dfebd
SR
898 /* If we have no addresses or the top level status code
899 * or the status code in this IA indicate no addresses
900 * toss the IA.
901 */
902 ia_code = STATUS_Success;
903 if ((ia->addrs == NULL) ||
904 (code == STATUS_NoAddrsAvail) ||
905 ((ia->options != NULL) &&
906 (dhc6_get_status_code(ia->options, &ia_code, NULL)
907 == ISC_R_SUCCESS) &&
908 (ia_code == STATUS_NoAddrsAvail))) {
909 log_debug("RCV: | !-- Status code of "
910 "no addrs, IA_TA discarded.");
911 dhc6_ia_destroy(&ia, MDL);
912 continue;
913 }
914
420d8b3f
FD
915 while (*pia != NULL)
916 pia = &(*pia)->next;
1d9774ab
FD
917 *pia = ia;
918 pia = &ia->next;
919 } else {
920 log_error("Invalid IA_TA option cache.");
921 dfree(ia, MDL);
922 if (ds.len != 0)
923 data_string_forget(&ds, MDL);
924 return ISC_R_UNEXPECTED;
925 }
926 }
cabdb9b1 927 delete_option(&dhcpv6_universe, options, D6O_IA_TA);
1d9774ab
FD
928
929 return ISC_R_SUCCESS;
930}
931
932static isc_result_t
933dhc6_parse_ia_pd(struct dhc6_ia **pia, struct packet *packet,
c88dfebd 934 struct option_state *options, unsigned code)
1d9774ab
FD
935{
936 struct data_string ds;
937 struct dhc6_ia *ia;
938 struct option_cache *oc;
939 isc_result_t result;
c88dfebd 940 unsigned ia_code;
1d9774ab
FD
941
942 memset(&ds, 0, sizeof(ds));
943
944 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_PD);
945 for ( ; oc != NULL ; oc = oc->next) {
946 ia = dmalloc(sizeof(*ia), MDL);
947 if (ia == NULL) {
948 log_error("Out of memory allocating IA_PD structure.");
949 return ISC_R_NOMEMORY;
950 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
951 options, NULL,
952 &global_scope, oc, MDL) &&
953 ds.len >= 12) {
954 memcpy(ia->iaid, ds.data, 4);
955 ia->ia_type = D6O_IA_PD;
956 ia->starts = cur_time;
957 ia->renew = getULong(ds.data + 4);
958 ia->rebind = getULong(ds.data + 8);
959
960 log_debug("RCV: X-- IA_PD %s",
961 print_hex_1(4, ia->iaid, 59));
962 /* XXX: This should be the printed time I think. */
963 log_debug("RCV: | X-- starts %u",
964 (unsigned)ia->starts);
965 log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
966 log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
967
420d8b3f
FD
968 /*
969 * RFC3633 section 9, discard IA_PD's that
1d9774ab 970 * have t1 greater than t2, and both not zero.
420d8b3f 971 * Since RFC3633 defines this behaviour, it is not
1d9774ab
FD
972 * an error - just normal operation.
973 */
974 if ((ia->renew > 0) && (ia->rebind > 0) &&
975 (ia->renew > ia->rebind)) {
976 log_debug("RCV: | !-- INVALID renew/rebind "
977 "times, IA_PD discarded.");
978 dfree(ia, MDL);
979 data_string_forget(&ds, MDL);
980 continue;
981 }
982
983 if (ds.len > 12) {
984 log_debug("RCV: | X-- [Options]");
985
986 if (!option_state_allocate(&ia->options,
987 MDL)) {
988 log_error("Out of memory allocating "
420d8b3f 989 "IA_PD option state.");
1d9774ab
FD
990 dfree(ia, MDL);
991 data_string_forget(&ds, MDL);
992 return ISC_R_NOMEMORY;
993 }
994
995 if (!parse_option_buffer(ia->options,
996 ds.data + 12,
997 ds.len - 12,
998 &dhcpv6_universe)) {
999 log_error("Corrupt IA_PD options.");
1000 option_state_dereference(&ia->options,
1001 MDL);
1002 dfree(ia, MDL);
1003 data_string_forget(&ds, MDL);
98bf1607 1004 return DHCP_R_BADPARSE;
1d9774ab
FD
1005 }
1006 }
1007 data_string_forget(&ds, MDL);
1008
1009 if (ia->options != NULL) {
420d8b3f
FD
1010 result = dhc6_parse_prefixes(&ia->addrs,
1011 packet,
1012 ia->options);
1d9774ab
FD
1013 if (result != ISC_R_SUCCESS) {
1014 option_state_dereference(&ia->options,
1015 MDL);
1016 dfree(ia, MDL);
1017 return result;
1018 }
1019 }
1020
c88dfebd
SR
1021 /* If we have no prefixes or the top level status code
1022 * or the status code in this IA indicate no prefixes
1023 * toss the IA.
1024 */
1025 ia_code = STATUS_Success;
1026 if ((ia->addrs == NULL) ||
1027 (code == STATUS_NoPrefixAvail) ||
1028 ((ia->options != NULL) &&
1029 (dhc6_get_status_code(ia->options, &ia_code, NULL)
1030 == ISC_R_SUCCESS) &&
1031 (ia_code == STATUS_NoPrefixAvail))) {
1032 log_debug("RCV: | !-- Status code of "
1033 "no prefix, IA_PD discarded.");
1034 dhc6_ia_destroy(&ia, MDL);
1035 continue;
1036 }
1037
420d8b3f
FD
1038 while (*pia != NULL)
1039 pia = &(*pia)->next;
1d9774ab
FD
1040 *pia = ia;
1041 pia = &ia->next;
1042 } else {
1043 log_error("Invalid IA_PD option cache.");
1044 dfree(ia, MDL);
1045 if (ds.len != 0)
1046 data_string_forget(&ds, MDL);
1047 return ISC_R_UNEXPECTED;
1048 }
1049 }
cabdb9b1 1050 delete_option(&dhcpv6_universe, options, D6O_IA_PD);
1d9774ab
FD
1051
1052 return ISC_R_SUCCESS;
1053}
1054
98bd7ca0
DH
1055
1056static isc_result_t
1057dhc6_parse_addrs(struct dhc6_addr **paddr, struct packet *packet,
1058 struct option_state *options)
1059{
1060 struct data_string ds;
1061 struct option_cache *oc;
1062 struct dhc6_addr *addr;
c88dfebd
SR
1063 isc_result_t rval = ISC_R_SUCCESS;
1064 unsigned code;
98bd7ca0
DH
1065
1066 memset(&ds, 0, sizeof(ds));
1067
1068 oc = lookup_option(&dhcpv6_universe, options, D6O_IAADDR);
1069 for ( ; oc != NULL ; oc = oc->next) {
1070 addr = dmalloc(sizeof(*addr), MDL);
1071 if (addr == NULL) {
1072 log_error("Out of memory allocating "
1073 "address structure.");
1074 return ISC_R_NOMEMORY;
1075 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
1076 options, NULL, &global_scope,
1077 oc, MDL) &&
1078 (ds.len >= 24)) {
1079
1080 addr->address.len = 16;
1081 memcpy(addr->address.iabuf, ds.data, 16);
1082 addr->starts = cur_time;
1083 addr->preferred_life = getULong(ds.data + 16);
1084 addr->max_life = getULong(ds.data + 20);
1085
1086 log_debug("RCV: | | X-- IAADDR %s",
1087 piaddr(addr->address));
1088 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1089 addr->preferred_life);
1090 log_debug("RCV: | | | X-- Max lifetime %u.",
1091 addr->max_life);
1092
420d8b3f
FD
1093 /*
1094 * RFC 3315 section 22.6 says we must discard
98bd7ca0
DH
1095 * addresses whose pref is later than valid.
1096 */
1097 if ((addr->preferred_life > addr->max_life)) {
1098 log_debug("RCV: | | | !-- INVALID lifetimes, "
1099 "IAADDR discarded. Check your "
1100 "server configuration.");
1101 dfree(addr, MDL);
1102 data_string_forget(&ds, MDL);
1103 continue;
1104 }
1105
420d8b3f
FD
1106 /*
1107 * Fortunately this is the last recursion in the
98bd7ca0
DH
1108 * protocol.
1109 */
1110 if (ds.len > 24) {
1111 if (!option_state_allocate(&addr->options,
1112 MDL)) {
1113 log_error("Out of memory allocating "
1114 "IAADDR option state.");
1115 dfree(addr, MDL);
1116 data_string_forget(&ds, MDL);
1117 return ISC_R_NOMEMORY;
1118 }
1119
1120 if (!parse_option_buffer(addr->options,
1121 ds.data + 24,
1122 ds.len - 24,
1123 &dhcpv6_universe)) {
1124 log_error("Corrupt IAADDR options.");
1125 option_state_dereference(&addr->options,
1126 MDL);
1127 dfree(addr, MDL);
1128 data_string_forget(&ds, MDL);
98bf1607 1129 return DHCP_R_BADPARSE;
98bd7ca0
DH
1130 }
1131 }
1132
98bd7ca0
DH
1133 data_string_forget(&ds, MDL);
1134
c88dfebd
SR
1135 if (addr->options != NULL) {
1136 log_debug("RCV: | | | X-- [Options]");
1137
1138 /* Get the status code if the return value
1139 * indicates an error or the status code
1140 * indicates no address toss the address
1141 */
1142 code = STATUS_Success;
1143 rval = dhc6_check_status(ISC_R_SUCCESS,
1144 addr->options,
1145 "IAADDR", &code);
1146 if (rval != ISC_R_SUCCESS) {
1147 log_debug("RCV: | | | X-- Status code"
1148 " issue, IAADDR discarded.");
1149 option_state_dereference(&addr->options,
1150 MDL);
1151 dfree(addr, MDL);
1152 continue;
1153 }
1154 }
1155
98bd7ca0
DH
1156 *paddr = addr;
1157 paddr = &addr->next;
1158 } else {
1159 log_error("Invalid IAADDR option cache.");
1160 dfree(addr, MDL);
1161 if (ds.len != 0)
1162 data_string_forget(&ds, MDL);
1163 return ISC_R_UNEXPECTED;
1164 }
1165 }
cabdb9b1 1166 delete_option(&dhcpv6_universe, options, D6O_IAADDR);
98bd7ca0
DH
1167
1168 return ISC_R_SUCCESS;
1169}
1170
1d9774ab 1171static isc_result_t
420d8b3f
FD
1172dhc6_parse_prefixes(struct dhc6_addr **ppfx, struct packet *packet,
1173 struct option_state *options)
1d9774ab
FD
1174{
1175 struct data_string ds;
1176 struct option_cache *oc;
420d8b3f 1177 struct dhc6_addr *pfx;
c88dfebd
SR
1178 isc_result_t rval = ISC_R_SUCCESS;
1179 unsigned code;
1d9774ab
FD
1180
1181 memset(&ds, 0, sizeof(ds));
1182
1183 oc = lookup_option(&dhcpv6_universe, options, D6O_IAPREFIX);
1184 for ( ; oc != NULL ; oc = oc->next) {
420d8b3f
FD
1185 pfx = dmalloc(sizeof(*pfx), MDL);
1186 if (pfx == NULL) {
1d9774ab
FD
1187 log_error("Out of memory allocating "
1188 "prefix structure.");
1189 return ISC_R_NOMEMORY;
1190 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
1191 options, NULL, &global_scope,
1192 oc, MDL) &&
1193 (ds.len >= 25)) {
1194
420d8b3f
FD
1195 pfx->preferred_life = getULong(ds.data);
1196 pfx->max_life = getULong(ds.data + 4);
1197 pfx->plen = getUChar(ds.data + 8);
1198 pfx->address.len = 16;
1199 memcpy(pfx->address.iabuf, ds.data + 9, 16);
1200 pfx->starts = cur_time;
1d9774ab
FD
1201
1202 log_debug("RCV: | | X-- IAPREFIX %s/%d",
420d8b3f 1203 piaddr(pfx->address), (int)pfx->plen);
1d9774ab 1204 log_debug("RCV: | | | X-- Preferred lifetime %u.",
420d8b3f 1205 pfx->preferred_life);
1d9774ab 1206 log_debug("RCV: | | | X-- Max lifetime %u.",
420d8b3f 1207 pfx->max_life);
1d9774ab
FD
1208
1209 /* Sanity check over the prefix length */
420d8b3f 1210 if ((pfx->plen < 4) || (pfx->plen > 128)) {
1d9774ab
FD
1211 log_debug("RCV: | | | !-- INVALID prefix "
1212 "length, IAPREFIX discarded. "
1213 "Check your server configuration.");
420d8b3f 1214 dfree(pfx, MDL);
1d9774ab
FD
1215 data_string_forget(&ds, MDL);
1216 continue;
1217 }
420d8b3f
FD
1218 /*
1219 * RFC 3633 section 10 says we must discard
1d9774ab
FD
1220 * prefixes whose pref is later than valid.
1221 */
420d8b3f 1222 if ((pfx->preferred_life > pfx->max_life)) {
1d9774ab
FD
1223 log_debug("RCV: | | | !-- INVALID lifetimes, "
1224 "IAPREFIX discarded. Check your "
1225 "server configuration.");
420d8b3f 1226 dfree(pfx, MDL);
1d9774ab
FD
1227 data_string_forget(&ds, MDL);
1228 continue;
1229 }
1230
420d8b3f
FD
1231 /*
1232 * Fortunately this is the last recursion in the
1d9774ab
FD
1233 * protocol.
1234 */
1235 if (ds.len > 25) {
420d8b3f 1236 if (!option_state_allocate(&pfx->options,
1d9774ab
FD
1237 MDL)) {
1238 log_error("Out of memory allocating "
1239 "IAPREFIX option state.");
420d8b3f 1240 dfree(pfx, MDL);
1d9774ab
FD
1241 data_string_forget(&ds, MDL);
1242 return ISC_R_NOMEMORY;
1243 }
1244
420d8b3f 1245 if (!parse_option_buffer(pfx->options,
1d9774ab
FD
1246 ds.data + 25,
1247 ds.len - 25,
1248 &dhcpv6_universe)) {
1249 log_error("Corrupt IAPREFIX options.");
420d8b3f 1250 option_state_dereference(&pfx->options,
1d9774ab 1251 MDL);
420d8b3f 1252 dfree(pfx, MDL);
1d9774ab 1253 data_string_forget(&ds, MDL);
98bf1607 1254 return DHCP_R_BADPARSE;
1d9774ab
FD
1255 }
1256 }
1257
1d9774ab
FD
1258 data_string_forget(&ds, MDL);
1259
c88dfebd
SR
1260 if (pfx->options != NULL) {
1261 log_debug("RCV: | | | X-- [Options]");
1262
1263 /* Get the status code if the return value
1264 * indicates an error or the status code
1265 * indicates no prefix toss the prefix
1266 */
1267 code = STATUS_Success;
1268 rval = dhc6_check_status(ISC_R_SUCCESS,
1269 pfx->options,
1270 "IAPREFIX", &code);
1271 if (rval != ISC_R_SUCCESS) {
1272 log_debug("RCV: | | | X-- Status code"
1273 " issue IAPREFIX discarded.");
1274 option_state_dereference(&pfx->options,
1275 MDL);
1276 dfree(pfx, MDL);
1277 continue;
1278 }
1279 }
1280
420d8b3f
FD
1281 *ppfx = pfx;
1282 ppfx = &pfx->next;
1d9774ab
FD
1283 } else {
1284 log_error("Invalid IAPREFIX option cache.");
420d8b3f 1285 dfree(pfx, MDL);
1d9774ab
FD
1286 if (ds.len != 0)
1287 data_string_forget(&ds, MDL);
1288 return ISC_R_UNEXPECTED;
1289 }
1290 }
cabdb9b1 1291 delete_option(&dhcpv6_universe, options, D6O_IAPREFIX);
1d9774ab
FD
1292
1293 return ISC_R_SUCCESS;
1294}
1295
e32529a5 1296/* Clean up a lease object, deallocate all its parts, and set it to NULL. */
98bd7ca0 1297void
e32529a5 1298dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
98bd7ca0
DH
1299{
1300 struct dhc6_ia *ia, *nia;
420d8b3f 1301 struct dhc6_lease *lease;
98bd7ca0 1302
e32529a5 1303 if (src == NULL || *src == NULL) {
420d8b3f 1304 log_error("Attempt to destroy null lease.");
98bd7ca0 1305 return;
420d8b3f 1306 }
e32529a5 1307 lease = *src;
98bd7ca0
DH
1308
1309 if (lease->server_id.len != 0)
1310 data_string_forget(&lease->server_id, file, line);
1311
1312 for (ia = lease->bindings ; ia != NULL ; ia = nia) {
1313 nia = ia->next;
1314
e32529a5 1315 dhc6_ia_destroy(&ia, file, line);
98bd7ca0
DH
1316 }
1317
1318 if (lease->options != NULL)
1319 option_state_dereference(&lease->options, file, line);
1320
1321 dfree(lease, file, line);
420d8b3f 1322 *src = NULL;
98bd7ca0
DH
1323}
1324
e32529a5
EH
1325/*
1326 * Traverse the addresses list, and destroy their contents, and NULL the
1327 * list pointer.
1328 */
98bd7ca0 1329static void
e32529a5 1330dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line)
98bd7ca0
DH
1331{
1332 struct dhc6_addr *addr, *naddr;
420d8b3f 1333 struct dhc6_ia *ia;
e32529a5
EH
1334
1335 if (src == NULL || *src == NULL) {
420d8b3f 1336 log_error("Attempt to destroy null IA.");
e32529a5 1337 return;
420d8b3f 1338 }
af9271c5 1339 ia = *src;
98bd7ca0
DH
1340
1341 for (addr = ia->addrs ; addr != NULL ; addr = naddr) {
1342 naddr = addr->next;
1343
1344 if (addr->options != NULL)
1345 option_state_dereference(&addr->options, file, line);
1346
1347 dfree(addr, file, line);
1348 }
1349
1350 if (ia->options != NULL)
1351 option_state_dereference(&ia->options, file, line);
1352
1353 dfree(ia, file, line);
420d8b3f 1354 *src = NULL;
98bd7ca0
DH
1355}
1356
420d8b3f
FD
1357/*
1358 * For a given lease, insert it into the tail of the lease list. Upon
98bd7ca0
DH
1359 * finding a duplicate by server id, remove it and take over its position.
1360 */
1361static void
1362insert_lease(struct dhc6_lease **head, struct dhc6_lease *new)
1363{
1364 while (*head != NULL) {
1365 if ((*head)->server_id.len == new->server_id.len &&
1366 memcmp((*head)->server_id.data, new->server_id.data,
1367 new->server_id.len) == 0) {
1368 new->next = (*head)->next;
e32529a5 1369 dhc6_lease_destroy(head, MDL);
98bd7ca0
DH
1370 break;
1371 }
1372
1373 head= &(*head)->next;
1374 }
1375
1376 *head = new;
1377 return;
1378}
1379
c88dfebd
SR
1380/*!
1381 *
1382 * \brief Determine a score for a lease. We use this to
1383 * compare and choose leases if we receive multiple candidates.
1384 *
1385 * We originally started with scores of 50 for a binding and 100 for
1386 * an address. This would select multiple adresses over multiple
1387 * bindings. As part of the 7550 work I've changed this to be
1388 * 10000 for a binding, 100 for an address and 1 for an option.
1389 * This will cause us to choose a lease with more bindings over
1390 * a lease with less bindings but more addresses which seems
1391 * to be the best selection criteria to me.
1392 * In theory we could end up with a lease with enough addresses
1393 * or options being better but at 100 to 1 I don't think it's likely.
1394 *
1395 * \param client = the state of the entire client
1396 * \param lease = the lease to score.
1397 *
1398 * \retrun the score of the lease
98bd7ca0 1399 */
c88dfebd
SR
1400
1401/* The scores for individual items. */
1402#ifdef USE_ORIGINAL_CLIENT_LEASE_WEIGHTS
1403#define SCORE_BINDING 50
1404#define SCORE_ADDRESS 100
1405#else
1406#define SCORE_BINDING 10000
1407#define SCORE_ADDRESS 100
1408#endif
1409
1410#define SCORE_OPTION 1
1411/* We need a lease with at least 1 binding and 1 address */
1412#define SCORE_MIN (SCORE_BINDING + SCORE_ADDRESS)
1413
98bd7ca0 1414static int
0c20eab3 1415dhc6_score_lease(struct client_state *client, struct dhc6_lease *lease)
98bd7ca0
DH
1416{
1417 struct dhc6_ia *ia;
1418 struct dhc6_addr *addr;
0c20eab3
DH
1419 struct option **req;
1420 int i;
98bd7ca0
DH
1421
1422 if (lease->score)
1423 return lease->score;
1424
c88dfebd 1425 lease->score = SCORE_OPTION;
98bd7ca0 1426
0c20eab3
DH
1427 /* If this lease lacks a required option, dump it. */
1428 /* XXX: we should be able to cache the failure... */
1429 req = client->config->required_options;
1430 if (req != NULL) {
1431 for (i = 0 ; req[i] != NULL ; i++) {
1432 if (lookup_option(&dhcpv6_universe, lease->options,
1433 req[i]->code) == NULL) {
1434 lease->score = 0;
1435 return lease->score;
1436 }
1437 }
1438 }
1439
420d8b3f 1440 /* If this lease contains a requested option, improve its score. */
0c20eab3
DH
1441 req = client->config->requested_options;
1442 if (req != NULL) {
1443 for (i = 0 ; req[i] != NULL ; i++) {
1444 if (lookup_option(&dhcpv6_universe, lease->options,
1445 req[i]->code) != NULL)
c88dfebd 1446 lease->score += SCORE_OPTION;
0c20eab3 1447 }
98bd7ca0 1448 }
98bd7ca0
DH
1449
1450 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
c88dfebd 1451 lease->score += SCORE_BINDING;
98bd7ca0
DH
1452
1453 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
c88dfebd 1454 lease->score += SCORE_ADDRESS;
98bd7ca0
DH
1455 }
1456 }
1457
1458 return lease->score;
1459}
1460
420d8b3f
FD
1461/*
1462 * start_init6() kicks off the process, transmitting a packet and
98bd7ca0
DH
1463 * scheduling a retransmission event.
1464 */
1465void
1466start_init6(struct client_state *client)
1467{
be62cf06
FD
1468 struct timeval tv;
1469
98bd7ca0
DH
1470 log_debug("PRC: Soliciting for leases (INIT).");
1471 client->state = S_INIT;
1472
98bd7ca0 1473 /* Initialize timers, RFC3315 section 17.1.2. */
be62cf06
FD
1474 client->IRT = SOL_TIMEOUT * 100;
1475 client->MRT = SOL_MAX_RT * 100;
98bd7ca0 1476 client->MRC = 0;
ffbaa880
FD
1477 /* Default is 0 (no max) but -1 changes this. */
1478 if (!onetry)
1479 client->MRD = 0;
1480 else
1481 client->MRD = client->config->timeout;
98bd7ca0
DH
1482
1483 dhc6_retrans_init(client);
3dbe2246
FD
1484
1485 /*
420d8b3f 1486 * RFC3315 section 17.1.2 goes out of its way:
98bd7ca0
DH
1487 * Also, the first RT MUST be selected to be strictly greater than IRT
1488 * by choosing RAND to be strictly greater than 0.
1489 */
be62cf06
FD
1490 /* if RAND < 0 then RAND = -RAND */
1491 if (client->RT <= client->IRT)
1492 client->RT = client->IRT + (client->IRT - client->RT);
1493 /* if RAND == 0 then RAND = 1 */
98bd7ca0
DH
1494 if (client->RT <= client->IRT)
1495 client->RT = client->IRT + 1;
1496
1497 client->v6_handler = init_handler;
1498
420d8b3f
FD
1499 /*
1500 * RFC3315 section 17.1.2 says we MUST start the first packet
98bd7ca0
DH
1501 * between 0 and SOL_MAX_DELAY seconds. The good news is
1502 * SOL_MAX_DELAY is 1.
1503 */
be62cf06
FD
1504 tv.tv_sec = cur_tv.tv_sec;
1505 tv.tv_usec = cur_tv.tv_usec;
1506 tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
1507 if (tv.tv_usec >= 1000000) {
1508 tv.tv_sec += 1;
1509 tv.tv_usec -= 1000000;
1510 }
1511 add_timeout(&tv, do_init6, client, NULL, NULL);
8ea19a71
DH
1512
1513 if (nowait)
29b23207 1514 detach();
98bd7ca0
DH
1515}
1516
420d8b3f
FD
1517/*
1518 * start_info_request6() kicks off the process, transmitting an info
3dbe2246
FD
1519 * request packet and scheduling a retransmission event.
1520 */
1521void
1522start_info_request6(struct client_state *client)
1523{
1524 struct timeval tv;
1525
1526 log_debug("PRC: Requesting information (INIT).");
1527 client->state = S_INIT;
1528
1529 /* Initialize timers, RFC3315 section 18.1.5. */
1530 client->IRT = INF_TIMEOUT * 100;
1531 client->MRT = INF_MAX_RT * 100;
1532 client->MRC = 0;
ffbaa880
FD
1533 /* Default is 0 (no max) but -1 changes this. */
1534 if (!onetry)
1535 client->MRD = 0;
1536 else
1537 client->MRD = client->config->timeout;
3dbe2246
FD
1538
1539 dhc6_retrans_init(client);
1540
1541 client->v6_handler = info_request_handler;
1542
420d8b3f
FD
1543 /*
1544 * RFC3315 section 18.1.5 says we MUST start the first packet
3dbe2246
FD
1545 * between 0 and INF_MAX_DELAY seconds. The good news is
1546 * INF_MAX_DELAY is 1.
1547 */
1548 tv.tv_sec = cur_tv.tv_sec;
1549 tv.tv_usec = cur_tv.tv_usec;
1550 tv.tv_usec += (random() % (INF_MAX_DELAY * 100)) * 10000;
1551 if (tv.tv_usec >= 1000000) {
1552 tv.tv_sec += 1;
1553 tv.tv_usec -= 1000000;
1554 }
1555 add_timeout(&tv, do_info_request6, client, NULL, NULL);
1556
1557 if (nowait)
29b23207 1558 detach();
3dbe2246
FD
1559}
1560
420d8b3f
FD
1561/*
1562 * start_confirm6() kicks off an "init-reboot" version of the process, at
98bd7ca0
DH
1563 * startup to find out if old bindings are 'fair' and at runtime whenever
1564 * a link cycles state we'll eventually want to do this.
1565 */
1566void
1567start_confirm6(struct client_state *client)
1568{
be62cf06
FD
1569 struct timeval tv;
1570
98bd7ca0 1571 /* If there is no active lease, there is nothing to check. */
420d8b3f
FD
1572 if ((client->active_lease == NULL) ||
1573 !active_prefix(client) ||
f1fc5ede
TM
1574 client->active_lease->released ||
1575 !unexpired_address_in_lease(client->active_lease)) {
1576 dhc6_lease_destroy(&client->active_lease, MDL);
98bd7ca0
DH
1577 start_init6(client);
1578 return;
1579 }
1580
1581 log_debug("PRC: Confirming active lease (INIT-REBOOT).");
1582 client->state = S_REBOOTING;
1583
98bd7ca0 1584 /* Initialize timers, RFC3315 section 17.1.3. */
be62cf06
FD
1585 client->IRT = CNF_TIMEOUT * 100;
1586 client->MRT = CNF_MAX_RT * 100;
98bd7ca0
DH
1587 client->MRC = 0;
1588 client->MRD = CNF_MAX_RD;
1589
1590 dhc6_retrans_init(client);
1591
1592 client->v6_handler = reply_handler;
1593
420d8b3f
FD
1594 /*
1595 * RFC3315 section 18.1.2 says we MUST start the first packet
be62cf06
FD
1596 * between 0 and CNF_MAX_DELAY seconds. The good news is
1597 * CNF_MAX_DELAY is 1.
1598 */
1599 tv.tv_sec = cur_tv.tv_sec;
1600 tv.tv_usec = cur_tv.tv_usec;
1601 tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
1602 if (tv.tv_usec >= 1000000) {
1603 tv.tv_sec += 1;
1604 tv.tv_usec -= 1000000;
1605 }
c88dfebd
SR
1606
1607 /* We do a rebind instead of a confirm if the user
1608 * is requesting PDs or previously requesed PDs or
1609 * increased the number of NAs or TAs they want
1610 * Confirms don't tell us if PDs are still on-link and
1611 * we won't add new IAs on a confirm.
1612 */
1613
1614 if ((wanted_ia_pd != 0) ||
1615 (dhc6_count_ia(client->active_lease, D6O_IA_PD) != 0) ||
1616 (dhc6_count_ia(client->active_lease, D6O_IA_NA) < wanted_ia_na) ||
1617 (dhc6_count_ia(client->active_lease, D6O_IA_TA) < wanted_ia_ta)) {
420d8b3f
FD
1618 client->state = S_REBINDING;
1619 client->refresh_type = DHCPV6_REBIND;
1620 add_timeout(&tv, do_refresh6, client, NULL, NULL);
1621 } else
1622 add_timeout(&tv, do_confirm6, client, NULL, NULL);
98bd7ca0
DH
1623}
1624
420d8b3f 1625/*
197c917e
SR
1626 * check_timing6() check on the timing for sending a v6 message
1627 * and then do the basic initialization for a v6 message.
98bd7ca0 1628 */
197c917e
SR
1629#define CHK_TIM_SUCCESS 0
1630#define CHK_TIM_MRC_EXCEEDED 1
1631#define CHK_TIM_MRD_EXCEEDED 2
1632#define CHK_TIM_ALLOC_FAILURE 3
1633
1634int
c88dfebd 1635check_timing6 (struct client_state *client, u_int8_t msg_type,
197c917e
SR
1636 char *msg_str, struct dhc6_lease *lease,
1637 struct data_string *ds)
98bd7ca0 1638{
197c917e 1639 struct timeval elapsed;
98bd7ca0 1640
be62cf06
FD
1641 /*
1642 * Start_time starts at the first transmission.
1643 */
1644 if (client->txcount == 0) {
1645 client->start_time.tv_sec = cur_tv.tv_sec;
1646 client->start_time.tv_usec = cur_tv.tv_usec;
197c917e
SR
1647 } else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
1648 log_info("Max retransmission count exceeded.");
1649 return(CHK_TIM_MRC_EXCEEDED);
be62cf06
FD
1650 }
1651
1652 /* elapsed = cur - start */
1653 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
1654 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
1655 if (elapsed.tv_usec < 0) {
1656 elapsed.tv_sec -= 1;
1657 elapsed.tv_usec += 1000000;
1658 }
197c917e 1659
ffbaa880 1660 /* Check if finished (-1 argument). */
b6ab3f6c 1661 if ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD)) {
98bd7ca0 1662 log_info("Max retransmission duration exceeded.");
197c917e 1663 return(CHK_TIM_MRD_EXCEEDED);
98bd7ca0
DH
1664 }
1665
197c917e
SR
1666 memset(ds, 0, sizeof(*ds));
1667 if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
1668 log_error("Unable to allocate memory for %s.", msg_str);
1669 return(CHK_TIM_ALLOC_FAILURE);
98bd7ca0 1670 }
197c917e
SR
1671 ds->data = ds->buffer->data;
1672 ds->len = 4;
98bd7ca0 1673
197c917e
SR
1674 ds->buffer->data[0] = msg_type;
1675 memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
98bd7ca0
DH
1676
1677 /* Form an elapsed option. */
be62cf06
FD
1678 /* Maximum value is 65535 1/100s coded as 0xffff. */
1679 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
1680 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
98bd7ca0 1681 client->elapsed = 0xffff;
be62cf06
FD
1682 } else {
1683 client->elapsed = elapsed.tv_sec * 100;
1684 client->elapsed += elapsed.tv_usec / 10000;
1685 }
98bd7ca0 1686
be62cf06 1687 if (client->elapsed == 0)
197c917e 1688 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
be62cf06 1689 else
197c917e 1690 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
be62cf06 1691 (unsigned)client->elapsed);
98bd7ca0
DH
1692
1693 client->elapsed = htons(client->elapsed);
1694
197c917e
SR
1695 make_client6_options(client, &client->sent_options, lease, msg_type);
1696
1697 return(CHK_TIM_SUCCESS);
1698}
1699
c88dfebd
SR
1700/*!
1701 *
1702 * \brief Create an iaid from information from the client.
1703 *
1704 * \param client = the state of the entire client
1705 * \param ia = the ia to fill in
1706 * \param idx = index of the ia in case we are doing multiples
1707 * \param len = length of the base IA (4 for TA, 12 for NA & PD)
1708 *
1709 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1710 * an error and the packet should be tossed
1711 */
1712
1713static isc_result_t
1714dhc6_create_iaid(struct client_state *client,
1715 struct data_string *ia,
1716 int idx,
1717 unsigned len)
1718{
1719 int start_idx, copy_len;
1720
1721 memset(ia, 0, sizeof(*ia));
c0e9661e 1722 if (!buffer_allocate(&ia->buffer, len, MDL)) {
c88dfebd
SR
1723 return (ISC_R_NOMEMORY);
1724 }
1725 ia->data = ia->buffer->data;
1726 ia->len = len;
1727
1728 /*
1729 * A simple IAID is the last 4 bytes
1730 * of the hardware address.
1731 */
1732 if (client->interface->hw_address.hlen > 4) {
1733 start_idx = client->interface->hw_address.hlen - 4;
1734 copy_len = 4;
1735 } else {
1736 start_idx = 0;
1737 copy_len = client->interface->hw_address.hlen;
1738 }
1739 memcpy(ia->buffer->data,
1740 client->interface->hw_address.hbuf + start_idx,
1741 copy_len);
1742 if (idx)
1743 ia->buffer->data[3] += idx;
1744
1745 return (ISC_R_SUCCESS);
1746}
1747
1748/*!
1749 *
1750 * \brief Add bare IA_NAs, IA_TAs or IA_PDs to the packet we are building.
1751 *
1752 * Attempt to add the number of bare IAs indicated by wanted to
1753 * the packet. As we have already added a number of IAs based
1754 * on what is in the current lease after we create an IAID we check
1755 * it against the current lease and skip any that are already in use.
1756 *
1757 * \param client = the state of the entire client
1758 * \param packet = the packet we are building and where we
1759 * shall append the IA_NA, IA_TA or IA_PDs we create
1760 * \param wanted = the number of IA_NA, IA_TA or IA_PDs we want to create
1761 * \param ia_type = the type of the IAs we want to create: NA, TA or PD.
1762 *
1763 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1764 * an error and the packet should be tossed
1765 */
1766static isc_result_t
1767dhc6_bare_ia_xx(struct client_state *client,
1768 struct data_string *packet,
1769 int wanted,
1770 u_int16_t ia_type)
1771{
1772 struct dhc6_ia *old_ia;
1773 struct data_string ia;
1774 u_int32_t t1, t2;
1775 int i, len;
1776 isc_result_t rval;
1777 char *type_string;
1778 struct option *type_option;
1779
1780 /* figure out what type of option we are working with */
1781 switch (ia_type) {
1782 case D6O_IA_NA:
1783 type_string = "IA_NA";
1784 type_option = ia_na_option;
c0e9661e 1785 len = IA_NA_OFFSET;
c88dfebd
SR
1786 break;
1787 case D6O_IA_TA:
1788 type_string = "IA_TA";
1789 type_option = ia_ta_option;
c0e9661e 1790 len = IA_TA_OFFSET;
c88dfebd
SR
1791 break;
1792 case D6O_IA_PD:
1793 type_string = "IA_PD";
1794 type_option = ia_pd_option;
c0e9661e
TM
1795 len = IA_PD_OFFSET;
1796 if (prefix_len_hint > 0) {
1797 len += IASUBOPT_PD_LEN;
1798 }
c88dfebd 1799 break;
c0e9661e 1800
c88dfebd
SR
1801 default:
1802 return (ISC_R_FAILURE);
1803 }
1804
1805 for (i = 0; wanted != 0; i++) {
1806 rval = dhc6_create_iaid(client, &ia, i, len);
1807 if (rval != ISC_R_SUCCESS) {
1808 log_error("Unable to allocate memory for %s.",
1809 type_string);
1810 return (rval);
1811 }
1812
1813 /* If we are already using this IAID, skip it and try again */
1814 if ((client->active_lease != NULL) &&
1815 ((old_ia = find_ia(client->active_lease->bindings,
1816 ia_type,
1817 (char *)ia.buffer->data)) != NULL)) {
1818 data_string_forget(&ia, MDL);
1819 continue;
1820 }
1821
1822 /* We have a good IAID, log it */
1823 log_debug("XMT: X-- %s %s",
1824 type_string, print_hex_1(4, ia.buffer->data, 55));
1825
1826 /* If we are requesting an NA or a PD we also want to add
1827 * the renew and rebind times we are requesting.
1828 */
c0e9661e 1829 if (ia_type != D6O_IA_TA) {
c88dfebd
SR
1830 t1 = client->config->requested_lease / 2;
1831 t2 = t1 + (t1 / 2);
1832 putULong(ia.buffer->data + 4, t1);
1833 putULong(ia.buffer->data + 8, t2);
1834
1835 log_debug("XMT: | X-- Request renew in +%u",
1836 (unsigned)t1);
1837 log_debug("XMT: | X-- Request rebind in +%u",
1838 (unsigned)t2);
1839 }
1840
c0e9661e
TM
1841 if (ia_type == D6O_IA_PD && prefix_len_hint > 0) {
1842 unsigned char *ptr = ia.buffer->data + IA_NA_OFFSET;
1843 putUShort(ptr, D6O_IAPREFIX);
1844 ptr += 2;
1845 putUShort(ptr, IASUBOPT_PD_LEN);
1846 ptr += 2;
1847 putUChar(ptr + IASUBOPT_PD_PREFLEN_OFFSET,
1848 prefix_len_hint);
1849 log_debug("XMT: | | X-- Request prefix ::/%u.",
1850 prefix_len_hint);
1851 }
1852
c88dfebd
SR
1853 /* and append it to the packet */
1854 append_option(packet, &dhcpv6_universe, type_option, &ia);
1855 data_string_forget(&ia, MDL);
1856
1857 /* decrement the number of IAs we want */
1858 wanted--;
1859 }
1860
1861 return (ISC_R_SUCCESS);
1862}
1863
197c917e
SR
1864/*
1865 * do_init6() marshals and transmits a solicit.
1866 */
1867void
1868do_init6(void *input)
1869{
1870 struct client_state *client;
1871 struct dhc6_ia *old_ia;
1872 struct dhc6_addr *old_addr;
1873 struct data_string ds;
1874 struct data_string ia;
1875 struct data_string addr;
1876 struct timeval tv;
1877 u_int32_t t1, t2;
c88dfebd 1878 int i, send_ret;
197c917e
SR
1879
1880 client = input;
1881
1882 /*
1883 * In RFC3315 section 17.1.2, the retransmission timer is
1884 * used as the selecting timer.
1885 */
1886 if (client->advertised_leases != NULL) {
1887 start_selecting6(client);
1888 return;
1889 }
1890
1891 switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
1892 case CHK_TIM_MRC_EXCEEDED:
1893 case CHK_TIM_ALLOC_FAILURE:
1894 return;
1895 case CHK_TIM_MRD_EXCEEDED:
1896 client->state = S_STOPPED;
1897 if (client->active_lease != NULL) {
1898 dhc6_lease_destroy(&client->active_lease, MDL);
1899 client->active_lease = NULL;
1900 }
1901 /* Stop if and only if this is the last client. */
1902 if (stopping_finished())
29b23207 1903 finish(2);
197c917e
SR
1904 return;
1905 }
98bd7ca0 1906
420d8b3f
FD
1907 /*
1908 * Fetch any configured 'sent' options (includes DUID) in wire format.
98bd7ca0
DH
1909 */
1910 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
1911 NULL, client->sent_options, &global_scope,
1912 &dhcpv6_universe);
1913
420d8b3f 1914 /* Use a specific handler with rapid-commit. */
6d7f9584
FD
1915 if (lookup_option(&dhcpv6_universe, client->sent_options,
1916 D6O_RAPID_COMMIT) != NULL) {
1917 client->v6_handler = rapid_commit_handler;
1918 }
1919
420d8b3f
FD
1920 /* Append IA_NA. */
1921 for (i = 0; i < wanted_ia_na; i++) {
1922 /*
1923 * XXX: maybe the IA_NA('s) should be put into the sent_options
1924 * cache. They'd have to be pulled down as they also contain
1925 * different option caches in the same universe...
1926 */
c88dfebd 1927 if (dhc6_create_iaid(client, &ia, i, 12) != ISC_R_SUCCESS) {
420d8b3f
FD
1928 log_error("Unable to allocate memory for IA_NA.");
1929 data_string_forget(&ds, MDL);
1930 return;
1931 }
420d8b3f
FD
1932
1933 t1 = client->config->requested_lease / 2;
1934 t2 = t1 + (t1 / 2);
1935 putULong(ia.buffer->data + 4, t1);
1936 putULong(ia.buffer->data + 8, t2);
1937
1938 log_debug("XMT: X-- IA_NA %s",
1939 print_hex_1(4, ia.buffer->data, 55));
1940 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
1941 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
1942
1943 if ((client->active_lease != NULL) &&
1944 ((old_ia = find_ia(client->active_lease->bindings,
1945 D6O_IA_NA,
1946 (char *)ia.buffer->data)) != NULL)) {
1947 /*
1948 * For each address in the old IA_NA,
1949 * request a binding.
1950 */
1951 memset(&addr, 0, sizeof(addr));
1952 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1953 old_addr = old_addr->next) {
1954 if (old_addr->address.len != 16) {
1955 log_error("Invalid IPv6 address "
1956 "length %d. "
1957 "Ignoring. (%s:%d)",
1958 old_addr->address.len,
1959 MDL);
1960 continue;
1961 }
98bd7ca0 1962
420d8b3f
FD
1963 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
1964 log_error("Unable to allocate memory "
1965 "for IAADDR.");
1966 data_string_forget(&ia, MDL);
1967 data_string_forget(&ds, MDL);
1968 return;
1969 }
1970 addr.data = addr.buffer->data;
1971 addr.len = 24;
1972
1973 memcpy(addr.buffer->data,
1974 old_addr->address.iabuf,
1975 16);
1976
1977 t1 = client->config->requested_lease;
1978 t2 = t1 + (t1 / 2);
1979 putULong(addr.buffer->data + 16, t1);
1980 putULong(addr.buffer->data + 20, t2);
1981
1982 log_debug("XMT: | X-- Request address %s.",
1983 piaddr(old_addr->address));
1984 log_debug("XMT: | | X-- Request "
1985 "preferred in +%u",
1986 (unsigned)t1);
1987 log_debug("XMT: | | X-- Request valid "
1988 "in +%u",
1989 (unsigned)t2);
1990
1991 append_option(&ia, &dhcpv6_universe,
1992 iaaddr_option,
1993 &addr);
1994
1995 data_string_forget(&addr, MDL);
98bd7ca0 1996 }
420d8b3f 1997 }
98bd7ca0 1998
420d8b3f
FD
1999 append_option(&ds, &dhcpv6_universe, ia_na_option, &ia);
2000 data_string_forget(&ia, MDL);
2001 }
98bd7ca0 2002
420d8b3f
FD
2003 /* Append IA_TA. */
2004 for (i = 0; i < wanted_ia_ta; i++) {
2005 /*
2006 * XXX: maybe the IA_TA('s) should be put into the sent_options
2007 * cache. They'd have to be pulled down as they also contain
2008 * different option caches in the same universe...
2009 */
c88dfebd 2010 if (dhc6_create_iaid(client, &ia, i, 4) != ISC_R_SUCCESS) {
420d8b3f
FD
2011 log_error("Unable to allocate memory for IA_TA.");
2012 data_string_forget(&ds, MDL);
2013 return;
2014 }
420d8b3f
FD
2015
2016 log_debug("XMT: X-- IA_TA %s",
2017 print_hex_1(4, ia.buffer->data, 55));
2018
2019 if ((client->active_lease != NULL) &&
2020 ((old_ia = find_ia(client->active_lease->bindings,
2021 D6O_IA_TA,
2022 (char *)ia.buffer->data)) != NULL)) {
2023 /*
2024 * For each address in the old IA_TA,
2025 * request a binding.
2026 */
2027 memset(&addr, 0, sizeof(addr));
2028 for (old_addr = old_ia->addrs ; old_addr != NULL ;
2029 old_addr = old_addr->next) {
2030 if (old_addr->address.len != 16) {
2031 log_error("Invalid IPv6 address "
2032 "length %d. "
2033 "Ignoring. (%s:%d)",
2034 old_addr->address.len,
2035 MDL);
2036 continue;
2037 }
98bd7ca0 2038
420d8b3f
FD
2039 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
2040 log_error("Unable to allocate memory "
2041 "for IAADDR.");
2042 data_string_forget(&ia, MDL);
2043 data_string_forget(&ds, MDL);
2044 return;
2045 }
2046 addr.data = addr.buffer->data;
2047 addr.len = 24;
2048
2049 memcpy(addr.buffer->data,
2050 old_addr->address.iabuf,
2051 16);
2052
2053 t1 = client->config->requested_lease;
2054 t2 = t1 + (t1 / 2);
2055 putULong(addr.buffer->data + 16, t1);
2056 putULong(addr.buffer->data + 20, t2);
2057
2058 log_debug("XMT: | X-- Request address %s.",
2059 piaddr(old_addr->address));
2060 log_debug("XMT: | | X-- Request "
2061 "preferred in +%u",
2062 (unsigned)t1);
2063 log_debug("XMT: | | X-- Request valid "
2064 "in +%u",
2065 (unsigned)t2);
2066
2067 append_option(&ia, &dhcpv6_universe,
2068 iaaddr_option,
2069 &addr);
2070
2071 data_string_forget(&addr, MDL);
2072 }
98bd7ca0 2073 }
420d8b3f
FD
2074
2075 append_option(&ds, &dhcpv6_universe, ia_ta_option, &ia);
2076 data_string_forget(&ia, MDL);
98bd7ca0
DH
2077 }
2078
420d8b3f
FD
2079 /* Append IA_PD. */
2080 for (i = 0; i < wanted_ia_pd; i++) {
2081 /*
2082 * XXX: maybe the IA_PD('s) should be put into the sent_options
2083 * cache. They'd have to be pulled down as they also contain
2084 * different option caches in the same universe...
2085 */
2086 memset(&ia, 0, sizeof(ia));
c88dfebd 2087 if (dhc6_create_iaid(client, &ia, i, 12) != ISC_R_SUCCESS) {
420d8b3f
FD
2088 log_error("Unable to allocate memory for IA_PD.");
2089 data_string_forget(&ds, MDL);
2090 return;
2091 }
420d8b3f
FD
2092
2093 t1 = client->config->requested_lease / 2;
2094 t2 = t1 + (t1 / 2);
2095 putULong(ia.buffer->data + 4, t1);
2096 putULong(ia.buffer->data + 8, t2);
2097
2098 log_debug("XMT: X-- IA_PD %s",
2099 print_hex_1(4, ia.buffer->data, 55));
2100 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
2101 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
2102
2103 if ((client->active_lease != NULL) &&
2104 ((old_ia = find_ia(client->active_lease->bindings,
2105 D6O_IA_PD,
2106 (char *)ia.buffer->data)) != NULL)) {
2107 /*
2108 * For each prefix in the old IA_PD,
2109 * request a binding.
2110 */
2111 memset(&addr, 0, sizeof(addr));
2112 for (old_addr = old_ia->addrs ; old_addr != NULL ;
2113 old_addr = old_addr->next) {
2114 if (old_addr->address.len != 16) {
2115 log_error("Invalid IPv6 prefix, "
2116 "Ignoring. (%s:%d)",
2117 MDL);
2118 continue;
2119 }
2120
2121 if (!buffer_allocate(&addr.buffer, 25, MDL)) {
2122 log_error("Unable to allocate memory "
2123 "for IAPREFIX.");
2124 data_string_forget(&ia, MDL);
2125 data_string_forget(&ds, MDL);
2126 return;
2127 }
2128 addr.data = addr.buffer->data;
2129 addr.len = 25;
2130
2131 t1 = client->config->requested_lease;
2132 t2 = t1 + (t1 / 2);
2133 putULong(addr.buffer->data, t1);
2134 putULong(addr.buffer->data + 4, t2);
2135
2136 putUChar(addr.buffer->data + 8,
2137 old_addr->plen);
2138 memcpy(addr.buffer->data + 9,
2139 old_addr->address.iabuf,
2140 16);
2141
2142 log_debug("XMT: | X-- Request prefix %s/%u.",
2143 piaddr(old_addr->address),
2144 (unsigned) old_addr->plen);
2145 log_debug("XMT: | | X-- Request "
2146 "preferred in +%u",
2147 (unsigned)t1);
2148 log_debug("XMT: | | X-- Request valid "
2149 "in +%u",
2150 (unsigned)t2);
2151
2152 append_option(&ia, &dhcpv6_universe,
2153 iaprefix_option,
2154 &addr);
2155
2156 data_string_forget(&addr, MDL);
2157 }
c0e9661e
TM
2158 } else if (prefix_len_hint > 0) {
2159 memset(&addr, 0, sizeof(addr));
2160 if (!buffer_allocate(&addr.buffer, 25, MDL)) {
2161 log_error("Unable to allocate memory "
2162 "for IAPREFIX.");
2163 data_string_forget(&ia, MDL);
2164 data_string_forget(&ds, MDL);
2165 return;
2166 }
2167
2168 addr.data = addr.buffer->data;
2169 addr.len = 25;
2170
2171 putUChar(addr.buffer->data + 8, prefix_len_hint);
2172 log_debug("XMT: | | X-- Request prefix ::/%u.",
2173 prefix_len_hint);
2174 append_option(&ia, &dhcpv6_universe, iaprefix_option,
2175 &addr);
2176 data_string_forget(&addr, MDL);
420d8b3f
FD
2177 }
2178
2179 append_option(&ds, &dhcpv6_universe, ia_pd_option, &ia);
2180 data_string_forget(&ia, MDL);
2181 }
98bd7ca0
DH
2182
2183 /* Transmit and wait. */
2184
be62cf06 2185 log_info("XMT: Solicit on %s, interval %ld0ms.",
98bd7ca0 2186 client->name ? client->name : client->interface->name,
9aa669fc 2187 (long int)client->RT);
98bd7ca0
DH
2188
2189 send_ret = send_packet6(client->interface,
2190 ds.data, ds.len, &DHCPv6DestAddr);
2191 if (send_ret != ds.len) {
2192 log_error("dhc6: send_packet6() sent %d of %d bytes",
2193 send_ret, ds.len);
2194 }
2195
2196 data_string_forget(&ds, MDL);
2197
be62cf06
FD
2198 /* Wait RT */
2199 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2200 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2201 if (tv.tv_usec >= 1000000) {
2202 tv.tv_sec += 1;
2203 tv.tv_usec -= 1000000;
2204 }
2205 add_timeout(&tv, do_init6, client, NULL, NULL);
98bd7ca0
DH
2206
2207 dhc6_retrans_advance(client);
2208}
2209
3dbe2246
FD
2210/* do_info_request6() marshals and transmits an information-request. */
2211void
2212do_info_request6(void *input)
2213{
2214 struct client_state *client;
2215 struct data_string ds;
197c917e 2216 struct timeval tv;
3dbe2246
FD
2217 int send_ret;
2218
2219 client = input;
2220
197c917e
SR
2221 switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
2222 "Info-Request", NULL, &ds)) {
2223 case CHK_TIM_MRC_EXCEEDED:
2224 case CHK_TIM_ALLOC_FAILURE:
3dbe2246 2225 return;
197c917e 2226 case CHK_TIM_MRD_EXCEEDED:
29b23207 2227 finish(2);
197c917e
SR
2228 case CHK_TIM_SUCCESS:
2229 break;
3dbe2246
FD
2230 }
2231
3dbe2246
FD
2232 /* Fetch any configured 'sent' options (includes DUID) in wire format.
2233 */
2234 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
2235 NULL, client->sent_options, &global_scope,
2236 &dhcpv6_universe);
2237
2238 /* Transmit and wait. */
2239
2240 log_info("XMT: Info-Request on %s, interval %ld0ms.",
2241 client->name ? client->name : client->interface->name,
2242 (long int)client->RT);
2243
2244 send_ret = send_packet6(client->interface,
2245 ds.data, ds.len, &DHCPv6DestAddr);
2246 if (send_ret != ds.len) {
2247 log_error("dhc6: send_packet6() sent %d of %d bytes",
2248 send_ret, ds.len);
2249 }
2250
2251 data_string_forget(&ds, MDL);
2252
2253 /* Wait RT */
2254 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2255 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2256 if (tv.tv_usec >= 1000000) {
2257 tv.tv_sec += 1;
2258 tv.tv_usec -= 1000000;
2259 }
2260 add_timeout(&tv, do_info_request6, client, NULL, NULL);
2261
2262 dhc6_retrans_advance(client);
2263}
2264
98bd7ca0
DH
2265/* do_confirm6() creates a Confirm packet and transmits it. This function
2266 * is called on every timeout to (re)transmit.
2267 */
2268void
2269do_confirm6(void *input)
2270{
2271 struct client_state *client;
98bd7ca0 2272 struct data_string ds;
c88dfebd 2273 int send_ret, added;
197c917e 2274 struct timeval tv;
98bd7ca0
DH
2275
2276 client = input;
2277
2278 if (client->active_lease == NULL)
2279 log_fatal("Impossible condition at %s:%d.", MDL);
2280
2281 /* In section 17.1.3, it is said:
2282 *
2283 * If the client receives no responses before the message
2284 * transmission process terminates, as described in section 14,
2285 * the client SHOULD continue to use any IP addresses, using the
2286 * last known lifetimes for those addresses, and SHOULD continue
2287 * to use any other previously obtained configuration parameters.
2288 *
2289 * So if confirm times out, we go active.
2290 *
2291 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
2292 * stick there until we get a reply?
2293 */
2294
197c917e
SR
2295 switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
2296 client->active_lease, &ds)) {
2297 case CHK_TIM_MRC_EXCEEDED:
2298 case CHK_TIM_MRD_EXCEEDED:
98bd7ca0
DH
2299 start_bound(client);
2300 return;
197c917e 2301 case CHK_TIM_ALLOC_FAILURE:
98bd7ca0 2302 return;
197c917e
SR
2303 case CHK_TIM_SUCCESS:
2304 break;
98bd7ca0 2305 }
98bd7ca0
DH
2306
2307 /* Fetch any configured 'sent' options (includes DUID') in wire format.
2308 */
2309 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
2310 client->sent_options, &global_scope,
2311 &dhcpv6_universe);
2312
2313 /* Append IA's. */
420d8b3f
FD
2314 if (wanted_ia_na &&
2315 dhc6_add_ia_na(client, &ds, client->active_lease,
c88dfebd 2316 DHCPV6_CONFIRM, 0, &added) != ISC_R_SUCCESS) {
420d8b3f
FD
2317 data_string_forget(&ds, MDL);
2318 return;
2319 }
2320 if (wanted_ia_ta &&
2321 dhc6_add_ia_ta(client, &ds, client->active_lease,
c88dfebd 2322 DHCPV6_CONFIRM, 0, &added) != ISC_R_SUCCESS) {
af5fa176
EH
2323 data_string_forget(&ds, MDL);
2324 return;
2325 }
98bd7ca0 2326
af5fa176 2327 /* Transmit and wait. */
98bd7ca0 2328
be62cf06 2329 log_info("XMT: Confirm on %s, interval %ld0ms.",
af5fa176 2330 client->name ? client->name : client->interface->name,
9aa669fc 2331 (long int)client->RT);
98bd7ca0 2332
af5fa176
EH
2333 send_ret = send_packet6(client->interface, ds.data, ds.len,
2334 &DHCPv6DestAddr);
2335 if (send_ret != ds.len) {
2336 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2337 send_ret, ds.len);
2338 }
98bd7ca0 2339
af5fa176 2340 data_string_forget(&ds, MDL);
98bd7ca0 2341
be62cf06
FD
2342 /* Wait RT */
2343 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2344 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2345 if (tv.tv_usec >= 1000000) {
2346 tv.tv_sec += 1;
2347 tv.tv_usec -= 1000000;
2348 }
2349 add_timeout(&tv, do_confirm6, client, NULL, NULL);
98bd7ca0 2350
af5fa176
EH
2351 dhc6_retrans_advance(client);
2352}
98bd7ca0 2353
af5fa176
EH
2354/*
2355 * Release addresses.
2356 */
2357void
2358start_release6(struct client_state *client)
2359{
420d8b3f 2360 /* Cancel any pending transmissions */
af5fa176
EH
2361 cancel_timeout(do_confirm6, client);
2362 cancel_timeout(do_select6, client);
2363 cancel_timeout(do_refresh6, client);
2364 cancel_timeout(do_release6, client);
0f69ff73 2365 cancel_timeout(do_decline6, client);
420d8b3f 2366 client->state = S_STOPPED;
af5fa176 2367
420d8b3f
FD
2368 /*
2369 * It is written: "The client MUST NOT use any of the addresses it
2370 * is releasing as the source address in the Release message or in
2371 * any subsequently transmitted message." So unconfigure now.
2372 */
2373 unconfigure6(client, "RELEASE6");
af5fa176 2374
cabdb9b1
FD
2375 /* Note this in the lease file. */
2376 if (client->active_lease == NULL)
2377 return;
2378 client->active_lease->released = ISC_TRUE;
2379 write_client6_lease(client, client->active_lease, 0, 1);
2380
87202683 2381 /* Set timers per RFC3315 section 18.1.6. */
be62cf06 2382 client->IRT = REL_TIMEOUT * 100;
af5fa176 2383 client->MRT = 0;
87202683 2384 client->MRC = REL_MAX_RC;
af5fa176 2385 client->MRD = 0;
98bd7ca0 2386
af5fa176
EH
2387 dhc6_retrans_init(client);
2388 client->v6_handler = reply_handler;
2389
af5fa176
EH
2390 do_release6(client);
2391}
2392/*
2393 * do_release6() creates a Release packet and transmits it.
2394 */
2395static void
2396do_release6(void *input)
2397{
af5fa176 2398 struct client_state *client;
af5fa176 2399 struct data_string ds;
c88dfebd 2400 int send_ret, added;
be62cf06 2401 struct timeval tv;
af5fa176
EH
2402
2403 client = input;
2404
420d8b3f 2405 if ((client->active_lease == NULL) || !active_prefix(client))
96b620e5 2406 return;
af5fa176 2407
c88dfebd 2408 switch(check_timing6(client, DHCPV6_RELEASE, "Release",
197c917e
SR
2409 client->active_lease, &ds)) {
2410 case CHK_TIM_MRC_EXCEEDED:
2411 case CHK_TIM_ALLOC_FAILURE:
2412 case CHK_TIM_MRD_EXCEEDED:
87202683 2413 goto release_done;
197c917e
SR
2414 case CHK_TIM_SUCCESS:
2415 break;
be62cf06
FD
2416 }
2417
af5fa176 2418 /*
87202683
FD
2419 * Don't use unicast as we don't know if we still have an
2420 * available address with enough scope.
af5fa176 2421 */
98bd7ca0 2422
af5fa176
EH
2423 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
2424 client->sent_options, &global_scope,
2425 &dhcpv6_universe);
2426
420d8b3f
FD
2427 /* Append IA's (but don't release temporary addresses). */
2428 if (wanted_ia_na &&
2429 dhc6_add_ia_na(client, &ds, client->active_lease,
c88dfebd 2430 DHCPV6_RELEASE, 0, &added) != ISC_R_SUCCESS) {
420d8b3f
FD
2431 data_string_forget(&ds, MDL);
2432 goto release_done;
2433 }
2434 if (wanted_ia_pd &&
2435 dhc6_add_ia_pd(client, &ds, client->active_lease,
c88dfebd 2436 DHCPV6_RELEASE, 0, &added) != ISC_R_SUCCESS) {
af5fa176 2437 data_string_forget(&ds, MDL);
87202683 2438 goto release_done;
af5fa176
EH
2439 }
2440
2441 /* Transmit and wait. */
be62cf06 2442 log_info("XMT: Release on %s, interval %ld0ms.",
98bd7ca0 2443 client->name ? client->name : client->interface->name,
9aa669fc 2444 (long int)client->RT);
98bd7ca0
DH
2445
2446 send_ret = send_packet6(client->interface, ds.data, ds.len,
2447 &DHCPv6DestAddr);
2448 if (send_ret != ds.len) {
2449 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2450 send_ret, ds.len);
2451 }
2452
2453 data_string_forget(&ds, MDL);
2454
be62cf06
FD
2455 /* Wait RT */
2456 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2457 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2458 if (tv.tv_usec >= 1000000) {
2459 tv.tv_sec += 1;
2460 tv.tv_usec -= 1000000;
2461 }
2462 add_timeout(&tv, do_release6, client, NULL, NULL);
98bd7ca0 2463 dhc6_retrans_advance(client);
87202683
FD
2464 return;
2465
2466 release_done:
2467 dhc6_lease_destroy(&client->active_lease, MDL);
2468 client->active_lease = NULL;
2469 if (stopping_finished())
29b23207 2470 finish(0);
98bd7ca0
DH
2471}
2472
2473/* status_log() just puts a status code into displayable form and logs it
2474 * to info level.
2475 */
2476static void
06eb8bab 2477status_log(int code, const char *scope, const char *additional, int len)
98bd7ca0 2478{
06eb8bab 2479 const char *msg = NULL;
98bd7ca0
DH
2480
2481 switch(code) {
2482 case STATUS_Success:
e32529a5 2483 msg = "Success";
98bd7ca0
DH
2484 break;
2485
2486 case STATUS_UnspecFail:
2487 msg = "UnspecFail";
2488 break;
87202683 2489
98bd7ca0
DH
2490 case STATUS_NoAddrsAvail:
2491 msg = "NoAddrsAvail";
2492 break;
2493
2494 case STATUS_NoBinding:
2495 msg = "NoBinding";
2496 break;
2497
2498 case STATUS_NotOnLink:
2499 msg = "NotOnLink";
2500 break;
2501
2502 case STATUS_UseMulticast:
2503 msg = "UseMulticast";
2504 break;
2505
420d8b3f
FD
2506 case STATUS_NoPrefixAvail:
2507 msg = "NoPrefixAvail";
2508 break;
2509
98bd7ca0
DH
2510 default:
2511 msg = "UNKNOWN";
2512 break;
2513 }
2514
2515 if (len > 0)
2516 log_info("%s status code %s: %s", scope, msg,
420d8b3f
FD
2517 print_hex_1(len,
2518 (const unsigned char *)additional, 50));
98bd7ca0
DH
2519 else
2520 log_info("%s status code %s.", scope, msg);
2521}
2522
2523/* Acquire a status code.
2524 */
2525static isc_result_t
2526dhc6_get_status_code(struct option_state *options, unsigned *code,
2527 struct data_string *msg)
2528{
2529 struct option_cache *oc;
2530 struct data_string ds;
2531 isc_result_t rval = ISC_R_SUCCESS;
2532
2533 if ((options == NULL) || (code == NULL))
98bf1607 2534 return DHCP_R_INVALIDARG;
98bd7ca0
DH
2535
2536 if ((msg != NULL) && (msg->len != 0))
98bf1607 2537 return DHCP_R_INVALIDARG;
98bd7ca0
DH
2538
2539 memset(&ds, 0, sizeof(ds));
2540
2541 /* Assume success if there is no option. */
2542 *code = STATUS_Success;
2543
2544 oc = lookup_option(&dhcpv6_universe, options, D6O_STATUS_CODE);
2545 if ((oc != NULL) &&
2546 evaluate_option_cache(&ds, NULL, NULL, NULL, options,
2547 NULL, &global_scope, oc, MDL)) {
2548 if (ds.len < 2) {
2549 log_error("Invalid status code length %d.", ds.len);
98bf1607 2550 rval = DHCP_R_FORMERR;
98bd7ca0
DH
2551 } else
2552 *code = getUShort(ds.data);
2553
2554 if ((msg != NULL) && (ds.len > 2)) {
2555 data_string_copy(msg, &ds, MDL);
2556 msg->data += 2;
2557 msg->len -= 2;
2558 }
2559
2560 data_string_forget(&ds, MDL);
2561 return rval;
2562 }
2563
2564 return ISC_R_NOTFOUND;
2565}
2566
2567/* Look at status codes in an advertise, and reform the return value.
2568 */
2569static isc_result_t
2570dhc6_check_status(isc_result_t rval, struct option_state *options,
06eb8bab 2571 const char *scope, unsigned *code)
98bd7ca0
DH
2572{
2573 struct data_string msg;
2574 isc_result_t status;
2575
2576 if ((scope == NULL) || (code == NULL))
98bf1607 2577 return DHCP_R_INVALIDARG;
98bd7ca0
DH
2578
2579 /* If we don't find a code, we assume success. */
2580 *code = STATUS_Success;
2581
2582 /* If there is no options cache, then there is no code. */
2583 if (options != NULL) {
2584 memset(&msg, 0, sizeof(msg));
2585 status = dhc6_get_status_code(options, code, &msg);
2586
2587 if (status == ISC_R_SUCCESS) {
28868515 2588 status_log(*code, scope, (char *)msg.data, msg.len);
98bd7ca0
DH
2589 data_string_forget(&msg, MDL);
2590
2591 if (*code != STATUS_Success)
2592 rval = ISC_R_FAILURE;
2593
2594 } else if (status != ISC_R_NOTFOUND)
2595 rval = status;
2596 }
2597
2598 return rval;
2599}
2600
c88dfebd
SR
2601/* Determine if this packet could provide usable information.
2602 * We check the status codes at the top level and at the IA level,
2603 * IAADDRS have already been checked in the leaseify step and any with
2604 * a bad format or status code that wasn't success have been dropped.
2605 *
2606 * leaseify has also already removed any IAs for which the top level status
2607 * code or the IA status code indicated no addresses or prefixes were
2608 * available.
98bd7ca0
DH
2609 */
2610static isc_result_t
2611dhc6_check_advertise(struct dhc6_lease *lease)
2612{
2613 struct dhc6_ia *ia;
98bd7ca0
DH
2614 isc_result_t rval = ISC_R_SUCCESS;
2615 int have_addrs = ISC_FALSE;
2616 unsigned code;
1d9774ab 2617 const char *scope;
c88dfebd 2618 int got_na = 0, got_ta = 0, got_pd = 0;
98bd7ca0
DH
2619
2620 rval = dhc6_check_status(rval, lease->options, "message", &code);
2621
2622 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
1d9774ab
FD
2623 switch (ia->ia_type) {
2624 case D6O_IA_NA:
1d9774ab 2625 scope = "IA_NA";
c88dfebd 2626 got_na++;
1d9774ab
FD
2627 break;
2628 case D6O_IA_TA:
2629 scope = "IA_TA";
c88dfebd 2630 got_ta++;
1d9774ab
FD
2631 break;
2632 case D6O_IA_PD:
2633 scope = "IA_PD";
c88dfebd 2634 got_pd++;
1d9774ab 2635 break;
420d8b3f
FD
2636 default:
2637 log_error("dhc6_check_advertise: no type.");
2638 return ISC_R_FAILURE;
1d9774ab 2639 }
c88dfebd
SR
2640 /* Currently we toss packets if we have an error getting a
2641 * status code or if the status code isn't success, so
2642 * no need to loop through the addresses */
1d9774ab 2643 rval = dhc6_check_status(rval, ia->options, scope, &code);
c88dfebd
SR
2644 if (rval != ISC_R_SUCCESS)
2645 continue;
98bd7ca0 2646
c88dfebd
SR
2647 /* We don't need to check status on IAADDRS here as we already
2648 * did it as part of the leaseify step and tossed bad IAADDRS.
2649 * We are just checking to see if we have any addrs.
2650 * Should we check the addr itself for usability?
2651 */
2652 if (ia->addrs != NULL) {
98bd7ca0
DH
2653 have_addrs = ISC_TRUE;
2654 }
2655 }
2656
c88dfebd
SR
2657 /* If we didn't get some addrs or the user required us to
2658 * get all of the requested IAs and we didn't return an error
2659 */
2660 if ((have_addrs != ISC_TRUE) ||
2661 ((require_all_ias != 0) &&
2662 ((got_na < wanted_ia_na) ||
2663 (got_ta < wanted_ia_ta) ||
2664 (got_pd < wanted_ia_pd))))
98bd7ca0
DH
2665 rval = ISC_R_ADDRNOTAVAIL;
2666
2667 return rval;
2668}
2669
6d7f9584
FD
2670/* status code <-> action matrix for the client in INIT state
2671 * (rapid/commit). Returns always false as no action is defined.
2672 */
2673static isc_boolean_t
87202683 2674dhc6_init_action(struct client_state *client, isc_result_t *rvalp,
6d7f9584
FD
2675 unsigned code)
2676{
87202683
FD
2677 if (rvalp == NULL)
2678 log_fatal("Impossible condition at %s:%d.", MDL);
6d7f9584 2679
87202683 2680 if (client == NULL) {
98bf1607 2681 *rvalp = DHCP_R_INVALIDARG;
87202683
FD
2682 return ISC_FALSE;
2683 }
2684
2685 if (*rvalp == ISC_R_SUCCESS)
6d7f9584
FD
2686 return ISC_FALSE;
2687
2688 /* No possible action in any case... */
2689 return ISC_FALSE;
2690}
2691
98bd7ca0
DH
2692/* status code <-> action matrix for the client in SELECT state
2693 * (request/reply). Returns true if action was taken (and the
2694 * packet should be ignored), or false if no action was taken.
2695 */
2696static isc_boolean_t
87202683 2697dhc6_select_action(struct client_state *client, isc_result_t *rvalp,
98bd7ca0
DH
2698 unsigned code)
2699{
2700 struct dhc6_lease *lease;
87202683 2701 isc_result_t rval;
98bd7ca0 2702
87202683
FD
2703 if (rvalp == NULL)
2704 log_fatal("Impossible condition at %s:%d.", MDL);
2705
2706 if (client == NULL) {
98bf1607 2707 *rvalp = DHCP_R_INVALIDARG;
87202683
FD
2708 return ISC_FALSE;
2709 }
2710 rval = *rvalp;
98bd7ca0
DH
2711
2712 if (rval == ISC_R_SUCCESS)
2713 return ISC_FALSE;
2714
2715 switch (code) {
2716 /* We may have an earlier failure status code (so no
2717 * success rval), and a success code now. This
2718 * doesn't upgrade the rval to success, but it does
2719 * mean we take no action here.
2720 */
2721 case STATUS_Success:
2722 /* Gimpy server, or possibly an attacker. */
2723 case STATUS_NoBinding:
2724 case STATUS_UseMulticast:
2725 /* Take no action. */
2726 return ISC_FALSE;
2727
2728 /* If the server can't deal with us, either try the
2729 * next advertised server, or continue retrying if there
2730 * weren't any.
2731 */
2732 default:
2733 case STATUS_UnspecFail:
2734 if (client->advertised_leases != NULL) {
e32529a5 2735 dhc6_lease_destroy(&client->selected_lease, MDL);
98bd7ca0
DH
2736 client->selected_lease = NULL;
2737
2738 start_selecting6(client);
2739
2740 break;
2741 } else /* Take no action - continue to retry. */
2742 return ISC_FALSE;
2743
2744 /* If the server has no addresses, try other servers if
2745 * we got some, otherwise go to INIT to hope for more
2746 * servers.
2747 */
2748 case STATUS_NoAddrsAvail:
420d8b3f 2749 case STATUS_NoPrefixAvail:
98bd7ca0
DH
2750 if (client->state == S_REBOOTING)
2751 return ISC_FALSE;
2752
2753 if (client->selected_lease == NULL)
2754 log_fatal("Impossible case at %s:%d.", MDL);
2755
e32529a5 2756 dhc6_lease_destroy(&client->selected_lease, MDL);
98bd7ca0
DH
2757 client->selected_lease = NULL;
2758
2759 if (client->advertised_leases != NULL)
2760 start_selecting6(client);
2761 else
2762 start_init6(client);
2763
2764 break;
2765
2766 /* If we got a NotOnLink from a Confirm, then we're not
2767 * on link. Kill the old-active binding and start over.
2768 *
2769 * If we got a NotOnLink from our Request, something weird
2770 * happened. Start over from scratch anyway.
2771 */
2772 case STATUS_NotOnLink:
2773 if (client->state == S_REBOOTING) {
2774 if (client->active_lease == NULL)
2775 log_fatal("Impossible case at %s:%d.", MDL);
2776
e32529a5 2777 dhc6_lease_destroy(&client->active_lease, MDL);
98bd7ca0
DH
2778 } else {
2779 if (client->selected_lease == NULL)
2780 log_fatal("Impossible case at %s:%d.", MDL);
2781
e32529a5 2782 dhc6_lease_destroy(&client->selected_lease, MDL);
98bd7ca0
DH
2783 client->selected_lease = NULL;
2784
2785 while (client->advertised_leases != NULL) {
2786 lease = client->advertised_leases;
2787 client->advertised_leases = lease->next;
2788
e32529a5 2789 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
2790 }
2791 }
2792
2793 start_init6(client);
2794 break;
2795 }
2796
2797 return ISC_TRUE;
2798}
2799
2800static void
2801dhc6_withdraw_lease(struct client_state *client)
2802{
2803 struct dhc6_ia *ia;
2804 struct dhc6_addr *addr;
98bd7ca0
DH
2805
2806 if ((client == NULL) || (client->active_lease == NULL))
2807 return;
2808
2809 for (ia = client->active_lease->bindings ; ia != NULL ;
2810 ia = ia->next) {
2811 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
2812 addr->max_life = addr->preferred_life = 0;
2813 }
2814 }
2815
2816 /* Perform expiry. */
2817 do_expire(client);
2818}
2819
2820/* status code <-> action matrix for the client in BOUND state
2821 * (request/reply). Returns true if action was taken (and the
2822 * packet should be ignored), or false if no action was taken.
2823 */
2824static isc_boolean_t
87202683 2825dhc6_reply_action(struct client_state *client, isc_result_t *rvalp,
98bd7ca0
DH
2826 unsigned code)
2827{
87202683 2828 isc_result_t rval;
98bd7ca0 2829
87202683
FD
2830 if (rvalp == NULL)
2831 log_fatal("Impossible condition at %s:%d.", MDL);
2832
2833 if (client == NULL) {
98bf1607 2834 *rvalp = DHCP_R_INVALIDARG;
87202683
FD
2835 return ISC_FALSE;
2836 }
2837 rval = *rvalp;
98bd7ca0
DH
2838
2839 if (rval == ISC_R_SUCCESS)
2840 return ISC_FALSE;
2841
2842 switch (code) {
2843 /* It's possible an earlier status code set rval to a failure
2844 * code, and we've encountered a later success.
2845 */
2846 case STATUS_Success:
2847 /* In "refreshes" (where we get replies), we probably
2848 * still have a valid lease. So "take no action" and
2849 * the upper levels will keep retrying until the lease
2850 * expires (or we rebind).
2851 */
2852 case STATUS_UnspecFail:
2853 /* For unknown codes...it's a soft (retryable) error. */
2854 default:
2855 return ISC_FALSE;
2856
2857 /* The server is telling us to use a multicast address, so
2858 * we have to delete the unicast option from the active
2859 * lease, then allow retransmission to occur normally.
2860 * (XXX: It might be preferable in this case to retransmit
2861 * sooner than the current interval, but for now we don't.)
2862 */
2863 case STATUS_UseMulticast:
87202683 2864 if (client->active_lease != NULL)
98bd7ca0
DH
2865 delete_option(&dhcp_universe,
2866 client->active_lease->options,
2867 D6O_UNICAST);
2868 return ISC_FALSE;
2869
2870 /* "When the client receives a NotOnLink status from the
2871 * server in response to a Request, the client can either
2872 * re-issue the Request without specifying any addresses
2873 * or restart the DHCP server discovery process."
2874 *
2875 * This is strange. If competing server evaluation is
2876 * useful (and therefore in the protocol), then why would
2877 * a client's first reaction be to request from the same
2878 * server on a different link? Surely you'd want to
2879 * re-evaluate your server selection.
2880 *
2881 * Well, I guess that's the answer.
2882 */
2883 case STATUS_NotOnLink:
2884 /* In this case, we need to rescind all current active
2885 * bindings (just 'expire' them all normally, if early).
2886 * They're no use to us on the wrong link. Then head back
2887 * to init, redo server selection and get new addresses.
2888 */
2889 dhc6_withdraw_lease(client);
87202683 2890 break;
98bd7ca0
DH
2891
2892 /* "If the status code is NoAddrsAvail, the client has
2893 * received no usable addresses in the IA and may choose
2894 * to try obtaining addresses for the IA from another
2895 * server."
2896 */
2897 case STATUS_NoAddrsAvail:
420d8b3f 2898 case STATUS_NoPrefixAvail:
98bd7ca0
DH
2899 /* Head back to init, keeping any active bindings (!). */
2900 start_init6(client);
2901 break;
2902
2903 /* - sends a Request message if the IA contained a Status
2904 * Code option with the NoBinding status (and does not
2905 * send any additional Renew/Rebind messages)
2906 */
2907 case STATUS_NoBinding:
2908 if (client->advertised_leases != NULL)
2909 log_fatal("Impossible condition at %s:%d.", MDL);
2910
2911 client->advertised_leases =
2912 dhc6_dup_lease(client->active_lease, MDL);
2913 start_selecting6(client);
2914 break;
2915 }
2916
2917 return ISC_TRUE;
2918}
2919
87202683
FD
2920/* status code <-> action matrix for the client in STOPPED state
2921 * (release/decline). Returns true if action was taken (and the
2922 * packet should be ignored), or false if no action was taken.
2923 * NoBinding is translated into Success.
2924 */
2925static isc_boolean_t
2926dhc6_stop_action(struct client_state *client, isc_result_t *rvalp,
2927 unsigned code)
2928{
2929 isc_result_t rval;
2930
2931 if (rvalp == NULL)
2932 log_fatal("Impossible condition at %s:%d.", MDL);
2933
2934 if (client == NULL) {
98bf1607 2935 *rvalp = DHCP_R_INVALIDARG;
87202683
FD
2936 return ISC_FALSE;
2937 }
2938 rval = *rvalp;
2939
2940 if (rval == ISC_R_SUCCESS)
2941 return ISC_FALSE;
2942
2943 switch (code) {
2944 /* It's possible an earlier status code set rval to a failure
2945 * code, and we've encountered a later success.
2946 */
2947 case STATUS_Success:
2948 /* For unknown codes...it's a soft (retryable) error. */
2949 case STATUS_UnspecFail:
2950 default:
2951 return ISC_FALSE;
2952
2953 /* NoBinding is not an error */
2954 case STATUS_NoBinding:
2955 if (rval == ISC_R_FAILURE)
2956 *rvalp = ISC_R_SUCCESS;
2957 return ISC_FALSE;
2958
2959 /* Should not happen */
2960 case STATUS_NoAddrsAvail:
420d8b3f 2961 case STATUS_NoPrefixAvail:
87202683
FD
2962 break;
2963
2964 /* Give up on it */
2965 case STATUS_NotOnLink:
2966 break;
2967
2968 /* The server is telling us to use a multicast address, so
2969 * we have to delete the unicast option from the active
2970 * lease, then allow retransmission to occur normally.
2971 * (XXX: It might be preferable in this case to retransmit
2972 * sooner than the current interval, but for now we don't.)
2973 */
2974 case STATUS_UseMulticast:
2975 if (client->active_lease != NULL)
2976 delete_option(&dhcp_universe,
2977 client->active_lease->options,
2978 D6O_UNICAST);
2979 return ISC_FALSE;
2980 }
2981
2982 return ISC_TRUE;
2983}
2984
0f69ff73
TM
2985static isc_boolean_t
2986dhc6_decline_action(struct client_state *client, isc_result_t *rvalp,
2987 unsigned code)
2988{
2989 isc_result_t rval;
2990
2991 if (rvalp == NULL)
2992 log_fatal("Impossible condition at %s:%d.", MDL);
2993
2994 if (client == NULL) {
2995 *rvalp = DHCP_R_INVALIDARG;
2996 return ISC_FALSE;
2997 }
2998 rval = *rvalp;
2999
3000 if (rval == ISC_R_SUCCESS) {
3001 return ISC_FALSE;
3002 }
3003
3004 switch (code) {
3005 case STATUS_UseMulticast:
3006 /* The server is telling us to use a multicast address, so
3007 * we have to delete the unicast option from the active
3008 * lease, then allow retransmission to occur normally.
3009 * (XXX: It might be preferable in this case to retransmit
3010 * sooner than the current interval, but for now we don't.)
3011 */
3012 if (client->active_lease != NULL)
3013 delete_option(&dhcp_universe,
3014 client->active_lease->options,
3015 D6O_UNICAST);
3016 return ISC_FALSE;
3017 default:
3018 /* Anything else is basically meaningless */
3019 break;
3020 }
3021
3022 return ISC_TRUE;
3023}
3024
3025
98bd7ca0
DH
3026/* Look at a new and old lease, and make sure the new information is not
3027 * losing us any state.
3028 */
3029static isc_result_t
3030dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
3031{
87202683
FD
3032 isc_boolean_t (*action)(struct client_state *,
3033 isc_result_t *, unsigned);
98bd7ca0 3034 struct dhc6_ia *ia;
28868515 3035 isc_result_t rval = ISC_R_SUCCESS;
98bd7ca0 3036 unsigned code;
1d9774ab 3037 const char *scope;
98bd7ca0 3038 int nscore, sscore;
c88dfebd
SR
3039 int have_addrs = ISC_FALSE;
3040 int got_na = 0, got_ta = 0, got_pd = 0;
98bd7ca0
DH
3041
3042 if ((client == NULL) || (new == NULL))
98bf1607 3043 return DHCP_R_INVALIDARG;
98bd7ca0
DH
3044
3045 switch (client->state) {
6d7f9584
FD
3046 case S_INIT:
3047 action = dhc6_init_action;
3048 break;
3049
98bd7ca0
DH
3050 case S_SELECTING:
3051 case S_REBOOTING:
3052 action = dhc6_select_action;
3053 break;
3054
3055 case S_RENEWING:
3056 case S_REBINDING:
3057 action = dhc6_reply_action;
3058 break;
3059
87202683
FD
3060 case S_STOPPED:
3061 action = dhc6_stop_action;
3062 break;
3063
0f69ff73
TM
3064 case S_DECLINING:
3065 action = dhc6_decline_action;
3066 break;
3067
98bd7ca0
DH
3068 default:
3069 log_fatal("Impossible condition at %s:%d.", MDL);
3070 return ISC_R_CANCELED;
3071 }
3072
3073 /* If there is a code to extract, and if there is some
3074 * action to take based on that code, then take the action
3075 * and do not continue.
3076 */
3077 rval = dhc6_check_status(rval, new->options, "message", &code);
87202683 3078 if (action(client, &rval, code))
98bd7ca0
DH
3079 return ISC_R_CANCELED;
3080
3081 for (ia = new->bindings ; ia != NULL ; ia = ia->next) {
1d9774ab
FD
3082 switch (ia->ia_type) {
3083 case D6O_IA_NA:
1d9774ab 3084 scope = "IA_NA";
c88dfebd 3085 got_na++;
1d9774ab
FD
3086 break;
3087 case D6O_IA_TA:
3088 scope = "IA_TA";
c88dfebd 3089 got_ta++;
1d9774ab
FD
3090 break;
3091 case D6O_IA_PD:
3092 scope = "IA_PD";
c88dfebd 3093 got_pd++;
1d9774ab 3094 break;
420d8b3f
FD
3095 default:
3096 log_error("dhc6_check_reply: no type.");
98bf1607 3097 return DHCP_R_INVALIDARG;
1d9774ab 3098 }
c88dfebd
SR
3099 rval = dhc6_check_status(rval, ia->options, scope, &code);
3100
87202683 3101 if (action(client, &rval, code))
98bd7ca0
DH
3102 return ISC_R_CANCELED;
3103
c88dfebd
SR
3104 if (ia->addrs != NULL) {
3105 have_addrs = ISC_TRUE;
98bd7ca0
DH
3106 }
3107 }
3108
9ab0cc6a
DH
3109 /* A Confirm->Reply is unsuitable for comparison to the old lease. */
3110 if (client->state == S_REBOOTING)
3111 return rval;
3112
c88dfebd
SR
3113 /* We expect the lease to have at least one address and if
3114 * required all of the requested IAs if not flag it as
3115 * NoAddrs and call the action routine to try again.
3116 *
3117 * Currently we don't completely handle TAs in all cases
3118 * so we don't check them for requires. I've left the
3119 * check in and commented it as I eventually do want
3120 * us to check for TAs as well. SAR
3121 */
3122 if ((have_addrs != ISC_TRUE) ||
3123 ((require_all_ias != 0) &&
3124 ((got_na < wanted_ia_na) ||
3125 /*(got_ta < wanted_ia_ta) ||*/
3126 (got_pd < wanted_ia_pd)))) {
3127 rval = ISC_R_FAILURE;
3128 if (action(client, &rval, STATUS_NoAddrsAvail) == ISC_TRUE) {
3129 return ISC_R_CANCELED;
3130 }
3131 }
3132
6d7f9584
FD
3133 /* No old lease in rapid-commit. */
3134 if (client->state == S_INIT)
3135 return rval;
3136
98bd7ca0
DH
3137 switch (client->state) {
3138 case S_SELECTING:
3139 /* Compare the new lease with the selected lease to make
3140 * sure there is no risky business.
3141 */
0c20eab3
DH
3142 nscore = dhc6_score_lease(client, new);
3143 sscore = dhc6_score_lease(client, client->selected_lease);
98bd7ca0
DH
3144 if ((client->advertised_leases != NULL) &&
3145 (nscore < (sscore / 2))) {
3146 /* XXX: An attacker might reply this way to make
3147 * XXX: sure we latch onto their configuration.
3148 * XXX: We might want to ignore the packet and
3149 * XXX: schedule re-selection at the next timeout?
3150 */
3151 log_error("PRC: BAIT AND SWITCH detected. Score of "
3152 "supplied lease (%d) is substantially "
3153 "smaller than the advertised score (%d). "
3154 "Trying other servers.",
3155 nscore, sscore);
3156
e32529a5 3157 dhc6_lease_destroy(&client->selected_lease, MDL);
98bd7ca0
DH
3158 client->selected_lease = NULL;
3159
3160 start_selecting6(client);
3161
3162 return ISC_R_CANCELED;
3163 }
3164 break;
3165
3166 case S_RENEWING:
3167 case S_REBINDING:
3168 /* This leaves one RFC3315 status check unimplemented:
3169 *
3170 * - sends a Renew/Rebind if the IA is not in the Reply
3171 * message
3172 *
3173 * We rely on the scheduling system to note that the IA has
3174 * not left Renewal/Rebinding/whatever since it still carries
3175 * old times from the last successful binding. So this is
3176 * implemented actually, just not explicitly.
3177 */
3178 break;
3179
87202683 3180 case S_STOPPED:
0f69ff73 3181 case S_DECLINING:
87202683
FD
3182 /* Nothing critical to do at this stage. */
3183 break;
3184
98bd7ca0
DH
3185 default:
3186 log_fatal("REALLY impossible condition at %s:%d.", MDL);
3187 return ISC_R_CANCELED;
3188 }
3189
3190 return rval;
3191}
3192
3193/* While in init state, we only collect advertisements. If there happens
3194 * to be an advertisement with a preference option of 255, that's an
3195 * automatic exit. Otherwise, we collect advertisements until our timeout
3196 * expires (client->RT).
3197 */
3198void
3199init_handler(struct packet *packet, struct client_state *client)
3200{
28868515 3201 struct dhc6_lease *lease;
98bd7ca0
DH
3202
3203 /* In INIT state, we send solicits, we only expect to get
6d7f9584 3204 * advertises (rapid commit has its own handler).
98bd7ca0
DH
3205 */
3206 if (packet->dhcpv6_msg_type != DHCPV6_ADVERTISE)
3207 return;
3208
3209 /* RFC3315 section 15.3 validation (same as 15.10 since we
3210 * always include a client id).
3211 */
3212 if (!valid_reply(packet, client)) {
3213 log_error("Invalid Advertise - rejecting.");
3214 return;
3215 }
3216
a3471269 3217 lease = dhc6_leaseify(packet, client);
98bd7ca0 3218
af25ded3
SR
3219 /* Out of memory or corrupt packet condition...hopefully a temporary
3220 * problem. Returning now makes us try to retransmit later.
3221 */
3222 if (lease == NULL)
3223 return;
3224
98bd7ca0
DH
3225 if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) {
3226 log_debug("PRC: Lease failed to satisfy.");
e32529a5 3227 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
3228 return;
3229 }
3230
1d7fceeb 3231 int lease_score = dhc6_score_lease(client, lease);
3232#ifdef ENFORCE_DHCPV6_CLIENT_REQUIRE
3233 if (lease_score == 0) {
3234 log_debug("RCV:Advertised lease scored 0, toss it.");
3235 dhc6_lease_destroy(&lease, MDL);
3236 return;
3237 }
3238#endif
3239
98bd7ca0
DH
3240 insert_lease(&client->advertised_leases, lease);
3241
3242 /* According to RFC3315 section 17.1.2, the client MUST wait for
3243 * the first RT before selecting a lease. But on the 400th RT,
3244 * we dont' want to wait the full timeout if we finally get an
3245 * advertise. We could probably wait a second, but ohwell,
3246 * RFC3315 doesn't say so.
3247 *
3248 * If the lease is highest possible preference, 255, RFC3315 claims
3249 * we should continue immediately even on the first RT. We probably
3250 * should not if the advertise contains less than one IA and address.
3251 */
3252 if ((client->txcount > 1) ||
1d7fceeb 3253 ((lease->pref == 255) && (lease_score > SCORE_MIN))) {
98bd7ca0
DH
3254 log_debug("RCV: Advertisement immediately selected.");
3255 cancel_timeout(do_init6, client);
3256 start_selecting6(client);
3257 } else
3258 log_debug("RCV: Advertisement recorded.");
3259}
3260
3dbe2246
FD
3261/* info_request_handler() accepts a Reply to an Info-request.
3262 */
3263void
3264info_request_handler(struct packet *packet, struct client_state *client)
3265{
3266 isc_result_t check_status;
3267 unsigned code;
3268
3269 if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
3270 return;
3271
3272 /* RFC3315 section 15.10 validation (same as 15.3 since we
3273 * always include a client id).
3274 */
3275 if (!valid_reply(packet, client)) {
3276 log_error("Invalid Reply - rejecting.");
3277 return;
3278 }
3279
3280 check_status = dhc6_check_status(ISC_R_SUCCESS, packet->options,
3281 "message", &code);
c88dfebd 3282
3dbe2246
FD
3283 if (check_status != ISC_R_SUCCESS) {
3284 /* If no action was taken, but there is an error, then
3285 * we wait for a retransmission.
3286 */
3287 if (check_status != ISC_R_CANCELED)
3288 return;
3289 }
3290
3291 /* We're done retransmitting at this point. */
3292 cancel_timeout(do_info_request6, client);
3293
3294 /* Action was taken, so now that we've torn down our scheduled
3295 * retransmissions, return.
3296 */
3297 if (check_status == ISC_R_CANCELED)
3298 return;
3299
3300 /* Cleanup if a previous attempt to go bound failed. */
3301 if (client->old_lease != NULL) {
3302 dhc6_lease_destroy(&client->old_lease, MDL);
3303 client->old_lease = NULL;
3304 }
3305
3306 /* Cache options in the active_lease. */
3307 if (client->active_lease != NULL)
3308 client->old_lease = client->active_lease;
3309 client->active_lease = dmalloc(sizeof(struct dhc6_lease), MDL);
3310 if (client->active_lease == NULL)
3311 log_fatal("Out of memory for v6 lease structure.");
3312 option_state_reference(&client->active_lease->options,
3313 packet->options, MDL);
3314
a3471269
TM
3315 execute_statements_in_scope(NULL, (struct packet *)packet, NULL, client,
3316 client->active_lease->options,
3317 client->active_lease->options,
3318 &global_scope, client->config->on_receipt,
3319 NULL, NULL);
3320
3dbe2246
FD
3321 start_informed(client);
3322}
3323
6d7f9584
FD
3324/* Specific version of init_handler() for rapid-commit.
3325 */
3326void
3327rapid_commit_handler(struct packet *packet, struct client_state *client)
3328{
3329 struct dhc6_lease *lease;
3330 isc_result_t check_status;
3331
3332 /* On ADVERTISE just fall back to the init_handler().
3333 */
3334 if (packet->dhcpv6_msg_type == DHCPV6_ADVERTISE) {
3335 init_handler(packet, client);
3336 return;
3337 } else if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
3338 return;
3339
3340 /* RFC3315 section 15.10 validation (same as 15.3 since we
3341 * always include a client id).
3342 */
3343 if (!valid_reply(packet, client)) {
3344 log_error("Invalid Reply - rejecting.");
3345 return;
3346 }
3347
3348 /* A rapid-commit option MUST be here. */
3349 if (lookup_option(&dhcpv6_universe, packet->options,
3350 D6O_RAPID_COMMIT) == 0) {
3351 log_error("Reply without Rapid-Commit - rejecting.");
3352 return;
3353 }
3354
a3471269 3355 lease = dhc6_leaseify(packet, client);
6d7f9584 3356
af25ded3 3357 /* Out of memory or corrupt packet condition...hopefully a temporary
6d7f9584
FD
3358 * problem. Returning now makes us try to retransmit later.
3359 */
3360 if (lease == NULL)
3361 return;
3362
3363 check_status = dhc6_check_reply(client, lease);
3364 if (check_status != ISC_R_SUCCESS) {
3365 dhc6_lease_destroy(&lease, MDL);
3366 return;
3367 }
3368
3369 /* Jump to the selecting state. */
3370 cancel_timeout(do_init6, client);
3371 client->state = S_SELECTING;
3372
3373 /* Merge any bindings in the active lease (if there is one) into
3374 * the new active lease.
3375 */
3376 dhc6_merge_lease(client->active_lease, lease);
3377
3378 /* Cleanup if a previous attempt to go bound failed. */
3379 if (client->old_lease != NULL) {
3380 dhc6_lease_destroy(&client->old_lease, MDL);
3381 client->old_lease = NULL;
3382 }
3383
3384 /* Make this lease active and BIND to it. */
3385 if (client->active_lease != NULL)
3386 client->old_lease = client->active_lease;
3387 client->active_lease = lease;
3388
3389 /* We're done with the ADVERTISEd leases, if any. */
3390 while(client->advertised_leases != NULL) {
3391 lease = client->advertised_leases;
3392 client->advertised_leases = lease->next;
3393
3394 dhc6_lease_destroy(&lease, MDL);
3395 }
3396
3397 start_bound(client);
3398}
3399
98bd7ca0
DH
3400/* Find the 'best' lease in the cache of advertised leases (usually). From
3401 * RFC3315 Section 17.1.3:
3402 *
3403 * Upon receipt of one or more valid Advertise messages, the client
3404 * selects one or more Advertise messages based upon the following
3405 * criteria.
3406 *
3407 * - Those Advertise messages with the highest server preference value
3408 * are preferred over all other Advertise messages.
3409 *
3410 * - Within a group of Advertise messages with the same server
3411 * preference value, a client MAY select those servers whose
3412 * Advertise messages advertise information of interest to the
3413 * client. For example, the client may choose a server that returned
3414 * an advertisement with configuration options of interest to the
3415 * client.
3416 *
3417 * - The client MAY choose a less-preferred server if that server has a
3418 * better set of advertised parameters, such as the available
3419 * addresses advertised in IAs.
3420 *
3421 * Note that the first and third contradict each other. The third should
3422 * probably be taken to mean that the client should prefer answers that
3423 * offer bindings, even if that violates the preference rule.
3424 *
3425 * The above also isn't deterministic where there are ties. So the final
3426 * tiebreaker we add, if all other values are equal, is to compare the
3427 * server identifiers and to select the numerically lower one.
3428 */
3429static struct dhc6_lease *
0c20eab3 3430dhc6_best_lease(struct client_state *client, struct dhc6_lease **head)
98bd7ca0
DH
3431{
3432 struct dhc6_lease **rpos, *rval, **candp, *cand;
3433 int cscore, rscore;
3434
3435 if (head == NULL || *head == NULL)
3436 return NULL;
3437
3438 rpos = head;
3439 rval = *rpos;
0c20eab3 3440 rscore = dhc6_score_lease(client, rval);
98bd7ca0
DH
3441 candp = &rval->next;
3442 cand = *candp;
3443
3444 log_debug("PRC: Considering best lease.");
3445 log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
3446 print_hex_1(rval->server_id.len,
3447 rval->server_id.data, 48),
3448 rscore, (unsigned)rval->pref);
3449
3450 for (; cand != NULL ; candp = &cand->next, cand = *candp) {
0c20eab3 3451 cscore = dhc6_score_lease(client, cand);
98bd7ca0
DH
3452
3453 log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
3454 print_hex_1(cand->server_id.len,
3455 cand->server_id.data, 48),
3456 cscore, (unsigned)cand->pref);
3457
3458 /* Above you'll find quoted RFC3315 Section 17.1.3.
3459 *
3460 * The third clause tells us to give up on leases that
3461 * have no bindings even if their preference is better.
c88dfebd
SR
3462 * So where our 'selected' lease's score is less than
3463 * SCORE_MIN (1 ia + 1 addr), choose any candidate >= SCORE_MIN.
98bd7ca0
DH
3464 *
3465 * The first clause tells us to make preference the primary
3466 * deciding factor. So if it's lower, reject, if it's
3467 * higher, select.
3468 *
3469 * The second clause tells us where the preference is
3470 * equal, we should use 'our judgement' of what we like
3471 * to see in an advertisement primarily.
3472 *
3473 * But there can still be a tie. To make this deterministic,
3474 * we compare the server identifiers and select the binary
3475 * lowest.
3476 *
3477 * Since server id's are unique in this list, there is
3478 * no further tie to break.
3479 */
c88dfebd 3480 if ((rscore < SCORE_MIN) && (cscore >= SCORE_MIN)) {
a0006737 3481 log_debug("PRC: | X-- Selected, has bindings.");
98bd7ca0
DH
3482 } else if (cand->pref < rval->pref) {
3483 log_debug("PRC: | X-- Rejected, lower preference.");
3484 continue;
3485 } else if (cand->pref > rval->pref) {
3486 log_debug("PRC: | X-- Selected, higher preference.");
3487 } else if (cscore > rscore) {
3488 log_debug("PRC: | X-- Selected, equal preference, "
3489 "higher score.");
3490 } else if (cscore < rscore) {
3491 log_debug("PRC: | X-- Rejected, equal preference, "
3492 "lower score.");
3493 continue;
3494 } else if ((cand->server_id.len < rval->server_id.len) ||
3495 ((cand->server_id.len == rval->server_id.len) &&
3496 (memcmp(cand->server_id.data,
3497 rval->server_id.data,
3498 cand->server_id.len) < 0))) {
3499 log_debug("PRC: | X-- Selected, equal preference, "
3500 "equal score, binary lesser server ID.");
3501 } else {
3502 log_debug("PRC: | X-- Rejected, equal preference, "
3503 "equal score, binary greater server ID.");
3504 continue;
3505 }
3506
3507 rpos = candp;
3508 rval = cand;
3509 rscore = cscore;
3510 }
3511
3512 /* Remove the selected lease from the chain. */
3513 *rpos = rval->next;
3514
3515 return rval;
3516}
3517
3518/* Select a lease out of the advertised leases and setup state to try and
3519 * acquire that lease.
3520 */
3521void
3522start_selecting6(struct client_state *client)
3523{
3524 struct dhc6_lease *lease;
98bd7ca0
DH
3525
3526 if (client->advertised_leases == NULL) {
3527 log_error("Can not enter DHCPv6 SELECTING state with no "
3528 "leases to select from!");
3529 return;
3530 }
3531
3532 log_debug("PRC: Selecting best advertised lease.");
3533 client->state = S_SELECTING;
3534
0c20eab3 3535 lease = dhc6_best_lease(client, &client->advertised_leases);
98bd7ca0
DH
3536
3537 if (lease == NULL)
3538 log_fatal("Impossible error at %s:%d.", MDL);
3539
3540 client->selected_lease = lease;
3541
98bd7ca0 3542 /* Set timers per RFC3315 section 18.1.1. */
be62cf06
FD
3543 client->IRT = REQ_TIMEOUT * 100;
3544 client->MRT = REQ_MAX_RT * 100;
98bd7ca0
DH
3545 client->MRC = REQ_MAX_RC;
3546 client->MRD = 0;
3547
3548 dhc6_retrans_init(client);
3549
3550 client->v6_handler = reply_handler;
3551
3552 /* ("re")transmit the first packet. */
3553 do_select6(client);
3554}
3555
3556/* Transmit a Request to select a lease offered in Advertisements. In
3557 * the event of failure, either move on to the next-best advertised lease,
3558 * or head back to INIT state if there are none.
3559 */
3560void
3561do_select6(void *input)
3562{
3563 struct client_state *client;
3564 struct dhc6_lease *lease;
98bd7ca0 3565 struct data_string ds;
197c917e 3566 struct timeval tv;
c88dfebd 3567 int send_ret, added;
98bd7ca0
DH
3568
3569 client = input;
3570
3571 /* 'lease' is fewer characters to type. */
3572 lease = client->selected_lease;
3573 if (lease == NULL || lease->bindings == NULL) {
3574 log_error("Illegal to attempt selection without selecting "
3575 "a lease.");
3576 return;
3577 }
3578
197c917e
SR
3579 switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
3580 case CHK_TIM_MRC_EXCEEDED:
3581 case CHK_TIM_MRD_EXCEEDED:
98bd7ca0
DH
3582 log_debug("PRC: Lease %s failed.",
3583 print_hex_1(lease->server_id.len,
3584 lease->server_id.data, 56));
3585
3586 /* Get rid of the lease that timed/counted out. */
e32529a5 3587 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
3588 client->selected_lease = NULL;
3589
3590 /* If there are more leases great. If not, get more. */
3591 if (client->advertised_leases != NULL)
3592 start_selecting6(client);
3593 else
3594 start_init6(client);
98bd7ca0 3595 return;
197c917e
SR
3596 case CHK_TIM_ALLOC_FAILURE:
3597 return;
3598 case CHK_TIM_SUCCESS:
3599 break;
98bd7ca0
DH
3600 }
3601
3602 /* Now make a packet that looks suspiciously like the one we
3603 * got from the server. But different.
3604 *
3605 * XXX: I guess IAID is supposed to be something the client
3606 * indicates and uses as a key to its internal state. It is
3607 * kind of odd to ask the server for IA's whose IAID the client
3608 * did not manufacture. We first need a formal dhclient.conf
3609 * construct for the iaid, then we can delve into this matter
3610 * more properly. In the time being, this will work.
3611 */
98bd7ca0
DH
3612
3613 /* Fetch any configured 'sent' options (includes DUID) in wire format.
3614 */
3615 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
3616 NULL, client->sent_options, &global_scope,
3617 &dhcpv6_universe);
3618
c88dfebd
SR
3619 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
3620 * For each type of IA (na, ta, pd) we start with the ones for
3621 * which we already have addresses (dhc6_add_ia_xx) and then
3622 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
3623 */
420d8b3f 3624 if (wanted_ia_na &&
c88dfebd
SR
3625 ((dhc6_add_ia_na(client, &ds, lease, DHCPV6_REQUEST,
3626 wanted_ia_na, &added) != ISC_R_SUCCESS) ||
3627 (dhc6_bare_ia_xx(client, &ds, wanted_ia_na - added,
3628 D6O_IA_NA) != ISC_R_SUCCESS))) {
420d8b3f
FD
3629 data_string_forget(&ds, MDL);
3630 return;
3631 }
3632 if (wanted_ia_ta &&
c88dfebd
SR
3633 ((dhc6_add_ia_ta(client, &ds, lease, DHCPV6_REQUEST,
3634 wanted_ia_ta, &added) != ISC_R_SUCCESS) ||
3635 (dhc6_bare_ia_xx(client, &ds, wanted_ia_ta - added,
3636 D6O_IA_TA) != ISC_R_SUCCESS))) {
420d8b3f
FD
3637 data_string_forget(&ds, MDL);
3638 return;
3639 }
3640 if (wanted_ia_pd &&
c88dfebd
SR
3641 ((dhc6_add_ia_pd(client, &ds, lease, DHCPV6_REQUEST,
3642 wanted_ia_pd, &added) != ISC_R_SUCCESS) ||
3643 (dhc6_bare_ia_xx(client, &ds, wanted_ia_pd - added,
3644 D6O_IA_PD) != ISC_R_SUCCESS))) {
98bd7ca0
DH
3645 data_string_forget(&ds, MDL);
3646 return;
3647 }
3648
be62cf06 3649 log_info("XMT: Request on %s, interval %ld0ms.",
98bd7ca0 3650 client->name ? client->name : client->interface->name,
9aa669fc 3651 (long int)client->RT);
98bd7ca0
DH
3652
3653 send_ret = send_packet6(client->interface,
3654 ds.data, ds.len, &DHCPv6DestAddr);
3655 if (send_ret != ds.len) {
3656 log_error("dhc6: send_packet6() sent %d of %d bytes",
3657 send_ret, ds.len);
3658 }
3659
3660 data_string_forget(&ds, MDL);
3661
be62cf06
FD
3662 /* Wait RT */
3663 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
3664 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
3665 if (tv.tv_usec >= 1000000) {
3666 tv.tv_sec += 1;
3667 tv.tv_usec -= 1000000;
3668 }
3669 add_timeout(&tv, do_select6, client, NULL, NULL);
98bd7ca0
DH
3670
3671 dhc6_retrans_advance(client);
3672}
3673
c88dfebd
SR
3674/*!
3675 *
3676 * \brief Count the number of IAs in the bindings
3677 *
3678 * \param lease the lease to count
3679 * \param ia_type the type of the IA we wish to count
3680 *
3681 * \return The number of IAs of the specified type we found
3682 */
3683static int
3684dhc6_count_ia(struct dhc6_lease *lease, u_int16_t ia_type)
3685{
3686 struct dhc6_ia *ia;
3687 int i = 0;
3688
3689 for (ia = lease->bindings; ia != NULL; ia = ia->next) {
3690 if (ia->ia_type == ia_type)
3691 /* bump the counter for the correct types */
3692 i++;
3693 }
3694
3695 return (i);
3696}
3697
3698/*!
3699 *
3700 * \brief Add IA_NA information from the lease to the packet
3701 * we are building.
3702 *
3703 * Walk through the lease and for each IA_NA in the lease
3704 * and for each address in the IA_NA append that information
3705 * onto the packet-so-far. If wanted is 0 include all IA_NAs
3706 * in the lease if wanted is non-zero include only that many
3707 * IA_NAs (this may occur if sommebody restarts a client with
3708 * arugments for a smaller number of NAs than before).
3709 *
3710 * \param client = the state of the entire client
3711 * \param packet = the packet we are building and where we
3712 * shall append the IA_NAs we create
3713 * \param lease = the current lease
3714 * \param message = the type of the packet
3715 * \param wanted = the number of IA_NAs to include in the packet
3716 * 0 means include all
3717 * \param added = the number of IA_NAs that were added to the packet
3718 *
3719 * \return ISC_R_SUCCESS - all is well continue, any other return
3720 * indicates an error (most likely memory issues)
3721 * and the packet should be tossed.
98bd7ca0
DH
3722 */
3723static isc_result_t
1d9774ab 3724dhc6_add_ia_na(struct client_state *client, struct data_string *packet,
c88dfebd
SR
3725 struct dhc6_lease *lease, u_int8_t message,
3726 int wanted, int *added)
98bd7ca0
DH
3727{
3728 struct data_string iads;
3729 struct data_string addrds;
3730 struct dhc6_addr *addr;
3731 struct dhc6_ia *ia;
3732 isc_result_t rval = ISC_R_SUCCESS;
3733 TIME t1, t2;
c88dfebd 3734 int i;
af5fa176 3735
c88dfebd 3736 *added = 0;
98bd7ca0
DH
3737 memset(&iads, 0, sizeof(iads));
3738 memset(&addrds, 0, sizeof(addrds));
c88dfebd
SR
3739 for (ia = lease->bindings, i = 0;
3740 ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
420d8b3f 3741 ia = ia->next) {
1d9774ab
FD
3742 if (ia->ia_type != D6O_IA_NA)
3743 continue;
3744
c88dfebd
SR
3745 /* Now that we know this is an NA bump the counter */
3746 i++;
3747
98bd7ca0 3748 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
af5fa176
EH
3749 log_error("Unable to allocate memory for IA_NA.");
3750 rval = ISC_R_NOMEMORY;
98bd7ca0
DH
3751 break;
3752 }
98bd7ca0 3753
af5fa176 3754 /* Copy the IAID into the packet buffer. */
98bd7ca0 3755 memcpy(iads.buffer->data, ia->iaid, 4);
af5fa176
EH
3756 iads.data = iads.buffer->data;
3757 iads.len = 12;
98bd7ca0 3758
420d8b3f
FD
3759 switch (message) {
3760 case DHCPV6_REQUEST:
3761 case DHCPV6_RENEW:
3762 case DHCPV6_REBIND:
3763
3764 t1 = client->config->requested_lease / 2;
3765 t2 = t1 + (t1 / 2);
98bd7ca0 3766#if MAX_TIME > 0xffffffff
420d8b3f
FD
3767 if (t1 > 0xffffffff)
3768 t1 = 0xffffffff;
3769 if (t2 > 0xffffffff)
3770 t2 = 0xffffffff;
98bd7ca0 3771#endif
420d8b3f
FD
3772 putULong(iads.buffer->data + 4, t1);
3773 putULong(iads.buffer->data + 8, t2);
3774
3775 log_debug("XMT: X-- IA_NA %s",
3776 print_hex_1(4, iads.data, 59));
3777 log_debug("XMT: | X-- Requested renew +%u",
3778 (unsigned) t1);
3779 log_debug("XMT: | X-- Requested rebind +%u",
3780 (unsigned) t2);
3781 break;
3782
3783 case DHCPV6_CONFIRM:
3784 case DHCPV6_RELEASE:
3785 case DHCPV6_DECLINE:
3786 /* Set t1 and t2 to zero; server will ignore them */
3787 memset(iads.buffer->data + 4, 0, 8);
3788 log_debug("XMT: X-- IA_NA %s",
3789 print_hex_1(4, iads.buffer->data, 55));
3790
3791 break;
3792
3793 default:
3794 log_fatal("Impossible condition at %s:%d.", MDL);
3795 }
98bd7ca0 3796
af5fa176 3797 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
703873ab
DH
3798 /*
3799 * Do not confirm expired addresses, do not request
3800 * expired addresses (but we keep them around for
3801 * solicit).
3802 */
3803 if (addr->flags & DHC6_ADDR_EXPIRED)
3804 continue;
3805
af5fa176
EH
3806 if (addr->address.len != 16) {
3807 log_error("Illegal IPv6 address length (%d), "
3808 "ignoring. (%s:%d)",
3809 addr->address.len, MDL);
3810 continue;
3811 }
98bd7ca0 3812
98bd7ca0
DH
3813 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
3814 log_error("Unable to allocate memory for "
3815 "IAADDR.");
af5fa176 3816 rval = ISC_R_NOMEMORY;
98bd7ca0
DH
3817 break;
3818 }
af5fa176 3819
98bd7ca0
DH
3820 addrds.data = addrds.buffer->data;
3821 addrds.len = 24;
3822
af5fa176 3823 /* Copy the address into the packet buffer. */
98bd7ca0 3824 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
98bd7ca0 3825
420d8b3f
FD
3826 /* Copy in additional information as appropriate */
3827 switch (message) {
3828 case DHCPV6_REQUEST:
3829 case DHCPV6_RENEW:
3830 case DHCPV6_REBIND:
3831 t1 = client->config->requested_lease;
3832 t2 = t1 + 300;
3833 putULong(addrds.buffer->data + 16, t1);
3834 putULong(addrds.buffer->data + 20, t2);
3835
3836 log_debug("XMT: | | X-- IAADDR %s",
3837 piaddr(addr->address));
3838 log_debug("XMT: | | | X-- Preferred "
3839 "lifetime +%u", (unsigned)t1);
3840 log_debug("XMT: | | | X-- Max lifetime +%u",
3841 (unsigned)t2);
3842
3843 break;
3844
3845 case DHCPV6_CONFIRM:
3846 /*
3847 * Set preferred and max life to zero,
3848 * per 17.1.3.
3849 */
3850 memset(addrds.buffer->data + 16, 0, 8);
3851 log_debug("XMT: | X-- Confirm Address %s",
3852 piaddr(addr->address));
3853 break;
3854
3855 case DHCPV6_RELEASE:
3856 /* Preferred and max life are irrelevant */
3857 memset(addrds.buffer->data + 16, 0, 8);
3858 log_debug("XMT: | X-- Release Address %s",
3859 piaddr(addr->address));
3860 break;
3861
3862 case DHCPV6_DECLINE:
3863 /* Preferred and max life are irrelevant */
3864 memset(addrds.buffer->data + 16, 0, 8);
3865 log_debug("XMT: | X-- Decline Address %s",
3866 piaddr(addr->address));
3867 break;
3868
3869 default:
3870 log_fatal("Impossible condition at %s:%d.",
3871 MDL);
3872 }
98bd7ca0
DH
3873
3874 append_option(&iads, &dhcpv6_universe, iaaddr_option,
420d8b3f 3875 &addrds);
98bd7ca0
DH
3876 data_string_forget(&addrds, MDL);
3877 }
3878
af5fa176 3879 /*
420d8b3f 3880 * It doesn't make sense to make a request without an
98bd7ca0
DH
3881 * address.
3882 */
af5fa176
EH
3883 if (ia->addrs == NULL) {
3884 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
3885 rval = ISC_R_FAILURE;
3886 } else if (rval == ISC_R_SUCCESS) {
98bd7ca0
DH
3887 log_debug("XMT: V IA_NA appended.");
3888 append_option(packet, &dhcpv6_universe, ia_na_option,
3889 &iads);
98bd7ca0
DH
3890 }
3891
3892 data_string_forget(&iads, MDL);
3893 }
3894
c88dfebd
SR
3895 if (rval == ISC_R_SUCCESS)
3896 *added = i;
3897
3898 return (rval);
420d8b3f
FD
3899}
3900
c88dfebd
SR
3901/*!
3902 *
3903 * \brief Add IA_TA information from the lease to the packet
3904 * we are building.
3905 *
3906 * Walk through the lease and for each IA_TA in the lease
3907 * and for each address in the IA_TA append that information
3908 * onto the packet-so-far. If wanted is 0 include all IA_TAs
3909 * in the lease if wanted is non-zero include only that many
3910 * IA_TAs (this may occur if sommebody restarts a client with
3911 * arugments for a smaller number of TAs than before).
3912 *
3913 * \param client = the state of the entire client
3914 * \param packet = the packet we are building and where we
3915 * shall append the IA_TAs we create
3916 * \param lease = the current lease
3917 * \param message = the type of the packet
3918 * \param wanted = the number of IA_TAs to include in the packet
3919 * 0 means include all
3920 * \param added = the number of IA_TAs that were added to the packet
3921 *
3922 * \return ISC_R_SUCCESS - all is well continue, any other return
3923 * indicates an error (most likely memory issues)
3924 * and the packet should be tossed.
420d8b3f
FD
3925 */
3926static isc_result_t
3927dhc6_add_ia_ta(struct client_state *client, struct data_string *packet,
c88dfebd
SR
3928 struct dhc6_lease *lease, u_int8_t message,
3929 int wanted, int *added)
420d8b3f
FD
3930{
3931 struct data_string iads;
3932 struct data_string addrds;
3933 struct dhc6_addr *addr;
3934 struct dhc6_ia *ia;
3935 isc_result_t rval = ISC_R_SUCCESS;
3936 TIME t1, t2;
c88dfebd 3937 int i;
420d8b3f 3938
c88dfebd 3939 *added = 0;
420d8b3f
FD
3940 memset(&iads, 0, sizeof(iads));
3941 memset(&addrds, 0, sizeof(addrds));
c88dfebd
SR
3942 for (ia = lease->bindings, i = 0;
3943 ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
420d8b3f
FD
3944 ia = ia->next) {
3945 if (ia->ia_type != D6O_IA_TA)
3946 continue;
3947
c88dfebd
SR
3948 /* Now that we know this is an TA bump the counter */
3949 i++;
3950
420d8b3f
FD
3951 if (!buffer_allocate(&iads.buffer, 4, MDL)) {
3952 log_error("Unable to allocate memory for IA_TA.");
3953 rval = ISC_R_NOMEMORY;
3954 break;
3955 }
3956
3957 /* Copy the IAID into the packet buffer. */
3958 memcpy(iads.buffer->data, ia->iaid, 4);
3959 iads.data = iads.buffer->data;
3960 iads.len = 4;
3961
3962 log_debug("XMT: X-- IA_TA %s",
3963 print_hex_1(4, iads.buffer->data, 55));
3964
3965 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3966 /*
3967 * Do not confirm expired addresses, do not request
3968 * expired addresses (but we keep them around for
3969 * solicit).
3970 */
3971 if (addr->flags & DHC6_ADDR_EXPIRED)
3972 continue;
3973
3974 if (addr->address.len != 16) {
3975 log_error("Illegal IPv6 address length (%d), "
3976 "ignoring. (%s:%d)",
3977 addr->address.len, MDL);
3978 continue;
3979 }
3980
3981 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
3982 log_error("Unable to allocate memory for "
3983 "IAADDR.");
3984 rval = ISC_R_NOMEMORY;
3985 break;
3986 }
3987
3988 addrds.data = addrds.buffer->data;
3989 addrds.len = 24;
3990
3991 /* Copy the address into the packet buffer. */
3992 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
3993
3994 /* Copy in additional information as appropriate */
3995 switch (message) {
3996 case DHCPV6_REQUEST:
3997 case DHCPV6_RENEW:
3998 case DHCPV6_REBIND:
3999 t1 = client->config->requested_lease;
4000 t2 = t1 + 300;
4001 putULong(addrds.buffer->data + 16, t1);
4002 putULong(addrds.buffer->data + 20, t2);
4003
4004 log_debug("XMT: | | X-- IAADDR %s",
4005 piaddr(addr->address));
4006 log_debug("XMT: | | | X-- Preferred "
4007 "lifetime +%u", (unsigned)t1);
4008 log_debug("XMT: | | | X-- Max lifetime +%u",
4009 (unsigned)t2);
4010
4011 break;
4012
4013 case DHCPV6_CONFIRM:
4014 /*
4015 * Set preferred and max life to zero,
4016 * per 17.1.3.
4017 */
4018 memset(addrds.buffer->data + 16, 0, 8);
4019 log_debug("XMT: | X-- Confirm Address %s",
4020 piaddr(addr->address));
4021 break;
4022
4023 case DHCPV6_RELEASE:
4024 /* Preferred and max life are irrelevant */
4025 memset(addrds.buffer->data + 16, 0, 8);
4026 log_debug("XMT: | X-- Release Address %s",
4027 piaddr(addr->address));
4028 break;
4029
4030 default:
4031 log_fatal("Impossible condition at %s:%d.",
4032 MDL);
4033 }
4034
4035 append_option(&iads, &dhcpv6_universe, iaaddr_option,
4036 &addrds);
4037 data_string_forget(&addrds, MDL);
4038 }
4039
4040 /*
4041 * It doesn't make sense to make a request without an
4042 * address.
4043 */
4044 if (ia->addrs == NULL) {
4045 log_debug("!!!: V IA_TA has no IAADDRs - removed.");
4046 rval = ISC_R_FAILURE;
4047 } else if (rval == ISC_R_SUCCESS) {
4048 log_debug("XMT: V IA_TA appended.");
4049 append_option(packet, &dhcpv6_universe, ia_ta_option,
4050 &iads);
4051 }
4052
4053 data_string_forget(&iads, MDL);
4054 }
4055
c88dfebd
SR
4056 if (rval == ISC_R_SUCCESS)
4057 *added = i;
4058
4059 return (rval);
420d8b3f
FD
4060}
4061
c88dfebd
SR
4062/*!
4063 *
4064 * \brief Add IA_PD information from the lease to the packet
4065 * we are building.
4066 *
4067 * Walk through the lease and for each IA_PD in the lease
4068 * and for each address in the IA_PD append that information
4069 * onto the packet-so-far. If wanted is 0 include all IA_PDs
4070 * in the lease if wanted is non-zero include only that many
4071 * IA_PDs (this may occur if sommebody restarts a client with
4072 * arugments for a smaller number of PDs than before).
4073 *
4074 * \param client = the state of the entire client
4075 * \param packet = the packet we are building and where we
4076 * shall append the IA_PDs we create
4077 * \param lease = the current lease
4078 * \param message = the type of the packet
4079 * \param wanted = the number of IA_PDs to include in the packet
4080 * 0 means include all
4081 * \param added = the number of IA_PDs that were added to the packet
4082 *
4083 * \return ISC_R_SUCCESS - all is well continue, any other return
4084 * indicates an error (most likely memory issues)
4085 * and the packet should be tossed.
420d8b3f
FD
4086 */
4087static isc_result_t
4088dhc6_add_ia_pd(struct client_state *client, struct data_string *packet,
c88dfebd
SR
4089 struct dhc6_lease *lease, u_int8_t message,
4090 int wanted, int *added)
420d8b3f
FD
4091{
4092 struct data_string iads;
4093 struct data_string prefds;
4094 struct dhc6_addr *pref;
4095 struct dhc6_ia *ia;
4096 isc_result_t rval = ISC_R_SUCCESS;
4097 TIME t1, t2;
c88dfebd 4098 int i;
420d8b3f 4099
c88dfebd 4100 *added = 0;
420d8b3f
FD
4101 memset(&iads, 0, sizeof(iads));
4102 memset(&prefds, 0, sizeof(prefds));
c88dfebd
SR
4103 for (ia = lease->bindings, i = 0;
4104 ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
420d8b3f
FD
4105 ia = ia->next) {
4106 if (ia->ia_type != D6O_IA_PD)
4107 continue;
4108
c88dfebd
SR
4109 /* Now that we know this is an PD bump the counter */
4110 i++;
4111
420d8b3f
FD
4112 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
4113 log_error("Unable to allocate memory for IA_PD.");
4114 rval = ISC_R_NOMEMORY;
4115 break;
4116 }
4117
4118 /* Copy the IAID into the packet buffer. */
4119 memcpy(iads.buffer->data, ia->iaid, 4);
4120 iads.data = iads.buffer->data;
4121 iads.len = 12;
4122
4123 switch (message) {
4124 case DHCPV6_REQUEST:
4125 case DHCPV6_RENEW:
4126 case DHCPV6_REBIND:
4127
4128 t1 = client->config->requested_lease / 2;
4129 t2 = t1 + (t1 / 2);
4130#if MAX_TIME > 0xffffffff
4131 if (t1 > 0xffffffff)
4132 t1 = 0xffffffff;
4133 if (t2 > 0xffffffff)
4134 t2 = 0xffffffff;
4135#endif
4136 putULong(iads.buffer->data + 4, t1);
4137 putULong(iads.buffer->data + 8, t2);
4138
4139 log_debug("XMT: X-- IA_PD %s",
4140 print_hex_1(4, iads.data, 59));
4141 log_debug("XMT: | X-- Requested renew +%u",
4142 (unsigned) t1);
4143 log_debug("XMT: | X-- Requested rebind +%u",
4144 (unsigned) t2);
4145 break;
4146
4147 case DHCPV6_RELEASE:
4148 /* Set t1 and t2 to zero; server will ignore them */
4149 memset(iads.buffer->data + 4, 0, 8);
4150 log_debug("XMT: X-- IA_PD %s",
4151 print_hex_1(4, iads.buffer->data, 55));
4152
4153 break;
4154
4155 default:
4156 log_fatal("Impossible condition at %s:%d.", MDL);
4157 }
4158
4159 for (pref = ia->addrs ; pref != NULL ; pref = pref->next) {
4160 /*
4161 * Do not confirm expired prefixes, do not request
4162 * expired prefixes (but we keep them around for
4163 * solicit).
4164 */
4165 if (pref->flags & DHC6_ADDR_EXPIRED)
4166 continue;
4167
4168 if (pref->address.len != 16) {
4169 log_error("Illegal IPv6 prefix "
4170 "ignoring. (%s:%d)",
4171 MDL);
4172 continue;
4173 }
4174
4175 if (pref->plen == 0) {
4176 log_info("Null IPv6 prefix, "
4177 "ignoring. (%s:%d)",
4178 MDL);
4179 }
4180
4181 if (!buffer_allocate(&prefds.buffer, 25, MDL)) {
4182 log_error("Unable to allocate memory for "
4183 "IAPREFIX.");
4184 rval = ISC_R_NOMEMORY;
4185 break;
4186 }
4187
4188 prefds.data = prefds.buffer->data;
4189 prefds.len = 25;
4190
4191 /* Copy the prefix into the packet buffer. */
4192 putUChar(prefds.buffer->data + 8, pref->plen);
4193 memcpy(prefds.buffer->data + 9,
4194 pref->address.iabuf,
4195 16);
4196
4197 /* Copy in additional information as appropriate */
4198 switch (message) {
4199 case DHCPV6_REQUEST:
4200 case DHCPV6_RENEW:
4201 case DHCPV6_REBIND:
4202 t1 = client->config->requested_lease;
4203 t2 = t1 + 300;
4204 putULong(prefds.buffer->data, t1);
4205 putULong(prefds.buffer->data + 4, t2);
4206
4207 log_debug("XMT: | | X-- IAPREFIX %s/%u",
4208 piaddr(pref->address),
4209 (unsigned) pref->plen);
4210 log_debug("XMT: | | | X-- Preferred "
4211 "lifetime +%u", (unsigned)t1);
4212 log_debug("XMT: | | | X-- Max lifetime +%u",
4213 (unsigned)t2);
4214
4215 break;
4216
4217 case DHCPV6_RELEASE:
4218 /* Preferred and max life are irrelevant */
4219 memset(prefds.buffer->data, 0, 8);
4220 log_debug("XMT: | X-- Release Prefix %s/%u",
4221 piaddr(pref->address),
4222 (unsigned) pref->plen);
4223 break;
4224
4225 default:
4226 log_fatal("Impossible condition at %s:%d.",
4227 MDL);
4228 }
4229
4230 append_option(&iads, &dhcpv6_universe,
4231 iaprefix_option, &prefds);
4232 data_string_forget(&prefds, MDL);
4233 }
4234
4235 /*
4236 * It doesn't make sense to make a request without an
4237 * address.
4238 */
4239 if (ia->addrs == NULL) {
4240 log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
4241 rval = ISC_R_FAILURE;
4242 } else if (rval == ISC_R_SUCCESS) {
4243 log_debug("XMT: V IA_PD appended.");
4244 append_option(packet, &dhcpv6_universe,
4245 ia_pd_option, &iads);
4246 }
4247
4248 data_string_forget(&iads, MDL);
4249 }
4250
c88dfebd
SR
4251 if (rval == ISC_R_SUCCESS)
4252 *added = i;
4253
4254 return (rval);
98bd7ca0
DH
4255}
4256
87202683
FD
4257/* stopping_finished() checks if there is a remaining work to do.
4258 */
4259static isc_boolean_t
4260stopping_finished(void)
4261{
4262 struct interface_info *ip;
4263 struct client_state *client;
4264
4265 for (ip = interfaces; ip; ip = ip -> next) {
4266 for (client = ip -> client; client; client = client -> next) {
4267 if (client->state != S_STOPPED)
4268 return ISC_FALSE;
4269 if (client->active_lease != NULL)
4270 return ISC_FALSE;
4271 }
4272 }
4273 return ISC_TRUE;
4274}
4275
98bd7ca0
DH
4276/* reply_handler() accepts a Reply while we're attempting Select or Renew or
4277 * Rebind. Basically any Reply packet.
4278 */
4279void
4280reply_handler(struct packet *packet, struct client_state *client)
4281{
28868515 4282 struct dhc6_lease *lease;
98bd7ca0
DH
4283 isc_result_t check_status;
4284
4285 if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
4286 return;
4287
4288 /* RFC3315 section 15.10 validation (same as 15.3 since we
4289 * always include a client id).
4290 */
4291 if (!valid_reply(packet, client)) {
7b22a9b4 4292 log_error("Invalid Reply - rejecting.");
98bd7ca0
DH
4293 return;
4294 }
4295
a3471269 4296 lease = dhc6_leaseify(packet, client);
98bd7ca0 4297
af25ded3 4298 /* Out of memory or corrupt packet condition...hopefully a temporary
98bd7ca0
DH
4299 * problem. Returning now makes us try to retransmit later.
4300 */
4301 if (lease == NULL)
4302 return;
4303
4304 check_status = dhc6_check_reply(client, lease);
4305 if (check_status != ISC_R_SUCCESS) {
e32529a5 4306 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
4307
4308 /* If no action was taken, but there is an error, then
4309 * we wait for a retransmission.
4310 */
4311 if (check_status != ISC_R_CANCELED)
4312 return;
4313 }
4314
a0006737 4315 /* We're done retransmitting at this point. */
98bd7ca0
DH
4316 cancel_timeout(do_confirm6, client);
4317 cancel_timeout(do_select6, client);
4318 cancel_timeout(do_refresh6, client);
af5fa176 4319 cancel_timeout(do_release6, client);
0f69ff73 4320 cancel_timeout(do_decline6, client);
98bd7ca0 4321
0f69ff73 4322 /* If this is in response to a Release, clean up and return. */
87202683 4323 if (client->state == S_STOPPED) {
0f69ff73
TM
4324 if (client->active_lease != NULL) {
4325 dhc6_lease_destroy(&client->active_lease, MDL);
4326 client->active_lease = NULL;
4327 /* We should never wait for nothing!? */
4328 if (stopping_finished()) {
4329 finish(0);
4330 }
4331 }
87202683 4332
0f69ff73
TM
4333 return;
4334 }
4335
4336 if (client->state == S_DECLINING) {
4337 /* Weed thru the lease and delete all declined addresses.
4338 * Toss the lease if there aren't any addresses left */
4339 int live_cnt = drop_declined_addrs(client->active_lease);
4340 if (live_cnt == 0) {
4341 dhc6_lease_destroy(&client->active_lease, MDL);
4342 client->active_lease = NULL;
4343 }
4344
4345 /* Solicit with any live addresses we have so far, and
4346 * add additional empty NA iasubopts for those we had
4347 * to decline. */
4348 start_init6(client);
87202683 4349 return;
420d8b3f 4350 }
87202683 4351
98bd7ca0
DH
4352 /* Action was taken, so now that we've torn down our scheduled
4353 * retransmissions, return.
4354 */
4355 if (check_status == ISC_R_CANCELED)
4356 return;
4357
4358 if (client->selected_lease != NULL) {
e32529a5 4359 dhc6_lease_destroy(&client->selected_lease, MDL);
98bd7ca0
DH
4360 client->selected_lease = NULL;
4361 }
4362
4363 /* If this is in response to a confirm, we use the lease we've
4364 * already got, not the reply we were sent.
4365 */
4366 if (client->state == S_REBOOTING) {
4367 if (client->active_lease == NULL)
4368 log_fatal("Impossible condition at %s:%d.", MDL);
4369
e32529a5 4370 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
4371 start_bound(client);
4372 return;
4373 }
4374
4375 /* Merge any bindings in the active lease (if there is one) into
4376 * the new active lease.
4377 */
4378 dhc6_merge_lease(client->active_lease, lease);
4379
4380 /* Cleanup if a previous attempt to go bound failed. */
4381 if (client->old_lease != NULL) {
e32529a5 4382 dhc6_lease_destroy(&client->old_lease, MDL);
98bd7ca0
DH
4383 client->old_lease = NULL;
4384 }
4385
4386 /* Make this lease active and BIND to it. */
4387 if (client->active_lease != NULL)
4388 client->old_lease = client->active_lease;
4389 client->active_lease = lease;
4390
4391 /* We're done with the ADVERTISEd leases, if any. */
4392 while(client->advertised_leases != NULL) {
4393 lease = client->advertised_leases;
4394 client->advertised_leases = lease->next;
4395
e32529a5 4396 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
4397 }
4398
4399 start_bound(client);
4400}
4401
4402/* DHCPv6 packets are a little sillier than they needed to be - the root
4403 * packet contains options, then IA's which contain options, then within
4404 * that IAADDR's which contain options.
4405 *
4406 * To sort this out at dhclient-script time (which fetches config parameters
4407 * in environment variables), start_bound() iterates over each IAADDR, and
4408 * calls this function to marshall an environment variable set that includes
4409 * the most-specific option values related to that IAADDR in particular.
4410 *
a0006737 4411 * To achieve this, we load environment variables for the root options space,
98bd7ca0
DH
4412 * then the IA, then the IAADDR. Any duplicate option names will be
4413 * over-written by the later versions.
4414 */
4415static void
06eb8bab 4416dhc6_marshall_values(const char *prefix, struct client_state *client,
98bd7ca0
DH
4417 struct dhc6_lease *lease, struct dhc6_ia *ia,
4418 struct dhc6_addr *addr)
4419{
4420 /* Option cache contents, in descending order of
4421 * scope.
4422 */
4423 if ((lease != NULL) && (lease->options != NULL))
4424 script_write_params6(client, prefix, lease->options);
4425 if ((ia != NULL) && (ia->options != NULL))
4426 script_write_params6(client, prefix, ia->options);
4427 if ((addr != NULL) && (addr->options != NULL))
4428 script_write_params6(client, prefix, addr->options);
4429
4430 /* addr fields. */
4431 if (addr != NULL) {
420d8b3f
FD
4432 if ((ia != NULL) && (ia->ia_type == D6O_IA_PD)) {
4433 client_envadd(client, prefix,
4434 "ip6_prefix", "%s/%u",
4435 piaddr(addr->address),
4436 (unsigned) addr->plen);
4437 } else {
420d8b3f 4438 client_envadd(client, prefix, "ip6_prefixlen",
140612c8 4439 "%d", address_prefix_len);
420d8b3f
FD
4440 client_envadd(client, prefix, "ip6_address",
4441 "%s", piaddr(addr->address));
4442 }
4443 if ((ia != NULL) && (ia->ia_type == D6O_IA_TA)) {
4444 client_envadd(client, prefix,
4445 "ip6_type", "temporary");
4446 }
98bd7ca0
DH
4447 client_envadd(client, prefix, "life_starts", "%d",
4448 (int)(addr->starts));
cb8c997e
SR
4449 client_envadd(client, prefix, "preferred_life", "%u",
4450 addr->preferred_life);
4451 client_envadd(client, prefix, "max_life", "%u",
4452 addr->max_life);
98bd7ca0
DH
4453 }
4454
4455 /* ia fields. */
4456 if (ia != NULL) {
4457 client_envadd(client, prefix, "iaid", "%s",
4458 print_hex_1(4, ia->iaid, 12));
4459 client_envadd(client, prefix, "starts", "%d",
4460 (int)(ia->starts));
4461 client_envadd(client, prefix, "renew", "%u", ia->renew);
4462 client_envadd(client, prefix, "rebind", "%u", ia->rebind);
4463 }
4464}
4465
4466/* Look at where the client's active lease is sitting. If it's looking to
4467 * time out on renew, rebind, depref, or expiration, do those things.
4468 */
4469static void
4470dhc6_check_times(struct client_state *client)
4471{
4472 struct dhc6_lease *lease;
4473 struct dhc6_ia *ia;
4474 struct dhc6_addr *addr;
4475 TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
c88dfebd 4476 lo_expire=MAX_TIME, hi_expire=0, max_ia_starts = 0, tmp;
98bd7ca0 4477 int has_addrs = ISC_FALSE;
251bb4b9 4478 int has_preferred_addrs = ISC_FALSE;
be62cf06 4479 struct timeval tv;
98bd7ca0
DH
4480
4481 lease = client->active_lease;
4482
4483 /* Bit spammy. We should probably keep record of scheduled
4484 * events instead.
4485 */
4486 cancel_timeout(start_renew6, client);
4487 cancel_timeout(start_rebind6, client);
4488 cancel_timeout(do_depref, client);
4489 cancel_timeout(do_expire, client);
4490
4491 for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
703873ab
DH
4492 TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
4493
4494 this_ia_lo_expire = MAX_TIME;
4495 this_ia_hi_expire = 0;
4496
98bd7ca0
DH
4497 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4498 if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
4499 if (addr->preferred_life == 0xffffffff)
4500 tmp = MAX_TIME;
4501 else
4502 tmp = addr->starts +
4503 addr->preferred_life;
4504
4505 if (tmp < depref)
4506 depref = tmp;
251bb4b9 4507
4508 if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
4509 has_preferred_addrs = ISC_TRUE;
4510 }
98bd7ca0
DH
4511 }
4512
4513 if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
703873ab 4514 /* Find EPOCH-relative expiration. */
98bd7ca0
DH
4515 if (addr->max_life == 0xffffffff)
4516 tmp = MAX_TIME;
4517 else
4518 tmp = addr->starts + addr->max_life;
4519
703873ab
DH
4520 /* Make the times ia->starts relative. */
4521 tmp -= ia->starts;
4522
4523 if (tmp > this_ia_hi_expire)
4524 this_ia_hi_expire = tmp;
4525 if (tmp < this_ia_lo_expire)
4526 this_ia_lo_expire = tmp;
98bd7ca0
DH
4527
4528 has_addrs = ISC_TRUE;
4529 }
4530 }
4531
703873ab
DH
4532 /* These times are ia->starts relative. */
4533 if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
4534 use_expire = this_ia_hi_expire;
4535 else
4536 use_expire = this_ia_lo_expire;
4537
4538 /*
4539 * If the auto-selected expiration time is "infinite", or
4540 * zero, assert a reasonable default.
4541 */
4542 if ((use_expire == MAX_TIME) || (use_expire <= 1))
4543 use_expire = client->config->requested_lease / 2;
4544 else
4545 use_expire /= 2;
98bd7ca0 4546
420d8b3f 4547 /* Don't renew/rebind temporary addresses. */
c88dfebd
SR
4548 /* For NA and PD we find the most recent IA and the smallest
4549 * values for the renew and rebind then base the timer on
4550 * the sum of the them.
4551 * Normally all the IAs will have the same time as they
4552 * are requested and served as a group but in some cases the
4553 * client isn't asking for all of the IAs (for example
4554 * restarted with a different set of arguments) or the server
4555 * isn't updating the client on all of them (probably a
4556 * broken server).
4557 */
420d8b3f 4558 if (ia->ia_type != D6O_IA_TA) {
c88dfebd
SR
4559 if (ia->starts > max_ia_starts)
4560 max_ia_starts = ia->starts;
420d8b3f
FD
4561
4562 if (ia->renew == 0) {
c88dfebd 4563 tmp = use_expire;
420d8b3f
FD
4564 } else if (ia->renew == 0xffffffff)
4565 tmp = MAX_TIME;
4566 else
c88dfebd 4567 tmp = ia->renew;
98bd7ca0 4568
420d8b3f
FD
4569 if (tmp < renew)
4570 renew = tmp;
98bd7ca0 4571
420d8b3f
FD
4572 if (ia->rebind == 0) {
4573 /* Set rebind to 3/4 expiration interval. */
c88dfebd 4574 tmp = use_expire + (use_expire / 2);
9f9265b6 4575 } else if (ia->rebind == 0xffffffff)
420d8b3f
FD
4576 tmp = MAX_TIME;
4577 else
c88dfebd 4578 tmp = ia->rebind;
98bd7ca0 4579
420d8b3f
FD
4580 if (tmp < rebind)
4581 rebind = tmp;
4582 }
703873ab
DH
4583
4584 /*
4585 * Return expiration ranges to EPOCH relative for event
4586 * scheduling (add_timeout()).
4587 */
4588 this_ia_hi_expire += ia->starts;
4589 this_ia_lo_expire += ia->starts;
4590
4591 if (this_ia_hi_expire > hi_expire)
4592 hi_expire = this_ia_hi_expire;
4593 if (this_ia_lo_expire < lo_expire)
4594 lo_expire = this_ia_lo_expire;
98bd7ca0
DH
4595 }
4596
4597 /* If there are no addresses, give up, go to INIT.
4598 * Note that if an address is unexpired with a date in the past,
4599 * we're scheduling an expiration event to ocurr in the past. We
4600 * could probably optimize this to expire now (but then there's
4601 * recursion).
4602 *
4603 * In the future, we may decide that we're done here, or to
4604 * schedule a future request (using 4-pkt info-request model).
4605 */
4606 if (has_addrs == ISC_FALSE) {
e32529a5 4607 dhc6_lease_destroy(&client->active_lease, MDL);
98bd7ca0
DH
4608 client->active_lease = NULL;
4609
4610 /* Go back to the beginning. */
4611 start_init6(client);
4612 return;
4613 }
4614
c88dfebd
SR
4615 /* Second part of calculating the renew and rebind times.
4616 * We have the start time and the desired periods for renew
4617 * and rebind, just add them to get the desired end time.
4618 */
4619 if (renew != MAX_TIME)
4620 renew += max_ia_starts;
4621 if (rebind != MAX_TIME)
4622 rebind += max_ia_starts;
4623
98bd7ca0
DH
4624 switch(client->state) {
4625 case S_BOUND:
4626 /* We'd like to hit renewing, but if rebinding has already
4627 * passed (time warp), head straight there.
4628 */
4629 if ((rebind > cur_time) && (renew < rebind)) {
4630 log_debug("PRC: Renewal event scheduled in %d seconds, "
4631 "to run for %u seconds.",
4632 (int)(renew - cur_time),
4633 (unsigned)(rebind - renew));
be62cf06
FD
4634 client->next_MRD = rebind;
4635 tv.tv_sec = renew;
4636 tv.tv_usec = 0;
4637 add_timeout(&tv, start_renew6, client, NULL, NULL);
98bd7ca0
DH
4638
4639 break;
4640 }
4641 /* FALL THROUGH */
4642 case S_RENEWING:
4643 /* While actively renewing, MRD is bounded by the time
4644 * we stop renewing and start rebinding. This helps us
4645 * process the state change on time.
4646 */
4647 client->MRD = rebind - cur_time;
4648 if (rebind != MAX_TIME) {
4649 log_debug("PRC: Rebind event scheduled in %d seconds, "
4650 "to run for %d seconds.",
4651 (int)(rebind - cur_time),
4652 (int)(hi_expire - rebind));
be62cf06
FD
4653 client->next_MRD = hi_expire;
4654 tv.tv_sec = rebind;
4655 tv.tv_usec = 0;
4656 add_timeout(&tv, start_rebind6, client, NULL, NULL);
98bd7ca0
DH
4657 }
4658 break;
4659
4660 case S_REBINDING:
4661 /* For now, we rebind up until the last lease expires. In
4662 * the future, we might want to start SOLICITing when we've
4663 * depreffed an address.
4664 */
4665 client->MRD = hi_expire - cur_time;
4666 break;
4667
4668 default:
251bb4b9 4669 if (has_preferred_addrs) {
4670 log_fatal("Impossible condition, state %d at %s:%d.",
4671 client->state, MDL);
4672 }
98bd7ca0
DH
4673 }
4674
4675 /* Separately, set a time at which we will depref and expire
4676 * leases. This might happen with multiple addresses while we
4677 * keep trying to refresh.
4678 */
4679 if (depref != MAX_TIME) {
4680 log_debug("PRC: Depreference scheduled in %d seconds.",
4681 (int)(depref - cur_time));
be62cf06
FD
4682 tv.tv_sec = depref;
4683 tv.tv_usec = 0;
4684 add_timeout(&tv, do_depref, client, NULL, NULL);
98bd7ca0
DH
4685 }
4686 if (lo_expire != MAX_TIME) {
4687 log_debug("PRC: Expiration scheduled in %d seconds.",
4688 (int)(lo_expire - cur_time));
be62cf06
FD
4689 tv.tv_sec = lo_expire;
4690 tv.tv_usec = 0;
4691 add_timeout(&tv, do_expire, client, NULL, NULL);
98bd7ca0
DH
4692 }
4693}
4694
420d8b3f 4695/* In a given IA chain, find the IA with the same type and 'iaid'. */
98bd7ca0 4696static struct dhc6_ia *
420d8b3f 4697find_ia(struct dhc6_ia *head, u_int16_t type, const char *id)
98bd7ca0
DH
4698{
4699 struct dhc6_ia *ia;
4700
4701 for (ia = head ; ia != NULL ; ia = ia->next) {
420d8b3f 4702 if (ia->ia_type != type)
1d9774ab 4703 continue;
98bd7ca0
DH
4704 if (memcmp(ia->iaid, id, 4) == 0)
4705 return ia;
4706 }
4707
4708 return NULL;
4709}
4710
4711/* In a given address chain, find a matching address. */
4712static struct dhc6_addr *
4713find_addr(struct dhc6_addr *head, struct iaddr *address)
4714{
4715 struct dhc6_addr *addr;
4716
4717 for (addr = head ; addr != NULL ; addr = addr->next) {
4718 if ((addr->address.len == address->len) &&
4719 (memcmp(addr->address.iabuf, address->iabuf,
4720 address->len) == 0))
4721 return addr;
4722 }
4723
4724 return NULL;
4725}
4726
420d8b3f
FD
4727/* In a given prefix chain, find a matching prefix. */
4728static struct dhc6_addr *
4729find_pref(struct dhc6_addr *head, struct iaddr *prefix, u_int8_t plen)
4730{
4731 struct dhc6_addr *pref;
4732
4733 for (pref = head ; pref != NULL ; pref = pref->next) {
4734 if ((pref->address.len == prefix->len) &&
4735 (pref->plen == plen) &&
4736 (memcmp(pref->address.iabuf, prefix->iabuf,
4737 prefix->len) == 0))
4738 return pref;
4739 }
4740
4741 return NULL;
4742}
4743
c88dfebd
SR
4744/*
4745 *
4746 * \brief Merge the bindings from the source lease into the destination
4747 * lease structure, where they are missing.
4748 *
4749 * This is used to merge any extra information we have in the current
4750 * (older, src) lease into the lease we have just received. For example
4751 * the src lease might include a binding for an NA that is still usable
4752 * but that we didn't request or that the server is no longer serving.
4753 * We want to keep that information until we toss the binding (expire,
4754 * release) so we move it to the new lease.
4755 *
4756 * We have to copy the stateful objects rather than move them over,
4757 * because later code needs to be able to compare new versus old if
4758 * they contain any bindings.
4759 *
4760 * \param src The older lease to copy the objects from
4761 * \param dst The newer lease to copy the objects to
98bd7ca0
DH
4762 */
4763static void
4764dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst)
4765{
c88dfebd 4766 struct dhc6_ia *sia, *dia, *tia, **eia;
98bd7ca0
DH
4767 struct dhc6_addr *saddr, *daddr, *taddr;
4768 int changes = 0;
4769
4770 if ((dst == NULL) || (src == NULL))
4771 return;
4772
4773 for (sia = src->bindings ; sia != NULL ; sia = sia->next) {
420d8b3f 4774 dia = find_ia(dst->bindings, sia->ia_type, (char *)sia->iaid);
98bd7ca0
DH
4775
4776 if (dia == NULL) {
4777 tia = dhc6_dup_ia(sia, MDL);
4778
4779 if (tia == NULL)
4780 log_fatal("Out of memory merging lease - "
4781 "Unable to continue without losing "
4782 "state! (%s:%d)", MDL);
4783
c88dfebd
SR
4784 /* Put any bindings that aren't in the new lease at the
4785 * end of the list. If the user or server reduces the
4786 * number of IAs the ones in use will be at the front
4787 * and will be used when building the next requests
4788 * We could be more efficient by finding the end
4789 * of the list once but we don't expect to do this
4790 * often.
4791 */
4792 for (eia = &dst->bindings;
4793 *eia != NULL;
4794 eia = &(*eia)->next) {
4795 ; /* no work just find the end */
4796 }
4797 *eia = tia;
98bd7ca0
DH
4798 changes = 1;
4799 } else {
4800 for (saddr = sia->addrs ; saddr != NULL ;
4801 saddr = saddr->next) {
420d8b3f
FD
4802 if (sia->ia_type != D6O_IA_PD)
4803 daddr = find_addr(dia->addrs,
4804 &saddr->address);
4805 else
4806 daddr = find_pref(dia->addrs,
4807 &saddr->address,
4808 saddr->plen);
98bd7ca0
DH
4809
4810 if (daddr == NULL) {
4811 taddr = dhc6_dup_addr(saddr, MDL);
4812
4813 if (taddr == NULL)
4814 log_fatal("Out of memory "
4815 "merging lease - "
4816 "Unable to continue "
4817 "without losing "
4818 "state! (%s:%d)",
4819 MDL);
4820
4821 /* XXX: consider sorting? */
4822 taddr->next = dia->addrs;
4823 dia->addrs = taddr;
4824 changes = 1;
4825 }
4826 }
4827 }
4828 }
4829
4830 /* If we made changes, reset the score to 0 so it is recalculated. */
4831 if (changes)
4832 dst->score = 0;
4833}
4834
4835/* We've either finished selecting or succeeded in Renew or Rebinding our
4836 * lease. In all cases we got a Reply. Give dhclient-script a tickle
4837 * to inform it about the new values, and then lay in wait for the next
4838 * event.
4839 */
3dbe2246 4840static void
98bd7ca0
DH
4841start_bound(struct client_state *client)
4842{
4843 struct dhc6_ia *ia, *oldia;
4844 struct dhc6_addr *addr, *oldaddr;
4845 struct dhc6_lease *lease, *old;
06eb8bab 4846 const char *reason;
0f69ff73 4847 int decline_cnt = 0;
98bf1607 4848#if defined (NSUPDATE)
98bd7ca0 4849 TIME dns_update_offset = 1;
98bf1607 4850#endif
98bd7ca0
DH
4851
4852 lease = client->active_lease;
4853 if (lease == NULL) {
4854 log_error("Cannot enter bound state unless an active lease "
4855 "is selected.");
4856 return;
4857 }
cabdb9b1 4858 lease->released = ISC_FALSE;
98bd7ca0
DH
4859 old = client->old_lease;
4860
4861 client->v6_handler = bound_handler;
4862
4863 switch (client->state) {
4864 case S_SELECTING:
4865 case S_REBOOTING: /* Pretend we got bound. */
4866 reason = "BOUND6";
4867 break;
4868
4869 case S_RENEWING:
4870 reason = "RENEW6";
4871 break;
4872
4873 case S_REBINDING:
4874 reason = "REBIND6";
4875 break;
4876
4877 default:
4878 log_fatal("Impossible condition at %s:%d.", MDL);
6705543f
DH
4879 /* Silence compiler warnings. */
4880 return;
98bd7ca0
DH
4881 }
4882
4883 log_debug("PRC: Bound to lease %s.",
4884 print_hex_1(client->active_lease->server_id.len,
4885 client->active_lease->server_id.data, 55));
4886 client->state = S_BOUND;
4887
4888 write_client6_lease(client, lease, 0, 1);
4889
4890 oldia = NULL;
4891 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4892 if (old != NULL)
420d8b3f
FD
4893 oldia = find_ia(old->bindings,
4894 ia->ia_type,
4895 (char *)ia->iaid);
98bd7ca0
DH
4896 else
4897 oldia = NULL;
4898
4899 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
30dcfbf6
SR
4900 /* Don't try to use the address if it's already expired */
4901 if (addr->flags & DHC6_ADDR_EXPIRED)
4902 continue;
4903
420d8b3f
FD
4904 if (oldia != NULL) {
4905 if (ia->ia_type != D6O_IA_PD)
4906 oldaddr = find_addr(oldia->addrs,
4907 &addr->address);
4908 else
4909 oldaddr = find_pref(oldia->addrs,
4910 &addr->address,
4911 addr->plen);
4912 } else
98bd7ca0
DH
4913 oldaddr = NULL;
4914
98bf1607 4915#if defined (NSUPDATE)
420d8b3f 4916 if ((oldaddr == NULL) && (ia->ia_type == D6O_IA_NA))
98bd7ca0
DH
4917 dhclient_schedule_updates(client,
4918 &addr->address,
4919 dns_update_offset++);
98bf1607 4920#endif
98bd7ca0
DH
4921
4922 /* Shell out to setup the new binding. */
4923 script_init(client, reason, NULL);
4924
4925 if (old != NULL)
4926 dhc6_marshall_values("old_", client, old,
4927 oldia, oldaddr);
4928 dhc6_marshall_values("new_", client, lease, ia, addr);
10613724 4929 script_write_requested6(client);
98bd7ca0 4930
0f69ff73
TM
4931 /* When script returns 3, DAD failed */
4932 if (script_go(client) == 3) {
4933 if (ia->ia_type == D6O_IA_NA) {
4934 addr->flags |= DHC6_ADDR_DECLINED;
4935 log_debug ("Flag address declined:%s",
4936 piaddr(addr->address));
4937 decline_cnt++;
4938 }
4939 }
4940 }
4941
4942 /* If the client script DAD failed any addresses we need
4943 * build and issue a DECLINE */
4944 if (decline_cnt) {
4945 start_decline6(client);
4946 return;
98bd7ca0
DH
4947 }
4948
4949 /* XXX: maybe we should loop on the old values instead? */
4950 if (ia->addrs == NULL) {
4951 script_init(client, reason, NULL);
4952
4953 if (old != NULL)
4954 dhc6_marshall_values("old_", client, old,
8ea19a71
DH
4955 oldia,
4956 oldia != NULL ?
4957 oldia->addrs : NULL);
98bd7ca0
DH
4958
4959 dhc6_marshall_values("new_", client, lease, ia,
4960 NULL);
10613724 4961 script_write_requested6(client);
8ea19a71
DH
4962
4963 script_go(client);
98bd7ca0
DH
4964 }
4965 }
4966
4967 /* XXX: maybe we should loop on the old values instead? */
4968 if (lease->bindings == NULL) {
4969 script_init(client, reason, NULL);
4970
4971 if (old != NULL)
4972 dhc6_marshall_values("old_", client, old,
4973 old->bindings,
4974 (old->bindings != NULL) ?
4975 old->bindings->addrs : NULL);
4976
4977 dhc6_marshall_values("new_", client, lease, NULL, NULL);
10613724 4978 script_write_requested6(client);
8ea19a71
DH
4979
4980 script_go(client);
98bd7ca0
DH
4981 }
4982
785c1a51
FD
4983#ifdef DHCP4o6
4984 if (dhcpv4_over_dhcpv6)
4985 dhcp4o6_start();
4986#endif
4987
29b23207 4988 detach();
8ea19a71 4989
98bd7ca0 4990 if (client->old_lease != NULL) {
e32529a5 4991 dhc6_lease_destroy(&client->old_lease, MDL);
98bd7ca0
DH
4992 client->old_lease = NULL;
4993 }
4994
4995 /* Schedule events. */
4996 dhc6_check_times(client);
4997}
4998
4999/* While bound, ignore packets. In the future we'll want to answer
5000 * Reconfigure-Request messages and the like.
5001 */
5002void
5003bound_handler(struct packet *packet, struct client_state *client)
5004{
5005 log_debug("RCV: Input packets are ignored once bound.");
5006}
5007
0f69ff73
TM
5008/*
5009 * start_decline6() kicks off the decline process, transmitting
5010 * an decline packet and scheduling a retransmission event.
5011 */
5012void
5013start_decline6(struct client_state *client)
5014{
5015 /* Cancel any pending transmissions */
5016 cancel_timeout(do_confirm6, client);
5017 cancel_timeout(do_select6, client);
5018 cancel_timeout(do_refresh6, client);
5019 cancel_timeout(do_release6, client);
5020 cancel_timeout(do_decline6, client);
5021 client->state = S_DECLINING;
5022
5023 if (client->active_lease == NULL)
5024 return;
5025
5026 /* Set timers per RFC3315 section 18.1.7. */
5027 client->IRT = DEC_TIMEOUT * 100;
5028 client->MRT = 0;
5029 client->MRC = DEC_MAX_RC;
5030 client->MRD = 0;
5031
5032 dhc6_retrans_init(client);
5033 client->v6_handler = reply_handler;
5034
5035 client->refresh_type = DHCPV6_DECLINE;
5036 do_decline6(client);
5037}
5038
5039/*
5040 * do_decline6() creates a Decline packet and transmits it.
5041 * The decline will contain an IA_NA with iasubopt(s) for
5042 * each IA_NA containing declined address(es) in the active
5043 * lease.
5044 */
5045static void
5046do_decline6(void *input)
5047{
5048 struct client_state *client;
5049 struct data_string ds;
5050 int send_ret;
5051 struct timeval elapsed, tv;
5052
5053 client = input;
5054 if (client == NULL || client->active_lease == NULL) {
5055 return;
5056 }
5057
5058 if ((client->MRC != 0) && (client->txcount > client->MRC)) {
5059 log_info("Max retransmission count exceeded.");
5060 goto decline_done;
5061 }
5062
5063 /*
5064 * Start_time starts at the first transmission.
5065 */
5066 if (client->txcount == 0) {
5067 client->start_time.tv_sec = cur_tv.tv_sec;
5068 client->start_time.tv_usec = cur_tv.tv_usec;
5069 }
5070
5071 /* elapsed = cur - start */
5072 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
5073 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
5074 if (elapsed.tv_usec < 0) {
5075 elapsed.tv_sec -= 1;
5076 elapsed.tv_usec += 1000000;
5077 }
5078
5079 memset(&ds, 0, sizeof(ds));
5080 if (!buffer_allocate(&ds.buffer, 4, MDL)) {
5081 log_error("Unable to allocate memory for Decline.");
5082 goto decline_done;
5083 }
5084
5085 ds.data = ds.buffer->data;
5086 ds.len = 4;
5087 ds.buffer->data[0] = DHCPV6_DECLINE;
5088 memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
5089
5090 /* Form an elapsed option. */
5091 /* Maximum value is 65535 1/100s coded as 0xffff. */
5092 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
5093 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
5094 client->elapsed = 0xffff;
5095 } else {
5096 client->elapsed = elapsed.tv_sec * 100;
5097 client->elapsed += elapsed.tv_usec / 10000;
5098 }
5099
5100 client->elapsed = htons(client->elapsed);
5101
5102 log_debug("XMT: Forming Decline.");
5103 make_client6_options(client, &client->sent_options,
5104 client->active_lease, DHCPV6_DECLINE);
5105 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
5106 client->sent_options, &global_scope,
5107 &dhcpv6_universe);
5108
5109 /* Append IA_NA's. */
5110 if (dhc6_add_ia_na_decline(client, &ds, client->active_lease)
5111 != ISC_R_SUCCESS) {
5112 data_string_forget(&ds, MDL);
5113 goto decline_done;
5114 }
5115
5116 /* Transmit and wait. */
5117 log_info("XMT: Decline on %s, interval %ld0ms.",
5118 client->name ? client->name : client->interface->name,
5119 (long int)client->RT);
5120
5121 send_ret = send_packet6(client->interface, ds.data, ds.len,
5122 &DHCPv6DestAddr);
5123 if (send_ret != ds.len) {
5124 log_error("dhc6: sendpacket6() sent %d of %d bytes",
5125 send_ret, ds.len);
5126 }
5127
5128 data_string_forget(&ds, MDL);
5129
5130 /* Wait RT */
5131 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
5132 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
5133 if (tv.tv_usec >= 1000000) {
5134 tv.tv_sec += 1;
5135 tv.tv_usec -= 1000000;
5136 }
5137 add_timeout(&tv, do_decline6, client, NULL, NULL);
5138 dhc6_retrans_advance(client);
5139 return;
5140
5141decline_done:
5142 /* We here because we've exhausted our retry limits or
5143 * something else has gone wrong with the decline process.
5144 * So let's just toss the existing lease and start over.
5145 */
5146 if (client->active_lease != NULL) {
5147 dhc6_lease_destroy(&client->active_lease, MDL);
5148 client->active_lease = NULL;
5149 }
5150
5151 start_init6(client);
5152 return;
5153}
5154
98bd7ca0 5155/* start_renew6() gets us all ready to go to start transmitting Renew packets.
be62cf06
FD
5156 * Note that client->next_MRD must be set before entering this function -
5157 * it must be set to the time at which the client should start Rebinding.
98bd7ca0
DH
5158 */
5159void
5160start_renew6(void *input)
5161{
5162 struct client_state *client;
5163
5164 client = (struct client_state *)input;
5165
5166 log_info("PRC: Renewing lease on %s.",
5167 client->name ? client->name : client->interface->name);
5168 client->state = S_RENEWING;
5169
5170 client->v6_handler = reply_handler;
5171
5172 /* Times per RFC3315 section 18.1.3. */
be62cf06
FD
5173 client->IRT = REN_TIMEOUT * 100;
5174 client->MRT = REN_MAX_RT * 100;
98bd7ca0
DH
5175 client->MRC = 0;
5176 /* MRD is special in renew - we need to set it by checking timer
5177 * state.
5178 */
be62cf06 5179 client->MRD = client->next_MRD - cur_time;
98bd7ca0
DH
5180
5181 dhc6_retrans_init(client);
5182
5183 client->refresh_type = DHCPV6_RENEW;
5184 do_refresh6(client);
5185}
5186
5187/* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
5188 * gives the retransmission state a bump for the next time. Note that
5189 * client->refresh_type must be set before entering this function.
5190 */
5191void
5192do_refresh6(void *input)
5193{
5194 struct option_cache *oc;
5195 struct sockaddr_in6 unicast, *dest_addr = &DHCPv6DestAddr;
5196 struct data_string ds;
5197 struct client_state *client;
5198 struct dhc6_lease *lease;
be62cf06 5199 struct timeval elapsed, tv;
c88dfebd 5200 int send_ret, added;
98bd7ca0
DH
5201
5202 client = (struct client_state *)input;
420d8b3f 5203 memset(&ds, 0, sizeof(ds));
98bd7ca0
DH
5204
5205 lease = client->active_lease;
5206 if (lease == NULL) {
5207 log_error("Cannot renew without an active binding.");
5208 return;
5209 }
5210
5211 /* Ensure we're emitting a valid message type. */
5212 switch (client->refresh_type) {
5213 case DHCPV6_RENEW:
5214 case DHCPV6_REBIND:
5215 break;
5216
5217 default:
5218 log_fatal("Internal inconsistency (%d) at %s:%d.",
5219 client->refresh_type, MDL);
5220 }
5221
be62cf06
FD
5222 /*
5223 * Start_time starts at the first transmission.
5224 */
5225 if (client->txcount == 0) {
5226 client->start_time.tv_sec = cur_tv.tv_sec;
5227 client->start_time.tv_usec = cur_tv.tv_usec;
5228 }
5229
5230 /* elapsed = cur - start */
5231 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
5232 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
5233 if (elapsed.tv_usec < 0) {
5234 elapsed.tv_sec -= 1;
5235 elapsed.tv_usec += 1000000;
5236 }
98bd7ca0 5237 if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
be62cf06 5238 ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
98bd7ca0
DH
5239 /* We're done. Move on to the next phase, if any. */
5240 dhc6_check_times(client);
5241 return;
5242 }
5243
5244 /*
5245 * Check whether the server has sent a unicast option; if so, we can
b51c785f 5246 * use the address it specified for RENEWs.
98bd7ca0
DH
5247 */
5248 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_UNICAST);
5249 if (oc && evaluate_option_cache(&ds, NULL, NULL, NULL,
420d8b3f 5250 lease->options, NULL, &global_scope,
98bd7ca0
DH
5251 oc, MDL)) {
5252 if (ds.len < 16) {
5253 log_error("Invalid unicast option length %d.", ds.len);
5254 } else {
5255 memset(&unicast, 0, sizeof(DHCPv6DestAddr));
5256 unicast.sin6_family = AF_INET6;
5257 unicast.sin6_port = remote_port;
5258 memcpy(&unicast.sin6_addr, ds.data, 16);
b51c785f
FD
5259 if (client->refresh_type == DHCPV6_RENEW) {
5260 dest_addr = &unicast;
5261 }
98bd7ca0
DH
5262 }
5263
5264 data_string_forget(&ds, MDL);
5265 }
5266
5267 /* Commence forming a renew packet. */
5268 memset(&ds, 0, sizeof(ds));
5269 if (!buffer_allocate(&ds.buffer, 4, MDL)) {
5270 log_error("Unable to allocate memory for packet.");
5271 return;
5272 }
5273 ds.data = ds.buffer->data;
5274 ds.len = 4;
5275
5276 ds.buffer->data[0] = client->refresh_type;
5277 memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
5278
be62cf06
FD
5279 /* Form an elapsed option. */
5280 /* Maximum value is 65535 1/100s coded as 0xffff. */
5281 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
5282 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
98bd7ca0 5283 client->elapsed = 0xffff;
be62cf06
FD
5284 } else {
5285 client->elapsed = elapsed.tv_sec * 100;
5286 client->elapsed += elapsed.tv_usec / 10000;
5287 }
98bd7ca0 5288
be62cf06
FD
5289 if (client->elapsed == 0)
5290 log_debug("XMT: Forming %s, 0 ms elapsed.",
5291 dhcpv6_type_names[client->refresh_type]);
5292 else
5293 log_debug("XMT: Forming %s, %u0 ms elapsed.",
5294 dhcpv6_type_names[client->refresh_type],
5295 (unsigned)client->elapsed);
98bd7ca0
DH
5296
5297 client->elapsed = htons(client->elapsed);
5298
5299 make_client6_options(client, &client->sent_options, lease,
5300 client->refresh_type);
5301
5302 /* Put in any options from the sent cache. */
5303 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
5304 client->sent_options, &global_scope,
5305 &dhcpv6_universe);
5306
c88dfebd
SR
5307 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
5308 * For each type of IA (na, ta, pd) we start with the ones for
5309 * which we already have addresses (dhc6_add_ia_xx) and then
5310 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
5311 */
420d8b3f 5312 if (wanted_ia_na &&
c88dfebd
SR
5313 ((dhc6_add_ia_na(client, &ds, lease, client->refresh_type,
5314 wanted_ia_na, &added) != ISC_R_SUCCESS) ||
5315 (dhc6_bare_ia_xx(client, &ds, wanted_ia_na - added,
5316 D6O_IA_NA) != ISC_R_SUCCESS))) {
420d8b3f
FD
5317 data_string_forget(&ds, MDL);
5318 return;
5319 }
5320 if (wanted_ia_pd &&
c88dfebd
SR
5321 ((dhc6_add_ia_pd(client, &ds, lease, client->refresh_type,
5322 wanted_ia_pd, &added) != ISC_R_SUCCESS) ||
5323 (dhc6_bare_ia_xx(client, &ds, wanted_ia_pd - added,
5324 D6O_IA_PD) != ISC_R_SUCCESS))) {
98bd7ca0
DH
5325 data_string_forget(&ds, MDL);
5326 return;
5327 }
5328
be62cf06 5329 log_info("XMT: %s on %s, interval %ld0ms.",
98bd7ca0
DH
5330 dhcpv6_type_names[client->refresh_type],
5331 client->name ? client->name : client->interface->name,
9aa669fc 5332 (long int)client->RT);
98bd7ca0
DH
5333
5334 send_ret = send_packet6(client->interface, ds.data, ds.len, dest_addr);
5335
5336 if (send_ret != ds.len) {
5337 log_error("dhc6: send_packet6() sent %d of %d bytes",
5338 send_ret, ds.len);
5339 }
5340
5341 data_string_forget(&ds, MDL);
5342
be62cf06
FD
5343 /* Wait RT */
5344 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
5345 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
5346 if (tv.tv_usec >= 1000000) {
5347 tv.tv_sec += 1;
5348 tv.tv_usec -= 1000000;
5349 }
5350 add_timeout(&tv, do_refresh6, client, NULL, NULL);
98bd7ca0
DH
5351
5352 dhc6_retrans_advance(client);
5353}
5354
5355/* start_rebind6() gets us all set up to go and rebind a lease. Note that
be62cf06 5356 * client->next_MRD must be set before entering this function. In this case,
98bd7ca0
DH
5357 * MRD must be set to the maximum time any address in the packet will
5358 * expire.
5359 */
5360void
5361start_rebind6(void *input)
5362{
5363 struct client_state *client;
5364
5365 client = (struct client_state *)input;
5366
5367 log_info("PRC: Rebinding lease on %s.",
5368 client->name ? client->name : client->interface->name);
5369 client->state = S_REBINDING;
5370
5371 client->v6_handler = reply_handler;
5372
5373 /* Times per RFC3315 section 18.1.4. */
be62cf06
FD
5374 client->IRT = REB_TIMEOUT * 100;
5375 client->MRT = REB_MAX_RT * 100;
98bd7ca0
DH
5376 client->MRC = 0;
5377 /* MRD is special in rebind - it's determined by the timer
5378 * state.
5379 */
be62cf06 5380 client->MRD = client->next_MRD - cur_time;
98bd7ca0
DH
5381
5382 dhc6_retrans_init(client);
5383
5384 client->refresh_type = DHCPV6_REBIND;
5385 do_refresh6(client);
5386}
5387
5388/* do_depref() runs through a given lease's addresses, for each that has
5389 * not yet been depreffed, shells out to the dhclient-script to inform it
5390 * of the status change. The dhclient-script should then do...something...
5391 * to encourage applications to move off the address and onto one of the
5392 * remaining 'preferred' addresses.
5393 */
5394void
5395do_depref(void *input)
5396{
5397 struct client_state *client;
5398 struct dhc6_lease *lease;
5399 struct dhc6_ia *ia;
5400 struct dhc6_addr *addr;
5401
5402 client = (struct client_state *)input;
5403
5404 lease = client->active_lease;
5405 if (lease == NULL)
5406 return;
5407
5408 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
5409 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
5410 if (addr->flags & DHC6_ADDR_DEPREFFED)
5411 continue;
5412
5413 if (addr->starts + addr->preferred_life <= cur_time) {
5414 script_init(client, "DEPREF6", NULL);
5415 dhc6_marshall_values("cur_", client, lease,
5416 ia, addr);
10613724 5417 script_write_requested6(client);
98bd7ca0
DH
5418 script_go(client);
5419
98bd7ca0
DH
5420 addr->flags |= DHC6_ADDR_DEPREFFED;
5421
420d8b3f
FD
5422 if (ia->ia_type != D6O_IA_PD)
5423 log_info("PRC: Address %s depreferred.",
5424 piaddr(addr->address));
5425 else
5426 log_info("PRC: Prefix %s/%u depreferred.",
5427 piaddr(addr->address),
5428 (unsigned) addr->plen);
5429
98bf1607 5430#if defined (NSUPDATE)
98bd7ca0 5431 /* Remove DDNS bindings at depref time. */
420d8b3f
FD
5432 if ((ia->ia_type == D6O_IA_NA) &&
5433 client->config->do_forward_update)
c88dfebd 5434 client_dns_remove(client,
98bd7ca0 5435 &addr->address);
98bf1607 5436#endif
98bd7ca0
DH
5437 }
5438 }
5439 }
5440
5441 dhc6_check_times(client);
5442}
5443
5444/* do_expire() searches through all the addresses on a given lease, and
5445 * expires/removes any addresses that are no longer valid.
5446 */
5447void
5448do_expire(void *input)
5449{
5450 struct client_state *client;
5451 struct dhc6_lease *lease;
c88dfebd 5452 struct dhc6_ia *ia, **tia;
98bd7ca0
DH
5453 struct dhc6_addr *addr;
5454 int has_addrs = ISC_FALSE;
c88dfebd 5455 int ia_has_addrs = ISC_FALSE;
98bd7ca0
DH
5456
5457 client = (struct client_state *)input;
5458
5459 lease = client->active_lease;
5460 if (lease == NULL)
5461 return;
5462
c88dfebd
SR
5463 for (ia = lease->bindings, tia = &lease->bindings; ia != NULL ; ) {
5464 ia_has_addrs = ISC_FALSE;
98bd7ca0
DH
5465 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
5466 if (addr->flags & DHC6_ADDR_EXPIRED)
5467 continue;
5468
5469 if (addr->starts + addr->max_life <= cur_time) {
5470 script_init(client, "EXPIRE6", NULL);
5471 dhc6_marshall_values("old_", client, lease,
5472 ia, addr);
10613724 5473 script_write_requested6(client);
98bd7ca0
DH
5474 script_go(client);
5475
5476 addr->flags |= DHC6_ADDR_EXPIRED;
5477
420d8b3f
FD
5478 if (ia->ia_type != D6O_IA_PD)
5479 log_info("PRC: Address %s expired.",
5480 piaddr(addr->address));
5481 else
5482 log_info("PRC: Prefix %s/%u expired.",
5483 piaddr(addr->address),
5484 (unsigned) addr->plen);
98bd7ca0 5485
98bf1607 5486#if defined (NSUPDATE)
98bd7ca0
DH
5487 /* We remove DNS records at depref time, but
5488 * it is possible that we might get here
5489 * without depreffing.
5490 */
420d8b3f
FD
5491 if ((ia->ia_type == D6O_IA_NA) &&
5492 client->config->do_forward_update &&
98bd7ca0 5493 !(addr->flags & DHC6_ADDR_DEPREFFED))
98bf1607 5494 client_dns_remove(client,
98bd7ca0 5495 &addr->address);
98bf1607 5496#endif
98bd7ca0
DH
5497
5498 continue;
5499 }
5500
c88dfebd 5501 ia_has_addrs = ISC_TRUE;
98bd7ca0
DH
5502 has_addrs = ISC_TRUE;
5503 }
c88dfebd
SR
5504
5505 /* Update to the next ia and git rid of this ia
5506 * if it doesn't have any leases.
5507 */
5508 if (ia_has_addrs == ISC_TRUE) {
5509 /* leases, just advance the list pointer */
5510 tia = &(*tia)->next;
5511 } else {
5512 /* no leases, update the list pointer
5513 * and free the ia
5514 */
5515 *tia = ia->next;
5516 dhc6_ia_destroy(&ia, MDL);
5517 }
5518 /* lastly update the ia pointer to our new ia */
5519 ia = *tia;
98bd7ca0
DH
5520 }
5521
5522 /* Clean up empty leases. */
5523 if (has_addrs == ISC_FALSE) {
5524 log_info("PRC: Bound lease is devoid of active addresses."
5525 " Re-initializing.");
5526
e32529a5 5527 dhc6_lease_destroy(&lease, MDL);
98bd7ca0
DH
5528 client->active_lease = NULL;
5529
5530 start_init6(client);
5531 return;
5532 }
5533
5534 /* Schedule the next run through. */
5535 dhc6_check_times(client);
5536}
5537
af5fa176
EH
5538/*
5539 * Run client script to unconfigure interface.
5540 * Called with reason STOP6 when dhclient -x is run, or with reason
5541 * RELEASE6 when server has replied to a Release message.
3dbe2246 5542 * Stateless is a special case.
af5fa176
EH
5543 */
5544void
5545unconfigure6(struct client_state *client, const char *reason)
5546{
af5fa176
EH
5547 struct dhc6_ia *ia;
5548 struct dhc6_addr *addr;
5549
3dbe2246
FD
5550 if (stateless) {
5551 script_init(client, reason, NULL);
5552 if (client->active_lease != NULL)
5553 script_write_params6(client, "old_",
5554 client->active_lease->options);
10613724 5555 script_write_requested6(client);
3dbe2246
FD
5556 script_go(client);
5557 return;
5558 }
5559
af5fa176
EH
5560 if (client->active_lease == NULL)
5561 return;
5562
5563 for (ia = client->active_lease->bindings ; ia != NULL ; ia = ia->next) {
420d8b3f 5564 if (ia->ia_type == D6O_IA_TA)
1d9774ab
FD
5565 continue;
5566
af5fa176
EH
5567 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
5568 script_init(client, reason, NULL);
420d8b3f 5569 dhc6_marshall_values("old_", client,
06eb8bab 5570 client->active_lease, ia, addr);
10613724 5571 script_write_requested6(client);
af5fa176 5572 script_go(client);
420d8b3f 5573
98bf1607 5574#if defined (NSUPDATE)
420d8b3f
FD
5575 if ((ia->ia_type == D6O_IA_NA) &&
5576 client->config->do_forward_update)
98bf1607
SR
5577 client_dns_remove(client, &addr->address);
5578#endif
af5fa176
EH
5579 }
5580 }
5581}
5582
3dbe2246
FD
5583void
5584refresh_info_request6(void *input)
5585{
5586 struct client_state *client;
5587
5588 client = (struct client_state *)input;
5589 start_info_request6(client);
5590}
5591
5592/* Timeout for Information-Request (using the IRT option).
5593 */
5594static void
5595dhc6_check_irt(struct client_state *client)
5596{
5597 struct option **req;
5598 struct option_cache *oc;
5599 TIME expire = MAX_TIME;
5600 struct timeval tv;
5601 int i;
5602 isc_boolean_t found = ISC_FALSE;
5603
5604 cancel_timeout(refresh_info_request6, client);
5605
5606 req = client->config->requested_options;
5607 for (i = 0; req[i] != NULL; i++) {
5608 if (req[i] == irt_option) {
5609 found = ISC_TRUE;
5610 break;
5611 }
5612 }
5613 /* Simply return gives a endless loop waiting for nothing. */
785c1a51
FD
5614 if (!found) {
5615#ifdef DHCP4o6
5616 if (!dhcpv4_over_dhcpv6)
5617#endif
29b23207 5618 finish(0);
785c1a51 5619 }
3dbe2246
FD
5620
5621 oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
5622 D6O_INFORMATION_REFRESH_TIME);
5623 if (oc != NULL) {
5624 struct data_string irt;
5625
5626 memset(&irt, 0, sizeof(irt));
5627 if (!evaluate_option_cache(&irt, NULL, NULL, client,
5628 client->active_lease->options,
5629 NULL, &global_scope, oc, MDL) ||
5630 (irt.len < 4)) {
5631 log_error("Can't evaluate IRT.");
5632 } else {
5633 expire = getULong(irt.data);
5634 if (expire < IRT_MINIMUM)
5635 expire = IRT_MINIMUM;
5636 if (expire == 0xffffffff)
5637 expire = MAX_TIME;
5638 }
5639 data_string_forget(&irt, MDL);
5640 } else
5641 expire = IRT_DEFAULT;
5642
5643 if (expire != MAX_TIME) {
5644 log_debug("PRC: Refresh event scheduled in %u seconds.",
5645 (unsigned) expire);
5646 tv.tv_sec = cur_time + expire;
5647 tv.tv_usec = 0;
5648 add_timeout(&tv, refresh_info_request6, client, NULL, NULL);
5649 }
5650}
5651
5652/* We got a Reply. Give dhclient-script a tickle to inform it about
5653 * the new values, and then lay in wait for the next event.
5654 */
5655static void
5656start_informed(struct client_state *client)
5657{
5658 client->v6_handler = informed_handler;
5659
5660 log_debug("PRC: Done.");
5661
5662 client->state = S_BOUND;
5663
5664 script_init(client, "RENEW6", NULL);
5665 if (client->old_lease != NULL)
5666 script_write_params6(client, "old_",
5667 client->old_lease->options);
5668 script_write_params6(client, "new_", client->active_lease->options);
10613724 5669 script_write_requested6(client);
3dbe2246
FD
5670 script_go(client);
5671
785c1a51
FD
5672#ifdef DHCP4o6
5673 if (dhcpv4_over_dhcpv6)
5674 dhcp4o6_start();
5675#endif
5676
29b23207 5677 detach();
3dbe2246
FD
5678
5679 if (client->old_lease != NULL) {
5680 dhc6_lease_destroy(&client->old_lease, MDL);
5681 client->old_lease = NULL;
5682 }
5683
5684 /* Schedule events. */
5685 dhc6_check_irt(client);
5686}
5687
5688/* While informed, ignore packets.
5689 */
5690void
5691informed_handler(struct packet *packet, struct client_state *client)
5692{
5693 log_debug("RCV: Input packets are ignored once bound.");
5694}
5695
98bd7ca0
DH
5696/* make_client6_options() fetches option caches relevant to the client's
5697 * scope and places them into the sent_options cache. This cache is later
5698 * used to populate DHCPv6 output packets with options.
5699 */
5700static void
5701make_client6_options(struct client_state *client, struct option_state **op,
5702 struct dhc6_lease *lease, u_int8_t message)
5703{
98bd7ca0 5704 struct option_cache *oc;
0c20eab3 5705 struct option **req;
e5d83524
DH
5706 struct buffer *buffer;
5707 int buflen, i, oro_len;
98bd7ca0
DH
5708
5709 if ((op == NULL) || (client == NULL))
5710 return;
5711
5712 if (*op)
5713 option_state_dereference(op, MDL);
5714
0c20eab3 5715 /* Create a cache to carry options to transmission. */
98bd7ca0
DH
5716 option_state_allocate(op, MDL);
5717
0c20eab3 5718 /* Create and store an 'elapsed time' option in the cache. */
98bd7ca0
DH
5719 oc = NULL;
5720 if (option_cache_allocate(&oc, MDL)) {
5721 const unsigned char *cdata;
5722
5723 cdata = (unsigned char *)&client->elapsed;
5724
5725 if (make_const_data(&oc->expression, cdata, 2, 0, 0, MDL)) {
5726 option_reference(&oc->option, elapsed_option, MDL);
5727 save_option(&dhcpv6_universe, *op, oc);
5728 }
5729
5730 option_cache_dereference(&oc, MDL);
5731 }
5732
420d8b3f 5733 /* Bring in any configured options to send. */
9ab0cc6a
DH
5734 if (client->config->on_transmission)
5735 execute_statements_in_scope(NULL, NULL, NULL, client,
5736 lease ? lease->options : NULL,
5737 *op, &global_scope,
5738 client->config->on_transmission,
a7341359 5739 NULL, NULL);
9ab0cc6a 5740
6d7f9584
FD
5741 /* Rapid-commit is only for SOLICITs. */
5742 if (message != DHCPV6_SOLICIT)
5743 delete_option(&dhcpv6_universe, *op, D6O_RAPID_COMMIT);
5744
98bd7ca0
DH
5745 /* See if the user configured a DUID in a relevant scope. If not,
5746 * introduce our default manufactured id.
5747 */
5748 if ((oc = lookup_option(&dhcpv6_universe, *op,
5749 D6O_CLIENTID)) == NULL) {
5750 if (!option_cache(&oc, &default_duid, NULL, clientid_option,
5751 MDL))
5752 log_fatal("Failure assembling a DUID.");
5753
5754 save_option(&dhcpv6_universe, *op, oc);
5755 option_cache_dereference(&oc, MDL);
5756 }
5757
5758 /* In cases where we're responding to a single server, put the
5759 * server's id in the response.
5760 *
5761 * Note that lease is NULL for SOLICIT or INFO request messages,
5762 * and otherwise MUST be present.
5763 */
5764 if (lease == NULL) {
5765 if ((message != DHCPV6_SOLICIT) &&
5766 (message != DHCPV6_INFORMATION_REQUEST))
5767 log_fatal("Impossible condition at %s:%d.", MDL);
5768 } else if ((message != DHCPV6_REBIND) &&
5769 (message != DHCPV6_CONFIRM)) {
5770 oc = lookup_option(&dhcpv6_universe, lease->options,
5771 D6O_SERVERID);
5772 if (oc != NULL)
5773 save_option(&dhcpv6_universe, *op, oc);
5774 }
5775
0c20eab3
DH
5776 /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
5777 * deprecated by adjustments to the 'request' syntax also used for
5778 * DHCPv4.
5779 */
9ab0cc6a 5780 if (lookup_option(&dhcpv6_universe, *op, D6O_ORO) != NULL)
0c20eab3 5781 log_error("'send dhcp6.oro' syntax is deprecated, please "
44a67e65 5782 "use the 'request' syntax (\"man dhclient.conf\").");
0c20eab3
DH
5783
5784 /* Construct and store an ORO (Option Request Option). It is a
5785 * fatal error to fail to send an ORO (of at least zero length).
5786 *
5787 * Discussion: RFC3315 appears to be inconsistent in its statements
5788 * of whether or not the ORO is mandatory. In section 18.1.1
5789 * ("Creation and Transmission of Request Messages"):
5790 *
5791 * The client MUST include an Option Request option (see section
5792 * 22.7) to indicate the options the client is interested in
5793 * receiving. The client MAY include options with data values as
5794 * hints to the server about parameter values the client would like
5795 * to have returned.
5796 *
5797 * This MUST is missing from the creation/transmission of other
5798 * messages (such as Renew and Rebind), and the section 22.7 ("Option
5799 * Request Option" format and definition):
5800 *
5801 * A client MAY include an Option Request option in a Solicit,
5802 * Request, Renew, Rebind, Confirm or Information-request message to
5803 * inform the server about options the client wants the server to
5804 * send to the client. A server MAY include an Option Request
5805 * option in a Reconfigure option to indicate which options the
5806 * client should request from the server.
5807 *
5808 * seems to relax the requirement from MUST to MAY (and still other
5809 * language in RFC3315 supports this).
5810 *
5811 * In lieu of a clarification of RFC3315, we will conform with the
5812 * MUST. Instead of an absent ORO, we will if there are no options
5813 * to request supply an empty ORO. Theoretically, an absent ORO is
5814 * difficult to interpret (does the client want all options or no
5815 * options?). A zero-length ORO is intuitively clear: requesting
5816 * nothing.
5817 */
e5d83524
DH
5818 buffer = NULL;
5819 oro_len = 0;
0c20eab3 5820 buflen = 32;
e5d83524 5821 if (!buffer_allocate(&buffer, buflen, MDL))
0c20eab3 5822 log_fatal("Out of memory constructing DHCPv6 ORO.");
0c20eab3
DH
5823 req = client->config->requested_options;
5824 if (req != NULL) {
5825 for (i = 0 ; req[i] != NULL ; i++) {
e5d83524 5826 if (buflen == oro_len) {
0c20eab3
DH
5827 struct buffer *tmpbuf = NULL;
5828
5829 buflen += 32;
5830
5831 /* Shell game. */
e5d83524
DH
5832 buffer_reference(&tmpbuf, buffer, MDL);
5833 buffer_dereference(&buffer, MDL);
0c20eab3 5834
e5d83524 5835 if (!buffer_allocate(&buffer, buflen, MDL))
0c20eab3
DH
5836 log_fatal("Out of memory resizing "
5837 "DHCPv6 ORO buffer.");
5838
e5d83524 5839 memcpy(buffer->data, tmpbuf->data, oro_len);
0c20eab3
DH
5840
5841 buffer_dereference(&tmpbuf, MDL);
5842 }
5843
5844 if (req[i]->universe == &dhcpv6_universe) {
5845 /* Append the code to the ORO. */
e5d83524 5846 putUShort(buffer->data + oro_len,
0c20eab3 5847 req[i]->code);
e5d83524 5848 oro_len += 2;
0c20eab3
DH
5849 }
5850 }
5851 }
5852
5853 oc = NULL;
e5d83524
DH
5854 if (make_const_option_cache(&oc, &buffer, NULL, oro_len,
5855 oro_option, MDL)) {
0c20eab3
DH
5856 save_option(&dhcpv6_universe, *op, oc);
5857 } else {
5858 log_fatal("Unable to create ORO option cache.");
5859 }
5860
e5d83524
DH
5861 /*
5862 * Note: make_const_option_cache() consumes the buffer, we do not
5863 * need to dereference it (XXX).
98bd7ca0 5864 */
e5d83524 5865 option_cache_dereference(&oc, MDL);
98bd7ca0
DH
5866}
5867
5868/* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
5869 * filename, server-name, etc specifics.
5870 *
5871 * Simply, store all values present in all universes of the option state
5872 * (probably derived from a DHCPv6 packet) into environment variables
5873 * named after the option names (and universe names) but with the 'prefix'
5874 * prepended.
5875 *
5876 * Later, dhclient-script may compare for example "new_time_servers" and
5877 * "old_time_servers" for differences, and only upon detecting a change
5878 * bother to rewrite ntp.conf and restart it. Or something along those
5879 * generic lines.
5880 */
5881static void
06eb8bab 5882script_write_params6(struct client_state *client, const char *prefix,
98bd7ca0
DH
5883 struct option_state *options)
5884{
5885 struct envadd_state es;
5886 int i;
5887
5888 if (options == NULL)
5889 return;
5890
5891 es.client = client;
5892 es.prefix = prefix;
5893
5894 for (i = 0 ; i < options->universe_count ; i++) {
5895 option_space_foreach(NULL, NULL, client, NULL, options,
5896 &global_scope, universes[i], &es,
5897 client_option_envadd);
5898 }
5899}
5900
10613724
SR
5901/*
5902 * A clone of the DHCPv4 routine.
5903 * Write out the environment variables for the objects that the
5904 * client requested. If the object was requested the variable will be:
5905 * requested_<option_name>=1
5906 * If it wasn't requested there won't be a variable.
5907 */
5908static void script_write_requested6(client)
5909 struct client_state *client;
5910{
5911 int i;
5912 struct option **req;
5913 char name[256];
5914 req = client->config->requested_options;
5915
5916 if (req == NULL)
5917 return;
5918
5919 for (i = 0 ; req[i] != NULL ; i++) {
5920 if ((req[i]->universe == &dhcpv6_universe) &&
5921 dhcp_option_ev_name (name, sizeof(name), req[i])) {
5922 client_envadd(client, "requested_", name, "%d", 1);
5923 }
5924 }
5925}
5926
420d8b3f
FD
5927/*
5928 * Check if there is something not fully defined in the active lease.
5929 */
5930static isc_boolean_t
5931active_prefix(struct client_state *client)
5932{
5933 struct dhc6_lease *lease;
5934 struct dhc6_ia *ia;
5935 struct dhc6_addr *pref;
5936 char zeros[16];
5937
5938 lease = client->active_lease;
5939 if (lease == NULL)
5940 return ISC_FALSE;
5941 memset(zeros, 0, 16);
5942 for (ia = lease->bindings; ia != NULL; ia = ia->next) {
5943 if (ia->ia_type != D6O_IA_PD)
5944 continue;
5945 for (pref = ia->addrs; pref != NULL; pref = pref->next) {
5946 if (pref->plen == 0)
5947 return ISC_FALSE;
5948 if (pref->address.len != 16)
5949 return ISC_FALSE;
5950 if (memcmp(pref->address.iabuf, zeros, 16) == 0)
5951 return ISC_FALSE;
5952 }
5953 }
5954 return ISC_TRUE;
5955}
0f69ff73
TM
5956
5957/* Adds a leases's declined addreses to the outbound packet
5958 *
5959 * For each IA_NA in the lease that contains one or more declined
5960 * addresses, an IA_NA option with an iasubopt for each declined
5961 * address is added to the outbound packet.
5962 *
5963 * We skip PDs and TAs as declines are undefined for them.
5964 */
5965static isc_result_t
5966dhc6_add_ia_na_decline(struct client_state *client, struct data_string *packet,
5967 struct dhc6_lease *lease) {
5968 struct data_string iads;
5969 struct data_string addrds;
5970 struct dhc6_addr *addr;
5971 struct dhc6_ia *ia;
5972 isc_result_t rval = ISC_R_SUCCESS;
5973
5974 memset(&iads, 0, sizeof(iads));
5975 memset(&addrds, 0, sizeof(addrds));
5976 for (ia = lease->bindings; ia != NULL && rval == ISC_R_SUCCESS;
5977 ia = ia->next) {
5978 if (ia->ia_type != D6O_IA_NA)
5979 continue;
5980
5981 int start_new_ia = 1;
5982 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
5983 /*
5984 * Do not confirm expired addresses, do not request
5985 * expired addresses (but we keep them around for
5986 * solicit).
5987 */
5988 if (!(addr->flags & DHC6_ADDR_DECLINED)) {
5989 continue;
5990 }
5991
5992 if (start_new_ia) {
5993 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
5994 log_error("Unable to allocate memory"
5995 " for IA_NA.");
5996 rval = ISC_R_NOMEMORY;
5997 break;
5998 }
5999
6000 /* Copy the IAID into the packet buffer. */
6001 memcpy(iads.buffer->data, ia->iaid, 4);
6002 iads.data = iads.buffer->data;
6003 iads.len = 12;
6004
6005 /* Set t1/t2 to zero; server will ignore them */
6006 memset(iads.buffer->data + 4, 0, 8);
6007 log_debug("XMT: X-- IA_NA %s",
6008 print_hex_1(4, iads.buffer->data, 55));
6009 start_new_ia = 0;
6010 }
6011
6012 if (addr->address.len != 16) {
6013 log_error("Illegal IPv6 address length (%d), "
6014 "ignoring. (%s:%d)",
6015 addr->address.len, MDL);
6016 continue;
6017 }
6018
6019 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
6020 log_error("Unable to allocate memory for "
6021 "IAADDR.");
6022 rval = ISC_R_NOMEMORY;
6023 break;
6024 }
6025
6026 addrds.data = addrds.buffer->data;
6027 addrds.len = 24;
6028
6029 /* Copy the address into the packet buffer. */
6030 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
6031
6032 /* Preferred and max life are irrelevant */
6033 memset(addrds.buffer->data + 16, 0, 8);
6034 log_debug("XMT: | X-- Decline Address %s",
6035 piaddr(addr->address));
6036
6037 append_option(&iads, &dhcpv6_universe, iaaddr_option,
6038 &addrds);
6039 data_string_forget(&addrds, MDL);
6040 }
6041
6042 /*
6043 * It doesn't make sense to make a request without an
6044 * address.
6045 */
6046 if (ia->addrs == NULL) {
6047 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
6048 rval = ISC_R_FAILURE;
6049 } else if (rval == ISC_R_SUCCESS) {
6050 log_debug("XMT: V IA_NA appended.");
6051 append_option(packet, &dhcpv6_universe, ia_na_option,
6052 &iads);
6053 }
6054
6055 data_string_forget(&iads, MDL);
6056 }
6057
6058 return (rval);
6059}
6060
6061/*
6062 * Remove any declined NA addresses from the lease.
6063 *
6064 * Returns zero if the all of the bindings on the lease
6065 * were removed, non-zero if there are PD, TA, or usuable NA
6066 * bindings
6067 */
6068int drop_declined_addrs(struct dhc6_lease *lease) {
6069 struct dhc6_ia *ia;
6070 int live_cnt = 0;
6071
6072 for (ia = lease->bindings; ia != NULL; ia = ia->next) {
6073 struct dhc6_addr* prev_addr;
6074 struct dhc6_addr* addr;
6075 struct dhc6_addr* next;
6076
6077 /* If it's a PD or TA, we assume it has at least
6078 * one usuable binding */
6079 if (ia->ia_type != D6O_IA_NA) {
6080 live_cnt++;
6081 continue;
6082 }
6083
6084 prev_addr = NULL;
6085 for (addr = ia->addrs ; addr != NULL ; ) {
6086 if (!(addr->flags & DHC6_ADDR_DECLINED)) {
6087 live_cnt++;
6088 addr = addr->next;
6089 prev_addr = addr;
6090 continue;
6091 }
6092
6093 /* If we're deleting head, move it up one */
6094 if (ia->addrs == addr) {
6095 ia->addrs = addr->next;
6096 prev_addr = addr->next;
6097 } else {
6098 prev_addr->next = addr->next;
6099 }
6100
6101 if (addr->options != NULL) {
6102 option_state_dereference(&addr->options, MDL);
6103 }
6104
6105 next = addr->next;
6106 dfree(addr, MDL);
6107 addr = next;
6108 }
6109 }
6110
6111 return (live_cnt);
6112}
6113
f1fc5ede
TM
6114/* Run through the addresses in lease and return true if there's any unexpired.
6115 * Return false otherwise.
6116 */
6117static isc_boolean_t
6118unexpired_address_in_lease(struct dhc6_lease *lease)
6119{
6120 struct dhc6_ia *ia;
6121 struct dhc6_addr *addr;
0f69ff73 6122
f1fc5ede
TM
6123 if (lease == NULL) {
6124 return ISC_FALSE;
6125 }
6126
6127 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
6128 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
6129 if (!(addr->flags & DHC6_ADDR_EXPIRED) &&
6130 (addr->starts + addr->max_life > cur_time)) {
6131 return ISC_TRUE;
6132 }
6133 }
6134 }
6135
6136 log_debug("PRC: Previous lease is devoid of active addresses.");
6137 return ISC_FALSE;
6138}
fe5b0fdd 6139#endif /* DHCPv6 */