]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dhcp.c
import of dnsmasq-2.29.tar.gz
[people/ms/dnsmasq.git] / src / dhcp.c
CommitLineData
cdeda28f 1/* dnsmasq is Copyright (c) 2000-2006 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
5 the Free Software Foundation; version 2 dated June, 1991.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11*/
12
9e4abcb5
SK
13#include "dnsmasq.h"
14
5e9e0efb
SK
15struct iface_param {
16 struct in_addr relay, primary;
17 struct dhcp_context *current;
18 int ind;
19};
20
21static int complete_context(struct daemon *daemon, struct in_addr local, int if_index,
22 struct in_addr netmask, struct in_addr broadcast, void *vparam);
23
3be34541 24void dhcp_init(struct daemon *daemon)
44a2a316
SK
25{
26 int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
27 struct sockaddr_in saddr;
5e9e0efb 28 int flags, oneopt = 1;
3be34541 29 struct dhcp_config *configs, *cp;
dfa666f2 30
44a2a316 31 if (fd == -1)
b8187c80 32 die (_("cannot create DHCP socket : %s"), NULL);
44a2a316 33
fd9fa481
SK
34 if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
35 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
5e9e0efb 36#if defined(HAVE_LINUX_NETWORK)
3be34541 37 setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
44a2a316 38#elif defined(IP_RECVIF)
3be34541 39 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
44a2a316 40#endif
3be34541 41 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
b8187c80 42 die(_("failed to set options on DHCP socket: %s"), NULL);
44a2a316 43
f6b7dc47
SK
44 /* When bind-interfaces is set, there might be more than one dnmsasq
45 instance binding port 67. That's Ok if they serve different networks.
46 Need to set REUSEADDR to make this posible. */
47 if ((daemon->options & OPT_NOWILD) &&
48 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)) == -1)
b8187c80 49 die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL);
f6b7dc47 50
44a2a316
SK
51 saddr.sin_family = AF_INET;
52 saddr.sin_port = htons(DHCP_SERVER_PORT);
53 saddr.sin_addr.s_addr = INADDR_ANY;
3be34541
SK
54#ifdef HAVE_SOCKADDR_SA_LEN
55 saddr.sin_len = sizeof(struct sockaddr_in);
56#endif
57
44a2a316 58 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
b8187c80 59 die(_("failed to bind DHCP server socket: %s"), NULL);
44a2a316 60
3be34541
SK
61 daemon->dhcpfd = fd;
62
5e9e0efb
SK
63#ifndef HAVE_LINUX_NETWORK
64 /* When we're not using capabilities, we need to do this here before
65 we drop root. Also, set buffer size small, to avoid wasting
66 kernel buffers */
67
68 if (daemon->options & OPT_NO_PING)
69 daemon->dhcp_icmp_fd = -1;
70 else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
71 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
b8187c80 72 die(_("cannot create ICMP raw socket: %s."), NULL);
44a2a316 73
5e9e0efb
SK
74 /* Make BPF raw send socket */
75 init_bpf(daemon);
76#endif
3be34541 77
dfa666f2
SK
78 /* If the same IP appears in more than one host config, then DISCOVER
79 for one of the hosts will get the address, but REQUEST will be NAKed,
80 since the address is reserved by the other one -> protocol loop. */
3be34541 81 for (configs = daemon->dhcp_conf; configs; configs = configs->next)
dfa666f2
SK
82 for (cp = configs->next; cp; cp = cp->next)
83 if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
b8187c80 84 die(_("duplicate IP address %s in dhcp-config directive."), inet_ntoa(cp->addr));
3be34541 85
5e9e0efb
SK
86 daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet);
87 daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
88 /* These two each hold a DHCP option max size 255
3be34541 89 and get a terminating zero added */
0a852541
SK
90 daemon->dhcp_buff = safe_malloc(256);
91 daemon->dhcp_buff2 = safe_malloc(256);
3d8df260 92 daemon->ping_results = NULL;
44a2a316 93}
5e9e0efb 94
3be34541 95void dhcp_packet(struct daemon *daemon, time_t now)
9e4abcb5 96{
5e9e0efb 97 struct dhcp_packet *mess;
44a2a316
SK
98 struct dhcp_context *context;
99 struct iname *tmp;
100 struct ifreq ifr;
101 struct msghdr msg;
5e9e0efb 102 struct sockaddr_in dest;
44a2a316 103 struct cmsghdr *cmptr;
5e9e0efb
SK
104 struct iovec iov;
105 ssize_t sz;
cdeda28f 106 int iface_index = 0, unicast_dest = 0;
0a852541 107 struct in_addr iface_addr;
5e9e0efb 108 struct iface_param parm;
9e4abcb5 109
44a2a316
SK
110 union {
111 struct cmsghdr align; /* this ensures alignment */
5e9e0efb 112#ifdef HAVE_LINUX_NETWORK
44a2a316
SK
113 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
114#else
115 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
9e4abcb5 116#endif
44a2a316
SK
117 } control_u;
118
44a2a316
SK
119 msg.msg_control = control_u.control;
120 msg.msg_controllen = sizeof(control_u);
44a2a316
SK
121 msg.msg_name = NULL;
122 msg.msg_namelen = 0;
5e9e0efb 123 msg.msg_iov = &daemon->dhcp_packet;
44a2a316
SK
124 msg.msg_iovlen = 1;
125
5e9e0efb
SK
126 do
127 {
128 msg.msg_flags = 0;
129 while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
130 }
131 while (sz != -1 && (msg.msg_flags & MSG_TRUNC) &&
132 expand_buf(&daemon->dhcp_packet, daemon->dhcp_packet.iov_len + 100));
44a2a316 133
5e9e0efb
SK
134 /* expand_buf may have moved buffer */
135 mess = daemon->dhcp_packet.iov_base;
136 msg.msg_controllen = sizeof(control_u);
137 msg.msg_flags = 0;
138 msg.msg_name = &dest;
139 msg.msg_namelen = sizeof(dest);
140
141 while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) && errno == EINTR);
142
143 if ((msg.msg_flags & MSG_TRUNC) ||
144 sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
44a2a316
SK
145 return;
146
5e9e0efb 147#if defined (HAVE_LINUX_NETWORK)
44a2a316
SK
148 if (msg.msg_controllen < sizeof(struct cmsghdr))
149 return;
150 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
151 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
b8187c80
SK
152 {
153 iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
154 if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
155 unicast_dest = 1;
156 }
157
8a911ccc 158 if (!(ifr.ifr_ifindex = iface_index) ||
3be34541 159 ioctl(daemon->dhcpfd, SIOCGIFNAME, &ifr) == -1)
44a2a316 160 return;
b8187c80 161
44a2a316
SK
162#elif defined(IP_RECVIF)
163 if (msg.msg_controllen < sizeof(struct cmsghdr))
164 return;
165 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
166 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
167 iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
b8187c80 168
44a2a316
SK
169 if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
170 return;
171
172#else
3be34541
SK
173 {
174 struct iname *name;
fd9fa481 175 for (name = daemon->if_names; name->isloop; name = name->next);
3be34541 176 strcpy(ifr.ifr_name, name->name);
5e9e0efb 177 iface_index = if_nametoindex(name->name);
3be34541 178 }
9e4abcb5
SK
179#endif
180
44a2a316 181 ifr.ifr_addr.sa_family = AF_INET;
3be34541 182 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) < 0 )
44a2a316
SK
183 return;
184 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
185
3d8df260
SK
186 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
187 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
188 return;
44a2a316 189
5e9e0efb
SK
190 if (!iface_check(daemon, AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name))
191 return;
44a2a316 192
91dccd09 193 /* unlinked contexts are marked by context->current == context */
3be34541 194 for (context = daemon->dhcp; context; context = context->next)
91dccd09 195 context->current = context;
0a852541 196
5e9e0efb
SK
197 parm.relay = mess->giaddr;
198 parm.primary = iface_addr;
199 parm.current = NULL;
200 parm.ind = iface_index;
0a852541 201
5e9e0efb
SK
202 if (!iface_enumerate(daemon, &parm, complete_context, NULL))
203 return;
44a2a316 204 lease_prune(NULL, now); /* lose any expired leases */
5e9e0efb
SK
205 iov.iov_len = dhcp_reply(daemon, parm.current, ifr.ifr_name, (size_t)sz, now, unicast_dest);
206 lease_update_file(daemon);
fd9fa481 207 lease_update_dns(daemon);
44a2a316 208
5e9e0efb 209 if (iov.iov_len == 0)
44a2a316
SK
210 return;
211
5e9e0efb
SK
212 msg.msg_name = &dest;
213 msg.msg_namelen = sizeof(dest);
214 msg.msg_control = NULL;
215 msg.msg_controllen = 0;
216 msg.msg_iov = &iov;
217 iov.iov_base = daemon->dhcp_packet.iov_base;
218
219 /* packet buffer may have moved */
220 mess = daemon->dhcp_packet.iov_base;
221
3be34541 222#ifdef HAVE_SOCKADDR_SA_LEN
5e9e0efb 223 dest.sin_len = sizeof(struct sockaddr_in);
3be34541
SK
224#endif
225
5e9e0efb
SK
226 if (mess->giaddr.s_addr)
227 {
228 /* Send to BOOTP relay */
229 if (!dest.sin_port)
230 dest.sin_port = htons(DHCP_SERVER_PORT);
231 dest.sin_addr = mess->giaddr;
232 }
233 else if (mess->ciaddr.s_addr)
234 {
235 dest.sin_addr = mess->ciaddr;
236 if (!dest.sin_port)
237 dest.sin_port = htons(DHCP_CLIENT_PORT);
238 }
239#ifdef HAVE_LINUX_NETWORK
240 else if (ntohs(mess->flags) & 0x8000)
241 {
242 /* broadcast to 255.255.255.255 */
243 struct in_pktinfo *pkt;
244 msg.msg_controllen = sizeof(control_u);
245 cmptr = CMSG_FIRSTHDR(&msg);
246 dest.sin_addr.s_addr = INADDR_BROADCAST;
247 dest.sin_port = htons(DHCP_CLIENT_PORT);
248 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
249 pkt->ipi_ifindex = iface_index;
250 pkt->ipi_spec_dst.s_addr = 0;
251 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
252 cmptr->cmsg_level = SOL_IP;
253 cmptr->cmsg_type = IP_PKTINFO;
44a2a316
SK
254 }
255 else
256 {
5e9e0efb
SK
257 /* unicast to unconfigured client */
258 dest.sin_addr = mess->yiaddr;
259 dest.sin_port = htons(DHCP_CLIENT_PORT);
260 if (mess->hlen != 0 && mess->htype != 0)
261 arp_inject(daemon->netlinkfd, mess->yiaddr, iface_index,
262 mess->chaddr, mess->hlen);
263 }
44a2a316 264#else
5e9e0efb
SK
265 else
266 {
267 send_via_bpf(daemon, mess, iov.iov_len, iface_addr, &ifr);
268 return;
9e4abcb5 269 }
5e9e0efb
SK
270#endif
271
272 while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send());
9e4abcb5 273}
5e9e0efb 274
0a852541 275/* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
5e9e0efb
SK
276 of each interface (and any relay address) and does the following things:
277
278 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
279 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
280 3) Fills in local (this host) and router (this host or relay) addresses.
281 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
282
0a852541 283 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
5e9e0efb
SK
284
285static int complete_context(struct daemon *daemon, struct in_addr local, int if_index,
286 struct in_addr netmask, struct in_addr broadcast, void *vparam)
0a852541
SK
287{
288 struct dhcp_context *context;
5e9e0efb
SK
289 struct iface_param *param = vparam;
290
291 if (if_index != param->ind)
292 return 1; /* no for us. */
0a852541
SK
293
294 for (context = daemon->dhcp; context; context = context->next)
295 {
296 if (!(context->flags & CONTEXT_NETMASK) &&
297 (is_same_net(local, context->start, netmask) ||
298 is_same_net(local, context->end, netmask)))
299 {
300 if (context->netmask.s_addr != netmask.s_addr &&
301 !(is_same_net(local, context->start, netmask) &&
302 is_same_net(local, context->end, netmask)))
303 {
304 strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
305 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
b8187c80 306 syslog(LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
0a852541
SK
307 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
308 }
309 context->netmask = netmask;
310 }
311
312 if (context->netmask.s_addr)
313 {
314 if (is_same_net(local, context->start, context->netmask) &&
315 is_same_net(local, context->end, context->netmask))
316 {
91dccd09
SK
317 /* link it onto the current chain if we've not seen it before */
318 if (context->current == context)
0a852541
SK
319 {
320 context->router = local;
321 context->local = local;
5e9e0efb
SK
322 context->current = param->current;
323 param->current = context;
0a852541
SK
324 }
325
326 if (!(context->flags & CONTEXT_BRDCAST))
327 {
328 if (is_same_net(broadcast, context->start, context->netmask))
329 context->broadcast = broadcast;
330 else
331 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
332 }
333 }
5e9e0efb 334 else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask))
0a852541 335 {
5e9e0efb
SK
336 context->router = param->relay;
337 context->local = param->primary;
0a852541
SK
338 /* fill in missing broadcast addresses for relayed ranges */
339 if (!(context->flags & CONTEXT_BRDCAST))
340 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
341 }
342
343 }
344 }
345
5e9e0efb 346 return 1;
0a852541
SK
347}
348
59353a6b 349struct dhcp_context *address_available(struct dhcp_context *context, struct in_addr taddr)
9e4abcb5 350{
36717eee 351 /* Check is an address is OK for this network, check all
5e9e0efb
SK
352 possible ranges. Make sure that the address isn't in use
353 by the server itself. */
9e4abcb5 354
36717eee 355 unsigned int start, end, addr = ntohl(taddr.s_addr);
5e9e0efb
SK
356 struct dhcp_context *tmp;
357
358 for (tmp = context; tmp; tmp = tmp->current)
359 if (taddr.s_addr == context->local.s_addr)
360 return NULL;
9e4abcb5 361
5e9e0efb 362 for (tmp = context; tmp; tmp = tmp->current)
36717eee 363 {
5e9e0efb
SK
364 start = ntohl(tmp->start.s_addr);
365 end = ntohl(tmp->end.s_addr);
9e4abcb5 366
5e9e0efb 367 if (!(tmp->flags & CONTEXT_STATIC) &&
36717eee
SK
368 addr >= start &&
369 addr <= end)
5e9e0efb 370 return tmp;
36717eee 371 }
9e4abcb5 372
59353a6b 373 return NULL;
9e4abcb5 374}
59353a6b
SK
375
376struct dhcp_context *narrow_context(struct dhcp_context *context, struct in_addr taddr)
377{
e17fb629 378 /* We start of with a set of possible contexts, all on the current physical interface.
59353a6b
SK
379 These are chained on ->current.
380 Here we have an address, and return the actual context correponding to that
381 address. Note that none may fit, if the address came a dhcp-host and is outside
e17fb629
SK
382 any dhcp-range. In that case we return a static range if possible, or failing that,
383 any context on the correct subnet. (If there's more than one, this is a dodgy
384 configuration: maybe there should be a warning.) */
59353a6b 385
e17fb629 386 struct dhcp_context *tmp;
59353a6b 387
e17fb629 388 if ((tmp = address_available(context, taddr)))
59353a6b
SK
389 return tmp;
390
391 for (tmp = context; tmp; tmp = tmp->current)
e17fb629
SK
392 if (is_same_net(taddr, tmp->start, tmp->netmask) &&
393 (tmp->flags & CONTEXT_STATIC))
394 return tmp;
395
396 for (tmp = context; tmp; tmp = tmp->current)
397 if (is_same_net(taddr, tmp->start, tmp->netmask))
59353a6b
SK
398 return tmp;
399
e17fb629 400 return NULL;
59353a6b
SK
401}
402
dfa666f2
SK
403struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
404{
405 struct dhcp_config *config;
406
407 for (config = configs; config; config = config->next)
408 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
409 return config;
410
411 return NULL;
412}
9e4abcb5 413
cdeda28f
SK
414/* Is every member of check matched by a member of pool?
415 If negonly, match unless there's a negative tag which matches. */
416int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly)
f6b7dc47
SK
417{
418 struct dhcp_netid *tmp1;
419
cdeda28f 420 if (!check && !negonly)
f6b7dc47
SK
421 return 0;
422
423 for (; check; check = check->next)
424 {
425 if (check->net[0] != '#')
426 {
427 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
428 if (strcmp(check->net, tmp1->net) == 0)
429 break;
cdeda28f 430 if (!tmp1 || negonly)
f6b7dc47
SK
431 return 0;
432 }
433 else
434 for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
435 if (strcmp((check->net)+1, tmp1->net) == 0)
436 return 0;
437 }
438 return 1;
439}
440
3be34541 441int address_allocate(struct dhcp_context *context, struct daemon *daemon,
cdeda28f 442 struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
3d8df260 443 struct dhcp_netid *netids, time_t now)
9e4abcb5 444{
feba5c1d 445 /* Find a free address: exclude anything in use and anything allocated to
f6b7dc47 446 a particular hwaddr/clientid/hostname in our configuration.
cdeda28f 447 Try to return from contexts which match netids first. */
9e4abcb5 448
5e9e0efb
SK
449 struct in_addr start, addr;
450 struct dhcp_context *c, *d;
cdeda28f
SK
451 int i, pass;
452 unsigned int j;
453
5e9e0efb
SK
454 /* hash hwaddr */
455 for (j = 0, i = 0; i < hw_len; i++)
456 j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
457
cdeda28f
SK
458 for (pass = 0; pass <= 1; pass++)
459 for (c = context; c; c = c->current)
460 if (c->flags & CONTEXT_STATIC)
461 continue;
462 else if (!match_netid(c->filter, netids, pass))
463 continue;
464 else
465 {
466 /* pick a seed based on hwaddr then iterate until we find a free address. */
cdeda28f
SK
467 start.s_addr = addr.s_addr =
468 htonl(ntohl(c->start.s_addr) +
5e9e0efb 469 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
cdeda28f
SK
470
471 do {
5e9e0efb
SK
472 /* eliminate addresses in use by the server. */
473 for (d = context; d; d = d->current)
474 if (addr.s_addr == d->local.s_addr)
475 break;
476
477 if (!d &&
478 !lease_find_by_addr(addr) &&
cdeda28f
SK
479 !config_find_by_address(daemon->dhcp_conf, addr))
480 {
481 struct ping_result *r, *victim = NULL;
5e9e0efb
SK
482 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
483 ((float)PING_WAIT)));
484
485 *addrp = addr;
486
487 if (daemon->options & OPT_NO_PING)
488 return 1;
cdeda28f
SK
489
490 /* check if we failed to ping addr sometime in the last
5e9e0efb 491 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
cdeda28f 492 This avoids problems when a stupid client bangs
5e9e0efb
SK
493 on us repeatedly. As a final check, if we did more
494 than 60% of the possible ping checks in the last
495 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
cdeda28f 496 for (count = 0, r = daemon->ping_results; r; r = r->next)
5e9e0efb 497 if (difftime(now, r->time) > (float)PING_CACHE_TIME)
cdeda28f 498 victim = r; /* old record */
5e9e0efb
SK
499 else if (++count == max || r->addr.s_addr == addr.s_addr)
500 return 1;
501
cdeda28f
SK
502 if (icmp_ping(daemon, addr))
503 /* address in use: perturb address selection so that we are
504 less likely to try this address again. */
505 c->addr_epoch++;
506 else
3d8df260 507 {
cdeda28f
SK
508 /* at this point victim may hold an expired record */
509 if (!victim)
510 {
511 if ((victim = malloc(sizeof(struct ping_result))))
512 {
513 victim->next = daemon->ping_results;
514 daemon->ping_results = victim;
515 }
516 }
517
518 /* record that this address is OK for 30s
519 without more ping checks */
520 if (victim)
521 {
522 victim->addr = addr;
523 victim->time = now;
524 }
3d8df260
SK
525 return 1;
526 }
cdeda28f
SK
527 }
528
529 addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
530
531 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
532 addr = c->start;
533
534 } while (addr.s_addr != start.s_addr);
535 }
9e4abcb5
SK
536 return 0;
537}
538
539static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config)
540{
b8187c80 541 if (!context) /* called via find_config() from lease_update_from_configs() */
0a852541 542 return 1;
33820b7e 543 if (!(config->flags & CONFIG_ADDR))
9e4abcb5 544 return 1;
b8187c80
SK
545 for (; context; context = context->current)
546 if (is_same_net(config->addr, context->start, context->netmask))
547 return 1;
9e4abcb5
SK
548
549 return 0;
550}
551
0a852541 552
9e4abcb5
SK
553struct dhcp_config *find_config(struct dhcp_config *configs,
554 struct dhcp_context *context,
555 unsigned char *clid, int clid_len,
cdeda28f
SK
556 unsigned char *hwaddr, int hw_len,
557 int hw_type, char *hostname)
9e4abcb5
SK
558{
559 struct dhcp_config *config;
560
0a852541 561 if (clid)
9e4abcb5 562 for (config = configs; config; config = config->next)
33820b7e
SK
563 if (config->flags & CONFIG_CLID)
564 {
565 if (config->clid_len == clid_len &&
566 memcmp(config->clid, clid, clid_len) == 0 &&
567 is_addr_in_context(context, config))
568 return config;
569
570 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
571 cope with that here */
572 if (*clid == 0 && config->clid_len == clid_len-1 &&
573 memcmp(config->clid, clid+1, clid_len-1) == 0 &&
574 is_addr_in_context(context, config))
575 return config;
576 }
577
0a852541 578
cdeda28f
SK
579 for (config = configs; config; config = config->next)
580 if ((config->flags & CONFIG_HWADDR) &&
581 config->wildcard_mask == 0 &&
582 config->hwaddr_len == hw_len &&
583 (config->hwaddr_type == hw_type || config->hwaddr_type == 0) &&
584 memcmp(config->hwaddr, hwaddr, hw_len) == 0 &&
585 is_addr_in_context(context, config))
586 return config;
3d8df260 587
0a852541 588 if (hostname && context)
9e4abcb5 589 for (config = configs; config; config = config->next)
33820b7e
SK
590 if ((config->flags & CONFIG_NAME) &&
591 hostname_isequal(config->hostname, hostname) &&
9e4abcb5
SK
592 is_addr_in_context(context, config))
593 return config;
594
cdeda28f
SK
595 for (config = configs; config; config = config->next)
596 if ((config->flags & CONFIG_HWADDR) &&
597 config->wildcard_mask != 0 &&
598 config->hwaddr_len == hw_len &&
599 (config->hwaddr_type == hw_type || config->hwaddr_type == 0) &&
5e9e0efb
SK
600 is_addr_in_context(context, config) &&
601 memcmp_masked(config->hwaddr, hwaddr, hw_len, config->wildcard_mask))
602 return config;
603
9e4abcb5
SK
604 return NULL;
605}
606
3be34541 607void dhcp_read_ethers(struct daemon *daemon)
44a2a316
SK
608{
609 FILE *f = fopen(ETHERSFILE, "r");
0a852541 610 unsigned int flags;
3be34541 611 char *buff = daemon->namebuff;
33820b7e 612 char *ip, *cp;
44a2a316 613 struct in_addr addr;
33820b7e 614 unsigned char hwaddr[ETHER_ADDR_LEN];
3be34541 615 struct dhcp_config *config, *configs = daemon->dhcp_conf;
b8187c80 616 int count = 0, lineno = 0;
3d8df260
SK
617
618 addr.s_addr = 0; /* eliminate warning */
44a2a316
SK
619
620 if (!f)
33820b7e 621 {
b8187c80 622 syslog(LOG_ERR, _("failed to read %s:%m"), ETHERSFILE);
3be34541 623 return;
33820b7e
SK
624 }
625
44a2a316
SK
626 while (fgets(buff, MAXDNAME, f))
627 {
b8187c80
SK
628 lineno++;
629
33820b7e 630 while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
44a2a316
SK
631 buff[strlen(buff)-1] = 0;
632
633 if ((*buff == '#') || (*buff == '+'))
634 continue;
635
33820b7e
SK
636 for (ip = buff; *ip && !isspace(*ip); ip++);
637 for(; *ip && isspace(*ip); ip++)
44a2a316 638 *ip = 0;
cdeda28f 639 if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
b8187c80
SK
640 {
641 syslog(LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
642 continue;
643 }
44a2a316
SK
644
645 /* check for name or dotted-quad */
646 for (cp = ip; *cp; cp++)
647 if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
648 break;
649
650 if (!*cp)
651 {
44a2a316 652 if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
b8187c80
SK
653 {
654 syslog(LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
655 continue;
656 }
657
33820b7e 658 flags = CONFIG_ADDR;
1cff166d
SK
659
660 for (config = configs; config; config = config->next)
33820b7e 661 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
1cff166d 662 break;
44a2a316
SK
663 }
664 else
665 {
1cff166d 666 if (!canonicalise(ip))
b8187c80
SK
667 {
668 syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
669 continue;
670 }
671
33820b7e 672 flags = CONFIG_NAME;
1cff166d
SK
673
674 for (config = configs; config; config = config->next)
33820b7e 675 if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, ip))
1cff166d 676 break;
44a2a316
SK
677 }
678
1cff166d
SK
679 if (!config)
680 {
33820b7e
SK
681 for (config = configs; config; config = config->next)
682 if ((config->flags & CONFIG_HWADDR) &&
91dccd09 683 config->wildcard_mask == 0 &&
cdeda28f
SK
684 config->hwaddr_len == ETHER_ADDR_LEN &&
685 (config->hwaddr_type == ARPHRD_ETHER || config->hwaddr_type == 0) &&
33820b7e
SK
686 memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
687 break;
688
689 if (!config)
690 {
691 if (!(config = malloc(sizeof(struct dhcp_config))))
692 continue;
693 config->flags = 0;
91dccd09 694 config->wildcard_mask = 0;
33820b7e
SK
695 config->next = configs;
696 configs = config;
697 }
698
699 config->flags |= flags;
700
701 if (flags & CONFIG_NAME)
702 {
703 if ((config->hostname = malloc(strlen(ip)+1)))
704 strcpy(config->hostname, ip);
705 else
706 config->flags &= ~CONFIG_NAME;
707 }
708
709 if (flags & CONFIG_ADDR)
710 config->addr = addr;
1cff166d 711 }
33820b7e 712
de37951c 713 config->flags |= CONFIG_HWADDR | CONFIG_NOCLID;
33820b7e 714 memcpy(config->hwaddr, hwaddr, ETHER_ADDR_LEN);
cdeda28f
SK
715 config->hwaddr_len = ETHER_ADDR_LEN;
716 config->hwaddr_type = ARPHRD_ETHER;
33820b7e 717 count++;
44a2a316
SK
718 }
719
720 fclose(f);
33820b7e 721
b8187c80 722 syslog(LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
3be34541
SK
723
724 daemon->dhcp_conf = configs;
44a2a316
SK
725}
726
727void dhcp_update_configs(struct dhcp_config *configs)
1ab84e2f 728{
44a2a316
SK
729 /* Some people like to keep all static IP addresses in /etc/hosts.
730 This goes through /etc/hosts and sets static addresses for any DHCP config
3d8df260
SK
731 records which don't have an address and whose name matches.
732 We take care to maintain the invariant that any IP address can appear
733 in at most one dhcp-host. */
44a2a316 734
1ab84e2f
SK
735 struct dhcp_config *config;
736 struct crec *crec;
44a2a316 737
1ab84e2f 738 for (config = configs; config; config = config->next)
33820b7e
SK
739 if (!(config->flags & CONFIG_ADDR) &&
740 (config->flags & CONFIG_NAME) &&
1ab84e2f
SK
741 (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
742 (crec->flags & F_HOSTS))
33820b7e 743 {
3d8df260 744 if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
b8187c80 745 syslog(LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
3d8df260
SK
746 inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
747 else
748 {
749 config->addr = crec->addr.addr.addr.addr4;
750 config->flags |= CONFIG_ADDR;
751 }
33820b7e 752 }
1ab84e2f 753}
44a2a316 754
bb01cb96
SK
755/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
756 for this address. If it has a domain part, that must match the set domain and
757 it gets stripped. */
758char *host_from_dns(struct daemon *daemon, struct in_addr addr)
759{
760 struct crec *lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
761 char *hostname = NULL;
762
763 if (lookup && (lookup->flags & F_HOSTS))
764 {
765 hostname = daemon->dhcp_buff;
bb01cb96 766 strncpy(hostname, cache_get_name(lookup), 256);
5e9e0efb 767 hostname[255] = 0;
bb01cb96
SK
768 hostname = strip_hostname(daemon, hostname);
769 }
770
771 return hostname;
772}
773
774char *strip_hostname(struct daemon *daemon, char *hostname)
775{
776 char *dot = strchr(hostname, '.');
777 if (dot)
778 {
779 if (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix))
780 {
b8187c80 781 syslog(LOG_WARNING, _("Ignoring DHCP host name %s because it has an illegal domain part"), hostname);
bb01cb96
SK
782 hostname = NULL;
783 }
784 else
785 {
786 *dot = 0; /* truncate */
787 if (strlen(hostname) == 0)
788 hostname = NULL; /* nothing left */
789 }
790 }
791 return hostname;
792}