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