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