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