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