Annotation of embedaddon/dnsmasq/src/dhcp-common.c, revision 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>