1 /* dnsmasq is Copyright (c) 2000-2013 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 (!(context
->flags
& CONTEXT_V6
))
277 if (!(config
->flags
& CONFIG_ADDR
))
280 for (; context
; context
= context
->current
)
281 if (is_same_net(config
->addr
, context
->start
, context
->netmask
))
287 if (!(config
->flags
& CONFIG_ADDR6
) || (config
->flags
& CONFIG_WILDCARD
))
290 for (; context
; context
= context
->current
)
291 if (is_same_net6(&config
->addr6
, &context
->start6
, context
->prefix
))
299 struct dhcp_config
*find_config(struct dhcp_config
*configs
,
300 struct dhcp_context
*context
,
301 unsigned char *clid
, int clid_len
,
302 unsigned char *hwaddr
, int hw_len
,
303 int hw_type
, char *hostname
)
306 struct dhcp_config
*config
, *candidate
;
307 struct hwaddr_config
*conf_addr
;
310 for (config
= configs
; config
; config
= config
->next
)
311 if (config
->flags
& CONFIG_CLID
)
313 if (config
->clid_len
== clid_len
&&
314 memcmp(config
->clid
, clid
, clid_len
) == 0 &&
315 is_config_in_context(context
, config
))
318 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
319 cope with that here */
320 if (!(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 void bindtodevice(int fd
)
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 a configured interface doesn't
457 yet exist, then more interfaces may arrive later, so we can't safely assert there
458 is only one interface and proceed.
461 struct irec
*iface
, *found
;
462 struct iname
*if_tmp
;
464 for (if_tmp
= daemon
->if_names
; if_tmp
; if_tmp
= if_tmp
->next
)
465 if (if_tmp
->name
&& (!if_tmp
->used
|| strchr(if_tmp
->name
, '*')))
468 for (found
= NULL
, iface
= daemon
->interfaces
; iface
; iface
= iface
->next
)
473 else if (strcmp(found
->name
, iface
->name
) != 0)
474 return; /* more than one. */
480 strcpy(ifr
.ifr_name
, found
->name
);
481 /* only allowed by root. */
482 if (setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, (void *)&ifr
, sizeof(ifr
)) == -1 &&
484 die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL
, EC_BADNET
);
489 static const struct opttab_t
{
493 { "netmask", 1, OT_ADDR_LIST
},
494 { "time-offset", 2, 4 },
495 { "router", 3, OT_ADDR_LIST
},
496 { "dns-server", 6, OT_ADDR_LIST
},
497 { "log-server", 7, OT_ADDR_LIST
},
498 { "lpr-server", 9, OT_ADDR_LIST
},
499 { "hostname", 12, OT_INTERNAL
| OT_NAME
},
500 { "boot-file-size", 13, 2 | OT_DEC
},
501 { "domain-name", 15, OT_NAME
},
502 { "swap-server", 16, OT_ADDR_LIST
},
503 { "root-path", 17, OT_NAME
},
504 { "extension-path", 18, OT_NAME
},
505 { "ip-forward-enable", 19, 1 },
506 { "non-local-source-routing", 20, 1 },
507 { "policy-filter", 21, OT_ADDR_LIST
},
508 { "max-datagram-reassembly", 22, 2 | OT_DEC
},
509 { "default-ttl", 23, 1 | OT_DEC
},
510 { "mtu", 26, 2 | OT_DEC
},
511 { "all-subnets-local", 27, 1 },
512 { "broadcast", 28, OT_INTERNAL
| OT_ADDR_LIST
},
513 { "router-discovery", 31, 1 },
514 { "router-solicitation", 32, OT_ADDR_LIST
},
515 { "static-route", 33, OT_ADDR_LIST
},
516 { "trailer-encapsulation", 34, 1 },
517 { "arp-timeout", 35, 4 | OT_DEC
},
518 { "ethernet-encap", 36, 1 },
519 { "tcp-ttl", 37, 1 },
520 { "tcp-keepalive", 38, 4 | OT_DEC
},
521 { "nis-domain", 40, OT_NAME
},
522 { "nis-server", 41, OT_ADDR_LIST
},
523 { "ntp-server", 42, OT_ADDR_LIST
},
524 { "vendor-encap", 43, OT_INTERNAL
},
525 { "netbios-ns", 44, OT_ADDR_LIST
},
526 { "netbios-dd", 45, OT_ADDR_LIST
},
527 { "netbios-nodetype", 46, 1 },
528 { "netbios-scope", 47, 0 },
529 { "x-windows-fs", 48, OT_ADDR_LIST
},
530 { "x-windows-dm", 49, OT_ADDR_LIST
},
531 { "requested-address", 50, OT_INTERNAL
| OT_ADDR_LIST
},
532 { "lease-time", 51, OT_INTERNAL
| OT_TIME
},
533 { "option-overload", 52, OT_INTERNAL
},
534 { "message-type", 53, OT_INTERNAL
| OT_DEC
},
535 { "server-identifier", 54, OT_INTERNAL
| OT_ADDR_LIST
},
536 { "parameter-request", 55, OT_INTERNAL
},
537 { "message", 56, OT_INTERNAL
},
538 { "max-message-size", 57, OT_INTERNAL
},
539 { "T1", 58, OT_INTERNAL
| OT_TIME
},
540 { "T2", 59, OT_INTERNAL
| OT_TIME
},
541 { "vendor-class", 60, 0 },
542 { "client-id", 61, OT_INTERNAL
},
543 { "nis+-domain", 64, OT_NAME
},
544 { "nis+-server", 65, OT_ADDR_LIST
},
545 { "tftp-server", 66, OT_NAME
},
546 { "bootfile-name", 67, OT_NAME
},
547 { "mobile-ip-home", 68, OT_ADDR_LIST
},
548 { "smtp-server", 69, OT_ADDR_LIST
},
549 { "pop3-server", 70, OT_ADDR_LIST
},
550 { "nntp-server", 71, OT_ADDR_LIST
},
551 { "irc-server", 74, OT_ADDR_LIST
},
552 { "user-class", 77, 0 },
553 { "FQDN", 81, OT_INTERNAL
},
554 { "agent-id", 82, OT_INTERNAL
},
555 { "client-arch", 93, 2 | OT_DEC
},
556 { "client-interface-id", 94, 0 },
557 { "client-machine-id", 97, 0 },
558 { "subnet-select", 118, OT_INTERNAL
},
559 { "domain-search", 119, OT_RFC1035_NAME
},
560 { "sip-server", 120, 0 },
561 { "classless-static-route", 121, 0 },
562 { "vendor-id-encap", 125, 0 },
563 { "server-ip-address", 255, OT_ADDR_LIST
}, /* special, internal only, sets siaddr */
568 static const struct opttab_t opttab6
[] = {
569 { "client-id", 1, OT_INTERNAL
},
570 { "server-id", 2, OT_INTERNAL
},
571 { "ia-na", 3, OT_INTERNAL
},
572 { "ia-ta", 4, OT_INTERNAL
},
573 { "iaaddr", 5, OT_INTERNAL
},
574 { "oro", 6, OT_INTERNAL
},
575 { "preference", 7, OT_INTERNAL
| OT_DEC
},
576 { "unicast", 12, OT_INTERNAL
},
577 { "status", 13, OT_INTERNAL
},
578 { "rapid-commit", 14, OT_INTERNAL
},
579 { "user-class", 15, OT_INTERNAL
| OT_CSTRING
},
580 { "vendor-class", 16, OT_INTERNAL
| OT_CSTRING
},
581 { "vendor-opts", 17, OT_INTERNAL
},
582 { "sip-server-domain", 21, OT_RFC1035_NAME
},
583 { "sip-server", 22, OT_ADDR_LIST
},
584 { "dns-server", 23, OT_ADDR_LIST
},
585 { "domain-search", 24, OT_RFC1035_NAME
},
586 { "nis-server", 27, OT_ADDR_LIST
},
587 { "nis+-server", 28, OT_ADDR_LIST
},
588 { "nis-domain", 29, OT_RFC1035_NAME
},
589 { "nis+-domain", 30, OT_RFC1035_NAME
},
590 { "sntp-server", 31, OT_ADDR_LIST
},
591 { "information-refresh-time", 32, OT_TIME
},
592 { "FQDN", 39, OT_INTERNAL
| OT_RFC1035_NAME
},
593 { "ntp-server", 56, OT_ADDR_LIST
},
594 { "bootfile-url", 59, OT_NAME
},
595 { "bootfile-param", 60, OT_CSTRING
},
602 void display_opts(void)
606 printf(_("Known DHCP options:\n"));
608 for (i
= 0; opttab
[i
].name
; i
++)
609 if (!(opttab
[i
].size
& OT_INTERNAL
))
610 printf("%3d %s\n", opttab
[i
].val
, opttab
[i
].name
);
614 void display_opts6(void)
617 printf(_("Known DHCPv6 options:\n"));
619 for (i
= 0; opttab6
[i
].name
; i
++)
620 if (!(opttab6
[i
].size
& OT_INTERNAL
))
621 printf("%3d %s\n", opttab6
[i
].val
, opttab6
[i
].name
);
625 int lookup_dhcp_opt(int prot
, char *name
)
627 const struct opttab_t
*t
;
633 if (prot
== AF_INET6
)
639 for (i
= 0; t
[i
].name
; i
++)
640 if (strcasecmp(t
[i
].name
, name
) == 0)
646 int lookup_dhcp_len(int prot
, int val
)
648 const struct opttab_t
*t
;
654 if (prot
== AF_INET6
)
660 for (i
= 0; t
[i
].name
; i
++)
662 return t
[i
].size
& ~OT_DEC
;
667 char *option_string(int prot
, unsigned int opt
, unsigned char *val
, int opt_len
, char *buf
, int buf_len
)
669 int o
, i
, j
, nodecode
= 0;
670 const struct opttab_t
*ot
= opttab
;
673 if (prot
== AF_INET6
)
677 for (o
= 0; ot
[o
].name
; o
++)
678 if (ot
[o
].val
== opt
)
682 memset(buf
, 0, buf_len
);
684 if (ot
[o
].size
& OT_ADDR_LIST
)
686 struct all_addr addr
;
687 int addr_len
= INADDRSZ
;
690 if (prot
== AF_INET6
)
691 addr_len
= IN6ADDRSZ
;
693 for (buf
[0]= 0, i
= 0; i
<= opt_len
- addr_len
; i
+= addr_len
)
696 strncat(buf
, ", ", buf_len
- strlen(buf
));
698 memcpy(&addr
, &val
[i
], addr_len
);
699 inet_ntop(prot
, &val
[i
], daemon
->addrbuff
, ADDRSTRLEN
);
700 strncat(buf
, daemon
->addrbuff
, buf_len
- strlen(buf
));
703 else if (ot
[o
].size
& OT_NAME
)
704 for (i
= 0, j
= 0; i
< opt_len
&& j
< buf_len
; i
++)
711 /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
712 else if ((ot
[o
].size
& OT_RFC1035_NAME
) && prot
== AF_INET6
)
715 while (i
< opt_len
&& val
[i
] != 0)
717 int k
, l
= i
+ val
[i
] + 1;
718 for (k
= i
+ 1; k
< opt_len
&& k
< l
&& j
< buf_len
; k
++)
725 if (val
[i
] != 0 && j
< buf_len
)
729 else if ((ot
[o
].size
& OT_CSTRING
))
739 for (k
= 0; k
< len
&& j
< buf_len
; k
++)
754 else if ((ot
[o
].size
& (OT_DEC
| OT_TIME
)) && opt_len
!= 0)
756 unsigned int dec
= 0;
758 for (i
= 0; i
< opt_len
; i
++)
759 dec
= (dec
<< 8) | val
[i
];
761 if (ot
[o
].size
& OT_TIME
)
762 prettyprint_time(buf
, dec
);
764 sprintf(buf
, "%u", dec
);
772 if (opt_len
!= 0 && buf
&& (!ot
[o
].name
|| nodecode
))
780 print_mac(buf
, val
, opt_len
);
782 strncat(buf
, "...", buf_len
- strlen(buf
));
787 return ot
[o
].name
? ot
[o
].name
: "";
791 void log_context(int family
, struct dhcp_context
*context
)
793 /* Cannot use dhcp_buff* for RA contexts */
795 void *start
= &context
->start
;
796 void *end
= &context
->end
;
797 char *template = "", *p
= daemon
->namebuff
;
802 if (family
== AF_INET6
)
804 struct in6_addr subnet
= context
->start6
;
805 if (!(context
->flags
& CONTEXT_TEMPLATE
))
806 setaddr6part(&subnet
, 0);
807 inet_ntop(AF_INET6
, &subnet
, daemon
->addrbuff
, ADDRSTRLEN
);
808 start
= &context
->start6
;
809 end
= &context
->end6
;
813 if (family
!= AF_INET
&& (context
->flags
& CONTEXT_DEPRECATE
))
814 strcpy(daemon
->namebuff
, _(", prefix deprecated"));
817 p
+= sprintf(p
, _(", lease time "));
818 prettyprint_time(p
, context
->lease_time
);
823 if (context
->flags
& CONTEXT_CONSTRUCTED
)
825 char ifrn_name
[IFNAMSIZ
];
828 p
+= sprintf(p
, ", ");
830 if (indextoname(daemon
->icmp6fd
, context
->if_index
, ifrn_name
))
831 sprintf(p
, "%s for %s", (context
->flags
& CONTEXT_OLD
) ? "old prefix" : "constructed", ifrn_name
);
833 else if (context
->flags
& CONTEXT_TEMPLATE
)
836 p
+= sprintf(p
, ", ");
838 sprintf(p
, "template for %s", context
->template_interface
);
842 if (!(context
->flags
& CONTEXT_OLD
) &&
843 ((context
->flags
& CONTEXT_DHCP
) || family
== AF_INET
))
845 inet_ntop(family
, start
, daemon
->dhcp_buff
, 256);
846 inet_ntop(family
, end
, daemon
->dhcp_buff3
, 256);
847 my_syslog(MS_DHCP
| LOG_INFO
,
848 (context
->flags
& CONTEXT_RA_STATELESS
) ?
849 _("%s stateless on %s%.0s%.0s%s") :
850 (context
->flags
& CONTEXT_STATIC
) ?
851 _("%s, static leases only on %.0s%s%s%.0s") :
852 (context
->flags
& CONTEXT_PROXY
) ?
853 _("%s, proxy on subnet %.0s%s%.0s%.0s") :
854 _("%s, IP range %s -- %s%s%.0s"),
855 (family
!= AF_INET
) ? "DHCPv6" : "DHCP",
856 daemon
->dhcp_buff
, daemon
->dhcp_buff3
, daemon
->namebuff
, template);
860 if ((context
->flags
& CONTEXT_RA_NAME
) && !(context
->flags
& CONTEXT_OLD
))
861 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCPv4-derived IPv6 names on %s%s"), daemon
->addrbuff
, template);
863 if ((context
->flags
& CONTEXT_RA
) || (option_bool(OPT_RA
) && (context
->flags
& CONTEXT_DHCP
) && family
== AF_INET6
))
864 my_syslog(MS_DHCP
| LOG_INFO
, _("router advertisement on %s%s"), daemon
->addrbuff
, template);
869 void log_relay(int family
, struct dhcp_relay
*relay
)
871 inet_ntop(family
, &relay
->local
, daemon
->addrbuff
, ADDRSTRLEN
);
872 inet_ntop(family
, &relay
->server
, daemon
->namebuff
, ADDRSTRLEN
);
874 if (relay
->interface
)
875 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCP relay from %s to %s via %s"), daemon
->addrbuff
, daemon
->namebuff
, relay
->interface
);
877 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCP relay from %s to %s"), daemon
->addrbuff
, daemon
->namebuff
);