]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/dhcp-common.c
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
);
95 /* flag options which are valid with the current tag set (sans context tags) */
96 for (opt
= opts
; opt
; opt
= opt
->next
)
98 opt
->flags
&= ~DHOPT_TAGOK
;
99 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)) &&
100 match_netid(opt
->netid
, tagif
, 0))
101 opt
->flags
|= DHOPT_TAGOK
;
104 /* now flag options which are valid, including the context tags,
105 otherwise valid options are inhibited if we found a higher priority one above */
108 struct dhcp_netid
*last_tag
;
110 for (last_tag
= context_tags
; last_tag
->next
; last_tag
= last_tag
->next
);
111 last_tag
->next
= tags
;
112 tagif
= run_tag_if(context_tags
);
114 /* reset stuff with tag:!<tag> which now matches. */
115 for (opt
= opts
; opt
; opt
= opt
->next
)
116 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
)) &&
117 (opt
->flags
& DHOPT_TAGOK
) &&
118 !match_netid(opt
->netid
, tagif
, 0))
119 opt
->flags
&= ~DHOPT_TAGOK
;
121 for (opt
= opts
; opt
; opt
= opt
->next
)
122 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
| DHOPT_TAGOK
)) &&
123 match_netid(opt
->netid
, tagif
, 0))
125 struct dhcp_opt
*tmp
;
126 for (tmp
= opts
; tmp
; tmp
= tmp
->next
)
127 if (tmp
->opt
== opt
->opt
&& opt
->netid
&& (tmp
->flags
& DHOPT_TAGOK
))
130 opt
->flags
|= DHOPT_TAGOK
;
134 /* now flag untagged options which are not overridden by tagged ones */
135 for (opt
= opts
; opt
; opt
= opt
->next
)
136 if (!(opt
->flags
& (DHOPT_ENCAPSULATE
| DHOPT_VENDOR
| DHOPT_RFC3925
| DHOPT_TAGOK
)) && !opt
->netid
)
138 struct dhcp_opt
*tmp
;
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
);
151 /* Is every member of check matched by a member of pool?
152 If tagnotneeded, untagged is OK */
153 int match_netid(struct dhcp_netid
*check
, struct dhcp_netid
*pool
, int tagnotneeded
)
155 struct dhcp_netid
*tmp1
;
157 if (!check
&& !tagnotneeded
)
160 for (; check
; check
= check
->next
)
162 /* '#' for not is for backwards compat. */
163 if (check
->net
[0] != '!' && check
->net
[0] != '#')
165 for (tmp1
= pool
; tmp1
; tmp1
= tmp1
->next
)
166 if (strcmp(check
->net
, tmp1
->net
) == 0)
172 for (tmp1
= pool
; tmp1
; tmp1
= tmp1
->next
)
173 if (strcmp((check
->net
)+1, tmp1
->net
) == 0)
179 /* return domain or NULL if none. */
180 char *strip_hostname(char *hostname
)
182 char *dot
= strchr(hostname
, '.');
187 *dot
= 0; /* truncate */
188 if (strlen(dot
+1) != 0)
194 void log_tags(struct dhcp_netid
*netid
, u32 xid
)
196 if (netid
&& option_bool(OPT_LOG_OPTS
))
198 char *s
= daemon
->namebuff
;
199 for (*s
= 0; netid
; netid
= netid
->next
)
202 struct dhcp_netid
*n
;
204 for (n
= netid
->next
; n
; n
= n
->next
)
205 if (strcmp(netid
->net
, n
->net
) == 0)
210 strncat (s
, netid
->net
, (MAXDNAME
-1) - strlen(s
));
212 strncat (s
, ", ", (MAXDNAME
-1) - strlen(s
));
215 my_syslog(MS_DHCP
| LOG_INFO
, _("%u tags: %s"), xid
, s
);
219 int match_bytes(struct dhcp_opt
*o
, unsigned char *p
, int len
)
229 if (o
->flags
& DHOPT_HEX
)
231 if (memcmp_masked(o
->val
, p
, o
->len
, o
->u
.wildcard_mask
))
235 for (i
= 0; i
<= (len
- o
->len
); )
237 if (memcmp(o
->val
, p
+ i
, o
->len
) == 0)
240 if (o
->flags
& DHOPT_STRING
)
249 void dhcp_update_configs(struct dhcp_config
*configs
)
251 /* Some people like to keep all static IP addresses in /etc/hosts.
252 This goes through /etc/hosts and sets static addresses for any DHCP config
253 records which don't have an address and whose name matches.
254 We take care to maintain the invariant that any IP address can appear
255 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
256 restore the status-quo ante first. */
258 struct dhcp_config
*config
, *conf_tmp
;
262 for (config
= configs
; config
; config
= config
->next
)
263 if (config
->flags
& CONFIG_ADDR_HOSTS
)
264 config
->flags
&= ~(CONFIG_ADDR
| CONFIG_ADDR6
| CONFIG_ADDR_HOSTS
);
270 if (daemon
->port
!= 0)
271 for (config
= configs
; config
; config
= config
->next
)
273 int conflags
= CONFIG_ADDR
;
274 int cacheflags
= F_IPV4
;
277 if (prot
== AF_INET6
)
279 conflags
= CONFIG_ADDR6
;
283 if (!(config
->flags
& conflags
) &&
284 (config
->flags
& CONFIG_NAME
) &&
285 (crec
= cache_find_by_name(NULL
, config
->hostname
, 0, cacheflags
)) &&
286 (crec
->flags
& F_HOSTS
))
288 if (cache_find_by_name(crec
, config
->hostname
, 0, cacheflags
))
290 /* use primary (first) address */
291 while (crec
&& !(crec
->flags
& F_REVERSE
))
292 crec
= cache_find_by_name(crec
, config
->hostname
, 0, cacheflags
);
294 continue; /* should be never */
295 inet_ntop(prot
, &crec
->addr
.addr
, daemon
->addrbuff
, ADDRSTRLEN
);
296 my_syslog(MS_DHCP
| LOG_WARNING
, _("%s has more than one address in hostsfile, using %s for DHCP"),
297 config
->hostname
, daemon
->addrbuff
);
300 if (prot
== AF_INET
&&
301 (!(conf_tmp
= config_find_by_address(configs
, crec
->addr
.addr
.addr
.addr4
)) || conf_tmp
== config
))
303 config
->addr
= crec
->addr
.addr
.addr
.addr4
;
304 config
->flags
|= CONFIG_ADDR
| CONFIG_ADDR_HOSTS
;
309 if (prot
== AF_INET6
&&
310 (!(conf_tmp
= config_find_by_address6(configs
, &crec
->addr
.addr
.addr
.addr6
, 128, 0)) || conf_tmp
== config
))
312 memcpy(&config
->addr6
, &crec
->addr
.addr
.addr
.addr6
, IN6ADDRSZ
);
313 config
->flags
|= CONFIG_ADDR6
| CONFIG_ADDR_HOSTS
;
318 inet_ntop(prot
, &crec
->addr
.addr
, daemon
->addrbuff
, ADDRSTRLEN
);
319 my_syslog(MS_DHCP
| LOG_WARNING
, _("duplicate IP address %s (%s) in dhcp-config directive"),
320 daemon
->addrbuff
, config
->hostname
);
336 #ifdef HAVE_LINUX_NETWORK
337 void bindtodevice(int fd
)
339 /* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
340 to that device. This is for the use case of (eg) OpenStack, which runs a new
341 dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
342 individual processes don't always see the packets they should.
343 SO_BINDTODEVICE is only available Linux. */
345 struct irec
*iface
, *found
;
347 for (found
= NULL
, iface
= daemon
->interfaces
; iface
; iface
= iface
->next
)
352 else if (strcmp(found
->name
, iface
->name
) != 0)
363 strcpy(ifr
.ifr_name
, found
->name
);
364 /* only allowed by root. */
365 if (setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, (void *)&ifr
, sizeof(ifr
)) == -1 &&
367 die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL
, EC_BADNET
);
372 static const struct opttab_t
{
376 { "netmask", 1, OT_ADDR_LIST
},
377 { "time-offset", 2, 4 },
378 { "router", 3, OT_ADDR_LIST
},
379 { "dns-server", 6, OT_ADDR_LIST
},
380 { "log-server", 7, OT_ADDR_LIST
},
381 { "lpr-server", 9, OT_ADDR_LIST
},
382 { "hostname", 12, OT_INTERNAL
| OT_NAME
},
383 { "boot-file-size", 13, 2 | OT_DEC
},
384 { "domain-name", 15, OT_NAME
},
385 { "swap-server", 16, OT_ADDR_LIST
},
386 { "root-path", 17, OT_NAME
},
387 { "extension-path", 18, OT_NAME
},
388 { "ip-forward-enable", 19, 1 },
389 { "non-local-source-routing", 20, 1 },
390 { "policy-filter", 21, OT_ADDR_LIST
},
391 { "max-datagram-reassembly", 22, 2 | OT_DEC
},
392 { "default-ttl", 23, 1 | OT_DEC
},
393 { "mtu", 26, 2 | OT_DEC
},
394 { "all-subnets-local", 27, 1 },
395 { "broadcast", 28, OT_INTERNAL
| OT_ADDR_LIST
},
396 { "router-discovery", 31, 1 },
397 { "router-solicitation", 32, OT_ADDR_LIST
},
398 { "static-route", 33, OT_ADDR_LIST
},
399 { "trailer-encapsulation", 34, 1 },
400 { "arp-timeout", 35, 4 | OT_DEC
},
401 { "ethernet-encap", 36, 1 },
402 { "tcp-ttl", 37, 1 },
403 { "tcp-keepalive", 38, 4 | OT_DEC
},
404 { "nis-domain", 40, OT_NAME
},
405 { "nis-server", 41, OT_ADDR_LIST
},
406 { "ntp-server", 42, OT_ADDR_LIST
},
407 { "vendor-encap", 43, OT_INTERNAL
},
408 { "netbios-ns", 44, OT_ADDR_LIST
},
409 { "netbios-dd", 45, OT_ADDR_LIST
},
410 { "netbios-nodetype", 46, 1 },
411 { "netbios-scope", 47, 0 },
412 { "x-windows-fs", 48, OT_ADDR_LIST
},
413 { "x-windows-dm", 49, OT_ADDR_LIST
},
414 { "requested-address", 50, OT_INTERNAL
| OT_ADDR_LIST
},
415 { "lease-time", 51, OT_INTERNAL
| OT_TIME
},
416 { "option-overload", 52, OT_INTERNAL
},
417 { "message-type", 53, OT_INTERNAL
| OT_DEC
},
418 { "server-identifier", 54, OT_INTERNAL
| OT_ADDR_LIST
},
419 { "parameter-request", 55, OT_INTERNAL
},
420 { "message", 56, OT_INTERNAL
},
421 { "max-message-size", 57, OT_INTERNAL
},
422 { "T1", 58, OT_INTERNAL
| OT_TIME
},
423 { "T2", 59, OT_INTERNAL
| OT_TIME
},
424 { "vendor-class", 60, 0 },
425 { "client-id", 61, OT_INTERNAL
},
426 { "nis+-domain", 64, OT_NAME
},
427 { "nis+-server", 65, OT_ADDR_LIST
},
428 { "tftp-server", 66, OT_NAME
},
429 { "bootfile-name", 67, OT_NAME
},
430 { "mobile-ip-home", 68, OT_ADDR_LIST
},
431 { "smtp-server", 69, OT_ADDR_LIST
},
432 { "pop3-server", 70, OT_ADDR_LIST
},
433 { "nntp-server", 71, OT_ADDR_LIST
},
434 { "irc-server", 74, OT_ADDR_LIST
},
435 { "user-class", 77, 0 },
436 { "FQDN", 81, OT_INTERNAL
},
437 { "agent-id", 82, OT_INTERNAL
},
438 { "client-arch", 93, 2 | OT_DEC
},
439 { "client-interface-id", 94, 0 },
440 { "client-machine-id", 97, 0 },
441 { "subnet-select", 118, OT_INTERNAL
},
442 { "domain-search", 119, OT_RFC1035_NAME
},
443 { "sip-server", 120, 0 },
444 { "classless-static-route", 121, 0 },
445 { "vendor-id-encap", 125, 0 },
446 { "server-ip-address", 255, OT_ADDR_LIST
}, /* special, internal only, sets siaddr */
451 static const struct opttab_t opttab6
[] = {
452 { "client-id", 1, OT_INTERNAL
},
453 { "server-id", 2, OT_INTERNAL
},
454 { "ia-na", 3, OT_INTERNAL
},
455 { "ia-ta", 4, OT_INTERNAL
},
456 { "iaaddr", 5, OT_INTERNAL
},
457 { "oro", 6, OT_INTERNAL
},
458 { "preference", 7, OT_INTERNAL
| OT_DEC
},
459 { "unicast", 12, OT_INTERNAL
},
460 { "status", 13, OT_INTERNAL
},
461 { "rapid-commit", 14, OT_INTERNAL
},
462 { "user-class", 15, OT_INTERNAL
| OT_CSTRING
},
463 { "vendor-class", 16, OT_INTERNAL
| OT_CSTRING
},
464 { "vendor-opts", 17, OT_INTERNAL
},
465 { "sip-server-domain", 21, OT_RFC1035_NAME
},
466 { "sip-server", 22, OT_ADDR_LIST
},
467 { "dns-server", 23, OT_ADDR_LIST
},
468 { "domain-search", 24, OT_RFC1035_NAME
},
469 { "nis-server", 27, OT_ADDR_LIST
},
470 { "nis+-server", 28, OT_ADDR_LIST
},
471 { "nis-domain", 29, OT_RFC1035_NAME
},
472 { "nis+-domain", 30, OT_RFC1035_NAME
},
473 { "sntp-server", 31, OT_ADDR_LIST
},
474 { "information-refresh-time", 32, OT_TIME
},
475 { "FQDN", 39, OT_INTERNAL
| OT_RFC1035_NAME
},
476 { "ntp-server", 56, OT_ADDR_LIST
},
477 { "bootfile-url", 59, OT_NAME
},
478 { "bootfile-param", 60, OT_CSTRING
},
485 void display_opts(void)
489 printf(_("Known DHCP options:\n"));
491 for (i
= 0; opttab
[i
].name
; i
++)
492 if (!(opttab
[i
].size
& OT_INTERNAL
))
493 printf("%3d %s\n", opttab
[i
].val
, opttab
[i
].name
);
497 void display_opts6(void)
500 printf(_("Known DHCPv6 options:\n"));
502 for (i
= 0; opttab6
[i
].name
; i
++)
503 if (!(opttab6
[i
].size
& OT_INTERNAL
))
504 printf("%3d %s\n", opttab6
[i
].val
, opttab6
[i
].name
);
508 u16
lookup_dhcp_opt(int prot
, char *name
)
510 const struct opttab_t
*t
;
514 if (prot
== AF_INET6
)
520 for (i
= 0; t
[i
].name
; i
++)
521 if (strcasecmp(t
[i
].name
, name
) == 0)
527 u16
lookup_dhcp_len(int prot
, u16 val
)
529 const struct opttab_t
*t
;
533 if (prot
== AF_INET6
)
539 for (i
= 0; t
[i
].name
; i
++)
541 return t
[i
].size
& ~OT_DEC
;
546 char *option_string(int prot
, unsigned int opt
, unsigned char *val
, int opt_len
, char *buf
, int buf_len
)
548 int o
, i
, j
, nodecode
= 0;
549 const struct opttab_t
*ot
= opttab
;
552 if (prot
== AF_INET6
)
556 for (o
= 0; ot
[o
].name
; o
++)
557 if (ot
[o
].val
== opt
)
561 memset(buf
, 0, buf_len
);
563 if (ot
[o
].size
& OT_ADDR_LIST
)
565 struct all_addr addr
;
566 int addr_len
= INADDRSZ
;
569 if (prot
== AF_INET6
)
570 addr_len
= IN6ADDRSZ
;
572 for (buf
[0]= 0, i
= 0; i
<= opt_len
- addr_len
; i
+= addr_len
)
575 strncat(buf
, ", ", buf_len
- strlen(buf
));
577 memcpy(&addr
, &val
[i
], addr_len
);
578 inet_ntop(prot
, &val
[i
], daemon
->addrbuff
, ADDRSTRLEN
);
579 strncat(buf
, daemon
->addrbuff
, buf_len
- strlen(buf
));
582 else if (ot
[o
].size
& OT_NAME
)
583 for (i
= 0, j
= 0; i
< opt_len
&& j
< buf_len
; i
++)
590 /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
591 else if ((ot
[o
].size
& OT_RFC1035_NAME
) && prot
== AF_INET6
)
594 while (i
< opt_len
&& val
[i
] != 0)
596 int k
, l
= i
+ val
[i
] + 1;
597 for (k
= i
+ 1; k
< opt_len
&& k
< l
&& j
< buf_len
; k
++)
604 if (val
[i
] != 0 && j
< buf_len
)
608 else if ((ot
[o
].size
& OT_CSTRING
))
618 for (k
= 0; k
< len
&& j
< buf_len
; k
++)
633 else if ((ot
[o
].size
& (OT_DEC
| OT_TIME
)) && opt_len
!= 0)
635 unsigned int dec
= 0;
637 for (i
= 0; i
< opt_len
; i
++)
638 dec
= (dec
<< 8) | val
[i
];
640 if (ot
[o
].size
& OT_TIME
)
641 prettyprint_time(buf
, dec
);
643 sprintf(buf
, "%u", dec
);
651 if (opt_len
!= 0 && buf
&& (!ot
[o
].name
|| nodecode
))
659 print_mac(buf
, val
, opt_len
);
661 strncat(buf
, "...", buf_len
- strlen(buf
));
666 return ot
[o
].name
? ot
[o
].name
: "";
670 void log_context(int family
, struct dhcp_context
*context
)
672 /* Cannot use dhcp_buff* for RA contexts */
674 void *start
= &context
->start
;
675 void *end
= &context
->end
;
676 char *template = "", *p
= daemon
->namebuff
;
681 if (family
== AF_INET6
)
683 struct in6_addr subnet
= context
->start6
;
684 if (!(context
->flags
& CONTEXT_TEMPLATE
))
685 setaddr6part(&subnet
, 0);
686 inet_ntop(AF_INET6
, &subnet
, daemon
->addrbuff
, ADDRSTRLEN
);
687 start
= &context
->start6
;
688 end
= &context
->end6
;
692 if (family
!= AF_INET
&& (context
->flags
& CONTEXT_DEPRECATE
))
693 strcpy(daemon
->namebuff
, _(", prefix deprecated"));
696 p
+= sprintf(p
, _(", lease time "));
697 prettyprint_time(p
, context
->lease_time
);
702 if (context
->flags
& CONTEXT_CONSTRUCTED
)
704 char ifrn_name
[IFNAMSIZ
];
707 p
+= sprintf(p
, ", ");
709 if (indextoname(daemon
->doing_dhcp6
? daemon
->dhcp6fd
: daemon
->icmp6fd
, context
->if_index
, ifrn_name
))
710 sprintf(p
, "constructed for %s", ifrn_name
);
712 else if (context
->flags
& CONTEXT_TEMPLATE
)
715 p
+= sprintf(p
, ", ");
717 sprintf(p
, "template for %s", context
->template_interface
);
721 if ((context
->flags
& CONTEXT_DHCP
) || family
== AF_INET
)
723 inet_ntop(family
, start
, daemon
->dhcp_buff
, 256);
724 inet_ntop(family
, end
, daemon
->dhcp_buff3
, 256);
725 my_syslog(MS_DHCP
| LOG_INFO
,
726 (context
->flags
& CONTEXT_RA_STATELESS
) ?
727 _("%s stateless on %s%.0s%.0s%s") :
728 (context
->flags
& CONTEXT_STATIC
) ?
729 _("%s, static leases only on %.0s%s%s%.0s") :
730 (context
->flags
& CONTEXT_PROXY
) ?
731 _("%s, proxy on subnet %.0s%s%.0s%.0s") :
732 _("%s, IP range %s -- %s%s%.0s"),
733 (family
!= AF_INET
) ? "DHCPv6" : "DHCP",
734 daemon
->dhcp_buff
, daemon
->dhcp_buff3
, daemon
->namebuff
, template);
738 if (context
->flags
& CONTEXT_RA_NAME
)
739 my_syslog(MS_DHCP
| LOG_INFO
, _("DHCPv4-derived IPv6 names on %s%s"), daemon
->addrbuff
, template);
741 if ((context
->flags
& CONTEXT_RA
) || (option_bool(OPT_RA
) && (context
->flags
& CONTEXT_DHCP
) && family
== AF_INET6
))
742 my_syslog(MS_DHCP
| LOG_INFO
, _("router advertisement on %s%s"), daemon
->addrbuff
, template);