1: /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
2:
3: This program is free software; you can redistribute it and/or modify
4: it under the terms of the GNU General Public License as published by
5: the Free Software Foundation; version 2 dated June, 1991, or
6: (at your option) version 3 dated 29 June, 2007.
7:
8: This program is distributed in the hope that it will be useful,
9: but WITHOUT ANY WARRANTY; without even the implied warranty of
10: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11: GNU General Public License for more details.
12:
13: You should have received a copy of the GNU General Public License
14: along with this program. If not, see <http://www.gnu.org/licenses/>.
15: */
16:
17:
18: #include "dnsmasq.h"
19:
20: #ifdef HAVE_DHCP6
21:
22: struct state {
23: unsigned char *clid;
24: int clid_len, iaid, ia_type, interface, hostname_auth, lease_allocate;
25: char *client_hostname, *hostname, *domain, *send_domain;
26: struct dhcp_context *context;
27: struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
28: unsigned int xid, fqdn_flags;
29: char *iface_name;
30: void *packet_options, *end;
31: struct dhcp_netid *tags, *context_tags;
32: unsigned char mac[DHCP_CHADDR_MAX];
33: unsigned int mac_len, mac_type;
34: #ifdef OPTION6_PREFIX_CLASS
35: struct prefix_class *send_prefix_class;
36: #endif
37: };
38:
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);
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);
44: static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
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
55: static void mark_context_used(struct state *state, struct in6_addr *addr);
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);
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);
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);
62: static struct dhcp_netid *add_options(struct state *state, int do_refresh);
63: static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
64: unsigned int *preferred_timep, unsigned int lease_time);
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:
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:
74:
75: unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
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)
78: {
79: struct dhcp_vendor *vendor;
80: int msg_type;
81: struct state state;
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);
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))
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. */
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)
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.
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. */
131:
132: if (!state->link_address)
133: get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type, now);
134: else
135: {
136: struct dhcp_context *c;
137: state->context = NULL;
138:
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))
142: for (c = daemon->dhcp6; c; c = c->next)
143: if ((c->flags & CONTEXT_DHCP) &&
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))
147: {
148: c->preferred = c->valid = 0xffffffff;
149: c->current = state->context;
150: state->context = c;
151: }
152:
153: if (!state->context)
154: {
155: inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN);
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: }
162:
163: if (!state->context)
164: {
165: my_syslog(MS_DHCP | LOG_WARNING,
166: _("no address range available for DHCPv6 request via %s"), state->iface_name);
167: return 0;
168: }
169:
170: return dhcp6_no_relay(state, msg_type, inbuff, sz, is_unicast, now);
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 */
179: if (!(outmsgtypep = put_opt6(inbuff, 34)))
180: return 0;
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: {
200: vendor->netid.next = state->tags;
201: state->tags = &vendor->netid;
202: break;
203: }
204: }
205:
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:
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: {
219: struct in6_addr align;
220: /* the packet data is unaligned, copy to aligned storage */
221: memcpy(&align, inbuff + 2, IN6ADDRSZ);
222: state->link_address = &align;
223: /* zero is_unicast since that is now known to refer to the
224: relayed packet, not the original sent by the client */
225: if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
226: return 0;
227: }
228: else if (opt6_type(opt) != OPTION6_CLIENT_MAC)
229: put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
230: end_opt6(o);
231: }
232:
233: return 1;
234: }
235:
236: static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now)
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;
247: struct dhcp_mac *mac_opt;
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:
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 */
266: #ifdef OPTION6_PREFIX_CLASS
267: state->send_prefix_class = NULL;
268: #endif
269:
270: /* set tag with name == interface */
271: iface_id.net = state->iface_name;
272: iface_id.next = state->tags;
273: state->tags = &iface_id;
274:
275: /* set tag "dhcpv6" */
276: v6_id.net = "dhcpv6";
277: v6_id.next = state->tags;
278: state->tags = &v6_id;
279:
280: /* copy over transaction-id, and save pointer to message type */
281: if (!(outmsgtypep = put_opt6(inbuff, 4)))
282: return 0;
283: start_opts = save_counter(-1);
284: state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
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 */
288: for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
289: {
290: context_tmp->netid.next = &context_tmp->netid;
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"),
298: state->xid, daemon->dhcp_buff, context_tmp->prefix);
299: else
300: my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
301: state->xid, daemon->dhcp_buff, daemon->dhcp_buff2);
302: }
303: }
304:
305: if ((opt = opt6_find(state->packet_options, state->end, OPTION6_CLIENT_ID, 1)))
306: {
307: state->clid = opt6_ptr(opt, 0);
308: state->clid_len = opt6_len(opt);
309: o = new_opt6(OPTION6_CLIENT_ID);
310: put_opt6(state->clid, state->clid_len);
311: end_opt6(o);
312: }
313: else if (msg_type != DHCP6IREQ)
314: return 0;
315:
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 &&
318: (!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
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: *outmsgtypep = DHCP6REPLY;
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:
351: if ((opt = opt6_find(state->packet_options, state->end, mopt, 2)))
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:
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)
371: {
372: vendor->netid.next = state->tags;
373: state->tags = &vendor->netid;
374: break;
375: }
376: }
377: }
378:
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));
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: {
392: for (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_OPTS, 4);
393: opt;
394: opt = opt6_find(opt6_next(opt, state->end), state->end, OPTION6_VENDOR_OPTS, 4))
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: {
410: if (!(opt = opt6_find(state->packet_options, state->end, opt_cfg->opt, 1)))
411: continue;
412:
413: match = match_bytes(opt_cfg, opt6_ptr(opt, 0), opt6_len(opt));
414: }
415:
416: if (match)
417: {
418: opt_cfg->netid->next = state->tags;
419: state->tags = opt_cfg->netid;
420: }
421: }
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: }
440:
441: if ((opt = opt6_find(state->packet_options, state->end, OPTION6_FQDN, 1)))
442: {
443: /* RFC4704 refers */
444: int len = opt6_len(opt) - 1;
445:
446: state->fqdn_flags = opt6_uint(opt, 0, 1);
447:
448: /* Always force update, since the client has no way to do it itself. */
449: if (!option_bool(OPT_FQDN_UPDATE) && !(state->fqdn_flags & 0x01))
450: state->fqdn_flags |= 0x03;
451:
452: state->fqdn_flags &= ~0x04;
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: {
474: state->client_hostname = daemon->dhcp_buff;
475: if (option_bool(OPT_LOG_OPTS))
476: my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), state->xid, state->client_hostname);
477: }
478: }
479: }
480:
481: if (state->clid)
482: {
483: config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL);
484:
485: if (have_config(config, CONFIG_NAME))
486: {
487: state->hostname = config->hostname;
488: state->domain = config->domain;
489: state->hostname_auth = 1;
490: }
491: else if (state->client_hostname)
492: {
493: state->domain = strip_hostname(state->client_hostname);
494:
495: if (strlen(state->client_hostname) != 0)
496: {
497: state->hostname = state->client_hostname;
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. */
503: struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname);
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: {
517: list->list->next = state->tags;
518: state->tags = list->list;
519: }
520:
521: /* set "known" tag for known hosts */
522: known_id.net = "known";
523: known_id.next = state->tags;
524: state->tags = &known_id;
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:
536: if ((oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0)))
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: {
549: p->tag.next = state->tags;
550: state->tags = &p->tag;
551: }
552: }
553: #endif
554:
555: tagif = run_tag_if(state->tags);
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 */
568: if (!state->hostname_auth)
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)
576: state->hostname = NULL;
577: }
578:
579:
580: switch (msg_type)
581: {
582: default:
583: return 0;
584:
585:
586: case DHCP6SOLICIT:
587: {
588: int address_assigned = 0;
589: /* tags without all prefix-class tags */
590: struct dhcp_netid *solicit_tags;
591: struct dhcp_context *c;
592:
593: *outmsgtypep = DHCP6ADVERTISE;
594:
595: if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
596: {
597: *outmsgtypep = DHCP6REPLY;
598: state->lease_allocate = 1;
599: o = new_opt6(OPTION6_RAPID_COMMIT);
600: end_opt6(o);
601: }
602:
603: log6_quiet(state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
604:
605: request_no_address:
606: solicit_tags = tagif;
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 */
615: for (c = state->context; c; c = c->current)
616: c->flags &= ~CONTEXT_CONF_USED;
617:
618: for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
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;
627: u32 lease_time;
628: struct dhcp_lease *ltmp;
629: struct in6_addr *req_addr;
630: struct in6_addr addr;
631:
632: if (!check_ia(state, opt, &ia_end, &ia_option))
633: continue;
634:
635: /* reset USED bits in contexts - one address per prefix per IAID */
636: for (c = state->context; c; c = c->current)
637: c->flags &= ~CONTEXT_USED;
638:
639: #ifdef OPTION6_PREFIX_CLASS
640: if (daemon->prefix_classes && state->ia_type == OPTION6_IA_NA)
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 */
664: p->tag.next = state->tags;
665: solicit_tags = run_tag_if(&p->tag);
666: plain_range = 0;
667: state->send_prefix_class = p;
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;
683: state->send_prefix_class = p;
684: }
685: }
686:
687: if (p && option_bool(OPT_LOG_OPTS))
688: my_syslog(MS_DHCP | LOG_INFO, "%u prefix class %d tag:%s", state->xid, p->class, p->tag.net);
689: }
690: }
691: #endif
692:
693: o = build_ia(state, &t1cntr);
694: if (address_assigned)
695: address_assigned = 2;
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);
700:
701: if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
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. */
707: if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
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: }
714: else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
715: continue; /* not an address we're allowed */
716: else if (!check_address(state, req_addr))
717: continue; /* address leased elsewhere */
718:
719: /* add address to output packet */
720: #ifdef OPTION6_PREFIX_CLASS
721: if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
722: state->send_prefix_class = prefix_class_from_context(c);
723: #endif
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);
727: address_assigned = 1;
728: }
729: }
730:
731: /* Suggest configured address(es) */
732: for (c = state->context; c; c = c->current)
733: if (!(c->flags & CONTEXT_CONF_USED) &&
734: match_netid(c->filter, solicit_tags, plain_range) &&
735: config_valid(config, c, &addr) &&
736: check_address(state, &addr))
737: {
738: mark_config_used(state->context, &addr);
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
745: if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
746: state->send_prefix_class = prefix_class_from_context(c);
747: #endif
748: add_address(state, c, lease_time, NULL, &min_time, &addr, now);
749: mark_context_used(state, &addr);
750: get_context_tag(state, c);
751: address_assigned = 1;
752: }
753:
754: /* return addresses for existing leases */
755: ltmp = NULL;
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)))
757: {
758: req_addr = <mp->addr6;
759: if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
760: {
761: #ifdef OPTION6_PREFIX_CLASS
762: if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
763: state->send_prefix_class = prefix_class_from_context(c);
764: #endif
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);
768: address_assigned = 1;
769: }
770: }
771:
772: /* Return addresses for all valid contexts which don't yet have one */
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)))
775: {
776: #ifdef OPTION6_PREFIX_CLASS
777: if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
778: state->send_prefix_class = prefix_class_from_context(c);
779: #endif
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);
783: address_assigned = 1;
784: }
785:
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:
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);
823: tagif = add_options(state, 0);
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);
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: }
842: }
843:
844: break;
845: }
846:
847: case DHCP6REQUEST:
848: {
849: int address_assigned = 0;
850: int start = save_counter(-1);
851:
852: /* set reply message type */
853: *outmsgtypep = DHCP6REPLY;
854: state->lease_allocate = 1;
855:
856: log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
857:
858: if (ignore)
859: return 0;
860:
861: for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
862: {
863: void *ia_option, *ia_end;
864: unsigned int min_time = 0xffffffff;
865: int t1cntr;
866:
867: if (!check_ia(state, opt, &ia_end, &ia_option))
868: continue;
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);
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:
888: if ((c = address6_valid(state->context, req_addr, tagif, 1)))
889: config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
890:
891: if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
892: {
893: if (!dynamic && !config_ok)
894: {
895: /* Static range, not configured. */
896: o1 = new_opt6(OPTION6_STATUS_CODE);
897: put_opt6_short(DHCP6NOADDRS);
898: put_opt6_string(_("address unavailable"));
899: end_opt6(o1);
900: }
901: else if (!check_address(state, req_addr))
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
920: if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
921: state->send_prefix_class = prefix_class_from_context(c);
922: #endif
923: add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
924: get_context_tag(state, dynamic);
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);
956: log6_packet(state, "DHCPREPLY", NULL, _("no addresses available"));
957: }
958:
959: tagif = add_options(state, 0);
960: break;
961: }
962:
963:
964: case DHCP6RENEW:
965: {
966: /* set reply message type */
967: *outmsgtypep = DHCP6REPLY;
968:
969: log6_quiet(state, "DHCPRENEW", NULL, NULL);
970:
971: for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
972: {
973: void *ia_option, *ia_end;
974: unsigned int min_time = 0xffffffff;
975: int t1cntr, iacntr;
976:
977: if (!check_ia(state, opt, &ia_end, &ia_option))
978: continue;
979:
980: o = build_ia(state, &t1cntr);
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);
987: unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
988: unsigned int valid_time = opt6_uint(ia_option, 20, 4);
989: char *message = NULL;
990: struct dhcp_context *this_context;
991:
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)))
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:
1002: log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
1003:
1004: o1 = new_opt6(OPTION6_STATUS_CODE);
1005: put_opt6_short(DHCP6NOBINDING);
1006: put_opt6_string(_("no binding found"));
1007: end_opt6(o1);
1008:
1009: preferred_time = valid_time = 0;
1010: break;
1011: }
1012:
1013:
1014: if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
1015: (this_context = address6_valid(state->context, req_addr, tagif, 1)))
1016: {
1017: struct in6_addr addr;
1018: unsigned int lease_time;
1019:
1020: get_context_tag(state, this_context);
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:
1027: calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time);
1028:
1029: lease_set_expires(lease, valid_time, now);
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)
1034: {
1035: char *addr_domain = get_domain6(req_addr);
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;
1040: }
1041:
1042:
1043: if (preferred_time == 0)
1044: message = _("deprecated");
1045: }
1046: else
1047: {
1048: preferred_time = valid_time = 0;
1049: message = _("address invalid");
1050: }
1051:
1052: if (message && (message != state->hostname))
1053: log6_packet(state, "DHCPREPLY", req_addr, message);
1054: else
1055: log6_quiet(state, "DHCPREPLY", req_addr, message);
1056:
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:
1068: tagif = add_options(state, 0);
1069: break;
1070:
1071: }
1072:
1073: case DHCP6CONFIRM:
1074: {
1075: int good_addr = 0;
1076:
1077: /* set reply message type */
1078: *outmsgtypep = DHCP6REPLY;
1079:
1080: log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
1081:
1082: for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1083: {
1084: void *ia_option, *ia_end;
1085:
1086: for (check_ia(state, opt, &ia_end, &ia_option);
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:
1092: if (!address6_valid(state->context, req_addr, tagif, 1))
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:
1101: good_addr = 1;
1102: log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
1103: }
1104: }
1105:
1106: /* No addresses, no reply: RFC 3315 18.2.2 */
1107: if (!good_addr)
1108: return 0;
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 */
1121: if (state->context && state->context->netid.net && !state->context->current)
1122: {
1123: state->context->netid.next = NULL;
1124: state->context_tags = &state->context->netid;
1125: }
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);
1136: if (ignore)
1137: return 0;
1138: *outmsgtypep = DHCP6REPLY;
1139: tagif = add_options(state, 1);
1140: break;
1141: }
1142:
1143:
1144: case DHCP6RELEASE:
1145: {
1146: /* set reply message type */
1147: *outmsgtypep = DHCP6REPLY;
1148:
1149: log6_quiet(state, "DHCPRELEASE", NULL, NULL);
1150:
1151: for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1152: {
1153: void *ia_option, *ia_end;
1154: int made_ia = 0;
1155:
1156: for (check_ia(state, opt, &ia_end, &ia_option);
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:
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))))
1164: lease_prune(lease, now);
1165: else
1166: {
1167: if (!made_ia)
1168: {
1169: o = new_opt6(state->ia_type);
1170: put_opt6_long(state->iaid);
1171: if (state->ia_type == OPTION6_IA_NA)
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:
1211: log6_quiet(state, "DHCPDECLINE", NULL, NULL);
1212:
1213: for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1214: {
1215: void *ia_option, *ia_end;
1216: int made_ia = 0;
1217:
1218: for (check_ia(state, opt, &ia_end, &ia_option);
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. */
1236: for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
1237: context_tmp->addr_epoch++;
1238:
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))))
1241: lease_prune(lease, now);
1242: else
1243: {
1244: if (!made_ia)
1245: {
1246: o = new_opt6(state->ia_type);
1247: put_opt6_long(state->iaid);
1248: if (state->ia_type == OPTION6_IA_NA)
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: }
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);
1281: break;
1282: }
1283:
1284: }
1285:
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));
1288:
1289: return 1;
1290:
1291: }
1292:
1293: static struct dhcp_netid *add_options(struct state *state, int do_refresh)
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;
1299: int done_dns = 0, done_refresh = !do_refresh, do_encap = 0;
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:
1321: if (opt_cfg->opt == OPTION6_REFRESH_TIME)
1322: done_refresh = 1;
1323:
1324: if (opt_cfg->opt == OPTION6_DNS_SERVER)
1325: done_dns = 1;
1326:
1327: if (opt_cfg->flags & DHOPT_ADDR6)
1328: {
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);
1362: }
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);
1373: }
1374: }
1375:
1376: if (daemon->port == NAMESERVER_PORT && !done_dns)
1377: {
1378: o = new_opt6(OPTION6_DNS_SERVER);
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);
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)
1469: len += strlen(state->send_domain) + 2;
1470:
1471: o = new_opt6(OPTION6_FQDN);
1472: if ((p = expand(len + 2)))
1473: {
1474: *(p++) = state->fqdn_flags;
1475: p = do_rfc1035_name(p, state->hostname);
1476: if (state->send_domain)
1477: {
1478: p = do_rfc1035_name(p, state->send_domain);
1479: *p = 0;
1480: }
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:
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)
1637: {
1638: unsigned int valid_time = 0, preferred_time = 0;
1639: int o = new_opt6(OPTION6_IAADDR);
1640: struct dhcp_lease *lease;
1641:
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);
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:
1666: if (state->lease_allocate)
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:
1690: log6_quiet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
1691:
1692: }
1693:
1694: static void mark_context_used(struct state *state, struct in6_addr *addr)
1695: {
1696: struct dhcp_context *context;
1697:
1698: /* Mark that we have an address for this prefix. */
1699: #ifdef OPTION6_PREFIX_CLASS
1700: for (context = state->context; context; context = context->current)
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
1705: for (context = state->context; context; context = context->current)
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 ||
1728: lease->iaid != state->iaid)
1729: return 0;
1730:
1731: return 1;
1732: }
1733:
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: */
1751: static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep,
1752: unsigned int *preferred_timep, unsigned int lease_time)
1753: {
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: }
1782:
1783: /* deprecate (preferred == 0) which configured, or when local address
1784: is deprecated */
1785: if ((context->flags & CONTEXT_DEPRECATE) || context->preferred == 0)
1786: preferred_time = 0;
1787:
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);
1801: #ifdef HAVE_SCRIPT
1802: struct dhcp_netid *tagif = run_tag_if(state->tags);
1803: #endif
1804:
1805: (void)context;
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);
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);
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:
1901: if (!option_bool(OPT_LOG_OPTS) || start_opts == end_opts)
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:
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:
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:
2057: void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
2058: struct in6_addr *peer_address, u32 scope_id, time_t now)
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);
2072: get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
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:
2184: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>