1/* dnsmasq is Copyright (c) 2000 - 2005 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.
6
7   This program is distributed in the hope that it will be useful,
8   but WITHOUT ANY WARRANTY; without even the implied warranty of
9   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10   GNU General Public License for more details.
11*/
12
13#include "dnsmasq.h"
14
15static struct frec *frec_list = NULL;
16
17static struct frec *get_new_frec(struct daemon *daemon, time_t now);
18static struct frec *lookup_frec(unsigned short id);
19static struct frec *lookup_frec_by_sender(unsigned short id,
20					  union mysockaddr *addr,
21					  unsigned int crc);
22static unsigned short get_id(void);
23
24
25/* Send a UDP packet with it's source address set as "source"
26   unless nowild is true, when we just send it with the kernel default */
27static void send_from(int fd, int nowild, char *packet, size_t len,
28		      union mysockaddr *to, struct all_addr *source,
29		      unsigned int iface)
30{
31  struct msghdr msg;
32  struct iovec iov[1];
33  union {
34    struct cmsghdr align; /* this ensures alignment */
35#if defined(HAVE_LINUX_NETWORK)
36    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
37#elif defined(IP_SENDSRCADDR)
38    char control[CMSG_SPACE(sizeof(struct in_addr))];
39#endif
40#ifdef HAVE_IPV6
41    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
42#endif
43  } control_u;
44
45  iov[0].iov_base = packet;
46  iov[0].iov_len = len;
47
48  msg.msg_control = NULL;
49  msg.msg_controllen = 0;
50  msg.msg_flags = 0;
51  msg.msg_name = to;
52  msg.msg_namelen = sa_len(to);
53  msg.msg_iov = iov;
54  msg.msg_iovlen = 1;
55
56  if (!nowild)
57    {
58      struct cmsghdr *cmptr;
59      msg.msg_control = &control_u;
60      msg.msg_controllen = sizeof(control_u);
61      cmptr = CMSG_FIRSTHDR(&msg);
62
63      if (to->sa.sa_family == AF_INET)
64	{
65#if defined(HAVE_LINUX_NETWORK)
66	  struct in_pktinfo *pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
67	  pkt->ipi_ifindex = 0;
68	  pkt->ipi_spec_dst = source->addr.addr4;
69	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
70	  cmptr->cmsg_level = SOL_IP;
71	  cmptr->cmsg_type = IP_PKTINFO;
72#elif defined(IP_SENDSRCADDR)
73	  struct in_addr *a = (struct in_addr *)CMSG_DATA(cmptr);
74	  *a = source->addr.addr4;
75	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
76	  cmptr->cmsg_level = IPPROTO_IP;
77	  cmptr->cmsg_type = IP_SENDSRCADDR;
78#endif
79	}
80      else
81#ifdef HAVE_IPV6
82	{
83	  struct in6_pktinfo *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr);
84	  pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
85	  pkt->ipi6_addr = source->addr.addr6;
86	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
87	  cmptr->cmsg_type = IPV6_PKTINFO;
88	  cmptr->cmsg_level = IPV6_LEVEL;
89	}
90#else
91      iface = 0; /* eliminate warning */
92#endif
93    }
94
95 retry:
96  if (sendmsg(fd, &msg, 0) == -1)
97    {
98      /* certain Linux kernels seem to object to setting the source address in the IPv6 stack
99	 by returning EINVAL from sendmsg. In that case, try again without setting the
100	 source address, since it will nearly alway be correct anyway.  IPv6 stinks. */
101      if (errno == EINVAL && msg.msg_controllen)
102	{
103	  msg.msg_controllen = 0;
104	  goto retry;
105	}
106      if (retry_send())
107	goto retry;
108    }
109}
110
111static unsigned short search_servers(struct daemon *daemon, time_t now, struct all_addr **addrpp,
112				     unsigned short qtype, char *qdomain, int *type, char **domain)
113
114{
115  /* If the query ends in the domain in one of our servers, set
116     domain to point to that name. We find the largest match to allow both
117     domain.org and sub.domain.org to exist. */
118
119  unsigned int namelen = strlen(qdomain);
120  unsigned int matchlen = 0;
121  struct server *serv;
122  unsigned short flags = 0;
123
124  for (serv = daemon->servers; serv; serv=serv->next)
125    /* domain matches take priority over NODOTS matches */
126    if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
127      {
128	unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
129	*type = SERV_FOR_NODOTS;
130	if (serv->flags & SERV_NO_ADDR)
131	  flags = F_NXDOMAIN;
132	else if (serv->flags & SERV_LITERAL_ADDRESS)
133	  {
134	    if (sflag & qtype)
135	      {
136		flags = sflag;
137		if (serv->addr.sa.sa_family == AF_INET)
138		  *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
139#ifdef HAVE_IPV6
140		else
141		  *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
142#endif
143	      }
144	    else if (!flags)
145	      flags = F_NOERR;
146	  }
147      }
148    else if (serv->flags & SERV_HAS_DOMAIN)
149      {
150	unsigned int domainlen = strlen(serv->domain);
151	char *matchstart = qdomain + namelen - domainlen;
152	if (namelen >= domainlen &&
153	    hostname_isequal(matchstart, serv->domain) &&
154	    domainlen >= matchlen &&
155	    (domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' ))
156	  {
157	    unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
158	    *type = SERV_HAS_DOMAIN;
159	    *domain = serv->domain;
160	    matchlen = domainlen;
161	    if (serv->flags & SERV_NO_ADDR)
162	      flags = F_NXDOMAIN;
163	    else if (serv->flags & SERV_LITERAL_ADDRESS)
164	      {
165		if ((sflag | F_QUERY ) & qtype)
166		  {
167		    flags = qtype;
168		    if (serv->addr.sa.sa_family == AF_INET)
169		      *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
170#ifdef HAVE_IPV6
171		    else
172		      *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
173#endif
174		  }
175		else if (!flags)
176		  flags = F_NOERR;
177	      }
178	  }
179      }
180
181  if (flags & ~(F_NOERR | F_NXDOMAIN)) /* flags set here means a literal found */
182    {
183      if (flags & F_QUERY)
184	log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0, NULL, 0);
185      else
186	log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0, NULL, 0);
187    }
188  else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
189    flags = F_NXDOMAIN;
190
191  if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon))
192    flags = F_NOERR;
193
194  if (flags == F_NXDOMAIN || flags == F_NOERR)
195    log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0, NULL, 0);
196
197  return  flags;
198}
199
200/* returns new last_server */
201static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *udpaddr,
202			  struct all_addr *dst_addr, unsigned int dst_iface,
203			  HEADER *header, size_t plen, time_t now, struct frec *forward)
204{
205  char *domain = NULL;
206  int type = 0;
207  struct all_addr *addrp = NULL;
208  unsigned int crc = questions_crc(header, plen, daemon->namebuff);
209  unsigned short flags = 0;
210  unsigned short gotname = extract_request(header, plen, daemon->namebuff, NULL);
211  struct server *start = NULL;
212
213  /* may be no servers available. */
214  if (!daemon->servers)
215    forward = NULL;
216  else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
217    {
218      /* retry on existing query, send to all available servers  */
219      domain = forward->sentto->domain;
220      if (!(daemon->options & OPT_ORDER))
221	{
222	  forward->forwardall = 1;
223	  daemon->last_server = NULL;
224	}
225      type = forward->sentto->flags & SERV_TYPE;
226      if (!(start = forward->sentto->next))
227	start = daemon->servers; /* at end of list, recycle */
228      header->id = htons(forward->new_id);
229    }
230  else
231    {
232      if (gotname)
233	flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
234
235      if (!flags && !(forward = get_new_frec(daemon, now)))
236	/* table full - server failure. */
237	flags = F_NEG;
238
239      if (forward)
240	{
241	  forward->source = *udpaddr;
242	  forward->dest = *dst_addr;
243	  forward->iface = dst_iface;
244	  forward->new_id = get_id();
245	  forward->fd = udpfd;
246	  forward->orig_id = ntohs(header->id);
247	  forward->crc = crc;
248	  forward->forwardall = 0;
249	  header->id = htons(forward->new_id);
250
251	  /* In strict_order mode, or when using domain specific servers
252	     always try servers in the order specified in resolv.conf,
253	     otherwise, use the one last known to work. */
254
255	  if (type != 0  || (daemon->options & OPT_ORDER))
256	    start = daemon->servers;
257	  else if (!(start = daemon->last_server))
258	    {
259	      start = daemon->servers;
260	      forward->forwardall = 1;
261	    }
262	}
263    }
264
265  /* check for send errors here (no route to host)
266     if we fail to send to all nameservers, send back an error
267     packet straight away (helps modem users when offline)  */
268
269  if (!flags && forward)
270    {
271      struct server *firstsentto = start;
272      int forwarded = 0;
273
274      while (1)
275	{
276	  /* only send to servers dealing with our domain.
277	     domain may be NULL, in which case server->domain
278	     must be NULL also. */
279
280	  if (type == (start->flags & SERV_TYPE) &&
281	      (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
282	      !(start->flags & SERV_LITERAL_ADDRESS))
283	    {
284	      if (sendto(start->sfd->fd, (char *)header, plen, 0,
285			 &start->addr.sa,
286			 sa_len(&start->addr)) == -1)
287		{
288		  if (retry_send())
289		    continue;
290		}
291	      else
292		{
293		  /* Keep info in case we want to re-send this packet */
294		  daemon->srv_save = start;
295		  daemon->packet_len = plen;
296
297		  if (!gotname)
298		    strcpy(daemon->namebuff, "query");
299		  if (start->addr.sa.sa_family == AF_INET)
300		    log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
301			      (struct all_addr *)&start->addr.in.sin_addr, 0,
302			      NULL, 0);
303#ifdef HAVE_IPV6
304		  else
305		    log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
306			      (struct all_addr *)&start->addr.in6.sin6_addr, 0,
307			      NULL, 0);
308#endif
309		  forwarded = 1;
310		  forward->sentto = start;
311		  if (!forward->forwardall)
312		    break;
313		  forward->forwardall++;
314		}
315	    }
316
317	  if (!(start = start->next))
318 	    start = daemon->servers;
319
320	  if (start == firstsentto)
321	    break;
322	}
323
324      if (forwarded)
325	  return;
326
327      /* could not send on, prepare to return */
328      header->id = htons(forward->orig_id);
329      forward->new_id = 0; /* cancel */
330    }
331
332  /* could not send on, return empty answer or address if known for whole domain */
333  if (udpfd != -1)
334    {
335      plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
336      send_from(udpfd, daemon->options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface);
337    }
338
339  return;
340}
341
342static size_t process_reply(struct daemon *daemon, HEADER *header, time_t now,
343			    unsigned int query_crc, struct server *server, size_t n)
344{
345  unsigned char *pheader, *sizep;
346  int munged = 0;
347  size_t plen;
348
349  /* If upstream is advertising a larger UDP packet size
350	 than we allow, trim it so that we don't get overlarge
351	 requests for the client. */
352
353  if ((pheader = find_pseudoheader(header, n, &plen, &sizep)))
354    {
355      unsigned short udpsz;
356      unsigned char *psave = sizep;
357
358      GETSHORT(udpsz, sizep);
359      if (udpsz > daemon->edns_pktsz)
360	PUTSHORT(daemon->edns_pktsz, psave);
361    }
362
363  if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN))
364    return n;
365
366  /* Complain loudly if the upstream server is non-recursive. */
367  if (!header->ra && header->rcode == NOERROR && ntohs(header->ancount) == 0 &&
368      server && !(server->flags & SERV_WARNED_RECURSIVE))
369    {
370      prettyprint_addr(&server->addr, daemon->namebuff);
371      syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
372      if (!(daemon->options & OPT_LOG))
373	server->flags |= SERV_WARNED_RECURSIVE;
374    }
375
376  if (daemon->bogus_addr && header->rcode != NXDOMAIN &&
377      check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
378    {
379      munged = 1;
380      header->rcode = NXDOMAIN;
381      header->aa = 0;
382    }
383  else
384    {
385      if (header->rcode == NXDOMAIN &&
386	  extract_request(header, n, daemon->namebuff, NULL) &&
387	  check_for_local_domain(daemon->namebuff, now, daemon))
388	{
389	  /* if we forwarded a query for a locally known name (because it was for
390	     an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
391	     since we know that the domain exists, even if upstream doesn't */
392	  munged = 1;
393	  header->aa = 1;
394	  header->rcode = NOERROR;
395	}
396
397      /* If the crc of the question section doesn't match the crc we sent, then
398	 someone might be attempting to insert bogus values into the cache by
399	 sending replies containing questions and bogus answers. */
400      if (query_crc == questions_crc(header, n, daemon->namebuff))
401	extract_addresses(header, n, daemon->namebuff, now, daemon);
402    }
403
404  /* do this after extract_addresses. Ensure NODATA reply and remove
405     nameserver info. */
406
407  if (munged)
408    {
409      header->ancount = htons(0);
410      header->nscount = htons(0);
411      header->arcount = htons(0);
412    }
413
414  /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
415     sections of the packet. Find the new length here and put back pseudoheader
416     if it was removed. */
417  return resize_packet(header, n, pheader, plen);
418}
419
420/* sets new last_server */
421void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
422{
423  /* packet from peer server, extract data for cache, and send to
424     original requester */
425  struct frec *forward;
426  HEADER *header;
427  union mysockaddr serveraddr;
428  socklen_t addrlen = sizeof(serveraddr);
429  ssize_t n = recvfrom(sfd->fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
430  size_t nn;
431
432  /* packet buffer overwritten */
433  daemon->srv_save = NULL;
434
435  /* Determine the address of the server replying  so that we can mark that as good */
436  serveraddr.sa.sa_family = sfd->source_addr.sa.sa_family;
437#ifdef HAVE_IPV6
438  if (serveraddr.sa.sa_family == AF_INET6)
439    serveraddr.in6.sin6_flowinfo = 0;
440#endif
441
442  header = (HEADER *)daemon->packet;
443  forward = lookup_frec(ntohs(header->id));
444
445  if (n >= (int)sizeof(HEADER) && header->qr && forward)
446    {
447       struct server *server = forward->sentto;
448
449       if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0)
450	 /* for broken servers, attempt to send to another one. */
451	 {
452	   unsigned char *pheader;
453	   size_t plen;
454
455	   /* recreate query from reply */
456	   pheader = find_pseudoheader(header, (size_t)n, &plen, NULL);
457	   header->ancount = htons(0);
458	   header->nscount = htons(0);
459	   header->arcount = htons(0);
460	   if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
461	     {
462	       forward->forwardall = 1;
463	       header->qr = 0;
464	       header->tc = 0;
465	       forward_query(daemon, -1, NULL, NULL, 0, header, nn, now, forward);
466	       return;
467	     }
468	 }
469
470       if ((forward->sentto->flags & SERV_TYPE) == 0)
471	 {
472	   if (header->rcode == SERVFAIL || header->rcode == REFUSED)
473	     server = NULL;
474	   else
475	     {
476	       struct server *last_server;
477	       /* find good server by address if possible, otherwise assume the last one we sent to */
478	       for (last_server = daemon->servers; last_server; last_server = last_server->next)
479		 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
480		     sockaddr_isequal(&last_server->addr, &serveraddr))
481		   {
482		     server = last_server;
483		     break;
484		   }
485	     }
486	   daemon->last_server = server;
487	 }
488
489      /* If the answer is an error, keep the forward record in place in case
490	 we get a good reply from another server. Kill it when we've
491	 had replies from all to avoid filling the forwarding table when
492	 everything is broken */
493      if (forward->forwardall == 0 || --forward->forwardall == 1 ||
494	  (header->rcode != REFUSED && header->rcode != SERVFAIL))
495	{
496	  if ((nn = process_reply(daemon, header, now, forward->crc, server, (size_t)n)))
497	    {
498	      header->id = htons(forward->orig_id);
499	      header->ra = 1; /* recursion if available */
500	      send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn,
501			&forward->source, &forward->dest, forward->iface);
502	    }
503	  forward->new_id = 0; /* cancel */
504	}
505    }
506}
507
508void receive_query(struct listener *listen, struct daemon *daemon, time_t now)
509{
510  HEADER *header = (HEADER *)daemon->packet;
511  union mysockaddr source_addr;
512  unsigned short type;
513  struct all_addr dst_addr;
514  struct in_addr netmask, dst_addr_4;
515  size_t m;
516  ssize_t n;
517  int if_index = 0;
518  struct iovec iov[1];
519  struct msghdr msg;
520  struct cmsghdr *cmptr;
521  union {
522    struct cmsghdr align; /* this ensures alignment */
523#ifdef HAVE_IPV6
524    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
525#endif
526#if defined(HAVE_LINUX_NETWORK)
527    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
528#elif defined(IP_RECVDSTADDR)
529    char control[CMSG_SPACE(sizeof(struct in_addr)) +
530		 CMSG_SPACE(sizeof(struct sockaddr_dl))];
531#endif
532  } control_u;
533
534  /* packet buffer overwritten */
535  daemon->srv_save = NULL;
536
537  if (listen->family == AF_INET && (daemon->options & OPT_NOWILD))
538    {
539      dst_addr_4 = listen->iface->addr.in.sin_addr;
540      netmask = listen->iface->netmask;
541    }
542  else
543    {
544      dst_addr_4.s_addr = 0;
545      netmask.s_addr = 0;
546    }
547
548  iov[0].iov_base = daemon->packet;
549  iov[0].iov_len = daemon->edns_pktsz;
550
551  msg.msg_control = control_u.control;
552  msg.msg_controllen = sizeof(control_u);
553  msg.msg_flags = 0;
554  msg.msg_name = &source_addr;
555  msg.msg_namelen = sizeof(source_addr);
556  msg.msg_iov = iov;
557  msg.msg_iovlen = 1;
558
559  if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
560    return;
561
562  if (n < (int)sizeof(HEADER) ||
563      (msg.msg_flags & MSG_TRUNC) ||
564      header->qr)
565    return;
566
567  source_addr.sa.sa_family = listen->family;
568#ifdef HAVE_IPV6
569  if (listen->family == AF_INET6)
570    source_addr.in6.sin6_flowinfo = 0;
571#endif
572
573  if (!(daemon->options & OPT_NOWILD))
574    {
575      struct ifreq ifr;
576
577      if (msg.msg_controllen < sizeof(struct cmsghdr))
578	return;
579
580#if defined(HAVE_LINUX_NETWORK)
581      if (listen->family == AF_INET)
582	for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
583	  if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
584	    {
585	      dst_addr_4 = dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
586	      if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
587	    }
588#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
589      if (listen->family == AF_INET)
590	{
591	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
592	    if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
593	      dst_addr_4 = dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
594	    else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
595	      if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
596	}
597#endif
598
599#ifdef HAVE_IPV6
600      if (listen->family == AF_INET6)
601	{
602	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
603	    if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
604	      {
605		dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
606		if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
607	      }
608	}
609#endif
610
611      /* enforce available interface configuration */
612
613      if (if_index == 0)
614	return;
615
616      if (daemon->if_except || daemon->if_names || (daemon->options & OPT_LOCALISE))
617	{
618#ifdef SIOCGIFNAME
619	  ifr.ifr_ifindex = if_index;
620	  if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
621	    return;
622#else
623	  if (!if_indextoname(if_index, ifr.ifr_name))
624	    return;
625#endif
626
627	  if (listen->family == AF_INET &&
628	      (daemon->options & OPT_LOCALISE) &&
629	      ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1)
630	    return;
631
632	  netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
633	}
634
635      if (!iface_check(daemon, listen->family, &dst_addr, ifr.ifr_name))
636	return;
637    }
638
639  if (extract_request(header, (size_t)n, daemon->namebuff, &type))
640    {
641      if (listen->family == AF_INET)
642	log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
643		  (struct all_addr *)&source_addr.in.sin_addr, type, NULL, 0);
644#ifdef HAVE_IPV6
645      else
646	log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
647		  (struct all_addr *)&source_addr.in6.sin6_addr, type, NULL, 0);
648#endif
649    }
650
651  m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, daemon,
652		      dst_addr_4, netmask, now);
653  if (m >= 1)
654    send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index);
655  else
656    forward_query(daemon, listen->fd, &source_addr, &dst_addr, if_index,
657		  header, (size_t)n, now, NULL);
658}
659
660static int read_write(int fd, unsigned char *packet, int size, int rw)
661{
662  ssize_t n, done;
663
664  for (done = 0; done < size; done += n)
665    {
666    retry:
667      if (rw)
668	n = read(fd, &packet[done], (size_t)(size - done));
669      else
670	n = write(fd, &packet[done], (size_t)(size - done));
671
672      if (n == 0)
673	return 0;
674      else if (n == -1)
675	{
676	  if (errno == EINTR)
677	    goto retry;
678	  else
679	    return 0;
680	}
681    }
682  return 1;
683}
684
685/* The daemon forks before calling this: it should deal with one connection,
686   blocking as neccessary, and then return. Note, need to be a bit careful
687   about resources for debug mode, when the fork is suppressed: that's
688   done by the caller. */
689unsigned char *tcp_request(struct daemon *daemon, int confd, time_t now,
690			   struct in_addr local_addr, struct in_addr netmask)
691{
692  int size = 0;
693  size_t m;
694  unsigned short qtype, gotname;
695  unsigned char c1, c2;
696  /* Max TCP packet + slop */
697  unsigned char *packet = malloc(65536 + MAXDNAME + RRFIXEDSZ);
698  HEADER *header;
699  struct server *last_server;
700
701  while (1)
702    {
703      if (!packet ||
704	  !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
705	  !(size = c1 << 8 | c2) ||
706	  !read_write(confd, packet, size, 1))
707       	return packet;
708
709      if (size < (int)sizeof(HEADER))
710	continue;
711
712      header = (HEADER *)packet;
713
714      if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
715	{
716	  union mysockaddr peer_addr;
717	  socklen_t peer_len = sizeof(union mysockaddr);
718
719	  if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1)
720	    {
721	      if (peer_addr.sa.sa_family == AF_INET)
722		log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
723			  (struct all_addr *)&peer_addr.in.sin_addr, qtype, NULL, 0);
724#ifdef HAVE_IPV6
725	      else
726		log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
727			  (struct all_addr *)&peer_addr.in6.sin6_addr, qtype, NULL, 0);
728#endif
729	    }
730	}
731
732      /* m > 0 if answered from cache */
733      m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, daemon,
734			 local_addr, netmask, now);
735
736      if (m == 0)
737	{
738	  unsigned short flags = 0;
739	  struct all_addr *addrp = NULL;
740	  int type = 0;
741	  char *domain = NULL;
742
743	  if (gotname)
744	    flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
745
746	  if (type != 0  || (daemon->options & OPT_ORDER) || !daemon->last_server)
747	    last_server = daemon->servers;
748	  else
749	    last_server = daemon->last_server;
750
751	  if (!flags && last_server)
752	    {
753	      struct server *firstsendto = NULL;
754	      unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
755
756	      /* Loop round available servers until we succeed in connecting to one.
757	         Note that this code subtley ensures that consecutive queries on this connection
758	         which can go to the same server, do so. */
759	      while (1)
760		{
761		  if (!firstsendto)
762		    firstsendto = last_server;
763		  else
764		    {
765		      if (!(last_server = last_server->next))
766			last_server = daemon->servers;
767
768		      if (last_server == firstsendto)
769			break;
770		    }
771
772		  /* server for wrong domain */
773		  if (type != (last_server->flags & SERV_TYPE) ||
774		      (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
775		    continue;
776
777		  if ((last_server->tcpfd == -1) &&
778		      (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 &&
779		      connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
780		    {
781		      close(last_server->tcpfd);
782		      last_server->tcpfd = -1;
783		    }
784
785		  if (last_server->tcpfd == -1)
786		    continue;
787
788		  c1 = size >> 8;
789		  c2 = size;
790
791		  if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
792		      !read_write(last_server->tcpfd, &c2, 1, 0) ||
793		      !read_write(last_server->tcpfd, packet, size, 0) ||
794		      !read_write(last_server->tcpfd, &c1, 1, 1) ||
795		      !read_write(last_server->tcpfd, &c2, 1, 1))
796		    {
797		      close(last_server->tcpfd);
798		      last_server->tcpfd = -1;
799		      continue;
800		    }
801
802		  m = (c1 << 8) | c2;
803		  if (!read_write(last_server->tcpfd, packet, m, 1))
804		    return packet;
805
806		  if (!gotname)
807		    strcpy(daemon->namebuff, "query");
808		  if (last_server->addr.sa.sa_family == AF_INET)
809		    log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
810			      (struct all_addr *)&last_server->addr.in.sin_addr, 0, NULL, 0);
811#ifdef HAVE_IPV6
812		  else
813		    log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
814			      (struct all_addr *)&last_server->addr.in6.sin6_addr, 0, NULL, 0);
815#endif
816
817		  /* There's no point in updating the cache, since this process will exit and
818		     lose the information after one query. We make this call for the alias and
819		     bogus-nxdomain side-effects. */
820		  m = process_reply(daemon, header, now, crc, last_server, (unsigned int)m);
821
822		  break;
823		}
824	    }
825
826	  /* In case of local answer or no connections made. */
827	  if (m == 0)
828	    m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
829	}
830
831      c1 = m>>8;
832      c2 = m;
833      if (!read_write(confd, &c1, 1, 0) ||
834	  !read_write(confd, &c2, 1, 0) ||
835	  !read_write(confd, packet, m, 0))
836	return packet;
837    }
838}
839
840static struct frec *get_new_frec(struct daemon *daemon, time_t now)
841{
842  struct frec *f = frec_list, *oldest = NULL;
843  time_t oldtime = now;
844  int count = 0;
845  static time_t warntime = 0;
846
847  while (f)
848    {
849      if (f->new_id == 0)
850	{
851	  f->time = now;
852	  return f;
853	}
854
855      if (difftime(f->time, oldtime) <= 0)
856	{
857	  oldtime = f->time;
858	  oldest = f;
859	}
860
861      count++;
862      f = f->next;
863    }
864
865  /* can't find empty one, use oldest if there is one
866     and it's older than timeout */
867  if (oldest && difftime(now, oldtime)  > TIMEOUT)
868    {
869      oldest->time = now;
870      return oldest;
871    }
872
873  if (count > daemon->ftabsize)
874    { /* limit logging rate so syslog isn't DOSed either */
875      if (!warntime || difftime(now, warntime) > LOGRATE)
876	{
877	  warntime = now;
878	  syslog(LOG_WARNING, _("forwarding table overflow: check for server loops."));
879	}
880      return NULL;
881    }
882
883  if ((f = (struct frec *)malloc(sizeof(struct frec))))
884    {
885      f->next = frec_list;
886      f->time = now;
887      f->new_id = 0;
888      frec_list = f;
889    }
890  return f; /* OK if malloc fails and this is NULL */
891}
892
893static struct frec *lookup_frec(unsigned short id)
894{
895  struct frec *f;
896
897  for(f = frec_list; f; f = f->next)
898    if (f->new_id == id)
899      return f;
900
901  return NULL;
902}
903
904static struct frec *lookup_frec_by_sender(unsigned short id,
905					  union mysockaddr *addr,
906					  unsigned int crc)
907{
908  struct frec *f;
909
910  for(f = frec_list; f; f = f->next)
911    if (f->new_id &&
912	f->orig_id == id &&
913	f->crc == crc &&
914	sockaddr_isequal(&f->source, addr))
915      return f;
916
917  return NULL;
918}
919
920/* A server record is going away, remove references to it */
921void server_gone(struct daemon *daemon, struct server *server)
922{
923  struct frec *f;
924
925  for (f = frec_list; f; f = f->next)
926    if (f->new_id != 0 && f->sentto == server)
927      f->new_id = 0;
928
929  if (daemon->last_server == server)
930    daemon->last_server = NULL;
931
932  if (daemon->srv_save == server)
933    daemon->srv_save = NULL;
934}
935
936/* return unique random ids between 1 and 65535 */
937static unsigned short get_id(void)
938{
939  unsigned short ret = 0;
940
941  while (ret == 0)
942    {
943      ret = rand16();
944
945      /* scrap ids already in use */
946      if ((ret != 0) && lookup_frec(ret))
947	ret = 0;
948    }
949
950  return ret;
951}
952
953
954
955
956
957