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