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