~ubuntu-branches/ubuntu/oneiric/isc-dhcp/oneiric-security

« back to all changes in this revision

Viewing changes to server/dhcpv6.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Pollock
  • Date: 2009-09-02 22:34:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090902223425-nypo7bkftxffq41m
Tags: upstream-4.1.0
ImportĀ upstreamĀ versionĀ 4.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2006-2008 by Internet Systems Consortium, Inc. ("ISC")
 
3
 *
 
4
 * Permission to use, copy, modify, and distribute this software for any
 
5
 * purpose with or without fee is hereby granted, provided that the above
 
6
 * copyright notice and this permission notice appear in all copies.
 
7
 *
 
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 
9
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 
10
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 
11
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 
12
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 
13
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
14
 * PERFORMANCE OF THIS SOFTWARE.
 
15
 */
 
16
 
 
17
#include "dhcpd.h"
 
18
 
 
19
#ifdef DHCPv6
 
20
 
 
21
/*
 
22
 * We use print_hex_1() to output DUID values. We could actually output 
 
23
 * the DUID with more information... MAC address if using type 1 or 3, 
 
24
 * and so on. However, RFC 3315 contains Grave Warnings against actually 
 
25
 * attempting to understand a DUID.
 
26
 */
 
27
 
 
28
/* 
 
29
 * TODO: gettext() or other method of localization for the messages
 
30
 *       for status codes (and probably for log formats eventually)
 
31
 * TODO: refactoring (simplify, simplify, simplify)
 
32
 * TODO: support multiple shared_networks on each interface (this 
 
33
 *       will allow the server to issue multiple IPv6 addresses to 
 
34
 *       a single interface)
 
35
 */
 
36
 
 
37
/*
 
38
 * DHCPv6 Reply workflow assist.  A Reply packet is built by various
 
39
 * different functions; this gives us one location where we keep state
 
40
 * regarding a reply.
 
41
 */
 
42
struct reply_state {
 
43
        /* root level persistent state */
 
44
        struct shared_network *shared;
 
45
        struct host_decl *host;
 
46
        struct option_state *opt_state;
 
47
        struct packet *packet;
 
48
        struct data_string client_id;
 
49
 
 
50
        /* IA level persistent state */
 
51
        unsigned ia_count;
 
52
        unsigned pd_count;
 
53
        unsigned client_resources;
 
54
        isc_boolean_t resources_included;
 
55
        isc_boolean_t static_lease;
 
56
        unsigned static_prefixes;
 
57
        struct ia_xx *ia;
 
58
        struct ia_xx *old_ia;
 
59
        struct option_state *reply_ia;
 
60
        struct data_string fixed;
 
61
 
 
62
        /* IAADDR/PREFIX level persistent state */
 
63
        struct iasubopt *lease;
 
64
 
 
65
        /*
 
66
         * "t1", "t2", preferred, and valid lifetimes records for calculating
 
67
         * t1 and t2 (min/max).
 
68
         */
 
69
        u_int32_t renew, rebind, prefer, valid;
 
70
 
 
71
        /* Client-requested valid and preferred lifetimes. */
 
72
        u_int32_t client_valid, client_prefer;
 
73
 
 
74
        /* Chosen values to transmit for valid and preferred lifetimes. */
 
75
        u_int32_t send_valid, send_prefer;
 
76
 
 
77
        /* Preferred prefix length (-1 is any). */
 
78
        int preflen;
 
79
 
 
80
        /* Index into the data field that has been consumed. */
 
81
        unsigned cursor;
 
82
 
 
83
        union reply_buffer {
 
84
                unsigned char data[65536];
 
85
                struct dhcpv6_packet reply;
 
86
        } buf;
 
87
};
 
88
 
 
89
/* 
 
90
 * Prototypes local to this file.
 
91
 */
 
92
static int get_encapsulated_IA_state(struct option_state **enc_opt_state,
 
93
                                     struct data_string *enc_opt_data,
 
94
                                     struct packet *packet,
 
95
                                     struct option_cache *oc,
 
96
                                     int offset);
 
97
static void build_dhcpv6_reply(struct data_string *, struct packet *);
 
98
static isc_result_t shared_network_from_packet6(struct shared_network **shared,
 
99
                                                struct packet *packet);
 
100
static void seek_shared_host(struct host_decl **hp,
 
101
                             struct shared_network *shared);
 
102
static isc_boolean_t fixed_matches_shared(struct host_decl *host,
 
103
                                          struct shared_network *shared);
 
104
static isc_result_t reply_process_ia_na(struct reply_state *reply,
 
105
                                        struct option_cache *ia);
 
106
static isc_result_t reply_process_ia_ta(struct reply_state *reply,
 
107
                                        struct option_cache *ia);
 
108
static isc_result_t reply_process_addr(struct reply_state *reply,
 
109
                                       struct option_cache *addr);
 
110
static isc_boolean_t address_is_owned(struct reply_state *reply,
 
111
                                      struct iaddr *addr);
 
112
static isc_boolean_t temporary_is_available(struct reply_state *reply,
 
113
                                            struct iaddr *addr);
 
114
static isc_result_t find_client_temporaries(struct reply_state *reply);
 
115
static isc_result_t reply_process_try_addr(struct reply_state *reply,
 
116
                                           struct iaddr *addr);
 
117
static isc_result_t find_client_address(struct reply_state *reply);
 
118
static isc_result_t reply_process_is_addressed(struct reply_state *reply,
 
119
                                               struct binding_scope **scope,
 
120
                                               struct group *group);
 
121
static isc_result_t reply_process_send_addr(struct reply_state *reply,
 
122
                                            struct iaddr *addr);
 
123
static struct iasubopt *lease_compare(struct iasubopt *alpha,
 
124
                                      struct iasubopt *beta);
 
125
static isc_result_t reply_process_ia_pd(struct reply_state *reply,
 
126
                                        struct option_cache *ia_pd);
 
127
static isc_result_t reply_process_prefix(struct reply_state *reply,
 
128
                                         struct option_cache *pref);
 
129
static isc_boolean_t prefix_is_owned(struct reply_state *reply,
 
130
                                     struct iaddrcidrnet *pref);
 
131
static isc_result_t find_client_prefix(struct reply_state *reply);
 
132
static isc_result_t reply_process_try_prefix(struct reply_state *reply,
 
133
                                             struct iaddrcidrnet *pref);
 
134
static isc_result_t reply_process_is_prefixed(struct reply_state *reply,
 
135
                                              struct binding_scope **scope,
 
136
                                              struct group *group);
 
137
static isc_result_t reply_process_send_prefix(struct reply_state *reply,
 
138
                                              struct iaddrcidrnet *pref);
 
139
static struct iasubopt *prefix_compare(struct reply_state *reply,
 
140
                                       struct iasubopt *alpha,
 
141
                                       struct iasubopt *beta);
 
142
 
 
143
/*
 
144
 * This function returns the time since DUID time start for the
 
145
 * given time_t value.
 
146
 */
 
147
static u_int32_t
 
148
duid_time(time_t when) {
 
149
        /*
 
150
         * This time is modulo 2^32.
 
151
         */
 
152
        while ((when - DUID_TIME_EPOCH) > 4294967295u) {
 
153
                /* use 2^31 to avoid spurious compiler warnings */
 
154
                when -= 2147483648u;
 
155
                when -= 2147483648u;
 
156
        }
 
157
 
 
158
        return when - DUID_TIME_EPOCH;
 
159
}
 
160
 
 
161
 
 
162
/* 
 
163
 * Server DUID.
 
164
 *
 
165
 * This must remain the same for the lifetime of this server, because
 
166
 * clients return the server DUID that we sent them in Request packets.
 
167
 *
 
168
 * We pick the server DUID like this:
 
169
 *
 
170
 * 1. Check dhcpd.conf - any value the administrator has configured 
 
171
 *    overrides any possible values.
 
172
 * 2. Check the leases.txt - we want to use the previous value if 
 
173
 *    possible.
 
174
 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
 
175
 *    and generate that type.
 
176
 * 4. Generate a type 1 (time + hardware address) DUID.
 
177
 */
 
178
static struct data_string server_duid;
 
179
 
 
180
/*
 
181
 * Check if the server_duid has been set.
 
182
 */
 
183
isc_boolean_t
 
184
server_duid_isset(void) {
 
185
        return (server_duid.data != NULL);
 
186
}
 
187
 
 
188
/*
 
189
 * Return the server_duid.
 
190
 */
 
191
void
 
192
copy_server_duid(struct data_string *ds, const char *file, int line) {
 
193
        data_string_copy(ds, &server_duid, file, line);
 
194
}
 
195
 
 
196
/*
 
197
 * Set the server DUID to a specified value. This is used when
 
198
 * the server DUID is stored in persistent memory (basically the
 
199
 * leases.txt file).
 
200
 */
 
201
void
 
202
set_server_duid(struct data_string *new_duid) {
 
203
        /* INSIST(new_duid != NULL); */
 
204
        /* INSIST(new_duid->data != NULL); */
 
205
 
 
206
        if (server_duid_isset()) {
 
207
                data_string_forget(&server_duid, MDL);
 
208
        }
 
209
        data_string_copy(&server_duid, new_duid, MDL);
 
210
}
 
211
 
 
212
 
 
213
/*
 
214
 * Set the server DUID based on the D6O_SERVERID option. This handles
 
215
 * the case where the administrator explicitly put it in the dhcpd.conf 
 
216
 * file.
 
217
 */
 
218
isc_result_t
 
219
set_server_duid_from_option(void) {
 
220
        struct option_state *opt_state;
 
221
        struct option_cache *oc;
 
222
        struct data_string option_duid;
 
223
        isc_result_t ret_val;
 
224
 
 
225
        opt_state = NULL;
 
226
        if (!option_state_allocate(&opt_state, MDL)) {
 
227
                log_fatal("No memory for server DUID.");
 
228
        }
 
229
 
 
230
        execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
 
231
                                    opt_state, &global_scope, root_group, NULL);
 
232
 
 
233
        oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
 
234
        if (oc == NULL) {
 
235
                ret_val = ISC_R_NOTFOUND;
 
236
        } else {
 
237
                memset(&option_duid, 0, sizeof(option_duid));
 
238
                if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL,
 
239
                                           opt_state, NULL, &global_scope,
 
240
                                           oc, MDL)) {
 
241
                        ret_val = ISC_R_UNEXPECTED;
 
242
                } else {
 
243
                        set_server_duid(&option_duid);
 
244
                        data_string_forget(&option_duid, MDL);
 
245
                        ret_val = ISC_R_SUCCESS;
 
246
                }
 
247
        }
 
248
 
 
249
        option_state_dereference(&opt_state, MDL);
 
250
 
 
251
        return ret_val;
 
252
}
 
253
 
 
254
/*
 
255
 * DUID layout, as defined in RFC 3315, section 9.
 
256
 * 
 
257
 * We support type 1 (hardware address plus time) and type 3 (hardware
 
258
 * address).
 
259
 *
 
260
 * We can support type 2 for specific vendors in the future, if they 
 
261
 * publish the specification. And of course there may be additional
 
262
 * types later.
 
263
 */
 
264
static int server_duid_type = DUID_LLT;
 
265
 
 
266
/* 
 
267
 * Set the DUID type.
 
268
 */
 
269
void
 
270
set_server_duid_type(int type) {
 
271
        server_duid_type = type;
 
272
}
 
273
 
 
274
/*
 
275
 * Generate a new server DUID. This is done if there was no DUID in 
 
276
 * the leases.txt or in the dhcpd.conf file.
 
277
 */
 
278
isc_result_t
 
279
generate_new_server_duid(void) {
 
280
        struct interface_info *p;
 
281
        u_int32_t time_val;
 
282
        struct data_string generated_duid;
 
283
 
 
284
        /*
 
285
         * Verify we have a type that we support.
 
286
         */
 
287
        if ((server_duid_type != DUID_LL) && (server_duid_type != DUID_LLT)) {
 
288
                log_error("Invalid DUID type %d specified, "
 
289
                          "only LL and LLT types supported", server_duid_type);
 
290
                return ISC_R_INVALIDARG;
 
291
        }
 
292
 
 
293
        /*
 
294
         * Find an interface with a hardware address.
 
295
         * Any will do. :)
 
296
         */
 
297
        for (p = interfaces; p != NULL; p = p->next) {
 
298
                if (p->hw_address.hlen > 0) {
 
299
                        break;
 
300
                }
 
301
        }
 
302
        if (p == NULL) {
 
303
                return ISC_R_UNEXPECTED;
 
304
        }
 
305
 
 
306
        /*
 
307
         * Build our DUID.
 
308
         */
 
309
        memset(&generated_duid, 0, sizeof(generated_duid));
 
310
        if (server_duid_type == DUID_LLT) {
 
311
                time_val = duid_time(time(NULL));
 
312
                generated_duid.len = 8 + p->hw_address.hlen - 1;
 
313
                if (!buffer_allocate(&generated_duid.buffer,
 
314
                                     generated_duid.len, MDL)) {
 
315
                        log_fatal("No memory for server DUID.");
 
316
                }
 
317
                generated_duid.data = generated_duid.buffer->data;
 
318
                putUShort(generated_duid.buffer->data, DUID_LLT);
 
319
                putUShort(generated_duid.buffer->data + 2,
 
320
                          p->hw_address.hbuf[0]);
 
321
                putULong(generated_duid.buffer->data + 4, time_val);
 
322
                memcpy(generated_duid.buffer->data + 8,
 
323
                       p->hw_address.hbuf+1, p->hw_address.hlen-1);
 
324
        } else if (server_duid_type == DUID_LL) {
 
325
                generated_duid.len = 4 + p->hw_address.hlen - 1;
 
326
                if (!buffer_allocate(&generated_duid.buffer,
 
327
                                     generated_duid.len, MDL)) {
 
328
                        log_fatal("No memory for server DUID.");
 
329
                }
 
330
                generated_duid.data = generated_duid.buffer->data;
 
331
                putUShort(generated_duid.buffer->data, DUID_LL);
 
332
                putUShort(generated_duid.buffer->data + 2,
 
333
                          p->hw_address.hbuf[0]);
 
334
                memcpy(generated_duid.buffer->data + 4,
 
335
                       p->hw_address.hbuf+1, p->hw_address.hlen-1);
 
336
        } else {
 
337
                log_fatal("Unsupported server DUID type %d.", server_duid_type);
 
338
        }
 
339
 
 
340
        set_server_duid(&generated_duid);
 
341
        data_string_forget(&generated_duid, MDL);
 
342
 
 
343
        return ISC_R_SUCCESS;
 
344
}
 
345
 
 
346
/*
 
347
 * Get the client identifier from the packet.
 
348
 */
 
349
isc_result_t
 
350
get_client_id(struct packet *packet, struct data_string *client_id) {
 
351
        struct option_cache *oc;
 
352
 
 
353
        /*
 
354
         * Verify our client_id structure is empty.
 
355
         */
 
356
        if ((client_id->data != NULL) || (client_id->len != 0)) {
 
357
                return ISC_R_INVALIDARG;
 
358
        }
 
359
 
 
360
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
 
361
        if (oc == NULL) {
 
362
                return ISC_R_NOTFOUND;
 
363
        }
 
364
 
 
365
        if (!evaluate_option_cache(client_id, packet, NULL, NULL,
 
366
                                   packet->options, NULL,
 
367
                                   &global_scope, oc, MDL)) {
 
368
                return ISC_R_FAILURE;
 
369
        }
 
370
 
 
371
        return ISC_R_SUCCESS;
 
372
}
 
373
 
 
374
/*
 
375
 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
 
376
 *
 
377
 *    Servers MUST discard any Solicit messages that do not include a
 
378
 *    Client Identifier option or that do include a Server Identifier
 
379
 *    option.
 
380
 */
 
381
int
 
382
valid_client_msg(struct packet *packet, struct data_string *client_id) {
 
383
        int ret_val;
 
384
        struct option_cache *oc;
 
385
        struct data_string data;
 
386
 
 
387
        ret_val = 0;
 
388
        memset(client_id, 0, sizeof(*client_id));
 
389
        memset(&data, 0, sizeof(data));
 
390
 
 
391
        switch (get_client_id(packet, client_id)) {
 
392
                case ISC_R_SUCCESS:
 
393
                        break;
 
394
                case ISC_R_NOTFOUND:
 
395
                        log_debug("Discarding %s from %s; "
 
396
                                  "client identifier missing",
 
397
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
398
                                  piaddr(packet->client_addr));
 
399
                        goto exit;
 
400
                default:
 
401
                        log_error("Error processing %s from %s; "
 
402
                                  "unable to evaluate Client Identifier",
 
403
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
404
                                  piaddr(packet->client_addr));
 
405
                        goto exit;
 
406
        }
 
407
 
 
408
        /*
 
409
         * Required by RFC 3315, section 15.
 
410
         */
 
411
        if (packet->unicast) {
 
412
                log_debug("Discarding %s from %s; packet sent unicast "
 
413
                          "(CLIENTID %s)",
 
414
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
415
                          piaddr(packet->client_addr),
 
416
                          print_hex_1(client_id->len, client_id->data, 60));
 
417
                goto exit;
 
418
        }
 
419
 
 
420
 
 
421
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
 
422
        if (oc != NULL) {
 
423
                if (evaluate_option_cache(&data, packet, NULL, NULL,
 
424
                                          packet->options, NULL,
 
425
                                          &global_scope, oc, MDL)) {
 
426
                        log_debug("Discarding %s from %s; "
 
427
                                  "server identifier found "
 
428
                                  "(CLIENTID %s, SERVERID %s)",
 
429
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
430
                                  piaddr(packet->client_addr),
 
431
                                  print_hex_1(client_id->len,
 
432
                                              client_id->data, 60),
 
433
                                  print_hex_2(data.len,
 
434
                                              data.data, 60));
 
435
                } else {
 
436
                        log_debug("Discarding %s from %s; "
 
437
                                  "server identifier found "
 
438
                                  "(CLIENTID %s)",
 
439
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
440
                                  print_hex_1(client_id->len,
 
441
                                              client_id->data, 60),
 
442
                                  piaddr(packet->client_addr));
 
443
                }
 
444
                goto exit;
 
445
        }
 
446
 
 
447
        /* looks good */
 
448
        ret_val = 1;
 
449
 
 
450
exit:
 
451
        if (data.len > 0) {
 
452
                data_string_forget(&data, MDL);
 
453
        }
 
454
        if (!ret_val) {
 
455
                if (client_id->len > 0) {
 
456
                        data_string_forget(client_id, MDL);
 
457
                }
 
458
        }
 
459
        return ret_val;
 
460
}
 
461
 
 
462
/*
 
463
 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8, 
 
464
 * 15.9 (slightly different wording, but same meaning):
 
465
 *
 
466
 *   Servers MUST discard any received Request message that meet any of
 
467
 *   the following conditions:
 
468
 *
 
469
 *   -  the message does not include a Server Identifier option.
 
470
 *   -  the contents of the Server Identifier option do not match the
 
471
 *      server's DUID.
 
472
 *   -  the message does not include a Client Identifier option.
 
473
 */
 
474
int
 
475
valid_client_resp(struct packet *packet,
 
476
                  struct data_string *client_id,
 
477
                  struct data_string *server_id)
 
478
{
 
479
        int ret_val;
 
480
        struct option_cache *oc;
 
481
 
 
482
        /* INSIST((duid.data != NULL) && (duid.len > 0)); */
 
483
 
 
484
        ret_val = 0;
 
485
        memset(client_id, 0, sizeof(*client_id));
 
486
        memset(server_id, 0, sizeof(*server_id));
 
487
 
 
488
        switch (get_client_id(packet, client_id)) {
 
489
                case ISC_R_SUCCESS:
 
490
                        break;
 
491
                case ISC_R_NOTFOUND:
 
492
                        log_debug("Discarding %s from %s; "
 
493
                                  "client identifier missing",
 
494
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
495
                                  piaddr(packet->client_addr));
 
496
                        goto exit;
 
497
                default:
 
498
                        log_error("Error processing %s from %s; "
 
499
                                  "unable to evaluate Client Identifier",
 
500
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
501
                                  piaddr(packet->client_addr));
 
502
                        goto exit;
 
503
        }
 
504
 
 
505
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
 
506
        if (oc == NULL) {
 
507
                log_debug("Discarding %s from %s: "
 
508
                          "server identifier missing (CLIENTID %s)",
 
509
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
510
                          piaddr(packet->client_addr),
 
511
                          print_hex_1(client_id->len, client_id->data, 60));
 
512
                goto exit;
 
513
        }
 
514
        if (!evaluate_option_cache(server_id, packet, NULL, NULL,
 
515
                                   packet->options, NULL,
 
516
                                   &global_scope, oc, MDL)) {
 
517
                log_error("Error processing %s from %s; "
 
518
                          "unable to evaluate Server Identifier (CLIENTID %s)",
 
519
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
520
                          piaddr(packet->client_addr),
 
521
                          print_hex_1(client_id->len, client_id->data, 60));
 
522
                goto exit;
 
523
        }
 
524
        if ((server_duid.len != server_id->len) ||
 
525
            (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) {
 
526
                log_debug("Discarding %s from %s; "
 
527
                          "not our server identifier "
 
528
                          "(CLIENTID %s, SERVERID %s, server DUID %s)",
 
529
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
530
                          piaddr(packet->client_addr),
 
531
                          print_hex_1(client_id->len, client_id->data, 60),
 
532
                          print_hex_2(server_id->len, server_id->data, 60),
 
533
                          print_hex_3(server_duid.len, server_duid.data, 60));
 
534
                goto exit;
 
535
        }
 
536
 
 
537
        /* looks good */
 
538
        ret_val = 1;
 
539
 
 
540
exit:
 
541
        if (!ret_val) {
 
542
                if (server_id->len > 0) {
 
543
                        data_string_forget(server_id, MDL);
 
544
                }
 
545
                if (client_id->len > 0) {
 
546
                        data_string_forget(client_id, MDL);
 
547
                }
 
548
        }
 
549
        return ret_val;
 
550
}
 
551
 
 
552
/*
 
553
 * Information request validation, defined in RFC 3315, section 15.12:
 
554
 *
 
555
 *   Servers MUST discard any received Information-request message that
 
556
 *   meets any of the following conditions:
 
557
 *
 
558
 *   -  The message includes a Server Identifier option and the DUID in
 
559
 *      the option does not match the server's DUID.
 
560
 *
 
561
 *   -  The message includes an IA option.
 
562
 */
 
563
int
 
564
valid_client_info_req(struct packet *packet, struct data_string *server_id) {
 
565
        int ret_val;
 
566
        struct option_cache *oc;
 
567
        struct data_string client_id;
 
568
        char client_id_str[80]; /* print_hex_1() uses maximum 60 characters,
 
569
                                   plus a few more for extra information */
 
570
 
 
571
        ret_val = 0;
 
572
        memset(server_id, 0, sizeof(*server_id));
 
573
 
 
574
        /*
 
575
         * Make a string that we can print out to give more 
 
576
         * information about the client if we need to.
 
577
         *
 
578
         * By RFC 3315, Section 18.1.5 clients SHOULD have a 
 
579
         * client-id on an Information-request packet, but it 
 
580
         * is not strictly necessary.
 
581
         */
 
582
        if (get_client_id(packet, &client_id) == ISC_R_SUCCESS) {
 
583
                snprintf(client_id_str, sizeof(client_id_str), " (CLIENTID %s)",
 
584
                         print_hex_1(client_id.len, client_id.data, 60));
 
585
                data_string_forget(&client_id, MDL);
 
586
        } else {
 
587
                client_id_str[0] = '\0';
 
588
        }
 
589
 
 
590
        /*
 
591
         * Required by RFC 3315, section 15.
 
592
         */
 
593
        if (packet->unicast) {
 
594
                log_debug("Discarding %s from %s; packet sent unicast%s",
 
595
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
596
                          piaddr(packet->client_addr), client_id_str);
 
597
                goto exit;
 
598
        }
 
599
 
 
600
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
 
601
        if (oc != NULL) {
 
602
                log_debug("Discarding %s from %s; "
 
603
                          "IA_NA option present%s",
 
604
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
605
                          piaddr(packet->client_addr), client_id_str);
 
606
                goto exit;
 
607
        }
 
608
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
 
609
        if (oc != NULL) {
 
610
                log_debug("Discarding %s from %s; "
 
611
                          "IA_TA option present%s",
 
612
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
613
                          piaddr(packet->client_addr), client_id_str);
 
614
                goto exit;
 
615
        }
 
616
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
 
617
        if (oc != NULL) {
 
618
                log_debug("Discarding %s from %s; "
 
619
                          "IA_PD option present%s",
 
620
                          dhcpv6_type_names[packet->dhcpv6_msg_type],
 
621
                          piaddr(packet->client_addr), client_id_str);
 
622
                goto exit;
 
623
        }
 
624
 
 
625
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
 
626
        if (oc != NULL) {
 
627
                if (!evaluate_option_cache(server_id, packet, NULL, NULL,
 
628
                                           packet->options, NULL,
 
629
                                           &global_scope, oc, MDL)) {
 
630
                        log_error("Error processing %s from %s; "
 
631
                                  "unable to evaluate Server Identifier%s",
 
632
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
633
                                  piaddr(packet->client_addr), client_id_str);
 
634
                        goto exit;
 
635
                }
 
636
                if ((server_duid.len != server_id->len) ||
 
637
                    (memcmp(server_duid.data, server_id->data,
 
638
                            server_duid.len) != 0)) {
 
639
                        log_debug("Discarding %s from %s; "
 
640
                                  "not our server identifier "
 
641
                                  "(SERVERID %s, server DUID %s)%s",
 
642
                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
643
                                  piaddr(packet->client_addr),
 
644
                                  print_hex_1(server_id->len,
 
645
                                              server_id->data, 60),
 
646
                                  print_hex_2(server_duid.len,
 
647
                                              server_duid.data, 60),
 
648
                                  client_id_str);
 
649
                        goto exit;
 
650
                }
 
651
        }
 
652
 
 
653
        /* looks good */
 
654
        ret_val = 1;
 
655
 
 
656
exit:
 
657
        if (!ret_val) {
 
658
                if (server_id->len > 0) {
 
659
                        data_string_forget(server_id, MDL);
 
660
                }
 
661
        }
 
662
        return ret_val;
 
663
}
 
664
 
 
665
/* 
 
666
 * Options that we want to send, in addition to what was requested
 
667
 * via the ORO.
 
668
 */
 
669
static const int required_opts[] = {
 
670
        D6O_CLIENTID,
 
671
        D6O_SERVERID,
 
672
        D6O_STATUS_CODE,
 
673
        D6O_PREFERENCE,
 
674
        0
 
675
};
 
676
static const int required_opts_NAA[] = {
 
677
        D6O_CLIENTID,
 
678
        D6O_SERVERID,
 
679
        D6O_STATUS_CODE,
 
680
        0
 
681
};
 
682
static const int required_opts_solicit[] = {
 
683
        D6O_CLIENTID,
 
684
        D6O_SERVERID,
 
685
        D6O_IA_NA,
 
686
        D6O_IA_TA,
 
687
        D6O_IA_PD,
 
688
        D6O_RAPID_COMMIT,
 
689
        D6O_STATUS_CODE,
 
690
        D6O_RECONF_ACCEPT,
 
691
        D6O_PREFERENCE,
 
692
        0
 
693
};
 
694
static const int required_opts_agent[] = {
 
695
        D6O_INTERFACE_ID,
 
696
        D6O_RELAY_MSG,
 
697
        0
 
698
};
 
699
static const int required_opts_IA[] = {
 
700
        D6O_IAADDR,
 
701
        D6O_STATUS_CODE,
 
702
        0
 
703
};
 
704
static const int required_opts_IA_PD[] = {
 
705
        D6O_IAPREFIX,
 
706
        D6O_STATUS_CODE,
 
707
        0
 
708
};
 
709
static const int required_opts_STATUS_CODE[] = {
 
710
        D6O_STATUS_CODE,
 
711
        0
 
712
};
 
713
 
 
714
/*
 
715
 * Extracts from packet contents an IA_* option, storing the IA structure
 
716
 * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
 
717
 * in enc_opt_state for later lookup and evaluation.  The 'offset' indicates
 
718
 * where in the IA_* the DHCPv6 options commence.
 
719
 */
 
720
static int
 
721
get_encapsulated_IA_state(struct option_state **enc_opt_state,
 
722
                          struct data_string *enc_opt_data,
 
723
                          struct packet *packet,
 
724
                          struct option_cache *oc,
 
725
                          int offset)
 
726
{
 
727
        /* 
 
728
         * Get the raw data for the encapsulated options.
 
729
         */
 
730
        memset(enc_opt_data, 0, sizeof(*enc_opt_data));
 
731
        if (!evaluate_option_cache(enc_opt_data, packet,
 
732
                                   NULL, NULL, packet->options, NULL,
 
733
                                   &global_scope, oc, MDL)) {
 
734
                log_error("get_encapsulated_IA_state: "
 
735
                          "error evaluating raw option.");
 
736
                return 0;
 
737
        }
 
738
        if (enc_opt_data->len < offset) {
 
739
                log_error("get_encapsulated_IA_state: raw option too small.");
 
740
                data_string_forget(enc_opt_data, MDL);
 
741
                return 0;
 
742
        }
 
743
 
 
744
        /*
 
745
         * Now create the option state structure, and pass it to the 
 
746
         * function that parses options.
 
747
         */
 
748
        *enc_opt_state = NULL;
 
749
        if (!option_state_allocate(enc_opt_state, MDL)) {
 
750
                log_error("get_encapsulated_IA_state: no memory for options.");
 
751
                data_string_forget(enc_opt_data, MDL);
 
752
                return 0;
 
753
        }
 
754
        if (!parse_option_buffer(*enc_opt_state,
 
755
                                 enc_opt_data->data + offset, 
 
756
                                 enc_opt_data->len - offset,
 
757
                                 &dhcpv6_universe)) {
 
758
                log_error("get_encapsulated_IA_state: error parsing options.");
 
759
                option_state_dereference(enc_opt_state, MDL);
 
760
                data_string_forget(enc_opt_data, MDL);
 
761
                return 0;
 
762
        }
 
763
 
 
764
        return 1;
 
765
}
 
766
 
 
767
static int
 
768
set_status_code(u_int16_t status_code, const char *status_message,
 
769
                struct option_state *opt_state)
 
770
{
 
771
        struct data_string d;
 
772
        int ret_val;
 
773
 
 
774
        memset(&d, 0, sizeof(d));
 
775
        d.len = sizeof(status_code) + strlen(status_message);
 
776
        if (!buffer_allocate(&d.buffer, d.len, MDL)) {
 
777
                log_fatal("set_status_code: no memory for status code.");
 
778
        }
 
779
        d.data = d.buffer->data;
 
780
        putUShort(d.buffer->data, status_code);
 
781
        memcpy(d.buffer->data + sizeof(status_code), 
 
782
               status_message, d.len - sizeof(status_code));
 
783
        if (!save_option_buffer(&dhcpv6_universe, opt_state, 
 
784
                                d.buffer, (unsigned char *)d.data, d.len, 
 
785
                                D6O_STATUS_CODE, 0)) {
 
786
                log_error("set_status_code: error saving status code.");
 
787
                ret_val = 0;
 
788
        } else {
 
789
                ret_val = 1;
 
790
        }
 
791
        data_string_forget(&d, MDL);
 
792
        return ret_val;
 
793
}
 
794
 
 
795
/*
 
796
 * We have a set of operations we do to set up the reply packet, which
 
797
 * is the same for many message types.
 
798
 */
 
799
static int
 
800
start_reply(struct packet *packet,
 
801
            const struct data_string *client_id, 
 
802
            const struct data_string *server_id,
 
803
            struct option_state **opt_state,
 
804
            struct dhcpv6_packet *reply)
 
805
{
 
806
        struct option_cache *oc;
 
807
        const unsigned char *server_id_data;
 
808
        int server_id_len;
 
809
 
 
810
        /*
 
811
         * Build our option state for reply.
 
812
         */
 
813
        *opt_state = NULL;
 
814
        if (!option_state_allocate(opt_state, MDL)) {
 
815
                log_error("start_reply: no memory for option_state.");
 
816
                return 0;
 
817
        }
 
818
        execute_statements_in_scope(NULL, packet, NULL, NULL,
 
819
                                    packet->options, *opt_state,
 
820
                                    &global_scope, root_group, NULL);
 
821
 
 
822
        /*
 
823
         * A small bit of special handling for Solicit messages.
 
824
         *
 
825
         * We could move the logic into a flag, but for now just check
 
826
         * explicitly.
 
827
         */
 
828
        if (packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
 
829
                reply->msg_type = DHCPV6_ADVERTISE;
 
830
 
 
831
                /*
 
832
                 * If:
 
833
                 * - this message type supports rapid commit (Solicit), and
 
834
                 * - the server is configured to supply a rapid commit, and
 
835
                 * - the client requests a rapid commit,
 
836
                 * Then we add a rapid commit option, and send Reply (instead
 
837
                 * of an Advertise).
 
838
                 */
 
839
                oc = lookup_option(&dhcpv6_universe,
 
840
                                   *opt_state, D6O_RAPID_COMMIT);
 
841
                if (oc != NULL) {
 
842
                        oc = lookup_option(&dhcpv6_universe,
 
843
                                           packet->options, D6O_RAPID_COMMIT);
 
844
                        if (oc != NULL) {
 
845
                                /* Rapid-commit in action. */
 
846
                                reply->msg_type = DHCPV6_REPLY;
 
847
                        } else {
 
848
                                /* Don't want a rapid-commit in advertise. */
 
849
                                delete_option(&dhcpv6_universe,
 
850
                                              *opt_state, D6O_RAPID_COMMIT);
 
851
                        }
 
852
                }
 
853
        } else {
 
854
                reply->msg_type = DHCPV6_REPLY;
 
855
                /* Delete the rapid-commit from the sent options. */
 
856
                oc = lookup_option(&dhcpv6_universe,
 
857
                                   *opt_state, D6O_RAPID_COMMIT);
 
858
                if (oc != NULL) {
 
859
                        delete_option(&dhcpv6_universe,
 
860
                                      *opt_state, D6O_RAPID_COMMIT);
 
861
                }
 
862
        }
 
863
 
 
864
        /* 
 
865
         * Use the client's transaction identifier for the reply.
 
866
         */
 
867
        memcpy(reply->transaction_id, packet->dhcpv6_transaction_id, 
 
868
               sizeof(reply->transaction_id));
 
869
 
 
870
        /* 
 
871
         * RFC 3315, section 18.2 says we need server identifier and
 
872
         * client identifier.
 
873
         *
 
874
         * If the server ID is defined via the configuration file, then
 
875
         * it will already be present in the option state at this point, 
 
876
         * so we don't need to set it.
 
877
         *
 
878
         * If we have a server ID passed in from the caller, 
 
879
         * use that, otherwise use the global DUID.
 
880
         */
 
881
        oc = lookup_option(&dhcpv6_universe, *opt_state, D6O_SERVERID);
 
882
        if (oc == NULL) {
 
883
                if (server_id == NULL) {
 
884
                        server_id_data = server_duid.data;
 
885
                        server_id_len = server_duid.len;
 
886
                } else {
 
887
                        server_id_data = server_id->data;
 
888
                        server_id_len = server_id->len;
 
889
                }
 
890
                if (!save_option_buffer(&dhcpv6_universe, *opt_state, 
 
891
                                        NULL, (unsigned char *)server_id_data,
 
892
                                        server_id_len, D6O_SERVERID, 0)) {
 
893
                                log_error("start_reply: "
 
894
                                          "error saving server identifier.");
 
895
                                return 0;
 
896
                }
 
897
        }
 
898
 
 
899
        if (client_id->buffer != NULL) {
 
900
                if (!save_option_buffer(&dhcpv6_universe, *opt_state, 
 
901
                                        client_id->buffer, 
 
902
                                        (unsigned char *)client_id->data, 
 
903
                                        client_id->len, 
 
904
                                        D6O_CLIENTID, 0)) {
 
905
                        log_error("start_reply: error saving "
 
906
                                  "client identifier.");
 
907
                        return 0;
 
908
                }
 
909
        }
 
910
 
 
911
        /*
 
912
         * If the client accepts reconfiguration, let it know that we
 
913
         * will send them.
 
914
         *
 
915
         * Note: we don't actually do this yet, but DOCSIS requires we
 
916
         *       claim to.
 
917
         */
 
918
        oc = lookup_option(&dhcpv6_universe, packet->options,
 
919
                           D6O_RECONF_ACCEPT);
 
920
        if (oc != NULL) {
 
921
                if (!save_option_buffer(&dhcpv6_universe, *opt_state,
 
922
                                        NULL, (unsigned char *)"", 0, 
 
923
                                        D6O_RECONF_ACCEPT, 0)) {
 
924
                        log_error("start_reply: "
 
925
                                  "error saving RECONF_ACCEPT option.");
 
926
                        option_state_dereference(opt_state, MDL);
 
927
                        return 0;
 
928
                }
 
929
        }
 
930
 
 
931
        return 1;
 
932
}
 
933
 
 
934
/*
 
935
 * Try to get the IPv6 address the client asked for from the
 
936
 * pool.
 
937
 *
 
938
 * addr is the result (should be a pointer to NULL on entry)
 
939
 * pool is the pool to search in
 
940
 * requested_addr is the address the client wants
 
941
 */
 
942
static isc_result_t
 
943
try_client_v6_address(struct iasubopt **addr,
 
944
                      struct ipv6_pool *pool,
 
945
                      const struct data_string *requested_addr)
 
946
{
 
947
        struct in6_addr tmp_addr;
 
948
        isc_result_t result;
 
949
 
 
950
        if (requested_addr->len < sizeof(tmp_addr)) {
 
951
                return ISC_R_INVALIDARG;
 
952
        }
 
953
        memcpy(&tmp_addr, requested_addr->data, sizeof(tmp_addr));
 
954
        if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
 
955
                return ISC_R_FAILURE;
 
956
        }
 
957
 
 
958
        if (!ipv6_in_pool(&tmp_addr, pool)) {
 
959
                return ISC_R_FAILURE;
 
960
        }
 
961
 
 
962
        if (lease6_exists(pool, &tmp_addr)) {
 
963
                return ISC_R_ADDRINUSE;
 
964
        }
 
965
 
 
966
        result = iasubopt_allocate(addr, MDL);
 
967
        if (result != ISC_R_SUCCESS) {
 
968
                return result;
 
969
        }
 
970
        (*addr)->addr = tmp_addr;
 
971
        (*addr)->plen = 0;
 
972
 
 
973
        /* Default is soft binding for 2 minutes. */
 
974
        result = add_lease6(pool, *addr, cur_time + 120);
 
975
        if (result != ISC_R_SUCCESS) {
 
976
                iasubopt_dereference(addr, MDL);
 
977
        }
 
978
        return result;
 
979
}
 
980
 
 
981
/*
 
982
 * Get an IPv6 address for the client.
 
983
 *
 
984
 * addr is the result (should be a pointer to NULL on entry)
 
985
 * packet is the information about the packet from the client
 
986
 * requested_iaaddr is a hint from the client
 
987
 * client_id is the DUID for the client
 
988
 */
 
989
static isc_result_t 
 
990
pick_v6_address(struct iasubopt **addr, struct shared_network *shared_network,
 
991
                const struct data_string *client_id)
 
992
{
 
993
        struct ipv6_pool *p;
 
994
        int i;
 
995
        int start_pool;
 
996
        unsigned int attempts;
 
997
        char tmp_buf[INET6_ADDRSTRLEN];
 
998
 
 
999
        /*
 
1000
         * No address pools, we're done.
 
1001
         */
 
1002
        if (shared_network->ipv6_pools == NULL) {
 
1003
                log_debug("Unable to pick client address: "
 
1004
                          "no IPv6 pools on this shared network");
 
1005
                return ISC_R_NORESOURCES;
 
1006
        }
 
1007
        for (i = 0;; i++) {
 
1008
                p = shared_network->ipv6_pools[i];
 
1009
                if (p == NULL) {
 
1010
                        log_debug("Unable to pick client address: "
 
1011
                                  "no IPv6 address pools "
 
1012
                                  "on this shared network");
 
1013
                        return ISC_R_NORESOURCES;
 
1014
                }
 
1015
                if (p->pool_type == D6O_IA_NA) {
 
1016
                        break;
 
1017
                }
 
1018
        }
 
1019
 
 
1020
        /*
 
1021
         * Otherwise try to get a lease from the first subnet possible.
 
1022
         *
 
1023
         * We start looking at the last pool we allocated from, unless
 
1024
         * it had a collision trying to allocate an address. This will
 
1025
         * tend to move us into less-filled pools.
 
1026
         */
 
1027
        start_pool = shared_network->last_ipv6_pool;
 
1028
        i = start_pool;
 
1029
        do {
 
1030
 
 
1031
                p = shared_network->ipv6_pools[i];
 
1032
                if ((p->pool_type == D6O_IA_NA) &&
 
1033
                    (create_lease6(p, addr, &attempts, client_id,
 
1034
                                   cur_time + 120) == ISC_R_SUCCESS)) {
 
1035
                        /*
 
1036
                         * Record the pool used (or next one if there 
 
1037
                         * was a collision).
 
1038
                         */
 
1039
                        if (attempts > 1) {
 
1040
                                i++;
 
1041
                                if (shared_network->ipv6_pools[i] == NULL) {
 
1042
                                        i = 0;
 
1043
                                }
 
1044
                        }
 
1045
                        shared_network->last_ipv6_pool = i;
 
1046
 
 
1047
                        log_debug("Picking pool address %s",
 
1048
                                  inet_ntop(AF_INET6, &((*addr)->addr),
 
1049
                                            tmp_buf, sizeof(tmp_buf)));
 
1050
                        return ISC_R_SUCCESS;
 
1051
                }
 
1052
 
 
1053
                i++;
 
1054
                if (shared_network->ipv6_pools[i] == NULL) {
 
1055
                        i = 0;
 
1056
                }
 
1057
        } while (i != start_pool);
 
1058
 
 
1059
        /*
 
1060
         * If we failed to pick an IPv6 address from any of the subnets.
 
1061
         * Presumably that means we have no addresses for the client.
 
1062
         */
 
1063
        log_debug("Unable to pick client address: no addresses available");
 
1064
        return ISC_R_NORESOURCES;
 
1065
}
 
1066
 
 
1067
/*
 
1068
 * Try to get the IPv6 prefix the client asked for from the
 
1069
 * prefix pool.
 
1070
 *
 
1071
 * pref is the result (should be a pointer to NULL on entry)
 
1072
 * pool is the prefix pool to search in
 
1073
 * requested_pref is the address the client wants
 
1074
 */
 
1075
static isc_result_t
 
1076
try_client_v6_prefix(struct iasubopt **pref,
 
1077
                     struct ipv6_pool *pool,
 
1078
                     const struct data_string *requested_pref)
 
1079
{
 
1080
        u_int8_t tmp_plen;
 
1081
        struct in6_addr tmp_pref;
 
1082
        struct iaddr ia;
 
1083
        isc_result_t result;
 
1084
 
 
1085
        if (requested_pref->len < sizeof(tmp_plen) + sizeof(tmp_pref)) {
 
1086
                return ISC_R_INVALIDARG;
 
1087
        }
 
1088
        tmp_plen = (int) requested_pref->data[0];
 
1089
        if ((tmp_plen < 3) || (tmp_plen > 128)) {
 
1090
                return ISC_R_FAILURE;
 
1091
        }
 
1092
        memcpy(&tmp_pref, requested_pref->data + 1, sizeof(tmp_pref));
 
1093
        if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
 
1094
                return ISC_R_FAILURE;
 
1095
        }
 
1096
        ia.len = 16;
 
1097
        memcpy(&ia.iabuf, &tmp_pref, 16);
 
1098
        if (!is_cidr_mask_valid(&ia, (int) tmp_plen)) {
 
1099
                return ISC_R_FAILURE;
 
1100
        }
 
1101
 
 
1102
        if (((int)tmp_plen != pool->units) ||
 
1103
            !ipv6_in_pool(&tmp_pref, pool)) {
 
1104
                return ISC_R_FAILURE;
 
1105
        }
 
1106
 
 
1107
        if (prefix6_exists(pool, &tmp_pref, tmp_plen)) {
 
1108
                return ISC_R_ADDRINUSE;
 
1109
        }
 
1110
 
 
1111
        result = iasubopt_allocate(pref, MDL);
 
1112
        if (result != ISC_R_SUCCESS) {
 
1113
                return result;
 
1114
        }
 
1115
        (*pref)->addr = tmp_pref;
 
1116
        (*pref)->plen = tmp_plen;
 
1117
 
 
1118
        /* Default is soft binding for 2 minutes. */
 
1119
        result = add_lease6(pool, *pref, cur_time + 120);
 
1120
        if (result != ISC_R_SUCCESS) {
 
1121
                iasubopt_dereference(pref, MDL);
 
1122
        }
 
1123
        return result;
 
1124
}
 
1125
 
 
1126
/*
 
1127
 * Get an IPv6 prefix for the client.
 
1128
 *
 
1129
 * pref is the result (should be a pointer to NULL on entry)
 
1130
 * packet is the information about the packet from the client
 
1131
 * requested_iaprefix is a hint from the client
 
1132
 * plen is -1 or the requested prefix length
 
1133
 * client_id is the DUID for the client
 
1134
 */
 
1135
static isc_result_t 
 
1136
pick_v6_prefix(struct iasubopt **pref, int plen,
 
1137
               struct shared_network *shared_network,
 
1138
               const struct data_string *client_id)
 
1139
{
 
1140
        struct ipv6_pool *p;
 
1141
        int i;
 
1142
        unsigned int attempts;
 
1143
        char tmp_buf[INET6_ADDRSTRLEN];
 
1144
 
 
1145
        /*
 
1146
         * No prefix pools, we're done.
 
1147
         */
 
1148
        if (shared_network->ipv6_pools == NULL) {
 
1149
                log_debug("Unable to pick client prefix: "
 
1150
                          "no IPv6 pools on this shared network");
 
1151
                return ISC_R_NORESOURCES;
 
1152
        }
 
1153
        for (i = 0;; i++) {
 
1154
                p = shared_network->ipv6_pools[i];
 
1155
                if (p == NULL) {
 
1156
                        log_debug("Unable to pick client prefix: "
 
1157
                                  "no IPv6 prefix pools "
 
1158
                                  "on this shared network");
 
1159
                        return ISC_R_NORESOURCES;
 
1160
                }
 
1161
                if (p->pool_type == D6O_IA_PD) {
 
1162
                        break;
 
1163
                }
 
1164
        }
 
1165
 
 
1166
        /*
 
1167
         * Otherwise try to get a prefix.
 
1168
         */
 
1169
        for (i = 0;; i++) {
 
1170
                p = shared_network->ipv6_pools[i];
 
1171
                if (p == NULL) {
 
1172
                        break;
 
1173
                }
 
1174
                if (p->pool_type != D6O_IA_PD) {
 
1175
                        continue;
 
1176
                }
 
1177
 
 
1178
                /*
 
1179
                 * Try only pools with the requested prefix length if any.
 
1180
                 */
 
1181
                if ((plen >= 0) && (p->units != plen)) {
 
1182
                        continue;
 
1183
                }
 
1184
 
 
1185
                if (create_prefix6(p, pref, &attempts, client_id,
 
1186
                                   cur_time + 120) == ISC_R_SUCCESS) {
 
1187
                        log_debug("Picking pool prefix %s/%u",
 
1188
                                  inet_ntop(AF_INET6, &((*pref)->addr),
 
1189
                                            tmp_buf, sizeof(tmp_buf)),
 
1190
                                  (unsigned) (*pref)->plen);
 
1191
                        return ISC_R_SUCCESS;
 
1192
                }
 
1193
        }
 
1194
 
 
1195
        /*
 
1196
         * If we failed to pick an IPv6 prefix
 
1197
         * Presumably that means we have no prefixes for the client.
 
1198
         */
 
1199
        log_debug("Unable to pick client prefix: no prefixes available");
 
1200
        return ISC_R_NORESOURCES;
 
1201
}
 
1202
 
 
1203
/*
 
1204
 * lease_to_client() is called from several messages to construct a
 
1205
 * reply that contains all that we know about the client's correct lease
 
1206
 * (or projected lease).
 
1207
 *
 
1208
 * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
 
1209
 *           send what we "may" give them on a request.
 
1210
 *
 
1211
 * Request - "Hard" binding, but ignore supplied addresses (just provide what
 
1212
 *           the client should really use).
 
1213
 *
 
1214
 * Renew   - "Hard" binding, but client-supplied addresses are 'real'.  Error
 
1215
 * Rebind    out any "wrong" addresses the client sends.  This means we send
 
1216
 *           an empty IA_NA with a status code of NoBinding or NotOnLink or
 
1217
 *           possibly send the address with zeroed lifetimes.
 
1218
 *
 
1219
 * Information-Request - No binding.
 
1220
 *
 
1221
 * The basic structure is to traverse the client-supplied data first, and
 
1222
 * validate and echo back any contents that can be.  If the client-supplied
 
1223
 * data does not error out (on renew/rebind as above), but we did not send
 
1224
 * any addresses, attempt to allocate one.
 
1225
 */
 
1226
/* TODO: look at client hints for lease times */
 
1227
static void
 
1228
lease_to_client(struct data_string *reply_ret,
 
1229
                struct packet *packet, 
 
1230
                const struct data_string *client_id,
 
1231
                const struct data_string *server_id)
 
1232
{
 
1233
        static struct reply_state reply;
 
1234
        struct option_cache *oc;
 
1235
        struct data_string packet_oro;
 
1236
        isc_boolean_t no_resources_avail;
 
1237
 
 
1238
        /* Locate the client.  */
 
1239
        if (shared_network_from_packet6(&reply.shared,
 
1240
                                        packet) != ISC_R_SUCCESS)
 
1241
                goto exit;
 
1242
 
 
1243
        /* 
 
1244
         * Initialize the reply.
 
1245
         */
 
1246
        packet_reference(&reply.packet, packet, MDL);
 
1247
        data_string_copy(&reply.client_id, client_id, MDL);
 
1248
 
 
1249
        if (!start_reply(packet, client_id, server_id, &reply.opt_state,
 
1250
                         &reply.buf.reply))
 
1251
                goto exit;
 
1252
 
 
1253
        /* Set the write cursor to just past the reply header. */
 
1254
        reply.cursor = REPLY_OPTIONS_INDEX;
 
1255
 
 
1256
        /*
 
1257
         * Get the ORO from the packet, if any.
 
1258
         */
 
1259
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ORO);
 
1260
        memset(&packet_oro, 0, sizeof(packet_oro));
 
1261
        if (oc != NULL) {
 
1262
                if (!evaluate_option_cache(&packet_oro, packet, 
 
1263
                                           NULL, NULL, 
 
1264
                                           packet->options, NULL,
 
1265
                                           &global_scope, oc, MDL)) {
 
1266
                        log_error("lease_to_client: error evaluating ORO.");
 
1267
                        goto exit;
 
1268
                }
 
1269
        }
 
1270
 
 
1271
        /* 
 
1272
         * Find a host record that matches from the packet, if any, and is
 
1273
         * valid for the shared network the client is on.
 
1274
         */
 
1275
        if (find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
 
1276
                seek_shared_host(&reply.host, reply.shared);
 
1277
        }
 
1278
 
 
1279
        if ((reply.host == NULL) &&
 
1280
            find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
 
1281
                              MDL)) {
 
1282
                seek_shared_host(&reply.host, reply.shared);
 
1283
        }
 
1284
 
 
1285
        /* Process the client supplied IA's onto the reply buffer. */
 
1286
        reply.ia_count = 0;
 
1287
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
 
1288
        no_resources_avail = ISC_FALSE;
 
1289
        for (; oc != NULL ; oc = oc->next) {
 
1290
                isc_result_t status;
 
1291
 
 
1292
                /* Start counting resources (addresses) offered. */
 
1293
                reply.client_resources = 0;
 
1294
                reply.resources_included = ISC_FALSE;
 
1295
 
 
1296
                status = reply_process_ia_na(&reply, oc);
 
1297
 
 
1298
                /*
 
1299
                 * We continue to try other IA's whether we can address
 
1300
                 * this one or not.  Any other result is an immediate fail.
 
1301
                 */
 
1302
                if ((status != ISC_R_SUCCESS) &&
 
1303
                    (status != ISC_R_NORESOURCES))
 
1304
                        goto exit;
 
1305
 
 
1306
                /*
 
1307
                 * If any address cannot be given to any IA, then set the
 
1308
                 * NoAddrsAvail status code.
 
1309
                 */
 
1310
                if (reply.client_resources == 0)
 
1311
                        no_resources_avail = ISC_TRUE;
 
1312
        }
 
1313
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
 
1314
        for (; oc != NULL ; oc = oc->next) {
 
1315
                isc_result_t status;
 
1316
 
 
1317
                /* Start counting resources (addresses) offered. */
 
1318
                reply.client_resources = 0;
 
1319
                reply.resources_included = ISC_FALSE;
 
1320
 
 
1321
                status = reply_process_ia_ta(&reply, oc);
 
1322
 
 
1323
                /*
 
1324
                 * We continue to try other IA's whether we can address
 
1325
                 * this one or not.  Any other result is an immediate fail.
 
1326
                 */
 
1327
                if ((status != ISC_R_SUCCESS) &&
 
1328
                    (status != ISC_R_NORESOURCES))
 
1329
                        goto exit;
 
1330
 
 
1331
                /*
 
1332
                 * If any address cannot be given to any IA, then set the
 
1333
                 * NoAddrsAvail status code.
 
1334
                 */
 
1335
                if (reply.client_resources == 0)
 
1336
                        no_resources_avail = ISC_TRUE;
 
1337
        }
 
1338
 
 
1339
        /* Same for IA_PD's. */
 
1340
        reply.pd_count = 0;
 
1341
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
 
1342
        for (; oc != NULL ; oc = oc->next) {
 
1343
                isc_result_t status;
 
1344
 
 
1345
                /* Start counting resources (prefixes) offered. */
 
1346
                reply.client_resources = 0;
 
1347
                reply.resources_included = ISC_FALSE;
 
1348
 
 
1349
                status = reply_process_ia_pd(&reply, oc);
 
1350
 
 
1351
                /*
 
1352
                 * We continue to try other IA_PD's whether we can address
 
1353
                 * this one or not.  Any other result is an immediate fail.
 
1354
                 */
 
1355
                if ((status != ISC_R_SUCCESS) &&
 
1356
                    (status != ISC_R_NORESOURCES))
 
1357
                        goto exit;
 
1358
 
 
1359
                /*
 
1360
                 * If any prefix cannot be given to any IA_PD, then
 
1361
                 * set the NoPrefixAvail status code.
 
1362
                 */
 
1363
                if (reply.client_resources == 0)
 
1364
                        no_resources_avail = ISC_TRUE;
 
1365
        }
 
1366
 
 
1367
        /*
 
1368
         * Make no reply if we gave no resources and is not
 
1369
         * for Information-Request.
 
1370
         */
 
1371
        if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
 
1372
                if (reply.packet->dhcpv6_msg_type !=
 
1373
                                            DHCPV6_INFORMATION_REQUEST)
 
1374
                        goto exit;
 
1375
 
 
1376
                /*
 
1377
                 * Because we only execute statements on a per-IA basis,
 
1378
                 * we need to execute statements in any non-IA reply to
 
1379
                 * source configuration.
 
1380
                 */
 
1381
                execute_statements_in_scope(NULL, reply.packet, NULL, NULL,
 
1382
                                            reply.packet->options,
 
1383
                                            reply.opt_state, &global_scope,
 
1384
                                            reply.shared->group, root_group);
 
1385
        }
 
1386
 
 
1387
        /*
 
1388
         * RFC3315 section 17.2.2 (Solicit):
 
1389
         *
 
1390
         * If the server will not assign any addresses to any IAs in a
 
1391
         * subsequent Request from the client, the server MUST send an
 
1392
         * Advertise message to the client that includes only a Status
 
1393
         * Code option with code NoAddrsAvail and a status message for
 
1394
         * the user, a Server Identifier option with the server's DUID,
 
1395
         * and a Client Identifier option with the client's DUID.
 
1396
         *
 
1397
         * Section 18.2.1 (Request):
 
1398
         *
 
1399
         * If the server cannot assign any addresses to an IA in the
 
1400
         * message from the client, the server MUST include the IA in
 
1401
         * the Reply message with no addresses in the IA and a Status
 
1402
         * Code option in the IA containing status code NoAddrsAvail.
 
1403
         *
 
1404
         * Section 18.1.8 (Client Behavior):
 
1405
         *
 
1406
         * Leave unchanged any information about addresses the client has
 
1407
         * recorded in the IA but that were not included in the IA from
 
1408
         * the server.
 
1409
         * Sends a Renew/Rebind if the IA is not in the Reply message.
 
1410
         */
 
1411
        if (no_resources_avail && (reply.ia_count != 0) &&
 
1412
            (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
 
1413
        {
 
1414
                /* Set the NoAddrsAvail status code. */
 
1415
                if (!set_status_code(STATUS_NoAddrsAvail,
 
1416
                                     "No addresses available for this "
 
1417
                                     "interface.", reply.opt_state)) {
 
1418
                        log_error("lease_to_client: Unable to set "
 
1419
                                  "NoAddrsAvail status code.");
 
1420
                        goto exit;
 
1421
                }
 
1422
 
 
1423
                /* Rewind the cursor to the start. */
 
1424
                reply.cursor = REPLY_OPTIONS_INDEX;
 
1425
 
 
1426
                /*
 
1427
                 * Produce an advertise that includes only:
 
1428
                 *
 
1429
                 * Status code.
 
1430
                 * Server DUID.
 
1431
                 * Client DUID.
 
1432
                 */
 
1433
                reply.buf.reply.msg_type = DHCPV6_ADVERTISE;
 
1434
                reply.cursor += store_options6((char *)reply.buf.data +
 
1435
                                                        reply.cursor,
 
1436
                                               sizeof(reply.buf) -
 
1437
                                                        reply.cursor,
 
1438
                                               reply.opt_state, reply.packet,
 
1439
                                               required_opts_NAA,
 
1440
                                               NULL);
 
1441
        } else if (no_resources_avail && (reply.ia_count == 0) &&
 
1442
                   (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
 
1443
        {
 
1444
                /* Set the NoPrefixAvail status code. */
 
1445
                if (!set_status_code(STATUS_NoPrefixAvail,
 
1446
                                     "No prefixes available for this "
 
1447
                                     "interface.", reply.opt_state)) {
 
1448
                        log_error("lease_to_client: Unable to set "
 
1449
                                  "NoPrefixAvail status code.");
 
1450
                        goto exit;
 
1451
                }
 
1452
 
 
1453
                /* Rewind the cursor to the start. */
 
1454
                reply.cursor = REPLY_OPTIONS_INDEX;
 
1455
 
 
1456
                /*
 
1457
                 * Produce an advertise that includes only:
 
1458
                 *
 
1459
                 * Status code.
 
1460
                 * Server DUID.
 
1461
                 * Client DUID.
 
1462
                 */
 
1463
                reply.buf.reply.msg_type = DHCPV6_ADVERTISE;
 
1464
                reply.cursor += store_options6((char *)reply.buf.data +
 
1465
                                                        reply.cursor,
 
1466
                                               sizeof(reply.buf) -
 
1467
                                                        reply.cursor,
 
1468
                                               reply.opt_state, reply.packet,
 
1469
                                               required_opts_NAA,
 
1470
                                               NULL);
 
1471
        } else {
 
1472
                /*
 
1473
                 * Having stored the client's IA's, store any options that
 
1474
                 * will fit in the remaining space.
 
1475
                 */
 
1476
                reply.cursor += store_options6((char *)reply.buf.data +
 
1477
                                                        reply.cursor,
 
1478
                                               sizeof(reply.buf) -
 
1479
                                                        reply.cursor,
 
1480
                                               reply.opt_state, reply.packet,
 
1481
                                               required_opts_solicit,
 
1482
                                               &packet_oro);
 
1483
        }
 
1484
 
 
1485
        /* Return our reply to the caller. */
 
1486
        reply_ret->len = reply.cursor;
 
1487
        reply_ret->buffer = NULL;
 
1488
        if (!buffer_allocate(&reply_ret->buffer, reply.cursor, MDL)) {
 
1489
                log_fatal("No memory to store Reply.");
 
1490
        }
 
1491
        memcpy(reply_ret->buffer->data, reply.buf.data, reply.cursor);
 
1492
        reply_ret->data = reply_ret->buffer->data;
 
1493
 
 
1494
      exit:
 
1495
        /* Cleanup. */
 
1496
        if (reply.shared != NULL)
 
1497
                shared_network_dereference(&reply.shared, MDL);
 
1498
        if (reply.host != NULL)
 
1499
                host_dereference(&reply.host, MDL);
 
1500
        if (reply.opt_state != NULL)
 
1501
                option_state_dereference(&reply.opt_state, MDL);
 
1502
        if (reply.packet != NULL)
 
1503
                packet_dereference(&reply.packet, MDL);
 
1504
        if (reply.client_id.data != NULL)
 
1505
                data_string_forget(&reply.client_id, MDL);
 
1506
        reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
 
1507
        reply.cursor = 0;
 
1508
}
 
1509
 
 
1510
/* Process a client-supplied IA_NA.  This may append options to the tail of
 
1511
 * the reply packet being built in the reply_state structure.
 
1512
 */
 
1513
static isc_result_t
 
1514
reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
 
1515
        isc_result_t status = ISC_R_SUCCESS;
 
1516
        u_int32_t iaid;
 
1517
        unsigned ia_cursor;
 
1518
        struct option_state *packet_ia;
 
1519
        struct option_cache *oc;
 
1520
        struct data_string ia_data, data;
 
1521
 
 
1522
        /* Initialize values that will get cleaned up on return. */
 
1523
        packet_ia = NULL;
 
1524
        memset(&ia_data, 0, sizeof(ia_data));
 
1525
        memset(&data, 0, sizeof(data));
 
1526
        /* 
 
1527
         * Note that find_client_address() may set reply->lease. 
 
1528
         */
 
1529
 
 
1530
        /* Make sure there is at least room for the header. */
 
1531
        if ((reply->cursor + IA_NA_OFFSET + 4) > sizeof(reply->buf)) {
 
1532
                log_error("reply_process_ia_na: Reply too long for IA.");
 
1533
                return ISC_R_NOSPACE;
 
1534
        }
 
1535
 
 
1536
 
 
1537
        /* Fetch the IA_NA contents. */
 
1538
        if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
 
1539
                                       ia, IA_NA_OFFSET)) {
 
1540
                log_error("reply_process_ia_na: error evaluating ia");
 
1541
                status = ISC_R_FAILURE;
 
1542
                goto cleanup;
 
1543
        }
 
1544
 
 
1545
        /* Extract IA_NA header contents. */
 
1546
        iaid = getULong(ia_data.data);
 
1547
        reply->renew = getULong(ia_data.data + 4);
 
1548
        reply->rebind = getULong(ia_data.data + 8);
 
1549
 
 
1550
        /* Create an IA_NA structure. */
 
1551
        if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
 
1552
                        reply->client_id.len, MDL) != ISC_R_SUCCESS) {
 
1553
                log_error("reply_process_ia_na: no memory for ia.");
 
1554
                status = ISC_R_NOMEMORY;
 
1555
                goto cleanup;
 
1556
        }
 
1557
        reply->ia->ia_type = D6O_IA_NA;
 
1558
 
 
1559
        /* Cache pre-existing IA, if any. */
 
1560
        ia_hash_lookup(&reply->old_ia, ia_na_active,
 
1561
                       (unsigned char *)reply->ia->iaid_duid.data,
 
1562
                       reply->ia->iaid_duid.len, MDL);
 
1563
 
 
1564
        /*
 
1565
         * Create an option cache to carry the IA_NA option contents, and
 
1566
         * execute any user-supplied values into it.
 
1567
         */
 
1568
        if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
1569
                status = ISC_R_NOMEMORY;
 
1570
                goto cleanup;
 
1571
        }
 
1572
 
 
1573
        /* Check & cache the fixed host record. */
 
1574
        if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
 
1575
                if (!evaluate_option_cache(&reply->fixed, NULL, NULL, NULL,
 
1576
                                           NULL, NULL, &global_scope,
 
1577
                                           reply->host->fixed_addr, MDL)) {
 
1578
                        log_error("reply_process_ia_na: unable to evaluate "
 
1579
                                  "fixed address.");
 
1580
                        status = ISC_R_FAILURE;
 
1581
                        goto cleanup;
 
1582
                }
 
1583
 
 
1584
                if (reply->fixed.len < 16) {
 
1585
                        log_error("reply_process_ia_na: invalid fixed address.");
 
1586
                        status = ISC_R_INVALIDARG;
 
1587
                        goto cleanup;
 
1588
                }
 
1589
 
 
1590
                reply->static_lease = ISC_TRUE;
 
1591
        } else
 
1592
                reply->static_lease = ISC_FALSE;
 
1593
 
 
1594
        /*
 
1595
         * Save the cursor position at the start of the IA, so we can
 
1596
         * set length and adjust t1/t2 values later.  We write a temporary
 
1597
         * header out now just in case we decide to adjust the packet
 
1598
         * within sub-process functions.
 
1599
         */
 
1600
        ia_cursor = reply->cursor;
 
1601
 
 
1602
        /* Initialize the IA_NA header.  First the code. */
 
1603
        putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_NA);
 
1604
        reply->cursor += 2;
 
1605
 
 
1606
        /* Then option length. */
 
1607
        putUShort(reply->buf.data + reply->cursor, 0x0Cu);
 
1608
        reply->cursor += 2;
 
1609
 
 
1610
        /* Then IA_NA header contents; IAID. */
 
1611
        putULong(reply->buf.data + reply->cursor, iaid);
 
1612
        reply->cursor += 4;
 
1613
 
 
1614
        /* We store the client's t1 for now, and may over-ride it later. */
 
1615
        putULong(reply->buf.data + reply->cursor, reply->renew);
 
1616
        reply->cursor += 4;
 
1617
 
 
1618
        /* We store the client's t2 for now, and may over-ride it later. */
 
1619
        putULong(reply->buf.data + reply->cursor, reply->rebind);
 
1620
        reply->cursor += 4;
 
1621
 
 
1622
        /* 
 
1623
         * For each address in this IA_NA, decide what to do about it.
 
1624
         *
 
1625
         * Guidelines:
 
1626
         *
 
1627
         * The client leaves unchanged any infomation about addresses
 
1628
         * it has recorded but are not included ("cancel/break" below).
 
1629
         * A not included IA ("cleanup" below) could give a Renew/Rebind.
 
1630
         */
 
1631
        oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
 
1632
        reply->valid = reply->prefer = 0xffffffff;
 
1633
        reply->client_valid = reply->client_prefer = 0;
 
1634
        for (; oc != NULL ; oc = oc->next) {
 
1635
                status = reply_process_addr(reply, oc);
 
1636
 
 
1637
                /*
 
1638
                 * Canceled means we did not allocate addresses to the
 
1639
                 * client, but we're "done" with this IA - we set a status
 
1640
                 * code.  So transmit this reply, e.g., move on to the next
 
1641
                 * IA.
 
1642
                 */
 
1643
                if (status == ISC_R_CANCELED)
 
1644
                        break;
 
1645
 
 
1646
                if ((status != ISC_R_SUCCESS) && (status != ISC_R_ADDRINUSE))
 
1647
                        goto cleanup;
 
1648
        }
 
1649
 
 
1650
        reply->ia_count++;
 
1651
 
 
1652
        /*
 
1653
         * If we fell through the above and never gave the client
 
1654
         * an address, give it one now.
 
1655
         */
 
1656
        if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
 
1657
                status = find_client_address(reply);
 
1658
 
 
1659
                if (status == ISC_R_NORESOURCES) {
 
1660
                        switch (reply->packet->dhcpv6_msg_type) {
 
1661
                              case DHCPV6_SOLICIT:
 
1662
                                /*
 
1663
                                 * No address for any IA is handled
 
1664
                                 * by the caller.
 
1665
                                 */
 
1666
                                /* FALL THROUGH */
 
1667
 
 
1668
                              case DHCPV6_REQUEST:
 
1669
                                /* Section 18.2.1 (Request):
 
1670
                                 *
 
1671
                                 * If the server cannot assign any addresses to
 
1672
                                 * an IA in the message from the client, the
 
1673
                                 * server MUST include the IA in the Reply
 
1674
                                 * message with no addresses in the IA and a
 
1675
                                 * Status Code option in the IA containing
 
1676
                                 * status code NoAddrsAvail.
 
1677
                                 */
 
1678
                                option_state_dereference(&reply->reply_ia, MDL);
 
1679
                                if (!option_state_allocate(&reply->reply_ia,
 
1680
                                                           MDL))
 
1681
                                {
 
1682
                                        log_error("reply_process_ia_na: No "
 
1683
                                                  "memory for option state "
 
1684
                                                  "wipe.");
 
1685
                                        status = ISC_R_NOMEMORY;
 
1686
                                        goto cleanup;
 
1687
                                }
 
1688
 
 
1689
                                if (!set_status_code(STATUS_NoAddrsAvail,
 
1690
                                                     "No addresses available "
 
1691
                                                     "for this interface.",
 
1692
                                                      reply->reply_ia)) {
 
1693
                                        log_error("reply_process_ia_na: Unable "
 
1694
                                                  "to set NoAddrsAvail status "
 
1695
                                                  "code.");
 
1696
                                        status = ISC_R_FAILURE;
 
1697
                                        goto cleanup;
 
1698
                                }
 
1699
 
 
1700
                                status = ISC_R_SUCCESS;
 
1701
                                break;
 
1702
 
 
1703
                              default:
 
1704
                                /*
 
1705
                                 * RFC 3315 does not tell us to emit a status
 
1706
                                 * code in this condition, or anything else.
 
1707
                                 *
 
1708
                                 * If we included non-allocated addresses
 
1709
                                 * (zeroed lifetimes) in an IA, then the client
 
1710
                                 * will deconfigure them.
 
1711
                                 *
 
1712
                                 * So we want to include the IA even if we
 
1713
                                 * can't give it a new address if it includes
 
1714
                                 * zeroed lifetime addresses.
 
1715
                                 *
 
1716
                                 * We don't want to include the IA if we
 
1717
                                 * provide zero addresses including zeroed
 
1718
                                 * lifetimes.
 
1719
                                 */
 
1720
                                if (reply->resources_included)
 
1721
                                        status = ISC_R_SUCCESS;
 
1722
                                else
 
1723
                                        goto cleanup;
 
1724
                                break;
 
1725
                        }
 
1726
                }
 
1727
 
 
1728
                if (status != ISC_R_SUCCESS)
 
1729
                        goto cleanup;
 
1730
        }
 
1731
 
 
1732
        reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
 
1733
                                        sizeof(reply->buf) - reply->cursor,
 
1734
                                        reply->reply_ia, reply->packet,
 
1735
                                        required_opts_IA, NULL);
 
1736
 
 
1737
        /* Reset the length of this IA to match what was just written. */
 
1738
        putUShort(reply->buf.data + ia_cursor + 2,
 
1739
                  reply->cursor - (ia_cursor + 4));
 
1740
 
 
1741
        /*
 
1742
         * T1/T2 time selection is kind of weird.  We actually use DHCP
 
1743
         * (v4) scoped options as handy existing places where these might
 
1744
         * be configured by an administrator.  A value of zero tells the
 
1745
         * client it may choose its own renewal time.
 
1746
         */
 
1747
        reply->renew = 0;
 
1748
        oc = lookup_option(&dhcp_universe, reply->opt_state,
 
1749
                           DHO_DHCP_RENEWAL_TIME);
 
1750
        if (oc != NULL) {
 
1751
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
1752
                                           reply->packet->options,
 
1753
                                           reply->opt_state, &global_scope,
 
1754
                                           oc, MDL) ||
 
1755
                    (data.len != 4)) {
 
1756
                        log_error("Invalid renewal time.");
 
1757
                } else {
 
1758
                        reply->renew = getULong(data.data);
 
1759
                }
 
1760
 
 
1761
                if (data.data != NULL)
 
1762
                        data_string_forget(&data, MDL);
 
1763
        }
 
1764
        putULong(reply->buf.data + ia_cursor + 8, reply->renew);
 
1765
 
 
1766
        /* Now T2. */
 
1767
        reply->rebind = 0;
 
1768
        oc = lookup_option(&dhcp_universe, reply->opt_state,
 
1769
                           DHO_DHCP_REBINDING_TIME);
 
1770
        if (oc != NULL) {
 
1771
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
1772
                                           reply->packet->options,
 
1773
                                           reply->opt_state, &global_scope,
 
1774
                                           oc, MDL) ||
 
1775
                    (data.len != 4)) {
 
1776
                        log_error("Invalid rebinding time.");
 
1777
                } else {
 
1778
                        reply->rebind = getULong(data.data);
 
1779
                }
 
1780
 
 
1781
                if (data.data != NULL)
 
1782
                        data_string_forget(&data, MDL);
 
1783
        }
 
1784
        putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
 
1785
 
 
1786
        /*
 
1787
         * If this is not a 'soft' binding, consume the new changes into
 
1788
         * the database (if any have been attached to the ia_na).
 
1789
         *
 
1790
         * Loop through the assigned dynamic addresses, referencing the
 
1791
         * leases onto this IA_NA rather than any old ones, and updating
 
1792
         * pool timers for each (if any).
 
1793
         */
 
1794
        if ((status != ISC_R_CANCELED) && !reply->static_lease &&
 
1795
            (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
 
1796
            (reply->ia->num_iasubopt != 0)) {
 
1797
                struct iasubopt *tmp;
 
1798
                struct data_string *ia_id;
 
1799
                int i;
 
1800
 
 
1801
                for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
 
1802
                        tmp = reply->ia->iasubopt[i];
 
1803
 
 
1804
                        if (tmp->ia != NULL)
 
1805
                                ia_dereference(&tmp->ia, MDL);
 
1806
                        ia_reference(&tmp->ia, reply->ia, MDL);
 
1807
 
 
1808
                        /* Commit 'hard' bindings. */
 
1809
                        tmp->hard_lifetime_end_time =
 
1810
                                tmp->soft_lifetime_end_time;
 
1811
                        tmp->soft_lifetime_end_time = 0;
 
1812
                        renew_lease6(tmp->ipv6_pool, tmp);
 
1813
                        schedule_lease_timeout(tmp->ipv6_pool);
 
1814
 
 
1815
                        /*
 
1816
                         * Perform ddns updates.
 
1817
                         */
 
1818
                        oc = lookup_option(&server_universe, reply->opt_state,
 
1819
                                           SV_DDNS_UPDATES);
 
1820
                        if ((oc == NULL) ||
 
1821
                            evaluate_boolean_option_cache(NULL, reply->packet,
 
1822
                                                          NULL, NULL,
 
1823
                                                        reply->packet->options,
 
1824
                                                          reply->opt_state,
 
1825
                                                          &tmp->scope,
 
1826
                                                          oc, MDL)) {
 
1827
                                ddns_updates(reply->packet, NULL, NULL,
 
1828
                                             tmp, NULL, reply->opt_state);
 
1829
                        }
 
1830
                }
 
1831
 
 
1832
                /* Remove any old ia from the hash. */
 
1833
                if (reply->old_ia != NULL) {
 
1834
                        ia_id = &reply->old_ia->iaid_duid;
 
1835
                        ia_hash_delete(ia_na_active,
 
1836
                                       (unsigned char *)ia_id->data,
 
1837
                                       ia_id->len, MDL);
 
1838
                        ia_dereference(&reply->old_ia, MDL);
 
1839
                }
 
1840
 
 
1841
                /* Put new ia into the hash. */
 
1842
                reply->ia->cltt = cur_time;
 
1843
                ia_id = &reply->ia->iaid_duid;
 
1844
                ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
 
1845
                            ia_id->len, reply->ia, MDL);
 
1846
 
 
1847
                write_ia(reply->ia);
 
1848
        }
 
1849
 
 
1850
      cleanup:
 
1851
        if (packet_ia != NULL)
 
1852
                option_state_dereference(&packet_ia, MDL);
 
1853
        if (reply->reply_ia != NULL)
 
1854
                option_state_dereference(&reply->reply_ia, MDL);
 
1855
        if (ia_data.data != NULL)
 
1856
                data_string_forget(&ia_data, MDL);
 
1857
        if (data.data != NULL)
 
1858
                data_string_forget(&data, MDL);
 
1859
        if (reply->ia != NULL)
 
1860
                ia_dereference(&reply->ia, MDL);
 
1861
        if (reply->old_ia != NULL)
 
1862
                ia_dereference(&reply->old_ia, MDL);
 
1863
        if (reply->lease != NULL)
 
1864
                iasubopt_dereference(&reply->lease, MDL);
 
1865
        if (reply->fixed.data != NULL)
 
1866
                data_string_forget(&reply->fixed, MDL);
 
1867
 
 
1868
        /*
 
1869
         * ISC_R_CANCELED is a status code used by the addr processing to
 
1870
         * indicate we're replying with a status code.  This is still a
 
1871
         * success at higher layers.
 
1872
         */
 
1873
        return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
 
1874
}
 
1875
 
 
1876
/*
 
1877
 * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
 
1878
 * into the reply's current ia-scoped option cache.  Returns ISC_R_CANCELED
 
1879
 * in the event we are replying with a status code and do not wish to process
 
1880
 * more IAADDRs within this IA.
 
1881
 */
 
1882
static isc_result_t
 
1883
reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
 
1884
        u_int32_t pref_life, valid_life;
 
1885
        struct binding_scope **scope;
 
1886
        struct group *group;
 
1887
        struct subnet *subnet;
 
1888
        struct iaddr tmp_addr;
 
1889
        struct option_cache *oc;
 
1890
        struct data_string iaaddr, data;
 
1891
        isc_result_t status = ISC_R_SUCCESS;
 
1892
 
 
1893
        /* Initializes values that will be cleaned up. */
 
1894
        memset(&iaaddr, 0, sizeof(iaaddr));
 
1895
        memset(&data, 0, sizeof(data));
 
1896
        /* Note that reply->lease may be set by address_is_owned() */
 
1897
 
 
1898
        /*
 
1899
         * There is no point trying to process an incoming address if there
 
1900
         * is no room for an outgoing address.
 
1901
         */
 
1902
        if ((reply->cursor + 28) > sizeof(reply->buf)) {
 
1903
                log_error("reply_process_addr: Out of room for address.");
 
1904
                return ISC_R_NOSPACE;
 
1905
        }
 
1906
 
 
1907
        /* Extract this IAADDR option. */
 
1908
        if (!evaluate_option_cache(&iaaddr, reply->packet, NULL, NULL, 
 
1909
                                   reply->packet->options, NULL, &global_scope,
 
1910
                                   addr, MDL) ||
 
1911
            (iaaddr.len < IAADDR_OFFSET)) {
 
1912
                log_error("reply_process_addr: error evaluating IAADDR.");
 
1913
                status = ISC_R_FAILURE;
 
1914
                goto cleanup;
 
1915
        }
 
1916
 
 
1917
        /* The first 16 bytes are the IPv6 address. */
 
1918
        pref_life = getULong(iaaddr.data + 16);
 
1919
        valid_life = getULong(iaaddr.data + 20);
 
1920
 
 
1921
        if ((reply->client_valid == 0) ||
 
1922
            (reply->client_valid > valid_life))
 
1923
                reply->client_valid = valid_life;
 
1924
 
 
1925
        if ((reply->client_prefer == 0) ||
 
1926
            (reply->client_prefer > pref_life))
 
1927
                reply->client_prefer = pref_life;
 
1928
 
 
1929
        /* 
 
1930
         * Clients may choose to send :: as an address, with the idea to give
 
1931
         * hints about preferred-lifetime or valid-lifetime.
 
1932
         */
 
1933
        tmp_addr.len = 16;
 
1934
        memset(tmp_addr.iabuf, 0, 16);
 
1935
        if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
 
1936
                /* Status remains success; we just ignore this one. */
 
1937
                goto cleanup;
 
1938
        }
 
1939
 
 
1940
        /* tmp_addr len remains 16 */
 
1941
        memcpy(tmp_addr.iabuf, iaaddr.data, 16);
 
1942
 
 
1943
        /*
 
1944
         * Verify that this address is on the client's network.
 
1945
         */
 
1946
        for (subnet = reply->shared->subnets ; subnet != NULL ;
 
1947
             subnet = subnet->next_sibling) {
 
1948
                if (addr_eq(subnet_number(tmp_addr, subnet->netmask),
 
1949
                            subnet->net))
 
1950
                        break;
 
1951
        }
 
1952
 
 
1953
        /* Address not found on shared network. */
 
1954
        if (subnet == NULL) {
 
1955
                /* Ignore this address on 'soft' bindings. */
 
1956
                if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
 
1957
                        /* disable rapid commit */
 
1958
                        reply->buf.reply.msg_type = DHCPV6_ADVERTISE;
 
1959
                        delete_option(&dhcpv6_universe,
 
1960
                                      reply->opt_state,
 
1961
                                      D6O_RAPID_COMMIT);
 
1962
                        /* status remains success */
 
1963
                        goto cleanup;
 
1964
                }
 
1965
 
 
1966
                /*
 
1967
                 * RFC3315 section 18.2.1:
 
1968
                 *
 
1969
                 * If the server finds that the prefix on one or more IP
 
1970
                 * addresses in any IA in the message from the client is not
 
1971
                 * appropriate for the link to which the client is connected,
 
1972
                 * the server MUST return the IA to the client with a Status
 
1973
                 * Code option with the value NotOnLink.
 
1974
                 */
 
1975
                if (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) {
 
1976
                        /* Rewind the IA_NA to empty. */
 
1977
                        option_state_dereference(&reply->reply_ia, MDL);
 
1978
                        if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
1979
                                log_error("reply_process_addr: No memory for "
 
1980
                                          "option state wipe.");
 
1981
                                status = ISC_R_NOMEMORY;
 
1982
                                goto cleanup;
 
1983
                        }
 
1984
 
 
1985
                        /* Append a NotOnLink status code. */
 
1986
                        if (!set_status_code(STATUS_NotOnLink,
 
1987
                                             "Address not for use on this "
 
1988
                                             "link.", reply->reply_ia)) {
 
1989
                                log_error("reply_process_addr: Failure "
 
1990
                                          "setting status code.");
 
1991
                                status = ISC_R_FAILURE;
 
1992
                                goto cleanup;
 
1993
                        }
 
1994
 
 
1995
                        /* Fin (no more IAADDRs). */
 
1996
                        status = ISC_R_CANCELED;
 
1997
                        goto cleanup;
 
1998
                }
 
1999
 
 
2000
                /*
 
2001
                 * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
 
2002
                 *
 
2003
                 * If the server finds that any of the addresses are not
 
2004
                 * appropriate for the link to which the client is attached,
 
2005
                 * the server returns the address to the client with lifetimes
 
2006
                 * of 0.
 
2007
                 */
 
2008
                if ((reply->packet->dhcpv6_msg_type != DHCPV6_RENEW) &&
 
2009
                    (reply->packet->dhcpv6_msg_type != DHCPV6_REBIND)) {
 
2010
                        log_error("It is impossible to lease a client that is "
 
2011
                                  "not sending a solicit, request, renew, or "
 
2012
                                  "rebind.");
 
2013
                        status = ISC_R_FAILURE;
 
2014
                        goto cleanup;
 
2015
                }
 
2016
 
 
2017
                reply->send_prefer = reply->send_valid = 0;
 
2018
                goto send_addr;
 
2019
        }
 
2020
 
 
2021
        /* Verify the address belongs to the client. */
 
2022
        if (!address_is_owned(reply, &tmp_addr)) {
 
2023
                /*
 
2024
                 * For solicit and request, any addresses included are
 
2025
                 * 'requested' addresses.  For rebind, we actually have
 
2026
                 * no direction on what to do from 3315 section 18.2.4!
 
2027
                 * So I think the best bet is to try and give it out, and if
 
2028
                 * we can't, zero lifetimes.
 
2029
                 */
 
2030
                if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
 
2031
                    (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
 
2032
                    (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
 
2033
                        status = reply_process_try_addr(reply, &tmp_addr);
 
2034
 
 
2035
                        /* Either error out or skip this address. */
 
2036
                        if ((status != ISC_R_SUCCESS) && 
 
2037
                            (status != ISC_R_ADDRINUSE)) 
 
2038
                                goto cleanup;
 
2039
 
 
2040
                        if (reply->lease == NULL) {
 
2041
                                if (reply->packet->dhcpv6_msg_type ==
 
2042
                                                        DHCPV6_REBIND) {
 
2043
                                        reply->send_prefer = 0;
 
2044
                                        reply->send_valid = 0;
 
2045
                                        goto send_addr;
 
2046
                                }
 
2047
 
 
2048
                                /* status remains success - ignore */
 
2049
                                goto cleanup;
 
2050
                        }
 
2051
                /*
 
2052
                 * RFC3315 section 18.2.3:
 
2053
                 *
 
2054
                 * If the server cannot find a client entry for the IA the
 
2055
                 * server returns the IA containing no addresses with a Status
 
2056
                 * Code option set to NoBinding in the Reply message.
 
2057
                 *
 
2058
                 * On mismatch we (ab)use this pretending we have not the IA
 
2059
                 * as soon as we have not an address.
 
2060
                 */
 
2061
                } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
 
2062
                        /* Rewind the IA_NA to empty. */
 
2063
                        option_state_dereference(&reply->reply_ia, MDL);
 
2064
                        if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
2065
                                log_error("reply_process_addr: No memory for "
 
2066
                                          "option state wipe.");
 
2067
                                status = ISC_R_NOMEMORY;
 
2068
                                goto cleanup;
 
2069
                        }
 
2070
 
 
2071
                        /* Append a NoBinding status code.  */
 
2072
                        if (!set_status_code(STATUS_NoBinding,
 
2073
                                             "Address not bound to this "
 
2074
                                             "interface.", reply->reply_ia)) {
 
2075
                                log_error("reply_process_addr: Unable to "
 
2076
                                          "attach status code.");
 
2077
                                status = ISC_R_FAILURE;
 
2078
                                goto cleanup;
 
2079
                        }
 
2080
 
 
2081
                        /* Fin (no more IAADDRs). */
 
2082
                        status = ISC_R_CANCELED;
 
2083
                        goto cleanup;
 
2084
                } else {
 
2085
                        log_error("It is impossible to lease a client that is "
 
2086
                                  "not sending a solicit, request, renew, or "
 
2087
                                  "rebind message.");
 
2088
                        status = ISC_R_FAILURE;
 
2089
                        goto cleanup;
 
2090
                }
 
2091
        }
 
2092
 
 
2093
        if (reply->static_lease) {
 
2094
                if (reply->host == NULL)
 
2095
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
2096
 
 
2097
                scope = &global_scope;
 
2098
                group = reply->host->group;
 
2099
        } else {
 
2100
                if (reply->lease == NULL)
 
2101
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
2102
 
 
2103
                scope = &reply->lease->scope;
 
2104
                group = reply->lease->ipv6_pool->subnet->group;
 
2105
        }
 
2106
 
 
2107
        /*
 
2108
         * If client_resources is nonzero, then the reply_process_is_addressed
 
2109
         * function has executed configuration state into the reply option
 
2110
         * cache.  We will use that valid cache to derive configuration for
 
2111
         * whether or not to engage in additional addresses, and similar.
 
2112
         */
 
2113
        if (reply->client_resources != 0) {
 
2114
                unsigned limit = 1;
 
2115
 
 
2116
                /*
 
2117
                 * Does this client have "enough" addresses already?  Default
 
2118
                 * to one.  Everybody gets one, and one should be enough for
 
2119
                 * anybody.
 
2120
                 */
 
2121
                oc = lookup_option(&server_universe, reply->opt_state,
 
2122
                                   SV_LIMIT_ADDRS_PER_IA);
 
2123
                if (oc != NULL) {
 
2124
                        if (!evaluate_option_cache(&data, reply->packet,
 
2125
                                                   NULL, NULL,
 
2126
                                                   reply->packet->options,
 
2127
                                                   reply->opt_state,
 
2128
                                                   scope, oc, MDL) ||
 
2129
                            (data.len != 4)) {
 
2130
                                log_error("reply_process_addr: unable to "
 
2131
                                          "evaluate addrs-per-ia value.");
 
2132
                                status = ISC_R_FAILURE;
 
2133
                                goto cleanup;
 
2134
                        }
 
2135
 
 
2136
                        limit = getULong(data.data);
 
2137
                        data_string_forget(&data, MDL);
 
2138
                }
 
2139
 
 
2140
                /*
 
2141
                 * If we wish to limit the client to a certain number of
 
2142
                 * addresses, then omit the address from the reply.
 
2143
                 */
 
2144
                if (reply->client_resources >= limit)
 
2145
                        goto cleanup;
 
2146
        }
 
2147
 
 
2148
        status = reply_process_is_addressed(reply, scope, group);
 
2149
        if (status != ISC_R_SUCCESS)
 
2150
                goto cleanup;
 
2151
 
 
2152
      send_addr:
 
2153
        status = reply_process_send_addr(reply, &tmp_addr);
 
2154
 
 
2155
      cleanup:
 
2156
        if (iaaddr.data != NULL)
 
2157
                data_string_forget(&iaaddr, MDL);
 
2158
        if (data.data != NULL)
 
2159
                data_string_forget(&data, MDL);
 
2160
        if (reply->lease != NULL)
 
2161
                iasubopt_dereference(&reply->lease, MDL);
 
2162
 
 
2163
        return status;
 
2164
}
 
2165
 
 
2166
/*
 
2167
 * Verify the address belongs to the client.  If we've got a host
 
2168
 * record with a fixed address, it has to be the assigned address
 
2169
 * (fault out all else).  Otherwise it's a dynamic address, so lookup
 
2170
 * that address and make sure it belongs to this DUID:IAID pair.
 
2171
 */
 
2172
static isc_boolean_t
 
2173
address_is_owned(struct reply_state *reply, struct iaddr *addr) {
 
2174
        int i;
 
2175
 
 
2176
        /*
 
2177
         * This faults out addresses that don't match fixed addresses.
 
2178
         */
 
2179
        if (reply->static_lease) {
 
2180
                if (reply->fixed.data == NULL)
 
2181
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
2182
 
 
2183
                if (memcmp(addr->iabuf, reply->fixed.data, 16) == 0)
 
2184
                        return ISC_TRUE;
 
2185
 
 
2186
                return ISC_FALSE;
 
2187
        }
 
2188
 
 
2189
        if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
 
2190
                return ISC_FALSE;
 
2191
 
 
2192
        for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
 
2193
                struct iasubopt *tmp;
 
2194
 
 
2195
                tmp = reply->old_ia->iasubopt[i];
 
2196
 
 
2197
                if (memcmp(addr->iabuf, &tmp->addr, 16) == 0) {
 
2198
                        iasubopt_reference(&reply->lease, tmp, MDL);
 
2199
                        return ISC_TRUE;
 
2200
                }
 
2201
        }
 
2202
 
 
2203
        return ISC_FALSE;
 
2204
}
 
2205
 
 
2206
/* Process a client-supplied IA_TA.  This may append options to the tail of
 
2207
 * the reply packet being built in the reply_state structure.
 
2208
 */
 
2209
static isc_result_t
 
2210
reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
 
2211
        isc_result_t status = ISC_R_SUCCESS;
 
2212
        u_int32_t iaid;
 
2213
        unsigned ia_cursor;
 
2214
        struct option_state *packet_ia;
 
2215
        struct option_cache *oc;
 
2216
        struct data_string ia_data, data;
 
2217
        struct data_string iaaddr;
 
2218
        u_int32_t pref_life, valid_life;
 
2219
        struct iaddr tmp_addr;
 
2220
 
 
2221
        /* Initialize values that will get cleaned up on return. */
 
2222
        packet_ia = NULL;
 
2223
        memset(&ia_data, 0, sizeof(ia_data));
 
2224
        memset(&data, 0, sizeof(data));
 
2225
        memset(&iaaddr, 0, sizeof(iaaddr));
 
2226
 
 
2227
        /* Make sure there is at least room for the header. */
 
2228
        if ((reply->cursor + IA_TA_OFFSET + 4) > sizeof(reply->buf)) {
 
2229
                log_error("reply_process_ia_ta: Reply too long for IA.");
 
2230
                return ISC_R_NOSPACE;
 
2231
        }
 
2232
 
 
2233
 
 
2234
        /* Fetch the IA_TA contents. */
 
2235
        if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
 
2236
                                       ia, IA_TA_OFFSET)) {
 
2237
                log_error("reply_process_ia_ta: error evaluating ia");
 
2238
                status = ISC_R_FAILURE;
 
2239
                goto cleanup;
 
2240
        }
 
2241
 
 
2242
        /* Extract IA_TA header contents. */
 
2243
        iaid = getULong(ia_data.data);
 
2244
 
 
2245
        /* Create an IA_TA structure. */
 
2246
        if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
 
2247
                        reply->client_id.len, MDL) != ISC_R_SUCCESS) {
 
2248
                log_error("reply_process_ia_ta: no memory for ia.");
 
2249
                status = ISC_R_NOMEMORY;
 
2250
                goto cleanup;
 
2251
        }
 
2252
        reply->ia->ia_type = D6O_IA_TA;
 
2253
 
 
2254
        /* Cache pre-existing IA, if any. */
 
2255
        ia_hash_lookup(&reply->old_ia, ia_ta_active,
 
2256
                       (unsigned char *)reply->ia->iaid_duid.data,
 
2257
                       reply->ia->iaid_duid.len, MDL);
 
2258
 
 
2259
        /*
 
2260
         * Create an option cache to carry the IA_TA option contents, and
 
2261
         * execute any user-supplied values into it.
 
2262
         */
 
2263
        if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
2264
                status = ISC_R_NOMEMORY;
 
2265
                goto cleanup;
 
2266
        }
 
2267
 
 
2268
        /*
 
2269
         * Temporary leases are dynamic by definition.
 
2270
         */
 
2271
        reply->static_lease = ISC_FALSE;
 
2272
 
 
2273
        /*
 
2274
         * Save the cursor position at the start of the IA, so we can
 
2275
         * set length later.  We write a temporary
 
2276
         * header out now just in case we decide to adjust the packet
 
2277
         * within sub-process functions.
 
2278
         */
 
2279
        ia_cursor = reply->cursor;
 
2280
 
 
2281
        /* Initialize the IA_TA header.  First the code. */
 
2282
        putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_TA);
 
2283
        reply->cursor += 2;
 
2284
 
 
2285
        /* Then option length. */
 
2286
        putUShort(reply->buf.data + reply->cursor, 0x04u);
 
2287
        reply->cursor += 2;
 
2288
 
 
2289
        /* Then IA_TA header contents; IAID. */
 
2290
        putULong(reply->buf.data + reply->cursor, iaid);
 
2291
        reply->cursor += 4;
 
2292
 
 
2293
        /* 
 
2294
         * Deal with an IAADDR for lifetimes.
 
2295
         * For all or none, process IAADDRs as hints.
 
2296
         */
 
2297
        reply->valid = reply->prefer = 0xffffffff;
 
2298
        reply->client_valid = reply->client_prefer = 0;
 
2299
        oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
 
2300
        for (; oc != NULL; oc = oc->next) {
 
2301
                memset(&iaaddr, 0, sizeof(iaaddr));
 
2302
                if (!evaluate_option_cache(&iaaddr, reply->packet,
 
2303
                                           NULL, NULL,
 
2304
                                           reply->packet->options, NULL,
 
2305
                                           &global_scope, oc, MDL) ||
 
2306
                    (iaaddr.len < IAADDR_OFFSET)) {
 
2307
                        log_error("reply_process_ia_ta: error "
 
2308
                                  "evaluating IAADDR.");
 
2309
                        status = ISC_R_FAILURE;
 
2310
                        goto cleanup;
 
2311
                }
 
2312
                /* The first 16 bytes are the IPv6 address. */
 
2313
                pref_life = getULong(iaaddr.data + 16);
 
2314
                valid_life = getULong(iaaddr.data + 20);
 
2315
 
 
2316
                if ((reply->client_valid == 0) ||
 
2317
                    (reply->client_valid > valid_life))
 
2318
                        reply->client_valid = valid_life;
 
2319
 
 
2320
                if ((reply->client_prefer == 0) ||
 
2321
                    (reply->client_prefer > pref_life))
 
2322
                        reply->client_prefer = pref_life;
 
2323
 
 
2324
                /* Nothing more if something has failed. */
 
2325
                if (status == ISC_R_CANCELED)
 
2326
                        continue;
 
2327
 
 
2328
                tmp_addr.len = 16;
 
2329
                memcpy(tmp_addr.iabuf, iaaddr.data, 16);
 
2330
                if (!temporary_is_available(reply, &tmp_addr))
 
2331
                        goto bad_temp;
 
2332
                status = reply_process_is_addressed(reply,
 
2333
                                                    &reply->lease->scope,
 
2334
                                                    reply->shared->group);
 
2335
                if (status != ISC_R_SUCCESS)
 
2336
                        goto bad_temp;
 
2337
                status = reply_process_send_addr(reply, &tmp_addr);
 
2338
                if (status != ISC_R_SUCCESS)
 
2339
                        goto bad_temp;
 
2340
                if (reply->lease != NULL)
 
2341
                        iasubopt_dereference(&reply->lease, MDL);
 
2342
                continue;
 
2343
 
 
2344
        bad_temp:
 
2345
                /* Rewind the IA_TA to empty. */
 
2346
                option_state_dereference(&reply->reply_ia, MDL);
 
2347
                if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
2348
                        status = ISC_R_NOMEMORY;
 
2349
                        goto cleanup;
 
2350
                }
 
2351
                status = ISC_R_CANCELED;
 
2352
                reply->client_resources = 0;
 
2353
                reply->resources_included = ISC_FALSE;
 
2354
                if (reply->lease != NULL)
 
2355
                        iasubopt_dereference(&reply->lease, MDL);
 
2356
        }
 
2357
        reply->ia_count++;
 
2358
 
 
2359
        /*
 
2360
         * Give the client temporary addresses.
 
2361
         */
 
2362
        if (reply->client_resources != 0)
 
2363
                goto store;
 
2364
        status = find_client_temporaries(reply);
 
2365
        if (status == ISC_R_NORESOURCES) {
 
2366
                switch (reply->packet->dhcpv6_msg_type) {
 
2367
                      case DHCPV6_SOLICIT:
 
2368
                        /*
 
2369
                         * No address for any IA is handled
 
2370
                         * by the caller.
 
2371
                         */
 
2372
                        /* FALL THROUGH */
 
2373
 
 
2374
                      case DHCPV6_REQUEST:
 
2375
                        /* Section 18.2.1 (Request):
 
2376
                         *
 
2377
                         * If the server cannot assign any addresses to
 
2378
                         * an IA in the message from the client, the
 
2379
                         * server MUST include the IA in the Reply
 
2380
                         * message with no addresses in the IA and a
 
2381
                         * Status Code option in the IA containing
 
2382
                         * status code NoAddrsAvail.
 
2383
                         */
 
2384
                        option_state_dereference(&reply->reply_ia, MDL);
 
2385
                        if (!option_state_allocate(&reply->reply_ia,  MDL)) {
 
2386
                                log_error("reply_process_ia_ta: No "
 
2387
                                          "memory for option state wipe.");
 
2388
                                status = ISC_R_NOMEMORY;
 
2389
                                goto cleanup;
 
2390
                        }
 
2391
 
 
2392
                        if (!set_status_code(STATUS_NoAddrsAvail,
 
2393
                                             "No addresses available "
 
2394
                                             "for this interface.",
 
2395
                                              reply->reply_ia)) {
 
2396
                                log_error("reply_process_ia_ta: Unable "
 
2397
                                          "to set NoAddrsAvail status code.");
 
2398
                                status = ISC_R_FAILURE;
 
2399
                                goto cleanup;
 
2400
                        }
 
2401
 
 
2402
                        status = ISC_R_SUCCESS;
 
2403
                        break;
 
2404
 
 
2405
                      default:
 
2406
                        /*
 
2407
                         * We don't want to include the IA if we
 
2408
                         * provide zero addresses including zeroed
 
2409
                         * lifetimes.
 
2410
                         */
 
2411
                        if (reply->resources_included)
 
2412
                                status = ISC_R_SUCCESS;
 
2413
                        else
 
2414
                                goto cleanup;
 
2415
                        break;
 
2416
                }
 
2417
        } else if (status != ISC_R_SUCCESS)
 
2418
                goto cleanup;
 
2419
 
 
2420
      store:
 
2421
        reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
 
2422
                                        sizeof(reply->buf) - reply->cursor,
 
2423
                                        reply->reply_ia, reply->packet,
 
2424
                                        required_opts_IA, NULL);
 
2425
 
 
2426
        /* Reset the length of this IA to match what was just written. */
 
2427
        putUShort(reply->buf.data + ia_cursor + 2,
 
2428
                  reply->cursor - (ia_cursor + 4));
 
2429
 
 
2430
        /*
 
2431
         * Consume the new changes into the database (if any have been
 
2432
         * attached to the ia_ta).
 
2433
         *
 
2434
         * Loop through the assigned dynamic addresses, referencing the
 
2435
         * leases onto this IA_TA rather than any old ones, and updating
 
2436
         * pool timers for each (if any).
 
2437
         */
 
2438
        if ((status != ISC_R_CANCELED) &&
 
2439
            (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
 
2440
            (reply->ia->num_iasubopt != 0)) {
 
2441
                struct iasubopt *tmp;
 
2442
                struct data_string *ia_id;
 
2443
                int i;
 
2444
 
 
2445
                for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
 
2446
                        tmp = reply->ia->iasubopt[i];
 
2447
 
 
2448
                        if (tmp->ia != NULL)
 
2449
                                ia_dereference(&tmp->ia, MDL);
 
2450
                        ia_reference(&tmp->ia, reply->ia, MDL);
 
2451
 
 
2452
                        /* Commit 'hard' bindings. */
 
2453
                        tmp->hard_lifetime_end_time =
 
2454
                                tmp->soft_lifetime_end_time;
 
2455
                        tmp->soft_lifetime_end_time = 0;
 
2456
                        renew_lease6(tmp->ipv6_pool, tmp);
 
2457
                        schedule_lease_timeout(tmp->ipv6_pool);
 
2458
 
 
2459
                        /*
 
2460
                         * Perform ddns updates.
 
2461
                         */
 
2462
                        oc = lookup_option(&server_universe, reply->opt_state,
 
2463
                                           SV_DDNS_UPDATES);
 
2464
                        if ((oc == NULL) ||
 
2465
                            evaluate_boolean_option_cache(NULL, reply->packet,
 
2466
                                                          NULL, NULL,
 
2467
                                                        reply->packet->options,
 
2468
                                                          reply->opt_state,
 
2469
                                                          &tmp->scope,
 
2470
                                                          oc, MDL)) {
 
2471
                                ddns_updates(reply->packet, NULL, NULL,
 
2472
                                             tmp, NULL, reply->opt_state);
 
2473
                        }
 
2474
                }
 
2475
 
 
2476
                /* Remove any old ia from the hash. */
 
2477
                if (reply->old_ia != NULL) {
 
2478
                        ia_id = &reply->old_ia->iaid_duid;
 
2479
                        ia_hash_delete(ia_ta_active,
 
2480
                                       (unsigned char *)ia_id->data,
 
2481
                                       ia_id->len, MDL);
 
2482
                        ia_dereference(&reply->old_ia, MDL);
 
2483
                }
 
2484
 
 
2485
                /* Put new ia into the hash. */
 
2486
                reply->ia->cltt = cur_time;
 
2487
                ia_id = &reply->ia->iaid_duid;
 
2488
                ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
 
2489
                            ia_id->len, reply->ia, MDL);
 
2490
 
 
2491
                write_ia(reply->ia);
 
2492
        }
 
2493
 
 
2494
      cleanup:
 
2495
        if (packet_ia != NULL)
 
2496
                option_state_dereference(&packet_ia, MDL);
 
2497
        if (iaaddr.data != NULL)
 
2498
                data_string_forget(&iaaddr, MDL);
 
2499
        if (reply->reply_ia != NULL)
 
2500
                option_state_dereference(&reply->reply_ia, MDL);
 
2501
        if (ia_data.data != NULL)
 
2502
                data_string_forget(&ia_data, MDL);
 
2503
        if (data.data != NULL)
 
2504
                data_string_forget(&data, MDL);
 
2505
        if (reply->ia != NULL)
 
2506
                ia_dereference(&reply->ia, MDL);
 
2507
        if (reply->old_ia != NULL)
 
2508
                ia_dereference(&reply->old_ia, MDL);
 
2509
        if (reply->lease != NULL)
 
2510
                iasubopt_dereference(&reply->lease, MDL);
 
2511
 
 
2512
        /*
 
2513
         * ISC_R_CANCELED is a status code used by the addr processing to
 
2514
         * indicate we're replying with other addresses.  This is still a
 
2515
         * success at higher layers.
 
2516
         */
 
2517
        return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
 
2518
}
 
2519
 
 
2520
/*
 
2521
 * Verify the temporary address is available.
 
2522
 */
 
2523
static isc_boolean_t
 
2524
temporary_is_available(struct reply_state *reply, struct iaddr *addr) {
 
2525
        struct in6_addr tmp_addr;
 
2526
        struct subnet *subnet;
 
2527
        struct ipv6_pool *pool;
 
2528
        int i;
 
2529
 
 
2530
        memcpy(&tmp_addr, addr->iabuf, sizeof(tmp_addr));
 
2531
        /*
 
2532
         * Clients may choose to send :: as an address, with the idea to give
 
2533
         * hints about preferred-lifetime or valid-lifetime.
 
2534
         * So this is not a request for this address.
 
2535
         */
 
2536
        if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
 
2537
                return ISC_FALSE;
 
2538
 
 
2539
        /*
 
2540
         * Verify that this address is on the client's network.
 
2541
         */
 
2542
        for (subnet = reply->shared->subnets ; subnet != NULL ;
 
2543
             subnet = subnet->next_sibling) {
 
2544
                if (addr_eq(subnet_number(*addr, subnet->netmask),
 
2545
                            subnet->net))
 
2546
                        break;
 
2547
        }
 
2548
 
 
2549
        /* Address not found on shared network. */
 
2550
        if (subnet == NULL)
 
2551
                return ISC_FALSE;
 
2552
 
 
2553
        /*
 
2554
         * Check if this address is owned (must be before next step).
 
2555
         */
 
2556
        if (address_is_owned(reply, addr))
 
2557
                return ISC_TRUE;
 
2558
 
 
2559
        /*
 
2560
         * Verify that this address is in a temporary pool and try to get it.
 
2561
         */
 
2562
        if (reply->shared->ipv6_pools == NULL)
 
2563
                return ISC_FALSE;
 
2564
        for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
 
2565
                if (pool->pool_type != D6O_IA_TA)
 
2566
                        continue;
 
2567
                if (ipv6_in_pool(&tmp_addr, pool))
 
2568
                        break;
 
2569
        }
 
2570
        if (pool == NULL)
 
2571
                return ISC_FALSE;
 
2572
        if (lease6_exists(pool, &tmp_addr))
 
2573
                return ISC_FALSE;
 
2574
        if (iasubopt_allocate(&reply->lease, MDL) != ISC_R_SUCCESS)
 
2575
                return ISC_FALSE;
 
2576
        reply->lease->addr = tmp_addr;
 
2577
        reply->lease->plen = 0;
 
2578
        /* Default is soft binding for 2 minutes. */
 
2579
        if (add_lease6(pool, reply->lease, cur_time + 120) != ISC_R_SUCCESS)
 
2580
                return ISC_FALSE;
 
2581
 
 
2582
        return ISC_TRUE;
 
2583
}
 
2584
 
 
2585
/*
 
2586
 * Get a temporary address per prefix.
 
2587
 */
 
2588
static isc_result_t
 
2589
find_client_temporaries(struct reply_state *reply) {
 
2590
        struct shared_network *shared;
 
2591
        int i;
 
2592
        struct ipv6_pool *p;
 
2593
        isc_result_t status;
 
2594
        unsigned int attempts;
 
2595
        struct iaddr send_addr;
 
2596
 
 
2597
        /*
 
2598
         * No pools, we're done.
 
2599
         */
 
2600
        shared = reply->shared;
 
2601
        if (shared->ipv6_pools == NULL) {
 
2602
                log_debug("Unable to get client addresses: "
 
2603
                          "no IPv6 pools on this shared network");
 
2604
                return ISC_R_NORESOURCES;
 
2605
        }
 
2606
 
 
2607
        status = ISC_R_NORESOURCES;
 
2608
        for (i = 0;; i++) {
 
2609
                p = shared->ipv6_pools[i];
 
2610
                if (p == NULL) {
 
2611
                        break;
 
2612
                }
 
2613
                if (p->pool_type != D6O_IA_TA) {
 
2614
                        continue;
 
2615
                }
 
2616
 
 
2617
                /*
 
2618
                 * Get an address in this temporary pool.
 
2619
                 */
 
2620
                status = create_lease6(p, &reply->lease, &attempts,
 
2621
                                       &reply->client_id, cur_time + 120);
 
2622
                if (status != ISC_R_SUCCESS) {
 
2623
                        log_debug("Unable to get a temporary address.");
 
2624
                        goto cleanup;
 
2625
                }
 
2626
 
 
2627
                status = reply_process_is_addressed(reply,
 
2628
                                                    &reply->lease->scope,
 
2629
                                      reply->lease->ipv6_pool->subnet->group);
 
2630
                if (status != ISC_R_SUCCESS) {
 
2631
                        goto cleanup;
 
2632
                }
 
2633
                send_addr.len = 16;
 
2634
                memcpy(send_addr.iabuf, &reply->lease->addr, 16);
 
2635
                status = reply_process_send_addr(reply, &send_addr);
 
2636
                if (status != ISC_R_SUCCESS) {
 
2637
                        goto cleanup;
 
2638
                }
 
2639
                if (reply->lease != NULL) {
 
2640
                        iasubopt_dereference(&reply->lease, MDL);
 
2641
                }
 
2642
        }
 
2643
 
 
2644
      cleanup:
 
2645
        if (reply->lease != NULL) {
 
2646
                iasubopt_dereference(&reply->lease, MDL);
 
2647
        }
 
2648
        return status;
 
2649
}
 
2650
 
 
2651
/*
 
2652
 * This function only returns failure on 'hard' failures.  If it succeeds,
 
2653
 * it will leave a lease structure behind.
 
2654
 */
 
2655
static isc_result_t
 
2656
reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
 
2657
        isc_result_t status = ISC_R_NORESOURCES;
 
2658
        struct ipv6_pool *pool;
 
2659
        int i;
 
2660
        struct data_string data_addr;
 
2661
 
 
2662
        if ((reply == NULL) || (reply->shared == NULL) ||
 
2663
            (reply->shared->ipv6_pools == NULL) || (addr == NULL) ||
 
2664
            (reply->lease != NULL))
 
2665
                return ISC_R_INVALIDARG;
 
2666
 
 
2667
        memset(&data_addr, 0, sizeof(data_addr));
 
2668
        data_addr.len = addr->len;
 
2669
        data_addr.data = addr->iabuf;
 
2670
 
 
2671
        for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
 
2672
                if (pool->pool_type != D6O_IA_NA)
 
2673
                        continue;
 
2674
                status = try_client_v6_address(&reply->lease, pool,
 
2675
                                               &data_addr);
 
2676
                if (status == ISC_R_SUCCESS)
 
2677
                        break;
 
2678
        }
 
2679
 
 
2680
        /* Note that this is just pedantry.  There is no allocation to free. */
 
2681
        data_string_forget(&data_addr, MDL);
 
2682
        /* Return just the most recent status... */
 
2683
        return status;
 
2684
}
 
2685
 
 
2686
/* Look around for an address to give the client.  First, look through the
 
2687
 * old IA for addresses we can extend.  Second, try to allocate a new address.
 
2688
 * Finally, actually add that address into the current reply IA.
 
2689
 */
 
2690
static isc_result_t
 
2691
find_client_address(struct reply_state *reply) {
 
2692
        struct iaddr send_addr;
 
2693
        isc_result_t status = ISC_R_NORESOURCES;
 
2694
        struct iasubopt *lease, *best_lease = NULL;
 
2695
        struct binding_scope **scope;
 
2696
        struct group *group;
 
2697
        int i;
 
2698
 
 
2699
        if (reply->static_lease) {
 
2700
                if (reply->host == NULL)
 
2701
                        return ISC_R_INVALIDARG;
 
2702
 
 
2703
                send_addr.len = 16;
 
2704
                memcpy(send_addr.iabuf, reply->fixed.data, 16);
 
2705
 
 
2706
                status = ISC_R_SUCCESS;
 
2707
                scope = &global_scope;
 
2708
                group = reply->host->group;
 
2709
                goto send_addr;
 
2710
        }
 
2711
 
 
2712
        if (reply->old_ia != NULL)  {
 
2713
                for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
 
2714
                        lease = reply->old_ia->iasubopt[i];
 
2715
 
 
2716
                        best_lease = lease_compare(lease, best_lease);
 
2717
                }
 
2718
        }
 
2719
 
 
2720
        /* Try to pick a new address if we didn't find one, or if we found an
 
2721
         * abandoned lease.
 
2722
         */
 
2723
        if ((best_lease == NULL) || (best_lease->state == FTS_ABANDONED)) {
 
2724
                status = pick_v6_address(&reply->lease, reply->shared,
 
2725
                                         &reply->client_id);
 
2726
        } else if (best_lease != NULL) {
 
2727
                iasubopt_reference(&reply->lease, best_lease, MDL);
 
2728
                status = ISC_R_SUCCESS;
 
2729
        }
 
2730
 
 
2731
        /* Pick the abandoned lease as a last resort. */
 
2732
        if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
 
2733
                /* I don't see how this is supposed to be done right now. */
 
2734
                log_error("Reclaiming abandoned addresses is not yet "
 
2735
                          "supported.  Treating this as an out of space "
 
2736
                          "condition.");
 
2737
                /* iasubopt_reference(&reply->lease, best_lease, MDL); */
 
2738
        }
 
2739
 
 
2740
        /* Give up now if we didn't find a lease. */
 
2741
        if (status != ISC_R_SUCCESS)
 
2742
                return status;
 
2743
 
 
2744
        if (reply->lease == NULL)
 
2745
                log_fatal("Impossible condition at %s:%d.", MDL);
 
2746
 
 
2747
        /* Draw binding scopes from the lease's binding scope, and config
 
2748
         * from the lease's containing subnet and higher.  Note that it may
 
2749
         * be desirable to place the group attachment directly in the pool.
 
2750
         */
 
2751
        scope = &reply->lease->scope;
 
2752
        group = reply->lease->ipv6_pool->subnet->group;
 
2753
 
 
2754
        send_addr.len = 16;
 
2755
        memcpy(send_addr.iabuf, &reply->lease->addr, 16);
 
2756
 
 
2757
      send_addr:
 
2758
        status = reply_process_is_addressed(reply, scope, group);
 
2759
        if (status != ISC_R_SUCCESS)
 
2760
                return status;
 
2761
 
 
2762
        status = reply_process_send_addr(reply, &send_addr);
 
2763
        return status;
 
2764
}
 
2765
 
 
2766
/* Once an address is found for a client, perform several common functions;
 
2767
 * Calculate and store valid and preferred lease times, draw client options
 
2768
 * into the option state.
 
2769
 */
 
2770
static isc_result_t
 
2771
reply_process_is_addressed(struct reply_state *reply,
 
2772
                           struct binding_scope **scope, struct group *group)
 
2773
{
 
2774
        isc_result_t status = ISC_R_SUCCESS;
 
2775
        struct data_string data;
 
2776
        struct option_cache *oc;
 
2777
 
 
2778
        /* Initialize values we will cleanup. */
 
2779
        memset(&data, 0, sizeof(data));
 
2780
 
 
2781
        /* Execute relevant options into root scope. */
 
2782
        execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
 
2783
                                    reply->packet->options, reply->opt_state,
 
2784
                                    scope, group, root_group);
 
2785
 
 
2786
        /* Determine valid lifetime. */
 
2787
        if (reply->client_valid == 0)
 
2788
                reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
 
2789
        else
 
2790
                reply->send_valid = reply->client_valid;
 
2791
 
 
2792
        oc = lookup_option(&server_universe, reply->opt_state,
 
2793
                           SV_DEFAULT_LEASE_TIME);
 
2794
        if (oc != NULL) {
 
2795
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
2796
                                           reply->packet->options,
 
2797
                                           reply->opt_state,
 
2798
                                           scope, oc, MDL) ||
 
2799
                    (data.len != 4)) {
 
2800
                        log_error("reply_process_is_addressed: unable to "
 
2801
                                  "evaluate default lease time");
 
2802
                        status = ISC_R_FAILURE;
 
2803
                        goto cleanup;
 
2804
                }
 
2805
 
 
2806
                reply->send_valid = getULong(data.data);
 
2807
                data_string_forget(&data, MDL);
 
2808
        }
 
2809
 
 
2810
        if (reply->client_prefer == 0)
 
2811
                reply->send_prefer = reply->send_valid;
 
2812
        else
 
2813
                reply->send_prefer = reply->client_prefer;
 
2814
 
 
2815
        if (reply->send_prefer >= reply->send_valid)
 
2816
                reply->send_prefer = (reply->send_valid / 2) +
 
2817
                                     (reply->send_valid / 8);
 
2818
 
 
2819
        oc = lookup_option(&server_universe, reply->opt_state,
 
2820
                           SV_PREFER_LIFETIME);
 
2821
        if (oc != NULL) {
 
2822
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
2823
                                           reply->packet->options,
 
2824
                                           reply->opt_state,
 
2825
                                           scope, oc, MDL) ||
 
2826
                    (data.len != 4)) {
 
2827
                        log_error("reply_process_is_addressed: unable to "
 
2828
                                  "evaluate preferred lease time");
 
2829
                        status = ISC_R_FAILURE;
 
2830
                        goto cleanup;
 
2831
                }
 
2832
 
 
2833
                reply->send_prefer = getULong(data.data);
 
2834
                data_string_forget(&data, MDL);
 
2835
        }
 
2836
 
 
2837
        /* Note lowest values for later calculation of renew/rebind times. */
 
2838
        if (reply->prefer > reply->send_prefer)
 
2839
                reply->prefer = reply->send_prefer;
 
2840
 
 
2841
        if (reply->valid > reply->send_valid)
 
2842
                reply->valid = reply->send_valid;
 
2843
 
 
2844
#if 0
 
2845
        /*
 
2846
         * XXX: Old 4.0.0 alpha code would change the host {} record
 
2847
         * XXX: uid upon lease assignment.  This was intended to cover the
 
2848
         * XXX: case where a client first identifies itself using vendor
 
2849
         * XXX: options in a solicit, or request, but later neglects to include
 
2850
         * XXX: these options in a Renew or Rebind.  It is not clear that this
 
2851
         * XXX: is required, and has some startling ramifications (such as
 
2852
         * XXX: how to recover this dynamic host {} state across restarts).
 
2853
         */
 
2854
        if (reply->host != NULL)
 
2855
                change_host_uid(host, reply->client_id->data,
 
2856
                                reply->client_id->len);
 
2857
#endif /* 0 */
 
2858
 
 
2859
        /* Perform dynamic lease related update work. */
 
2860
        if (reply->lease != NULL) {
 
2861
                /* Cached lifetimes */
 
2862
                reply->lease->prefer = reply->send_prefer;
 
2863
                reply->lease->valid = reply->send_valid;
 
2864
 
 
2865
                /* Advance (or rewind) the valid lifetime. */
 
2866
                if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
 
2867
                        reply->lease->soft_lifetime_end_time =
 
2868
                                cur_time + reply->send_valid;
 
2869
                        /* Wait before renew! */
 
2870
                }
 
2871
 
 
2872
                status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
 
2873
                if (status != ISC_R_SUCCESS) {
 
2874
                        log_fatal("reply_process_is_addressed: Unable to "
 
2875
                                  "attach lease to new IA: %s",
 
2876
                                  isc_result_totext(status));
 
2877
                }
 
2878
 
 
2879
                /*
 
2880
                 * If this is a new lease, make sure it is attached somewhere.
 
2881
                 */
 
2882
                if (reply->lease->ia == NULL) {
 
2883
                        ia_reference(&reply->lease->ia, reply->ia, MDL);
 
2884
                }
 
2885
        }
 
2886
 
 
2887
        /* Bring a copy of the relevant options into the IA scope. */
 
2888
        execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
 
2889
                                    reply->packet->options, reply->reply_ia,
 
2890
                                    scope, group, root_group);
 
2891
 
 
2892
      cleanup:
 
2893
        if (data.data != NULL)
 
2894
                data_string_forget(&data, MDL);
 
2895
 
 
2896
        if (status == ISC_R_SUCCESS)
 
2897
                reply->client_resources++;
 
2898
 
 
2899
        return status;
 
2900
}
 
2901
 
 
2902
/* Simply send an IAADDR within the IA scope as described. */
 
2903
static isc_result_t
 
2904
reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
 
2905
        isc_result_t status = ISC_R_SUCCESS;
 
2906
        struct data_string data;
 
2907
 
 
2908
        memset(&data, 0, sizeof(data));
 
2909
 
 
2910
        /* Now append the lease. */
 
2911
        data.len = IAADDR_OFFSET;
 
2912
        if (!buffer_allocate(&data.buffer, data.len, MDL)) {
 
2913
                log_error("reply_process_send_addr: out of memory"
 
2914
                          "allocating new IAADDR buffer.");
 
2915
                status = ISC_R_NOMEMORY;
 
2916
                goto cleanup;
 
2917
        }
 
2918
        data.data = data.buffer->data;
 
2919
 
 
2920
        memcpy(data.buffer->data, addr->iabuf, 16);
 
2921
        putULong(data.buffer->data + 16, reply->send_prefer);
 
2922
        putULong(data.buffer->data + 20, reply->send_valid);
 
2923
 
 
2924
        if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
 
2925
                                  data.buffer, data.buffer->data,
 
2926
                                  data.len, D6O_IAADDR, 0)) {
 
2927
                log_error("reply_process_send_addr: unable "
 
2928
                          "to save IAADDR option");
 
2929
                status = ISC_R_FAILURE;
 
2930
                goto cleanup;
 
2931
        }
 
2932
 
 
2933
        reply->resources_included = ISC_TRUE;
 
2934
 
 
2935
      cleanup:
 
2936
        if (data.data != NULL)
 
2937
                data_string_forget(&data, MDL);
 
2938
 
 
2939
        return status;
 
2940
}
 
2941
 
 
2942
/* Choose the better of two leases. */
 
2943
static struct iasubopt *
 
2944
lease_compare(struct iasubopt *alpha, struct iasubopt *beta) {
 
2945
        if (alpha == NULL)
 
2946
                return beta;
 
2947
        if (beta == NULL)
 
2948
                return alpha;
 
2949
 
 
2950
        switch(alpha->state) {
 
2951
              case FTS_ACTIVE:
 
2952
                switch(beta->state) {
 
2953
                      case FTS_ACTIVE:
 
2954
                        /* Choose the lease with the longest lifetime (most
 
2955
                         * likely the most recently allocated).
 
2956
                         */
 
2957
                        if (alpha->hard_lifetime_end_time < 
 
2958
                            beta->hard_lifetime_end_time)
 
2959
                                return beta;
 
2960
                        else
 
2961
                                return alpha;
 
2962
 
 
2963
                      case FTS_EXPIRED:
 
2964
                      case FTS_ABANDONED:
 
2965
                        return alpha;
 
2966
 
 
2967
                      default:
 
2968
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
2969
                }
 
2970
                break;
 
2971
 
 
2972
              case FTS_EXPIRED:
 
2973
                switch (beta->state) {
 
2974
                      case FTS_ACTIVE:
 
2975
                        return beta;
 
2976
 
 
2977
                      case FTS_EXPIRED:
 
2978
                        /* Choose the most recently expired lease. */
 
2979
                        if (alpha->hard_lifetime_end_time <
 
2980
                            beta->hard_lifetime_end_time)
 
2981
                                return beta;
 
2982
                        else if ((alpha->hard_lifetime_end_time ==
 
2983
                                  beta->hard_lifetime_end_time) &&
 
2984
                                 (alpha->soft_lifetime_end_time <
 
2985
                                  beta->soft_lifetime_end_time))
 
2986
                                return beta;
 
2987
                        else
 
2988
                                return alpha;
 
2989
 
 
2990
                      case FTS_ABANDONED:
 
2991
                        return alpha;
 
2992
 
 
2993
                      default:
 
2994
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
2995
                }
 
2996
                break;
 
2997
 
 
2998
              case FTS_ABANDONED:
 
2999
                switch (beta->state) {
 
3000
                      case FTS_ACTIVE:
 
3001
                      case FTS_EXPIRED:
 
3002
                        return alpha;
 
3003
 
 
3004
                      case FTS_ABANDONED:
 
3005
                        /* Choose the lease that was abandoned longest ago. */
 
3006
                        if (alpha->hard_lifetime_end_time <
 
3007
                            beta->hard_lifetime_end_time)
 
3008
                                return alpha;
 
3009
 
 
3010
                      default:
 
3011
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3012
                }
 
3013
                break;
 
3014
 
 
3015
              default:
 
3016
                log_fatal("Impossible condition at %s:%d.", MDL);
 
3017
        }
 
3018
 
 
3019
        log_fatal("Triple impossible condition at %s:%d.", MDL);
 
3020
        return NULL;
 
3021
}
 
3022
 
 
3023
/* Process a client-supplied IA_PD.  This may append options to the tail of
 
3024
 * the reply packet being built in the reply_state structure.
 
3025
 */
 
3026
static isc_result_t
 
3027
reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
 
3028
        isc_result_t status = ISC_R_SUCCESS;
 
3029
        u_int32_t iaid;
 
3030
        unsigned ia_cursor;
 
3031
        struct option_state *packet_ia;
 
3032
        struct option_cache *oc;
 
3033
        struct data_string ia_data, data;
 
3034
 
 
3035
        /* Initialize values that will get cleaned up on return. */
 
3036
        packet_ia = NULL;
 
3037
        memset(&ia_data, 0, sizeof(ia_data));
 
3038
        memset(&data, 0, sizeof(data));
 
3039
        /* 
 
3040
         * Note that find_client_prefix() may set reply->lease.
 
3041
         */
 
3042
 
 
3043
        /* Make sure there is at least room for the header. */
 
3044
        if ((reply->cursor + IA_PD_OFFSET + 4) > sizeof(reply->buf)) {
 
3045
                log_error("reply_process_ia_pd: Reply too long for IA.");
 
3046
                return ISC_R_NOSPACE;
 
3047
        }
 
3048
 
 
3049
 
 
3050
        /* Fetch the IA_PD contents. */
 
3051
        if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
 
3052
                                       ia, IA_PD_OFFSET)) {
 
3053
                log_error("reply_process_ia_pd: error evaluating ia");
 
3054
                status = ISC_R_FAILURE;
 
3055
                goto cleanup;
 
3056
        }
 
3057
 
 
3058
        /* Extract IA_PD header contents. */
 
3059
        iaid = getULong(ia_data.data);
 
3060
        reply->renew = getULong(ia_data.data + 4);
 
3061
        reply->rebind = getULong(ia_data.data + 8);
 
3062
 
 
3063
        /* Create an IA_PD structure. */
 
3064
        if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
 
3065
                        reply->client_id.len, MDL) != ISC_R_SUCCESS) {
 
3066
                log_error("reply_process_ia_pd: no memory for ia.");
 
3067
                status = ISC_R_NOMEMORY;
 
3068
                goto cleanup;
 
3069
        }
 
3070
        reply->ia->ia_type = D6O_IA_PD;
 
3071
 
 
3072
        /* Cache pre-existing IA_PD, if any. */
 
3073
        ia_hash_lookup(&reply->old_ia, ia_pd_active,
 
3074
                       (unsigned char *)reply->ia->iaid_duid.data,
 
3075
                       reply->ia->iaid_duid.len, MDL);
 
3076
 
 
3077
        /*
 
3078
         * Create an option cache to carry the IA_PD option contents, and
 
3079
         * execute any user-supplied values into it.
 
3080
         */
 
3081
        if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
3082
                status = ISC_R_NOMEMORY;
 
3083
                goto cleanup;
 
3084
        }
 
3085
 
 
3086
        /* Check & count the fixed prefix host records. */
 
3087
        reply->static_prefixes = 0;
 
3088
        if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
 
3089
                struct iaddrcidrnetlist *fp;
 
3090
 
 
3091
                for (fp = reply->host->fixed_prefix; fp != NULL;
 
3092
                     fp = fp->next) {
 
3093
                        reply->static_prefixes += 1;
 
3094
                }
 
3095
        }
 
3096
 
 
3097
        /*
 
3098
         * Save the cursor position at the start of the IA_PD, so we can
 
3099
         * set length and adjust t1/t2 values later.  We write a temporary
 
3100
         * header out now just in case we decide to adjust the packet
 
3101
         * within sub-process functions.
 
3102
         */
 
3103
        ia_cursor = reply->cursor;
 
3104
 
 
3105
        /* Initialize the IA_PD header.  First the code. */
 
3106
        putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_PD);
 
3107
        reply->cursor += 2;
 
3108
 
 
3109
        /* Then option length. */
 
3110
        putUShort(reply->buf.data + reply->cursor, 0x0Cu);
 
3111
        reply->cursor += 2;
 
3112
 
 
3113
        /* Then IA_PD header contents; IAID. */
 
3114
        putULong(reply->buf.data + reply->cursor, iaid);
 
3115
        reply->cursor += 4;
 
3116
 
 
3117
        /* We store the client's t1 for now, and may over-ride it later. */
 
3118
        putULong(reply->buf.data + reply->cursor, reply->renew);
 
3119
        reply->cursor += 4;
 
3120
 
 
3121
        /* We store the client's t2 for now, and may over-ride it later. */
 
3122
        putULong(reply->buf.data + reply->cursor, reply->rebind);
 
3123
        reply->cursor += 4;
 
3124
 
 
3125
        /* 
 
3126
         * For each prefix in this IA_PD, decide what to do about it.
 
3127
         */
 
3128
        oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
 
3129
        reply->valid = reply->prefer = 0xffffffff;
 
3130
        reply->client_valid = reply->client_prefer = 0;
 
3131
        reply->preflen = -1;
 
3132
        for (; oc != NULL ; oc = oc->next) {
 
3133
                status = reply_process_prefix(reply, oc);
 
3134
 
 
3135
                /*
 
3136
                 * Canceled means we did not allocate prefixes to the
 
3137
                 * client, but we're "done" with this IA - we set a status
 
3138
                 * code.  So transmit this reply, e.g., move on to the next
 
3139
                 * IA.
 
3140
                 */
 
3141
                if (status == ISC_R_CANCELED)
 
3142
                        break;
 
3143
 
 
3144
                if ((status != ISC_R_SUCCESS) && (status != ISC_R_ADDRINUSE))
 
3145
                        goto cleanup;
 
3146
        }
 
3147
 
 
3148
        reply->pd_count++;
 
3149
 
 
3150
        /*
 
3151
         * If we fell through the above and never gave the client
 
3152
         * a prefix, give it one now.
 
3153
         */
 
3154
        if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
 
3155
                status = find_client_prefix(reply);
 
3156
 
 
3157
                if (status == ISC_R_NORESOURCES) {
 
3158
                        switch (reply->packet->dhcpv6_msg_type) {
 
3159
                              case DHCPV6_SOLICIT:
 
3160
                                /*
 
3161
                                 * No prefix for any IA is handled
 
3162
                                 * by the caller.
 
3163
                                 */
 
3164
                                /* FALL THROUGH */
 
3165
 
 
3166
                              case DHCPV6_REQUEST:
 
3167
                                /* Same than for addresses. */
 
3168
                                option_state_dereference(&reply->reply_ia, MDL);
 
3169
                                if (!option_state_allocate(&reply->reply_ia,
 
3170
                                                           MDL))
 
3171
                                {
 
3172
                                        log_error("reply_process_ia_pd: No "
 
3173
                                                  "memory for option state "
 
3174
                                                  "wipe.");
 
3175
                                        status = ISC_R_NOMEMORY;
 
3176
                                        goto cleanup;
 
3177
                                }
 
3178
 
 
3179
                                if (!set_status_code(STATUS_NoPrefixAvail,
 
3180
                                                     "No prefixes available "
 
3181
                                                     "for this interface.",
 
3182
                                                      reply->reply_ia)) {
 
3183
                                        log_error("reply_process_ia_pd: "
 
3184
                                                  "Unable to set "
 
3185
                                                  "NoPrefixAvail status "
 
3186
                                                  "code.");
 
3187
                                        status = ISC_R_FAILURE;
 
3188
                                        goto cleanup;
 
3189
                                }
 
3190
 
 
3191
                                status = ISC_R_SUCCESS;
 
3192
                                break;
 
3193
 
 
3194
                              default:
 
3195
                                if (reply->resources_included)
 
3196
                                        status = ISC_R_SUCCESS;
 
3197
                                else
 
3198
                                        goto cleanup;
 
3199
                                break;
 
3200
                        }
 
3201
                }
 
3202
 
 
3203
                if (status != ISC_R_SUCCESS)
 
3204
                        goto cleanup;
 
3205
        }
 
3206
 
 
3207
        reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
 
3208
                                        sizeof(reply->buf) - reply->cursor,
 
3209
                                        reply->reply_ia, reply->packet,
 
3210
                                        required_opts_IA_PD, NULL);
 
3211
 
 
3212
        /* Reset the length of this IA_PD to match what was just written. */
 
3213
        putUShort(reply->buf.data + ia_cursor + 2,
 
3214
                  reply->cursor - (ia_cursor + 4));
 
3215
 
 
3216
        /*
 
3217
         * T1/T2 time selection is kind of weird.  We actually use DHCP
 
3218
         * (v4) scoped options as handy existing places where these might
 
3219
         * be configured by an administrator.  A value of zero tells the
 
3220
         * client it may choose its own renewal time.
 
3221
         */
 
3222
        reply->renew = 0;
 
3223
        oc = lookup_option(&dhcp_universe, reply->opt_state,
 
3224
                           DHO_DHCP_RENEWAL_TIME);
 
3225
        if (oc != NULL) {
 
3226
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
3227
                                           reply->packet->options,
 
3228
                                           reply->opt_state, &global_scope,
 
3229
                                           oc, MDL) ||
 
3230
                    (data.len != 4)) {
 
3231
                        log_error("Invalid renewal time.");
 
3232
                } else {
 
3233
                        reply->renew = getULong(data.data);
 
3234
                }
 
3235
 
 
3236
                if (data.data != NULL)
 
3237
                        data_string_forget(&data, MDL);
 
3238
        }
 
3239
        putULong(reply->buf.data + ia_cursor + 8, reply->renew);
 
3240
 
 
3241
        /* Now T2. */
 
3242
        reply->rebind = 0;
 
3243
        oc = lookup_option(&dhcp_universe, reply->opt_state,
 
3244
                           DHO_DHCP_REBINDING_TIME);
 
3245
        if (oc != NULL) {
 
3246
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
3247
                                           reply->packet->options,
 
3248
                                           reply->opt_state, &global_scope,
 
3249
                                           oc, MDL) ||
 
3250
                    (data.len != 4)) {
 
3251
                        log_error("Invalid rebinding time.");
 
3252
                } else {
 
3253
                        reply->rebind = getULong(data.data);
 
3254
                }
 
3255
 
 
3256
                if (data.data != NULL)
 
3257
                        data_string_forget(&data, MDL);
 
3258
        }
 
3259
        putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
 
3260
 
 
3261
        /*
 
3262
         * If this is not a 'soft' binding, consume the new changes into
 
3263
         * the database (if any have been attached to the ia_pd).
 
3264
         *
 
3265
         * Loop through the assigned dynamic prefixes, referencing the
 
3266
         * prefixes onto this IA_PD rather than any old ones, and updating
 
3267
         * prefix pool timers for each (if any).
 
3268
         */
 
3269
        if ((status != ISC_R_CANCELED) && (reply->static_prefixes == 0) &&
 
3270
            (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
 
3271
            (reply->ia->num_iasubopt != 0)) {
 
3272
                struct iasubopt *tmp;
 
3273
                struct data_string *ia_id;
 
3274
                int i;
 
3275
 
 
3276
                for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
 
3277
                        tmp = reply->ia->iasubopt[i];
 
3278
 
 
3279
                        if (tmp->ia != NULL)
 
3280
                                ia_dereference(&tmp->ia, MDL);
 
3281
                        ia_reference(&tmp->ia, reply->ia, MDL);
 
3282
 
 
3283
                        /* Commit 'hard' bindings. */
 
3284
                        tmp->hard_lifetime_end_time =
 
3285
                                tmp->soft_lifetime_end_time;
 
3286
                        tmp->soft_lifetime_end_time = 0;
 
3287
                        renew_lease6(tmp->ipv6_pool, tmp);
 
3288
                        schedule_lease_timeout(tmp->ipv6_pool);
 
3289
                }
 
3290
 
 
3291
                /* Remove any old ia from the hash. */
 
3292
                if (reply->old_ia != NULL) {
 
3293
                        ia_id = &reply->old_ia->iaid_duid;
 
3294
                        ia_hash_delete(ia_pd_active,
 
3295
                                       (unsigned char *)ia_id->data,
 
3296
                                       ia_id->len, MDL);
 
3297
                        ia_dereference(&reply->old_ia, MDL);
 
3298
                }
 
3299
 
 
3300
                /* Put new ia into the hash. */
 
3301
                reply->ia->cltt = cur_time;
 
3302
                ia_id = &reply->ia->iaid_duid;
 
3303
                ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
 
3304
                            ia_id->len, reply->ia, MDL);
 
3305
 
 
3306
                write_ia(reply->ia);
 
3307
        }
 
3308
 
 
3309
      cleanup:
 
3310
        if (packet_ia != NULL)
 
3311
                option_state_dereference(&packet_ia, MDL);
 
3312
        if (reply->reply_ia != NULL)
 
3313
                option_state_dereference(&reply->reply_ia, MDL);
 
3314
        if (ia_data.data != NULL)
 
3315
                data_string_forget(&ia_data, MDL);
 
3316
        if (data.data != NULL)
 
3317
                data_string_forget(&data, MDL);
 
3318
        if (reply->ia != NULL)
 
3319
                ia_dereference(&reply->ia, MDL);
 
3320
        if (reply->old_ia != NULL)
 
3321
                ia_dereference(&reply->old_ia, MDL);
 
3322
        if (reply->lease != NULL)
 
3323
                iasubopt_dereference(&reply->lease, MDL);
 
3324
 
 
3325
        /*
 
3326
         * ISC_R_CANCELED is a status code used by the prefix processing to
 
3327
         * indicate we're replying with a status code.  This is still a
 
3328
         * success at higher layers.
 
3329
         */
 
3330
        return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
 
3331
}
 
3332
 
 
3333
/*
 
3334
 * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply
 
3335
 * contents into the reply's current ia_pd-scoped option cache.  Returns
 
3336
 * ISC_R_CANCELED in the event we are replying with a status code and do
 
3337
 * not wish to process more IAPREFIXes within this IA_PD.
 
3338
 */
 
3339
static isc_result_t
 
3340
reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
 
3341
        u_int32_t pref_life, valid_life;
 
3342
        struct binding_scope **scope;
 
3343
        struct group *group;
 
3344
        struct iaddrcidrnet tmp_pref;
 
3345
        struct option_cache *oc;
 
3346
        struct data_string iapref, data;
 
3347
        isc_result_t status = ISC_R_SUCCESS;
 
3348
 
 
3349
        /* Initializes values that will be cleaned up. */
 
3350
        memset(&iapref, 0, sizeof(iapref));
 
3351
        memset(&data, 0, sizeof(data));
 
3352
        /* Note that reply->lease may be set by prefix_is_owned() */
 
3353
 
 
3354
        /*
 
3355
         * There is no point trying to process an incoming prefix if there
 
3356
         * is no room for an outgoing prefix.
 
3357
         */
 
3358
        if ((reply->cursor + 29) > sizeof(reply->buf)) {
 
3359
                log_error("reply_process_prefix: Out of room for prefix.");
 
3360
                return ISC_R_NOSPACE;
 
3361
        }
 
3362
 
 
3363
        /* Extract this IAPREFIX option. */
 
3364
        if (!evaluate_option_cache(&iapref, reply->packet, NULL, NULL, 
 
3365
                                   reply->packet->options, NULL, &global_scope,
 
3366
                                   pref, MDL) ||
 
3367
            (iapref.len < IAPREFIX_OFFSET)) {
 
3368
                log_error("reply_process_prefix: error evaluating IAPREFIX.");
 
3369
                status = ISC_R_FAILURE;
 
3370
                goto cleanup;
 
3371
        }
 
3372
 
 
3373
        /*
 
3374
         * Layout: preferred and valid lifetimes followed by the prefix
 
3375
         * length and the IPv6 address.
 
3376
         */
 
3377
        pref_life = getULong(iapref.data);
 
3378
        valid_life = getULong(iapref.data + 4);
 
3379
 
 
3380
        if ((reply->client_valid == 0) ||
 
3381
            (reply->client_valid > valid_life))
 
3382
                reply->client_valid = valid_life;
 
3383
 
 
3384
        if ((reply->client_prefer == 0) ||
 
3385
            (reply->client_prefer > pref_life))
 
3386
                reply->client_prefer = pref_life;
 
3387
 
 
3388
        /* 
 
3389
         * Clients may choose to send ::/0 as a prefix, with the idea to give
 
3390
         * hints about preferred-lifetime or valid-lifetime.
 
3391
         */
 
3392
        tmp_pref.lo_addr.len = 16;
 
3393
        memset(tmp_pref.lo_addr.iabuf, 0, 16);
 
3394
        if ((iapref.data[8] == 0) &&
 
3395
            (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
 
3396
                /* Status remains success; we just ignore this one. */
 
3397
                goto cleanup;
 
3398
        }
 
3399
 
 
3400
        /*
 
3401
         * Clients may choose to send ::/X as a prefix to specify a
 
3402
         * preferred/requested prefix length. Note X is never zero here.
 
3403
         */
 
3404
        tmp_pref.bits = (int) iapref.data[8];
 
3405
        if (reply->preflen < 0) {
 
3406
                /* Cache the first preferred prefix length. */
 
3407
                reply->preflen = tmp_pref.bits;
 
3408
        }
 
3409
        if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
 
3410
                goto cleanup;
 
3411
        }
 
3412
 
 
3413
        memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
 
3414
 
 
3415
        /* Verify the prefix belongs to the client. */
 
3416
        if (!prefix_is_owned(reply, &tmp_pref)) {
 
3417
                /* Same than for addresses. */
 
3418
                if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
 
3419
                    (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
 
3420
                    (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
 
3421
                        status = reply_process_try_prefix(reply, &tmp_pref);
 
3422
 
 
3423
                        /* Either error out or skip this prefix. */
 
3424
                        if ((status != ISC_R_SUCCESS) && 
 
3425
                            (status != ISC_R_ADDRINUSE)) 
 
3426
                                goto cleanup;
 
3427
 
 
3428
                        if (reply->lease == NULL) {
 
3429
                                if (reply->packet->dhcpv6_msg_type ==
 
3430
                                                        DHCPV6_REBIND) {
 
3431
                                        reply->send_prefer = 0;
 
3432
                                        reply->send_valid = 0;
 
3433
                                        goto send_pref;
 
3434
                                }
 
3435
 
 
3436
                                /* status remains success - ignore */
 
3437
                                goto cleanup;
 
3438
                        }
 
3439
                /*
 
3440
                 * RFC3633 section 18.2.3:
 
3441
                 *
 
3442
                 * If the delegating router cannot find a binding
 
3443
                 * for the requesting router's IA_PD the delegating
 
3444
                 * router returns the IA_PD containing no prefixes
 
3445
                 * with a Status Code option set to NoBinding in the
 
3446
                 * Reply message.
 
3447
                 *
 
3448
                 * On mismatch we (ab)use this pretending we have not the IA
 
3449
                 * as soon as we have not a prefix.
 
3450
                 */
 
3451
                } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
 
3452
                        /* Rewind the IA_PD to empty. */
 
3453
                        option_state_dereference(&reply->reply_ia, MDL);
 
3454
                        if (!option_state_allocate(&reply->reply_ia, MDL)) {
 
3455
                                log_error("reply_process_prefix: No memory "
 
3456
                                          "for option state wipe.");
 
3457
                                status = ISC_R_NOMEMORY;
 
3458
                                goto cleanup;
 
3459
                        }
 
3460
 
 
3461
                        /* Append a NoBinding status code.  */
 
3462
                        if (!set_status_code(STATUS_NoBinding,
 
3463
                                             "Prefix not bound to this "
 
3464
                                             "interface.", reply->reply_ia)) {
 
3465
                                log_error("reply_process_prefix: Unable to "
 
3466
                                          "attach status code.");
 
3467
                                status = ISC_R_FAILURE;
 
3468
                                goto cleanup;
 
3469
                        }
 
3470
 
 
3471
                        /* Fin (no more IAPREFIXes). */
 
3472
                        status = ISC_R_CANCELED;
 
3473
                        goto cleanup;
 
3474
                } else {
 
3475
                        log_error("It is impossible to lease a client that is "
 
3476
                                  "not sending a solicit, request, renew, or "
 
3477
                                  "rebind message.");
 
3478
                        status = ISC_R_FAILURE;
 
3479
                        goto cleanup;
 
3480
                }
 
3481
        }
 
3482
 
 
3483
        if (reply->static_prefixes > 0) {
 
3484
                if (reply->host == NULL)
 
3485
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3486
 
 
3487
                scope = &global_scope;
 
3488
                group = reply->host->group;
 
3489
        } else {
 
3490
                if (reply->lease == NULL)
 
3491
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3492
 
 
3493
                scope = &reply->lease->scope;
 
3494
                group = reply->shared->group;
 
3495
        }
 
3496
 
 
3497
        /*
 
3498
         * If client_resources is nonzero, then the reply_process_is_prefixed
 
3499
         * function has executed configuration state into the reply option
 
3500
         * cache.  We will use that valid cache to derive configuration for
 
3501
         * whether or not to engage in additional prefixes, and similar.
 
3502
         */
 
3503
        if (reply->client_resources != 0) {
 
3504
                unsigned limit = 1;
 
3505
 
 
3506
                /*
 
3507
                 * Does this client have "enough" prefixes already?  Default
 
3508
                 * to one.  Everybody gets one, and one should be enough for
 
3509
                 * anybody.
 
3510
                 */
 
3511
                oc = lookup_option(&server_universe, reply->opt_state,
 
3512
                                   SV_LIMIT_PREFS_PER_IA);
 
3513
                if (oc != NULL) {
 
3514
                        if (!evaluate_option_cache(&data, reply->packet,
 
3515
                                                   NULL, NULL,
 
3516
                                                   reply->packet->options,
 
3517
                                                   reply->opt_state,
 
3518
                                                   scope, oc, MDL) ||
 
3519
                            (data.len != 4)) {
 
3520
                                log_error("reply_process_prefix: unable to "
 
3521
                                          "evaluate prefs-per-ia value.");
 
3522
                                status = ISC_R_FAILURE;
 
3523
                                goto cleanup;
 
3524
                        }
 
3525
 
 
3526
                        limit = getULong(data.data);
 
3527
                        data_string_forget(&data, MDL);
 
3528
                }
 
3529
 
 
3530
                /*
 
3531
                 * If we wish to limit the client to a certain number of
 
3532
                 * prefixes, then omit the prefix from the reply.
 
3533
                 */
 
3534
                if (reply->client_resources >= limit)
 
3535
                        goto cleanup;
 
3536
        }
 
3537
 
 
3538
        status = reply_process_is_prefixed(reply, scope, group);
 
3539
        if (status != ISC_R_SUCCESS)
 
3540
                goto cleanup;
 
3541
 
 
3542
      send_pref:
 
3543
        status = reply_process_send_prefix(reply, &tmp_pref);
 
3544
 
 
3545
      cleanup:
 
3546
        if (iapref.data != NULL)
 
3547
                data_string_forget(&iapref, MDL);
 
3548
        if (data.data != NULL)
 
3549
                data_string_forget(&data, MDL);
 
3550
        if (reply->lease != NULL)
 
3551
                iasubopt_dereference(&reply->lease, MDL);
 
3552
 
 
3553
        return status;
 
3554
}
 
3555
 
 
3556
/*
 
3557
 * Verify the prefix belongs to the client.  If we've got a host
 
3558
 * record with fixed prefixes, it has to be an assigned prefix
 
3559
 * (fault out all else).  Otherwise it's a dynamic prefix, so lookup
 
3560
 * that prefix and make sure it belongs to this DUID:IAID pair.
 
3561
 */
 
3562
static isc_boolean_t
 
3563
prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
 
3564
        struct iaddrcidrnetlist *l;
 
3565
        int i;
 
3566
 
 
3567
        /*
 
3568
         * This faults out prefixes that don't match fixed prefixes.
 
3569
         */
 
3570
        if (reply->static_prefixes > 0) {
 
3571
                for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
 
3572
                        if ((pref->bits == l->cidrnet.bits) &&
 
3573
                            (memcmp(pref->lo_addr.iabuf,
 
3574
                                    l->cidrnet.lo_addr.iabuf, 16) == 0))
 
3575
                                return ISC_TRUE;
 
3576
                }
 
3577
                return ISC_FALSE;
 
3578
        }
 
3579
 
 
3580
        if ((reply->old_ia == NULL) ||
 
3581
            (reply->old_ia->num_iasubopt == 0))
 
3582
                return ISC_FALSE;
 
3583
 
 
3584
        for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
 
3585
                struct iasubopt *tmp;
 
3586
 
 
3587
                tmp = reply->old_ia->iasubopt[i];
 
3588
 
 
3589
                if ((pref->bits == (int) tmp->plen) &&
 
3590
                    memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0) {
 
3591
                        iasubopt_reference(&reply->lease, tmp, MDL);
 
3592
                        return ISC_TRUE;
 
3593
                }
 
3594
        }
 
3595
 
 
3596
        return ISC_FALSE;
 
3597
}
 
3598
 
 
3599
/*
 
3600
 * This function only returns failure on 'hard' failures.  If it succeeds,
 
3601
 * it will leave a prefix structure behind.
 
3602
 */
 
3603
static isc_result_t
 
3604
reply_process_try_prefix(struct reply_state *reply,
 
3605
                         struct iaddrcidrnet *pref) {
 
3606
        isc_result_t status = ISC_R_NORESOURCES;
 
3607
        struct ipv6_pool *pool;
 
3608
        int i;
 
3609
        struct data_string data_pref;
 
3610
 
 
3611
        if ((reply == NULL) || (reply->shared == NULL) ||
 
3612
            (reply->shared->ipv6_pools == NULL) || (pref == NULL) ||
 
3613
            (reply->lease != NULL))
 
3614
                return ISC_R_INVALIDARG;
 
3615
 
 
3616
        memset(&data_pref, 0, sizeof(data_pref));
 
3617
        data_pref.len = 17;
 
3618
        if (!buffer_allocate(&data_pref.buffer, data_pref.len, MDL)) {
 
3619
                log_error("reply_process_try_prefix: out of memory.");
 
3620
                return ISC_R_NOMEMORY;
 
3621
        }
 
3622
        data_pref.data = data_pref.buffer->data;
 
3623
        data_pref.buffer->data[0] = (u_int8_t) pref->bits;
 
3624
        memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
 
3625
 
 
3626
        for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
 
3627
                if (pool->pool_type != D6O_IA_PD)
 
3628
                        continue;
 
3629
                status = try_client_v6_prefix(&reply->lease, pool,
 
3630
                                              &data_pref);
 
3631
                if (status == ISC_R_SUCCESS)
 
3632
                        break;
 
3633
        }
 
3634
 
 
3635
        data_string_forget(&data_pref, MDL);
 
3636
        /* Return just the most recent status... */
 
3637
        return status;
 
3638
}
 
3639
 
 
3640
/* Look around for a prefix to give the client.  First, look through the old
 
3641
 * IA_PD for prefixes we can extend.  Second, try to allocate a new prefix.
 
3642
 * Finally, actually add that prefix into the current reply IA_PD.
 
3643
 */
 
3644
static isc_result_t
 
3645
find_client_prefix(struct reply_state *reply) {
 
3646
        struct iaddrcidrnet send_pref;
 
3647
        isc_result_t status = ISC_R_NORESOURCES;
 
3648
        struct iasubopt *prefix, *best_prefix = NULL;
 
3649
        struct binding_scope **scope;
 
3650
        struct group *group;
 
3651
        int i;
 
3652
 
 
3653
        if (reply->host != NULL)
 
3654
                group = reply->host->group;
 
3655
        else
 
3656
                group = reply->shared->group;
 
3657
 
 
3658
        if (reply->static_prefixes > 0) {
 
3659
                struct iaddrcidrnetlist *l;
 
3660
 
 
3661
                if (reply->host == NULL)
 
3662
                        return ISC_R_INVALIDARG;
 
3663
 
 
3664
                for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
 
3665
                        if (l->cidrnet.bits == reply->preflen)
 
3666
                                break;
 
3667
                }
 
3668
                if (l == NULL) {
 
3669
                        /*
 
3670
                         * If no fixed prefix has the preferred length,
 
3671
                         * get the first one.
 
3672
                         */
 
3673
                        l = reply->host->fixed_prefix;
 
3674
                }
 
3675
                memcpy(&send_pref, &l->cidrnet, sizeof(send_pref));
 
3676
 
 
3677
                status = ISC_R_SUCCESS;
 
3678
                scope = &global_scope;
 
3679
                goto send_pref;
 
3680
        }
 
3681
 
 
3682
        if (reply->old_ia != NULL)  {
 
3683
                for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
 
3684
                        prefix = reply->old_ia->iasubopt[i];
 
3685
 
 
3686
                        best_prefix = prefix_compare(reply, prefix,
 
3687
                                                     best_prefix);
 
3688
                }
 
3689
        }
 
3690
 
 
3691
        /* Try to pick a new prefix if we didn't find one, or if we found an
 
3692
         * abandoned prefix.
 
3693
         */
 
3694
        if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
 
3695
                status = pick_v6_prefix(&reply->lease, reply->preflen,
 
3696
                                        reply->shared, &reply->client_id);
 
3697
        } else if (best_prefix != NULL) {
 
3698
                iasubopt_reference(&reply->lease, best_prefix, MDL);
 
3699
                status = ISC_R_SUCCESS;
 
3700
        }
 
3701
 
 
3702
        /* Pick the abandoned prefix as a last resort. */
 
3703
        if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
 
3704
                /* I don't see how this is supposed to be done right now. */
 
3705
                log_error("Reclaiming abandoned prefixes is not yet "
 
3706
                          "supported.  Treating this as an out of space "
 
3707
                          "condition.");
 
3708
                /* iasubopt_reference(&reply->lease, best_prefix, MDL); */
 
3709
        }
 
3710
 
 
3711
        /* Give up now if we didn't find a prefix. */
 
3712
        if (status != ISC_R_SUCCESS)
 
3713
                return status;
 
3714
 
 
3715
        if (reply->lease == NULL)
 
3716
                log_fatal("Impossible condition at %s:%d.", MDL);
 
3717
 
 
3718
        scope = &reply->lease->scope;
 
3719
        group = reply->shared->group;
 
3720
 
 
3721
        send_pref.lo_addr.len = 16;
 
3722
        memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
 
3723
        send_pref.bits = (int) reply->lease->plen;
 
3724
 
 
3725
      send_pref:
 
3726
        status = reply_process_is_prefixed(reply, scope, group);
 
3727
        if (status != ISC_R_SUCCESS)
 
3728
                return status;
 
3729
 
 
3730
        status = reply_process_send_prefix(reply, &send_pref);
 
3731
        return status;
 
3732
}
 
3733
 
 
3734
/* Once a prefix is found for a client, perform several common functions;
 
3735
 * Calculate and store valid and preferred prefix times, draw client options
 
3736
 * into the option state.
 
3737
 */
 
3738
static isc_result_t
 
3739
reply_process_is_prefixed(struct reply_state *reply,
 
3740
                          struct binding_scope **scope, struct group *group)
 
3741
{
 
3742
        isc_result_t status = ISC_R_SUCCESS;
 
3743
        struct data_string data;
 
3744
        struct option_cache *oc;
 
3745
 
 
3746
        /* Initialize values we will cleanup. */
 
3747
        memset(&data, 0, sizeof(data));
 
3748
 
 
3749
        /* Execute relevant options into root scope. */
 
3750
        execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
 
3751
                                    reply->packet->options, reply->opt_state,
 
3752
                                    scope, group, root_group);
 
3753
 
 
3754
        /* Determine valid lifetime. */
 
3755
        if (reply->client_valid == 0)
 
3756
                reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
 
3757
        else
 
3758
                reply->send_valid = reply->client_valid;
 
3759
 
 
3760
        oc = lookup_option(&server_universe, reply->opt_state,
 
3761
                           SV_DEFAULT_LEASE_TIME);
 
3762
        if (oc != NULL) {
 
3763
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
3764
                                           reply->packet->options,
 
3765
                                           reply->opt_state,
 
3766
                                           scope, oc, MDL) ||
 
3767
                    (data.len != 4)) {
 
3768
                        log_error("reply_process_is_prefixed: unable to "
 
3769
                                  "evaluate default prefix time");
 
3770
                        status = ISC_R_FAILURE;
 
3771
                        goto cleanup;
 
3772
                }
 
3773
 
 
3774
                reply->send_valid = getULong(data.data);
 
3775
                data_string_forget(&data, MDL);
 
3776
        }
 
3777
 
 
3778
        if (reply->client_prefer == 0)
 
3779
                reply->send_prefer = reply->send_valid;
 
3780
        else
 
3781
                reply->send_prefer = reply->client_prefer;
 
3782
 
 
3783
        if (reply->send_prefer >= reply->send_valid)
 
3784
                reply->send_prefer = (reply->send_valid / 2) +
 
3785
                                     (reply->send_valid / 8);
 
3786
 
 
3787
        oc = lookup_option(&server_universe, reply->opt_state,
 
3788
                           SV_PREFER_LIFETIME);
 
3789
        if (oc != NULL) {
 
3790
                if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
 
3791
                                           reply->packet->options,
 
3792
                                           reply->opt_state,
 
3793
                                           scope, oc, MDL) ||
 
3794
                    (data.len != 4)) {
 
3795
                        log_error("reply_process_is_prefixed: unable to "
 
3796
                                  "evaluate preferred prefix time");
 
3797
                        status = ISC_R_FAILURE;
 
3798
                        goto cleanup;
 
3799
                }
 
3800
 
 
3801
                reply->send_prefer = getULong(data.data);
 
3802
                data_string_forget(&data, MDL);
 
3803
        }
 
3804
 
 
3805
        /* Note lowest values for later calculation of renew/rebind times. */
 
3806
        if (reply->prefer > reply->send_prefer)
 
3807
                reply->prefer = reply->send_prefer;
 
3808
 
 
3809
        if (reply->valid > reply->send_valid)
 
3810
                reply->valid = reply->send_valid;
 
3811
 
 
3812
        /* Perform dynamic prefix related update work. */
 
3813
        if (reply->lease != NULL) {
 
3814
                /* Cached lifetimes */
 
3815
                reply->lease->prefer = reply->send_prefer;
 
3816
                reply->lease->valid = reply->send_valid;
 
3817
 
 
3818
                /* Advance (or rewind) the valid lifetime. */
 
3819
                if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
 
3820
                        reply->lease->soft_lifetime_end_time =
 
3821
                                cur_time + reply->send_valid;
 
3822
                        /* Wait before renew! */
 
3823
                }
 
3824
 
 
3825
                status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
 
3826
                if (status != ISC_R_SUCCESS) {
 
3827
                        log_fatal("reply_process_is_prefixed: Unable to "
 
3828
                                  "attach prefix to new IA_PD: %s",
 
3829
                                  isc_result_totext(status));
 
3830
                }
 
3831
 
 
3832
                /*
 
3833
                 * If this is a new prefix, make sure it is attached somewhere.
 
3834
                 */
 
3835
                if (reply->lease->ia == NULL) {
 
3836
                        ia_reference(&reply->lease->ia, reply->ia, MDL);
 
3837
                }
 
3838
        }
 
3839
 
 
3840
        /* Bring a copy of the relevant options into the IA_PD scope. */
 
3841
        execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
 
3842
                                    reply->packet->options, reply->reply_ia,
 
3843
                                    scope, group, root_group);
 
3844
 
 
3845
      cleanup:
 
3846
        if (data.data != NULL)
 
3847
                data_string_forget(&data, MDL);
 
3848
 
 
3849
        if (status == ISC_R_SUCCESS)
 
3850
                reply->client_resources++;
 
3851
 
 
3852
        return status;
 
3853
}
 
3854
 
 
3855
/* Simply send an IAPREFIX within the IA_PD scope as described. */
 
3856
static isc_result_t
 
3857
reply_process_send_prefix(struct reply_state *reply,
 
3858
                          struct iaddrcidrnet *pref) {
 
3859
        isc_result_t status = ISC_R_SUCCESS;
 
3860
        struct data_string data;
 
3861
 
 
3862
        memset(&data, 0, sizeof(data));
 
3863
 
 
3864
        /* Now append the prefix. */
 
3865
        data.len = IAPREFIX_OFFSET;
 
3866
        if (!buffer_allocate(&data.buffer, data.len, MDL)) {
 
3867
                log_error("reply_process_send_prefix: out of memory"
 
3868
                          "allocating new IAPREFIX buffer.");
 
3869
                status = ISC_R_NOMEMORY;
 
3870
                goto cleanup;
 
3871
        }
 
3872
        data.data = data.buffer->data;
 
3873
 
 
3874
        putULong(data.buffer->data, reply->send_prefer);
 
3875
        putULong(data.buffer->data + 4, reply->send_valid);
 
3876
        data.buffer->data[8] = pref->bits;
 
3877
        memcpy(data.buffer->data + 9, pref->lo_addr.iabuf, 16);
 
3878
 
 
3879
        if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
 
3880
                                  data.buffer, data.buffer->data,
 
3881
                                  data.len, D6O_IAPREFIX, 0)) {
 
3882
                log_error("reply_process_send_prefix: unable "
 
3883
                          "to save IAPREFIX option");
 
3884
                status = ISC_R_FAILURE;
 
3885
                goto cleanup;
 
3886
        }
 
3887
 
 
3888
        reply->resources_included = ISC_TRUE;
 
3889
 
 
3890
      cleanup:
 
3891
        if (data.data != NULL)
 
3892
                data_string_forget(&data, MDL);
 
3893
 
 
3894
        return status;
 
3895
}
 
3896
 
 
3897
/* Choose the better of two prefixes. */
 
3898
static struct iasubopt *
 
3899
prefix_compare(struct reply_state *reply,
 
3900
               struct iasubopt *alpha, struct iasubopt *beta) {
 
3901
        if (alpha == NULL)
 
3902
                return beta;
 
3903
        if (beta == NULL)
 
3904
                return alpha;
 
3905
 
 
3906
        if (reply->preflen >= 0) {
 
3907
                if ((alpha->plen == reply->preflen) &&
 
3908
                    (beta->plen != reply->preflen))
 
3909
                        return alpha;
 
3910
                if ((beta->plen == reply->preflen) &&
 
3911
                    (alpha->plen != reply->preflen))
 
3912
                        return beta;
 
3913
        }
 
3914
 
 
3915
        switch(alpha->state) {
 
3916
              case FTS_ACTIVE:
 
3917
                switch(beta->state) {
 
3918
                      case FTS_ACTIVE:
 
3919
                        /* Choose the prefix with the longest lifetime (most
 
3920
                         * likely the most recently allocated).
 
3921
                         */
 
3922
                        if (alpha->hard_lifetime_end_time < 
 
3923
                            beta->hard_lifetime_end_time)
 
3924
                                return beta;
 
3925
                        else
 
3926
                                return alpha;
 
3927
 
 
3928
                      case FTS_EXPIRED:
 
3929
                      case FTS_ABANDONED:
 
3930
                        return alpha;
 
3931
 
 
3932
                      default:
 
3933
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3934
                }
 
3935
                break;
 
3936
 
 
3937
              case FTS_EXPIRED:
 
3938
                switch (beta->state) {
 
3939
                      case FTS_ACTIVE:
 
3940
                        return beta;
 
3941
 
 
3942
                      case FTS_EXPIRED:
 
3943
                        /* Choose the most recently expired prefix. */
 
3944
                        if (alpha->hard_lifetime_end_time <
 
3945
                            beta->hard_lifetime_end_time)
 
3946
                                return beta;
 
3947
                        else if ((alpha->hard_lifetime_end_time ==
 
3948
                                  beta->hard_lifetime_end_time) &&
 
3949
                                 (alpha->soft_lifetime_end_time <
 
3950
                                  beta->soft_lifetime_end_time))
 
3951
                                return beta;
 
3952
                        else
 
3953
                                return alpha;
 
3954
 
 
3955
                      case FTS_ABANDONED:
 
3956
                        return alpha;
 
3957
 
 
3958
                      default:
 
3959
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3960
                }
 
3961
                break;
 
3962
 
 
3963
              case FTS_ABANDONED:
 
3964
                switch (beta->state) {
 
3965
                      case FTS_ACTIVE:
 
3966
                      case FTS_EXPIRED:
 
3967
                        return alpha;
 
3968
 
 
3969
                      case FTS_ABANDONED:
 
3970
                        /* Choose the prefix that was abandoned longest ago. */
 
3971
                        if (alpha->hard_lifetime_end_time <
 
3972
                            beta->hard_lifetime_end_time)
 
3973
                                return alpha;
 
3974
 
 
3975
                      default:
 
3976
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
3977
                }
 
3978
                break;
 
3979
 
 
3980
              default:
 
3981
                log_fatal("Impossible condition at %s:%d.", MDL);
 
3982
        }
 
3983
 
 
3984
        log_fatal("Triple impossible condition at %s:%d.", MDL);
 
3985
        return NULL;
 
3986
}
 
3987
 
 
3988
/*
 
3989
 * Solicit is how a client starts requesting addresses.
 
3990
 *
 
3991
 * If the client asks for rapid commit, and we support it, we will 
 
3992
 * allocate the addresses and reply.
 
3993
 *
 
3994
 * Otherwise we will send an advertise message.
 
3995
 */
 
3996
 
 
3997
static void
 
3998
dhcpv6_solicit(struct data_string *reply_ret, struct packet *packet) {
 
3999
        struct data_string client_id;
 
4000
 
 
4001
        /* 
 
4002
         * Validate our input.
 
4003
         */
 
4004
        if (!valid_client_msg(packet, &client_id)) {
 
4005
                return;
 
4006
        }
 
4007
 
 
4008
        lease_to_client(reply_ret, packet, &client_id, NULL);
 
4009
 
 
4010
        /*
 
4011
         * Clean up.
 
4012
         */
 
4013
        data_string_forget(&client_id, MDL);
 
4014
}
 
4015
 
 
4016
/*
 
4017
 * Request is how a client actually requests addresses.
 
4018
 *
 
4019
 * Very similar to Solicit handling, except the server DUID is required.
 
4020
 */
 
4021
 
 
4022
/* TODO: reject unicast messages, unless we set unicast option */
 
4023
static void
 
4024
dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
 
4025
        struct data_string client_id;
 
4026
        struct data_string server_id;
 
4027
 
 
4028
        /*
 
4029
         * Validate our input.
 
4030
         */
 
4031
        if (!valid_client_resp(packet, &client_id, &server_id)) {
 
4032
                return;
 
4033
        }
 
4034
 
 
4035
        /*
 
4036
         * Issue our lease.
 
4037
         */
 
4038
        lease_to_client(reply_ret, packet, &client_id, &server_id);
 
4039
 
 
4040
        /*
 
4041
         * Cleanup.
 
4042
         */
 
4043
        data_string_forget(&client_id, MDL);
 
4044
        data_string_forget(&server_id, MDL);
 
4045
}
 
4046
 
 
4047
/* Find a DHCPv6 packet's shared network from hints in the packet.
 
4048
 */
 
4049
static isc_result_t
 
4050
shared_network_from_packet6(struct shared_network **shared,
 
4051
                            struct packet *packet)
 
4052
{
 
4053
        const struct packet *chk_packet;
 
4054
        const struct in6_addr *link_addr, *first_link_addr;
 
4055
        struct iaddr tmp_addr;
 
4056
        struct subnet *subnet;
 
4057
        isc_result_t status;
 
4058
 
 
4059
        if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
 
4060
                return ISC_R_INVALIDARG;
 
4061
 
 
4062
        /*
 
4063
         * First, find the link address where the packet from the client
 
4064
         * first appeared (if this packet was relayed).
 
4065
         */
 
4066
        first_link_addr = NULL;
 
4067
        chk_packet = packet->dhcpv6_container_packet;
 
4068
        while (chk_packet != NULL) {
 
4069
                link_addr = &chk_packet->dhcpv6_link_address;
 
4070
                if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
 
4071
                    !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
 
4072
                        first_link_addr = link_addr;
 
4073
                        break;
 
4074
                }
 
4075
                chk_packet = chk_packet->dhcpv6_container_packet;
 
4076
        }
 
4077
 
 
4078
        /*
 
4079
         * If there is a relayed link address, find the subnet associated
 
4080
         * with that, and use that to get the appropriate
 
4081
         * shared_network.
 
4082
         */
 
4083
        if (first_link_addr != NULL) {
 
4084
                tmp_addr.len = sizeof(*first_link_addr);
 
4085
                memcpy(tmp_addr.iabuf,
 
4086
                       first_link_addr, sizeof(*first_link_addr));
 
4087
                subnet = NULL;
 
4088
                if (!find_subnet(&subnet, tmp_addr, MDL)) {
 
4089
                        log_debug("No subnet found for link-address %s.",
 
4090
                                  piaddr(tmp_addr));
 
4091
                        return ISC_R_NOTFOUND;
 
4092
                }
 
4093
                status = shared_network_reference(shared,
 
4094
                                                  subnet->shared_network, MDL);
 
4095
                subnet_dereference(&subnet, MDL);
 
4096
 
 
4097
        /*
 
4098
         * If there is no link address, we will use the interface
 
4099
         * that this packet came in on to pick the shared_network.
 
4100
         */
 
4101
        } else {
 
4102
                status = shared_network_reference(shared,
 
4103
                                         packet->interface->shared_network,
 
4104
                                         MDL);
 
4105
        }
 
4106
 
 
4107
        return status;
 
4108
}
 
4109
 
 
4110
/*
 
4111
 * When a client thinks it might be on a new link, it sends a 
 
4112
 * Confirm message.
 
4113
 *
 
4114
 * From RFC3315 section 18.2.2:
 
4115
 *
 
4116
 *   When the server receives a Confirm message, the server determines
 
4117
 *   whether the addresses in the Confirm message are appropriate for the
 
4118
 *   link to which the client is attached.  If all of the addresses in the
 
4119
 *   Confirm message pass this test, the server returns a status of
 
4120
 *   Success.  If any of the addresses do not pass this test, the server
 
4121
 *   returns a status of NotOnLink.  If the server is unable to perform
 
4122
 *   this test (for example, the server does not have information about
 
4123
 *   prefixes on the link to which the client is connected), or there were
 
4124
 *   no addresses in any of the IAs sent by the client, the server MUST
 
4125
 *   NOT send a reply to the client.
 
4126
 */
 
4127
 
 
4128
static void
 
4129
dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
 
4130
        struct shared_network *shared;
 
4131
        struct subnet *subnet;
 
4132
        struct option_cache *ia, *ta, *oc;
 
4133
        struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
 
4134
        struct option_state *cli_enc_opt_state, *opt_state;
 
4135
        struct iaddr cli_addr;
 
4136
        int pass;
 
4137
        isc_boolean_t inappropriate, has_addrs;
 
4138
        char reply_data[65536];
 
4139
        struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
 
4140
        int reply_ofs = (int)((char *)reply->options - (char *)reply);
 
4141
 
 
4142
        /* 
 
4143
         * Basic client message validation.
 
4144
         */
 
4145
        memset(&client_id, 0, sizeof(client_id));
 
4146
        if (!valid_client_msg(packet, &client_id)) {
 
4147
                return;
 
4148
        }
 
4149
 
 
4150
        /*
 
4151
         * Do not process Confirms that do not have IA's we do not recognize.
 
4152
         */
 
4153
        ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
 
4154
        ta = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
 
4155
        if ((ia == NULL) && (ta == NULL))
 
4156
                return;
 
4157
 
 
4158
        /*
 
4159
         * IA_PD's are simply ignored.
 
4160
         */
 
4161
        delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
 
4162
 
 
4163
        /* 
 
4164
         * Bit of variable initialization.
 
4165
         */
 
4166
        opt_state = cli_enc_opt_state = NULL;
 
4167
        memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
 
4168
        memset(&iaaddr, 0, sizeof(iaaddr));
 
4169
        memset(&packet_oro, 0, sizeof(packet_oro));
 
4170
 
 
4171
        /* Determine what shared network the client is connected to.  We
 
4172
         * must not respond if we don't have any information about the
 
4173
         * network the client is on.
 
4174
         */
 
4175
        shared = NULL;
 
4176
        if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
 
4177
            (shared == NULL))
 
4178
                goto exit;
 
4179
 
 
4180
        /* If there are no recorded subnets, then we have no
 
4181
         * information about this subnet - ignore Confirms.
 
4182
         */
 
4183
        subnet = shared->subnets;
 
4184
        if (subnet == NULL)
 
4185
                goto exit;
 
4186
 
 
4187
        /* Are the addresses in all the IA's appropriate for that link? */
 
4188
        has_addrs = inappropriate = ISC_FALSE;
 
4189
        pass = D6O_IA_NA;
 
4190
        while(!inappropriate) {
 
4191
                /* If we've reached the end of the IA_NA pass, move to the
 
4192
                 * IA_TA pass.
 
4193
                 */
 
4194
                if ((pass == D6O_IA_NA) && (ia == NULL)) {
 
4195
                        pass = D6O_IA_TA;
 
4196
                        ia = ta;
 
4197
                }
 
4198
 
 
4199
                /* If we've reached the end of all passes, we're done. */
 
4200
                if (ia == NULL)
 
4201
                        break;
 
4202
 
 
4203
                if (((pass == D6O_IA_NA) &&
 
4204
                     !get_encapsulated_IA_state(&cli_enc_opt_state,
 
4205
                                                &cli_enc_opt_data,
 
4206
                                                packet, ia, IA_NA_OFFSET)) ||
 
4207
                    ((pass == D6O_IA_TA) &&
 
4208
                     !get_encapsulated_IA_state(&cli_enc_opt_state,
 
4209
                                                &cli_enc_opt_data,
 
4210
                                                packet, ia, IA_TA_OFFSET))) {
 
4211
                        goto exit;
 
4212
                }
 
4213
 
 
4214
                oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
 
4215
                                   D6O_IAADDR);
 
4216
 
 
4217
                for ( ; oc != NULL ; oc = oc->next) {
 
4218
                        if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
 
4219
                                                   packet->options, NULL,
 
4220
                                                   &global_scope, oc, MDL) ||
 
4221
                            (iaaddr.len < IAADDR_OFFSET)) {
 
4222
                                log_error("dhcpv6_confirm: "
 
4223
                                          "error evaluating IAADDR.");
 
4224
                                goto exit;
 
4225
                        }
 
4226
 
 
4227
                        /* Copy out the IPv6 address for processing. */
 
4228
                        cli_addr.len = 16;
 
4229
                        memcpy(cli_addr.iabuf, iaaddr.data, 16);
 
4230
 
 
4231
                        data_string_forget(&iaaddr, MDL);
 
4232
 
 
4233
                        /* Record that we've processed at least one address. */
 
4234
                        has_addrs = ISC_TRUE;
 
4235
 
 
4236
                        /* Find out if any subnets cover this address. */
 
4237
                        for (subnet = shared->subnets ; subnet != NULL ;
 
4238
                             subnet = subnet->next_sibling) {
 
4239
                                if (addr_eq(subnet_number(cli_addr,
 
4240
                                                          subnet->netmask),
 
4241
                                            subnet->net))
 
4242
                                        break;
 
4243
                        }
 
4244
 
 
4245
                        /* If we reach the end of the subnet list, and no
 
4246
                         * subnet matches the client address, then it must
 
4247
                         * be inappropriate to the link (so far as our
 
4248
                         * configuration says).  Once we've found one
 
4249
                         * inappropriate address, there is no reason to
 
4250
                         * continue searching.
 
4251
                         */
 
4252
                        if (subnet == NULL) {
 
4253
                                inappropriate = ISC_TRUE;
 
4254
                                break;
 
4255
                        }
 
4256
                }
 
4257
 
 
4258
                option_state_dereference(&cli_enc_opt_state, MDL);
 
4259
                data_string_forget(&cli_enc_opt_data, MDL);
 
4260
 
 
4261
                /* Advance to the next IA_*. */
 
4262
                ia = ia->next;
 
4263
        }
 
4264
 
 
4265
        /* If the client supplied no addresses, do not reply. */
 
4266
        if (!has_addrs)
 
4267
                goto exit;
 
4268
 
 
4269
        /* 
 
4270
         * Set up reply.
 
4271
         */
 
4272
        if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
 
4273
                goto exit;
 
4274
        }
 
4275
 
 
4276
        /* 
 
4277
         * Set our status.
 
4278
         */
 
4279
        if (inappropriate) {
 
4280
                if (!set_status_code(STATUS_NotOnLink, 
 
4281
                                     "Some of the addresses are not on link.",
 
4282
                                     opt_state)) {
 
4283
                        goto exit;
 
4284
                }
 
4285
        } else {
 
4286
                if (!set_status_code(STATUS_Success, 
 
4287
                                     "All addresses still on link.",
 
4288
                                     opt_state)) {
 
4289
                        goto exit;
 
4290
                }
 
4291
        }
 
4292
 
 
4293
        /* 
 
4294
         * Only one option: add it.
 
4295
         */
 
4296
        reply_ofs += store_options6(reply_data+reply_ofs,
 
4297
                                    sizeof(reply_data)-reply_ofs, 
 
4298
                                    opt_state, packet,
 
4299
                                    required_opts, &packet_oro);
 
4300
 
 
4301
        /* 
 
4302
         * Return our reply to the caller.
 
4303
         */
 
4304
        reply_ret->len = reply_ofs;
 
4305
        reply_ret->buffer = NULL;
 
4306
        if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
 
4307
                log_fatal("No memory to store reply.");
 
4308
        }
 
4309
        reply_ret->data = reply_ret->buffer->data;
 
4310
        memcpy(reply_ret->buffer->data, reply, reply_ofs);
 
4311
 
 
4312
exit:
 
4313
        /* Cleanup any stale data strings. */
 
4314
        if (cli_enc_opt_data.buffer != NULL)
 
4315
                data_string_forget(&cli_enc_opt_data, MDL);
 
4316
        if (iaaddr.buffer != NULL)
 
4317
                data_string_forget(&iaaddr, MDL);
 
4318
        if (client_id.buffer != NULL)
 
4319
                data_string_forget(&client_id, MDL);
 
4320
        if (packet_oro.buffer != NULL)
 
4321
                data_string_forget(&packet_oro, MDL);
 
4322
 
 
4323
        /* Release any stale option states. */
 
4324
        if (cli_enc_opt_state != NULL)
 
4325
                option_state_dereference(&cli_enc_opt_state, MDL);
 
4326
        if (opt_state != NULL)
 
4327
                option_state_dereference(&opt_state, MDL);
 
4328
}
 
4329
 
 
4330
/*
 
4331
 * Renew is when a client wants to extend its lease/prefix, at time T1.
 
4332
 *
 
4333
 * We handle this the same as if the client wants a new lease/prefix,
 
4334
 * except for the error code of when addresses don't match.
 
4335
 */
 
4336
 
 
4337
/* TODO: reject unicast messages, unless we set unicast option */
 
4338
static void
 
4339
dhcpv6_renew(struct data_string *reply, struct packet *packet) {
 
4340
        struct data_string client_id;
 
4341
        struct data_string server_id;
 
4342
 
 
4343
        /* 
 
4344
         * Validate the request.
 
4345
         */
 
4346
        if (!valid_client_resp(packet, &client_id, &server_id)) {
 
4347
                return;
 
4348
        }
 
4349
 
 
4350
        /*
 
4351
         * Renew our lease.
 
4352
         */
 
4353
        lease_to_client(reply, packet, &client_id, &server_id);
 
4354
 
 
4355
        /*
 
4356
         * Cleanup.
 
4357
         */
 
4358
        data_string_forget(&server_id, MDL);
 
4359
        data_string_forget(&client_id, MDL);
 
4360
}
 
4361
 
 
4362
/*
 
4363
 * Rebind is when a client wants to extend its lease, at time T2.
 
4364
 *
 
4365
 * We handle this the same as if the client wants a new lease, except
 
4366
 * for the error code of when addresses don't match.
 
4367
 */
 
4368
 
 
4369
static void
 
4370
dhcpv6_rebind(struct data_string *reply, struct packet *packet) {
 
4371
        struct data_string client_id;
 
4372
 
 
4373
        if (!valid_client_msg(packet, &client_id)) {
 
4374
                return;
 
4375
        }
 
4376
 
 
4377
        lease_to_client(reply, packet, &client_id, NULL);
 
4378
 
 
4379
        data_string_forget(&client_id, MDL);
 
4380
}
 
4381
 
 
4382
static void
 
4383
ia_na_match_decline(const struct data_string *client_id,
 
4384
                    const struct data_string *iaaddr,
 
4385
                    struct iasubopt *lease)
 
4386
{
 
4387
        char tmp_addr[INET6_ADDRSTRLEN];
 
4388
 
 
4389
        log_error("Client %s reports address %s is "
 
4390
                  "already in use by another host!",
 
4391
                  print_hex_1(client_id->len, client_id->data, 60),
 
4392
                  inet_ntop(AF_INET6, iaaddr->data, 
 
4393
                            tmp_addr, sizeof(tmp_addr)));
 
4394
        if (lease != NULL) {
 
4395
                decline_lease6(lease->ipv6_pool, lease);
 
4396
                lease->ia->cltt = cur_time;
 
4397
                write_ia(lease->ia);
 
4398
        }
 
4399
}
 
4400
 
 
4401
static void
 
4402
ia_na_nomatch_decline(const struct data_string *client_id,
 
4403
                      const struct data_string *iaaddr,
 
4404
                      u_int32_t *ia_na_id,
 
4405
                      struct packet *packet,
 
4406
                      char *reply_data,
 
4407
                      int *reply_ofs,
 
4408
                      int reply_len)
 
4409
{
 
4410
        char tmp_addr[INET6_ADDRSTRLEN];
 
4411
        struct option_state *host_opt_state;
 
4412
        int len;
 
4413
 
 
4414
        log_info("Client %s declines address %s, which is not offered to it.",
 
4415
                 print_hex_1(client_id->len, client_id->data, 60),
 
4416
                 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
 
4417
 
 
4418
        /*
 
4419
         * Create state for this IA_NA.
 
4420
         */
 
4421
        host_opt_state = NULL;
 
4422
        if (!option_state_allocate(&host_opt_state, MDL)) {
 
4423
                log_error("ia_na_nomatch_decline: out of memory "
 
4424
                          "allocating option_state.");
 
4425
                goto exit;
 
4426
        }
 
4427
 
 
4428
        if (!set_status_code(STATUS_NoBinding, "Decline for unknown address.",
 
4429
                             host_opt_state)) {
 
4430
                goto exit;
 
4431
        }
 
4432
 
 
4433
        /*
 
4434
         * Insure we have enough space
 
4435
         */
 
4436
        if (reply_len < (*reply_ofs + 16)) {
 
4437
                log_error("ia_na_nomatch_decline: "
 
4438
                          "out of space for reply packet.");
 
4439
                goto exit;
 
4440
        }
 
4441
 
 
4442
        /*
 
4443
         * Put our status code into the reply packet.
 
4444
         */
 
4445
        len = store_options6(reply_data+(*reply_ofs)+16,
 
4446
                             reply_len-(*reply_ofs)-16,
 
4447
                             host_opt_state, packet,
 
4448
                             required_opts_STATUS_CODE, NULL);
 
4449
 
 
4450
        /*
 
4451
         * Store the non-encapsulated option data for this 
 
4452
         * IA_NA into our reply packet. Defined in RFC 3315, 
 
4453
         * section 22.4.  
 
4454
         */
 
4455
        /* option number */
 
4456
        putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
 
4457
        /* option length */
 
4458
        putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
 
4459
        /* IA_NA, copied from the client */
 
4460
        memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
 
4461
        /* t1 and t2, odd that we need them, but here it is */
 
4462
        putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
 
4463
        putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
 
4464
 
 
4465
        /*
 
4466
         * Get ready for next IA_NA.
 
4467
         */
 
4468
        *reply_ofs += (len + 16);
 
4469
 
 
4470
exit:
 
4471
        option_state_dereference(&host_opt_state, MDL);
 
4472
}
 
4473
 
 
4474
static void
 
4475
iterate_over_ia_na(struct data_string *reply_ret, 
 
4476
                   struct packet *packet,
 
4477
                   const struct data_string *client_id,
 
4478
                   const struct data_string *server_id,
 
4479
                   const char *packet_type,
 
4480
                   void (*ia_na_match)(),
 
4481
                   void (*ia_na_nomatch)())
 
4482
{
 
4483
        struct option_state *opt_state;
 
4484
        struct host_decl *packet_host;
 
4485
        struct option_cache *ia;
 
4486
        struct option_cache *oc;
 
4487
        /* cli_enc_... variables come from the IA_NA/IA_TA options */
 
4488
        struct data_string cli_enc_opt_data;
 
4489
        struct option_state *cli_enc_opt_state;
 
4490
        struct host_decl *host;
 
4491
        struct option_state *host_opt_state;
 
4492
        struct data_string iaaddr;
 
4493
        struct data_string fixed_addr;
 
4494
        int iaaddr_is_found;
 
4495
        char reply_data[65536];
 
4496
        struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
 
4497
        int reply_ofs = (int)((char *)reply->options - (char *)reply);
 
4498
        char status_msg[32];
 
4499
        struct iasubopt *lease;
 
4500
        struct ia_xx *existing_ia_na;
 
4501
        int i;
 
4502
        struct data_string key;
 
4503
        u_int32_t iaid;
 
4504
 
 
4505
        /*
 
4506
         * Initialize to empty values, in case we have to exit early.
 
4507
         */
 
4508
        opt_state = NULL;
 
4509
        memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
 
4510
        cli_enc_opt_state = NULL;
 
4511
        memset(&iaaddr, 0, sizeof(iaaddr));
 
4512
        memset(&fixed_addr, 0, sizeof(fixed_addr));
 
4513
        host_opt_state = NULL;
 
4514
        lease = NULL;
 
4515
 
 
4516
        /* 
 
4517
         * Find the host record that matches from the packet, if any.
 
4518
         */
 
4519
        packet_host = NULL;
 
4520
        if (!find_hosts_by_uid(&packet_host, 
 
4521
                               client_id->data, client_id->len, MDL)) {
 
4522
                packet_host = NULL;
 
4523
                /* 
 
4524
                 * Note: In general, we don't expect a client to provide
 
4525
                 *       enough information to match by option for these
 
4526
                 *       types of messages, but if we don't have a UID
 
4527
                 *       match we can check anyway.
 
4528
                 */
 
4529
                if (!find_hosts_by_option(&packet_host, 
 
4530
                                          packet, packet->options, MDL)) {
 
4531
                        packet_host = NULL;
 
4532
                }
 
4533
        }
 
4534
 
 
4535
        /* 
 
4536
         * Set our reply information.
 
4537
         */
 
4538
        reply->msg_type = DHCPV6_REPLY;
 
4539
        memcpy(reply->transaction_id, packet->dhcpv6_transaction_id, 
 
4540
               sizeof(reply->transaction_id));
 
4541
 
 
4542
        /*
 
4543
         * Build our option state for reply.
 
4544
         */
 
4545
        opt_state = NULL;
 
4546
        if (!option_state_allocate(&opt_state, MDL)) {
 
4547
                log_error("iterate_over_ia_na: no memory for option_state.");
 
4548
                goto exit;
 
4549
        }
 
4550
        execute_statements_in_scope(NULL, packet, NULL, NULL, 
 
4551
                                    packet->options, opt_state, 
 
4552
                                    &global_scope, root_group, NULL);
 
4553
 
 
4554
        /* 
 
4555
         * RFC 3315, section 18.2.7 tells us which options to include.
 
4556
         */
 
4557
        oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
 
4558
        if (oc == NULL) {
 
4559
                if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL, 
 
4560
                                        (unsigned char *)server_duid.data, 
 
4561
                                        server_duid.len, D6O_SERVERID, 0)) {
 
4562
                        log_error("iterate_over_ia_na: "
 
4563
                                  "error saving server identifier.");
 
4564
                        goto exit;
 
4565
                }
 
4566
        }
 
4567
 
 
4568
        if (!save_option_buffer(&dhcpv6_universe, opt_state, 
 
4569
                                client_id->buffer, 
 
4570
                                (unsigned char *)client_id->data,
 
4571
                                client_id->len, 
 
4572
                                D6O_CLIENTID, 0)) {
 
4573
                log_error("iterate_over_ia_na: "
 
4574
                          "error saving client identifier.");
 
4575
                goto exit;
 
4576
        }
 
4577
 
 
4578
        snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
 
4579
        if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
 
4580
                goto exit;
 
4581
        }
 
4582
 
 
4583
        /* 
 
4584
         * Add our options that are not associated with any IA_NA or IA_TA. 
 
4585
         */
 
4586
        reply_ofs += store_options6(reply_data+reply_ofs,
 
4587
                                    sizeof(reply_data)-reply_ofs, 
 
4588
                                    opt_state, packet,
 
4589
                                    required_opts, NULL);
 
4590
 
 
4591
        /*
 
4592
         * Loop through the IA_NA reported by the client, and deal with
 
4593
         * addresses reported as already in use.
 
4594
         */
 
4595
        for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
 
4596
             ia != NULL; ia = ia->next) {
 
4597
                iaaddr_is_found = 0;
 
4598
 
 
4599
                if (!get_encapsulated_IA_state(&cli_enc_opt_state,
 
4600
                                               &cli_enc_opt_data,
 
4601
                                               packet, ia, IA_NA_OFFSET)) {
 
4602
                        goto exit;
 
4603
                }
 
4604
 
 
4605
                iaid = getULong(cli_enc_opt_data.data);
 
4606
 
 
4607
                /* 
 
4608
                 * XXX: It is possible that we can get multiple addresses
 
4609
                 *      sent by the client. We don't send multiple 
 
4610
                 *      addresses, so this indicates a client error. 
 
4611
                 *      We should check for multiple IAADDR options, log
 
4612
                 *      if found, and set as an error.
 
4613
                 */
 
4614
                oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state, 
 
4615
                                   D6O_IAADDR);
 
4616
                if (oc == NULL) {
 
4617
                        /* no address given for this IA, ignore */
 
4618
                        option_state_dereference(&cli_enc_opt_state, MDL);
 
4619
                        data_string_forget(&cli_enc_opt_data, MDL);
 
4620
                        continue;
 
4621
                }
 
4622
 
 
4623
                memset(&iaaddr, 0, sizeof(iaaddr));
 
4624
                if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL, 
 
4625
                                           packet->options, NULL,
 
4626
                                           &global_scope, oc, MDL)) {
 
4627
                        log_error("iterate_over_ia_na: "
 
4628
                                  "error evaluating IAADDR.");
 
4629
                        goto exit;
 
4630
                }
 
4631
 
 
4632
                /* 
 
4633
                 * Now we need to figure out which host record matches
 
4634
                 * this IA_NA and IAADDR.
 
4635
                 *
 
4636
                 * XXX: We don't currently track IA_NA separately, but
 
4637
                 *      we will need to do this!
 
4638
                 */
 
4639
                host = NULL;
 
4640
                if (!find_hosts_by_option(&host, packet, 
 
4641
                                          cli_enc_opt_state, MDL)) { 
 
4642
                        if (packet_host != NULL) {
 
4643
                                host = packet_host;
 
4644
                        } else {
 
4645
                                host = NULL;
 
4646
                        }
 
4647
                }
 
4648
                while (host != NULL) {
 
4649
                        if (host->fixed_addr != NULL) {
 
4650
                                if (!evaluate_option_cache(&fixed_addr, NULL, 
 
4651
                                                           NULL, NULL, NULL, 
 
4652
                                                           NULL, &global_scope,
 
4653
                                                           host->fixed_addr, 
 
4654
                                                           MDL)) {
 
4655
                                        log_error("iterate_over_ia_na: error "
 
4656
                                                  "evaluating host address.");
 
4657
                                        goto exit;
 
4658
                                }
 
4659
                                if ((iaaddr.len >= 16) &&
 
4660
                                    !memcmp(fixed_addr.data, iaaddr.data, 16)) {
 
4661
                                        data_string_forget(&fixed_addr, MDL);
 
4662
                                        break;
 
4663
                                }
 
4664
                                data_string_forget(&fixed_addr, MDL);
 
4665
                        }
 
4666
                        host = host->n_ipaddr;
 
4667
                }
 
4668
 
 
4669
                if ((host == NULL) && (iaaddr.len >= IAADDR_OFFSET)) {
 
4670
                        /*
 
4671
                         * Find existing IA_NA.
 
4672
                         */
 
4673
                        if (ia_make_key(&key, iaid, 
 
4674
                                        (char *)client_id->data,
 
4675
                                        client_id->len, 
 
4676
                                        MDL) != ISC_R_SUCCESS) {
 
4677
                                log_fatal("iterate_over_ia_na: no memory for "
 
4678
                                          "key.");
 
4679
                        }
 
4680
 
 
4681
                        existing_ia_na = NULL;
 
4682
                        if (ia_hash_lookup(&existing_ia_na, ia_na_active, 
 
4683
                                           (unsigned char *)key.data, 
 
4684
                                           key.len, MDL)) {
 
4685
                                /* 
 
4686
                                 * Make sure this address is in the IA_NA.
 
4687
                                 */
 
4688
                                for (i=0; i<existing_ia_na->num_iasubopt; i++) {
 
4689
                                        struct iasubopt *tmp;
 
4690
                                        struct in6_addr *in6_addr;
 
4691
 
 
4692
                                        tmp = existing_ia_na->iasubopt[i];
 
4693
                                        in6_addr = &tmp->addr;
 
4694
                                        if (memcmp(in6_addr, 
 
4695
                                                   iaaddr.data, 16) == 0) {
 
4696
                                                iasubopt_reference(&lease,
 
4697
                                                                   tmp, MDL);
 
4698
                                                break;
 
4699
                                        }
 
4700
                                }
 
4701
                        }
 
4702
 
 
4703
                        data_string_forget(&key, MDL);
 
4704
                }
 
4705
 
 
4706
                if ((host != NULL) || (lease != NULL)) {
 
4707
                        ia_na_match(client_id, &iaaddr, lease);
 
4708
                } else {
 
4709
                        ia_na_nomatch(client_id, &iaaddr, 
 
4710
                                      (u_int32_t *)cli_enc_opt_data.data, 
 
4711
                                      packet, reply_data, &reply_ofs, 
 
4712
                                      sizeof(reply_data));
 
4713
                }
 
4714
 
 
4715
                if (lease != NULL) {
 
4716
                        iasubopt_dereference(&lease, MDL);
 
4717
                }
 
4718
 
 
4719
                data_string_forget(&iaaddr, MDL);
 
4720
                option_state_dereference(&cli_enc_opt_state, MDL);
 
4721
                data_string_forget(&cli_enc_opt_data, MDL);
 
4722
        }
 
4723
 
 
4724
        /* 
 
4725
         * Return our reply to the caller.
 
4726
         */
 
4727
        reply_ret->len = reply_ofs;
 
4728
        reply_ret->buffer = NULL;
 
4729
        if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
 
4730
                log_fatal("No memory to store reply.");
 
4731
        }
 
4732
        reply_ret->data = reply_ret->buffer->data;
 
4733
        memcpy(reply_ret->buffer->data, reply, reply_ofs);
 
4734
 
 
4735
exit:
 
4736
        if (lease != NULL) {
 
4737
                iasubopt_dereference(&lease, MDL);
 
4738
        }
 
4739
        if (host_opt_state != NULL) {
 
4740
                option_state_dereference(&host_opt_state, MDL);
 
4741
        }
 
4742
        if (fixed_addr.buffer != NULL) {
 
4743
                data_string_forget(&fixed_addr, MDL);
 
4744
        }
 
4745
        if (iaaddr.buffer != NULL) {
 
4746
                data_string_forget(&iaaddr, MDL);
 
4747
        }
 
4748
        if (cli_enc_opt_state != NULL) {
 
4749
                option_state_dereference(&cli_enc_opt_state, MDL);
 
4750
        }
 
4751
        if (cli_enc_opt_data.buffer != NULL) {
 
4752
                data_string_forget(&cli_enc_opt_data, MDL);
 
4753
        }
 
4754
        if (opt_state != NULL) {
 
4755
                option_state_dereference(&opt_state, MDL);
 
4756
        }
 
4757
}
 
4758
 
 
4759
/*
 
4760
 * Decline means a client has detected that something else is using an
 
4761
 * address we gave it.
 
4762
 *
 
4763
 * Since we're only dealing with fixed leases for now, there's not
 
4764
 * much we can do, other that log the occurrence.
 
4765
 * 
 
4766
 * When we start issuing addresses from pools, then we will have to
 
4767
 * record our declined addresses and issue another. In general with
 
4768
 * IPv6 there is no worry about DoS by clients exhausting space, but
 
4769
 * we still need to be aware of this possibility.
 
4770
 */
 
4771
 
 
4772
/* TODO: reject unicast messages, unless we set unicast option */
 
4773
/* TODO: IA_TA */
 
4774
static void
 
4775
dhcpv6_decline(struct data_string *reply, struct packet *packet) {
 
4776
        struct data_string client_id;
 
4777
        struct data_string server_id;
 
4778
 
 
4779
        /* 
 
4780
         * Validate our input.
 
4781
         */
 
4782
        if (!valid_client_resp(packet, &client_id, &server_id)) {
 
4783
                return;
 
4784
        }
 
4785
 
 
4786
        /*
 
4787
         * Undefined for IA_PD.
 
4788
         */
 
4789
        delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
 
4790
 
 
4791
        /*
 
4792
         * And operate on each IA_NA in this packet.
 
4793
         */
 
4794
        iterate_over_ia_na(reply, packet, &client_id, &server_id, "Decline", 
 
4795
                           ia_na_match_decline, ia_na_nomatch_decline);
 
4796
 
 
4797
        data_string_forget(&server_id, MDL);
 
4798
        data_string_forget(&client_id, MDL);
 
4799
}
 
4800
 
 
4801
static void
 
4802
ia_na_match_release(const struct data_string *client_id,
 
4803
                    const struct data_string *iaaddr,
 
4804
                    struct iasubopt *lease)
 
4805
{
 
4806
        char tmp_addr[INET6_ADDRSTRLEN];
 
4807
 
 
4808
        log_info("Client %s releases address %s",
 
4809
                 print_hex_1(client_id->len, client_id->data, 60),
 
4810
                 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
 
4811
        if (lease != NULL) {
 
4812
                release_lease6(lease->ipv6_pool, lease);
 
4813
                lease->ia->cltt = cur_time;
 
4814
                write_ia(lease->ia);
 
4815
        }
 
4816
}
 
4817
 
 
4818
static void
 
4819
ia_na_nomatch_release(const struct data_string *client_id,
 
4820
                      const struct data_string *iaaddr,
 
4821
                      u_int32_t *ia_na_id,
 
4822
                      struct packet *packet,
 
4823
                      char *reply_data,
 
4824
                      int *reply_ofs,
 
4825
                      int reply_len)
 
4826
{
 
4827
        char tmp_addr[INET6_ADDRSTRLEN];
 
4828
        struct option_state *host_opt_state;
 
4829
        int len;
 
4830
 
 
4831
        log_info("Client %s releases address %s, which is not leased to it.",
 
4832
                 print_hex_1(client_id->len, client_id->data, 60),
 
4833
                 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
 
4834
 
 
4835
        /*
 
4836
         * Create state for this IA_NA.
 
4837
         */
 
4838
        host_opt_state = NULL;
 
4839
        if (!option_state_allocate(&host_opt_state, MDL)) {
 
4840
                log_error("ia_na_nomatch_release: out of memory "
 
4841
                          "allocating option_state.");
 
4842
                goto exit;
 
4843
        }
 
4844
 
 
4845
        if (!set_status_code(STATUS_NoBinding, 
 
4846
                             "Release for non-leased address.",
 
4847
                             host_opt_state)) {
 
4848
                goto exit;
 
4849
        }
 
4850
 
 
4851
        /*
 
4852
         * Insure we have enough space
 
4853
         */
 
4854
        if (reply_len < (*reply_ofs + 16)) {
 
4855
                log_error("ia_na_nomatch_release: "
 
4856
                          "out of space for reply packet.");
 
4857
                goto exit;
 
4858
        }
 
4859
 
 
4860
        /*
 
4861
         * Put our status code into the reply packet.
 
4862
         */
 
4863
        len = store_options6(reply_data+(*reply_ofs)+16,
 
4864
                             reply_len-(*reply_ofs)-16,
 
4865
                             host_opt_state, packet,
 
4866
                             required_opts_STATUS_CODE, NULL);
 
4867
 
 
4868
        /*
 
4869
         * Store the non-encapsulated option data for this 
 
4870
         * IA_NA into our reply packet. Defined in RFC 3315, 
 
4871
         * section 22.4.  
 
4872
         */
 
4873
        /* option number */
 
4874
        putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
 
4875
        /* option length */
 
4876
        putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
 
4877
        /* IA_NA, copied from the client */
 
4878
        memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
 
4879
        /* t1 and t2, odd that we need them, but here it is */
 
4880
        putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
 
4881
        putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
 
4882
 
 
4883
        /*
 
4884
         * Get ready for next IA_NA.
 
4885
         */
 
4886
        *reply_ofs += (len + 16);
 
4887
 
 
4888
exit:
 
4889
        option_state_dereference(&host_opt_state, MDL);
 
4890
}
 
4891
 
 
4892
static void
 
4893
ia_pd_match_release(const struct data_string *client_id,
 
4894
                    const struct data_string *iapref,
 
4895
                    struct iasubopt *prefix)
 
4896
{
 
4897
        char tmp_addr[INET6_ADDRSTRLEN];
 
4898
 
 
4899
        log_info("Client %s releases prefix %s/%u",
 
4900
                 print_hex_1(client_id->len, client_id->data, 60),
 
4901
                 inet_ntop(AF_INET6, iapref->data + 9,
 
4902
                           tmp_addr, sizeof(tmp_addr)),
 
4903
                 (unsigned) getUChar(iapref->data + 8));
 
4904
        if (prefix != NULL) {
 
4905
                release_lease6(prefix->ipv6_pool, prefix);
 
4906
                prefix->ia->cltt = cur_time;
 
4907
                write_ia(prefix->ia);
 
4908
        }
 
4909
}
 
4910
 
 
4911
static void
 
4912
ia_pd_nomatch_release(const struct data_string *client_id,
 
4913
                      const struct data_string *iapref,
 
4914
                      u_int32_t *ia_pd_id,
 
4915
                      struct packet *packet,
 
4916
                      char *reply_data,
 
4917
                      int *reply_ofs,
 
4918
                      int reply_len)
 
4919
{
 
4920
        char tmp_addr[INET6_ADDRSTRLEN];
 
4921
        struct option_state *host_opt_state;
 
4922
        int len;
 
4923
 
 
4924
        log_info("Client %s releases prefix %s/%u, which is not leased to it.",
 
4925
                 print_hex_1(client_id->len, client_id->data, 60),
 
4926
                 inet_ntop(AF_INET6, iapref->data + 9,
 
4927
                           tmp_addr, sizeof(tmp_addr)),
 
4928
                 (unsigned) getUChar(iapref->data + 8));
 
4929
 
 
4930
        /*
 
4931
         * Create state for this IA_PD.
 
4932
         */
 
4933
        host_opt_state = NULL;
 
4934
        if (!option_state_allocate(&host_opt_state, MDL)) {
 
4935
                log_error("ia_pd_nomatch_release: out of memory "
 
4936
                          "allocating option_state.");
 
4937
                goto exit;
 
4938
        }
 
4939
 
 
4940
        if (!set_status_code(STATUS_NoBinding, 
 
4941
                             "Release for non-leased prefix.",
 
4942
                             host_opt_state)) {
 
4943
                goto exit;
 
4944
        }
 
4945
 
 
4946
        /*
 
4947
         * Insure we have enough space
 
4948
         */
 
4949
        if (reply_len < (*reply_ofs + 16)) {
 
4950
                log_error("ia_pd_nomatch_release: "
 
4951
                          "out of space for reply packet.");
 
4952
                goto exit;
 
4953
        }
 
4954
 
 
4955
        /*
 
4956
         * Put our status code into the reply packet.
 
4957
         */
 
4958
        len = store_options6(reply_data+(*reply_ofs)+16,
 
4959
                             reply_len-(*reply_ofs)-16,
 
4960
                             host_opt_state, packet,
 
4961
                             required_opts_STATUS_CODE, NULL);
 
4962
 
 
4963
        /*
 
4964
         * Store the non-encapsulated option data for this 
 
4965
         * IA_PD into our reply packet. Defined in RFC 3315, 
 
4966
         * section 22.4.  
 
4967
         */
 
4968
        /* option number */
 
4969
        putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_PD);
 
4970
        /* option length */
 
4971
        putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
 
4972
        /* IA_PD, copied from the client */
 
4973
        memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
 
4974
        /* t1 and t2, odd that we need them, but here it is */
 
4975
        putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
 
4976
        putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
 
4977
 
 
4978
        /*
 
4979
         * Get ready for next IA_PD.
 
4980
         */
 
4981
        *reply_ofs += (len + 16);
 
4982
 
 
4983
exit:
 
4984
        option_state_dereference(&host_opt_state, MDL);
 
4985
}
 
4986
 
 
4987
static void
 
4988
iterate_over_ia_pd(struct data_string *reply_ret, 
 
4989
                   struct packet *packet,
 
4990
                   const struct data_string *client_id,
 
4991
                   const struct data_string *server_id,
 
4992
                   const char *packet_type,
 
4993
                   void (*ia_pd_match)(),
 
4994
                   void (*ia_pd_nomatch)())
 
4995
{
 
4996
        struct data_string reply_new;
 
4997
        int reply_len;
 
4998
        struct option_state *opt_state;
 
4999
        struct host_decl *packet_host;
 
5000
        struct option_cache *ia;
 
5001
        struct option_cache *oc;
 
5002
        /* cli_enc_... variables come from the IA_PD options */
 
5003
        struct data_string cli_enc_opt_data;
 
5004
        struct option_state *cli_enc_opt_state;
 
5005
        struct host_decl *host;
 
5006
        struct option_state *host_opt_state;
 
5007
        struct data_string iaprefix;
 
5008
        int iaprefix_is_found;
 
5009
        char reply_data[65536];
 
5010
        int reply_ofs;
 
5011
        struct iasubopt *prefix;
 
5012
        struct ia_xx *existing_ia_pd;
 
5013
        int i;
 
5014
        struct data_string key;
 
5015
        u_int32_t iaid;
 
5016
 
 
5017
        /*
 
5018
         * Initialize to empty values, in case we have to exit early.
 
5019
         */
 
5020
        memset(&reply_new, 0, sizeof(reply_new));
 
5021
        opt_state = NULL;
 
5022
        memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
 
5023
        cli_enc_opt_state = NULL;
 
5024
        memset(&iaprefix, 0, sizeof(iaprefix));
 
5025
        host_opt_state = NULL;
 
5026
        prefix = NULL;
 
5027
 
 
5028
        /*
 
5029
         * Compute the available length for the reply.
 
5030
         */
 
5031
        reply_len = sizeof(reply_data) - reply_ret->len;
 
5032
        reply_ofs = 0;
 
5033
 
 
5034
        /* 
 
5035
         * Find the host record that matches from the packet, if any.
 
5036
         */
 
5037
        packet_host = NULL;
 
5038
        if (!find_hosts_by_uid(&packet_host, 
 
5039
                               client_id->data, client_id->len, MDL)) {
 
5040
                packet_host = NULL;
 
5041
                /* 
 
5042
                 * Note: In general, we don't expect a client to provide
 
5043
                 *       enough information to match by option for these
 
5044
                 *       types of messages, but if we don't have a UID
 
5045
                 *       match we can check anyway.
 
5046
                 */
 
5047
                if (!find_hosts_by_option(&packet_host, 
 
5048
                                          packet, packet->options, MDL)) {
 
5049
                        packet_host = NULL;
 
5050
                }
 
5051
        }
 
5052
 
 
5053
        /*
 
5054
         * Build our option state for reply.
 
5055
         */
 
5056
        opt_state = NULL;
 
5057
        if (!option_state_allocate(&opt_state, MDL)) {
 
5058
                log_error("iterate_over_ia_pd: no memory for option_state.");
 
5059
                goto exit;
 
5060
        }
 
5061
        execute_statements_in_scope(NULL, packet, NULL, NULL, 
 
5062
                                    packet->options, opt_state, 
 
5063
                                    &global_scope, root_group, NULL);
 
5064
 
 
5065
        /*
 
5066
         * Loop through the IA_PD reported by the client, and deal with
 
5067
         * prefixes reported as already in use.
 
5068
         */
 
5069
        for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
 
5070
             ia != NULL; ia = ia->next) {
 
5071
            iaprefix_is_found = 0;
 
5072
 
 
5073
            if (!get_encapsulated_IA_state(&cli_enc_opt_state,
 
5074
                                           &cli_enc_opt_data,
 
5075
                                           packet, ia, IA_PD_OFFSET)) {
 
5076
                goto exit;
 
5077
            }
 
5078
 
 
5079
            iaid = getULong(cli_enc_opt_data.data);
 
5080
 
 
5081
            oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state, 
 
5082
                               D6O_IAPREFIX);
 
5083
            if (oc == NULL) {
 
5084
                /* no prefix given for this IA_PD, ignore */
 
5085
                option_state_dereference(&cli_enc_opt_state, MDL);
 
5086
                data_string_forget(&cli_enc_opt_data, MDL);
 
5087
                continue;
 
5088
            }
 
5089
 
 
5090
            for (; oc != NULL; oc = oc->next) {
 
5091
                memset(&iaprefix, 0, sizeof(iaprefix));
 
5092
                if (!evaluate_option_cache(&iaprefix, packet, NULL, NULL, 
 
5093
                                           packet->options, NULL,
 
5094
                                           &global_scope, oc, MDL)) {
 
5095
                        log_error("iterate_over_ia_pd: "
 
5096
                                  "error evaluating IAPREFIX.");
 
5097
                        goto exit;
 
5098
                }
 
5099
 
 
5100
                /* 
 
5101
                 * Now we need to figure out which host record matches
 
5102
                 * this IA_PD and IAPREFIX.
 
5103
                 *
 
5104
                 * XXX: We don't currently track IA_PD separately, but
 
5105
                 *      we will need to do this!
 
5106
                 */
 
5107
                host = NULL;
 
5108
                if (!find_hosts_by_option(&host, packet, 
 
5109
                                          cli_enc_opt_state, MDL)) { 
 
5110
                        if (packet_host != NULL) {
 
5111
                                host = packet_host;
 
5112
                        } else {
 
5113
                                host = NULL;
 
5114
                        }
 
5115
                }
 
5116
                while (host != NULL) {
 
5117
                        if (host->fixed_prefix != NULL) {
 
5118
                                struct iaddrcidrnetlist *l;
 
5119
                                int plen = (int) getUChar(iaprefix.data + 8);
 
5120
 
 
5121
                                for (l = host->fixed_prefix; l != NULL;
 
5122
                                     l = l->next) {
 
5123
                                        if (plen != l->cidrnet.bits)
 
5124
                                                continue;
 
5125
                                        if (memcmp(iaprefix.data + 9,
 
5126
                                                   l->cidrnet.lo_addr.iabuf,
 
5127
                                                   16) == 0)
 
5128
                                                break;
 
5129
                                }
 
5130
                                if ((l != NULL) && (iaprefix.len >= 17))
 
5131
                                        break;
 
5132
                        }
 
5133
                        host = host->n_ipaddr;
 
5134
                }
 
5135
 
 
5136
                if ((host == NULL) && (iaprefix.len >= IAPREFIX_OFFSET)) {
 
5137
                        /*
 
5138
                         * Find existing IA_PD.
 
5139
                         */
 
5140
                        if (ia_make_key(&key, iaid, 
 
5141
                                        (char *)client_id->data,
 
5142
                                        client_id->len, 
 
5143
                                        MDL) != ISC_R_SUCCESS) {
 
5144
                                log_fatal("iterate_over_ia_pd: no memory for "
 
5145
                                          "key.");
 
5146
                        }
 
5147
 
 
5148
                        existing_ia_pd = NULL;
 
5149
                        if (ia_hash_lookup(&existing_ia_pd, ia_pd_active, 
 
5150
                                           (unsigned char *)key.data, 
 
5151
                                           key.len, MDL)) {
 
5152
                                /* 
 
5153
                                 * Make sure this prefix is in the IA_PD.
 
5154
                                 */
 
5155
                                for (i = 0;
 
5156
                                     i < existing_ia_pd->num_iasubopt;
 
5157
                                     i++) {
 
5158
                                        struct iasubopt *tmp;
 
5159
                                        u_int8_t plen;
 
5160
 
 
5161
                                        plen = getUChar(iaprefix.data + 8);
 
5162
                                        tmp = existing_ia_pd->iasubopt[i];
 
5163
                                        if ((tmp->plen == plen) &&
 
5164
                                            (memcmp(&tmp->addr,
 
5165
                                                    iaprefix.data + 9,
 
5166
                                                    16) == 0)) {
 
5167
                                                iasubopt_reference(&prefix,
 
5168
                                                                   tmp, MDL);
 
5169
                                                break;
 
5170
                                        }
 
5171
                                }
 
5172
                        }
 
5173
 
 
5174
                        data_string_forget(&key, MDL);
 
5175
                }
 
5176
 
 
5177
                if ((host != NULL) || (prefix != NULL)) {
 
5178
                        ia_pd_match(client_id, &iaprefix, prefix);
 
5179
                } else {
 
5180
                        ia_pd_nomatch(client_id, &iaprefix, 
 
5181
                                      (u_int32_t *)cli_enc_opt_data.data, 
 
5182
                                      packet, reply_data, &reply_ofs, 
 
5183
                                      reply_len - reply_ofs);
 
5184
                }
 
5185
 
 
5186
                if (prefix != NULL) {
 
5187
                        iasubopt_dereference(&prefix, MDL);
 
5188
                }
 
5189
 
 
5190
                data_string_forget(&iaprefix, MDL);
 
5191
            }
 
5192
 
 
5193
            option_state_dereference(&cli_enc_opt_state, MDL);
 
5194
            data_string_forget(&cli_enc_opt_data, MDL);
 
5195
        }
 
5196
 
 
5197
        /* 
 
5198
         * Return our reply to the caller.
 
5199
         * The IA_NA routine has already filled at least the header.
 
5200
         */
 
5201
        reply_new.len = reply_ret->len + reply_ofs;
 
5202
        if (!buffer_allocate(&reply_new.buffer, reply_new.len, MDL)) {
 
5203
                log_fatal("No memory to store reply.");
 
5204
        }
 
5205
        reply_new.data = reply_new.buffer->data;
 
5206
        memcpy(reply_new.buffer->data,
 
5207
               reply_ret->buffer->data, reply_ret->len);
 
5208
        memcpy(reply_new.buffer->data + reply_ret->len,
 
5209
               reply_data, reply_ofs);
 
5210
        data_string_forget(reply_ret, MDL);
 
5211
        data_string_copy(reply_ret, &reply_new, MDL);
 
5212
        data_string_forget(&reply_new, MDL);
 
5213
 
 
5214
exit:
 
5215
        if (prefix != NULL) {
 
5216
                iasubopt_dereference(&prefix, MDL);
 
5217
        }
 
5218
        if (host_opt_state != NULL) {
 
5219
                option_state_dereference(&host_opt_state, MDL);
 
5220
        }
 
5221
        if (iaprefix.buffer != NULL) {
 
5222
                data_string_forget(&iaprefix, MDL);
 
5223
        }
 
5224
        if (cli_enc_opt_state != NULL) {
 
5225
                option_state_dereference(&cli_enc_opt_state, MDL);
 
5226
        }
 
5227
        if (cli_enc_opt_data.buffer != NULL) {
 
5228
                data_string_forget(&cli_enc_opt_data, MDL);
 
5229
        }
 
5230
        if (opt_state != NULL) {
 
5231
                option_state_dereference(&opt_state, MDL);
 
5232
        }
 
5233
}
 
5234
 
 
5235
/*
 
5236
 * Release means a client is done with the leases.
 
5237
 */
 
5238
 
 
5239
/* TODO: reject unicast messages, unless we set unicast option */
 
5240
static void
 
5241
dhcpv6_release(struct data_string *reply, struct packet *packet) {
 
5242
        struct data_string client_id;
 
5243
        struct data_string server_id;
 
5244
 
 
5245
        /* 
 
5246
         * Validate our input.
 
5247
         */
 
5248
        if (!valid_client_resp(packet, &client_id, &server_id)) {
 
5249
                return;
 
5250
        }
 
5251
 
 
5252
        /*
 
5253
         * And operate on each IA_NA in this packet.
 
5254
         */
 
5255
        iterate_over_ia_na(reply, packet, &client_id, &server_id, "Release", 
 
5256
                           ia_na_match_release, ia_na_nomatch_release);
 
5257
 
 
5258
        /*
 
5259
         * And operate on each IA_PD in this packet.
 
5260
         */
 
5261
        iterate_over_ia_pd(reply, packet, &client_id, &server_id, "Release",
 
5262
                           ia_pd_match_release, ia_pd_nomatch_release);
 
5263
 
 
5264
        data_string_forget(&server_id, MDL);
 
5265
        data_string_forget(&client_id, MDL);
 
5266
}
 
5267
 
 
5268
/*
 
5269
 * Information-Request is used by clients who have obtained an address
 
5270
 * from other means, but want configuration information from the server.
 
5271
 */
 
5272
 
 
5273
static void
 
5274
dhcpv6_information_request(struct data_string *reply, struct packet *packet) {
 
5275
        struct data_string client_id;
 
5276
        struct data_string server_id;
 
5277
 
 
5278
        /*
 
5279
         * Validate our input.
 
5280
         */
 
5281
        if (!valid_client_info_req(packet, &server_id)) {
 
5282
                return;
 
5283
        }
 
5284
 
 
5285
        /*
 
5286
         * Get our client ID, if there is one.
 
5287
         */
 
5288
        memset(&client_id, 0, sizeof(client_id));
 
5289
        if (get_client_id(packet, &client_id) != ISC_R_SUCCESS) {
 
5290
                data_string_forget(&client_id, MDL);
 
5291
        }
 
5292
 
 
5293
        /*
 
5294
         * Use the lease_to_client() function. This will work fine, 
 
5295
         * because the valid_client_info_req() insures that we 
 
5296
         * don't have any IA that would cause us to allocate
 
5297
         * resources to the client.
 
5298
         */
 
5299
        lease_to_client(reply, packet, &client_id,
 
5300
                        server_id.data != NULL ? &server_id : NULL);
 
5301
 
 
5302
        /*
 
5303
         * Cleanup.
 
5304
         */
 
5305
        if (client_id.data != NULL) {
 
5306
                data_string_forget(&client_id, MDL);
 
5307
        }
 
5308
        data_string_forget(&server_id, MDL);
 
5309
}
 
5310
 
 
5311
/* 
 
5312
 * The Relay-forw message is sent by relays. It typically contains a
 
5313
 * single option, which encapsulates an entire packet.
 
5314
 *
 
5315
 * We need to build an encapsulated reply.
 
5316
 */
 
5317
 
 
5318
/* XXX: this is very, very similar to do_packet6(), and should probably
 
5319
        be combined in a clever way */
 
5320
static void
 
5321
dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
 
5322
        struct option_cache *oc;
 
5323
        struct data_string enc_opt_data;
 
5324
        struct packet *enc_packet;
 
5325
        unsigned char msg_type;
 
5326
        const struct dhcpv6_packet *msg;
 
5327
        const struct dhcpv6_relay_packet *relay;
 
5328
        struct data_string enc_reply;
 
5329
        char link_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
 
5330
        char peer_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
 
5331
        struct data_string a_opt, packet_ero;
 
5332
        struct option_state *opt_state;
 
5333
        static char reply_data[65536];
 
5334
        struct dhcpv6_relay_packet *reply;
 
5335
        int reply_ofs;
 
5336
 
 
5337
        /* 
 
5338
         * Initialize variables for early exit.
 
5339
         */
 
5340
        opt_state = NULL;
 
5341
        memset(&a_opt, 0, sizeof(a_opt));
 
5342
        memset(&packet_ero, 0, sizeof(packet_ero));
 
5343
        memset(&enc_reply, 0, sizeof(enc_reply));
 
5344
        memset(&enc_opt_data, 0, sizeof(enc_opt_data));
 
5345
        enc_packet = NULL;
 
5346
 
 
5347
        /*
 
5348
         * Get our encapsulated relay message.
 
5349
         */
 
5350
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_RELAY_MSG);
 
5351
        if (oc == NULL) {
 
5352
                inet_ntop(AF_INET6, &packet->dhcpv6_link_address,
 
5353
                          link_addr, sizeof(link_addr));
 
5354
                inet_ntop(AF_INET6, &packet->dhcpv6_peer_address,
 
5355
                          peer_addr, sizeof(peer_addr));
 
5356
                log_info("Relay-forward from %s with link address=%s and "
 
5357
                         "peer address=%s missing Relay Message option.",
 
5358
                          piaddr(packet->client_addr), link_addr, peer_addr);
 
5359
                goto exit;
 
5360
        }
 
5361
 
 
5362
        if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL, 
 
5363
                                   NULL, NULL, &global_scope, oc, MDL)) {
 
5364
                log_error("dhcpv6_forw_relay: error evaluating "
 
5365
                          "relayed message.");
 
5366
                goto exit;
 
5367
        }
 
5368
 
 
5369
        if (!packet6_len_okay((char *)enc_opt_data.data, enc_opt_data.len)) {
 
5370
                log_error("dhcpv6_forw_relay: encapsulated packet too short.");
 
5371
                goto exit;
 
5372
        }
 
5373
 
 
5374
        /*
 
5375
         * Build a packet structure from this encapsulated packet.
 
5376
         */
 
5377
        enc_packet = NULL;
 
5378
        if (!packet_allocate(&enc_packet, MDL)) {
 
5379
                log_error("dhcpv6_forw_relay: "
 
5380
                          "no memory for encapsulated packet.");
 
5381
                goto exit;
 
5382
        }
 
5383
 
 
5384
        if (!option_state_allocate(&enc_packet->options, MDL)) {
 
5385
                log_error("dhcpv6_forw_relay: "
 
5386
                          "no memory for encapsulated packet's options.");
 
5387
                goto exit;
 
5388
        }
 
5389
 
 
5390
        enc_packet->client_port = packet->client_port;
 
5391
        enc_packet->client_addr = packet->client_addr;
 
5392
        enc_packet->dhcpv6_container_packet = packet;
 
5393
 
 
5394
        msg_type = enc_opt_data.data[0];
 
5395
        if ((msg_type == DHCPV6_RELAY_FORW) ||
 
5396
            (msg_type == DHCPV6_RELAY_REPL)) {
 
5397
                relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
 
5398
                enc_packet->dhcpv6_msg_type = relay->msg_type;
 
5399
 
 
5400
                /* relay-specific data */
 
5401
                enc_packet->dhcpv6_hop_count = relay->hop_count;
 
5402
                memcpy(&enc_packet->dhcpv6_link_address,
 
5403
                       relay->link_address, sizeof(relay->link_address));
 
5404
                memcpy(&enc_packet->dhcpv6_peer_address,
 
5405
                       relay->peer_address, sizeof(relay->peer_address));
 
5406
 
 
5407
                if (!parse_option_buffer(enc_packet->options,
 
5408
                                         relay->options, 
 
5409
                                         enc_opt_data.len-sizeof(*relay),
 
5410
                                         &dhcpv6_universe)) {
 
5411
                        /* no logging here, as parse_option_buffer() logs all
 
5412
                           cases where it fails */
 
5413
                        goto exit;
 
5414
                }
 
5415
        } else {
 
5416
                msg = (struct dhcpv6_packet *)enc_opt_data.data;
 
5417
                enc_packet->dhcpv6_msg_type = msg->msg_type;
 
5418
 
 
5419
                /* message-specific data */
 
5420
                memcpy(enc_packet->dhcpv6_transaction_id,
 
5421
                       msg->transaction_id,
 
5422
                       sizeof(enc_packet->dhcpv6_transaction_id));
 
5423
 
 
5424
                if (!parse_option_buffer(enc_packet->options,
 
5425
                                         msg->options, 
 
5426
                                         enc_opt_data.len-sizeof(*msg),
 
5427
                                         &dhcpv6_universe)) {
 
5428
                        /* no logging here, as parse_option_buffer() logs all
 
5429
                           cases where it fails */
 
5430
                        goto exit;
 
5431
                }
 
5432
        }
 
5433
 
 
5434
        /*
 
5435
         * This is recursive. It is possible to exceed maximum packet size.
 
5436
         * XXX: This will cause the packet send to fail.
 
5437
         */
 
5438
        build_dhcpv6_reply(&enc_reply, enc_packet);
 
5439
 
 
5440
        /*
 
5441
         * If we got no encapsulated data, then it is discarded, and
 
5442
         * our reply-forw is also discarded.
 
5443
         */
 
5444
        if (enc_reply.data == NULL) {
 
5445
                goto exit;
 
5446
        }
 
5447
 
 
5448
        /*
 
5449
         * Now we can use the reply_data buffer.
 
5450
         * Packet header stuff all comes from the forward message.
 
5451
         */
 
5452
        reply = (struct dhcpv6_relay_packet *)reply_data;
 
5453
        reply->msg_type = DHCPV6_RELAY_REPL;
 
5454
        reply->hop_count = packet->dhcpv6_hop_count;
 
5455
        memcpy(reply->link_address, &packet->dhcpv6_link_address,
 
5456
               sizeof(reply->link_address));
 
5457
        memcpy(reply->peer_address, &packet->dhcpv6_peer_address,
 
5458
               sizeof(reply->peer_address));
 
5459
        reply_ofs = (int)((char *)reply->options - (char *)reply);
 
5460
 
 
5461
        /*
 
5462
         * Get the reply option state.
 
5463
         */
 
5464
        opt_state = NULL;
 
5465
        if (!option_state_allocate(&opt_state, MDL)) {
 
5466
                log_error("dhcpv6_relay_forw: no memory for option state.");
 
5467
                goto exit;
 
5468
        }
 
5469
 
 
5470
        /*
 
5471
         * Append the interface-id if present.
 
5472
         */
 
5473
        oc = lookup_option(&dhcpv6_universe, packet->options,
 
5474
                           D6O_INTERFACE_ID);
 
5475
        if (oc != NULL) {
 
5476
                if (!evaluate_option_cache(&a_opt, packet,
 
5477
                                           NULL, NULL, 
 
5478
                                           packet->options, NULL,
 
5479
                                           &global_scope, oc, MDL)) {
 
5480
                        log_error("dhcpv6_relay_forw: error evaluating "
 
5481
                                  "Interface ID.");
 
5482
                        goto exit;
 
5483
                }
 
5484
                if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
 
5485
                                        (unsigned char *)a_opt.data,
 
5486
                                        a_opt.len,
 
5487
                                        D6O_INTERFACE_ID, 0)) {
 
5488
                        log_error("dhcpv6_relay_forw: error saving "
 
5489
                                  "Interface ID.");
 
5490
                        goto exit;
 
5491
                }
 
5492
                data_string_forget(&a_opt, MDL);
 
5493
        }
 
5494
 
 
5495
        /* 
 
5496
         * Append our encapsulated stuff for caller.
 
5497
         */
 
5498
        if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
 
5499
                                (unsigned char *)enc_reply.data,
 
5500
                                enc_reply.len,
 
5501
                                D6O_RELAY_MSG, 0)) {
 
5502
                log_error("dhcpv6_relay_forw: error saving Relay MSG.");
 
5503
                goto exit;
 
5504
        }
 
5505
 
 
5506
        /*
 
5507
         * Get the ERO if any.
 
5508
         */
 
5509
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ERO);
 
5510
        if (oc != NULL) {
 
5511
                unsigned req;
 
5512
                int i;
 
5513
 
 
5514
                if (!evaluate_option_cache(&packet_ero, packet,
 
5515
                                           NULL, NULL,
 
5516
                                           packet->options, NULL,
 
5517
                                           &global_scope, oc, MDL) ||
 
5518
                        (packet_ero.len & 1)) {
 
5519
                        log_error("dhcpv6_relay_forw: error evaluating ERO.");
 
5520
                        goto exit;
 
5521
                }
 
5522
 
 
5523
                /* Decode and apply the ERO. */
 
5524
                for (i = 0; i < packet_ero.len; i += 2) {
 
5525
                        req = getUShort(packet_ero.data + i);
 
5526
                        /* Already in the reply? */
 
5527
                        oc = lookup_option(&dhcpv6_universe, opt_state, req);
 
5528
                        if (oc != NULL)
 
5529
                                continue;
 
5530
                        /* Get it from the packet if present. */
 
5531
                        oc = lookup_option(&dhcpv6_universe,
 
5532
                                           packet->options,
 
5533
                                           req);
 
5534
                        if (oc == NULL)
 
5535
                                continue;
 
5536
                        if (!evaluate_option_cache(&a_opt, packet,
 
5537
                                                   NULL, NULL,
 
5538
                                                   packet->options, NULL,
 
5539
                                                   &global_scope, oc, MDL)) {
 
5540
                                log_error("dhcpv6_relay_forw: error "
 
5541
                                          "evaluating option %u.", req);
 
5542
                                goto exit;
 
5543
                        }
 
5544
                        if (!save_option_buffer(&dhcpv6_universe,
 
5545
                                                opt_state,
 
5546
                                                NULL,
 
5547
                                                (unsigned char *)a_opt.data,
 
5548
                                                a_opt.len,
 
5549
                                                req,
 
5550
                                                0)) {
 
5551
                                log_error("dhcpv6_relay_forw: error saving "
 
5552
                                          "option %u.", req);
 
5553
                                goto exit;
 
5554
                        }
 
5555
                        data_string_forget(&a_opt, MDL);
 
5556
                }
 
5557
        }
 
5558
 
 
5559
        reply_ofs += store_options6(reply_data + reply_ofs,
 
5560
                                    sizeof(reply_data) - reply_ofs,
 
5561
                                    opt_state, packet,
 
5562
                                    required_opts_agent, &packet_ero);
 
5563
 
 
5564
        /*
 
5565
         * Return our reply to the caller.
 
5566
         */
 
5567
        reply_ret->len = reply_ofs;
 
5568
        reply_ret->buffer = NULL;
 
5569
        if (!buffer_allocate(&reply_ret->buffer, reply_ret->len, MDL)) {
 
5570
                log_fatal("No memory to store reply.");
 
5571
        }
 
5572
        reply_ret->data = reply_ret->buffer->data;
 
5573
        memcpy(reply_ret->buffer->data, reply_data, reply_ofs);
 
5574
 
 
5575
exit:
 
5576
        if (opt_state != NULL)
 
5577
                option_state_dereference(&opt_state, MDL);
 
5578
        if (a_opt.data != NULL) {
 
5579
                data_string_forget(&a_opt, MDL);
 
5580
        }
 
5581
        if (packet_ero.data != NULL) {
 
5582
                data_string_forget(&packet_ero, MDL);
 
5583
        }
 
5584
        if (enc_reply.data != NULL) {
 
5585
                data_string_forget(&enc_reply, MDL);
 
5586
        }
 
5587
        if (enc_opt_data.data != NULL) {
 
5588
                data_string_forget(&enc_opt_data, MDL);
 
5589
        }
 
5590
        if (enc_packet != NULL) {
 
5591
                packet_dereference(&enc_packet, MDL);
 
5592
        }
 
5593
}
 
5594
 
 
5595
static void
 
5596
dhcpv6_discard(struct packet *packet) {
 
5597
        /* INSIST(packet->msg_type > 0); */
 
5598
        /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
 
5599
 
 
5600
        log_debug("Discarding %s from %s; message type not handled by server", 
 
5601
                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 
5602
                  piaddr(packet->client_addr));
 
5603
}
 
5604
 
 
5605
static void 
 
5606
build_dhcpv6_reply(struct data_string *reply, struct packet *packet) {
 
5607
        memset(reply, 0, sizeof(*reply));
 
5608
        switch (packet->dhcpv6_msg_type) {
 
5609
                case DHCPV6_SOLICIT:
 
5610
                        dhcpv6_solicit(reply, packet);
 
5611
                        break;
 
5612
                case DHCPV6_ADVERTISE:
 
5613
                        dhcpv6_discard(packet);
 
5614
                        break;
 
5615
                case DHCPV6_REQUEST:
 
5616
                        dhcpv6_request(reply, packet);
 
5617
                        break;
 
5618
                case DHCPV6_CONFIRM:
 
5619
                        dhcpv6_confirm(reply, packet);
 
5620
                        break;
 
5621
                case DHCPV6_RENEW:
 
5622
                        dhcpv6_renew(reply, packet);
 
5623
                        break;
 
5624
                case DHCPV6_REBIND:
 
5625
                        dhcpv6_rebind(reply, packet);
 
5626
                        break;
 
5627
                case DHCPV6_REPLY:
 
5628
                        dhcpv6_discard(packet);
 
5629
                        break;
 
5630
                case DHCPV6_RELEASE:
 
5631
                        dhcpv6_release(reply, packet);
 
5632
                        break;
 
5633
                case DHCPV6_DECLINE:
 
5634
                        dhcpv6_decline(reply, packet);
 
5635
                        break;
 
5636
                case DHCPV6_RECONFIGURE:
 
5637
                        dhcpv6_discard(packet);
 
5638
                        break;
 
5639
                case DHCPV6_INFORMATION_REQUEST:
 
5640
                        dhcpv6_information_request(reply, packet);
 
5641
                        break;
 
5642
                case DHCPV6_RELAY_FORW:
 
5643
                        dhcpv6_relay_forw(reply, packet);
 
5644
                        break;
 
5645
                case DHCPV6_RELAY_REPL:
 
5646
                        dhcpv6_discard(packet);
 
5647
                        break;
 
5648
                case DHCPV6_LEASEQUERY:
 
5649
                        dhcpv6_leasequery(reply, packet);
 
5650
                        break;
 
5651
                case DHCPV6_LEASEQUERY_REPLY:
 
5652
                        dhcpv6_discard(packet);
 
5653
                        break;
 
5654
                default:
 
5655
                        /* XXX: would be nice if we had "notice" level, 
 
5656
                                as syslog, for this */
 
5657
                        log_info("Discarding unknown DHCPv6 message type %d "
 
5658
                                 "from %s", packet->dhcpv6_msg_type, 
 
5659
                                 piaddr(packet->client_addr));
 
5660
        }
 
5661
}
 
5662
 
 
5663
static void
 
5664
log_packet_in(const struct packet *packet) {
 
5665
        struct data_string s;
 
5666
        u_int32_t tid;
 
5667
        char tmp_addr[INET6_ADDRSTRLEN];
 
5668
        const void *addr;
 
5669
 
 
5670
        memset(&s, 0, sizeof(s));
 
5671
 
 
5672
        if (packet->dhcpv6_msg_type < dhcpv6_type_name_max) {
 
5673
                data_string_sprintfa(&s, "%s message from %s port %d",
 
5674
                                     dhcpv6_type_names[packet->dhcpv6_msg_type],
 
5675
                                     piaddr(packet->client_addr),
 
5676
                                     ntohs(packet->client_port));
 
5677
        } else {
 
5678
                data_string_sprintfa(&s, 
 
5679
                                     "Unknown message type %d from %s port %d",
 
5680
                                     packet->dhcpv6_msg_type,
 
5681
                                     piaddr(packet->client_addr),
 
5682
                                     ntohs(packet->client_port));
 
5683
        }
 
5684
        if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) || 
 
5685
            (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
 
5686
                addr = &packet->dhcpv6_link_address;
 
5687
                data_string_sprintfa(&s, ", link address %s", 
 
5688
                                     inet_ntop(AF_INET6, addr, 
 
5689
                                               tmp_addr, sizeof(tmp_addr)));
 
5690
                addr = &packet->dhcpv6_peer_address;
 
5691
                data_string_sprintfa(&s, ", peer address %s", 
 
5692
                                     inet_ntop(AF_INET6, addr, 
 
5693
                                               tmp_addr, sizeof(tmp_addr)));
 
5694
        } else {
 
5695
                tid = 0;
 
5696
                memcpy(((char *)&tid)+1, packet->dhcpv6_transaction_id, 3);
 
5697
                data_string_sprintfa(&s, ", transaction ID 0x%06X", tid);
 
5698
 
 
5699
/*
 
5700
                oc = lookup_option(&dhcpv6_universe, packet->options, 
 
5701
                                   D6O_CLIENTID);
 
5702
                if (oc != NULL) {
 
5703
                        memset(&tmp_ds, 0, sizeof(tmp_ds_));
 
5704
                        if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL, 
 
5705
                                                   packet->options, NULL,
 
5706
                                                   &global_scope, oc, MDL)) {
 
5707
                                log_error("Error evaluating Client Identifier");
 
5708
                        } else {
 
5709
                                data_strint_sprintf(&s, ", client ID %s",
 
5710
 
 
5711
                                data_string_forget(&tmp_ds, MDL);
 
5712
                        }
 
5713
                }
 
5714
*/
 
5715
 
 
5716
        }
 
5717
        log_info("%s", s.data);
 
5718
 
 
5719
        data_string_forget(&s, MDL);
 
5720
}
 
5721
 
 
5722
void 
 
5723
dhcpv6(struct packet *packet) {
 
5724
        struct data_string reply;
 
5725
        struct sockaddr_in6 to_addr;
 
5726
        int send_ret;
 
5727
 
 
5728
        /* 
 
5729
         * Log a message that we received this packet.
 
5730
         */
 
5731
        log_packet_in(packet); 
 
5732
 
 
5733
        /*
 
5734
         * Build our reply packet.
 
5735
         */
 
5736
        build_dhcpv6_reply(&reply, packet);
 
5737
 
 
5738
        if (reply.data != NULL) {
 
5739
                /* 
 
5740
                 * Send our reply, if we have one.
 
5741
                 */
 
5742
                memset(&to_addr, 0, sizeof(to_addr));
 
5743
                to_addr.sin6_family = AF_INET6;
 
5744
                if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) || 
 
5745
                    (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
 
5746
                        to_addr.sin6_port = local_port;
 
5747
                } else {
 
5748
                        to_addr.sin6_port = remote_port;
 
5749
                }
 
5750
/* For testing, we reply to the sending port, so we don't need a root client */
 
5751
                to_addr.sin6_port = packet->client_port;
 
5752
                memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf, 
 
5753
                       sizeof(to_addr.sin6_addr));
 
5754
 
 
5755
                log_info("Sending %s to %s port %d", 
 
5756
                         dhcpv6_type_names[reply.data[0]],
 
5757
                         piaddr(packet->client_addr),
 
5758
                         ntohs(to_addr.sin6_port));
 
5759
 
 
5760
                send_ret = send_packet6(packet->interface, 
 
5761
                                        reply.data, reply.len, &to_addr);
 
5762
                if (send_ret != reply.len) {
 
5763
                        log_error("dhcpv6: send_packet6() sent %d of %d bytes",
 
5764
                                  send_ret, reply.len);
 
5765
                }
 
5766
                data_string_forget(&reply, MDL);
 
5767
        }
 
5768
}
 
5769
 
 
5770
static void
 
5771
seek_shared_host(struct host_decl **hp, struct shared_network *shared) {
 
5772
        struct host_decl *nofixed = NULL;
 
5773
        struct host_decl *seek, *hold = NULL;
 
5774
 
 
5775
        /*
 
5776
         * Seek forward through fixed addresses for the right link.
 
5777
         *
 
5778
         * Note: how to do this for fixed prefixes???
 
5779
         */
 
5780
        host_reference(&hold, *hp, MDL);
 
5781
        host_dereference(hp, MDL);
 
5782
        seek = hold;
 
5783
        while (seek != NULL) {
 
5784
                if (seek->fixed_addr == NULL)
 
5785
                        nofixed = seek;
 
5786
                else if (fixed_matches_shared(seek, shared))
 
5787
                        break;
 
5788
 
 
5789
                seek = seek->n_ipaddr;
 
5790
        }
 
5791
 
 
5792
        if ((seek == NULL) && (nofixed != NULL))
 
5793
                seek = nofixed;
 
5794
 
 
5795
        if (seek != NULL)
 
5796
                host_reference(hp, seek, MDL);
 
5797
}
 
5798
 
 
5799
static isc_boolean_t
 
5800
fixed_matches_shared(struct host_decl *host, struct shared_network *shared) {
 
5801
        struct subnet *subnet;
 
5802
        struct data_string addr;
 
5803
        isc_boolean_t matched;
 
5804
        struct iaddr fixed;
 
5805
 
 
5806
        if (host->fixed_addr == NULL)
 
5807
                return ISC_FALSE;
 
5808
 
 
5809
        memset(&addr, 0, sizeof(addr));
 
5810
        if (!evaluate_option_cache(&addr, NULL, NULL, NULL, NULL, NULL,
 
5811
                                   &global_scope, host->fixed_addr, MDL))
 
5812
                return ISC_FALSE;
 
5813
 
 
5814
        if (addr.len < 16) {
 
5815
                data_string_forget(&addr, MDL);
 
5816
                return ISC_FALSE;
 
5817
        }
 
5818
 
 
5819
        fixed.len = 16;
 
5820
        memcpy(fixed.iabuf, addr.data, 16);
 
5821
 
 
5822
        matched = ISC_FALSE;
 
5823
        for (subnet = shared->subnets ; subnet != NULL ;
 
5824
             subnet = subnet->next_sibling) {
 
5825
                if (addr_eq(subnet_number(fixed, subnet->netmask),
 
5826
                            subnet->net)) {
 
5827
                        matched = ISC_TRUE;
 
5828
                        break;
 
5829
                }
 
5830
        }
 
5831
 
 
5832
        data_string_forget(&addr, MDL);
 
5833
        return matched;
 
5834
}
 
5835
 
 
5836
#endif /* DHCPv6 */
 
5837