Tomato 1.28
[tomato.git] / release / src / router / dnsmasq / src / dhcp.c
blob00ca03a51c3bf980e9377177c8036daeb7cb55c5
1 /* dnsmasq is Copyright (c) 2000-2010 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/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_DHCP
21 struct iface_param {
22 struct in_addr relay, primary;
23 struct dhcp_context *current;
24 int ind;
27 static int complete_context(struct in_addr local, int if_index,
28 struct in_addr netmask, struct in_addr broadcast, void *vparam);
30 static int make_fd(int port)
32 int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
33 struct sockaddr_in saddr;
34 int oneopt = 1;
35 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
36 int mtu = IP_PMTUDISC_DONT;
37 #endif
39 if (fd == -1)
40 die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
42 if (!fix_fd(fd) ||
43 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
44 setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 ||
45 #endif
46 #if defined(HAVE_LINUX_NETWORK)
47 setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
48 #else
49 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
50 #endif
51 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
52 die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
54 /* When bind-interfaces is set, there might be more than one dnmsasq
55 instance binding port 67. That's OK if they serve different networks.
56 Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
57 if (daemon->options & OPT_NOWILD)
59 #ifdef SO_REUSEPORT
60 int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
61 #else
62 int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
63 #endif
64 if (rc == -1)
65 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
68 memset(&saddr, 0, sizeof(saddr));
69 saddr.sin_family = AF_INET;
70 saddr.sin_port = htons(port);
71 saddr.sin_addr.s_addr = INADDR_ANY;
72 #ifdef HAVE_SOCKADDR_SA_LEN
73 saddr.sin_len = sizeof(struct sockaddr_in);
74 #endif
76 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
77 die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);
79 return fd;
82 void dhcp_init(void)
84 #if defined(HAVE_BSD_NETWORK)
85 int oneopt = 1;
86 #endif
88 daemon->dhcpfd = make_fd(daemon->dhcp_server_port);
89 if (daemon->enable_pxe)
90 daemon->pxefd = make_fd(PXE_PORT);
91 else
92 daemon->pxefd = -1;
94 #if defined(HAVE_BSD_NETWORK)
95 /* When we're not using capabilities, we need to do this here before
96 we drop root. Also, set buffer size small, to avoid wasting
97 kernel buffers */
99 if (daemon->options & OPT_NO_PING)
100 daemon->dhcp_icmp_fd = -1;
101 else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
102 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
103 die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
105 /* Make BPF raw send socket */
106 init_bpf();
107 #endif
109 check_dhcp_hosts(1);
111 daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet);
112 daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
115 void dhcp_packet(time_t now, int pxe_fd)
117 int fd = pxe_fd ? daemon->pxefd : daemon->dhcpfd;
118 struct dhcp_packet *mess;
119 struct dhcp_context *context;
120 struct iname *tmp;
121 struct ifreq ifr;
122 struct msghdr msg;
123 struct sockaddr_in dest;
124 struct cmsghdr *cmptr;
125 struct iovec iov;
126 ssize_t sz;
127 int iface_index = 0, unicast_dest = 0, is_inform = 0;
128 struct in_addr iface_addr, *addrp = NULL;
129 struct iface_param parm;
130 #ifdef HAVE_LINUX_NETWORK
131 struct arpreq arp_req;
132 #endif
134 union {
135 struct cmsghdr align; /* this ensures alignment */
136 #if defined(HAVE_LINUX_NETWORK)
137 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
138 #elif defined(HAVE_SOLARIS_NETWORK)
139 char control[CMSG_SPACE(sizeof(unsigned int))];
140 #elif defined(HAVE_BSD_NETWORK)
141 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
142 #endif
143 } control_u;
145 msg.msg_control = NULL;
146 msg.msg_controllen = 0;
147 msg.msg_name = NULL;
148 msg.msg_namelen = 0;
149 msg.msg_iov = &daemon->dhcp_packet;
150 msg.msg_iovlen = 1;
152 while (1)
154 msg.msg_flags = 0;
155 while ((sz = recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
157 if (sz == -1)
158 return;
160 if (!(msg.msg_flags & MSG_TRUNC))
161 break;
163 /* Very new Linux kernels return the actual size needed,
164 older ones always return truncated size */
165 if ((size_t)sz == daemon->dhcp_packet.iov_len)
167 if (!expand_buf(&daemon->dhcp_packet, sz + 100))
168 return;
170 else
172 expand_buf(&daemon->dhcp_packet, sz);
173 break;
177 /* expand_buf may have moved buffer */
178 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
179 msg.msg_controllen = sizeof(control_u);
180 msg.msg_control = control_u.control;
181 msg.msg_flags = 0;
182 msg.msg_name = &dest;
183 msg.msg_namelen = sizeof(dest);
185 while ((sz = recvmsg(fd, &msg, 0)) == -1 && errno == EINTR);
187 if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
188 return;
190 #if defined (HAVE_LINUX_NETWORK)
191 if (msg.msg_controllen >= sizeof(struct cmsghdr))
192 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
193 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
195 union {
196 unsigned char *c;
197 struct in_pktinfo *p;
198 } p;
199 p.c = CMSG_DATA(cmptr);
200 iface_index = p.p->ipi_ifindex;
201 if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
202 unicast_dest = 1;
205 #elif defined(HAVE_BSD_NETWORK)
206 if (msg.msg_controllen >= sizeof(struct cmsghdr))
207 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
208 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
210 union {
211 unsigned char *c;
212 struct sockaddr_dl *s;
213 } p;
214 p.c = CMSG_DATA(cmptr);
215 iface_index = p.s->sdl_index;
218 #elif defined(HAVE_SOLARIS_NETWORK)
219 if (msg.msg_controllen >= sizeof(struct cmsghdr))
220 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
221 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
223 union {
224 unsigned char *c;
225 unsigned int *i;
226 } p;
227 p.c = CMSG_DATA(cmptr);
228 iface_index = *(p.i);
230 #endif
232 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
233 return;
235 #ifdef HAVE_LINUX_NETWORK
236 /* ARP fiddling uses original interface even if we pretend to use a different one. */
237 strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
238 #endif
240 #ifdef MSG_BCAST
241 /* OpenBSD tells us when a packet was broadcast */
242 if (!(msg.msg_flags & MSG_BCAST))
243 unicast_dest = 1;
244 #endif
246 ifr.ifr_addr.sa_family = AF_INET;
247 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
249 addrp = &iface_addr;
250 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
253 if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index))
254 return;
256 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
257 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
258 return;
260 /* weird libvirt-inspired access control */
261 for (context = daemon->dhcp; context; context = context->next)
262 if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
263 break;
265 if (!context)
266 return;
268 /* unlinked contexts are marked by context->current == context */
269 for (context = daemon->dhcp; context; context = context->next)
270 context->current = context;
272 parm.relay = mess->giaddr;
273 parm.primary = iface_addr;
274 parm.current = NULL;
275 parm.ind = iface_index;
277 /* interface may have been changed by alias in iface_check, make sure it gets priority in case
278 there is more than one address on the interface in the same subnet */
279 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
281 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
282 return;
284 else
286 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
287 if (ioctl(daemon->dhcpfd, SIOCGIFNETMASK, &ifr) != -1)
289 struct in_addr netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
290 if (ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1)
292 struct in_addr broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
293 complete_context(iface_addr, iface_index, netmask, broadcast, &parm);
298 if (!iface_enumerate(&parm, complete_context, NULL))
299 return;
300 lease_prune(NULL, now); /* lose any expired leases */
301 iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
302 now, unicast_dest, &is_inform, pxe_fd);
303 lease_update_file(now);
304 lease_update_dns();
306 if (iov.iov_len == 0)
307 return;
309 msg.msg_name = &dest;
310 msg.msg_namelen = sizeof(dest);
311 msg.msg_control = NULL;
312 msg.msg_controllen = 0;
313 msg.msg_iov = &iov;
314 iov.iov_base = daemon->dhcp_packet.iov_base;
316 /* packet buffer may have moved */
317 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
319 #ifdef HAVE_SOCKADDR_SA_LEN
320 dest.sin_len = sizeof(struct sockaddr_in);
321 #endif
323 if (pxe_fd)
325 if (mess->ciaddr.s_addr != 0)
326 dest.sin_addr = mess->ciaddr;
328 else if (mess->giaddr.s_addr)
330 /* Send to BOOTP relay */
331 dest.sin_port = htons(daemon->dhcp_server_port);
332 dest.sin_addr = mess->giaddr;
334 else if (mess->ciaddr.s_addr)
336 /* If the client's idea of its own address tallys with
337 the source address in the request packet, we believe the
338 source port too, and send back to that. If we're replying
339 to a DHCPINFORM, trust the source address always. */
340 if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
341 dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
343 dest.sin_port = htons(daemon->dhcp_client_port);
344 dest.sin_addr = mess->ciaddr;
347 #if defined(HAVE_LINUX_NETWORK)
348 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
349 mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
351 /* broadcast to 255.255.255.255 (or mac address invalid) */
352 struct in_pktinfo *pkt;
353 msg.msg_control = control_u.control;
354 msg.msg_controllen = sizeof(control_u);
355 cmptr = CMSG_FIRSTHDR(&msg);
356 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
357 pkt->ipi_ifindex = iface_index;
358 pkt->ipi_spec_dst.s_addr = 0;
359 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
360 cmptr->cmsg_level = SOL_IP;
361 cmptr->cmsg_type = IP_PKTINFO;
362 dest.sin_addr.s_addr = INADDR_BROADCAST;
363 dest.sin_port = htons(daemon->dhcp_client_port);
365 else
367 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
368 struct sockaddr limits size to 14 bytes. */
369 dest.sin_addr = mess->yiaddr;
370 dest.sin_port = htons(daemon->dhcp_client_port);
371 memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
372 arp_req.arp_ha.sa_family = mess->htype;
373 memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
374 /* interface name already copied in */
375 arp_req.arp_flags = ATF_COM;
376 ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
378 #elif defined(HAVE_SOLARIS_NETWORK)
379 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
381 /* broadcast to 255.255.255.255 (or mac address invalid) */
382 dest.sin_addr.s_addr = INADDR_BROADCAST;
383 dest.sin_port = htons(daemon->dhcp_client_port);
384 /* note that we don't specify the interface here: that's done by the
385 IP_BOUND_IF sockopt lower down. */
387 else
389 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
390 Note that this only works for ethernet on solaris, because we use SIOCSARP
391 and not SIOCSXARP, which would be perfect, except that it returns ENXIO
392 mysteriously. Bah. Fall back to broadcast for other net types. */
393 struct arpreq req;
394 dest.sin_addr = mess->yiaddr;
395 dest.sin_port = htons(daemon->dhcp_client_port);
396 *((struct sockaddr_in *)&req.arp_pa) = dest;
397 req.arp_ha.sa_family = AF_UNSPEC;
398 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
399 req.arp_flags = ATF_COM;
400 ioctl(daemon->dhcpfd, SIOCSARP, &req);
402 #elif defined(HAVE_BSD_NETWORK)
403 else
405 send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
406 return;
408 #endif
410 #ifdef HAVE_SOLARIS_NETWORK
411 setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
412 #endif
414 while(sendmsg(fd, &msg, 0) == -1 && retry_send());
417 /* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
418 of each interface (and any relay address) and does the following things:
420 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
421 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
422 3) Fills in local (this host) and router (this host or relay) addresses.
423 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
425 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
427 static int complete_context(struct in_addr local, int if_index,
428 struct in_addr netmask, struct in_addr broadcast, void *vparam)
430 struct dhcp_context *context;
431 struct iface_param *param = vparam;
433 for (context = daemon->dhcp; context; context = context->next)
435 if (!(context->flags & CONTEXT_NETMASK) &&
436 (is_same_net(local, context->start, netmask) ||
437 is_same_net(local, context->end, netmask)))
439 if (context->netmask.s_addr != netmask.s_addr &&
440 !(is_same_net(local, context->start, netmask) &&
441 is_same_net(local, context->end, netmask)))
443 strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
444 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
445 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
446 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
448 context->netmask = netmask;
451 if (context->netmask.s_addr)
453 if (is_same_net(local, context->start, context->netmask) &&
454 is_same_net(local, context->end, context->netmask))
456 /* link it onto the current chain if we've not seen it before */
457 if (if_index == param->ind && context->current == context)
459 context->router = local;
460 context->local = local;
461 context->current = param->current;
462 param->current = context;
465 if (!(context->flags & CONTEXT_BRDCAST))
467 if (is_same_net(broadcast, context->start, context->netmask))
468 context->broadcast = broadcast;
469 else
470 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
473 else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask))
475 context->router = param->relay;
476 context->local = param->primary;
477 /* fill in missing broadcast addresses for relayed ranges */
478 if (!(context->flags & CONTEXT_BRDCAST))
479 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
485 return 1;
488 struct dhcp_context *address_available(struct dhcp_context *context,
489 struct in_addr taddr,
490 struct dhcp_netid *netids)
492 /* Check is an address is OK for this network, check all
493 possible ranges. Make sure that the address isn't in use
494 by the server itself. */
496 unsigned int start, end, addr = ntohl(taddr.s_addr);
497 struct dhcp_context *tmp;
499 for (tmp = context; tmp; tmp = tmp->current)
500 if (taddr.s_addr == context->router.s_addr)
501 return NULL;
503 for (tmp = context; tmp; tmp = tmp->current)
505 start = ntohl(tmp->start.s_addr);
506 end = ntohl(tmp->end.s_addr);
508 if (!(tmp->flags & CONTEXT_STATIC) &&
509 addr >= start &&
510 addr <= end &&
511 match_netid(tmp->filter, netids, 1))
512 return tmp;
515 return NULL;
518 struct dhcp_context *narrow_context(struct dhcp_context *context,
519 struct in_addr taddr,
520 struct dhcp_netid *netids)
522 /* We start of with a set of possible contexts, all on the current physical interface.
523 These are chained on ->current.
524 Here we have an address, and return the actual context correponding to that
525 address. Note that none may fit, if the address came a dhcp-host and is outside
526 any dhcp-range. In that case we return a static range if possible, or failing that,
527 any context on the correct subnet. (If there's more than one, this is a dodgy
528 configuration: maybe there should be a warning.) */
530 struct dhcp_context *tmp;
532 if (!(tmp = address_available(context, taddr, netids)))
534 for (tmp = context; tmp; tmp = tmp->current)
535 if (match_netid(tmp->filter, netids, 1) &&
536 is_same_net(taddr, tmp->start, tmp->netmask) &&
537 (tmp->flags & CONTEXT_STATIC))
538 break;
540 if (!tmp)
541 for (tmp = context; tmp; tmp = tmp->current)
542 if (match_netid(tmp->filter, netids, 1) &&
543 is_same_net(taddr, tmp->start, tmp->netmask))
544 break;
547 /* Only one context allowed now */
548 if (tmp)
549 tmp->current = NULL;
551 return tmp;
554 struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
556 struct dhcp_config *config;
558 for (config = configs; config; config = config->next)
559 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
560 return config;
562 return NULL;
565 /* Is every member of check matched by a member of pool?
566 If tagnotneeded, untagged is OK */
567 int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
569 struct dhcp_netid *tmp1;
571 if (!check && !tagnotneeded)
572 return 0;
574 for (; check; check = check->next)
576 /* '#' for not is for backwards compat. */
577 if (check->net[0] != '!' && check->net[0] != '#')
579 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
580 if (strcmp(check->net, tmp1->net) == 0)
581 break;
582 if (!tmp1)
583 return 0;
585 else
586 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
587 if (strcmp((check->net)+1, tmp1->net) == 0)
588 return 0;
590 return 1;
593 struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
595 struct tag_if *exprs;
596 struct dhcp_netid_list *list;
598 for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
599 if (match_netid(exprs->tag, tags, 1))
600 for (list = exprs->set; list; list = list->next)
602 list->list->next = tags;
603 tags = list->list;
606 return tags;
609 int address_allocate(struct dhcp_context *context,
610 struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
611 struct dhcp_netid *netids, time_t now)
613 /* Find a free address: exclude anything in use and anything allocated to
614 a particular hwaddr/clientid/hostname in our configuration.
615 Try to return from contexts which match netids first. */
617 struct in_addr start, addr;
618 struct dhcp_context *c, *d;
619 int i, pass;
620 unsigned int j;
622 /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
623 dispersal even with similarly-valued "strings". */
624 for (j = 0, i = 0; i < hw_len; i++)
625 j += hwaddr[i] + (j << 6) + (j << 16) - j;
627 for (pass = 0; pass <= 1; pass++)
628 for (c = context; c; c = c->current)
629 if (c->flags & CONTEXT_STATIC)
630 continue;
631 else if (!match_netid(c->filter, netids, pass))
632 continue;
633 else
635 /* pick a seed based on hwaddr then iterate until we find a free address. */
636 start.s_addr = addr.s_addr =
637 htonl(ntohl(c->start.s_addr) +
638 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
640 do {
641 /* eliminate addresses in use by the server. */
642 for (d = context; d; d = d->current)
643 if (addr.s_addr == d->router.s_addr)
644 break;
646 /* Addresses which end in .255 and .0 are broken in Windows even when using
647 supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
648 then 192.168.0.255 is a valid IP address, but not for Windows as it's
649 in the class C range. See KB281579. We therefore don't allocate these
650 addresses to avoid hard-to-diagnose problems. Thanks Bill. */
651 if (!d &&
652 !lease_find_by_addr(addr) &&
653 !config_find_by_address(daemon->dhcp_conf, addr) &&
654 (!IN_CLASSC(ntohl(addr.s_addr)) ||
655 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
657 struct ping_result *r, *victim = NULL;
658 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
659 ((float)PING_WAIT)));
661 *addrp = addr;
663 if (daemon->options & OPT_NO_PING)
664 return 1;
666 /* check if we failed to ping addr sometime in the last
667 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
668 This avoids problems when a stupid client bangs
669 on us repeatedly. As a final check, if we did more
670 than 60% of the possible ping checks in the last
671 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
672 for (count = 0, r = daemon->ping_results; r; r = r->next)
673 if (difftime(now, r->time) > (float)PING_CACHE_TIME)
674 victim = r; /* old record */
675 else if (++count == max || r->addr.s_addr == addr.s_addr)
676 return 1;
678 if (icmp_ping(addr))
679 /* address in use: perturb address selection so that we are
680 less likely to try this address again. */
681 c->addr_epoch++;
682 else
684 /* at this point victim may hold an expired record */
685 if (!victim)
687 if ((victim = whine_malloc(sizeof(struct ping_result))))
689 victim->next = daemon->ping_results;
690 daemon->ping_results = victim;
694 /* record that this address is OK for 30s
695 without more ping checks */
696 if (victim)
698 victim->addr = addr;
699 victim->time = now;
701 return 1;
705 addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
707 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
708 addr = c->start;
710 } while (addr.s_addr != start.s_addr);
712 return 0;
715 static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config)
717 if (!context) /* called via find_config() from lease_update_from_configs() */
718 return 1;
719 if (!(config->flags & CONFIG_ADDR))
720 return 1;
721 for (; context; context = context->current)
722 if (is_same_net(config->addr, context->start, context->netmask))
723 return 1;
725 return 0;
728 int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
730 struct hwaddr_config *conf_addr;
732 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
733 if (conf_addr->wildcard_mask == 0 &&
734 conf_addr->hwaddr_len == len &&
735 (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
736 memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
737 return 1;
739 return 0;
742 struct dhcp_config *find_config(struct dhcp_config *configs,
743 struct dhcp_context *context,
744 unsigned char *clid, int clid_len,
745 unsigned char *hwaddr, int hw_len,
746 int hw_type, char *hostname)
748 int count, new;
749 struct dhcp_config *config, *candidate;
750 struct hwaddr_config *conf_addr;
752 if (clid)
753 for (config = configs; config; config = config->next)
754 if (config->flags & CONFIG_CLID)
756 if (config->clid_len == clid_len &&
757 memcmp(config->clid, clid, clid_len) == 0 &&
758 is_addr_in_context(context, config))
759 return config;
761 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
762 cope with that here */
763 if (*clid == 0 && config->clid_len == clid_len-1 &&
764 memcmp(config->clid, clid+1, clid_len-1) == 0 &&
765 is_addr_in_context(context, config))
766 return config;
770 for (config = configs; config; config = config->next)
771 if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
772 is_addr_in_context(context, config))
773 return config;
775 if (hostname && context)
776 for (config = configs; config; config = config->next)
777 if ((config->flags & CONFIG_NAME) &&
778 hostname_isequal(config->hostname, hostname) &&
779 is_addr_in_context(context, config))
780 return config;
782 /* use match with fewest wildcast octets */
783 for (candidate = NULL, count = 0, config = configs; config; config = config->next)
784 if (is_addr_in_context(context, config))
785 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
786 if (conf_addr->wildcard_mask != 0 &&
787 conf_addr->hwaddr_len == hw_len &&
788 (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
789 (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
791 count = new;
792 candidate = config;
795 return candidate;
798 void dhcp_read_ethers(void)
800 FILE *f = fopen(ETHERSFILE, "r");
801 unsigned int flags;
802 char *buff = daemon->namebuff;
803 char *ip, *cp;
804 struct in_addr addr;
805 unsigned char hwaddr[ETHER_ADDR_LEN];
806 struct dhcp_config **up, *tmp;
807 struct dhcp_config *config;
808 int count = 0, lineno = 0;
810 addr.s_addr = 0; /* eliminate warning */
812 if (!f)
814 my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
815 return;
818 /* This can be called again on SIGHUP, so remove entries created last time round. */
819 for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp)
821 tmp = config->next;
822 if (config->flags & CONFIG_FROM_ETHERS)
824 *up = tmp;
825 /* cannot have a clid */
826 if (config->flags & CONFIG_NAME)
827 free(config->hostname);
828 free(config->hwaddr);
829 free(config);
831 else
832 up = &config->next;
835 while (fgets(buff, MAXDNAME, f))
837 char *host = NULL;
839 lineno++;
841 while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
842 buff[strlen(buff)-1] = 0;
844 if ((*buff == '#') || (*buff == '+') || (*buff == 0))
845 continue;
847 for (ip = buff; *ip && !isspace((int)*ip); ip++);
848 for(; *ip && isspace((int)*ip); ip++)
849 *ip = 0;
850 if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
852 my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
853 continue;
856 /* check for name or dotted-quad */
857 for (cp = ip; *cp; cp++)
858 if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
859 break;
861 if (!*cp)
863 if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
865 my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
866 continue;
869 flags = CONFIG_ADDR;
871 for (config = daemon->dhcp_conf; config; config = config->next)
872 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
873 break;
875 else
877 int nomem;
878 if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
880 if (!nomem)
881 my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
882 free(host);
883 continue;
886 flags = CONFIG_NAME;
888 for (config = daemon->dhcp_conf; config; config = config->next)
889 if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
890 break;
893 if (config && (config->flags & CONFIG_FROM_ETHERS))
895 my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno);
896 continue;
899 if (!config)
901 for (config = daemon->dhcp_conf; config; config = config->next)
903 struct hwaddr_config *conf_addr = config->hwaddr;
904 if (conf_addr &&
905 conf_addr->next == NULL &&
906 conf_addr->wildcard_mask == 0 &&
907 conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
908 (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
909 memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
910 break;
913 if (!config)
915 if (!(config = whine_malloc(sizeof(struct dhcp_config))))
916 continue;
917 config->flags = CONFIG_FROM_ETHERS;
918 config->hwaddr = NULL;
919 config->domain = NULL;
920 config->netid = NULL;
921 config->next = daemon->dhcp_conf;
922 daemon->dhcp_conf = config;
925 config->flags |= flags;
927 if (flags & CONFIG_NAME)
929 config->hostname = host;
930 host = NULL;
933 if (flags & CONFIG_ADDR)
934 config->addr = addr;
937 config->flags |= CONFIG_NOCLID;
938 if (!config->hwaddr)
939 config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
940 if (config->hwaddr)
942 memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
943 config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
944 config->hwaddr->hwaddr_type = ARPHRD_ETHER;
945 config->hwaddr->wildcard_mask = 0;
946 config->hwaddr->next = NULL;
948 count++;
950 free(host);
954 fclose(f);
956 my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
959 void check_dhcp_hosts(int fatal)
961 /* If the same IP appears in more than one host config, then DISCOVER
962 for one of the hosts will get the address, but REQUEST will be NAKed,
963 since the address is reserved by the other one -> protocol loop.
964 Also check that FQDNs match the domain we are using. */
966 struct dhcp_config *configs, *cp;
968 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
970 char *domain;
972 if ((configs->flags & DHOPT_BANK) || fatal)
974 for (cp = configs->next; cp; cp = cp->next)
975 if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
977 if (fatal)
978 die(_("duplicate IP address %s in dhcp-config directive."),
979 inet_ntoa(cp->addr), EC_BADCONF);
980 else
981 my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
982 inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
983 configs->flags &= ~CONFIG_ADDR;
986 /* split off domain part */
987 if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
988 configs->domain = domain;
993 void dhcp_update_configs(struct dhcp_config *configs)
995 /* Some people like to keep all static IP addresses in /etc/hosts.
996 This goes through /etc/hosts and sets static addresses for any DHCP config
997 records which don't have an address and whose name matches.
998 We take care to maintain the invariant that any IP address can appear
999 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
1000 restore the status-quo ante first. */
1002 struct dhcp_config *config;
1003 struct crec *crec;
1005 for (config = configs; config; config = config->next)
1006 if (config->flags & CONFIG_ADDR_HOSTS)
1007 config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
1010 if (daemon->port != 0)
1011 for (config = configs; config; config = config->next)
1012 if (!(config->flags & CONFIG_ADDR) &&
1013 (config->flags & CONFIG_NAME) &&
1014 (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
1015 (crec->flags & F_HOSTS))
1017 if (cache_find_by_name(crec, config->hostname, 0, F_IPV4))
1019 /* use primary (first) address */
1020 while (crec && !(crec->flags & F_REVERSE))
1021 crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4);
1022 if (!crec)
1023 continue; /* should be never */
1024 my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
1025 config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
1028 if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
1029 my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
1030 inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
1031 else
1033 config->addr = crec->addr.addr.addr.addr4;
1034 config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
1039 /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
1040 for this address. If it has a domain part, that must match the set domain and
1041 it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
1042 so check here that the domain name is legal as a hostname.
1043 NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
1044 char *host_from_dns(struct in_addr addr)
1046 struct crec *lookup;
1048 if (daemon->port == 0)
1049 return NULL; /* DNS disabled. */
1051 lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
1053 if (lookup && (lookup->flags & F_HOSTS))
1055 char *dot, *hostname = cache_get_name(lookup);
1056 dot = strchr(hostname, '.');
1058 if (dot && strlen(dot+1) != 0)
1060 char *d2 = get_domain(addr);
1061 if (!d2 || !hostname_isequal(dot+1, d2))
1062 return NULL; /* wrong domain */
1065 if (!legal_hostname(hostname))
1066 return NULL;
1068 strncpy(daemon->dhcp_buff, hostname, 256);
1069 daemon->dhcp_buff[255] = 0;
1070 strip_hostname(daemon->dhcp_buff);
1072 return daemon->dhcp_buff;
1075 return NULL;
1078 /* return domain or NULL if none. */
1079 char *strip_hostname(char *hostname)
1081 char *dot = strchr(hostname, '.');
1083 if (!dot)
1084 return NULL;
1086 *dot = 0; /* truncate */
1087 if (strlen(dot+1) != 0)
1088 return dot+1;
1090 return NULL;
1093 #endif