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