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