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 check_dhcp_hosts(1);
87
88 daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet);
89 daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
90 }
91
dhcp_packet(time_t now)92 void dhcp_packet(time_t now)
93 {
94 struct dhcp_packet *mess;
95 struct dhcp_context *context;
96 struct iname *tmp;
97 struct ifreq ifr;
98 struct msghdr msg;
99 struct sockaddr_in dest;
100 struct cmsghdr *cmptr;
101 struct iovec iov;
102 ssize_t sz;
103 int iface_index = 0, unicast_dest = 0, is_inform = 0;
104 struct in_addr iface_addr, *addrp = NULL;
105 struct iface_param parm;
106
107 union {
108 struct cmsghdr align; /* this ensures alignment */
109 #if defined(HAVE_LINUX_NETWORK)
110 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
111 #endif
112 } control_u;
113
114 msg.msg_control = NULL;
115 msg.msg_controllen = 0;
116 msg.msg_name = NULL;
117 msg.msg_namelen = 0;
118 msg.msg_iov = &daemon->dhcp_packet;
119 msg.msg_iovlen = 1;
120
121 while (1)
122 {
123 msg.msg_flags = 0;
124 while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
125
126 if (sz == -1)
127 return;
128
129 if (!(msg.msg_flags & MSG_TRUNC))
130 break;
131
132 /* Very new Linux kernels return the actual size needed,
133 older ones always return truncated size */
134 if ((size_t)sz == daemon->dhcp_packet.iov_len)
135 {
136 if (!expand_buf(&daemon->dhcp_packet, sz + 100))
137 return;
138 }
139 else
140 {
141 expand_buf(&daemon->dhcp_packet, sz);
142 break;
143 }
144 }
145
146 /* expand_buf may have moved buffer */
147 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
148 msg.msg_controllen = sizeof(control_u);
149 msg.msg_control = control_u.control;
150 msg.msg_flags = 0;
151 msg.msg_name = &dest;
152 msg.msg_namelen = sizeof(dest);
153
154 while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) == -1 && errno == EINTR);
155
156 if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
157 return;
158
159 #if defined (HAVE_LINUX_NETWORK)
160 if (msg.msg_controllen >= sizeof(struct cmsghdr))
161 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
162 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
163 {
164 iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
165 if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
166 unicast_dest = 1;
167 }
168 #endif
169
170 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
171 return;
172
173 #ifdef MSG_BCAST
174 /* OpenBSD tells us when a packet was broadcast */
175 if (!(msg.msg_flags & MSG_BCAST))
176 unicast_dest = 1;
177 #endif
178
179 ifr.ifr_addr.sa_family = AF_INET;
180 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
181 {
182 addrp = &iface_addr;
183 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
184 }
185
186 if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index))
187 return;
188
189 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
190 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
191 return;
192
193 /* interface may have been changed by alias in iface_check */
194 if (!addrp)
195 {
196 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
197 {
198 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
199 return;
200 }
201 else
202 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
203 }
204
205 /* unlinked contexts are marked by context->current == context */
206 for (context = daemon->dhcp; context; context = context->next)
207 context->current = context;
208
209 parm.relay = mess->giaddr;
210 parm.primary = iface_addr;
211 parm.current = NULL;
212 parm.ind = iface_index;
213
214 if (!iface_enumerate(&parm, complete_context, NULL))
215 return;
216 lease_prune(NULL, now); /* lose any expired leases */
217 iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
218 now, unicast_dest, &is_inform);
219 lease_update_file(now);
220 lease_update_dns();
221
222 if (iov.iov_len == 0)
223 return;
224
225 msg.msg_name = &dest;
226 msg.msg_namelen = sizeof(dest);
227 msg.msg_control = NULL;
228 msg.msg_controllen = 0;
229 msg.msg_iov = &iov;
230 iov.iov_base = daemon->dhcp_packet.iov_base;
231
232 /* packet buffer may have moved */
233 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
234
235 #ifdef HAVE_SOCKADDR_SA_LEN
236 dest.sin_len = sizeof(struct sockaddr_in);
237 #endif
238
239 if (mess->giaddr.s_addr)
240 {
241 /* Send to BOOTP relay */
242 dest.sin_port = htons(daemon->dhcp_server_port);
243 dest.sin_addr = mess->giaddr;
244 }
245 else if (mess->ciaddr.s_addr)
246 {
247 /* If the client's idea of its own address tallys with
248 the source address in the request packet, we believe the
249 source port too, and send back to that. If we're replying
250 to a DHCPINFORM, trust the source address always. */
251 if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
252 dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
253 {
254 dest.sin_port = htons(daemon->dhcp_client_port);
255 dest.sin_addr = mess->ciaddr;
256 }
257 }
258 #if defined(HAVE_LINUX_NETWORK)
259 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
260 mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
261 {
262 /* broadcast to 255.255.255.255 (or mac address invalid) */
263 struct in_pktinfo *pkt;
264 msg.msg_control = control_u.control;
265 msg.msg_controllen = sizeof(control_u);
266 cmptr = CMSG_FIRSTHDR(&msg);
267 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
268 pkt->ipi_ifindex = iface_index;
269 pkt->ipi_spec_dst.s_addr = 0;
270 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
271 cmptr->cmsg_level = SOL_IP;
272 cmptr->cmsg_type = IP_PKTINFO;
273 dest.sin_addr.s_addr = INADDR_BROADCAST;
274 dest.sin_port = htons(daemon->dhcp_client_port);
275 }
276 else
277 {
278 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
279 struct sockaddr limits size to 14 bytes. */
280 struct arpreq req;
281 dest.sin_addr = mess->yiaddr;
282 dest.sin_port = htons(daemon->dhcp_client_port);
283 *((struct sockaddr_in *)&req.arp_pa) = dest;
284 req.arp_ha.sa_family = mess->htype;
285 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
286 strncpy(req.arp_dev, ifr.ifr_name, 16);
287 req.arp_flags = ATF_COM;
288 ioctl(daemon->dhcpfd, SIOCSARP, &req);
289 }
290 #endif
291
292 while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
293 }
294
295 /* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
296 of each interface (and any relay address) and does the following things:
297
298 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
299 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
300 3) Fills in local (this host) and router (this host or relay) addresses.
301 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
302
303 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
304
complete_context(struct in_addr local,int if_index,struct in_addr netmask,struct in_addr broadcast,void * vparam)305 static int complete_context(struct in_addr local, int if_index,
306 struct in_addr netmask, struct in_addr broadcast, void *vparam)
307 {
308 struct dhcp_context *context;
309 struct iface_param *param = vparam;
310
311 for (context = daemon->dhcp; context; context = context->next)
312 {
313 if (!(context->flags & CONTEXT_NETMASK) &&
314 (is_same_net(local, context->start, netmask) ||
315 is_same_net(local, context->end, netmask)))
316 {
317 if (context->netmask.s_addr != netmask.s_addr &&
318 !(is_same_net(local, context->start, netmask) &&
319 is_same_net(local, context->end, netmask)))
320 {
321 strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
322 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
323 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
324 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
325 }
326 context->netmask = netmask;
327 }
328
329 if (context->netmask.s_addr)
330 {
331 if (is_same_net(local, context->start, context->netmask) &&
332 is_same_net(local, context->end, context->netmask))
333 {
334 /* link it onto the current chain if we've not seen it before */
335 if (if_index == param->ind && context->current == context)
336 {
337 context->router = local;
338 context->local = local;
339 context->current = param->current;
340 param->current = context;
341 }
342
343 if (!(context->flags & CONTEXT_BRDCAST))
344 {
345 if (is_same_net(broadcast, context->start, context->netmask))
346 context->broadcast = broadcast;
347 else
348 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
349 }
350 }
351 else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask))
352 {
353 context->router = param->relay;
354 context->local = param->primary;
355 /* fill in missing broadcast addresses for relayed ranges */
356 if (!(context->flags & CONTEXT_BRDCAST))
357 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
358 }
359
360 }
361 }
362
363 return 1;
364 }
365
address_available(struct dhcp_context * context,struct in_addr taddr,struct dhcp_netid * netids)366 struct dhcp_context *address_available(struct dhcp_context *context,
367 struct in_addr taddr,
368 struct dhcp_netid *netids)
369 {
370 /* Check is an address is OK for this network, check all
371 possible ranges. Make sure that the address isn't in use
372 by the server itself. */
373
374 unsigned int start, end, addr = ntohl(taddr.s_addr);
375 struct dhcp_context *tmp;
376
377 for (tmp = context; tmp; tmp = tmp->current)
378 if (taddr.s_addr == context->router.s_addr)
379 return NULL;
380
381 for (tmp = context; tmp; tmp = tmp->current)
382 {
383 start = ntohl(tmp->start.s_addr);
384 end = ntohl(tmp->end.s_addr);
385
386 if (!(tmp->flags & CONTEXT_STATIC) &&
387 addr >= start &&
388 addr <= end &&
389 match_netid(tmp->filter, netids, 1))
390 return tmp;
391 }
392
393 return NULL;
394 }
395
narrow_context(struct dhcp_context * context,struct in_addr taddr,struct dhcp_netid * netids)396 struct dhcp_context *narrow_context(struct dhcp_context *context,
397 struct in_addr taddr,
398 struct dhcp_netid *netids)
399 {
400 /* We start of with a set of possible contexts, all on the current physical interface.
401 These are chained on ->current.
402 Here we have an address, and return the actual context correponding to that
403 address. Note that none may fit, if the address came a dhcp-host and is outside
404 any dhcp-range. In that case we return a static range if possible, or failing that,
405 any context on the correct subnet. (If there's more than one, this is a dodgy
406 configuration: maybe there should be a warning.) */
407
408 struct dhcp_context *tmp;
409
410 if (!(tmp = address_available(context, taddr, netids)))
411 {
412 for (tmp = context; tmp; tmp = tmp->current)
413 if (is_same_net(taddr, tmp->start, tmp->netmask) &&
414 (tmp->flags & CONTEXT_STATIC))
415 break;
416
417 if (!tmp)
418 for (tmp = context; tmp; tmp = tmp->current)
419 if (is_same_net(taddr, tmp->start, tmp->netmask))
420 break;
421 }
422
423 /* Only one context allowed now */
424 if (tmp)
425 tmp->current = NULL;
426
427 return tmp;
428 }
429
config_find_by_address(struct dhcp_config * configs,struct in_addr addr)430 struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
431 {
432 struct dhcp_config *config;
433
434 for (config = configs; config; config = config->next)
435 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
436 return config;
437
438 return NULL;
439 }
440
441 /* Is every member of check matched by a member of pool?
442 If tagnotneeded, untagged is OK */
match_netid(struct dhcp_netid * check,struct dhcp_netid * pool,int tagnotneeded)443 int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
444 {
445 struct dhcp_netid *tmp1;
446
447 if (!check && !tagnotneeded)
448 return 0;
449
450 for (; check; check = check->next)
451 {
452 if (check->net[0] != '#')
453 {
454 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
455 if (strcmp(check->net, tmp1->net) == 0)
456 break;
457 if (!tmp1)
458 return 0;
459 }
460 else
461 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
462 if (strcmp((check->net)+1, tmp1->net) == 0)
463 return 0;
464 }
465 return 1;
466 }
467
address_allocate(struct dhcp_context * context,struct in_addr * addrp,unsigned char * hwaddr,int hw_len,struct dhcp_netid * netids,time_t now)468 int address_allocate(struct dhcp_context *context,
469 struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
470 struct dhcp_netid *netids, time_t now)
471 {
472 /* Find a free address: exclude anything in use and anything allocated to
473 a particular hwaddr/clientid/hostname in our configuration.
474 Try to return from contexts which match netids first. */
475
476 struct in_addr start, addr;
477 struct dhcp_context *c, *d;
478 int i, pass;
479 unsigned int j;
480
481 /* hash hwaddr */
482 for (j = 0, i = 0; i < hw_len; i++)
483 j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
484
485 for (pass = 0; pass <= 1; pass++)
486 for (c = context; c; c = c->current)
487 if (c->flags & CONTEXT_STATIC)
488 continue;
489 else if (!match_netid(c->filter, netids, pass))
490 continue;
491 else
492 {
493 /* pick a seed based on hwaddr then iterate until we find a free address. */
494 start.s_addr = addr.s_addr =
495 htonl(ntohl(c->start.s_addr) +
496 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
497
498 do {
499 /* eliminate addresses in use by the server. */
500 for (d = context; d; d = d->current)
501 if (addr.s_addr == d->router.s_addr)
502 break;
503
504 /* Addresses which end in .255 and .0 are broken in Windows even when using
505 supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
506 then 192.168.0.255 is a valid IP address, but not for Windows as it's
507 in the class C range. See KB281579. We therefore don't allocate these
508 addresses to avoid hard-to-diagnose problems. Thanks Bill. */
509 if (!d &&
510 !lease_find_by_addr(addr) &&
511 !config_find_by_address(daemon->dhcp_conf, addr) &&
512 (!IN_CLASSC(ntohl(addr.s_addr)) ||
513 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
514 {
515 struct ping_result *r, *victim = NULL;
516 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
517 ((float)PING_WAIT)));
518
519 *addrp = addr;
520
521 if (daemon->options & OPT_NO_PING)
522 return 1;
523
524 /* check if we failed to ping addr sometime in the last
525 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
526 This avoids problems when a stupid client bangs
527 on us repeatedly. As a final check, if we did more
528 than 60% of the possible ping checks in the last
529 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
530 for (count = 0, r = daemon->ping_results; r; r = r->next)
531 if (difftime(now, r->time) > (float)PING_CACHE_TIME)
532 victim = r; /* old record */
533 else if (++count == max || r->addr.s_addr == addr.s_addr)
534 return 1;
535
536 if (icmp_ping(addr))
537 /* address in use: perturb address selection so that we are
538 less likely to try this address again. */
539 c->addr_epoch++;
540 else
541 {
542 /* at this point victim may hold an expired record */
543 if (!victim)
544 {
545 if ((victim = whine_malloc(sizeof(struct ping_result))))
546 {
547 victim->next = daemon->ping_results;
548 daemon->ping_results = victim;
549 }
550 }
551
552 /* record that this address is OK for 30s
553 without more ping checks */
554 if (victim)
555 {
556 victim->addr = addr;
557 victim->time = now;
558 }
559 return 1;
560 }
561 }
562
563 addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
564
565 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
566 addr = c->start;
567
568 } while (addr.s_addr != start.s_addr);
569 }
570 return 0;
571 }
572
is_addr_in_context(struct dhcp_context * context,struct dhcp_config * config)573 static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config)
574 {
575 if (!context) /* called via find_config() from lease_update_from_configs() */
576 return 1;
577 if (!(config->flags & CONFIG_ADDR))
578 return 1;
579 for (; context; context = context->current)
580 if (is_same_net(config->addr, context->start, context->netmask))
581 return 1;
582
583 return 0;
584 }
585
config_has_mac(struct dhcp_config * config,unsigned char * hwaddr,int len,int type)586 int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
587 {
588 struct hwaddr_config *conf_addr;
589
590 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
591 if (conf_addr->wildcard_mask == 0 &&
592 conf_addr->hwaddr_len == len &&
593 (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
594 memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
595 return 1;
596
597 return 0;
598 }
599
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)600 struct dhcp_config *find_config(struct dhcp_config *configs,
601 struct dhcp_context *context,
602 unsigned char *clid, int clid_len,
603 unsigned char *hwaddr, int hw_len,
604 int hw_type, char *hostname)
605 {
606 int count, new;
607 struct dhcp_config *config, *candidate;
608 struct hwaddr_config *conf_addr;
609
610 if (clid)
611 for (config = configs; config; config = config->next)
612 if (config->flags & CONFIG_CLID)
613 {
614 if (config->clid_len == clid_len &&
615 memcmp(config->clid, clid, clid_len) == 0 &&
616 is_addr_in_context(context, config))
617 return config;
618
619 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
620 cope with that here */
621 if (*clid == 0 && config->clid_len == clid_len-1 &&
622 memcmp(config->clid, clid+1, clid_len-1) == 0 &&
623 is_addr_in_context(context, config))
624 return config;
625 }
626
627
628 for (config = configs; config; config = config->next)
629 if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
630 is_addr_in_context(context, config))
631 return config;
632
633 if (hostname && context)
634 for (config = configs; config; config = config->next)
635 if ((config->flags & CONFIG_NAME) &&
636 hostname_isequal(config->hostname, hostname) &&
637 is_addr_in_context(context, config))
638 return config;
639
640 /* use match with fewest wildcast octets */
641 for (candidate = NULL, count = 0, config = configs; config; config = config->next)
642 if (is_addr_in_context(context, config))
643 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
644 if (conf_addr->wildcard_mask != 0 &&
645 conf_addr->hwaddr_len == hw_len &&
646 (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
647 (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
648 {
649 count = new;
650 candidate = config;
651 }
652
653 return candidate;
654 }
655
check_dhcp_hosts(int fatal)656 void check_dhcp_hosts(int fatal)
657 {
658 /* If the same IP appears in more than one host config, then DISCOVER
659 for one of the hosts will get the address, but REQUEST will be NAKed,
660 since the address is reserved by the other one -> protocol loop.
661 Also check that FQDNs match the domain we are using. */
662
663 struct dhcp_config *configs, *cp;
664
665 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
666 {
667 char *domain;
668
669 if ((configs->flags & DHOPT_BANK) || fatal)
670 {
671 for (cp = configs->next; cp; cp = cp->next)
672 if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
673 {
674 if (fatal)
675 die(_("duplicate IP address %s in dhcp-config directive."),
676 inet_ntoa(cp->addr), EC_BADCONF);
677 else
678 my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
679 inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
680 configs->flags &= ~CONFIG_ADDR;
681 }
682
683 /* split off domain part */
684 if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
685 configs->domain = domain;
686 }
687 }
688 }
689
dhcp_update_configs(struct dhcp_config * configs)690 void dhcp_update_configs(struct dhcp_config *configs)
691 {
692 /* Some people like to keep all static IP addresses in /etc/hosts.
693 This goes through /etc/hosts and sets static addresses for any DHCP config
694 records which don't have an address and whose name matches.
695 We take care to maintain the invariant that any IP address can appear
696 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
697 restore the status-quo ante first. */
698
699 struct dhcp_config *config;
700 struct crec *crec;
701
702 for (config = configs; config; config = config->next)
703 if (config->flags & CONFIG_ADDR_HOSTS)
704 config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
705
706
707 if (daemon->port != 0)
708 for (config = configs; config; config = config->next)
709 if (!(config->flags & CONFIG_ADDR) &&
710 (config->flags & CONFIG_NAME) &&
711 (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
712 (crec->flags & F_HOSTS))
713 {
714 if (cache_find_by_name(crec, config->hostname, 0, F_IPV4))
715 {
716 /* use primary (first) address */
717 while (crec && !(crec->flags & F_REVERSE))
718 crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4);
719 if (!crec)
720 continue; /* should be never */
721 my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
722 config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
723 }
724
725 if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
726 my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
727 inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
728 else
729 {
730 config->addr = crec->addr.addr.addr.addr4;
731 config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
732 }
733 }
734 }
735
736 /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
737 for this address. If it has a domain part, that must match the set domain and
738 it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
739 so check here that the domain name is legal as a hostname. */
host_from_dns(struct in_addr addr)740 char *host_from_dns(struct in_addr addr)
741 {
742 struct crec *lookup;
743 char *hostname = NULL;
744 char *d1, *d2;
745
746 if (daemon->port == 0)
747 return NULL; /* DNS disabled. */
748
749 lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
750 if (lookup && (lookup->flags & F_HOSTS))
751 {
752 hostname = daemon->dhcp_buff;
753 strncpy(hostname, cache_get_name(lookup), 256);
754 hostname[255] = 0;
755 d1 = strip_hostname(hostname);
756 d2 = get_domain(addr);
757 if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
758 hostname = NULL;
759 }
760
761 return hostname;
762 }
763
764 /* return domain or NULL if none. */
strip_hostname(char * hostname)765 char *strip_hostname(char *hostname)
766 {
767 char *dot = strchr(hostname, '.');
768
769 if (!dot)
770 return NULL;
771
772 *dot = 0; /* truncate */
773 if (strlen(dot+1) != 0)
774 return dot+1;
775
776 return NULL;
777 }
778
779 #endif
780
781