dnsmasq: update to 2.73 (23.06.2015)
[tomato.git] / release / src / router / dnsmasq / src / dhcp.c
blobe6fceb13a3e1da9f1d104506f0279b0bfc3e3b27
1 /* dnsmasq is Copyright (c) 2000-2015 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 struct dhcp_relay *relay;
24 struct in_addr relay_local;
25 int ind;
28 struct match_param {
29 int ind, matched;
30 struct in_addr netmask, broadcast, addr;
33 static int complete_context(struct in_addr local, int if_index, char *label,
34 struct in_addr netmask, struct in_addr broadcast, void *vparam);
35 static int check_listen_addrs(struct in_addr local, int if_index, char *label,
36 struct in_addr netmask, struct in_addr broadcast, void *vparam);
37 static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index);
38 static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface);
40 static int make_fd(int port)
42 int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
43 struct sockaddr_in saddr;
44 int oneopt = 1;
45 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
46 int mtu = IP_PMTUDISC_DONT;
47 #endif
48 #if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
49 int tos = IPTOS_CLASS_CS6;
50 #endif
52 if (fd == -1)
53 die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
55 if (!fix_fd(fd) ||
56 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
57 setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 ||
58 #endif
59 #if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
60 setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1 ||
61 #endif
62 #if defined(HAVE_LINUX_NETWORK)
63 setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
64 #else
65 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
66 #endif
67 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
68 die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
70 /* When bind-interfaces is set, there might be more than one dnmsasq
71 instance binding port 67. That's OK if they serve different networks.
72 Need to set REUSEADDR|REUSEPORT to make this posible.
73 Handle the case that REUSEPORT is defined, but the kernel doesn't
74 support it. This handles the introduction of REUSEPORT on Linux. */
75 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
77 int rc = 0;
79 #ifdef SO_REUSEPORT
80 if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
81 errno == ENOPROTOOPT)
82 rc = 0;
83 #endif
85 if (rc != -1)
86 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
88 if (rc == -1)
89 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
92 memset(&saddr, 0, sizeof(saddr));
93 saddr.sin_family = AF_INET;
94 saddr.sin_port = htons(port);
95 saddr.sin_addr.s_addr = INADDR_ANY;
96 #ifdef HAVE_SOCKADDR_SA_LEN
97 saddr.sin_len = sizeof(struct sockaddr_in);
98 #endif
100 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
101 die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);
103 return fd;
106 void dhcp_init(void)
108 #if defined(HAVE_BSD_NETWORK)
109 int oneopt = 1;
110 #endif
112 daemon->dhcpfd = make_fd(daemon->dhcp_server_port);
113 if (daemon->enable_pxe)
114 daemon->pxefd = make_fd(PXE_PORT);
115 else
116 daemon->pxefd = -1;
118 #if defined(HAVE_BSD_NETWORK)
119 /* When we're not using capabilities, we need to do this here before
120 we drop root. Also, set buffer size small, to avoid wasting
121 kernel buffers */
123 if (option_bool(OPT_NO_PING))
124 daemon->dhcp_icmp_fd = -1;
125 else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
126 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
127 die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
129 /* Make BPF raw send socket */
130 init_bpf();
131 #endif
134 void dhcp_packet(time_t now, int pxe_fd)
136 int fd = pxe_fd ? daemon->pxefd : daemon->dhcpfd;
137 struct dhcp_packet *mess;
138 struct dhcp_context *context;
139 struct dhcp_relay *relay;
140 int is_relay_reply = 0;
141 struct iname *tmp;
142 struct ifreq ifr;
143 struct msghdr msg;
144 struct sockaddr_in dest;
145 struct cmsghdr *cmptr;
146 struct iovec iov;
147 ssize_t sz;
148 int iface_index = 0, unicast_dest = 0, is_inform = 0;
149 struct in_addr iface_addr;
150 struct iface_param parm;
151 #ifdef HAVE_LINUX_NETWORK
152 struct arpreq arp_req;
153 #endif
155 union {
156 struct cmsghdr align; /* this ensures alignment */
157 #if defined(HAVE_LINUX_NETWORK)
158 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
159 #elif defined(HAVE_SOLARIS_NETWORK)
160 char control[CMSG_SPACE(sizeof(unsigned int))];
161 #elif defined(HAVE_BSD_NETWORK)
162 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
163 #endif
164 } control_u;
165 struct dhcp_bridge *bridge, *alias;
167 msg.msg_controllen = sizeof(control_u);
168 msg.msg_control = control_u.control;
169 msg.msg_name = &dest;
170 msg.msg_namelen = sizeof(dest);
171 msg.msg_iov = &daemon->dhcp_packet;
172 msg.msg_iovlen = 1;
174 if ((sz = recv_dhcp_packet(fd, &msg)) == -1 ||
175 (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))))
176 return;
178 #if defined (HAVE_LINUX_NETWORK)
179 if (msg.msg_controllen >= sizeof(struct cmsghdr))
180 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
181 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
183 union {
184 unsigned char *c;
185 struct in_pktinfo *p;
186 } p;
187 p.c = CMSG_DATA(cmptr);
188 iface_index = p.p->ipi_ifindex;
189 if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
190 unicast_dest = 1;
193 #elif defined(HAVE_BSD_NETWORK)
194 if (msg.msg_controllen >= sizeof(struct cmsghdr))
195 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
196 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
198 union {
199 unsigned char *c;
200 struct sockaddr_dl *s;
201 } p;
202 p.c = CMSG_DATA(cmptr);
203 iface_index = p.s->sdl_index;
206 #elif defined(HAVE_SOLARIS_NETWORK)
207 if (msg.msg_controllen >= sizeof(struct cmsghdr))
208 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
209 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
211 union {
212 unsigned char *c;
213 unsigned int *i;
214 } p;
215 p.c = CMSG_DATA(cmptr);
216 iface_index = *(p.i);
218 #endif
220 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
221 return;
223 #ifdef HAVE_LINUX_NETWORK
224 /* ARP fiddling uses original interface even if we pretend to use a different one. */
225 strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
226 #endif
228 /* If the interface on which the DHCP request was received is an
229 alias of some other interface (as specified by the
230 --bridge-interface option), change ifr.ifr_name so that we look
231 for DHCP contexts associated with the aliased interface instead
232 of with the aliasing one. */
233 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
235 for (alias = bridge->alias; alias; alias = alias->next)
236 if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
238 if (!(iface_index = if_nametoindex(bridge->iface)))
240 my_syslog(MS_DHCP | LOG_WARNING,
241 _("unknown interface %s in bridge-interface"),
242 bridge->iface);
243 return;
245 else
247 strncpy(ifr.ifr_name, bridge->iface, IF_NAMESIZE);
248 break;
252 if (alias)
253 break;
256 #ifdef MSG_BCAST
257 /* OpenBSD tells us when a packet was broadcast */
258 if (!(msg.msg_flags & MSG_BCAST))
259 unicast_dest = 1;
260 #endif
262 if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
264 /* Reply from server, using us as relay. */
265 iface_index = relay->iface_index;
266 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
267 return;
268 is_relay_reply = 1;
269 iov.iov_len = sz;
270 #ifdef HAVE_LINUX_NETWORK
271 strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
272 #endif
274 else
276 ifr.ifr_addr.sa_family = AF_INET;
277 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
278 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
279 else
281 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
282 return;
285 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
286 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
287 return;
289 /* unlinked contexts/relays are marked by context->current == context */
290 for (context = daemon->dhcp; context; context = context->next)
291 context->current = context;
293 for (relay = daemon->relay4; relay; relay = relay->next)
294 relay->current = relay;
296 parm.current = NULL;
297 parm.relay = NULL;
298 parm.relay_local.s_addr = 0;
299 parm.ind = iface_index;
301 if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
303 /* If we failed to match the primary address of the interface, see if we've got a --listen-address
304 for a secondary */
305 struct match_param match;
307 match.matched = 0;
308 match.ind = iface_index;
310 if (!daemon->if_addrs ||
311 !iface_enumerate(AF_INET, &match, check_listen_addrs) ||
312 !match.matched)
313 return;
315 iface_addr = match.addr;
316 /* make sure secondary address gets priority in case
317 there is more than one address on the interface in the same subnet */
318 complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
321 if (!iface_enumerate(AF_INET, &parm, complete_context))
322 return;
324 /* We're relaying this request */
325 if (parm.relay_local.s_addr != 0 &&
326 relay_upstream4(parm.relay, (struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, iface_index))
327 return;
329 /* May have configured relay, but not DHCP server */
330 if (!daemon->dhcp)
331 return;
333 lease_prune(NULL, now); /* lose any expired leases */
334 iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
335 now, unicast_dest, &is_inform, pxe_fd, iface_addr);
336 lease_update_file(now);
337 lease_update_dns(0);
339 if (iov.iov_len == 0)
340 return;
343 msg.msg_name = &dest;
344 msg.msg_namelen = sizeof(dest);
345 msg.msg_control = NULL;
346 msg.msg_controllen = 0;
347 msg.msg_iov = &iov;
348 iov.iov_base = daemon->dhcp_packet.iov_base;
350 /* packet buffer may have moved */
351 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
353 #ifdef HAVE_SOCKADDR_SA_LEN
354 dest.sin_len = sizeof(struct sockaddr_in);
355 #endif
357 if (pxe_fd)
359 if (mess->ciaddr.s_addr != 0)
360 dest.sin_addr = mess->ciaddr;
362 else if (mess->giaddr.s_addr && !is_relay_reply)
364 /* Send to BOOTP relay */
365 dest.sin_port = htons(daemon->dhcp_server_port);
366 dest.sin_addr = mess->giaddr;
368 else if (mess->ciaddr.s_addr)
370 /* If the client's idea of its own address tallys with
371 the source address in the request packet, we believe the
372 source port too, and send back to that. If we're replying
373 to a DHCPINFORM, trust the source address always. */
374 if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
375 dest.sin_port == 0 || dest.sin_addr.s_addr == 0 || is_relay_reply)
377 dest.sin_port = htons(daemon->dhcp_client_port);
378 dest.sin_addr = mess->ciaddr;
381 #if defined(HAVE_LINUX_NETWORK)
382 else
384 /* fill cmsg for outbound interface (both broadcast & unicast) */
385 struct in_pktinfo *pkt;
386 msg.msg_control = control_u.control;
387 msg.msg_controllen = sizeof(control_u);
388 cmptr = CMSG_FIRSTHDR(&msg);
389 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
390 pkt->ipi_ifindex = iface_index;
391 pkt->ipi_spec_dst.s_addr = 0;
392 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
393 cmptr->cmsg_level = IPPROTO_IP;
394 cmptr->cmsg_type = IP_PKTINFO;
396 if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
397 mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
399 /* broadcast to 255.255.255.255 (or mac address invalid) */
400 dest.sin_addr.s_addr = INADDR_BROADCAST;
401 dest.sin_port = htons(daemon->dhcp_client_port);
403 else
405 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
406 struct sockaddr limits size to 14 bytes. */
407 dest.sin_addr = mess->yiaddr;
408 dest.sin_port = htons(daemon->dhcp_client_port);
409 memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
410 arp_req.arp_ha.sa_family = mess->htype;
411 memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
412 /* interface name already copied in */
413 arp_req.arp_flags = ATF_COM;
414 if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
415 my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
418 #elif defined(HAVE_SOLARIS_NETWORK)
419 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
421 /* broadcast to 255.255.255.255 (or mac address invalid) */
422 dest.sin_addr.s_addr = INADDR_BROADCAST;
423 dest.sin_port = htons(daemon->dhcp_client_port);
424 /* note that we don't specify the interface here: that's done by the
425 IP_BOUND_IF sockopt lower down. */
427 else
429 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
430 Note that this only works for ethernet on solaris, because we use SIOCSARP
431 and not SIOCSXARP, which would be perfect, except that it returns ENXIO
432 mysteriously. Bah. Fall back to broadcast for other net types. */
433 struct arpreq req;
434 dest.sin_addr = mess->yiaddr;
435 dest.sin_port = htons(daemon->dhcp_client_port);
436 *((struct sockaddr_in *)&req.arp_pa) = dest;
437 req.arp_ha.sa_family = AF_UNSPEC;
438 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
439 req.arp_flags = ATF_COM;
440 ioctl(daemon->dhcpfd, SIOCSARP, &req);
442 #elif defined(HAVE_BSD_NETWORK)
443 else
445 send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
446 return;
448 #endif
450 #ifdef HAVE_SOLARIS_NETWORK
451 setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
452 #endif
454 while(retry_send(sendmsg(fd, &msg, 0)));
457 /* check against secondary interface addresses */
458 static int check_listen_addrs(struct in_addr local, int if_index, char *label,
459 struct in_addr netmask, struct in_addr broadcast, void *vparam)
461 struct match_param *param = vparam;
462 struct iname *tmp;
464 (void) label;
466 if (if_index == param->ind)
468 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
469 if ( tmp->addr.sa.sa_family == AF_INET &&
470 tmp->addr.in.sin_addr.s_addr == local.s_addr)
472 param->matched = 1;
473 param->addr = local;
474 param->netmask = netmask;
475 param->broadcast = broadcast;
476 break;
480 return 1;
483 /* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
484 of each interface (and any relay address) and does the following things:
486 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
487 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
488 3) Fills in local (this host) and router (this host or relay) addresses.
489 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
491 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
493 static int complete_context(struct in_addr local, int if_index, char *label,
494 struct in_addr netmask, struct in_addr broadcast, void *vparam)
496 struct dhcp_context *context;
497 struct dhcp_relay *relay;
498 struct iface_param *param = vparam;
500 (void)label;
502 for (context = daemon->dhcp; context; context = context->next)
504 if (!(context->flags & CONTEXT_NETMASK) &&
505 (is_same_net(local, context->start, netmask) ||
506 is_same_net(local, context->end, netmask)))
508 if (context->netmask.s_addr != netmask.s_addr &&
509 !(is_same_net(local, context->start, netmask) &&
510 is_same_net(local, context->end, netmask)))
512 strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
513 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
514 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
515 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
517 context->netmask = netmask;
520 if (context->netmask.s_addr != 0 &&
521 is_same_net(local, context->start, context->netmask) &&
522 is_same_net(local, context->end, context->netmask))
524 /* link it onto the current chain if we've not seen it before */
525 if (if_index == param->ind && context->current == context)
527 context->router = local;
528 context->local = local;
529 context->current = param->current;
530 param->current = context;
533 if (!(context->flags & CONTEXT_BRDCAST))
535 if (is_same_net(broadcast, context->start, context->netmask))
536 context->broadcast = broadcast;
537 else
538 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
543 for (relay = daemon->relay4; relay; relay = relay->next)
544 if (if_index == param->ind && relay->local.addr.addr4.s_addr == local.s_addr && relay->current == relay &&
545 (param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr))
547 relay->current = param->relay;
548 param->relay = relay;
549 param->relay_local = local;
552 return 1;
555 struct dhcp_context *address_available(struct dhcp_context *context,
556 struct in_addr taddr,
557 struct dhcp_netid *netids)
559 /* Check is an address is OK for this network, check all
560 possible ranges. Make sure that the address isn't in use
561 by the server itself. */
563 unsigned int start, end, addr = ntohl(taddr.s_addr);
564 struct dhcp_context *tmp;
566 for (tmp = context; tmp; tmp = tmp->current)
567 if (taddr.s_addr == context->router.s_addr)
568 return NULL;
570 for (tmp = context; tmp; tmp = tmp->current)
572 start = ntohl(tmp->start.s_addr);
573 end = ntohl(tmp->end.s_addr);
575 if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) &&
576 addr >= start &&
577 addr <= end &&
578 match_netid(tmp->filter, netids, 1))
579 return tmp;
582 return NULL;
585 struct dhcp_context *narrow_context(struct dhcp_context *context,
586 struct in_addr taddr,
587 struct dhcp_netid *netids)
589 /* We start of with a set of possible contexts, all on the current physical interface.
590 These are chained on ->current.
591 Here we have an address, and return the actual context correponding to that
592 address. Note that none may fit, if the address came a dhcp-host and is outside
593 any dhcp-range. In that case we return a static range if possible, or failing that,
594 any context on the correct subnet. (If there's more than one, this is a dodgy
595 configuration: maybe there should be a warning.) */
597 struct dhcp_context *tmp;
599 if (!(tmp = address_available(context, taddr, netids)))
601 for (tmp = context; tmp; tmp = tmp->current)
602 if (match_netid(tmp->filter, netids, 1) &&
603 is_same_net(taddr, tmp->start, tmp->netmask) &&
604 (tmp->flags & CONTEXT_STATIC))
605 break;
607 if (!tmp)
608 for (tmp = context; tmp; tmp = tmp->current)
609 if (match_netid(tmp->filter, netids, 1) &&
610 is_same_net(taddr, tmp->start, tmp->netmask) &&
611 !(tmp->flags & CONTEXT_PROXY))
612 break;
615 /* Only one context allowed now */
616 if (tmp)
617 tmp->current = NULL;
619 return tmp;
622 struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
624 struct dhcp_config *config;
626 for (config = configs; config; config = config->next)
627 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
628 return config;
630 return NULL;
633 int address_allocate(struct dhcp_context *context,
634 struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
635 struct dhcp_netid *netids, time_t now)
637 /* Find a free address: exclude anything in use and anything allocated to
638 a particular hwaddr/clientid/hostname in our configuration.
639 Try to return from contexts which match netids first. */
641 struct in_addr start, addr;
642 struct dhcp_context *c, *d;
643 int i, pass;
644 unsigned int j;
646 /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
647 dispersal even with similarly-valued "strings". */
648 for (j = 0, i = 0; i < hw_len; i++)
649 j += hwaddr[i] + (j << 6) + (j << 16) - j;
651 for (pass = 0; pass <= 1; pass++)
652 for (c = context; c; c = c->current)
653 if (c->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
654 continue;
655 else if (!match_netid(c->filter, netids, pass))
656 continue;
657 else
659 if (option_bool(OPT_CONSEC_ADDR))
660 /* seed is largest extant lease addr in this context */
661 start = lease_find_max_addr(c);
662 else
663 /* pick a seed based on hwaddr */
664 start.s_addr = htonl(ntohl(c->start.s_addr) +
665 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
667 /* iterate until we find a free address. */
668 addr = start;
670 do {
671 /* eliminate addresses in use by the server. */
672 for (d = context; d; d = d->current)
673 if (addr.s_addr == d->router.s_addr)
674 break;
676 /* Addresses which end in .255 and .0 are broken in Windows even when using
677 supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
678 then 192.168.0.255 is a valid IP address, but not for Windows as it's
679 in the class C range. See KB281579. We therefore don't allocate these
680 addresses to avoid hard-to-diagnose problems. Thanks Bill. */
681 if (!d &&
682 !lease_find_by_addr(addr) &&
683 !config_find_by_address(daemon->dhcp_conf, addr) &&
684 (!IN_CLASSC(ntohl(addr.s_addr)) ||
685 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
687 struct ping_result *r, *victim = NULL;
688 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
689 ((float)PING_WAIT)));
691 *addrp = addr;
693 /* check if we failed to ping addr sometime in the last
694 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
695 This avoids problems when a stupid client bangs
696 on us repeatedly. As a final check, if we did more
697 than 60% of the possible ping checks in the last
698 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
699 for (count = 0, r = daemon->ping_results; r; r = r->next)
700 if (difftime(now, r->time) > (float)PING_CACHE_TIME)
701 victim = r; /* old record */
702 else
704 count++;
705 if (r->addr.s_addr == addr.s_addr)
707 /* consec-ip mode: we offered this address for another client
708 (different hash) recently, don't offer it to this one. */
709 if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
710 break;
712 return 1;
716 if (!r)
718 if ((count < max) && !option_bool(OPT_NO_PING) && icmp_ping(addr))
720 /* address in use: perturb address selection so that we are
721 less likely to try this address again. */
722 if (!option_bool(OPT_CONSEC_ADDR))
723 c->addr_epoch++;
725 else
727 /* at this point victim may hold an expired record */
728 if (!victim)
730 if ((victim = whine_malloc(sizeof(struct ping_result))))
732 victim->next = daemon->ping_results;
733 daemon->ping_results = victim;
737 /* record that this address is OK for 30s
738 without more ping checks */
739 if (victim)
741 victim->addr = addr;
742 victim->time = now;
743 victim->hash = j;
745 return 1;
750 addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
752 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
753 addr = c->start;
755 } while (addr.s_addr != start.s_addr);
758 return 0;
761 void dhcp_read_ethers(void)
763 FILE *f = fopen(ETHERSFILE, "r");
764 unsigned int flags;
765 char *buff = daemon->namebuff;
766 char *ip, *cp;
767 struct in_addr addr;
768 unsigned char hwaddr[ETHER_ADDR_LEN];
769 struct dhcp_config **up, *tmp;
770 struct dhcp_config *config;
771 int count = 0, lineno = 0;
773 addr.s_addr = 0; /* eliminate warning */
775 if (!f)
777 my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
778 return;
781 /* This can be called again on SIGHUP, so remove entries created last time round. */
782 for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp)
784 tmp = config->next;
785 if (config->flags & CONFIG_FROM_ETHERS)
787 *up = tmp;
788 /* cannot have a clid */
789 if (config->flags & CONFIG_NAME)
790 free(config->hostname);
791 free(config->hwaddr);
792 free(config);
794 else
795 up = &config->next;
798 while (fgets(buff, MAXDNAME, f))
800 char *host = NULL;
802 lineno++;
804 while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
805 buff[strlen(buff)-1] = 0;
807 if ((*buff == '#') || (*buff == '+') || (*buff == 0))
808 continue;
810 for (ip = buff; *ip && !isspace((int)*ip); ip++);
811 for(; *ip && isspace((int)*ip); ip++)
812 *ip = 0;
813 if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
815 my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
816 continue;
819 /* check for name or dotted-quad */
820 for (cp = ip; *cp; cp++)
821 if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
822 break;
824 if (!*cp)
826 if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
828 my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
829 continue;
832 flags = CONFIG_ADDR;
834 for (config = daemon->dhcp_conf; config; config = config->next)
835 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
836 break;
838 else
840 int nomem;
841 if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
843 if (!nomem)
844 my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
845 free(host);
846 continue;
849 flags = CONFIG_NAME;
851 for (config = daemon->dhcp_conf; config; config = config->next)
852 if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
853 break;
856 if (config && (config->flags & CONFIG_FROM_ETHERS))
858 my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno);
859 continue;
862 if (!config)
864 for (config = daemon->dhcp_conf; config; config = config->next)
866 struct hwaddr_config *conf_addr = config->hwaddr;
867 if (conf_addr &&
868 conf_addr->next == NULL &&
869 conf_addr->wildcard_mask == 0 &&
870 conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
871 (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
872 memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
873 break;
876 if (!config)
878 if (!(config = whine_malloc(sizeof(struct dhcp_config))))
879 continue;
880 config->flags = CONFIG_FROM_ETHERS;
881 config->hwaddr = NULL;
882 config->domain = NULL;
883 config->netid = NULL;
884 config->next = daemon->dhcp_conf;
885 daemon->dhcp_conf = config;
888 config->flags |= flags;
890 if (flags & CONFIG_NAME)
892 config->hostname = host;
893 host = NULL;
896 if (flags & CONFIG_ADDR)
897 config->addr = addr;
900 config->flags |= CONFIG_NOCLID;
901 if (!config->hwaddr)
902 config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
903 if (config->hwaddr)
905 memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
906 config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
907 config->hwaddr->hwaddr_type = ARPHRD_ETHER;
908 config->hwaddr->wildcard_mask = 0;
909 config->hwaddr->next = NULL;
911 count++;
913 free(host);
917 fclose(f);
919 my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
923 /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
924 for this address. If it has a domain part, that must match the set domain and
925 it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
926 so check here that the domain name is legal as a hostname.
927 NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
928 char *host_from_dns(struct in_addr addr)
930 struct crec *lookup;
932 if (daemon->port == 0)
933 return NULL; /* DNS disabled. */
935 lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
937 if (lookup && (lookup->flags & F_HOSTS))
939 char *dot, *hostname = cache_get_name(lookup);
940 dot = strchr(hostname, '.');
942 if (dot && strlen(dot+1) != 0)
944 char *d2 = get_domain(addr);
945 if (!d2 || !hostname_isequal(dot+1, d2))
946 return NULL; /* wrong domain */
949 if (!legal_hostname(hostname))
950 return NULL;
952 strncpy(daemon->dhcp_buff, hostname, 256);
953 daemon->dhcp_buff[255] = 0;
954 strip_hostname(daemon->dhcp_buff);
956 return daemon->dhcp_buff;
959 return NULL;
962 static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index)
964 /* ->local is same value for all relays on ->current chain */
965 struct all_addr from;
967 if (mess->op != BOOTREQUEST)
968 return 0;
970 /* source address == relay address */
971 from.addr.addr4 = relay->local.addr.addr4;
973 /* already gatewayed ? */
974 if (mess->giaddr.s_addr)
976 /* if so check if by us, to stomp on loops. */
977 if (mess->giaddr.s_addr == relay->local.addr.addr4.s_addr)
978 return 1;
980 else
982 /* plug in our address */
983 mess->giaddr.s_addr = relay->local.addr.addr4.s_addr;
986 if ((mess->hops++) > 20)
987 return 1;
989 for (; relay; relay = relay->current)
991 union mysockaddr to;
993 to.sa.sa_family = AF_INET;
994 to.in.sin_addr = relay->server.addr.addr4;
995 to.in.sin_port = htons(daemon->dhcp_server_port);
997 send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
999 if (option_bool(OPT_LOG_OPTS))
1001 inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
1002 my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, inet_ntoa(relay->server.addr.addr4));
1005 /* Save this for replies */
1006 relay->iface_index = iface_index;
1009 return 1;
1013 static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface)
1015 struct dhcp_relay *relay;
1017 if (mess->giaddr.s_addr == 0 || mess->op != BOOTREPLY)
1018 return NULL;
1020 for (relay = daemon->relay4; relay; relay = relay->next)
1022 if (mess->giaddr.s_addr == relay->local.addr.addr4.s_addr)
1024 if (!relay->interface || wildcard_match(relay->interface, arrival_interface))
1025 return relay->iface_index != 0 ? relay : NULL;
1029 return NULL;
1032 #endif