blob: 335fc040adceaa9ed4e8d1ed63c2aa67220b4b11 [file] [log] [blame]
San Mehatffd68722010-01-20 09:56:15 -08001/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2
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.
7
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.
12
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/>.
15*/
16
17#include "dnsmasq.h"
18
19#ifdef HAVE_DHCP
20
21struct iface_param {
22 struct in_addr relay, primary;
23 struct dhcp_context *current;
24 int ind;
25};
26
27static int complete_context(struct in_addr local, int if_index,
28 struct in_addr netmask, struct in_addr broadcast, void *vparam);
29
30void dhcp_init(void)
31{
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
38
39 if (fd == -1)
40 die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
41
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);
53
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)
58 {
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);
66 }
67
68 memset(&saddr, 0, sizeof(saddr));
69 saddr.sin_family = AF_INET;
70 saddr.sin_port = htons(daemon->dhcp_server_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
75
76 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
77 die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);
78
79 daemon->dhcpfd = fd;
80
81#if defined(HAVE_BSD_NETWORK)
82 /* When we're not using capabilities, we need to do this here before
83 we drop root. Also, set buffer size small, to avoid wasting
84 kernel buffers */
85
86 if (daemon->options & OPT_NO_PING)
87 daemon->dhcp_icmp_fd = -1;
88 else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
89 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
90 die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
91
92 /* Make BPF raw send socket */
93 init_bpf();
94#endif
95
96 check_dhcp_hosts(1);
97
98 daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet);
99 daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
100}
101
102void dhcp_packet(time_t now)
103{
104 struct dhcp_packet *mess;
105 struct dhcp_context *context;
106 struct iname *tmp;
107 struct ifreq ifr;
108 struct msghdr msg;
109 struct sockaddr_in dest;
110 struct cmsghdr *cmptr;
111 struct iovec iov;
112 ssize_t sz;
113 int iface_index = 0, unicast_dest = 0, is_inform = 0;
114 struct in_addr iface_addr, *addrp = NULL;
115 struct iface_param parm;
116
117 union {
118 struct cmsghdr align; /* this ensures alignment */
119#if defined(HAVE_LINUX_NETWORK)
120 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
121#elif defined(HAVE_SOLARIS_NETWORK)
122 char control[CMSG_SPACE(sizeof(unsigned int))];
123#elif defined(HAVE_BSD_NETWORK)
124 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
125#endif
126 } control_u;
127
128 msg.msg_control = NULL;
129 msg.msg_controllen = 0;
130 msg.msg_name = NULL;
131 msg.msg_namelen = 0;
132 msg.msg_iov = &daemon->dhcp_packet;
133 msg.msg_iovlen = 1;
134
135 while (1)
136 {
137 msg.msg_flags = 0;
138 while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
139
140 if (sz == -1)
141 return;
142
143 if (!(msg.msg_flags & MSG_TRUNC))
144 break;
145
146 /* Very new Linux kernels return the actual size needed,
147 older ones always return truncated size */
148 if ((size_t)sz == daemon->dhcp_packet.iov_len)
149 {
150 if (!expand_buf(&daemon->dhcp_packet, sz + 100))
151 return;
152 }
153 else
154 {
155 expand_buf(&daemon->dhcp_packet, sz);
156 break;
157 }
158 }
159
160 /* expand_buf may have moved buffer */
161 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
162 msg.msg_controllen = sizeof(control_u);
163 msg.msg_control = control_u.control;
164 msg.msg_flags = 0;
165 msg.msg_name = &dest;
166 msg.msg_namelen = sizeof(dest);
167
168 while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) == -1 && errno == EINTR);
169
170 if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
171 return;
172
173#if defined (HAVE_LINUX_NETWORK)
174 if (msg.msg_controllen >= sizeof(struct cmsghdr))
175 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
176 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
177 {
178 iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
179 if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
180 unicast_dest = 1;
181 }
182
183#elif defined(HAVE_BSD_NETWORK)
184 if (msg.msg_controllen >= sizeof(struct cmsghdr))
185 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
186 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
187 iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
188
189
190#elif defined(HAVE_SOLARIS_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 == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
194 iface_index = *((unsigned int *)CMSG_DATA(cmptr));
195
196#endif
197
198 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
199 return;
200
201#ifdef MSG_BCAST
202 /* OpenBSD tells us when a packet was broadcast */
203 if (!(msg.msg_flags & MSG_BCAST))
204 unicast_dest = 1;
205#endif
206
207 ifr.ifr_addr.sa_family = AF_INET;
208 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
209 {
210 addrp = &iface_addr;
211 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
212 }
213
214 if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index))
215 return;
216
217 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
218 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
219 return;
220
221 /* interface may have been changed by alias in iface_check */
222 if (!addrp)
223 {
224 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
225 {
226 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
227 return;
228 }
229 else
230 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
231 }
232
233 /* unlinked contexts are marked by context->current == context */
234 for (context = daemon->dhcp; context; context = context->next)
235 context->current = context;
236
237 parm.relay = mess->giaddr;
238 parm.primary = iface_addr;
239 parm.current = NULL;
240 parm.ind = iface_index;
241
242 if (!iface_enumerate(&parm, complete_context, NULL))
243 return;
244 lease_prune(NULL, now); /* lose any expired leases */
245 iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
246 now, unicast_dest, &is_inform);
247 lease_update_file(now);
248 lease_update_dns();
249
250 if (iov.iov_len == 0)
251 return;
252
253 msg.msg_name = &dest;
254 msg.msg_namelen = sizeof(dest);
255 msg.msg_control = NULL;
256 msg.msg_controllen = 0;
257 msg.msg_iov = &iov;
258 iov.iov_base = daemon->dhcp_packet.iov_base;
259
260 /* packet buffer may have moved */
261 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
262
263#ifdef HAVE_SOCKADDR_SA_LEN
264 dest.sin_len = sizeof(struct sockaddr_in);
265#endif
266
267 if (mess->giaddr.s_addr)
268 {
269 /* Send to BOOTP relay */
270 dest.sin_port = htons(daemon->dhcp_server_port);
271 dest.sin_addr = mess->giaddr;
272 }
273 else if (mess->ciaddr.s_addr)
274 {
275 /* If the client's idea of its own address tallys with
276 the source address in the request packet, we believe the
277 source port too, and send back to that. If we're replying
278 to a DHCPINFORM, trust the source address always. */
279 if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
280 dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
281 {
282 dest.sin_port = htons(daemon->dhcp_client_port);
283 dest.sin_addr = mess->ciaddr;
284 }
285 }
286#if defined(HAVE_LINUX_NETWORK)
287 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
288 mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
289 {
290 /* broadcast to 255.255.255.255 (or mac address invalid) */
291 struct in_pktinfo *pkt;
292 msg.msg_control = control_u.control;
293 msg.msg_controllen = sizeof(control_u);
294 cmptr = CMSG_FIRSTHDR(&msg);
295 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
296 pkt->ipi_ifindex = iface_index;
297 pkt->ipi_spec_dst.s_addr = 0;
298 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
299 cmptr->cmsg_level = SOL_IP;
300 cmptr->cmsg_type = IP_PKTINFO;
301 dest.sin_addr.s_addr = INADDR_BROADCAST;
302 dest.sin_port = htons(daemon->dhcp_client_port);
303 }
304 else
305 {
306 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
307 struct sockaddr limits size to 14 bytes. */
308 struct arpreq req;
309 dest.sin_addr = mess->yiaddr;
310 dest.sin_port = htons(daemon->dhcp_client_port);
311 *((struct sockaddr_in *)&req.arp_pa) = dest;
312 req.arp_ha.sa_family = mess->htype;
313 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
314 strncpy(req.arp_dev, ifr.ifr_name, 16);
315 req.arp_flags = ATF_COM;
316 ioctl(daemon->dhcpfd, SIOCSARP, &req);
317 }
318#elif defined(HAVE_SOLARIS_NETWORK)
319 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
320 {
321 /* broadcast to 255.255.255.255 (or mac address invalid) */
322 dest.sin_addr.s_addr = INADDR_BROADCAST;
323 dest.sin_port = htons(daemon->dhcp_client_port);
324 /* note that we don't specify the interface here: that's done by the
325 IP_BOUND_IF sockopt lower down. */
326 }
327 else
328 {
329 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
330 Note that this only works for ethernet on solaris, because we use SIOCSARP
331 and not SIOCSXARP, which would be perfect, except that it returns ENXIO
332 mysteriously. Bah. Fall back to broadcast for other net types. */
333 struct arpreq req;
334 dest.sin_addr = mess->yiaddr;
335 dest.sin_port = htons(daemon->dhcp_client_port);
336 *((struct sockaddr_in *)&req.arp_pa) = dest;
337 req.arp_ha.sa_family = AF_UNSPEC;
338 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
339 req.arp_flags = ATF_COM;
340 ioctl(daemon->dhcpfd, SIOCSARP, &req);
341 }
342#elif defined(HAVE_BSD_NETWORK)
343 else
344 {
345 send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
346 return;
347 }
348#endif
349
350#ifdef HAVE_SOLARIS_NETWORK
351 setsockopt(daemon->dhcpfd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
352#endif
353
354 while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
355}
356
357/* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
358 of each interface (and any relay address) and does the following things:
359
360 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
361 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
362 3) Fills in local (this host) and router (this host or relay) addresses.
363 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
364
365 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
366
367static int complete_context(struct in_addr local, int if_index,
368 struct in_addr netmask, struct in_addr broadcast, void *vparam)
369{
370 struct dhcp_context *context;
371 struct iface_param *param = vparam;
372
373 for (context = daemon->dhcp; context; context = context->next)
374 {
375 if (!(context->flags & CONTEXT_NETMASK) &&
376 (is_same_net(local, context->start, netmask) ||
377 is_same_net(local, context->end, netmask)))
378 {
379 if (context->netmask.s_addr != netmask.s_addr &&
380 !(is_same_net(local, context->start, netmask) &&
381 is_same_net(local, context->end, netmask)))
382 {
383 strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
384 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
385 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
386 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
387 }
388 context->netmask = netmask;
389 }
390
391 if (context->netmask.s_addr)
392 {
393 if (is_same_net(local, context->start, context->netmask) &&
394 is_same_net(local, context->end, context->netmask))
395 {
396 /* link it onto the current chain if we've not seen it before */
397 if (if_index == param->ind && context->current == context)
398 {
399 context->router = local;
400 context->local = local;
401 context->current = param->current;
402 param->current = context;
403 }
404
405 if (!(context->flags & CONTEXT_BRDCAST))
406 {
407 if (is_same_net(broadcast, context->start, context->netmask))
408 context->broadcast = broadcast;
409 else
410 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
411 }
412 }
413 else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask))
414 {
415 context->router = param->relay;
416 context->local = param->primary;
417 /* fill in missing broadcast addresses for relayed ranges */
418 if (!(context->flags & CONTEXT_BRDCAST))
419 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
420 }
421
422 }
423 }
424
425 return 1;
426}
427
428struct dhcp_context *address_available(struct dhcp_context *context,
429 struct in_addr taddr,
430 struct dhcp_netid *netids)
431{
432 /* Check is an address is OK for this network, check all
433 possible ranges. Make sure that the address isn't in use
434 by the server itself. */
435
436 unsigned int start, end, addr = ntohl(taddr.s_addr);
437 struct dhcp_context *tmp;
438
439 for (tmp = context; tmp; tmp = tmp->current)
440 if (taddr.s_addr == context->router.s_addr)
441 return NULL;
442
443 for (tmp = context; tmp; tmp = tmp->current)
444 {
445 start = ntohl(tmp->start.s_addr);
446 end = ntohl(tmp->end.s_addr);
447
448 if (!(tmp->flags & CONTEXT_STATIC) &&
449 addr >= start &&
450 addr <= end &&
451 match_netid(tmp->filter, netids, 1))
452 return tmp;
453 }
454
455 return NULL;
456}
457
458struct dhcp_context *narrow_context(struct dhcp_context *context,
459 struct in_addr taddr,
460 struct dhcp_netid *netids)
461{
462 /* We start of with a set of possible contexts, all on the current physical interface.
463 These are chained on ->current.
464 Here we have an address, and return the actual context correponding to that
465 address. Note that none may fit, if the address came a dhcp-host and is outside
466 any dhcp-range. In that case we return a static range if possible, or failing that,
467 any context on the correct subnet. (If there's more than one, this is a dodgy
468 configuration: maybe there should be a warning.) */
469
470 struct dhcp_context *tmp;
471
472 if (!(tmp = address_available(context, taddr, netids)))
473 {
474 for (tmp = context; tmp; tmp = tmp->current)
475 if (is_same_net(taddr, tmp->start, tmp->netmask) &&
476 (tmp->flags & CONTEXT_STATIC))
477 break;
478
479 if (!tmp)
480 for (tmp = context; tmp; tmp = tmp->current)
481 if (is_same_net(taddr, tmp->start, tmp->netmask))
482 break;
483 }
484
485 /* Only one context allowed now */
486 if (tmp)
487 tmp->current = NULL;
488
489 return tmp;
490}
491
492struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
493{
494 struct dhcp_config *config;
495
496 for (config = configs; config; config = config->next)
497 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
498 return config;
499
500 return NULL;
501}
502
503/* Is every member of check matched by a member of pool?
504 If tagnotneeded, untagged is OK */
505int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
506{
507 struct dhcp_netid *tmp1;
508
509 if (!check && !tagnotneeded)
510 return 0;
511
512 for (; check; check = check->next)
513 {
514 if (check->net[0] != '#')
515 {
516 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
517 if (strcmp(check->net, tmp1->net) == 0)
518 break;
519 if (!tmp1)
520 return 0;
521 }
522 else
523 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
524 if (strcmp((check->net)+1, tmp1->net) == 0)
525 return 0;
526 }
527 return 1;
528}
529
530int address_allocate(struct dhcp_context *context,
531 struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
532 struct dhcp_netid *netids, time_t now)
533{
534 /* Find a free address: exclude anything in use and anything allocated to
535 a particular hwaddr/clientid/hostname in our configuration.
536 Try to return from contexts which match netids first. */
537
538 struct in_addr start, addr;
539 struct dhcp_context *c, *d;
540 int i, pass;
541 unsigned int j;
542
543 /* hash hwaddr */
544 for (j = 0, i = 0; i < hw_len; i++)
545 j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
546
547 for (pass = 0; pass <= 1; pass++)
548 for (c = context; c; c = c->current)
549 if (c->flags & CONTEXT_STATIC)
550 continue;
551 else if (!match_netid(c->filter, netids, pass))
552 continue;
553 else
554 {
555 /* pick a seed based on hwaddr then iterate until we find a free address. */
556 start.s_addr = addr.s_addr =
557 htonl(ntohl(c->start.s_addr) +
558 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
559
560 do {
561 /* eliminate addresses in use by the server. */
562 for (d = context; d; d = d->current)
563 if (addr.s_addr == d->router.s_addr)
564 break;
565
566 /* Addresses which end in .255 and .0 are broken in Windows even when using
567 supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
568 then 192.168.0.255 is a valid IP address, but not for Windows as it's
569 in the class C range. See KB281579. We therefore don't allocate these
570 addresses to avoid hard-to-diagnose problems. Thanks Bill. */
571 if (!d &&
572 !lease_find_by_addr(addr) &&
573 !config_find_by_address(daemon->dhcp_conf, addr) &&
574 (!IN_CLASSC(ntohl(addr.s_addr)) ||
575 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
576 {
577 struct ping_result *r, *victim = NULL;
578 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
579 ((float)PING_WAIT)));
580
581 *addrp = addr;
582
583 if (daemon->options & OPT_NO_PING)
584 return 1;
585
586 /* check if we failed to ping addr sometime in the last
587 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
588 This avoids problems when a stupid client bangs
589 on us repeatedly. As a final check, if we did more
590 than 60% of the possible ping checks in the last
591 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
592 for (count = 0, r = daemon->ping_results; r; r = r->next)
593 if (difftime(now, r->time) > (float)PING_CACHE_TIME)
594 victim = r; /* old record */
595 else if (++count == max || r->addr.s_addr == addr.s_addr)
596 return 1;
597
598 if (icmp_ping(addr))
599 /* address in use: perturb address selection so that we are
600 less likely to try this address again. */
601 c->addr_epoch++;
602 else
603 {
604 /* at this point victim may hold an expired record */
605 if (!victim)
606 {
607 if ((victim = whine_malloc(sizeof(struct ping_result))))
608 {
609 victim->next = daemon->ping_results;
610 daemon->ping_results = victim;
611 }
612 }
613
614 /* record that this address is OK for 30s
615 without more ping checks */
616 if (victim)
617 {
618 victim->addr = addr;
619 victim->time = now;
620 }
621 return 1;
622 }
623 }
624
625 addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
626
627 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
628 addr = c->start;
629
630 } while (addr.s_addr != start.s_addr);
631 }
632 return 0;
633}
634
635static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config)
636{
637 if (!context) /* called via find_config() from lease_update_from_configs() */
638 return 1;
639 if (!(config->flags & CONFIG_ADDR))
640 return 1;
641 for (; context; context = context->current)
642 if (is_same_net(config->addr, context->start, context->netmask))
643 return 1;
644
645 return 0;
646}
647
648int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
649{
650 struct hwaddr_config *conf_addr;
651
652 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
653 if (conf_addr->wildcard_mask == 0 &&
654 conf_addr->hwaddr_len == len &&
655 (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
656 memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
657 return 1;
658
659 return 0;
660}
661
662struct dhcp_config *find_config(struct dhcp_config *configs,
663 struct dhcp_context *context,
664 unsigned char *clid, int clid_len,
665 unsigned char *hwaddr, int hw_len,
666 int hw_type, char *hostname)
667{
668 int count, new;
669 struct dhcp_config *config, *candidate;
670 struct hwaddr_config *conf_addr;
671
672 if (clid)
673 for (config = configs; config; config = config->next)
674 if (config->flags & CONFIG_CLID)
675 {
676 if (config->clid_len == clid_len &&
677 memcmp(config->clid, clid, clid_len) == 0 &&
678 is_addr_in_context(context, config))
679 return config;
680
681 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
682 cope with that here */
683 if (*clid == 0 && config->clid_len == clid_len-1 &&
684 memcmp(config->clid, clid+1, clid_len-1) == 0 &&
685 is_addr_in_context(context, config))
686 return config;
687 }
688
689
690 for (config = configs; config; config = config->next)
691 if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
692 is_addr_in_context(context, config))
693 return config;
694
695 if (hostname && context)
696 for (config = configs; config; config = config->next)
697 if ((config->flags & CONFIG_NAME) &&
698 hostname_isequal(config->hostname, hostname) &&
699 is_addr_in_context(context, config))
700 return config;
701
702 /* use match with fewest wildcast octets */
703 for (candidate = NULL, count = 0, config = configs; config; config = config->next)
704 if (is_addr_in_context(context, config))
705 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
706 if (conf_addr->wildcard_mask != 0 &&
707 conf_addr->hwaddr_len == hw_len &&
708 (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
709 (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
710 {
711 count = new;
712 candidate = config;
713 }
714
715 return candidate;
716}
717
718void dhcp_read_ethers(void)
719{
720 FILE *f = fopen(ETHERSFILE, "r");
721 unsigned int flags;
722 char *buff = daemon->namebuff;
723 char *ip, *cp;
724 struct in_addr addr;
725 unsigned char hwaddr[ETHER_ADDR_LEN];
726 struct dhcp_config **up, *tmp;
727 struct dhcp_config *config;
728 int count = 0, lineno = 0;
729
730 addr.s_addr = 0; /* eliminate warning */
731
732 if (!f)
733 {
734 my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
735 return;
736 }
737
738 /* This can be called again on SIGHUP, so remove entries created last time round. */
739 for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp)
740 {
741 tmp = config->next;
742 if (config->flags & CONFIG_FROM_ETHERS)
743 {
744 *up = tmp;
745 /* cannot have a clid */
746 if (config->flags & CONFIG_NAME)
747 free(config->hostname);
748 free(config->hwaddr);
749 free(config);
750 }
751 else
752 up = &config->next;
753 }
754
755 while (fgets(buff, MAXDNAME, f))
756 {
757 char *host = NULL;
758
759 lineno++;
760
761 while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
762 buff[strlen(buff)-1] = 0;
763
764 if ((*buff == '#') || (*buff == '+') || (*buff == 0))
765 continue;
766
767 for (ip = buff; *ip && !isspace((int)*ip); ip++);
768 for(; *ip && isspace((int)*ip); ip++)
769 *ip = 0;
770 if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
771 {
772 my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
773 continue;
774 }
775
776 /* check for name or dotted-quad */
777 for (cp = ip; *cp; cp++)
778 if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
779 break;
780
781 if (!*cp)
782 {
783 if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
784 {
785 my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
786 continue;
787 }
788
789 flags = CONFIG_ADDR;
790
791 for (config = daemon->dhcp_conf; config; config = config->next)
792 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
793 break;
794 }
795 else
796 {
797 int nomem;
798 if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
799 {
800 if (!nomem)
801 my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
802 free(host);
803 continue;
804 }
805
806 flags = CONFIG_NAME;
807
808 for (config = daemon->dhcp_conf; config; config = config->next)
809 if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
810 break;
811 }
812
813 if (config && (config->flags & CONFIG_FROM_ETHERS))
814 {
815 my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno);
816 continue;
817 }
818
819 if (!config)
820 {
821 for (config = daemon->dhcp_conf; config; config = config->next)
822 {
823 struct hwaddr_config *conf_addr = config->hwaddr;
824 if (conf_addr &&
825 conf_addr->next == NULL &&
826 conf_addr->wildcard_mask == 0 &&
827 conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
828 (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
829 memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
830 break;
831 }
832
833 if (!config)
834 {
835 if (!(config = whine_malloc(sizeof(struct dhcp_config))))
836 continue;
837 config->flags = CONFIG_FROM_ETHERS;
838 config->hwaddr = NULL;
839 config->domain = NULL;
840 config->next = daemon->dhcp_conf;
841 daemon->dhcp_conf = config;
842 }
843
844 config->flags |= flags;
845
846 if (flags & CONFIG_NAME)
847 {
848 config->hostname = host;
849 host = NULL;
850 }
851
852 if (flags & CONFIG_ADDR)
853 config->addr = addr;
854 }
855
856 config->flags |= CONFIG_NOCLID;
857 if (!config->hwaddr)
858 config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
859 if (config->hwaddr)
860 {
861 memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
862 config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
863 config->hwaddr->hwaddr_type = ARPHRD_ETHER;
864 config->hwaddr->wildcard_mask = 0;
865 config->hwaddr->next = NULL;
866 }
867 count++;
868
869 free(host);
870
871 }
872
873 fclose(f);
874
875 my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
876}
877
878void check_dhcp_hosts(int fatal)
879{
880 /* If the same IP appears in more than one host config, then DISCOVER
881 for one of the hosts will get the address, but REQUEST will be NAKed,
882 since the address is reserved by the other one -> protocol loop.
883 Also check that FQDNs match the domain we are using. */
884
885 struct dhcp_config *configs, *cp;
886
887 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
888 {
889 char *domain;
890
891 if ((configs->flags & DHOPT_BANK) || fatal)
892 {
893 for (cp = configs->next; cp; cp = cp->next)
894 if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
895 {
896 if (fatal)
897 die(_("duplicate IP address %s in dhcp-config directive."),
898 inet_ntoa(cp->addr), EC_BADCONF);
899 else
900 my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
901 inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
902 configs->flags &= ~CONFIG_ADDR;
903 }
904
905 /* split off domain part */
906 if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
907 configs->domain = domain;
908 }
909 }
910}
911
912void dhcp_update_configs(struct dhcp_config *configs)
913{
914 /* Some people like to keep all static IP addresses in /etc/hosts.
915 This goes through /etc/hosts and sets static addresses for any DHCP config
916 records which don't have an address and whose name matches.
917 We take care to maintain the invariant that any IP address can appear
918 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
919 restore the status-quo ante first. */
920
921 struct dhcp_config *config;
922 struct crec *crec;
923
924 for (config = configs; config; config = config->next)
925 if (config->flags & CONFIG_ADDR_HOSTS)
926 config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
927
928
929 if (daemon->port != 0)
930 for (config = configs; config; config = config->next)
931 if (!(config->flags & CONFIG_ADDR) &&
932 (config->flags & CONFIG_NAME) &&
933 (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
934 (crec->flags & F_HOSTS))
935 {
936 if (cache_find_by_name(crec, config->hostname, 0, F_IPV4))
937 {
938 /* use primary (first) address */
939 while (crec && !(crec->flags & F_REVERSE))
940 crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4);
941 if (!crec)
942 continue; /* should be never */
943 my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
944 config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
945 }
946
947 if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
948 my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
949 inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
950 else
951 {
952 config->addr = crec->addr.addr.addr.addr4;
953 config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
954 }
955 }
956}
957
958/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
959 for this address. If it has a domain part, that must match the set domain and
960 it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
961 so check here that the domain name is legal as a hostname. */
962char *host_from_dns(struct in_addr addr)
963{
964 struct crec *lookup;
965 char *hostname = NULL;
966 char *d1, *d2;
967
968 if (daemon->port == 0)
969 return NULL; /* DNS disabled. */
970
971 lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
972 if (lookup && (lookup->flags & F_HOSTS))
973 {
974 hostname = daemon->dhcp_buff;
975 strncpy(hostname, cache_get_name(lookup), 256);
976 hostname[255] = 0;
977 d1 = strip_hostname(hostname);
978 d2 = get_domain(addr);
979 if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
980 hostname = NULL;
981 }
982
983 return hostname;
984}
985
986/* return domain or NULL if none. */
987char *strip_hostname(char *hostname)
988{
989 char *dot = strchr(hostname, '.');
990
991 if (!dot)
992 return NULL;
993
994 *dot = 0; /* truncate */
995 if (strlen(dot+1) != 0)
996 return dot+1;
997
998 return NULL;
999}
1000
1001#endif
1002