Coverage Report

Created: 2025-10-13 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dnsmasq/src/rfc3315.c
Line
Count
Source
1
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 dated June, 1991, or
6
   (at your option) version 3 dated 29 June, 2007.
7
 
8
   This program is distributed in the hope that it will be useful,
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
   GNU General Public License for more details.
12
     
13
   You should have received a copy of the GNU General Public License
14
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
*/
16
17
18
#include "dnsmasq.h"
19
20
#ifdef HAVE_DHCP6
21
22
struct state {
23
  unsigned char *clid;
24
  int multicast_dest, clid_len, ia_type, interface, hostname_auth, lease_allocate;
25
  char *client_hostname, *hostname, *domain, *send_domain;
26
  struct dhcp_context *context;
27
  struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
28
  unsigned int xid, fqdn_flags, iaid;
29
  char *iface_name;
30
  void *packet_options, *end;
31
  struct dhcp_netid *tags, *context_tags;
32
  unsigned char mac[DHCP_CHADDR_MAX];
33
  unsigned int mac_len, mac_type;
34
};
35
36
static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz, 
37
           struct in6_addr *client_addr, int is_unicast, time_t now);
38
static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now);
39
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
40
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
41
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
42
static void *opt6_find (uint8_t *opts, uint8_t *end, unsigned int search, unsigned int minsize);
43
static void *opt6_next(uint8_t *opts, uint8_t *end);
44
static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
45
static void get_context_tag(struct state *state, struct dhcp_context *context);
46
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
47
static int build_ia(struct state *state, int *t1cntr);
48
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
49
static void mark_context_used(struct state *state, struct in6_addr *addr);
50
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
51
static int check_address(struct state *state, struct in6_addr *addr);
52
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now);
53
static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
54
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option, 
55
      unsigned int *min_time, struct in6_addr *addr, time_t now);
56
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
57
static int add_local_addrs(struct dhcp_context *context);
58
static struct dhcp_netid *add_options(struct state *state, int do_refresh);
59
static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep, 
60
          unsigned int *preferred_timep, unsigned int lease_time);
61
62
0
#define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
63
0
#define opt6_type(opt) (opt6_uint(opt, -4, 2))
64
0
#define opt6_ptr(opt, i) ((void *)&(((uint8_t *)(opt))[4+(i)]))
65
66
0
#define opt6_user_vendor_ptr(opt, i) ((void *)&(((uint8_t *)(opt))[2+(i)]))
67
0
#define opt6_user_vendor_len(opt) ((int)(opt6_uint(opt, -4, 2)))
68
0
#define opt6_user_vendor_next(opt, end) (opt6_next(((uint8_t *) opt) - 2, end))
69
 
70
71
unsigned short dhcp6_reply(struct dhcp_context *context, int multicast_dest, int interface, char *iface_name,
72
         struct in6_addr *fallback,  struct in6_addr *ll_addr, struct in6_addr *ula_addr,
73
         size_t sz, struct in6_addr *client_addr, time_t now)
74
0
{
75
0
  struct dhcp_vendor *vendor;
76
0
  int msg_type;
77
0
  struct state state;
78
  
79
0
  if (sz <= 4)
80
0
    return 0;
81
  
82
0
  msg_type = *((unsigned char *)daemon->dhcp_packet.iov_base);
83
  
84
  /* Mark these so we only match each at most once, to avoid tangled linked lists */
85
0
  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
86
0
    vendor->netid.next = &vendor->netid;
87
  
88
0
  reset_counter();
89
0
  state.context = context;
90
0
  state.multicast_dest = multicast_dest;
91
0
  state.interface = interface;
92
0
  state.iface_name = iface_name;
93
0
  state.fallback = fallback;
94
0
  state.ll_addr = ll_addr;
95
0
  state.ula_addr = ula_addr;
96
0
  state.mac_len = 0;
97
0
  state.tags = NULL;
98
0
  state.link_address = NULL;
99
100
0
  if (dhcp6_maybe_relay(&state, daemon->dhcp_packet.iov_base, sz, client_addr, 
101
0
      IN6_IS_ADDR_MULTICAST(client_addr), now))
102
0
    return msg_type == DHCP6RELAYFORW ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
103
104
0
  return 0;
105
0
}
106
107
/* This cost me blood to write, it will probably cost you blood to understand - srk. */
108
static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz, 
109
           struct in6_addr *client_addr, int is_unicast, time_t now)
110
0
{
111
0
  uint8_t *end = inbuff + sz;
112
0
  uint8_t *opts = inbuff + 34;
113
0
  int msg_type = *inbuff;
114
0
  unsigned char *outmsgtypep;
115
0
  uint8_t *opt;
116
0
  struct dhcp_vendor *vendor;
117
118
  /* if not an encapsulated relayed message, just do the stuff */
119
0
  if (msg_type != DHCP6RELAYFORW)
120
0
    {
121
      /* if link_address != NULL if points to the link address field of the 
122
   innermost nested RELAYFORW message, which is where we find the
123
   address of the network on which we can allocate an address.
124
   Recalculate the available contexts using that information. 
125
126
      link_address == NULL means there's no relay in use, so we try and find the client's 
127
      MAC address from the local ND cache. */
128
      
129
0
      if (!state->link_address)
130
0
  get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type, now);
131
0
      else
132
0
  {
133
0
    struct dhcp_context *c;
134
0
    struct shared_network *share = NULL;
135
0
    state->context = NULL;
136
137
0
    if (!IN6_IS_ADDR_LOOPBACK(state->link_address) &&
138
0
        !IN6_IS_ADDR_LINKLOCAL(state->link_address) &&
139
0
        !IN6_IS_ADDR_MULTICAST(state->link_address))
140
0
      for (c = daemon->dhcp6; c; c = c->next)
141
0
        {
142
0
    for (share = daemon->shared_networks; share; share = share->next)
143
0
      {
144
0
        if (share->shared_addr.s_addr != 0)
145
0
          continue;
146
        
147
0
        if (share->if_index != 0 ||
148
0
      !IN6_ARE_ADDR_EQUAL(state->link_address, &share->match_addr6))
149
0
          continue;
150
        
151
0
        if ((c->flags & CONTEXT_DHCP) &&
152
0
      !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
153
0
      is_same_net6(&share->shared_addr6, &c->start6, c->prefix) &&
154
0
      is_same_net6(&share->shared_addr6, &c->end6, c->prefix))
155
0
          break;
156
0
      }
157
    
158
0
    if (share ||
159
0
        ((c->flags & CONTEXT_DHCP) &&
160
0
         !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
161
0
         is_same_net6(state->link_address, &c->start6, c->prefix) &&
162
0
         is_same_net6(state->link_address, &c->end6, c->prefix)))
163
0
      {
164
0
        c->preferred = c->valid = 0xffffffff;
165
0
        c->current = state->context;
166
0
        state->context = c;
167
0
      }
168
0
        }
169
    
170
0
    if (!state->context)
171
0
      {
172
0
        inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN); 
173
0
        my_syslog(MS_DHCP | LOG_WARNING, 
174
0
      _("no address range available for DHCPv6 request from relay at %s"),
175
0
      daemon->addrbuff);
176
0
        return 0;
177
0
      }
178
0
  }
179
    
180
0
      if (!state->context)
181
0
  {
182
0
    my_syslog(MS_DHCP | LOG_WARNING, 
183
0
        _("no address range available for DHCPv6 request via %s"), state->iface_name);
184
0
    return 0;
185
0
  }
186
187
0
      return dhcp6_no_relay(state, msg_type, inbuff, sz, is_unicast, now);
188
0
    }
189
190
  /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
191
     which is               1   +    1   +    16      +     16     + 2 + 2 = 38 */
192
0
  if (sz < 38)
193
0
    return 0;
194
  
195
  /* copy header stuff into reply message and set type to reply */
196
0
  if (!(outmsgtypep = put_opt6(inbuff, 34)))
197
0
    return 0;
198
0
  *outmsgtypep = DHCP6RELAYREPL;
199
200
  /* look for relay options and set tags if found. */
201
0
  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
202
0
    {
203
0
      int mopt;
204
      
205
0
      if (vendor->match_type == MATCH_SUBSCRIBER)
206
0
  mopt = OPTION6_SUBSCRIBER_ID;
207
0
      else if (vendor->match_type == MATCH_REMOTE)
208
0
  mopt = OPTION6_REMOTE_ID; 
209
0
      else
210
0
  continue;
211
212
0
      if ((opt = opt6_find(opts, end, mopt, 1)) &&
213
0
    vendor->len == opt6_len(opt) &&
214
0
    memcmp(vendor->data, opt6_ptr(opt, 0), vendor->len) == 0 &&
215
0
    vendor->netid.next != &vendor->netid)
216
0
  {
217
0
    vendor->netid.next = state->tags;
218
0
    state->tags = &vendor->netid;
219
0
    break;
220
0
  }
221
0
    }
222
  
223
  /* RFC-6939 */
224
0
  if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
225
0
    {
226
0
      if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
227
0
        return 0;
228
0
      }
229
0
      state->mac_type = opt6_uint(opt, 0, 2);
230
0
      state->mac_len = opt6_len(opt) - 2;
231
0
      memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
232
0
    }
233
  
234
0
  for (opt = opts; opt; opt = opt6_next(opt, end))
235
0
    {
236
0
      if ((uint8_t *)opt6_ptr(opt, 0) + opt6_len(opt) > end)
237
0
        return 0;
238
     
239
      /* Don't copy MAC address into reply. */
240
0
      if (opt6_type(opt) != OPTION6_CLIENT_MAC)
241
0
  {
242
0
    int o = new_opt6(opt6_type(opt));
243
0
    if (opt6_type(opt) == OPTION6_RELAY_MSG)
244
0
      {
245
0
        struct in6_addr align;
246
        /* the packet data is unaligned, copy to aligned storage */
247
0
        memcpy(&align, inbuff + 2, IN6ADDRSZ); 
248
249
250
        /* RFC6221 para 4 */
251
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&align))
252
0
    state->link_address = &align;
253
        /* zero is_unicast since that is now known to refer to the 
254
     relayed packet, not the original sent by the client */
255
0
        if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
256
0
    return 0;
257
0
      }
258
0
    else
259
0
      put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
260
0
    end_opt6(o);
261
0
  }
262
0
    }
263
  
264
0
  return 1;
265
0
}
266
267
static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now)
268
0
{
269
0
  void *opt;
270
0
  int i, o, o1, start_opts, start_msg;
271
0
  struct dhcp_opt *opt_cfg;
272
0
  struct dhcp_netid *tagif;
273
0
  struct dhcp_config *config = NULL;
274
0
  struct dhcp_netid known_id, iface_id, v6_id;
275
0
  unsigned char outmsgtype;
276
0
  struct dhcp_vendor *vendor;
277
0
  struct dhcp_context *context_tmp;
278
0
  struct dhcp_mac *mac_opt;
279
0
  unsigned int ignore = 0;
280
281
0
  state->packet_options = inbuff + 4;
282
0
  state->end = inbuff + sz;
283
0
  state->clid = NULL;
284
0
  state->clid_len = 0;
285
0
  state->lease_allocate = 0;
286
0
  state->context_tags = NULL;
287
0
  state->domain = NULL;
288
0
  state->send_domain = NULL;
289
0
  state->hostname_auth = 0;
290
0
  state->hostname = NULL;
291
0
  state->client_hostname = NULL;
292
0
  state->fqdn_flags = 0x01; /* default to send if we receive no FQDN option */
293
294
  /* set tag with name == interface */
295
0
  iface_id.net = state->iface_name;
296
0
  iface_id.next = state->tags;
297
0
  state->tags = &iface_id; 
298
299
  /* set tag "dhcpv6" */
300
0
  v6_id.net = "dhcpv6";
301
0
  v6_id.next = state->tags;
302
0
  state->tags = &v6_id;
303
304
0
  start_msg = save_counter(-1);
305
  /* copy over transaction-id */
306
0
  if (!put_opt6(inbuff, 4))
307
0
    return 0;
308
0
  start_opts = save_counter(-1);
309
0
  state->xid = inbuff[3] | inbuff[2] << 8 | inbuff[1] << 16;
310
    
311
  /* We're going to be linking tags from all context we use. 
312
     mark them as unused so we don't link one twice and break the list */
313
0
  for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
314
0
    {
315
0
      context_tmp->netid.next = &context_tmp->netid;
316
317
0
      if (option_bool(OPT_LOG_OPTS))
318
0
  {
319
0
     inet_ntop(AF_INET6, &context_tmp->start6, daemon->dhcp_buff, ADDRSTRLEN); 
320
0
     inet_ntop(AF_INET6, &context_tmp->end6, daemon->dhcp_buff2, ADDRSTRLEN); 
321
0
     if (context_tmp->flags & (CONTEXT_STATIC))
322
0
       my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCPv6 subnet: %s/%d"),
323
0
           state->xid, daemon->dhcp_buff, context_tmp->prefix);
324
0
     else
325
0
       my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"), 
326
0
           state->xid, daemon->dhcp_buff, daemon->dhcp_buff2);
327
0
  }
328
0
    }
329
330
0
  if ((opt = opt6_find(state->packet_options, state->end, OPTION6_CLIENT_ID, 1)))
331
0
    {
332
0
      state->clid = opt6_ptr(opt, 0);
333
0
      state->clid_len = opt6_len(opt);
334
0
      o = new_opt6(OPTION6_CLIENT_ID);
335
0
      put_opt6(state->clid, state->clid_len);
336
0
      end_opt6(o);
337
0
    }
338
0
  else if (msg_type != DHCP6IREQ)
339
0
    return 0;
340
341
0
  opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1);
342
  
343
0
  if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND || msg_type == DHCP6IREQ)
344
0
    {
345
      /* Above message types must be multicast 3315 Section 15. */
346
0
      if (!state->multicast_dest)
347
0
  return 0;
348
349
      /* server-id must match except for SOLICIT, CONFIRM and REBIND messages, which MUST NOT
350
   have a server-id.  3315 para 15.x */
351
0
      if (msg_type == DHCP6IREQ)
352
0
  {
353
    /* If server-id provided in IREQ, it must match. */
354
0
    if (opt && (opt6_len(opt) != daemon->duid_len ||
355
0
          memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
356
0
      return 0;
357
0
  }
358
0
      else if (opt) 
359
0
  return 0;
360
0
    }
361
0
  else
362
0
    {
363
      /* Everything else MUST have a server-id that matches ours. */
364
0
      if (!opt || opt6_len(opt) != daemon->duid_len ||
365
0
    memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0)
366
0
  return 0;
367
0
    }
368
  
369
0
  o = new_opt6(OPTION6_SERVER_ID);
370
0
  put_opt6(daemon->duid, daemon->duid_len);
371
0
  end_opt6(o);
372
373
0
  if (is_unicast &&
374
0
      (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
375
    
376
0
    {  
377
0
      outmsgtype = DHCP6REPLY;
378
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
379
0
      put_opt6_short(DHCP6USEMULTI);
380
0
      put_opt6_string("Use multicast");
381
0
      end_opt6(o1);
382
0
      goto done;
383
0
    }
384
385
  /* match vendor and user class options */
386
0
  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
387
0
    {
388
0
      int mopt;
389
      
390
0
      if (vendor->match_type == MATCH_VENDOR)
391
0
  mopt = OPTION6_VENDOR_CLASS;
392
0
      else if (vendor->match_type == MATCH_USER)
393
0
  mopt = OPTION6_USER_CLASS; 
394
0
      else
395
0
  continue;
396
397
0
      if ((opt = opt6_find(state->packet_options, state->end, mopt, 2)))
398
0
  {
399
0
    void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
400
0
    int offset = 0;
401
    
402
0
    if (mopt == OPTION6_VENDOR_CLASS)
403
0
      {
404
0
        if (opt6_len(opt) < 4)
405
0
    continue;
406
        
407
0
        if (vendor->enterprise != opt6_uint(opt, 0, 4))
408
0
    continue;
409
      
410
0
        offset = 4;
411
0
      }
412
 
413
    /* Note that format if user/vendor classes is different to DHCP options - no option types. */
414
0
    for (enc_opt = opt6_ptr(opt, offset); enc_opt; enc_opt = opt6_user_vendor_next(enc_opt, enc_end))
415
0
      for (i = 0; i <= (opt6_user_vendor_len(enc_opt) - vendor->len); i++)
416
0
        if (memcmp(vendor->data, opt6_user_vendor_ptr(enc_opt, i), vendor->len) == 0)
417
0
    {
418
0
      vendor->netid.next = state->tags;
419
0
      state->tags = &vendor->netid;
420
0
      break;
421
0
    }
422
0
  }
423
0
    }
424
425
0
  if (option_bool(OPT_LOG_OPTS) && (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
426
0
    my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %u"), state->xid, opt6_uint(opt, 0, 4));
427
  
428
  /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
429
     Otherwise assume the option is an array, and look for a matching element. 
430
     If no data given, existence of the option is enough. This code handles 
431
     V-I opts too. */
432
0
  for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
433
0
    {
434
0
      int match = 0;
435
      
436
0
      if (opt_cfg->flags & DHOPT_RFC3925)
437
0
  {
438
0
    for (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_OPTS, 4);
439
0
         opt;
440
0
         opt = opt6_find(opt6_next(opt, state->end), state->end, OPTION6_VENDOR_OPTS, 4))
441
0
      {
442
0
        void *vopt;
443
0
        void *vend = opt6_ptr(opt, opt6_len(opt));
444
        
445
0
        for (vopt = opt6_find(opt6_ptr(opt, 4), vend, opt_cfg->opt, 0);
446
0
       vopt;
447
0
       vopt = opt6_find(opt6_next(vopt, vend), vend, opt_cfg->opt, 0))
448
0
    if ((match = match_bytes(opt_cfg, opt6_ptr(vopt, 0), opt6_len(vopt))))
449
0
      break;
450
0
      }
451
0
    if (match)
452
0
      break;
453
0
  }
454
0
      else
455
0
  {
456
0
    if (!(opt = opt6_find(state->packet_options, state->end, opt_cfg->opt, 1)))
457
0
      continue;
458
    
459
0
    match = match_bytes(opt_cfg, opt6_ptr(opt, 0), opt6_len(opt));
460
0
  } 
461
  
462
0
      if (match)
463
0
  {
464
0
    opt_cfg->netid->next = state->tags;
465
0
    state->tags = opt_cfg->netid;
466
0
  }
467
0
    }
468
469
0
  if (state->mac_len != 0)
470
0
    {
471
0
      if (option_bool(OPT_LOG_OPTS))
472
0
  {
473
0
    print_mac(daemon->dhcp_buff, state->mac, state->mac_len);
474
0
    my_syslog(MS_DHCP | LOG_INFO, _("%u client MAC address: %s"), state->xid, daemon->dhcp_buff);
475
0
  }
476
477
0
      for (mac_opt = daemon->dhcp_macs; mac_opt; mac_opt = mac_opt->next)
478
0
  if ((unsigned)mac_opt->hwaddr_len == state->mac_len &&
479
0
      ((unsigned)mac_opt->hwaddr_type == state->mac_type || mac_opt->hwaddr_type == 0) &&
480
0
      memcmp_masked(mac_opt->hwaddr, state->mac, state->mac_len, mac_opt->mask))
481
0
    {
482
0
      mac_opt->netid.next = state->tags;
483
0
      state->tags = &mac_opt->netid;
484
0
    }
485
0
    }
486
0
  else if (option_bool(OPT_LOG_OPTS))
487
0
    my_syslog(MS_DHCP | LOG_INFO, _("%u cannot determine client MAC address"), state->xid);
488
  
489
0
  if ((opt = opt6_find(state->packet_options, state->end, OPTION6_FQDN, 1)))
490
0
    {
491
      /* RFC4704 refers */
492
0
       int len = opt6_len(opt) - 1;
493
       
494
0
       state->fqdn_flags = opt6_uint(opt, 0, 1);
495
       
496
       /* Always force update, since the client has no way to do it itself. */
497
0
       if (!option_bool(OPT_FQDN_UPDATE) && !(state->fqdn_flags & 0x01))
498
0
   state->fqdn_flags |= 0x03;
499
 
500
0
       state->fqdn_flags &= ~0x04;
501
502
0
       if (len != 0 && len < 255)
503
0
   {
504
0
     unsigned char *pp, *op = opt6_ptr(opt, 1);
505
0
     char *pq = daemon->dhcp_buff;
506
     
507
0
     pp = op;
508
0
     while (*op != 0 && ((op + (*op)) - pp) < len)
509
0
       {
510
0
         memcpy(pq, op+1, *op);
511
0
         pq += *op;
512
0
         op += (*op)+1;
513
0
         *(pq++) = '.';
514
0
       }
515
     
516
0
     if (pq != daemon->dhcp_buff)
517
0
       pq--;
518
0
     *pq = 0;
519
     
520
0
     if (legal_hostname(daemon->dhcp_buff))
521
0
       {
522
0
         struct dhcp_match_name *m;
523
0
         size_t nl = strlen(daemon->dhcp_buff);
524
         
525
0
         state->client_hostname = daemon->dhcp_buff;
526
         
527
0
         if (option_bool(OPT_LOG_OPTS))
528
0
     my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), state->xid, state->client_hostname);
529
         
530
0
         for (m = daemon->dhcp_name_match; m; m = m->next)
531
0
     {
532
0
       size_t ml = strlen(m->name);
533
0
       char save = 0;
534
       
535
0
       if (nl < ml)
536
0
         continue;
537
0
       if (nl > ml)
538
0
         {
539
0
           save = state->client_hostname[ml];
540
0
           state->client_hostname[ml] = 0;
541
0
         }
542
       
543
0
       if (hostname_isequal(state->client_hostname, m->name) &&
544
0
           (save == 0 || m->wildcard))
545
0
         {
546
0
           m->netid->next = state->tags;
547
0
           state->tags = m->netid;
548
0
         }
549
       
550
0
       if (save != 0)
551
0
         state->client_hostname[ml] = save;
552
0
     }
553
0
       }
554
0
   }
555
0
    }  
556
  
557
0
  if (state->clid &&
558
0
      (config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len,
559
0
          state->mac, state->mac_len, state->mac_type, NULL, run_tag_if(state->tags))) &&
560
0
      have_config(config, CONFIG_NAME))
561
0
    {
562
0
      state->hostname = config->hostname;
563
0
      state->domain = config->domain;
564
0
      state->hostname_auth = 1;
565
0
    }
566
0
  else if (state->client_hostname)
567
0
    {
568
0
      state->domain = strip_hostname(state->client_hostname);
569
      
570
0
      if (strlen(state->client_hostname) != 0)
571
0
  {
572
0
    state->hostname = state->client_hostname;
573
    
574
0
    if (!config)
575
0
      {
576
        /* Search again now we have a hostname. 
577
     Only accept configs without CLID here, (it won't match)
578
     to avoid impersonation by name. */
579
0
        struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname, run_tag_if(state->tags));
580
0
        if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
581
0
    config = new;
582
0
      }
583
0
  }
584
0
    }
585
586
0
  if (config)
587
0
    {
588
0
      struct dhcp_netid_list *list;
589
      
590
0
      for (list = config->netid; list; list = list->next)
591
0
        {
592
0
          list->list->next = state->tags;
593
0
          state->tags = list->list;
594
0
        }
595
596
      /* set "known" tag for known hosts */
597
0
      known_id.net = "known";
598
0
      known_id.next = state->tags;
599
0
      state->tags = &known_id;
600
601
0
      if (have_config(config, CONFIG_DISABLE))
602
0
  ignore = 1;
603
0
    }
604
0
  else if (state->clid &&
605
0
     find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len,
606
0
           state->mac, state->mac_len, state->mac_type, NULL, run_tag_if(state->tags)))
607
0
    {
608
0
      known_id.net = "known-othernet";
609
0
      known_id.next = state->tags;
610
0
      state->tags = &known_id;
611
0
    }
612
  
613
0
  tagif = run_tag_if(state->tags);
614
  
615
  /* if all the netids in the ignore list are present, ignore this client */
616
0
  if (daemon->dhcp_ignore)
617
0
    {
618
0
      struct dhcp_netid_list *id_list;
619
     
620
0
      for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
621
0
  if (match_netid(id_list->list, tagif, 0))
622
0
    ignore = 1;
623
0
    }
624
  
625
  /* if all the netids in the ignore_name list are present, ignore client-supplied name */
626
0
  if (!state->hostname_auth)
627
0
    {
628
0
       struct dhcp_netid_list *id_list;
629
       
630
0
       for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
631
0
   if ((!id_list->list) || match_netid(id_list->list, tagif, 0))
632
0
     break;
633
0
       if (id_list)
634
0
   state->hostname = NULL;
635
0
    }
636
  
637
638
0
  switch (msg_type)
639
0
    {
640
0
    default:
641
0
      return 0;
642
      
643
      
644
0
    case DHCP6SOLICIT:
645
0
      {
646
0
        int address_assigned;
647
  /* tags without all prefix-class tags */
648
0
  struct dhcp_netid *solicit_tags;
649
0
  struct dhcp_context *c;
650
  
651
0
  outmsgtype = DHCP6ADVERTISE;
652
  
653
0
  if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
654
0
    {
655
0
      outmsgtype = DHCP6REPLY;
656
0
      state->lease_allocate = 1;
657
0
      o = new_opt6(OPTION6_RAPID_COMMIT);
658
0
      end_opt6(o);
659
0
    }
660
  
661
0
    log6_quiet(state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
662
663
0
      request_no_address:
664
0
  solicit_tags = tagif;
665
0
  address_assigned = 0;
666
  
667
0
  if (ignore)
668
0
    return 0;
669
  
670
  /* reset USED bits in leases */
671
0
  lease6_reset();
672
673
  /* Can use configured address max once per prefix */
674
0
  for (c = state->context; c; c = c->current)
675
0
    c->flags &= ~CONTEXT_CONF_USED;
676
677
0
  for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
678
0
    {   
679
0
      void *ia_option, *ia_end;
680
0
      unsigned int min_time = 0xffffffff;
681
0
      int t1cntr;
682
0
      int ia_counter;
683
      /* set unless we're sending a particular prefix-class, when we
684
         want only dhcp-ranges with the correct tags set and not those without any tags. */
685
0
      int plain_range = 1;
686
0
      u32 lease_time;
687
0
      struct dhcp_lease *ltmp;
688
0
      struct in6_addr req_addr, addr;
689
      
690
0
      if (!check_ia(state, opt, &ia_end, &ia_option))
691
0
        continue;
692
      
693
      /* reset USED bits in contexts - one address per prefix per IAID */
694
0
      for (c = state->context; c; c = c->current)
695
0
        c->flags &= ~CONTEXT_USED;
696
697
0
      o = build_ia(state, &t1cntr);
698
0
      if (address_assigned)
699
0
    address_assigned = 2;
700
701
0
      for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
702
0
        {
703
    /* worry about alignment here. */
704
0
    memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
705
        
706
0
    if ((c = address6_valid(state->context, &req_addr, solicit_tags, plain_range)))
707
0
      {
708
0
        lease_time = c->lease_time;
709
        /* If the client asks for an address on the same network as a configured address, 
710
           offer the configured address instead, to make moving to newly-configured
711
           addresses automatic. */
712
0
        if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state, now))
713
0
          {
714
0
      req_addr = addr;
715
0
      mark_config_used(c, &addr);
716
0
      if (have_config(config, CONFIG_TIME))
717
0
        lease_time = config->lease_time;
718
0
          }
719
0
        else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
720
0
          continue; /* not an address we're allowed */
721
0
        else if (!check_address(state, &req_addr))
722
0
          continue; /* address leased elsewhere */
723
        
724
        /* add address to output packet */
725
0
        add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
726
0
        mark_context_used(state, &req_addr);
727
0
        get_context_tag(state, c);
728
0
        address_assigned = 1;
729
0
      }
730
0
        }
731
      
732
      /* Suggest configured address(es) */
733
0
      for (c = state->context; c; c = c->current) 
734
0
        if (!(c->flags & CONTEXT_CONF_USED) &&
735
0
      match_netid(c->filter, solicit_tags, plain_range) &&
736
0
      config_valid(config, c, &addr, state, now))
737
0
    {
738
0
      mark_config_used(state->context, &addr);
739
0
      if (have_config(config, CONFIG_TIME))
740
0
        lease_time = config->lease_time;
741
0
      else
742
0
        lease_time = c->lease_time;
743
744
      /* add address to output packet */
745
0
      add_address(state, c, lease_time, NULL, &min_time, &addr, now);
746
0
      mark_context_used(state, &addr);
747
0
      get_context_tag(state, c);
748
0
      address_assigned = 1;
749
0
    }
750
      
751
      /* return addresses for existing leases */
752
0
      ltmp = NULL;
753
0
      while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
754
0
        {
755
0
    req_addr = ltmp->addr6;
756
0
    if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
757
0
      {
758
0
        add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
759
0
        mark_context_used(state, &req_addr);
760
0
        get_context_tag(state, c);
761
0
        address_assigned = 1;
762
0
      }
763
0
        }
764
         
765
      /* Return addresses for all valid contexts which don't yet have one */
766
0
      while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
767
0
            state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
768
0
        {
769
0
    add_address(state, c, c->lease_time, NULL, &min_time, &addr, now);
770
0
    mark_context_used(state, &addr);
771
0
    get_context_tag(state, c);
772
0
    address_assigned = 1;
773
0
        }
774
      
775
0
      if (address_assigned != 1)
776
0
        {
777
    /* If the server cannot assign any addresses to an IA in the message
778
       from the client, the server MUST include the IA in the Reply message
779
       with no addresses in the IA and a Status Code option in the IA
780
       containing status code NoAddrsAvail. */
781
0
    o1 = new_opt6(OPTION6_STATUS_CODE);
782
0
    put_opt6_short(DHCP6NOADDRS);
783
0
    put_opt6_string(_("address unavailable"));
784
0
    end_opt6(o1);
785
0
        }
786
      
787
0
      end_ia(t1cntr, min_time, 0);
788
0
      end_opt6(o);  
789
0
    }
790
791
0
  if (address_assigned) 
792
0
    {
793
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
794
0
      put_opt6_short(DHCP6SUCCESS);
795
0
      put_opt6_string(_("success"));
796
0
      end_opt6(o1);
797
      
798
      /* If --dhcp-authoritative is set, we can tell client not to wait for
799
         other possible servers */
800
0
      o = new_opt6(OPTION6_PREFERENCE);
801
0
      put_opt6_char(option_bool(OPT_AUTHORITATIVE) ? 255 : 0);
802
0
      end_opt6(o);
803
0
    }
804
0
  else
805
0
    { 
806
      /* no address, return error */
807
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
808
0
      put_opt6_short(DHCP6NOADDRS);
809
0
      put_opt6_string(_("no addresses available"));
810
0
      end_opt6(o1);
811
812
      /* Some clients will ask repeatedly when we're not giving
813
         out addresses because we're in stateless mode. Avoid spamming
814
         the log in that case. */
815
0
      for (c = state->context; c; c = c->current)
816
0
        if (!(c->flags & CONTEXT_RA_STATELESS))
817
0
    {
818
0
      log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
819
0
      break;
820
0
    }
821
0
    }
822
  
823
0
  tagif = add_options(state, 0);
824
0
  break;
825
0
      }
826
      
827
0
    case DHCP6REQUEST:
828
0
      {
829
0
  int address_assigned = 0;
830
0
  int start = save_counter(-1);
831
832
  /* set reply message type */
833
0
  outmsgtype = DHCP6REPLY;
834
0
  state->lease_allocate = 1;
835
836
0
  log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
837
  
838
0
  if (ignore)
839
0
    return 0;
840
  
841
0
  for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
842
0
    {   
843
0
      void *ia_option, *ia_end;
844
0
      unsigned int min_time = 0xffffffff;
845
0
      int t1cntr;
846
      
847
0
       if (!check_ia(state, opt, &ia_end, &ia_option))
848
0
         continue;
849
850
0
       if (!ia_option)
851
0
         {
852
     /* If we get a request with an IA_*A without addresses, treat it exactly like
853
        a SOLICT with rapid commit set. */
854
0
     save_counter(start);
855
0
     goto request_no_address; 
856
0
         }
857
858
0
      o = build_ia(state, &t1cntr);
859
        
860
0
      for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
861
0
        {
862
0
    struct in6_addr req_addr;
863
0
    struct dhcp_context *dynamic, *c;
864
0
    unsigned int lease_time;
865
0
    int config_ok = 0;
866
867
    /* align. */
868
0
    memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
869
    
870
0
    if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
871
0
      config_ok = (config_implies(config, c, &req_addr) != NULL);
872
    
873
0
    if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
874
0
      {
875
0
        if (!dynamic && !config_ok)
876
0
          {
877
      /* Static range, not configured. */
878
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
879
0
      put_opt6_short(DHCP6NOADDRS);
880
0
      put_opt6_string(_("address unavailable"));
881
0
      end_opt6(o1);
882
0
          }
883
0
        else if (!check_address(state, &req_addr))
884
0
          {
885
      /* Address leased to another DUID/IAID */
886
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
887
0
      put_opt6_short(DHCP6UNSPEC);
888
0
      put_opt6_string(_("address in use"));
889
0
      end_opt6(o1);
890
0
          } 
891
0
        else 
892
0
          {
893
0
      if (!dynamic)
894
0
        dynamic = c;
895
896
0
      lease_time = dynamic->lease_time;
897
      
898
0
      if (config_ok && have_config(config, CONFIG_TIME))
899
0
        lease_time = config->lease_time;
900
901
0
      add_address(state, dynamic, lease_time, ia_option, &min_time, &req_addr, now);
902
0
      get_context_tag(state, dynamic);
903
0
      address_assigned = 1;
904
0
          }
905
0
      }
906
0
    else 
907
0
      {
908
        /* requested address not on the correct link */
909
0
        o1 = new_opt6(OPTION6_STATUS_CODE);
910
0
        put_opt6_short(DHCP6NOTONLINK);
911
0
        put_opt6_string(_("not on link"));
912
0
        end_opt6(o1);
913
0
      }
914
0
        }
915
   
916
0
      end_ia(t1cntr, min_time, 0);
917
0
      end_opt6(o);  
918
0
    }
919
920
0
  if (address_assigned) 
921
0
    {
922
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
923
0
      put_opt6_short(DHCP6SUCCESS);
924
0
      put_opt6_string(_("success"));
925
0
      end_opt6(o1);
926
0
    }
927
0
  else
928
0
    { 
929
      /* no address, return error */
930
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
931
0
      put_opt6_short(DHCP6NOADDRS);
932
0
      put_opt6_string(_("no addresses available"));
933
0
      end_opt6(o1);
934
0
      log6_packet(state, "DHCPREPLY", NULL, _("no addresses available"));
935
0
    }
936
937
0
  tagif = add_options(state, 0);
938
0
  break;
939
0
      }
940
      
941
  
942
0
    case DHCP6RENEW:
943
0
    case DHCP6REBIND:
944
0
      {
945
0
  int address_assigned = 0;
946
947
  /* set reply message type */
948
0
  outmsgtype = DHCP6REPLY;
949
  
950
0
  log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
951
952
0
  for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
953
0
    {
954
0
      void *ia_option, *ia_end;
955
0
      unsigned int min_time = 0xffffffff;
956
0
      int t1cntr, iacntr;
957
      
958
0
      if (!check_ia(state, opt, &ia_end, &ia_option))
959
0
        continue;
960
      
961
0
      o = build_ia(state, &t1cntr);
962
0
      iacntr = save_counter(-1); 
963
      
964
0
      for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
965
0
        {
966
0
    struct dhcp_lease *lease = NULL;
967
0
    struct in6_addr req_addr;
968
0
    unsigned int preferred_time =  opt6_uint(ia_option, 16, 4);
969
0
    unsigned int valid_time =  opt6_uint(ia_option, 20, 4);
970
0
    char *message = NULL;
971
0
    struct dhcp_context *this_context;
972
973
0
    memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ); 
974
    
975
0
    if (!(lease = lease6_find(state->clid, state->clid_len,
976
0
            state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, 
977
0
            state->iaid, &req_addr)))
978
0
      {
979
0
        if (msg_type == DHCP6REBIND)
980
0
          {
981
      /* When rebinding, we can create a lease if it doesn't exist, as long
982
         as --dhcp-authoritative is set. */
983
0
      if (option_bool(OPT_AUTHORITATIVE))
984
0
        lease = lease6_allocate(&req_addr, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
985
0
      if (lease)
986
0
        lease_set_iaid(lease, state->iaid);
987
0
      else
988
0
        break;
989
0
          }
990
0
        else
991
0
          {
992
      /* If the server cannot find a client entry for the IA the server
993
         returns the IA containing no addresses with a Status Code option set
994
         to NoBinding in the Reply message. */
995
0
      save_counter(iacntr);
996
0
      t1cntr = 0;
997
      
998
0
      log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
999
      
1000
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
1001
0
      put_opt6_short(DHCP6NOBINDING);
1002
0
      put_opt6_string(_("no binding found"));
1003
0
      end_opt6(o1);
1004
      
1005
0
      preferred_time = valid_time = 0;
1006
0
      break;
1007
0
          }
1008
0
      }
1009
    
1010
0
    if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
1011
0
        (this_context = address6_valid(state->context, &req_addr, tagif, 1)))
1012
0
      {
1013
0
        unsigned int lease_time;
1014
1015
0
        get_context_tag(state, this_context);
1016
        
1017
0
        if (config_implies(config, this_context, &req_addr) && have_config(config, CONFIG_TIME))
1018
0
          lease_time = config->lease_time;
1019
0
        else 
1020
0
          lease_time = this_context->lease_time;
1021
        
1022
0
        calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time); 
1023
        
1024
0
        lease_set_expires(lease, valid_time, now);
1025
        /* Update MAC record in case it's new information. */
1026
0
        if (state->mac_len != 0)
1027
0
          lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
1028
0
        if (state->ia_type == OPTION6_IA_NA && state->hostname)
1029
0
          {
1030
0
      char *addr_domain = get_domain6(&req_addr);
1031
0
      if (!state->send_domain)
1032
0
        state->send_domain = addr_domain;
1033
0
      lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain); 
1034
0
      message = state->hostname;
1035
0
          }
1036
        
1037
        
1038
0
        if (preferred_time == 0)
1039
0
          message = _("deprecated");
1040
1041
0
        address_assigned = 1;
1042
0
      }
1043
0
    else
1044
0
      {
1045
0
        preferred_time = valid_time = 0;
1046
0
        message = _("address invalid");
1047
0
      } 
1048
1049
0
    if (message && (message != state->hostname))
1050
0
      log6_packet(state, "DHCPREPLY", &req_addr, message); 
1051
0
    else
1052
0
      log6_quiet(state, "DHCPREPLY", &req_addr, message);
1053
  
1054
0
    o1 =  new_opt6(OPTION6_IAADDR);
1055
0
    put_opt6(&req_addr, sizeof(req_addr));
1056
0
    put_opt6_long(preferred_time);
1057
0
    put_opt6_long(valid_time);
1058
0
    end_opt6(o1);
1059
0
        }
1060
      
1061
0
      end_ia(t1cntr, min_time, 1);
1062
0
      end_opt6(o);
1063
0
    }
1064
1065
0
  if (!address_assigned && msg_type == DHCP6REBIND)
1066
0
    { 
1067
      /* can't create lease for any address, return error */
1068
0
      o1 = new_opt6(OPTION6_STATUS_CODE);
1069
0
      put_opt6_short(DHCP6NOADDRS);
1070
0
      put_opt6_string(_("no addresses available"));
1071
0
      end_opt6(o1);
1072
0
    }
1073
  
1074
0
  tagif = add_options(state, 0);
1075
0
  break;
1076
0
      }
1077
      
1078
0
    case DHCP6CONFIRM:
1079
0
      {
1080
0
  int good_addr = 0, bad_addr = 0;
1081
1082
  /* set reply message type */
1083
0
  outmsgtype = DHCP6REPLY;
1084
  
1085
0
  log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
1086
  
1087
0
  for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1088
0
    {
1089
0
      void *ia_option, *ia_end;
1090
      
1091
0
      for (check_ia(state, opt, &ia_end, &ia_option);
1092
0
     ia_option;
1093
0
     ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
1094
0
        {
1095
0
    struct in6_addr req_addr;
1096
1097
    /* alignment */
1098
0
    memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
1099
    
1100
0
    if (!address6_valid(state->context, &req_addr, tagif, 1))
1101
0
      {
1102
0
        bad_addr = 1;
1103
0
        log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
1104
0
      }
1105
0
    else
1106
0
      {
1107
0
        good_addr = 1;
1108
0
        log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
1109
0
      }
1110
0
        }
1111
0
    }  
1112
  
1113
  /* No addresses, no reply: RFC 3315 18.2.2 */
1114
0
  if (!good_addr && !bad_addr)
1115
0
    return 0;
1116
1117
0
  o1 = new_opt6(OPTION6_STATUS_CODE);
1118
0
  put_opt6_short(bad_addr ? DHCP6NOTONLINK : DHCP6SUCCESS);
1119
0
  put_opt6_string(bad_addr ? (_("confirm failed")) : (_("all addresses still on link")));
1120
0
  end_opt6(o1);
1121
0
  break;
1122
0
    }
1123
      
1124
0
    case DHCP6IREQ:
1125
0
      {
1126
  /* 3315 para 15.12 */
1127
0
  if (opt6_find(state->packet_options, state->end, OPTION6_IA_NA, 1) ||
1128
0
      opt6_find(state->packet_options, state->end, OPTION6_IA_TA, 1))
1129
0
    return 0;
1130
  
1131
  /* We can't discriminate contexts based on address, as we don't know it.
1132
     If there is only one possible context, we can use its tags */
1133
0
  if (state->context && state->context->netid.net && !state->context->current)
1134
0
    {
1135
0
      state->context->netid.next = NULL;
1136
0
      state->context_tags =  &state->context->netid;
1137
0
    }
1138
1139
  /* Similarly, we can't determine domain from address, but if the FQDN is
1140
     given in --dhcp-host, we can use that, and failing that we can use the 
1141
     unqualified configured domain, if any. */
1142
0
  if (state->hostname_auth)
1143
0
    state->send_domain = state->domain;
1144
0
  else
1145
0
    state->send_domain = get_domain6(NULL);
1146
1147
0
  log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
1148
0
  if (ignore)
1149
0
    return 0;
1150
0
  outmsgtype = DHCP6REPLY;
1151
0
  tagif = add_options(state, 1);
1152
0
  break;
1153
0
      }
1154
      
1155
      
1156
0
    case DHCP6RELEASE:
1157
0
      {
1158
  /* set reply message type */
1159
0
  outmsgtype = DHCP6REPLY;
1160
1161
0
  log6_quiet(state, "DHCPRELEASE", NULL, NULL);
1162
1163
0
  for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1164
0
    {
1165
0
      void *ia_option, *ia_end;
1166
0
      int made_ia = 0;
1167
            
1168
0
      for (check_ia(state, opt, &ia_end, &ia_option);
1169
0
     ia_option;
1170
0
     ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) 
1171
0
        {
1172
0
    struct dhcp_lease *lease;
1173
0
    struct in6_addr addr;
1174
1175
    /* align */
1176
0
    memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
1177
0
    if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1178
0
           state->iaid, &addr)))
1179
0
      lease_prune(lease, now);
1180
0
    else
1181
0
      {
1182
0
        if (!made_ia)
1183
0
          {
1184
0
      o = new_opt6(state->ia_type);
1185
0
      put_opt6_long(state->iaid);
1186
0
      if (state->ia_type == OPTION6_IA_NA)
1187
0
        {
1188
0
          put_opt6_long(0);
1189
0
          put_opt6_long(0); 
1190
0
        }
1191
0
      made_ia = 1;
1192
0
          }
1193
        
1194
0
        o1 = new_opt6(OPTION6_IAADDR);
1195
0
        put_opt6(&addr, IN6ADDRSZ);
1196
0
        put_opt6_long(0);
1197
0
        put_opt6_long(0);
1198
0
        end_opt6(o1);
1199
0
      }
1200
0
        }
1201
      
1202
0
      if (made_ia)
1203
0
        {
1204
0
    o1 = new_opt6(OPTION6_STATUS_CODE);
1205
0
    put_opt6_short(DHCP6NOBINDING);
1206
0
    put_opt6_string(_("no binding found"));
1207
0
    end_opt6(o1);
1208
    
1209
0
    end_opt6(o);
1210
0
        }
1211
0
    }
1212
  
1213
0
  o1 = new_opt6(OPTION6_STATUS_CODE);
1214
0
  put_opt6_short(DHCP6SUCCESS);
1215
0
  put_opt6_string(_("release received"));
1216
0
  end_opt6(o1);
1217
  
1218
0
  break;
1219
0
      }
1220
1221
0
    case DHCP6DECLINE:
1222
0
      {
1223
  /* set reply message type */
1224
0
  outmsgtype = DHCP6REPLY;
1225
  
1226
0
  log6_quiet(state, "DHCPDECLINE", NULL, NULL);
1227
1228
0
  for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1229
0
    {
1230
0
      void *ia_option, *ia_end;
1231
0
      int made_ia = 0;
1232
            
1233
0
      for (check_ia(state, opt, &ia_end, &ia_option);
1234
0
     ia_option;
1235
0
     ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) 
1236
0
        {
1237
0
    struct dhcp_lease *lease;
1238
0
    struct in6_addr addr;
1239
0
    struct addrlist *addr_list;
1240
    
1241
    /* align */
1242
0
    memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
1243
1244
0
    if ((addr_list = config_implies(config, state->context, &addr)))
1245
0
      {
1246
0
        prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
1247
0
        inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
1248
0
        my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), 
1249
0
            daemon->addrbuff, daemon->dhcp_buff3);
1250
0
        addr_list->flags |= ADDRLIST_DECLINED;
1251
0
        addr_list->decline_time = now;
1252
0
      }
1253
0
    else
1254
      /* make sure this host gets a different address next time. */
1255
0
      for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
1256
0
        context_tmp->addr_epoch++;
1257
    
1258
0
    if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
1259
0
           state->iaid, &addr)))
1260
0
      lease_prune(lease, now);
1261
0
    else
1262
0
      {
1263
0
        if (!made_ia)
1264
0
          {
1265
0
      o = new_opt6(state->ia_type);
1266
0
      put_opt6_long(state->iaid);
1267
0
      if (state->ia_type == OPTION6_IA_NA)
1268
0
        {
1269
0
          put_opt6_long(0);
1270
0
          put_opt6_long(0); 
1271
0
        }
1272
0
      made_ia = 1;
1273
0
          }
1274
        
1275
0
        o1 = new_opt6(OPTION6_IAADDR);
1276
0
        put_opt6(&addr, IN6ADDRSZ);
1277
0
        put_opt6_long(0);
1278
0
        put_opt6_long(0);
1279
0
        end_opt6(o1);
1280
0
      }
1281
0
        }
1282
      
1283
0
      if (made_ia)
1284
0
        {
1285
0
    o1 = new_opt6(OPTION6_STATUS_CODE);
1286
0
    put_opt6_short(DHCP6NOBINDING);
1287
0
    put_opt6_string(_("no binding found"));
1288
0
    end_opt6(o1);
1289
    
1290
0
    end_opt6(o);
1291
0
        }
1292
      
1293
0
    }
1294
1295
  /* We must answer with 'success' in global section anyway */
1296
0
  o1 = new_opt6(OPTION6_STATUS_CODE);
1297
0
  put_opt6_short(DHCP6SUCCESS);
1298
0
  put_opt6_string(_("success"));
1299
0
  end_opt6(o1);
1300
0
  break;
1301
0
      }
1302
1303
0
    }
1304
1305
0
  log_tags(tagif, state->xid);
1306
1307
0
 done:
1308
  /* Fill in the message type. Note that we store the offset,
1309
     not a direct pointer, since the packet memory may have been 
1310
     reallocated. */
1311
0
  ((unsigned char *)(daemon->outpacket.iov_base))[start_msg] = outmsgtype;
1312
1313
0
  log6_opts(0, state->xid, (uint8_t *)daemon->outpacket.iov_base + start_opts, (uint8_t *)daemon->outpacket.iov_base + save_counter(-1));
1314
  
1315
0
  return 1;
1316
1317
0
}
1318
1319
static struct dhcp_netid *add_options(struct state *state, int do_refresh)  
1320
0
{
1321
0
  void *oro;
1322
  /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
1323
0
  struct dhcp_netid *tagif = option_filter(state->tags, state->context_tags, daemon->dhcp_opts6, 0);
1324
0
  struct dhcp_opt *opt_cfg;
1325
0
  int done_dns = 0, done_refresh = !do_refresh, do_encap = 0;
1326
0
  int i, o, o1;
1327
1328
0
  oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0);
1329
  
1330
0
  for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1331
0
    {
1332
      /* netids match and not encapsulated? */
1333
0
      if (!(opt_cfg->flags & DHOPT_TAGOK))
1334
0
  continue;
1335
      
1336
0
      if (!(opt_cfg->flags & DHOPT_FORCE) && oro)
1337
0
  {
1338
0
    for (i = 0; i <  opt6_len(oro) - 1; i += 2)
1339
0
      if (opt6_uint(oro, i, 2) == (unsigned)opt_cfg->opt)
1340
0
        break;
1341
    
1342
    /* option not requested */
1343
0
    if (i >=  opt6_len(oro) - 1)
1344
0
      continue;
1345
0
  }
1346
      
1347
0
      if (opt_cfg->opt == OPTION6_REFRESH_TIME)
1348
0
  done_refresh = 1;
1349
       
1350
0
      if (opt_cfg->opt == OPTION6_DNS_SERVER)
1351
0
  done_dns = 1;
1352
      
1353
0
      if (opt_cfg->flags & DHOPT_ADDR6)
1354
0
  {
1355
0
    int len, j;
1356
0
    struct in6_addr *a;
1357
    
1358
0
    for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0; 
1359
0
         j < opt_cfg->len; j += IN6ADDRSZ, a++)
1360
0
      if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) ||
1361
0
    (IN6_IS_ADDR_LINK_LOCAL_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ll_addr)))
1362
0
        len -= IN6ADDRSZ;
1363
    
1364
0
    if (len != 0)
1365
0
      {
1366
        
1367
0
        o = new_opt6(opt_cfg->opt);
1368
            
1369
0
        for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
1370
0
    {
1371
0
      struct in6_addr *p = NULL;
1372
1373
0
      if (IN6_IS_ADDR_UNSPECIFIED(a))
1374
0
        {
1375
0
          if (!add_local_addrs(state->context))
1376
0
      p = state->fallback;
1377
0
        }
1378
0
      else if (IN6_IS_ADDR_ULA_ZERO(a))
1379
0
        {
1380
0
          if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr))
1381
0
      p = state->ula_addr;
1382
0
        }
1383
0
      else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
1384
0
        {
1385
0
          if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr))
1386
0
      p = state->ll_addr;
1387
0
        }
1388
0
      else
1389
0
        p = a;
1390
1391
0
      if (!p)
1392
0
        continue;
1393
0
      else if (opt_cfg->opt == OPTION6_NTP_SERVER)
1394
0
        {
1395
0
          if (IN6_IS_ADDR_MULTICAST(p))
1396
0
      o1 = new_opt6(NTP_SUBOPTION_MC_ADDR);
1397
0
          else
1398
0
      o1 = new_opt6(NTP_SUBOPTION_SRV_ADDR);
1399
0
          put_opt6(p, IN6ADDRSZ);
1400
0
          end_opt6(o1);
1401
0
        }
1402
0
      else
1403
0
        put_opt6(p, IN6ADDRSZ);
1404
0
    }
1405
1406
0
        end_opt6(o);
1407
0
      }
1408
0
  }
1409
0
      else
1410
0
  {
1411
0
    o = new_opt6(opt_cfg->opt);
1412
0
    if (opt_cfg->val)
1413
0
      put_opt6(opt_cfg->val, opt_cfg->len);
1414
0
    end_opt6(o);
1415
0
  }
1416
0
    }
1417
  
1418
0
  if (daemon->port == NAMESERVER_PORT && !done_dns)
1419
0
    {
1420
0
      o = new_opt6(OPTION6_DNS_SERVER);
1421
0
      if (!add_local_addrs(state->context))
1422
0
  put_opt6(state->fallback, IN6ADDRSZ);
1423
0
      end_opt6(o); 
1424
0
    }
1425
1426
0
  if (state->context && !done_refresh)
1427
0
    {
1428
0
      struct dhcp_context *c;
1429
0
      unsigned int lease_time = 0xffffffff;
1430
      
1431
      /* Find the smallest lease tie of all contexts,
1432
   subject to the RFC-4242 stipulation that this must not 
1433
   be less than 600. */
1434
0
      for (c = state->context; c; c = c->next)
1435
0
  if (c->lease_time < lease_time)
1436
0
    {
1437
0
      if (c->lease_time < 600)
1438
0
        lease_time = 600;
1439
0
      else
1440
0
        lease_time = c->lease_time;
1441
0
    }
1442
1443
0
      o = new_opt6(OPTION6_REFRESH_TIME);
1444
0
      put_opt6_long(lease_time);
1445
0
      end_opt6(o); 
1446
0
    }
1447
   
1448
    /* handle vendor-identifying vendor-encapsulated options,
1449
       dhcp-option = vi-encap:13,17,....... */
1450
0
  for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1451
0
    opt_cfg->flags &= ~DHOPT_ENCAP_DONE;
1452
    
1453
0
  if (oro)
1454
0
    for (i = 0; i <  opt6_len(oro) - 1; i += 2)
1455
0
      if (opt6_uint(oro, i, 2) == OPTION6_VENDOR_OPTS)
1456
0
  do_encap = 1;
1457
  
1458
0
  for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
1459
0
    { 
1460
0
      if (opt_cfg->flags & DHOPT_RFC3925)
1461
0
  {
1462
0
    int found = 0;
1463
0
    struct dhcp_opt *oc;
1464
    
1465
0
    if (opt_cfg->flags & DHOPT_ENCAP_DONE)
1466
0
      continue;
1467
    
1468
0
    for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1469
0
      {
1470
0
        oc->flags &= ~DHOPT_ENCAP_MATCH;
1471
        
1472
0
        if (!(oc->flags & DHOPT_RFC3925) || opt_cfg->u.encap != oc->u.encap)
1473
0
    continue;
1474
        
1475
0
        oc->flags |= DHOPT_ENCAP_DONE;
1476
0
        if (match_netid(oc->netid, tagif, 1))
1477
0
    {
1478
      /* option requested/forced? */
1479
0
      if (!oro || do_encap || (oc->flags & DHOPT_FORCE))
1480
0
        {
1481
0
          oc->flags |= DHOPT_ENCAP_MATCH;
1482
0
          found = 1;
1483
0
        }
1484
0
    } 
1485
0
      }
1486
    
1487
0
    if (found)
1488
0
      { 
1489
0
        o = new_opt6(OPTION6_VENDOR_OPTS);        
1490
0
        put_opt6_long(opt_cfg->u.encap);  
1491
       
1492
0
        for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
1493
0
    if (oc->flags & DHOPT_ENCAP_MATCH)
1494
0
      {
1495
0
        o1 = new_opt6(oc->opt);
1496
0
        put_opt6(oc->val, oc->len);
1497
0
        end_opt6(o1);
1498
0
      }
1499
0
        end_opt6(o);
1500
0
      }
1501
0
  }
1502
0
    }      
1503
1504
1505
0
  if (state->hostname)
1506
0
    {
1507
0
      unsigned char *p;
1508
0
      size_t len = strlen(state->hostname);
1509
      
1510
0
      if (state->send_domain)
1511
0
  len += strlen(state->send_domain) + 2;
1512
1513
0
      o = new_opt6(OPTION6_FQDN);
1514
0
      if ((p = expand(len + 2)))
1515
0
  {
1516
0
    *(p++) = state->fqdn_flags;
1517
0
    p = do_rfc1035_name(p, state->hostname, NULL);
1518
0
    if (state->send_domain)
1519
0
      {
1520
0
        p = do_rfc1035_name(p, state->send_domain, NULL);
1521
0
        *p = 0;
1522
0
      }
1523
0
  }
1524
0
      end_opt6(o);
1525
0
    }
1526
1527
1528
  /* logging */
1529
0
  if (option_bool(OPT_LOG_OPTS) && oro)
1530
0
    {
1531
0
      char *q = daemon->namebuff;
1532
0
      for (i = 0; i <  opt6_len(oro) - 1; i += 2)
1533
0
  {
1534
0
    char *s = option_string(AF_INET6, opt6_uint(oro, i, 2), NULL, 0, NULL, 0);
1535
0
    q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
1536
0
      "%d%s%s%s", 
1537
0
      opt6_uint(oro, i, 2),
1538
0
      strlen(s) != 0 ? ":" : "",
1539
0
      s, 
1540
0
      (i > opt6_len(oro) - 3) ? "" : ", ");
1541
0
    if ( i >  opt6_len(oro) - 3 || (q - daemon->namebuff) > 40)
1542
0
      {
1543
0
        q = daemon->namebuff;
1544
0
        my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), state->xid, daemon->namebuff);
1545
0
      }
1546
0
  }
1547
0
    } 
1548
1549
0
  return tagif;
1550
0
}
1551
 
1552
static int add_local_addrs(struct dhcp_context *context)
1553
0
{
1554
0
  int done = 0;
1555
  
1556
0
  for (; context; context = context->current)
1557
0
    if ((context->flags & CONTEXT_USED) && !IN6_IS_ADDR_UNSPECIFIED(&context->local6))
1558
0
      {
1559
  /* squash duplicates */
1560
0
  struct dhcp_context *c;
1561
0
  for (c = context->current; c; c = c->current)
1562
0
    if ((c->flags & CONTEXT_USED) &&
1563
0
        IN6_ARE_ADDR_EQUAL(&context->local6, &c->local6))
1564
0
      break;
1565
  
1566
0
  if (!c)
1567
0
    { 
1568
0
      done = 1;
1569
0
      put_opt6(&context->local6, IN6ADDRSZ);
1570
0
    }
1571
0
      }
1572
1573
0
  return done;
1574
0
}
1575
1576
1577
static void get_context_tag(struct state *state, struct dhcp_context *context)
1578
0
{
1579
  /* get tags from context if we've not used it before */
1580
0
  if (context->netid.next == &context->netid && context->netid.net)
1581
0
    {
1582
0
      context->netid.next = state->context_tags;
1583
0
      state->context_tags = &context->netid;
1584
0
      if (!state->hostname_auth)
1585
0
  {
1586
0
    struct dhcp_netid_list *id_list;
1587
    
1588
0
    for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1589
0
      if ((!id_list->list) || match_netid(id_list->list, &context->netid, 0))
1590
0
        break;
1591
0
    if (id_list)
1592
0
      state->hostname = NULL;
1593
0
  }
1594
0
    }
1595
0
} 
1596
1597
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
1598
0
{
1599
0
  state->ia_type = opt6_type(opt);
1600
0
  *ia_option = NULL;
1601
1602
0
  if (state->ia_type != OPTION6_IA_NA && state->ia_type != OPTION6_IA_TA)
1603
0
    return 0;
1604
  
1605
0
  if (state->ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
1606
0
    return 0;
1607
      
1608
0
  if (state->ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
1609
0
    return 0;
1610
  
1611
0
  *endp = opt6_ptr(opt, opt6_len(opt));
1612
0
  state->iaid = opt6_uint(opt, 0, 4);
1613
0
  *ia_option = opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
1614
1615
0
  return 1;
1616
0
}
1617
1618
1619
static int build_ia(struct state *state, int *t1cntr)
1620
0
{
1621
0
  int  o = new_opt6(state->ia_type);
1622
 
1623
0
  put_opt6_long(state->iaid);
1624
0
  *t1cntr = 0;
1625
      
1626
0
  if (state->ia_type == OPTION6_IA_NA)
1627
0
    {
1628
      /* save pointer */
1629
0
      *t1cntr = save_counter(-1);
1630
      /* so we can fill these in later */
1631
0
      put_opt6_long(0);
1632
0
      put_opt6_long(0); 
1633
0
    }
1634
1635
0
  return o;
1636
0
}
1637
1638
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
1639
0
{
1640
0
  if (t1cntr != 0)
1641
0
    {
1642
      /* go back and fill in fields in IA_NA option */
1643
0
      int sav = save_counter(t1cntr);
1644
0
      unsigned int t1, t2, fuzz = 0;
1645
1646
0
      if (do_fuzz)
1647
0
  {
1648
0
    fuzz = rand16();
1649
      
1650
0
    while (fuzz > (min_time/16))
1651
0
      fuzz = fuzz/2;
1652
0
  }
1653
      
1654
0
      t1 = (min_time == 0xffffffff) ? 0xffffffff : min_time/2 - fuzz;
1655
0
      t2 = (min_time == 0xffffffff) ? 0xffffffff : ((min_time/8)*7) - fuzz;
1656
0
      put_opt6_long(t1);
1657
0
      put_opt6_long(t2);
1658
0
      save_counter(sav);
1659
0
    } 
1660
0
}
1661
1662
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option, 
1663
      unsigned int *min_time, struct in6_addr *addr, time_t now)
1664
0
{
1665
0
  unsigned int valid_time = 0, preferred_time = 0;
1666
0
  int o = new_opt6(OPTION6_IAADDR);
1667
0
  struct dhcp_lease *lease;
1668
1669
  /* get client requested times */
1670
0
  if (ia_option)
1671
0
    {
1672
0
      preferred_time =  opt6_uint(ia_option, 16, 4);
1673
0
      valid_time =  opt6_uint(ia_option, 20, 4);
1674
0
    }
1675
1676
0
  calculate_times(context, min_time, &valid_time, &preferred_time, lease_time); 
1677
  
1678
0
  put_opt6(addr, sizeof(*addr));
1679
0
  put_opt6_long(preferred_time);
1680
0
  put_opt6_long(valid_time);        
1681
0
  end_opt6(o);
1682
  
1683
0
  if (state->lease_allocate)
1684
0
    update_leases(state, context, addr, valid_time, now);
1685
1686
0
  if ((lease = lease6_find_by_addr(addr, 128, 0)))
1687
0
    lease->flags |= LEASE_USED;
1688
1689
  /* get tags from context if we've not used it before */
1690
0
  if (context->netid.next == &context->netid && context->netid.net)
1691
0
    {
1692
0
      context->netid.next = state->context_tags;
1693
0
      state->context_tags = &context->netid;
1694
      
1695
0
      if (!state->hostname_auth)
1696
0
  {
1697
0
    struct dhcp_netid_list *id_list;
1698
    
1699
0
    for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1700
0
      if ((!id_list->list) || match_netid(id_list->list, &context->netid, 0))
1701
0
        break;
1702
0
    if (id_list)
1703
0
      state->hostname = NULL;
1704
0
  }
1705
0
    }
1706
1707
0
  log6_quiet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
1708
1709
0
}
1710
1711
static void mark_context_used(struct state *state, struct in6_addr *addr)
1712
0
{
1713
0
  struct dhcp_context *context;
1714
1715
  /* Mark that we have an address for this prefix. */
1716
0
  for (context = state->context; context; context = context->current)
1717
0
    if (is_same_net6(addr, &context->start6, context->prefix))
1718
0
      context->flags |= CONTEXT_USED;
1719
0
}
1720
1721
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
1722
0
{
1723
0
  for (; context; context = context->current)
1724
0
    if (is_same_net6(addr, &context->start6, context->prefix))
1725
0
      context->flags |= CONTEXT_CONF_USED;
1726
0
}
1727
1728
/* make sure address not leased to another CLID/IAID */
1729
static int check_address(struct state *state, struct in6_addr *addr)
1730
0
{ 
1731
0
  struct dhcp_lease *lease;
1732
1733
0
  if (!(lease = lease6_find_by_addr(addr, 128, 0)))
1734
0
    return 1;
1735
1736
0
  if (lease->clid_len != state->clid_len || 
1737
0
      memcmp(lease->clid, state->clid, state->clid_len) != 0 ||
1738
0
      lease->iaid != state->iaid)
1739
0
    return 0;
1740
1741
0
  return 1;
1742
0
}
1743
1744
1745
/* return true of *addr could have been generated from config. */
1746
static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
1747
0
{
1748
0
  int prefix;
1749
0
  struct in6_addr wild_addr;
1750
0
  struct addrlist *addr_list;
1751
  
1752
0
  if (!config || !(config->flags & CONFIG_ADDR6))
1753
0
    return NULL;
1754
  
1755
0
  for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
1756
0
    {
1757
0
      prefix = (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128;
1758
0
      wild_addr = addr_list->addr.addr6;
1759
      
1760
0
      if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64)
1761
0
  {
1762
0
    wild_addr = context->start6;
1763
0
    setaddr6part(&wild_addr, addr6part(&addr_list->addr.addr6));
1764
0
  }
1765
0
      else if (!is_same_net6(&context->start6, addr, context->prefix))
1766
0
  continue;
1767
      
1768
0
      if (is_same_net6(&wild_addr, addr, prefix))
1769
0
  return addr_list;
1770
0
    }
1771
  
1772
0
  return NULL;
1773
0
}
1774
1775
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now)
1776
0
{
1777
0
  u64 addrpart, i, addresses;
1778
0
  struct addrlist *addr_list;
1779
  
1780
0
  if (!config || !(config->flags & CONFIG_ADDR6))
1781
0
    return 0;
1782
1783
0
  for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
1784
0
    if (!(addr_list->flags & ADDRLIST_DECLINED) ||
1785
0
  difftime(now, addr_list->decline_time) >= (float)DECLINE_BACKOFF)
1786
0
      {
1787
0
  addrpart = addr6part(&addr_list->addr.addr6);
1788
0
  addresses = 1;
1789
  
1790
0
  if (addr_list->flags & ADDRLIST_PREFIX)
1791
0
    addresses = (u64)1<<(128-addr_list->prefixlen);
1792
  
1793
0
  if ((addr_list->flags & ADDRLIST_WILDCARD))
1794
0
    {
1795
0
      if (context->prefix != 64)
1796
0
        continue;
1797
      
1798
0
      *addr = context->start6;
1799
0
    }
1800
0
  else if (is_same_net6(&context->start6, &addr_list->addr.addr6, context->prefix))
1801
0
    *addr = addr_list->addr.addr6;
1802
0
  else
1803
0
    continue;
1804
  
1805
0
  for (i = 0 ; i < addresses; i++)
1806
0
    {
1807
0
      setaddr6part(addr, addrpart+i);
1808
      
1809
0
      if (check_address(state, addr))
1810
0
        return 1;
1811
0
    }
1812
0
      }
1813
  
1814
0
  return 0;
1815
0
}
1816
1817
/* Calculate valid and preferred times to send in leases/renewals. 
1818
1819
   Inputs are:
1820
1821
   *valid_timep, *preferred_timep - requested times from IAADDR options.
1822
   context->valid, context->preferred - times associated with subnet address on local interface.
1823
   context->flags | CONTEXT_DEPRECATE - "deprecated" flag in dhcp-range.
1824
   lease_time - configured time for context for individual client.
1825
   *min_time - smallest valid time sent so far.
1826
1827
   Outputs are :
1828
   
1829
   *valid_timep, *preferred_timep - times to be send in IAADDR option.
1830
   *min_time - smallest valid time sent so far, to calculate T1 and T2.
1831
   
1832
   */
1833
static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep, 
1834
          unsigned int *preferred_timep, unsigned int lease_time)
1835
0
{
1836
0
  unsigned int req_preferred = *preferred_timep, req_valid = *valid_timep;
1837
0
  unsigned int valid_time = lease_time, preferred_time = lease_time;
1838
  
1839
  /* RFC 3315: "A server ignores the lifetimes set
1840
     by the client if the preferred lifetime is greater than the valid
1841
     lifetime. */
1842
0
  if (req_preferred <= req_valid)
1843
0
    {
1844
0
      if (req_preferred != 0)
1845
0
  {
1846
    /* 0 == "no preference from client" */
1847
0
    if (req_preferred < 120u)
1848
0
      req_preferred = 120u; /* sanity */
1849
    
1850
0
    if (req_preferred < preferred_time)
1851
0
      preferred_time = req_preferred;
1852
0
  }
1853
      
1854
0
      if (req_valid != 0)
1855
  /* 0 == "no preference from client" */
1856
0
  {
1857
0
    if (req_valid < 120u)
1858
0
      req_valid = 120u; /* sanity */
1859
    
1860
0
    if (req_valid < valid_time)
1861
0
      valid_time = req_valid;
1862
0
  }
1863
0
    }
1864
1865
  /* deprecate (preferred == 0) which configured, or when local address 
1866
     is deprecated */
1867
0
  if ((context->flags & CONTEXT_DEPRECATE) || context->preferred == 0)
1868
0
    preferred_time = 0;
1869
  
1870
0
  if (preferred_time != 0 && preferred_time < *min_time)
1871
0
    *min_time = preferred_time;
1872
  
1873
0
  if (valid_time != 0 && valid_time < *min_time)
1874
0
    *min_time = valid_time;
1875
  
1876
0
  *valid_timep = valid_time;
1877
0
  *preferred_timep = preferred_time;
1878
0
}
1879
1880
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now)
1881
0
{
1882
0
  struct dhcp_lease *lease = lease6_find_by_addr(addr, 128, 0);
1883
0
#ifdef HAVE_SCRIPT
1884
0
  struct dhcp_netid *tagif = run_tag_if(state->tags);
1885
0
#endif
1886
1887
0
  (void)context;
1888
1889
0
  if (!lease)
1890
0
    lease = lease6_allocate(addr, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
1891
  
1892
0
  if (lease)
1893
0
    {
1894
0
      lease_set_expires(lease, lease_time, now);
1895
0
      lease_set_iaid(lease, state->iaid); 
1896
0
      lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
1897
0
      lease_set_interface(lease, state->interface, now);
1898
0
      if (state->hostname && state->ia_type == OPTION6_IA_NA)
1899
0
  {
1900
0
    char *addr_domain = get_domain6(addr);
1901
0
    if (!state->send_domain)
1902
0
      state->send_domain = addr_domain;
1903
0
    lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
1904
0
  }
1905
      
1906
0
#ifdef HAVE_SCRIPT
1907
0
      if (daemon->lease_change_command)
1908
0
  {
1909
0
    void *opt;
1910
    
1911
0
    lease->flags |= LEASE_CHANGED;
1912
0
    free(lease->extradata);
1913
0
    lease->extradata = NULL;
1914
0
    lease->extradata_size = lease->extradata_len = 0;
1915
0
    lease->vendorclass_count = 0; 
1916
    
1917
0
    if ((opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
1918
0
      {
1919
0
        void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
1920
0
        lease->vendorclass_count++;
1921
        /* send enterprise number first  */
1922
0
        sprintf(daemon->dhcp_buff2, "%u", opt6_uint(opt, 0, 4));
1923
0
        lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
1924
        
1925
0
        if (opt6_len(opt) >= 6) 
1926
0
    for (enc_opt = opt6_ptr(opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
1927
0
      {
1928
0
        lease->vendorclass_count++;
1929
0
        lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
1930
0
      }
1931
0
      }
1932
    
1933
0
    lease_add_extradata(lease, (unsigned char *)state->client_hostname, 
1934
0
            state->client_hostname ? strlen(state->client_hostname) : 0, 0);       
1935
    
1936
    /* DNSMASQ_REQUESTED_OPTIONS */
1937
0
    if ((opt = opt6_find(state->packet_options, state->end, OPTION6_ORO, 2)))
1938
0
      {
1939
0
        int i, len = opt6_len(opt)/2;
1940
0
        u16 *rop = opt6_ptr(opt, 0);
1941
        
1942
0
        for (i = 0; i < len; i++)
1943
0
    lease_add_extradata(lease, (unsigned char *)daemon->namebuff,
1944
0
            sprintf(daemon->namebuff, "%u", ntohs(rop[i])), (i + 1) == len ? 0 : ',');
1945
0
      }
1946
0
    else
1947
0
      lease_add_extradata(lease, NULL, 0, 0);
1948
1949
0
    if ((opt = opt6_find(state->packet_options, state->end, OPTION6_MUD_URL, 1)))
1950
0
      lease_add_extradata(lease, opt6_ptr(opt, 0), opt6_len(opt), 0);
1951
0
    else
1952
0
      lease_add_extradata(lease, NULL, 0, 0);
1953
1954
    /* space-concat tag set */
1955
0
    if (!tagif && !context->netid.net)
1956
0
      lease_add_extradata(lease, NULL, 0, 0);
1957
0
    else
1958
0
      {
1959
0
        if (context->netid.net)
1960
0
    lease_add_extradata(lease, (unsigned char *)context->netid.net, strlen(context->netid.net), tagif ? ' ' : 0);
1961
        
1962
0
        if (tagif)
1963
0
    {
1964
0
      struct dhcp_netid *n;
1965
0
      for (n = tagif; n; n = n->next)
1966
0
        {
1967
0
          struct dhcp_netid *n1;
1968
          /* kill dupes */
1969
0
          for (n1 = n->next; n1; n1 = n1->next)
1970
0
      if (strcmp(n->net, n1->net) == 0)
1971
0
        break;
1972
0
          if (!n1)
1973
0
      lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0); 
1974
0
        }
1975
0
    }
1976
0
      }
1977
    
1978
0
    if (state->link_address)
1979
0
      inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN);
1980
    
1981
0
    lease_add_extradata(lease, (unsigned char *)daemon->addrbuff, state->link_address ? strlen(daemon->addrbuff) : 0, 0);
1982
    
1983
0
    if ((opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
1984
0
      {
1985
0
        void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
1986
0
        for (enc_opt = opt6_ptr(opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
1987
0
    lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
1988
0
      }
1989
0
  }
1990
0
#endif  
1991
      
1992
0
    }
1993
0
}
1994
        
1995
      
1996
  
1997
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts)
1998
0
{
1999
0
  void *opt;
2000
0
  char *desc = nest ? "nest" : "sent";
2001
  
2002
0
  if (!option_bool(OPT_LOG_OPTS) || start_opts == end_opts)
2003
0
    return;
2004
  
2005
0
  for (opt = start_opts; opt; opt = opt6_next(opt, end_opts))
2006
0
    {
2007
0
      int type = opt6_type(opt);
2008
0
      void *ia_options = NULL;
2009
0
      char *optname;
2010
      
2011
0
      if (type == OPTION6_IA_NA)
2012
0
  {
2013
0
    sprintf(daemon->namebuff, "IAID=%u T1=%u T2=%u",
2014
0
      opt6_uint(opt, 0, 4), opt6_uint(opt, 4, 4), opt6_uint(opt, 8, 4));
2015
0
    optname = "ia-na";
2016
0
    ia_options = opt6_ptr(opt, 12);
2017
0
  }
2018
0
      else if (type == OPTION6_IA_TA)
2019
0
  {
2020
0
    sprintf(daemon->namebuff, "IAID=%u", opt6_uint(opt, 0, 4));
2021
0
    optname = "ia-ta";
2022
0
    ia_options = opt6_ptr(opt, 4);
2023
0
  }
2024
0
      else if (type == OPTION6_IAADDR)
2025
0
  {
2026
0
    struct in6_addr addr;
2027
2028
    /* align */
2029
0
    memcpy(&addr, opt6_ptr(opt, 0), IN6ADDRSZ);
2030
0
    inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
2031
0
    sprintf(daemon->namebuff, "%s PL=%u VL=%u", 
2032
0
      daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
2033
0
    optname = "iaaddr";
2034
0
    ia_options = opt6_ptr(opt, 24);
2035
0
  }
2036
0
      else if (type == OPTION6_STATUS_CODE)
2037
0
  {
2038
0
    int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
2039
0
    memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
2040
0
    daemon->namebuff[len + opt6_len(opt) - 2] = 0;
2041
0
    optname = "status";
2042
0
  }
2043
0
      else
2044
0
  {
2045
    /* account for flag byte on FQDN */
2046
0
    int offset = type == OPTION6_FQDN ? 1 : 0;
2047
0
    optname = option_string(AF_INET6, type, opt6_ptr(opt, offset), opt6_len(opt) - offset, daemon->namebuff, MAXDNAME);
2048
0
  }
2049
      
2050
0
      my_syslog(MS_DHCP | LOG_INFO, "%u %s size:%3d option:%3d %s  %s", 
2051
0
    xid, desc, opt6_len(opt), type, optname, daemon->namebuff);
2052
      
2053
0
      if (ia_options)
2054
0
  log6_opts(1, xid, ia_options, opt6_ptr(opt, opt6_len(opt)));
2055
0
    }
2056
0
}     
2057
 
2058
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string)
2059
0
{
2060
0
  if (option_bool(OPT_LOG_OPTS) || !option_bool(OPT_QUIET_DHCP6))
2061
0
    log6_packet(state, type, addr, string);
2062
0
}
2063
2064
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string)
2065
0
{
2066
0
  int clid_len = state->clid_len;
2067
2068
  /* avoid buffer overflow */
2069
0
  if (clid_len > 100)
2070
0
    clid_len = 100;
2071
  
2072
0
  print_mac(daemon->namebuff, state->clid, clid_len);
2073
2074
0
  if (addr)
2075
0
    {
2076
0
      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
2077
0
      strcat(daemon->dhcp_buff2, " ");
2078
0
    }
2079
0
  else
2080
0
    daemon->dhcp_buff2[0] = 0;
2081
2082
0
  if(option_bool(OPT_LOG_OPTS))
2083
0
    my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s %s",
2084
0
        state->xid, 
2085
0
        type,
2086
0
        state->iface_name, 
2087
0
        daemon->dhcp_buff2,
2088
0
        daemon->namebuff,
2089
0
        string ? string : "");
2090
0
  else
2091
0
    my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s %s",
2092
0
        type,
2093
0
        state->iface_name, 
2094
0
        daemon->dhcp_buff2,
2095
0
        daemon->namebuff,
2096
0
        string ? string : "");
2097
0
}
2098
2099
static void *opt6_find (uint8_t *opts, uint8_t *end, unsigned int search, unsigned int minsize)
2100
0
{
2101
0
  u16 opt, opt_len;
2102
0
  void *start;
2103
  
2104
0
  if (!opts)
2105
0
    return NULL;
2106
    
2107
0
  while (1)
2108
0
    {
2109
0
      if (end - opts < 4) 
2110
0
  return NULL;
2111
      
2112
0
      start = opts;
2113
0
      GETSHORT(opt, opts);
2114
0
      GETSHORT(opt_len, opts);
2115
      
2116
0
      if (opt_len > (end - opts))
2117
0
  return NULL;
2118
      
2119
0
      if (opt == search && (opt_len >= minsize))
2120
0
  return start;
2121
      
2122
0
      opts += opt_len;
2123
0
    }
2124
0
}
2125
2126
static void *opt6_next(uint8_t *opts, uint8_t *end)
2127
0
{
2128
0
  u16 opt_len;
2129
  
2130
0
  if (end - opts < 4) 
2131
0
    return NULL;
2132
  
2133
0
  opts += 2;
2134
0
  GETSHORT(opt_len, opts);
2135
  
2136
0
  if (opt_len >= (end - opts))
2137
0
    return NULL;
2138
  
2139
0
  return opts + opt_len;
2140
0
}
2141
2142
static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
2143
0
{
2144
  /* this worries about unaligned data and byte order */
2145
0
  unsigned int ret = 0;
2146
0
  int i;
2147
0
  unsigned char *p = opt6_ptr(opt, offset);
2148
  
2149
0
  for (i = 0; i < size; i++)
2150
0
    ret = (ret << 8) | *p++;
2151
  
2152
0
  return ret;
2153
0
} 
2154
2155
int relay_upstream6(int iface_index, ssize_t sz, 
2156
        struct in6_addr *peer_address, u32 scope_id, time_t now)
2157
0
{
2158
0
  unsigned char *header;
2159
0
  unsigned char *inbuff = daemon->dhcp_packet.iov_base;
2160
0
  int msg_type = *inbuff;
2161
0
  int hopcount, o;
2162
0
  struct in6_addr multicast;
2163
0
  unsigned int maclen, mactype;
2164
0
  unsigned char mac[DHCP_CHADDR_MAX];
2165
0
  struct dhcp_relay *relay;
2166
  
2167
0
  for (relay = daemon->relay6; relay; relay = relay->next)
2168
0
    if (relay->iface_index != 0 && relay->iface_index == iface_index)
2169
0
      break;
2170
2171
  /* No relay config. */
2172
0
  if (!relay)
2173
0
    return 0;
2174
  
2175
0
  inet_pton(AF_INET6, ALL_SERVERS, &multicast);
2176
0
  get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
2177
  
2178
  /* Get hop count from nested relayed message */ 
2179
0
  if (msg_type == DHCP6RELAYFORW)
2180
0
    hopcount = *((unsigned char *)inbuff+1) + 1;
2181
0
  else
2182
0
    hopcount = 0;
2183
2184
0
  reset_counter();
2185
2186
  /* RFC 3315 HOP_COUNT_LIMIT */
2187
0
  if (hopcount > 32 || !(header = put_opt6(NULL, 34)))
2188
0
    return 1;
2189
  
2190
0
  header[0] = DHCP6RELAYFORW;
2191
0
  header[1] = hopcount;
2192
0
  memcpy(&header[18], peer_address, IN6ADDRSZ);
2193
  
2194
  /* RFC-6939 */
2195
0
  if (maclen != 0)
2196
0
    {
2197
0
      o = new_opt6(OPTION6_CLIENT_MAC);
2198
0
      put_opt6_short(mactype);
2199
0
      put_opt6(mac, maclen);
2200
0
      end_opt6(o);
2201
0
    }
2202
  
2203
0
  o = new_opt6(OPTION6_RELAY_MSG);
2204
0
  put_opt6(inbuff, sz);
2205
0
  end_opt6(o);
2206
  
2207
0
  for (; relay; relay = relay->next)
2208
0
    if (relay->iface_index != 0 && relay->iface_index == iface_index)
2209
0
      {
2210
0
  union mysockaddr to;
2211
2212
0
  memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ);
2213
  
2214
0
  to.sa.sa_family = AF_INET6;
2215
0
  to.in6.sin6_addr = relay->server.addr6;
2216
#ifdef HAVE_SOCKADDR_SA_LEN
2217
  to.in6.sin6_len = sizeof(struct sockaddr_in6);
2218
#endif 
2219
0
  to.in6.sin6_port = htons(relay->port);
2220
0
  to.in6.sin6_flowinfo = 0;
2221
0
  to.in6.sin6_scope_id = 0;
2222
  
2223
0
  if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast))
2224
0
    {
2225
0
      int multicast_iface;
2226
0
      if (!relay->interface || strchr(relay->interface, '*') ||
2227
0
    (multicast_iface = if_nametoindex(relay->interface)) == 0 ||
2228
0
    setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1)
2229
0
        {
2230
0
    my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface);
2231
0
    continue;
2232
0
        }
2233
0
    }
2234
  
2235
0
#ifdef HAVE_DUMPFILE
2236
0
  dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, &to, daemon->dhcp6fd);
2237
0
#endif
2238
2239
0
  while (retry_send(sendto(daemon->dhcp6fd, (void *)daemon->outpacket.iov_base, save_counter(-1),
2240
0
         0, (struct sockaddr *)&to, sa_len(&to))));
2241
  
2242
0
  if (option_bool(OPT_LOG_OPTS))
2243
0
    {
2244
0
      inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN);
2245
0
      if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast))
2246
0
        snprintf(daemon->namebuff, MAXDNAME, _("multicast via %s"), relay->interface);
2247
0
      else
2248
0
        inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN);
2249
0
      my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff);
2250
0
    }
2251
  
2252
0
      }
2253
  
2254
0
  return 1;
2255
0
}
2256
2257
int relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface)
2258
0
{
2259
0
  struct dhcp_relay *relay;
2260
0
  struct in6_addr link;
2261
0
  unsigned char *inbuff = daemon->dhcp_packet.iov_base;
2262
  
2263
  /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
2264
     which is               1   +    1   +    16      +     16     + 2 + 2 = 38 */
2265
  
2266
0
  if (sz < 38 || *inbuff != DHCP6RELAYREPL)
2267
0
    return 0;
2268
  
2269
0
  memcpy(&link, &inbuff[2], IN6ADDRSZ); 
2270
  
2271
0
  for (relay = daemon->relay6; relay; relay = relay->next)
2272
0
    if (IN6_ARE_ADDR_EQUAL(&link, &relay->local.addr6) &&
2273
0
  (!relay->interface || wildcard_match(relay->interface, arrival_interface)))
2274
0
      break;
2275
      
2276
0
  reset_counter();
2277
2278
0
  if (relay)
2279
0
    {
2280
0
      void *opt, *opts = inbuff + 34;
2281
0
      void *end = inbuff + sz;
2282
      
2283
0
      if ((opt = opt6_find(opts, end, OPTION6_RELAY_MSG, 4)))
2284
0
  {
2285
0
    int encap_type = opt6_uint(opt, 0, 1);
2286
0
    put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
2287
0
    memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ); 
2288
0
    peer->sin6_scope_id = relay->iface_index;
2289
2290
0
    if (encap_type == DHCP6RELAYREPL)
2291
0
      {
2292
0
        peer->sin6_port = ntohs(DHCPV6_SERVER_PORT);
2293
0
        return 1;
2294
0
      }
2295
    
2296
0
    peer->sin6_port = ntohs(DHCPV6_CLIENT_PORT);
2297
    
2298
0
#ifdef HAVE_SCRIPT
2299
0
    if (daemon->lease_change_command && encap_type == DHCP6REPLY)
2300
0
      {
2301
        /* skip over message type and transaction-id. to get to options. */
2302
0
        opts = opt6_ptr(opt, 4);
2303
0
        end = opt6_ptr(opt, opt6_len(opt));
2304
2305
0
        if ((opt = opt6_find(opts, end, OPTION6_IA_PD, 12)))
2306
0
    {
2307
0
      opts = opt6_ptr(opt, 12);
2308
0
      end = opt6_ptr(opt, opt6_len(opt));
2309
      
2310
0
      for (opt = opt6_find(opts, end, OPTION6_IAPREFIX, 25); opt; opt = opt6_find(opt6_next(opt, end), end, OPTION6_IAPREFIX, 25))
2311
        /* valid lifetime must not be zero. */
2312
0
        if (opt6_uint(opt, 4, 4) != 0)
2313
0
          {
2314
0
      if (daemon->free_snoops ||
2315
0
          (daemon->free_snoops = whine_malloc(sizeof(struct snoop_record))))
2316
0
        {
2317
0
          struct snoop_record *snoop = daemon->free_snoops;
2318
          
2319
0
          daemon->free_snoops = snoop->next;
2320
0
          snoop->client = peer->sin6_addr;
2321
0
          snoop->prefix_len = opt6_uint(opt, 8, 1); 
2322
0
          memcpy(&snoop->prefix, opt6_ptr(opt, 9), IN6ADDRSZ); 
2323
0
          snoop->next = relay->snoop_records;
2324
0
          relay->snoop_records = snoop;
2325
0
        }
2326
0
          }
2327
0
    }       
2328
0
      }
2329
0
#endif
2330
0
    return 1;
2331
0
  }
2332
0
    }
2333
  
2334
0
  return 0;
2335
0
}
2336
  
2337
#ifdef HAVE_SCRIPT
2338
int do_snoop_script_run(void)
2339
0
{
2340
0
  struct dhcp_relay *relay;
2341
0
  struct snoop_record *snoop;
2342
  
2343
0
  for (relay = daemon->relay6; relay; relay = relay->next)
2344
0
    if ((snoop = relay->snoop_records))
2345
0
      {
2346
0
  relay->snoop_records = snoop->next;
2347
0
  snoop->next = daemon->free_snoops;
2348
0
  daemon->free_snoops = snoop;
2349
  
2350
0
  queue_relay_snoop(&snoop->client, relay->iface_index, &snoop->prefix, snoop->prefix_len);
2351
0
  return 1;
2352
0
      }
2353
  
2354
0
  return 0;
2355
0
}
2356
#endif
2357
2358
#endif