Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnsmasq / src / dhcp.c
blob333a327bb6404964a03e6a85a59d99601367e84c
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/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_DHCP
21 struct iface_param {
22 struct dhcp_context *current;
23 int ind;
26 struct match_param {
27 int ind, matched;
28 struct in_addr netmask, broadcast, addr;
31 static int complete_context(struct in_addr local, int if_index, char *label,
32 struct in_addr netmask, struct in_addr broadcast, void *vparam);
33 static int check_listen_addrs(struct in_addr local, int if_index, char *label,
34 struct in_addr netmask, struct in_addr broadcast, void *vparam);
36 static int make_fd(int port)
38 int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
39 struct sockaddr_in saddr;
40 int oneopt = 1;
41 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
42 int mtu = IP_PMTUDISC_DONT;
43 #endif
44 #if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
45 int tos = IPTOS_CLASS_CS6;
46 #endif
48 if (fd == -1)
49 die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
51 if (!fix_fd(fd) ||
52 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
53 setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 ||
54 #endif
55 #if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
56 setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1 ||
57 #endif
58 #if defined(HAVE_LINUX_NETWORK)
59 setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
60 #else
61 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
62 #endif
63 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
64 die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
66 /* When bind-interfaces is set, there might be more than one dnmsasq
67 instance binding port 67. That's OK if they serve different networks.
68 Need to set REUSEADDR|REUSEPORT to make this posible.
69 Handle the case that REUSEPORT is defined, but the kernel doesn't
70 support it. This handles the introduction of REUSEPORT on Linux. */
71 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
73 int rc = -1, porterr = 0;
75 #ifdef SO_REUSEPORT
76 if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
77 errno != ENOPROTOOPT)
78 porterr = 1;
79 #endif
81 if (rc == -1 && !porterr)
82 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
84 if (rc == -1)
85 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
88 memset(&saddr, 0, sizeof(saddr));
89 saddr.sin_family = AF_INET;
90 saddr.sin_port = htons(port);
91 saddr.sin_addr.s_addr = INADDR_ANY;
92 #ifdef HAVE_SOCKADDR_SA_LEN
93 saddr.sin_len = sizeof(struct sockaddr_in);
94 #endif
96 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
97 die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);
99 return fd;
102 void dhcp_init(void)
104 #if defined(HAVE_BSD_NETWORK)
105 int oneopt = 1;
106 #endif
108 daemon->dhcpfd = make_fd(daemon->dhcp_server_port);
109 if (daemon->enable_pxe)
110 daemon->pxefd = make_fd(PXE_PORT);
111 else
112 daemon->pxefd = -1;
114 #if defined(HAVE_BSD_NETWORK)
115 /* When we're not using capabilities, we need to do this here before
116 we drop root. Also, set buffer size small, to avoid wasting
117 kernel buffers */
119 if (option_bool(OPT_NO_PING))
120 daemon->dhcp_icmp_fd = -1;
121 else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
122 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
123 die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
125 /* Make BPF raw send socket */
126 init_bpf();
127 #endif
130 void dhcp_packet(time_t now, int pxe_fd)
132 int fd = pxe_fd ? daemon->pxefd : daemon->dhcpfd;
133 struct dhcp_packet *mess;
134 struct dhcp_context *context;
135 struct iname *tmp;
136 struct ifreq ifr;
137 struct msghdr msg;
138 struct sockaddr_in dest;
139 struct cmsghdr *cmptr;
140 struct iovec iov;
141 ssize_t sz;
142 int iface_index = 0, unicast_dest = 0, is_inform = 0;
143 struct in_addr iface_addr;
144 struct iface_param parm;
145 #ifdef HAVE_LINUX_NETWORK
146 struct arpreq arp_req;
147 #endif
149 union {
150 struct cmsghdr align; /* this ensures alignment */
151 #if defined(HAVE_LINUX_NETWORK)
152 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
153 #elif defined(HAVE_SOLARIS_NETWORK)
154 char control[CMSG_SPACE(sizeof(unsigned int))];
155 #elif defined(HAVE_BSD_NETWORK)
156 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
157 #endif
158 } control_u;
159 struct dhcp_bridge *bridge, *alias;
161 msg.msg_controllen = sizeof(control_u);
162 msg.msg_control = control_u.control;
163 msg.msg_name = &dest;
164 msg.msg_namelen = sizeof(dest);
165 msg.msg_iov = &daemon->dhcp_packet;
166 msg.msg_iovlen = 1;
168 if ((sz = recv_dhcp_packet(fd, &msg)) == -1 ||
169 (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))))
170 return;
172 #if defined (HAVE_LINUX_NETWORK)
173 if (msg.msg_controllen >= sizeof(struct cmsghdr))
174 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
175 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
177 union {
178 unsigned char *c;
179 struct in_pktinfo *p;
180 } p;
181 p.c = CMSG_DATA(cmptr);
182 iface_index = p.p->ipi_ifindex;
183 if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
184 unicast_dest = 1;
187 #elif defined(HAVE_BSD_NETWORK)
188 if (msg.msg_controllen >= sizeof(struct cmsghdr))
189 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
190 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
192 union {
193 unsigned char *c;
194 struct sockaddr_dl *s;
195 } p;
196 p.c = CMSG_DATA(cmptr);
197 iface_index = p.s->sdl_index;
200 #elif defined(HAVE_SOLARIS_NETWORK)
201 if (msg.msg_controllen >= sizeof(struct cmsghdr))
202 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
203 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
205 union {
206 unsigned char *c;
207 unsigned int *i;
208 } p;
209 p.c = CMSG_DATA(cmptr);
210 iface_index = *(p.i);
212 #endif
214 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
215 return;
217 #ifdef HAVE_LINUX_NETWORK
218 /* ARP fiddling uses original interface even if we pretend to use a different one. */
219 strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
220 #endif
222 /* One form of bridging on BSD has the property that packets
223 can be recieved on bridge interfaces which do not have an IP address.
224 We allow these to be treated as aliases of another interface which does have
225 an IP address with --dhcp-bridge=interface,alias,alias */
226 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
228 for (alias = bridge->alias; alias; alias = alias->next)
229 if (strncmp(ifr.ifr_name, alias->iface, IF_NAMESIZE) == 0)
231 if (!(iface_index = if_nametoindex(bridge->iface)))
233 my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);
234 return;
236 else
238 strncpy(ifr.ifr_name, bridge->iface, IF_NAMESIZE);
239 break;
243 if (alias)
244 break;
247 #ifdef MSG_BCAST
248 /* OpenBSD tells us when a packet was broadcast */
249 if (!(msg.msg_flags & MSG_BCAST))
250 unicast_dest = 1;
251 #endif
253 ifr.ifr_addr.sa_family = AF_INET;
254 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
255 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
256 else
258 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
259 return;
262 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
263 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
264 return;
266 /* unlinked contexts are marked by context->current == context */
267 for (context = daemon->dhcp; context; context = context->next)
268 context->current = context;
270 parm.current = NULL;
271 parm.ind = iface_index;
273 if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
275 /* If we failed to match the primary address of the interface, see if we've got a --listen-address
276 for a secondary */
277 struct match_param match;
279 match.matched = 0;
280 match.ind = iface_index;
282 if (!daemon->if_addrs ||
283 !iface_enumerate(AF_INET, &match, check_listen_addrs) ||
284 !match.matched)
285 return;
287 iface_addr = match.addr;
288 /* make sure secondary address gets priority in case
289 there is more than one address on the interface in the same subnet */
290 complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
293 if (!iface_enumerate(AF_INET, &parm, complete_context))
294 return;
296 lease_prune(NULL, now); /* lose any expired leases */
297 iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
298 now, unicast_dest, &is_inform, pxe_fd, iface_addr);
299 lease_update_file(now);
300 lease_update_dns(0);
302 if (iov.iov_len == 0)
303 return;
305 msg.msg_name = &dest;
306 msg.msg_namelen = sizeof(dest);
307 msg.msg_control = NULL;
308 msg.msg_controllen = 0;
309 msg.msg_iov = &iov;
310 iov.iov_base = daemon->dhcp_packet.iov_base;
312 /* packet buffer may have moved */
313 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
315 #ifdef HAVE_SOCKADDR_SA_LEN
316 dest.sin_len = sizeof(struct sockaddr_in);
317 #endif
319 if (pxe_fd)
321 if (mess->ciaddr.s_addr != 0)
322 dest.sin_addr = mess->ciaddr;
324 else if (mess->giaddr.s_addr)
326 /* Send to BOOTP relay */
327 dest.sin_port = htons(daemon->dhcp_server_port);
328 dest.sin_addr = mess->giaddr;
330 else if (mess->ciaddr.s_addr)
332 /* If the client's idea of its own address tallys with
333 the source address in the request packet, we believe the
334 source port too, and send back to that. If we're replying
335 to a DHCPINFORM, trust the source address always. */
336 if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
337 dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
339 dest.sin_port = htons(daemon->dhcp_client_port);
340 dest.sin_addr = mess->ciaddr;
343 #if defined(HAVE_LINUX_NETWORK)
344 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
345 mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
347 /* broadcast to 255.255.255.255 (or mac address invalid) */
348 struct in_pktinfo *pkt;
349 msg.msg_control = control_u.control;
350 msg.msg_controllen = sizeof(control_u);
351 cmptr = CMSG_FIRSTHDR(&msg);
352 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
353 pkt->ipi_ifindex = iface_index;
354 pkt->ipi_spec_dst.s_addr = 0;
355 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
356 cmptr->cmsg_level = IPPROTO_IP;
357 cmptr->cmsg_type = IP_PKTINFO;
358 dest.sin_addr.s_addr = INADDR_BROADCAST;
359 dest.sin_port = htons(daemon->dhcp_client_port);
361 else
363 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
364 struct sockaddr limits size to 14 bytes. */
365 dest.sin_addr = mess->yiaddr;
366 dest.sin_port = htons(daemon->dhcp_client_port);
367 memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
368 arp_req.arp_ha.sa_family = mess->htype;
369 memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
370 /* interface name already copied in */
371 arp_req.arp_flags = ATF_COM;
372 ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
374 #elif defined(HAVE_SOLARIS_NETWORK)
375 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
377 /* broadcast to 255.255.255.255 (or mac address invalid) */
378 dest.sin_addr.s_addr = INADDR_BROADCAST;
379 dest.sin_port = htons(daemon->dhcp_client_port);
380 /* note that we don't specify the interface here: that's done by the
381 IP_BOUND_IF sockopt lower down. */
383 else
385 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
386 Note that this only works for ethernet on solaris, because we use SIOCSARP
387 and not SIOCSXARP, which would be perfect, except that it returns ENXIO
388 mysteriously. Bah. Fall back to broadcast for other net types. */
389 struct arpreq req;
390 dest.sin_addr = mess->yiaddr;
391 dest.sin_port = htons(daemon->dhcp_client_port);
392 *((struct sockaddr_in *)&req.arp_pa) = dest;
393 req.arp_ha.sa_family = AF_UNSPEC;
394 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
395 req.arp_flags = ATF_COM;
396 ioctl(daemon->dhcpfd, SIOCSARP, &req);
398 #elif defined(HAVE_BSD_NETWORK)
399 else
401 send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
402 return;
404 #endif
406 #ifdef HAVE_SOLARIS_NETWORK
407 setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
408 #endif
410 while(sendmsg(fd, &msg, 0) == -1 && retry_send());
413 /* check against secondary interface addresses */
414 static int check_listen_addrs(struct in_addr local, int if_index, char *label,
415 struct in_addr netmask, struct in_addr broadcast, void *vparam)
417 struct match_param *param = vparam;
418 struct iname *tmp;
420 (void) label;
422 if (if_index == param->ind)
424 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
425 if ( tmp->addr.sa.sa_family == AF_INET &&
426 tmp->addr.in.sin_addr.s_addr == local.s_addr)
428 param->matched = 1;
429 param->addr = local;
430 param->netmask = netmask;
431 param->broadcast = broadcast;
432 break;
436 return 1;
439 /* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
440 of each interface (and any relay address) and does the following things:
442 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
443 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
444 3) Fills in local (this host) and router (this host or relay) addresses.
445 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
447 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
449 static int complete_context(struct in_addr local, int if_index, char *label,
450 struct in_addr netmask, struct in_addr broadcast, void *vparam)
452 struct dhcp_context *context;
453 struct iface_param *param = vparam;
455 (void)label;
457 for (context = daemon->dhcp; context; context = context->next)
459 if (!(context->flags & CONTEXT_NETMASK) &&
460 (is_same_net(local, context->start, netmask) ||
461 is_same_net(local, context->end, netmask)))
463 if (context->netmask.s_addr != netmask.s_addr &&
464 !(is_same_net(local, context->start, netmask) &&
465 is_same_net(local, context->end, netmask)))
467 strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
468 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
469 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
470 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
472 context->netmask = netmask;
475 if (context->netmask.s_addr != 0 &&
476 is_same_net(local, context->start, context->netmask) &&
477 is_same_net(local, context->end, context->netmask))
479 /* link it onto the current chain if we've not seen it before */
480 if (if_index == param->ind && context->current == context)
482 context->router = local;
483 context->local = local;
484 context->current = param->current;
485 param->current = context;
488 if (!(context->flags & CONTEXT_BRDCAST))
490 if (is_same_net(broadcast, context->start, context->netmask))
491 context->broadcast = broadcast;
492 else
493 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
498 return 1;
501 struct dhcp_context *address_available(struct dhcp_context *context,
502 struct in_addr taddr,
503 struct dhcp_netid *netids)
505 /* Check is an address is OK for this network, check all
506 possible ranges. Make sure that the address isn't in use
507 by the server itself. */
509 unsigned int start, end, addr = ntohl(taddr.s_addr);
510 struct dhcp_context *tmp;
512 for (tmp = context; tmp; tmp = tmp->current)
513 if (taddr.s_addr == context->router.s_addr)
514 return NULL;
516 for (tmp = context; tmp; tmp = tmp->current)
518 start = ntohl(tmp->start.s_addr);
519 end = ntohl(tmp->end.s_addr);
521 if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) &&
522 addr >= start &&
523 addr <= end &&
524 match_netid(tmp->filter, netids, 1))
525 return tmp;
528 return NULL;
531 struct dhcp_context *narrow_context(struct dhcp_context *context,
532 struct in_addr taddr,
533 struct dhcp_netid *netids)
535 /* We start of with a set of possible contexts, all on the current physical interface.
536 These are chained on ->current.
537 Here we have an address, and return the actual context correponding to that
538 address. Note that none may fit, if the address came a dhcp-host and is outside
539 any dhcp-range. In that case we return a static range if possible, or failing that,
540 any context on the correct subnet. (If there's more than one, this is a dodgy
541 configuration: maybe there should be a warning.) */
543 struct dhcp_context *tmp;
545 if (!(tmp = address_available(context, taddr, netids)))
547 for (tmp = context; tmp; tmp = tmp->current)
548 if (match_netid(tmp->filter, netids, 1) &&
549 is_same_net(taddr, tmp->start, tmp->netmask) &&
550 (tmp->flags & CONTEXT_STATIC))
551 break;
553 if (!tmp)
554 for (tmp = context; tmp; tmp = tmp->current)
555 if (match_netid(tmp->filter, netids, 1) &&
556 is_same_net(taddr, tmp->start, tmp->netmask) &&
557 !(tmp->flags & CONTEXT_PROXY))
558 break;
561 /* Only one context allowed now */
562 if (tmp)
563 tmp->current = NULL;
565 return tmp;
568 struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
570 struct dhcp_config *config;
572 for (config = configs; config; config = config->next)
573 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
574 return config;
576 return NULL;
579 int address_allocate(struct dhcp_context *context,
580 struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
581 struct dhcp_netid *netids, time_t now)
583 /* Find a free address: exclude anything in use and anything allocated to
584 a particular hwaddr/clientid/hostname in our configuration.
585 Try to return from contexts which match netids first. */
587 struct in_addr start, addr;
588 struct dhcp_context *c, *d;
589 int i, pass;
590 unsigned int j;
592 /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
593 dispersal even with similarly-valued "strings". */
594 for (j = 0, i = 0; i < hw_len; i++)
595 j += hwaddr[i] + (j << 6) + (j << 16) - j;
597 for (pass = 0; pass <= 1; pass++)
598 for (c = context; c; c = c->current)
599 if (c->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
600 continue;
601 else if (!match_netid(c->filter, netids, pass))
602 continue;
603 else
605 if (option_bool(OPT_CONSEC_ADDR))
606 /* seed is largest extant lease addr in this context */
607 start = lease_find_max_addr(c);
608 else
609 /* pick a seed based on hwaddr */
610 start.s_addr = htonl(ntohl(c->start.s_addr) +
611 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
613 /* iterate until we find a free address. */
614 addr = start;
616 do {
617 /* eliminate addresses in use by the server. */
618 for (d = context; d; d = d->current)
619 if (addr.s_addr == d->router.s_addr)
620 break;
622 /* Addresses which end in .255 and .0 are broken in Windows even when using
623 supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
624 then 192.168.0.255 is a valid IP address, but not for Windows as it's
625 in the class C range. See KB281579. We therefore don't allocate these
626 addresses to avoid hard-to-diagnose problems. Thanks Bill. */
627 if (!d &&
628 !lease_find_by_addr(addr) &&
629 !config_find_by_address(daemon->dhcp_conf, addr) &&
630 (!IN_CLASSC(ntohl(addr.s_addr)) ||
631 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
633 struct ping_result *r, *victim = NULL;
634 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
635 ((float)PING_WAIT)));
637 *addrp = addr;
639 /* check if we failed to ping addr sometime in the last
640 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
641 This avoids problems when a stupid client bangs
642 on us repeatedly. As a final check, if we did more
643 than 60% of the possible ping checks in the last
644 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
645 for (count = 0, r = daemon->ping_results; r; r = r->next)
646 if (difftime(now, r->time) > (float)PING_CACHE_TIME)
647 victim = r; /* old record */
648 else
650 count++;
651 if (r->addr.s_addr == addr.s_addr)
653 /* consec-ip mode: we offered this address for another client
654 (different hash) recently, don't offer it to this one. */
655 if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
656 break;
658 return 1;
662 if (!r)
664 if ((count < max) && !option_bool(OPT_NO_PING) && icmp_ping(addr))
666 /* address in use: perturb address selection so that we are
667 less likely to try this address again. */
668 if (!option_bool(OPT_CONSEC_ADDR))
669 c->addr_epoch++;
671 else
673 /* at this point victim may hold an expired record */
674 if (!victim)
676 if ((victim = whine_malloc(sizeof(struct ping_result))))
678 victim->next = daemon->ping_results;
679 daemon->ping_results = victim;
683 /* record that this address is OK for 30s
684 without more ping checks */
685 if (victim)
687 victim->addr = addr;
688 victim->time = now;
689 victim->hash = j;
691 return 1;
696 addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
698 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
699 addr = c->start;
701 } while (addr.s_addr != start.s_addr);
704 return 0;
707 static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config)
709 if (!context) /* called via find_config() from lease_update_from_configs() */
710 return 1;
711 if (!(config->flags & CONFIG_ADDR))
712 return 1;
713 for (; context; context = context->current)
714 if (is_same_net(config->addr, context->start, context->netmask))
715 return 1;
717 return 0;
720 int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
722 struct hwaddr_config *conf_addr;
724 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
725 if (conf_addr->wildcard_mask == 0 &&
726 conf_addr->hwaddr_len == len &&
727 (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
728 memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
729 return 1;
731 return 0;
734 struct dhcp_config *find_config(struct dhcp_config *configs,
735 struct dhcp_context *context,
736 unsigned char *clid, int clid_len,
737 unsigned char *hwaddr, int hw_len,
738 int hw_type, char *hostname)
740 int count, new;
741 struct dhcp_config *config, *candidate;
742 struct hwaddr_config *conf_addr;
744 if (clid)
745 for (config = configs; config; config = config->next)
746 if (config->flags & CONFIG_CLID)
748 if (config->clid_len == clid_len &&
749 memcmp(config->clid, clid, clid_len) == 0 &&
750 is_addr_in_context(context, config))
751 return config;
753 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
754 cope with that here */
755 if (*clid == 0 && config->clid_len == clid_len-1 &&
756 memcmp(config->clid, clid+1, clid_len-1) == 0 &&
757 is_addr_in_context(context, config))
758 return config;
762 for (config = configs; config; config = config->next)
763 if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
764 is_addr_in_context(context, config))
765 return config;
767 if (hostname && context)
768 for (config = configs; config; config = config->next)
769 if ((config->flags & CONFIG_NAME) &&
770 hostname_isequal(config->hostname, hostname) &&
771 is_addr_in_context(context, config))
772 return config;
774 /* use match with fewest wildcard octets */
775 for (candidate = NULL, count = 0, config = configs; config; config = config->next)
776 if (is_addr_in_context(context, config))
777 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
778 if (conf_addr->wildcard_mask != 0 &&
779 conf_addr->hwaddr_len == hw_len &&
780 (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
781 (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
783 count = new;
784 candidate = config;
787 return candidate;
790 void dhcp_read_ethers(void)
792 FILE *f = fopen(ETHERSFILE, "r");
793 unsigned int flags;
794 char *buff = daemon->namebuff;
795 char *ip, *cp;
796 struct in_addr addr;
797 unsigned char hwaddr[ETHER_ADDR_LEN];
798 struct dhcp_config **up, *tmp;
799 struct dhcp_config *config;
800 int count = 0, lineno = 0;
802 addr.s_addr = 0; /* eliminate warning */
804 if (!f)
806 my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
807 return;
810 /* This can be called again on SIGHUP, so remove entries created last time round. */
811 for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp)
813 tmp = config->next;
814 if (config->flags & CONFIG_FROM_ETHERS)
816 *up = tmp;
817 /* cannot have a clid */
818 if (config->flags & CONFIG_NAME)
819 free(config->hostname);
820 free(config->hwaddr);
821 free(config);
823 else
824 up = &config->next;
827 while (fgets(buff, MAXDNAME, f))
829 char *host = NULL;
831 lineno++;
833 while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
834 buff[strlen(buff)-1] = 0;
836 if ((*buff == '#') || (*buff == '+') || (*buff == 0))
837 continue;
839 for (ip = buff; *ip && !isspace((int)*ip); ip++);
840 for(; *ip && isspace((int)*ip); ip++)
841 *ip = 0;
842 if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
844 my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
845 continue;
848 /* check for name or dotted-quad */
849 for (cp = ip; *cp; cp++)
850 if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
851 break;
853 if (!*cp)
855 if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
857 my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
858 continue;
861 flags = CONFIG_ADDR;
863 for (config = daemon->dhcp_conf; config; config = config->next)
864 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
865 break;
867 else
869 int nomem;
870 if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
872 if (!nomem)
873 my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
874 free(host);
875 continue;
878 flags = CONFIG_NAME;
880 for (config = daemon->dhcp_conf; config; config = config->next)
881 if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
882 break;
885 if (config && (config->flags & CONFIG_FROM_ETHERS))
887 my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno);
888 continue;
891 if (!config)
893 for (config = daemon->dhcp_conf; config; config = config->next)
895 struct hwaddr_config *conf_addr = config->hwaddr;
896 if (conf_addr &&
897 conf_addr->next == NULL &&
898 conf_addr->wildcard_mask == 0 &&
899 conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
900 (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
901 memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
902 break;
905 if (!config)
907 if (!(config = whine_malloc(sizeof(struct dhcp_config))))
908 continue;
909 config->flags = CONFIG_FROM_ETHERS;
910 config->hwaddr = NULL;
911 config->domain = NULL;
912 config->netid = NULL;
913 config->next = daemon->dhcp_conf;
914 daemon->dhcp_conf = config;
917 config->flags |= flags;
919 if (flags & CONFIG_NAME)
921 config->hostname = host;
922 host = NULL;
925 if (flags & CONFIG_ADDR)
926 config->addr = addr;
929 config->flags |= CONFIG_NOCLID;
930 if (!config->hwaddr)
931 config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
932 if (config->hwaddr)
934 memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
935 config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
936 config->hwaddr->hwaddr_type = ARPHRD_ETHER;
937 config->hwaddr->wildcard_mask = 0;
938 config->hwaddr->next = NULL;
940 count++;
942 free(host);
946 fclose(f);
948 my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
952 /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
953 for this address. If it has a domain part, that must match the set domain and
954 it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
955 so check here that the domain name is legal as a hostname.
956 NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
957 char *host_from_dns(struct in_addr addr)
959 struct crec *lookup;
961 if (daemon->port == 0)
962 return NULL; /* DNS disabled. */
964 lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
966 if (lookup && (lookup->flags & F_HOSTS))
968 char *dot, *hostname = cache_get_name(lookup);
969 dot = strchr(hostname, '.');
971 if (dot && strlen(dot+1) != 0)
973 char *d2 = get_domain(addr);
974 if (!d2 || !hostname_isequal(dot+1, d2))
975 return NULL; /* wrong domain */
978 if (!legal_hostname(hostname))
979 return NULL;
981 strncpy(daemon->dhcp_buff, hostname, 256);
982 daemon->dhcp_buff[255] = 0;
983 strip_hostname(daemon->dhcp_buff);
985 return daemon->dhcp_buff;
988 return NULL;
991 #endif