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