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