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