1 /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
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.
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.
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/>.
21 void dhcp_common_init(void)
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);
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,
32 expand_buf(&daemon
->dhcp_packet
, sizeof(struct dhcp_packet
));
35 expand_buf(&daemon
->outpacket
, sizeof(struct dhcp_packet
));
39 ssize_t
recv_dhcp_packet(int fd
, struct msghdr
*msg
)
46 while ((sz
= recvmsg(fd
, msg
, MSG_PEEK
| MSG_TRUNC
)) == -1 && errno
== EINTR
);
51 if (!(msg
->msg_flags
& MSG_TRUNC
))
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
)
58 if (!expand_buf(msg
->msg_iov
, sz
+ 100))
63 expand_buf(msg
->msg_iov
, sz
);
68 while ((sz
= recvmsg(fd
, msg
, 0)) == -1 && errno
== EINTR
);
70 return (msg
->msg_flags
& MSG_TRUNC
) ? -1 : sz
;
73 struct dhcp_netid
*run_tag_if(struct dhcp_netid
*tags
)
76 struct dhcp_netid_list
*list
;
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
)
82 list
->list
->next
= tags
;
90 struct dhcp_netid
*option_filter(struct dhcp_netid
*tags
, struct dhcp_netid
*context_tags
, struct dhcp_opt
*opts
)
92 struct dhcp_netid
*tagif
= run_tag_if(tags
);
96 /* flag options which are valid with the current tag set (sans context tags) */
97 for (opt
= opts
; opt
; opt
= opt
->next
)
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
;
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 */
109 struct dhcp_netid
*last_tag
;
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
);
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
;
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))
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
))
131 opt
->flags
|= DHOPT_TAGOK
;
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
)
139 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
140 if (tmp
->opt
== opt
->opt
&& (tmp
->flags
& DHOPT_TAGOK
))
143 opt
->flags
|= DHOPT_TAGOK
;
144 else if (!tmp
->netid
)
145 my_syslog(MS_DHCP
| LOG_WARNING
, _("Ignoring duplicate dhcp-option %d"), tmp
->opt
);
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
;
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
)
162 struct dhcp_netid
*tmp1
;
164 if (!check
&& !tagnotneeded
)
167 for (; check
; check
= check
->next
)
169 /* '#' for not is for backwards compat. */
170 if (check
->net
[0] != '!' && check
->net
[0] != '#')
172 for (tmp1
= pool
; tmp1
; tmp1
= tmp1
->next
)
173 if (strcmp(check
->net
, tmp1
->net
) == 0)
179 for (tmp1
= pool
; tmp1
; tmp1
= tmp1
->next
)
180 if (strcmp((check
->net
)+1, tmp1
->net
) == 0)
186 /* return domain or NULL if none. */
187 char *strip_hostname(char *hostname
)
189 char *dot
= strchr(hostname
, '.');
194 *dot
= 0; /* truncate */
195 if (strlen(dot
+1) != 0)
201 void log_tags(struct dhcp_netid
*netid
, u32 xid
)
203 if (netid
&& option_bool(OPT_LOG_OPTS
))
205 char *s
= daemon
->namebuff
;
206 for (*s
= 0; netid
; netid
= netid
->next
)
209 struct dhcp_netid
*n
;
211 for (n
= netid
->next
; n
; n
= n
->next
)
212 if (strcmp(netid
->net
, n
->net
) == 0)
217 strncat (s
, netid
->net
, (MAXDNAME
-1) - strlen(s
));
219 strncat (s
, ", ", (MAXDNAME
-1) - strlen(s
));
222 my_syslog(MS_DHCP
| LOG_INFO
, _("%u tags: %s"), xid
, s
);
226 int match_bytes(struct dhcp_opt
*o
, unsigned char *p
, int len
)
236 if (o
->flags
& DHOPT_HEX
)
238 if (memcmp_masked(o
->val
, p
, o
->len
, o
->u
.wildcard_mask
))
242 for (i
= 0; i
<= (len
- o
->len
); )
244 if (memcmp(o
->val
, p
+ i
, o
->len
) == 0)
247 if (o
->flags
& DHOPT_STRING
)
256 int config_has_mac(struct dhcp_config
*config
, unsigned char *hwaddr
, int len
, int type
)
258 struct hwaddr_config
*conf_addr
;
260 for (conf_addr
= config
->hwaddr
; conf_addr
; conf_addr
= conf_addr
->next
)
261 if (conf_addr
->wildcard_mask
== 0 &&
262 conf_addr
->hwaddr_len
== len
&&
263 (conf_addr
->hwaddr_type
== type
|| conf_addr
->hwaddr_type
== 0) &&
264 memcmp(conf_addr
->hwaddr
, hwaddr
, len
) == 0)
270 static int is_config_in_context(struct dhcp_context
*context
, struct dhcp_config
*config
)
272 if (!context
) /* called via find_config() from lease_update_from_configs() */
275 if (!(config
->flags
& (CONFIG_ADDR
| CONFIG_ADDR6
)))
279 if ((context
->flags
& CONTEXT_V6
) && (config
->flags
& CONFIG_WILDCARD
))
283 for (; context
; context
= context
->current
)
285 if (context
->flags
& CONTEXT_V6
)
287 if ((config
->flags
& CONFIG_ADDR6
) && is_same_net6(&config
->addr6
, &context
->start6
, context
->prefix
))
292 if ((config
->flags
& CONFIG_ADDR
) && is_same_net(config
->addr
, context
->start
, context
->netmask
))
298 struct dhcp_config
*find_config(struct dhcp_config
*configs
,
299 struct dhcp_context
*context
,
300 unsigned char *clid
, int clid_len
,
301 unsigned char *hwaddr
, int hw_len
,
302 int hw_type
, char *hostname
)
305 struct dhcp_config
*config
, *candidate
;
306 struct hwaddr_config
*conf_addr
;
309 for (config
= configs
; config
; config
= config
->next
)
310 if (config
->flags
& CONFIG_CLID
)
312 if (config
->clid_len
== clid_len
&&
313 memcmp(config
->clid
, clid
, clid_len
) == 0 &&
314 is_config_in_context(context
, config
))
317 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
318 cope with that here. This is IPv4 only. context==NULL implies IPv4,
319 see lease_update_from_configs() */
320 if ((!context
|| !(context
->flags
& CONTEXT_V6
)) && *clid
== 0 && config
->clid_len
== clid_len
-1 &&
321 memcmp(config
->clid
, clid
+1, clid_len
-1) == 0 &&
322 is_config_in_context(context
, config
))
328 for (config
= configs
; config
; config
= config
->next
)
329 if (config_has_mac(config
, hwaddr
, hw_len
, hw_type
) &&
330 is_config_in_context(context
, config
))
333 if (hostname
&& context
)
334 for (config
= configs
; config
; config
= config
->next
)
335 if ((config
->flags
& CONFIG_NAME
) &&
336 hostname_isequal(config
->hostname
, hostname
) &&
337 is_config_in_context(context
, config
))
344 /* use match with fewest wildcard octets */
345 for (candidate
= NULL
, count
= 0, config
= configs
; config
; config
= config
->next
)
346 if (is_config_in_context(context
, config
))
347 for (conf_addr
= config
->hwaddr
; conf_addr
; conf_addr
= conf_addr
->next
)
348 if (conf_addr
->wildcard_mask
!= 0 &&
349 conf_addr
->hwaddr_len
== hw_len
&&
350 (conf_addr
->hwaddr_type
== hw_type
|| conf_addr
->hwaddr_type
== 0) &&
351 (new = memcmp_masked(conf_addr
->hwaddr
, hwaddr
, hw_len
, conf_addr
->wildcard_mask
)) > count
)
360 void dhcp_update_configs(struct dhcp_config
*configs
)
362 /* Some people like to keep all static IP addresses in /etc/hosts.
363 This goes through /etc/hosts and sets static addresses for any DHCP config
364 records which don't have an address and whose name matches.
365 We take care to maintain the invariant that any IP address can appear
366 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
367 restore the status-quo ante first. */
369 struct dhcp_config
*config
, *conf_tmp
;
373 for (config
= configs
; config
; config
= config
->next
)
374 if (config
->flags
& CONFIG_ADDR_HOSTS
)
375 config
->flags
&= ~(CONFIG_ADDR
| CONFIG_ADDR6
| CONFIG_ADDR_HOSTS
);
381 if (daemon
->port
!= 0)
382 for (config
= configs
; config
; config
= config
->next
)
384 int conflags
= CONFIG_ADDR
;
385 int cacheflags
= F_IPV4
;
388 if (prot
== AF_INET6
)
390 conflags
= CONFIG_ADDR6
;
394 if (!(config
->flags
& conflags
) &&
395 (config
->flags
& CONFIG_NAME
) &&
396 (crec
= cache_find_by_name(NULL
, config
->hostname
, 0, cacheflags
)) &&
397 (crec
->flags
& F_HOSTS
))
399 if (cache_find_by_name(crec
, config
->hostname
, 0, cacheflags
))
401 /* use primary (first) address */
402 while (crec
&& !(crec
->flags
& F_REVERSE
))
403 crec
= cache_find_by_name(crec
, config
->hostname
, 0, cacheflags
);
405 continue; /* should be never */
406 inet_ntop(prot
, &crec
->addr
.addr
, daemon
->addrbuff
, ADDRSTRLEN
);
407 my_syslog(MS_DHCP
| LOG_WARNING
, _("%s has more than one address in hostsfile, using %s for DHCP"),
408 config
->hostname
, daemon
->addrbuff
);
411 if (prot
== AF_INET
&&
412 (!(conf_tmp
= config_find_by_address(configs
, crec
->addr
.addr
.addr
.addr4
)) || conf_tmp
== config
))
414 config
->addr
= crec
->addr
.addr
.addr
.addr4
;
415 config
->flags
|= CONFIG_ADDR
| CONFIG_ADDR_HOSTS
;
420 if (prot
== AF_INET6
&&
421 (!(conf_tmp
= config_find_by_address6(configs
, &crec
->addr
.addr
.addr
.addr6
, 128, 0)) || conf_tmp
== config
))
423 memcpy(&config
->addr6
, &crec
->addr
.addr
.addr
.addr6
, IN6ADDRSZ
);
424 config
->flags
|= CONFIG_ADDR6
| CONFIG_ADDR_HOSTS
;
429 inet_ntop(prot
, &crec
->addr
.addr
, daemon
->addrbuff
, ADDRSTRLEN
);
430 my_syslog(MS_DHCP
| LOG_WARNING
, _("duplicate IP address %s (%s) in dhcp-config directive"),
431 daemon
->addrbuff
, config
->hostname
);
447 #ifdef HAVE_LINUX_NETWORK
448 char *whichdevice(void)
450 /* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
451 to that device. This is for the use case of (eg) OpenStack, which runs a new
452 dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
453 individual processes don't always see the packets they should.
454 SO_BINDTODEVICE is only available Linux.
456 Note that if wildcards are used in --interface, or --interface is not used at all,
457 or a configured interface doesn't yet exist, then more interfaces may arrive later,
458 so we can't safely assert there is only one interface and proceed.
461 struct irec
*iface
, *found
;
462 struct iname
*if_tmp
;
464 if (!daemon
->if_names
)
467 for (if_tmp
= daemon
->if_names
; if_tmp
; if_tmp
= if_tmp
->next
)
468 if (if_tmp
->name
&& (!if_tmp
->used
|| strchr(if_tmp
->name
, '*')))
471 for (found
= NULL
, iface
= daemon
->interfaces
; iface
; iface
= iface
->next
)
476 else if (strcmp(found
->name
, iface
->name
) != 0)
477 return NULL
; /* more than one. */
486 void bindtodevice(char *device
, int fd
)
490 strcpy(ifr
.ifr_name
, device
);
491 /* only allowed by root. */
492 if (setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, (void *)&ifr
, sizeof(ifr
)) == -1 &&
494 die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL
, EC_BADNET
);
498 static const struct opttab_t
{
502 { "netmask", 1, OT_ADDR_LIST
},
503 { "time-offset", 2, 4 },
504 { "router", 3, OT_ADDR_LIST
},
505 { "dns-server", 6, OT_ADDR_LIST
},
506 { "log-server", 7, OT_ADDR_LIST
},
507 { "lpr-server", 9, OT_ADDR_LIST
},
508 { "hostname", 12, OT_INTERNAL
| OT_NAME
},
509 { "boot-file-size", 13, 2 | OT_DEC
},
510 { "domain-name", 15, OT_NAME
},
511 { "swap-server", 16, OT_ADDR_LIST
},
512 { "root-path", 17, OT_NAME
},
513 { "extension-path", 18, OT_NAME
},
514 { "ip-forward-enable", 19, 1 },
515 { "non-local-source-routing", 20, 1 },
516 { "policy-filter", 21, OT_ADDR_LIST
},
517 { "max-datagram-reassembly", 22, 2 | OT_DEC
},
518 { "default-ttl", 23, 1 | OT_DEC
},
519 { "mtu", 26, 2 | OT_DEC
},
520 { "all-subnets-local", 27, 1 },
521 { "broadcast", 28, OT_INTERNAL
| OT_ADDR_LIST
},
522 { "router-discovery", 31, 1 },
523 { "router-solicitation", 32, OT_ADDR_LIST
},
524 { "static-route", 33, OT_ADDR_LIST
},
525 { "trailer-encapsulation", 34, 1 },
526 { "arp-timeout", 35, 4 | OT_DEC
},
527 { "ethernet-encap", 36, 1 },
528 { "tcp-ttl", 37, 1 },
529 { "tcp-keepalive", 38, 4 | OT_DEC
},
530 { "nis-domain", 40, OT_NAME
},
531 { "nis-server", 41, OT_ADDR_LIST
},
532 { "ntp-server", 42, OT_ADDR_LIST
},
533 { "vendor-encap", 43, OT_INTERNAL
},
534 { "netbios-ns", 44, OT_ADDR_LIST
},
535 { "netbios-dd", 45, OT_ADDR_LIST
},
536 { "netbios-nodetype", 46, 1 },
537 { "netbios-scope", 47, 0 },
538 { "x-windows-fs", 48, OT_ADDR_LIST
},
539 { "x-windows-dm", 49, OT_ADDR_LIST
},
540 { "requested-address", 50, OT_INTERNAL
| OT_ADDR_LIST
},
541 { "lease-time", 51, OT_INTERNAL
| OT_TIME
},
542 { "option-overload", 52, OT_INTERNAL
},
543 { "message-type", 53, OT_INTERNAL
| OT_DEC
},
544 { "server-identifier", 54, OT_INTERNAL
| OT_ADDR_LIST
},
545 { "parameter-request", 55, OT_INTERNAL
},
546 { "message", 56, OT_INTERNAL
},
547 { "max-message-size", 57, OT_INTERNAL
},
548 { "T1", 58, OT_TIME
},
549 { "T2", 59, OT_TIME
},
550 { "vendor-class", 60, 0 },
551 { "client-id", 61, OT_INTERNAL
},
552 { "nis+-domain", 64, OT_NAME
},
553 { "nis+-server", 65, OT_ADDR_LIST
},
554 { "tftp-server", 66, OT_NAME
},
555 { "bootfile-name", 67, OT_NAME
},
556 { "mobile-ip-home", 68, OT_ADDR_LIST
},
557 { "smtp-server", 69, OT_ADDR_LIST
},
558 { "pop3-server", 70, OT_ADDR_LIST
},
559 { "nntp-server", 71, OT_ADDR_LIST
},
560 { "irc-server", 74, OT_ADDR_LIST
},
561 { "user-class", 77, 0 },
562 { "FQDN", 81, OT_INTERNAL
},
563 { "agent-id", 82, OT_INTERNAL
},
564 { "client-arch", 93, 2 | OT_DEC
},
565 { "client-interface-id", 94, 0 },
566 { "client-machine-id", 97, 0 },
567 { "subnet-select", 118, OT_INTERNAL
},
568 { "domain-search", 119, OT_RFC1035_NAME
},
569 { "sip-server", 120, 0 },
570 { "classless-static-route", 121, 0 },
571 { "vendor-id-encap", 125, 0 },
572 { "server-ip-address", 255, OT_ADDR_LIST
}, /* special, internal only, sets siaddr */
577 static const struct opttab_t opttab6
[] = {
578 { "client-id", 1, OT_INTERNAL
},
579 { "server-id", 2, OT_INTERNAL
},
580 { "ia-na", 3, OT_INTERNAL
},
581 { "ia-ta", 4, OT_INTERNAL
},
582 { "iaaddr", 5, OT_INTERNAL
},
583 { "oro", 6, OT_INTERNAL
},
584 { "preference", 7, OT_INTERNAL
| OT_DEC
},
585 { "unicast", 12, OT_INTERNAL
},
586 { "status", 13, OT_INTERNAL
},
587 { "rapid-commit", 14, OT_INTERNAL
},
588 { "user-class", 15, OT_INTERNAL
| OT_CSTRING
},
589 { "vendor-class", 16, OT_INTERNAL
| OT_CSTRING
},
590 { "vendor-opts", 17, OT_INTERNAL
},
591 { "sip-server-domain", 21, OT_RFC1035_NAME
},
592 { "sip-server", 22, OT_ADDR_LIST
},
593 { "dns-server", 23, OT_ADDR_LIST
},
594 { "domain-search", 24, OT_RFC1035_NAME
},
595 { "nis-server", 27, OT_ADDR_LIST
},
596 { "nis+-server", 28, OT_ADDR_LIST
},
597 { "nis-domain", 29, OT_RFC1035_NAME
},
598 { "nis+-domain", 30, OT_RFC1035_NAME
},
599 { "sntp-server", 31, OT_ADDR_LIST
},
600 { "information-refresh-time", 32, OT_TIME
},
601 { "FQDN", 39, OT_INTERNAL
| OT_RFC1035_NAME
},
602 { "ntp-server", 56, 0 },
603 { "bootfile-url", 59, OT_NAME
},
604 { "bootfile-param", 60, OT_CSTRING
},
611 void display_opts(void)
615 printf(_("Known DHCP options:\n"));
617 for (i
= 0; opttab
[i
].name
; i
++)
618 if (!(opttab
[i
].size
& OT_INTERNAL
))
619 printf("%3d %s\n", opttab
[i
].val
, opttab
[i
].name
);
623 void display_opts6(void)
626 printf(_("Known DHCPv6 options:\n"));
628 for (i
= 0; opttab6
[i
].name
; i
++)
629 if (!(opttab6
[i
].size
& OT_INTERNAL
))
630 printf("%3d %s\n", opttab6
[i
].val
, opttab6
[i
].name
);
634 int lookup_dhcp_opt(int prot
, char *name
)
636 const struct opttab_t
*t
;
642 if (prot
== AF_INET6
)
648 for (i
= 0; t
[i
].name
; i
++)
649 if (strcasecmp(t
[i
].name
, name
) == 0)
655 int lookup_dhcp_len(int prot
, int val
)
657 const struct opttab_t
*t
;
663 if (prot
== AF_INET6
)
669 for (i
= 0; t
[i
].name
; i
++)
671 return t
[i
].size
& ~OT_DEC
;
676 char *option_string(int prot
, unsigned int opt
, unsigned char *val
, int opt_len
, char *buf
, int buf_len
)
678 int o
, i
, j
, nodecode
= 0;
679 const struct opttab_t
*ot
= opttab
;
682 if (prot
== AF_INET6
)
686 for (o
= 0; ot
[o
].name
; o
++)
687 if (ot
[o
].val
== opt
)
691 memset(buf
, 0, buf_len
);
693 if (ot
[o
].size
& OT_ADDR_LIST
)
695 struct all_addr addr
;
696 int addr_len
= INADDRSZ
;
699 if (prot
== AF_INET6
)
700 addr_len
= IN6ADDRSZ
;
702 for (buf
[0]= 0, i
= 0; i
<= opt_len
- addr_len
; i
+= addr_len
)
705 strncat(buf
, ", ", buf_len
- strlen(buf
));
707 memcpy(&addr
, &val
[i
], addr_len
);
708 inet_ntop(prot
, &val
[i
], daemon
->addrbuff
, ADDRSTRLEN
);
709 strncat(buf
, daemon
->addrbuff
, buf_len
- strlen(buf
));
712 else if (ot
[o
].size
& OT_NAME
)
713 for (i
= 0, j
= 0; i
< opt_len
&& j
< buf_len
; i
++)
720 /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
721 else if ((ot
[o
].size
& OT_RFC1035_NAME
) && prot
== AF_INET6
)
724 while (i
< opt_len
&& val
[i
] != 0)
726 int k
, l
= i
+ val
[i
] + 1;
727 for (k
= i
+ 1; k
< opt_len
&& k
< l
&& j
< buf_len
; k
++)
734 if (val
[i
] != 0 && j
< buf_len
)
738 else if ((ot
[o
].size
& OT_CSTRING
))
748 for (k
= 0; k
< len
&& j
< buf_len
; k
++)
763 else if ((ot
[o
].size
& (OT_DEC
| OT_TIME
)) && opt_len
!= 0)
765 unsigned int dec
= 0;
767 for (i
= 0; i
< opt_len
; i
++)
768 dec
= (dec
<< 8) | val
[i
];
770 if (ot
[o
].size
& OT_TIME
)
771 prettyprint_time(buf
, dec
);
773 sprintf(buf
, "%u", dec
);
781 if (opt_len
!= 0 && buf
&& (!ot
[o
].name
|| nodecode
))
789 print_mac(buf
, val
, opt_len
);
791 strncat(buf
, "...", buf_len
- strlen(buf
));
796 return ot
[o
].name
? ot
[o
].name
: "";
800 void log_context(int family
, struct dhcp_context
*context
)
802 /* Cannot use dhcp_buff* for RA contexts */
804 void *start
= &context
->start
;
805 void *end
= &context
->end
;
806 char *template = "", *p
= daemon
->namebuff
;
811 if (family
== AF_INET6
)
813 struct in6_addr subnet
= context
->start6
;
814 if (!(context
->flags
& CONTEXT_TEMPLATE
))
815 setaddr6part(&subnet
, 0);
816 inet_ntop(AF_INET6
, &subnet
, daemon
->addrbuff
, ADDRSTRLEN
);
817 start
= &context
->start6
;
818 end
= &context
->end6
;
822 if (family
!= AF_INET
&& (context
->flags
& CONTEXT_DEPRECATE
))
823 strcpy(daemon
->namebuff
, _(", prefix deprecated"));
826 p
+= sprintf(p
, _(", lease time "));
827 prettyprint_time(p
, context
->lease_time
);
832 if (context
->flags
& CONTEXT_CONSTRUCTED
)
834 char ifrn_name
[IFNAMSIZ
];
837 p
+= sprintf(p
, ", ");
839 if (indextoname(daemon
->icmp6fd
, context
->if_index
, ifrn_name
))
840 sprintf(p
, "%s for %s", (context
->flags
& CONTEXT_OLD
) ? "old prefix" : "constructed", ifrn_name
);
842 else if (context
->flags
& CONTEXT_TEMPLATE
&& !(context
->flags
& CONTEXT_RA_STATELESS
))
845 p
+= sprintf(p
, ", ");
847 sprintf(p
, "template for %s", context
->template_interface
);
851 if (!(context
->flags
& CONTEXT_OLD
) &&
852 ((context
->flags
& CONTEXT_DHCP
) || family
== AF_INET
))
855 if (context
->flags
& CONTEXT_RA_STATELESS
)
857 if (context
->flags
& CONTEXT_TEMPLATE
)
858 strncpy(daemon
->dhcp_buff
, context
->template_interface
, 256);
860 strcpy(daemon
->dhcp_buff
, daemon
->addrbuff
);
864 inet_ntop(family
, start
, daemon
->dhcp_buff
, 256);
865 inet_ntop(family
, end
, daemon
->dhcp_buff3
, 256);
866 my_syslog(MS_DHCP
| LOG_INFO
,
867 (context
->flags
& CONTEXT_RA_STATELESS
) ?
868 _("%s stateless on %s%.0s%.0s%s") :
869 (context
->flags
& CONTEXT_STATIC
) ?
870 _("%s, static leases only on %.0s%s%s%.0s") :
871 (context
->flags
& CONTEXT_PROXY
) ?
872 _("%s, proxy on subnet %.0s%s%.0s%.0s") :
873 _("%s, IP range %s -- %s%s%.0s"),
874 (family
!= AF_INET
) ? "DHCPv6" : "DHCP",
875 daemon
->dhcp_buff
, daemon
->dhcp_buff3
, daemon
->namebuff
, template);
879 if (context
->flags
& CONTEXT_TEMPLATE
)
881 strcpy(daemon
->addrbuff
, context
->template_interface
);
885 if ((context
->flags
& CONTEXT_RA_NAME
) && !(context
->flags
& CONTEXT_OLD
))
886 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCPv4-derived IPv6 names on %s%s"), daemon
->addrbuff
, template);
888 if ((context
->flags
& CONTEXT_RA
) || (option_bool(OPT_RA
) && (context
->flags
& CONTEXT_DHCP
) && family
== AF_INET6
))
889 my_syslog(MS_DHCP
| LOG_INFO
, _("router advertisement on %s%s"), daemon
->addrbuff
, template);
894 void log_relay(int family
, struct dhcp_relay
*relay
)
896 inet_ntop(family
, &relay
->local
, daemon
->addrbuff
, ADDRSTRLEN
);
897 inet_ntop(family
, &relay
->server
, daemon
->namebuff
, ADDRSTRLEN
);
899 if (relay
->interface
)
900 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCP relay from %s to %s via %s"), daemon
->addrbuff
, daemon
->namebuff
, relay
->interface
);
902 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCP relay from %s to %s"), daemon
->addrbuff
, daemon
->namebuff
);