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