Annotation of embedaddon/dnsmasq/src/dhcp-common.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: #include "dnsmasq.h"
18:
19: #ifdef HAVE_DHCP
20:
21: void dhcp_common_init(void)
22: {
23: /* These each hold a DHCP option max size 255
24: and get a terminating zero added */
25: daemon->dhcp_buff = safe_malloc(256);
26: daemon->dhcp_buff2 = safe_malloc(256);
27: daemon->dhcp_buff3 = safe_malloc(256);
28:
29: /* dhcp_packet is used by v4 and v6, outpacket only by v6
30: sizeof(struct dhcp_packet) is as good an initial size as any,
31: even for v6 */
32: expand_buf(&daemon->dhcp_packet, sizeof(struct dhcp_packet));
33: #ifdef HAVE_DHCP6
34: if (daemon->dhcp6)
35: expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
36: #endif
37: }
38:
39: ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
40: {
41: ssize_t sz;
42:
43: while (1)
44: {
45: msg->msg_flags = 0;
46: while ((sz = recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
47:
48: if (sz == -1)
49: return -1;
50:
51: if (!(msg->msg_flags & MSG_TRUNC))
52: break;
53:
54: /* Very new Linux kernels return the actual size needed,
55: older ones always return truncated size */
56: if ((size_t)sz == msg->msg_iov->iov_len)
57: {
58: if (!expand_buf(msg->msg_iov, sz + 100))
59: return -1;
60: }
61: else
62: {
63: expand_buf(msg->msg_iov, sz);
64: break;
65: }
66: }
67:
68: while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
69:
70: return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
71: }
72:
73: struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
74: {
75: struct tag_if *exprs;
76: struct dhcp_netid_list *list;
77:
78: for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
79: if (match_netid(exprs->tag, tags, 1))
80: for (list = exprs->set; list; list = list->next)
81: {
82: list->list->next = tags;
83: tags = list->list;
84: }
85:
86: return tags;
87: }
88:
89:
90: struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags, struct dhcp_opt *opts)
91: {
92: struct dhcp_netid *tagif = run_tag_if(tags);
93: struct dhcp_opt *opt;
94: struct dhcp_opt *tmp;
95:
96: /* flag options which are valid with the current tag set (sans context tags) */
97: for (opt = opts; opt; opt = opt->next)
98: {
99: opt->flags &= ~DHOPT_TAGOK;
100: if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
101: match_netid(opt->netid, tagif, 0))
102: opt->flags |= DHOPT_TAGOK;
103: }
104:
105: /* now flag options which are valid, including the context tags,
106: otherwise valid options are inhibited if we found a higher priority one above */
107: if (context_tags)
108: {
109: struct dhcp_netid *last_tag;
110:
111: for (last_tag = context_tags; last_tag->next; last_tag = last_tag->next);
112: last_tag->next = tags;
113: tagif = run_tag_if(context_tags);
114:
115: /* reset stuff with tag:!<tag> which now matches. */
116: for (opt = opts; opt; opt = opt->next)
117: if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
118: (opt->flags & DHOPT_TAGOK) &&
119: !match_netid(opt->netid, tagif, 0))
120: opt->flags &= ~DHOPT_TAGOK;
121:
122: for (opt = opts; opt; opt = opt->next)
123: if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
124: match_netid(opt->netid, tagif, 0))
125: {
126: struct dhcp_opt *tmp;
127: for (tmp = opts; tmp; tmp = tmp->next)
128: if (tmp->opt == opt->opt && opt->netid && (tmp->flags & DHOPT_TAGOK))
129: break;
130: if (!tmp)
131: opt->flags |= DHOPT_TAGOK;
132: }
133: }
134:
135: /* now flag untagged options which are not overridden by tagged ones */
136: for (opt = opts; opt; opt = opt->next)
137: if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) && !opt->netid)
138: {
139: for (tmp = opts; tmp; tmp = tmp->next)
140: if (tmp->opt == opt->opt && (tmp->flags & DHOPT_TAGOK))
141: break;
142: if (!tmp)
143: opt->flags |= DHOPT_TAGOK;
144: else if (!tmp->netid)
145: my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring duplicate dhcp-option %d"), tmp->opt);
146: }
147:
148: /* Finally, eliminate duplicate options later in the chain, and therefore earlier in the config file. */
149: for (opt = opts; opt; opt = opt->next)
150: if (opt->flags & DHOPT_TAGOK)
151: for (tmp = opt->next; tmp; tmp = tmp->next)
152: if (tmp->opt == opt->opt)
153: tmp->flags &= ~DHOPT_TAGOK;
154:
155: return tagif;
156: }
157:
158: /* Is every member of check matched by a member of pool?
159: If tagnotneeded, untagged is OK */
160: int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
161: {
162: struct dhcp_netid *tmp1;
163:
164: if (!check && !tagnotneeded)
165: return 0;
166:
167: for (; check; check = check->next)
168: {
169: /* '#' for not is for backwards compat. */
170: if (check->net[0] != '!' && check->net[0] != '#')
171: {
172: for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
173: if (strcmp(check->net, tmp1->net) == 0)
174: break;
175: if (!tmp1)
176: return 0;
177: }
178: else
179: for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
180: if (strcmp((check->net)+1, tmp1->net) == 0)
181: return 0;
182: }
183: return 1;
184: }
185:
186: /* return domain or NULL if none. */
187: char *strip_hostname(char *hostname)
188: {
189: char *dot = strchr(hostname, '.');
190:
191: if (!dot)
192: return NULL;
193:
194: *dot = 0; /* truncate */
195: if (strlen(dot+1) != 0)
196: return dot+1;
197:
198: return NULL;
199: }
200:
201: void log_tags(struct dhcp_netid *netid, u32 xid)
202: {
203: if (netid && option_bool(OPT_LOG_OPTS))
204: {
205: char *s = daemon->namebuff;
206: for (*s = 0; netid; netid = netid->next)
207: {
208: /* kill dupes. */
209: struct dhcp_netid *n;
210:
211: for (n = netid->next; n; n = n->next)
212: if (strcmp(netid->net, n->net) == 0)
213: break;
214:
215: if (!n)
216: {
217: strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
218: if (netid->next)
219: strncat (s, ", ", (MAXDNAME-1) - strlen(s));
220: }
221: }
222: my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), xid, s);
223: }
224: }
225:
226: int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
227: {
228: int i;
229:
230: if (o->len > len)
231: return 0;
232:
233: if (o->len == 0)
234: return 1;
235:
236: if (o->flags & DHOPT_HEX)
237: {
238: if (memcmp_masked(o->val, p, o->len, o->u.wildcard_mask))
239: return 1;
240: }
241: else
242: for (i = 0; i <= (len - o->len); )
243: {
244: if (memcmp(o->val, p + i, o->len) == 0)
245: return 1;
246:
247: if (o->flags & DHOPT_STRING)
248: i++;
249: else
250: i += o->len;
251: }
252:
253: return 0;
254: }
255:
256: void dhcp_update_configs(struct dhcp_config *configs)
257: {
258: /* Some people like to keep all static IP addresses in /etc/hosts.
259: This goes through /etc/hosts and sets static addresses for any DHCP config
260: records which don't have an address and whose name matches.
261: We take care to maintain the invariant that any IP address can appear
262: in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
263: restore the status-quo ante first. */
264:
265: struct dhcp_config *config, *conf_tmp;
266: struct crec *crec;
267: int prot = AF_INET;
268:
269: for (config = configs; config; config = config->next)
270: if (config->flags & CONFIG_ADDR_HOSTS)
271: config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR6 | CONFIG_ADDR_HOSTS);
272:
273: #ifdef HAVE_DHCP6
274: again:
275: #endif
276:
277: if (daemon->port != 0)
278: for (config = configs; config; config = config->next)
279: {
280: int conflags = CONFIG_ADDR;
281: int cacheflags = F_IPV4;
282:
283: #ifdef HAVE_DHCP6
284: if (prot == AF_INET6)
285: {
286: conflags = CONFIG_ADDR6;
287: cacheflags = F_IPV6;
288: }
289: #endif
290: if (!(config->flags & conflags) &&
291: (config->flags & CONFIG_NAME) &&
292: (crec = cache_find_by_name(NULL, config->hostname, 0, cacheflags)) &&
293: (crec->flags & F_HOSTS))
294: {
295: if (cache_find_by_name(crec, config->hostname, 0, cacheflags))
296: {
297: /* use primary (first) address */
298: while (crec && !(crec->flags & F_REVERSE))
299: crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
300: if (!crec)
301: continue; /* should be never */
302: inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
303: my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
304: config->hostname, daemon->addrbuff);
305: }
306:
307: if (prot == AF_INET &&
308: (!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
309: {
310: config->addr = crec->addr.addr.addr.addr4;
311: config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
312: continue;
313: }
314:
315: #ifdef HAVE_DHCP6
316: if (prot == AF_INET6 &&
317: (!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
318: {
319: memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
320: config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
321: continue;
322: }
323: #endif
324:
325: inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
326: my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
327: daemon->addrbuff, config->hostname);
328:
329:
330: }
331: }
332:
333: #ifdef HAVE_DHCP6
334: if (prot == AF_INET)
335: {
336: prot = AF_INET6;
337: goto again;
338: }
339: #endif
340:
341: }
342:
343: #ifdef HAVE_LINUX_NETWORK
344: void bindtodevice(int fd)
345: {
346: /* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
347: to that device. This is for the use case of (eg) OpenStack, which runs a new
348: dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
349: individual processes don't always see the packets they should.
350: SO_BINDTODEVICE is only available Linux. */
351:
352: struct irec *iface, *found;
353:
354: for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
355: if (iface->dhcp_ok)
356: {
357: if (!found)
358: found = iface;
359: else if (strcmp(found->name, iface->name) != 0)
360: {
361: /* more than one. */
362: found = NULL;
363: break;
364: }
365: }
366:
367: if (found)
368: {
369: struct ifreq ifr;
370: strcpy(ifr.ifr_name, found->name);
371: /* only allowed by root. */
372: if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
373: errno != EPERM)
374: die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
375: }
376: }
377: #endif
378:
379: static const struct opttab_t {
380: char *name;
381: u16 val, size;
382: } opttab[] = {
383: { "netmask", 1, OT_ADDR_LIST },
384: { "time-offset", 2, 4 },
385: { "router", 3, OT_ADDR_LIST },
386: { "dns-server", 6, OT_ADDR_LIST },
387: { "log-server", 7, OT_ADDR_LIST },
388: { "lpr-server", 9, OT_ADDR_LIST },
389: { "hostname", 12, OT_INTERNAL | OT_NAME },
390: { "boot-file-size", 13, 2 | OT_DEC },
391: { "domain-name", 15, OT_NAME },
392: { "swap-server", 16, OT_ADDR_LIST },
393: { "root-path", 17, OT_NAME },
394: { "extension-path", 18, OT_NAME },
395: { "ip-forward-enable", 19, 1 },
396: { "non-local-source-routing", 20, 1 },
397: { "policy-filter", 21, OT_ADDR_LIST },
398: { "max-datagram-reassembly", 22, 2 | OT_DEC },
399: { "default-ttl", 23, 1 | OT_DEC },
400: { "mtu", 26, 2 | OT_DEC },
401: { "all-subnets-local", 27, 1 },
402: { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
403: { "router-discovery", 31, 1 },
404: { "router-solicitation", 32, OT_ADDR_LIST },
405: { "static-route", 33, OT_ADDR_LIST },
406: { "trailer-encapsulation", 34, 1 },
407: { "arp-timeout", 35, 4 | OT_DEC },
408: { "ethernet-encap", 36, 1 },
409: { "tcp-ttl", 37, 1 },
410: { "tcp-keepalive", 38, 4 | OT_DEC },
411: { "nis-domain", 40, OT_NAME },
412: { "nis-server", 41, OT_ADDR_LIST },
413: { "ntp-server", 42, OT_ADDR_LIST },
414: { "vendor-encap", 43, OT_INTERNAL },
415: { "netbios-ns", 44, OT_ADDR_LIST },
416: { "netbios-dd", 45, OT_ADDR_LIST },
417: { "netbios-nodetype", 46, 1 },
418: { "netbios-scope", 47, 0 },
419: { "x-windows-fs", 48, OT_ADDR_LIST },
420: { "x-windows-dm", 49, OT_ADDR_LIST },
421: { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
422: { "lease-time", 51, OT_INTERNAL | OT_TIME },
423: { "option-overload", 52, OT_INTERNAL },
424: { "message-type", 53, OT_INTERNAL | OT_DEC },
425: { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
426: { "parameter-request", 55, OT_INTERNAL },
427: { "message", 56, OT_INTERNAL },
428: { "max-message-size", 57, OT_INTERNAL },
429: { "T1", 58, OT_INTERNAL | OT_TIME},
430: { "T2", 59, OT_INTERNAL | OT_TIME},
431: { "vendor-class", 60, 0 },
432: { "client-id", 61, OT_INTERNAL },
433: { "nis+-domain", 64, OT_NAME },
434: { "nis+-server", 65, OT_ADDR_LIST },
435: { "tftp-server", 66, OT_NAME },
436: { "bootfile-name", 67, OT_NAME },
437: { "mobile-ip-home", 68, OT_ADDR_LIST },
438: { "smtp-server", 69, OT_ADDR_LIST },
439: { "pop3-server", 70, OT_ADDR_LIST },
440: { "nntp-server", 71, OT_ADDR_LIST },
441: { "irc-server", 74, OT_ADDR_LIST },
442: { "user-class", 77, 0 },
443: { "FQDN", 81, OT_INTERNAL },
444: { "agent-id", 82, OT_INTERNAL },
445: { "client-arch", 93, 2 | OT_DEC },
446: { "client-interface-id", 94, 0 },
447: { "client-machine-id", 97, 0 },
448: { "subnet-select", 118, OT_INTERNAL },
449: { "domain-search", 119, OT_RFC1035_NAME },
450: { "sip-server", 120, 0 },
451: { "classless-static-route", 121, 0 },
452: { "vendor-id-encap", 125, 0 },
453: { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
454: { NULL, 0, 0 }
455: };
456:
457: #ifdef HAVE_DHCP6
458: static const struct opttab_t opttab6[] = {
459: { "client-id", 1, OT_INTERNAL },
460: { "server-id", 2, OT_INTERNAL },
461: { "ia-na", 3, OT_INTERNAL },
462: { "ia-ta", 4, OT_INTERNAL },
463: { "iaaddr", 5, OT_INTERNAL },
464: { "oro", 6, OT_INTERNAL },
465: { "preference", 7, OT_INTERNAL | OT_DEC },
466: { "unicast", 12, OT_INTERNAL },
467: { "status", 13, OT_INTERNAL },
468: { "rapid-commit", 14, OT_INTERNAL },
469: { "user-class", 15, OT_INTERNAL | OT_CSTRING },
470: { "vendor-class", 16, OT_INTERNAL | OT_CSTRING },
471: { "vendor-opts", 17, OT_INTERNAL },
472: { "sip-server-domain", 21, OT_RFC1035_NAME },
473: { "sip-server", 22, OT_ADDR_LIST },
474: { "dns-server", 23, OT_ADDR_LIST },
475: { "domain-search", 24, OT_RFC1035_NAME },
476: { "nis-server", 27, OT_ADDR_LIST },
477: { "nis+-server", 28, OT_ADDR_LIST },
478: { "nis-domain", 29, OT_RFC1035_NAME },
479: { "nis+-domain", 30, OT_RFC1035_NAME },
480: { "sntp-server", 31, OT_ADDR_LIST },
481: { "information-refresh-time", 32, OT_TIME },
482: { "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
483: { "ntp-server", 56, OT_ADDR_LIST },
484: { "bootfile-url", 59, OT_NAME },
485: { "bootfile-param", 60, OT_CSTRING },
486: { NULL, 0, 0 }
487: };
488: #endif
489:
490:
491:
492: void display_opts(void)
493: {
494: int i;
495:
496: printf(_("Known DHCP options:\n"));
497:
498: for (i = 0; opttab[i].name; i++)
499: if (!(opttab[i].size & OT_INTERNAL))
500: printf("%3d %s\n", opttab[i].val, opttab[i].name);
501: }
502:
503: #ifdef HAVE_DHCP6
504: void display_opts6(void)
505: {
506: int i;
507: printf(_("Known DHCPv6 options:\n"));
508:
509: for (i = 0; opttab6[i].name; i++)
510: if (!(opttab6[i].size & OT_INTERNAL))
511: printf("%3d %s\n", opttab6[i].val, opttab6[i].name);
512: }
513: #endif
514:
515: u16 lookup_dhcp_opt(int prot, char *name)
516: {
517: const struct opttab_t *t;
518: int i;
519:
520: #ifdef HAVE_DHCP6
521: if (prot == AF_INET6)
522: t = opttab6;
523: else
524: #endif
525: t = opttab;
526:
527: for (i = 0; t[i].name; i++)
528: if (strcasecmp(t[i].name, name) == 0)
529: return t[i].val;
530:
531: return 0;
532: }
533:
534: u16 lookup_dhcp_len(int prot, u16 val)
535: {
536: const struct opttab_t *t;
537: int i;
538:
539: #ifdef HAVE_DHCP6
540: if (prot == AF_INET6)
541: t = opttab6;
542: else
543: #endif
544: t = opttab;
545:
546: for (i = 0; t[i].name; i++)
547: if (val == t[i].val)
548: return t[i].size & ~OT_DEC;
549:
550: return 0;
551: }
552:
553: char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len)
554: {
555: int o, i, j, nodecode = 0;
556: const struct opttab_t *ot = opttab;
557:
558: #ifdef HAVE_DHCP6
559: if (prot == AF_INET6)
560: ot = opttab6;
561: #endif
562:
563: for (o = 0; ot[o].name; o++)
564: if (ot[o].val == opt)
565: {
566: if (buf)
567: {
568: memset(buf, 0, buf_len);
569:
570: if (ot[o].size & OT_ADDR_LIST)
571: {
572: struct all_addr addr;
573: int addr_len = INADDRSZ;
574:
575: #ifdef HAVE_DHCP6
576: if (prot == AF_INET6)
577: addr_len = IN6ADDRSZ;
578: #endif
579: for (buf[0]= 0, i = 0; i <= opt_len - addr_len; i += addr_len)
580: {
581: if (i != 0)
582: strncat(buf, ", ", buf_len - strlen(buf));
583: /* align */
584: memcpy(&addr, &val[i], addr_len);
585: inet_ntop(prot, &val[i], daemon->addrbuff, ADDRSTRLEN);
586: strncat(buf, daemon->addrbuff, buf_len - strlen(buf));
587: }
588: }
589: else if (ot[o].size & OT_NAME)
590: for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
591: {
592: char c = val[i];
593: if (isprint((int)c))
594: buf[j++] = c;
595: }
596: #ifdef HAVE_DHCP6
597: /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
598: else if ((ot[o].size & OT_RFC1035_NAME) && prot == AF_INET6)
599: {
600: i = 0, j = 0;
601: while (i < opt_len && val[i] != 0)
602: {
603: int k, l = i + val[i] + 1;
604: for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
605: {
606: char c = val[k];
607: if (isprint((int)c))
608: buf[j++] = c;
609: }
610: i = l;
611: if (val[i] != 0 && j < buf_len)
612: buf[j++] = '.';
613: }
614: }
615: else if ((ot[o].size & OT_CSTRING))
616: {
617: int k, len;
618: unsigned char *p;
619:
620: i = 0, j = 0;
621: while (1)
622: {
623: p = &val[i];
624: GETSHORT(len, p);
625: for (k = 0; k < len && j < buf_len; k++)
626: {
627: char c = *p++;
628: if (isprint((int)c))
629: buf[j++] = c;
630: }
631: i += len +2;
632: if (i >= opt_len)
633: break;
634:
635: if (j < buf_len)
636: buf[j++] = ',';
637: }
638: }
639: #endif
640: else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
641: {
642: unsigned int dec = 0;
643:
644: for (i = 0; i < opt_len; i++)
645: dec = (dec << 8) | val[i];
646:
647: if (ot[o].size & OT_TIME)
648: prettyprint_time(buf, dec);
649: else
650: sprintf(buf, "%u", dec);
651: }
652: else
653: nodecode = 1;
654: }
655: break;
656: }
657:
658: if (opt_len != 0 && buf && (!ot[o].name || nodecode))
659: {
660: int trunc = 0;
661: if (opt_len > 14)
662: {
663: trunc = 1;
664: opt_len = 14;
665: }
666: print_mac(buf, val, opt_len);
667: if (trunc)
668: strncat(buf, "...", buf_len - strlen(buf));
669:
670:
671: }
672:
673: return ot[o].name ? ot[o].name : "";
674:
675: }
676:
677: void log_context(int family, struct dhcp_context *context)
678: {
679: /* Cannot use dhcp_buff* for RA contexts */
680:
681: void *start = &context->start;
682: void *end = &context->end;
683: char *template = "", *p = daemon->namebuff;
684:
685: *p = 0;
686:
687: #ifdef HAVE_DHCP6
688: if (family == AF_INET6)
689: {
690: struct in6_addr subnet = context->start6;
691: if (!(context->flags & CONTEXT_TEMPLATE))
692: setaddr6part(&subnet, 0);
693: inet_ntop(AF_INET6, &subnet, daemon->addrbuff, ADDRSTRLEN);
694: start = &context->start6;
695: end = &context->end6;
696: }
697: #endif
698:
699: if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
700: strcpy(daemon->namebuff, _(", prefix deprecated"));
701: else
702: {
703: p += sprintf(p, _(", lease time "));
704: prettyprint_time(p, context->lease_time);
705: p += strlen(p);
706: }
707:
708: #ifdef HAVE_DHCP6
709: if (context->flags & CONTEXT_CONSTRUCTED)
710: {
711: char ifrn_name[IFNAMSIZ];
712:
713: template = p;
714: p += sprintf(p, ", ");
715:
716: if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name))
717: sprintf(p, "constructed for %s", ifrn_name);
718: }
719: else if (context->flags & CONTEXT_TEMPLATE)
720: {
721: template = p;
722: p += sprintf(p, ", ");
723:
724: sprintf(p, "template for %s", context->template_interface);
725: }
726: #endif
727:
728: if ((context->flags & CONTEXT_DHCP) || family == AF_INET)
729: {
730: inet_ntop(family, start, daemon->dhcp_buff, 256);
731: inet_ntop(family, end, daemon->dhcp_buff3, 256);
732: my_syslog(MS_DHCP | LOG_INFO,
733: (context->flags & CONTEXT_RA_STATELESS) ?
734: _("%s stateless on %s%.0s%.0s%s") :
735: (context->flags & CONTEXT_STATIC) ?
736: _("%s, static leases only on %.0s%s%s%.0s") :
737: (context->flags & CONTEXT_PROXY) ?
738: _("%s, proxy on subnet %.0s%s%.0s%.0s") :
739: _("%s, IP range %s -- %s%s%.0s"),
740: (family != AF_INET) ? "DHCPv6" : "DHCP",
741: daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff, template);
742: }
743:
744: #ifdef HAVE_DHCP6
745: if (context->flags & CONTEXT_RA_NAME)
746: my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template);
747:
748: if ((context->flags & CONTEXT_RA) || (option_bool(OPT_RA) && (context->flags & CONTEXT_DHCP) && family == AF_INET6))
749: my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s"), daemon->addrbuff, template);
750: #endif
751:
752: }
753:
754:
755: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>