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