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