Annotation of embedaddon/dnsmasq/src/forward.c, revision 1.1.1.4
1.1.1.4 ! misho 1: /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
1.1 misho 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:
1.1.1.4 ! misho 19: static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash);
1.1 misho 20: static struct frec *lookup_frec_by_sender(unsigned short id,
21: union mysockaddr *addr,
1.1.1.2 misho 22: void *hash);
1.1.1.4 ! misho 23: static struct frec *lookup_frec_by_query(void *hash, unsigned int flags);
! 24:
1.1.1.2 misho 25: static unsigned short get_id(void);
1.1 misho 26: static void free_frec(struct frec *f);
1.1.1.2 misho 27:
1.1 misho 28: /* Send a UDP packet with its source address set as "source"
29: unless nowild is true, when we just send it with the kernel default */
30: int send_from(int fd, int nowild, char *packet, size_t len,
1.1.1.4 ! misho 31: union mysockaddr *to, union all_addr *source,
1.1 misho 32: unsigned int iface)
33: {
34: struct msghdr msg;
35: struct iovec iov[1];
36: union {
37: struct cmsghdr align; /* this ensures alignment */
38: #if defined(HAVE_LINUX_NETWORK)
39: char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
40: #elif defined(IP_SENDSRCADDR)
41: char control[CMSG_SPACE(sizeof(struct in_addr))];
42: #endif
43: char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
44: } control_u;
45:
46: iov[0].iov_base = packet;
47: iov[0].iov_len = len;
48:
49: msg.msg_control = NULL;
50: msg.msg_controllen = 0;
51: msg.msg_flags = 0;
52: msg.msg_name = to;
53: msg.msg_namelen = sa_len(to);
54: msg.msg_iov = iov;
55: msg.msg_iovlen = 1;
56:
57: if (!nowild)
58: {
59: struct cmsghdr *cmptr;
60: msg.msg_control = &control_u;
61: msg.msg_controllen = sizeof(control_u);
62: cmptr = CMSG_FIRSTHDR(&msg);
63:
64: if (to->sa.sa_family == AF_INET)
65: {
66: #if defined(HAVE_LINUX_NETWORK)
67: struct in_pktinfo p;
68: p.ipi_ifindex = 0;
1.1.1.4 ! misho 69: p.ipi_spec_dst = source->addr4;
! 70: msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
1.1 misho 71: memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
1.1.1.4 ! misho 72: cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1.1 misho 73: cmptr->cmsg_level = IPPROTO_IP;
74: cmptr->cmsg_type = IP_PKTINFO;
75: #elif defined(IP_SENDSRCADDR)
1.1.1.4 ! misho 76: msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
! 77: memcpy(CMSG_DATA(cmptr), &(source->addr4), sizeof(source->addr4));
! 78: cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
1.1 misho 79: cmptr->cmsg_level = IPPROTO_IP;
80: cmptr->cmsg_type = IP_SENDSRCADDR;
81: #endif
82: }
83: else
84: {
85: struct in6_pktinfo p;
86: p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
1.1.1.4 ! misho 87: p.ipi6_addr = source->addr6;
! 88: msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
1.1 misho 89: memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
1.1.1.4 ! misho 90: cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1.1 misho 91: cmptr->cmsg_type = daemon->v6pktinfo;
92: cmptr->cmsg_level = IPPROTO_IPV6;
93: }
94: }
95:
1.1.1.3 misho 96: while (retry_send(sendmsg(fd, &msg, 0)));
97:
1.1.1.4 ! misho 98: if (errno != 0)
1.1 misho 99: {
1.1.1.4 ! misho 100: #ifdef HAVE_LINUX_NETWORK
! 101: /* If interface is still in DAD, EINVAL results - ignore that. */
! 102: if (errno != EINVAL)
! 103: my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
! 104: #endif
1.1 misho 105: return 0;
106: }
107:
108: return 1;
109: }
110:
1.1.1.4 ! misho 111: static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned int qtype,
1.1.1.3 misho 112: char *qdomain, int *type, char **domain, int *norebind)
1.1 misho 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 int flags = 0;
1.1.1.4 ! misho 123: static union all_addr zero;
1.1 misho 124:
125: for (serv = daemon->servers; serv; serv=serv->next)
1.1.1.4 ! misho 126: if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
! 127: continue;
1.1 misho 128: /* domain matches take priority over NODOTS matches */
1.1.1.4 ! misho 129: else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
1.1 misho 130: {
131: unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
132: *type = SERV_FOR_NODOTS;
1.1.1.4 ! misho 133: if ((serv->flags & SERV_NO_REBIND) && norebind)
! 134: *norebind = 1;
! 135: else if (serv->flags & SERV_NO_ADDR)
1.1 misho 136: flags = F_NXDOMAIN;
1.1.1.4 ! misho 137: else if (serv->flags & SERV_LITERAL_ADDRESS)
1.1 misho 138: {
1.1.1.4 ! misho 139: /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
! 140: if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
! 141: {
! 142: memset(&zero, 0, sizeof(zero));
! 143: flags = qtype;
! 144: *addrpp = &zero;
! 145: }
! 146: else if (sflag & qtype)
1.1 misho 147: {
148: flags = sflag;
149: if (serv->addr.sa.sa_family == AF_INET)
1.1.1.4 ! misho 150: *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
1.1 misho 151: else
1.1.1.4 ! misho 152: *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
1.1 misho 153: }
154: else if (!flags || (flags & F_NXDOMAIN))
155: flags = F_NOERR;
156: }
157: }
158: else if (serv->flags & SERV_HAS_DOMAIN)
159: {
160: unsigned int domainlen = strlen(serv->domain);
161: char *matchstart = qdomain + namelen - domainlen;
162: if (namelen >= domainlen &&
163: hostname_isequal(matchstart, serv->domain) &&
164: (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
165: {
1.1.1.3 misho 166: if ((serv->flags & SERV_NO_REBIND) && norebind)
1.1 misho 167: *norebind = 1;
168: else
169: {
170: unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
171: /* implement priority rules for --address and --server for same domain.
172: --address wins if the address is for the correct AF
173: --server wins otherwise. */
174: if (domainlen != 0 && domainlen == matchlen)
175: {
176: if ((serv->flags & SERV_LITERAL_ADDRESS))
177: {
178: if (!(sflag & qtype) && flags == 0)
179: continue;
180: }
181: else
182: {
183: if (flags & (F_IPV4 | F_IPV6))
184: continue;
185: }
186: }
187:
188: if (domainlen >= matchlen)
189: {
1.1.1.3 misho 190: *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
1.1 misho 191: *domain = serv->domain;
192: matchlen = domainlen;
193: if (serv->flags & SERV_NO_ADDR)
194: flags = F_NXDOMAIN;
195: else if (serv->flags & SERV_LITERAL_ADDRESS)
196: {
1.1.1.4 ! misho 197: /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
! 198: if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
! 199: {
! 200: memset(&zero, 0, sizeof(zero));
! 201: flags = qtype;
! 202: *addrpp = &zero;
! 203: }
! 204: else if (sflag & qtype)
1.1 misho 205: {
206: flags = sflag;
207: if (serv->addr.sa.sa_family == AF_INET)
1.1.1.4 ! misho 208: *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
1.1 misho 209: else
1.1.1.4 ! misho 210: *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
1.1 misho 211: }
212: else if (!flags || (flags & F_NXDOMAIN))
213: flags = F_NOERR;
214: }
215: else
216: flags = 0;
217: }
218: }
219: }
220: }
221:
1.1.1.4 ! misho 222: if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) &&
1.1 misho 223: option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
224: /* don't forward A or AAAA queries for simple names, except the empty name */
225: flags = F_NOERR;
226:
227: if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
228: flags = F_NOERR;
229:
230: if (flags)
231: {
1.1.1.4 ! misho 232: if (flags == F_NXDOMAIN || flags == F_NOERR)
! 233: log_query(flags | qtype | F_NEG | F_CONFIG | F_FORWARD, qdomain, NULL, NULL);
! 234: else
! 235: {
! 236: /* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */
! 237: if (flags & F_IPV4)
! 238: log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL);
! 239: if (flags & F_IPV6)
! 240: log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL);
! 241: }
1.1 misho 242: }
243: else if ((*type) & SERV_USE_RESOLV)
244: {
245: *type = 0; /* use normal servers for this domain */
246: *domain = NULL;
247: }
248: return flags;
249: }
250:
251: static int forward_query(int udpfd, union mysockaddr *udpaddr,
1.1.1.4 ! misho 252: union all_addr *dst_addr, unsigned int dst_iface,
1.1.1.2 misho 253: struct dns_header *header, size_t plen, time_t now,
254: struct frec *forward, int ad_reqd, int do_bit)
1.1 misho 255: {
256: char *domain = NULL;
1.1.1.3 misho 257: int type = SERV_DO_DNSSEC, norebind = 0;
1.1.1.4 ! misho 258: union all_addr *addrp = NULL;
1.1 misho 259: unsigned int flags = 0;
1.1.1.4 ! misho 260: unsigned int fwd_flags = 0;
1.1 misho 261: struct server *start = NULL;
1.1.1.2 misho 262: void *hash = hash_questions(header, plen, daemon->namebuff);
1.1.1.4 ! misho 263: #ifdef HAVE_DNSSEC
1.1.1.3 misho 264: int do_dnssec = 0;
1.1.1.2 misho 265: #endif
1.1.1.4 ! misho 266: unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
! 267: unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
! 268: (void)do_bit;
! 269:
! 270: if (header->hb4 & HB4_CD)
! 271: fwd_flags |= FREC_CHECKING_DISABLED;
! 272: if (ad_reqd)
! 273: fwd_flags |= FREC_AD_QUESTION;
! 274: if (oph)
! 275: fwd_flags |= FREC_HAS_PHEADER;
! 276: #ifdef HAVE_DNSSEC
! 277: if (do_bit)
! 278: fwd_flags |= FREC_DO_QUESTION;
! 279: #endif
! 280:
1.1 misho 281: /* may be no servers available. */
1.1.1.4 ! misho 282: if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash)))
1.1 misho 283: {
1.1.1.3 misho 284: /* If we didn't get an answer advertising a maximal packet in EDNS,
285: fall back to 1280, which should work everywhere on IPv6.
286: If that generates an answer, it will become the new default
287: for this server */
288: forward->flags |= FREC_TEST_PKTSZ;
289:
1.1.1.2 misho 290: #ifdef HAVE_DNSSEC
291: /* If we've already got an answer to this query, but we're awaiting keys for validation,
292: there's no point retrying the query, retry the key query instead...... */
293: if (forward->blocking_query)
294: {
1.1.1.3 misho 295: int fd, is_sign;
296: unsigned char *pheader;
297:
298: forward->flags &= ~FREC_TEST_PKTSZ;
299:
1.1.1.2 misho 300: while (forward->blocking_query)
301: forward = forward->blocking_query;
1.1.1.3 misho 302:
1.1.1.2 misho 303: blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
304: plen = forward->stash_len;
305:
1.1.1.4 ! misho 306: forward->flags |= FREC_TEST_PKTSZ;
1.1.1.3 misho 307: if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
308: PUTSHORT(SAFE_PKTSZ, pheader);
1.1.1.4 ! misho 309:
1.1.1.2 misho 310: if (forward->sentto->addr.sa.sa_family == AF_INET)
1.1.1.4 ! misho 311: log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (union all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
1.1.1.2 misho 312: else
1.1.1.4 ! misho 313: log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
! 314:
1.1.1.2 misho 315:
316: if (forward->sentto->sfd)
317: fd = forward->sentto->sfd->fd;
318: else
319: {
320: if (forward->sentto->addr.sa.sa_family == AF_INET6)
321: fd = forward->rfd6->fd;
322: else
323: fd = forward->rfd4->fd;
324: }
325:
1.1.1.4 ! misho 326: while (retry_send(sendto(fd, (char *)header, plen, 0,
! 327: &forward->sentto->addr.sa,
! 328: sa_len(&forward->sentto->addr))));
1.1.1.2 misho 329:
330: return 1;
331: }
332: #endif
333:
1.1 misho 334: /* retry on existing query, send to all available servers */
335: domain = forward->sentto->domain;
336: forward->sentto->failed_queries++;
337: if (!option_bool(OPT_ORDER))
338: {
339: forward->forwardall = 1;
340: daemon->last_server = NULL;
341: }
342: type = forward->sentto->flags & SERV_TYPE;
1.1.1.3 misho 343: #ifdef HAVE_DNSSEC
344: do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
345: #endif
346:
1.1 misho 347: if (!(start = forward->sentto->next))
348: start = daemon->servers; /* at end of list, recycle */
349: header->id = htons(forward->new_id);
350: }
351: else
352: {
1.1.1.4 ! misho 353: /* Query from new source, but the same query may be in progress
! 354: from another source. If so, just add this client to the
! 355: list that will get the reply.*/
! 356:
! 357: if (!option_bool(OPT_ADD_MAC) && !option_bool(OPT_MAC_B64) &&
! 358: (forward = lookup_frec_by_query(hash, fwd_flags)))
! 359: {
! 360: /* Note whine_malloc() zeros memory. */
! 361: if (!daemon->free_frec_src &&
! 362: daemon->frec_src_count < daemon->ftabsize &&
! 363: (daemon->free_frec_src = whine_malloc(sizeof(struct frec_src))))
! 364: {
! 365: daemon->frec_src_count++;
! 366: daemon->free_frec_src->next = NULL;
! 367: }
! 368:
! 369: /* If we've been spammed with many duplicates, just drop the query. */
! 370: if (daemon->free_frec_src)
! 371: {
! 372: struct frec_src *new = daemon->free_frec_src;
! 373: daemon->free_frec_src = new->next;
! 374: new->next = forward->frec_src.next;
! 375: forward->frec_src.next = new;
! 376: new->orig_id = ntohs(header->id);
! 377: new->source = *udpaddr;
! 378: new->dest = *dst_addr;
! 379: new->log_id = daemon->log_id;
! 380: new->iface = dst_iface;
! 381: new->fd = udpfd;
! 382: }
! 383:
! 384: return 1;
! 385: }
! 386:
1.1 misho 387: if (gotname)
388: flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
389:
1.1.1.3 misho 390: #ifdef HAVE_DNSSEC
391: do_dnssec = type & SERV_DO_DNSSEC;
392: #endif
393: type &= ~SERV_DO_DNSSEC;
1.1.1.4 ! misho 394:
1.1.1.3 misho 395: if (daemon->servers && !flags)
1.1.1.4 ! misho 396: forward = get_new_frec(now, NULL, NULL);
1.1.1.3 misho 397: /* table full - flags == 0, return REFUSED */
1.1 misho 398:
399: if (forward)
400: {
1.1.1.4 ! misho 401: forward->frec_src.source = *udpaddr;
! 402: forward->frec_src.orig_id = ntohs(header->id);
! 403: forward->frec_src.dest = *dst_addr;
! 404: forward->frec_src.iface = dst_iface;
! 405: forward->frec_src.next = NULL;
! 406: forward->frec_src.fd = udpfd;
1.1.1.2 misho 407: forward->new_id = get_id();
408: memcpy(forward->hash, hash, HASH_SIZE);
1.1 misho 409: forward->forwardall = 0;
1.1.1.4 ! misho 410: forward->flags = fwd_flags;
1.1 misho 411: if (norebind)
412: forward->flags |= FREC_NOREBIND;
413: if (header->hb4 & HB4_CD)
414: forward->flags |= FREC_CHECKING_DISABLED;
1.1.1.2 misho 415: if (ad_reqd)
416: forward->flags |= FREC_AD_QUESTION;
417: #ifdef HAVE_DNSSEC
418: forward->work_counter = DNSSEC_WORK;
419: if (do_bit)
420: forward->flags |= FREC_DO_QUESTION;
421: #endif
422:
1.1 misho 423: header->id = htons(forward->new_id);
424:
425: /* In strict_order mode, always try servers in the order
426: specified in resolv.conf, if a domain is given
427: always try all the available servers,
428: otherwise, use the one last known to work. */
429:
430: if (type == 0)
431: {
432: if (option_bool(OPT_ORDER))
433: start = daemon->servers;
434: else if (!(start = daemon->last_server) ||
435: daemon->forwardcount++ > FORWARD_TEST ||
436: difftime(now, daemon->forwardtime) > FORWARD_TIME)
437: {
438: start = daemon->servers;
439: forward->forwardall = 1;
440: daemon->forwardcount = 0;
441: daemon->forwardtime = now;
442: }
443: }
444: else
445: {
446: start = daemon->servers;
447: if (!option_bool(OPT_ORDER))
448: forward->forwardall = 1;
449: }
450: }
451: }
452:
453: /* check for send errors here (no route to host)
454: if we fail to send to all nameservers, send back an error
455: packet straight away (helps modem users when offline) */
456:
457: if (!flags && forward)
458: {
459: struct server *firstsentto = start;
1.1.1.4 ! misho 460: int subnet, cacheable, forwarded = 0;
1.1.1.3 misho 461: size_t edns0_len;
1.1.1.4 ! misho 462: unsigned char *pheader;
! 463:
1.1.1.3 misho 464: /* If a query is retried, use the log_id for the retry when logging the answer. */
1.1.1.4 ! misho 465: forward->frec_src.log_id = daemon->log_id;
1.1 misho 466:
1.1.1.4 ! misho 467: plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &subnet, &cacheable);
1.1.1.3 misho 468:
1.1.1.4 ! misho 469: if (subnet)
! 470: forward->flags |= FREC_HAS_SUBNET;
! 471:
! 472: if (!cacheable)
! 473: forward->flags |= FREC_NO_CACHE;
! 474:
1.1.1.2 misho 475: #ifdef HAVE_DNSSEC
1.1.1.3 misho 476: if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
1.1.1.2 misho 477: {
1.1.1.4 ! misho 478: plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
! 479:
1.1.1.2 misho 480: /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
481: this allows it to select auth servers when one is returning bad data. */
482: if (option_bool(OPT_DNSSEC_DEBUG))
483: header->hb4 |= HB4_CD;
484:
485: }
486: #endif
487:
1.1.1.4 ! misho 488: if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
! 489: {
! 490: /* If there wasn't a PH before, and there is now, we added it. */
! 491: if (!oph)
! 492: forward->flags |= FREC_ADDED_PHEADER;
! 493:
! 494: /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
! 495: if (edns0_len > 11)
! 496: forward->flags |= FREC_HAS_EXTRADATA;
! 497:
! 498: /* Reduce udp size on retransmits. */
! 499: if (forward->flags & FREC_TEST_PKTSZ)
! 500: PUTSHORT(SAFE_PKTSZ, pheader);
! 501: }
1.1.1.3 misho 502:
1.1 misho 503: while (1)
504: {
505: /* only send to servers dealing with our domain.
506: domain may be NULL, in which case server->domain
507: must be NULL also. */
508:
509: if (type == (start->flags & SERV_TYPE) &&
510: (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
1.1.1.3 misho 511: !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1.1 misho 512: {
513: int fd;
514:
515: /* find server socket to use, may need to get random one. */
516: if (start->sfd)
517: fd = start->sfd->fd;
518: else
519: {
520: if (start->addr.sa.sa_family == AF_INET6)
521: {
522: if (!forward->rfd6 &&
523: !(forward->rfd6 = allocate_rfd(AF_INET6)))
524: break;
525: daemon->rfd_save = forward->rfd6;
526: fd = forward->rfd6->fd;
527: }
528: else
529: {
530: if (!forward->rfd4 &&
531: !(forward->rfd4 = allocate_rfd(AF_INET)))
532: break;
533: daemon->rfd_save = forward->rfd4;
534: fd = forward->rfd4->fd;
535: }
536:
537: #ifdef HAVE_CONNTRACK
538: /* Copy connection mark of incoming query to outgoing connection. */
539: if (option_bool(OPT_CONNTRACK))
540: {
541: unsigned int mark;
1.1.1.4 ! misho 542: if (get_incoming_mark(&forward->frec_src.source, &forward->frec_src.dest, 0, &mark))
1.1 misho 543: setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
544: }
545: #endif
546: }
547:
1.1.1.3 misho 548: #ifdef HAVE_DNSSEC
549: if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
1.1 misho 550: {
1.1.1.3 misho 551: /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
552: packet size to 512. But that won't provide space for the RRSIGS in many cases.
553: The RRSIGS will be stripped out before the answer goes back, so the packet should
554: shrink again. So, if we added a do-bit, bump the udp packet size to the value
555: known to be OK for this server. We check returned size after stripping and set
556: the truncated bit if it's still too big. */
557: unsigned char *pheader;
558: int is_sign;
559: if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
560: PUTSHORT(start->edns_pktsz, pheader);
1.1 misho 561: }
1.1.1.3 misho 562: #endif
563:
564: if (retry_send(sendto(fd, (char *)header, plen, 0,
565: &start->addr.sa,
566: sa_len(&start->addr))))
567: continue;
568:
569: if (errno == 0)
1.1 misho 570: {
1.1.1.4 ! misho 571: #ifdef HAVE_DUMPFILE
! 572: dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &start->addr);
! 573: #endif
! 574:
1.1 misho 575: /* Keep info in case we want to re-send this packet */
576: daemon->srv_save = start;
577: daemon->packet_len = plen;
578:
579: if (!gotname)
580: strcpy(daemon->namebuff, "query");
581: if (start->addr.sa.sa_family == AF_INET)
582: log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 583: (union all_addr *)&start->addr.in.sin_addr, NULL);
1.1 misho 584: else
585: log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 586: (union all_addr *)&start->addr.in6.sin6_addr, NULL);
1.1 misho 587: start->queries++;
588: forwarded = 1;
589: forward->sentto = start;
590: if (!forward->forwardall)
591: break;
592: forward->forwardall++;
593: }
594: }
595:
596: if (!(start = start->next))
597: start = daemon->servers;
598:
599: if (start == firstsentto)
600: break;
601: }
602:
603: if (forwarded)
604: return 1;
605:
606: /* could not send on, prepare to return */
1.1.1.4 ! misho 607: header->id = htons(forward->frec_src.orig_id);
1.1 misho 608: free_frec(forward); /* cancel */
609: }
610:
611: /* could not send on, return empty answer or address if known for whole domain */
612: if (udpfd != -1)
613: {
614: plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
1.1.1.4 ! misho 615: if (oph)
! 616: plen = add_pseudoheader(header, plen, ((unsigned char *) header) + PACKETSZ, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
1.1 misho 617: send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
618: }
619:
620: return 0;
621: }
622:
1.1.1.2 misho 623: static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
1.1.1.3 misho 624: int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
625: int check_subnet, union mysockaddr *query_source)
1.1 misho 626: {
627: unsigned char *pheader, *sizep;
628: char **sets = 0;
629: int munged = 0, is_sign;
1.1.1.4 ! misho 630: unsigned int rcode = RCODE(header);
1.1 misho 631: size_t plen;
1.1.1.4 ! misho 632:
1.1.1.2 misho 633: (void)ad_reqd;
1.1.1.3 misho 634: (void)do_bit;
635: (void)bogusanswer;
1.1.1.2 misho 636:
1.1 misho 637: #ifdef HAVE_IPSET
1.1.1.2 misho 638: if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
1.1 misho 639: {
1.1.1.2 misho 640: /* Similar algorithm to search_servers. */
641: struct ipsets *ipset_pos;
642: unsigned int namelen = strlen(daemon->namebuff);
643: unsigned int matchlen = 0;
644: for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
645: {
646: unsigned int domainlen = strlen(ipset_pos->domain);
647: char *matchstart = daemon->namebuff + namelen - domainlen;
648: if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
649: (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
650: domainlen >= matchlen)
651: {
652: matchlen = domainlen;
653: sets = ipset_pos->sets;
654: }
655: }
1.1 misho 656: }
657: #endif
1.1.1.4 ! misho 658:
1.1.1.3 misho 659: if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
1.1 misho 660: {
1.1.1.4 ! misho 661: /* Get extended RCODE. */
! 662: rcode |= sizep[2] << 4;
! 663:
1.1.1.2 misho 664: if (check_subnet && !check_source(header, plen, pheader, query_source))
665: {
666: my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
667: return 0;
668: }
669:
1.1.1.3 misho 670: if (!is_sign)
1.1.1.2 misho 671: {
1.1.1.3 misho 672: if (added_pheader)
673: {
674: /* client didn't send EDNS0, we added one, strip it off before returning answer. */
675: n = rrfilter(header, n, 0);
676: pheader = NULL;
677: }
678: else
679: {
680: unsigned short udpsz;
681:
682: /* If upstream is advertising a larger UDP packet size
683: than we allow, trim it so that we don't get overlarge
684: requests for the client. We can't do this for signed packets. */
685: GETSHORT(udpsz, sizep);
686: if (udpsz > daemon->edns_pktsz)
687: {
688: sizep -= 2;
689: PUTSHORT(daemon->edns_pktsz, sizep);
690: }
691:
692: #ifdef HAVE_DNSSEC
693: /* If the client didn't set the do bit, but we did, reset it. */
694: if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
695: {
696: unsigned short flags;
697: sizep += 2; /* skip RCODE */
698: GETSHORT(flags, sizep);
699: flags &= ~0x8000;
700: sizep -= 2;
701: PUTSHORT(flags, sizep);
702: }
703: #endif
704: }
1.1.1.2 misho 705: }
1.1 misho 706: }
1.1.1.2 misho 707:
1.1 misho 708: /* RFC 4035 sect 4.6 para 3 */
1.1.1.2 misho 709: if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
1.1 misho 710: header->hb4 &= ~HB4_AD;
1.1.1.2 misho 711:
1.1.1.4 ! misho 712: if (OPCODE(header) != QUERY)
1.1.1.2 misho 713: return resize_packet(header, n, pheader, plen);
1.1.1.4 ! misho 714:
! 715: if (rcode != NOERROR && rcode != NXDOMAIN)
! 716: {
! 717: union all_addr a;
! 718: a.log.rcode = rcode;
! 719: log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
! 720:
! 721: return resize_packet(header, n, pheader, plen);
! 722: }
1.1 misho 723:
724: /* Complain loudly if the upstream server is non-recursive. */
1.1.1.4 ! misho 725: if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
1.1 misho 726: server && !(server->flags & SERV_WARNED_RECURSIVE))
727: {
1.1.1.4 ! misho 728: (void)prettyprint_addr(&server->addr, daemon->namebuff);
1.1 misho 729: my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
730: if (!option_bool(OPT_LOG))
731: server->flags |= SERV_WARNED_RECURSIVE;
732: }
1.1.1.2 misho 733:
1.1.1.4 ! misho 734: if (daemon->bogus_addr && rcode != NXDOMAIN &&
1.1 misho 735: check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
736: {
737: munged = 1;
738: SET_RCODE(header, NXDOMAIN);
739: header->hb3 &= ~HB3_AA;
1.1.1.2 misho 740: cache_secure = 0;
1.1 misho 741: }
742: else
743: {
1.1.1.2 misho 744: int doctored = 0;
745:
1.1.1.4 ! misho 746: if (rcode == NXDOMAIN &&
1.1 misho 747: extract_request(header, n, daemon->namebuff, NULL) &&
748: check_for_local_domain(daemon->namebuff, now))
749: {
750: /* if we forwarded a query for a locally known name (because it was for
751: an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
752: since we know that the domain exists, even if upstream doesn't */
753: munged = 1;
754: header->hb3 |= HB3_AA;
755: SET_RCODE(header, NOERROR);
1.1.1.2 misho 756: cache_secure = 0;
1.1 misho 757: }
758:
1.1.1.2 misho 759: if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
1.1 misho 760: {
761: my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
762: munged = 1;
1.1.1.2 misho 763: cache_secure = 0;
764: }
765:
766: if (doctored)
767: cache_secure = 0;
768: }
769:
770: #ifdef HAVE_DNSSEC
1.1.1.3 misho 771: if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
1.1.1.2 misho 772: {
1.1.1.3 misho 773: /* Bogus reply, turn into SERVFAIL */
774: SET_RCODE(header, SERVFAIL);
775: munged = 1;
1.1 misho 776: }
1.1.1.2 misho 777:
778: if (option_bool(OPT_DNSSEC_VALID))
1.1.1.3 misho 779: {
780: header->hb4 &= ~HB4_AD;
781:
782: if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
783: header->hb4 |= HB4_AD;
784:
785: /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
786: if (!do_bit)
787: n = rrfilter(header, n, 1);
788: }
1.1.1.2 misho 789: #endif
790:
1.1 misho 791: /* do this after extract_addresses. Ensure NODATA reply and remove
792: nameserver info. */
793:
794: if (munged)
795: {
796: header->ancount = htons(0);
797: header->nscount = htons(0);
798: header->arcount = htons(0);
1.1.1.3 misho 799: header->hb3 &= ~HB3_TC;
1.1 misho 800: }
801:
802: /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
803: sections of the packet. Find the new length here and put back pseudoheader
804: if it was removed. */
805: return resize_packet(header, n, pheader, plen);
806: }
807:
808: /* sets new last_server */
809: void reply_query(int fd, int family, time_t now)
810: {
811: /* packet from peer server, extract data for cache, and send to
812: original requester */
813: struct dns_header *header;
814: union mysockaddr serveraddr;
815: struct frec *forward;
816: socklen_t addrlen = sizeof(serveraddr);
1.1.1.2 misho 817: ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
1.1 misho 818: size_t nn;
819: struct server *server;
1.1.1.2 misho 820: void *hash;
821:
1.1 misho 822: /* packet buffer overwritten */
823: daemon->srv_save = NULL;
824:
825: /* Determine the address of the server replying so that we can mark that as good */
1.1.1.4 ! misho 826: if ((serveraddr.sa.sa_family = family) == AF_INET6)
1.1 misho 827: serveraddr.in6.sin6_flowinfo = 0;
828:
1.1.1.2 misho 829: header = (struct dns_header *)daemon->packet;
1.1.1.4 ! misho 830:
1.1.1.2 misho 831: if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
832: return;
833:
1.1 misho 834: /* spoof check: answer must come from known server, */
835: for (server = daemon->servers; server; server = server->next)
836: if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
837: sockaddr_isequal(&server->addr, &serveraddr))
838: break;
839:
1.1.1.2 misho 840: if (!server)
841: return;
1.1.1.4 ! misho 842:
! 843: /* If sufficient time has elapsed, try and expand UDP buffer size again. */
! 844: if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
! 845: server->edns_pktsz = daemon->edns_pktsz;
! 846:
1.1.1.2 misho 847: hash = hash_questions(header, n, daemon->namebuff);
848:
1.1.1.4 ! misho 849: if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
1.1 misho 850: return;
851:
1.1.1.4 ! misho 852: #ifdef HAVE_DUMPFILE
! 853: dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
! 854: (void *)header, n, &serveraddr, NULL);
! 855: #endif
! 856:
1.1.1.3 misho 857: /* log_query gets called indirectly all over the place, so
858: pass these in global variables - sorry. */
1.1.1.4 ! misho 859: daemon->log_display_id = forward->frec_src.log_id;
! 860: daemon->log_source_addr = &forward->frec_src.source;
1.1.1.3 misho 861:
862: if (daemon->ignore_addr && RCODE(header) == NOERROR &&
863: check_for_ignored_address(header, n, daemon->ignore_addr))
864: return;
865:
866: /* Note: if we send extra options in the EDNS0 header, we can't recreate
867: the query from the reply. */
1.1.1.4 ! misho 868: if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
1.1.1.3 misho 869: forward->forwardall == 0 &&
870: !(forward->flags & FREC_HAS_EXTRADATA))
1.1 misho 871: /* for broken servers, attempt to send to another one. */
872: {
873: unsigned char *pheader;
874: size_t plen;
875: int is_sign;
1.1.1.4 ! misho 876:
! 877: #ifdef HAVE_DNSSEC
! 878: if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
! 879: {
! 880: struct server *start;
! 881:
! 882: blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
! 883: plen = forward->stash_len;
! 884:
! 885: forward->forwardall = 2; /* only retry once */
! 886: start = forward->sentto;
! 887:
! 888: /* for non-domain specific servers, see if we can find another to try. */
! 889: if ((forward->sentto->flags & SERV_TYPE) == 0)
! 890: while (1)
! 891: {
! 892: if (!(start = start->next))
! 893: start = daemon->servers;
! 894: if (start == forward->sentto)
! 895: break;
! 896:
! 897: if ((start->flags & SERV_TYPE) == 0 &&
! 898: (start->flags & SERV_DO_DNSSEC))
! 899: break;
! 900: }
! 901:
! 902:
! 903: fd = -1;
! 904:
! 905: if (start->sfd)
! 906: fd = start->sfd->fd;
! 907: else
! 908: {
! 909: if (start->addr.sa.sa_family == AF_INET6)
! 910: {
! 911: /* may have changed family */
! 912: if (forward->rfd6 || (forward->rfd6 = allocate_rfd(AF_INET6)))
! 913: fd = forward->rfd6->fd;
! 914: }
! 915: else
! 916: {
! 917: /* may have changed family */
! 918: if (forward->rfd4 || (forward->rfd4 = allocate_rfd(AF_INET)))
! 919: fd = forward->rfd4->fd;
! 920: }
! 921: }
! 922:
! 923: /* Can't get socket. */
! 924: if (fd == -1)
! 925: return;
! 926:
! 927: #ifdef HAVE_DUMPFILE
! 928: dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
! 929: #endif
! 930:
! 931: while (retry_send(sendto(fd, (char *)header, plen, 0,
! 932: &start->addr.sa,
! 933: sa_len(&start->addr))));
! 934:
! 935: if (start->addr.sa.sa_family == AF_INET)
! 936: log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (union all_addr *)&start->addr.in.sin_addr, "dnssec");
! 937: else
! 938: log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&start->addr.in6.sin6_addr, "dnssec");
! 939:
! 940: return;
! 941: }
! 942: #endif
1.1 misho 943:
1.1.1.4 ! misho 944: /* In strict order mode, there must be a server later in the chain
! 945: left to send to, otherwise without the forwardall mechanism,
! 946: code further on will cycle around the list forwever if they
! 947: all return REFUSED. Note that server is always non-NULL before
! 948: this executes. */
! 949: if (option_bool(OPT_ORDER))
! 950: for (server = forward->sentto->next; server; server = server->next)
! 951: if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
! 952: break;
! 953:
1.1 misho 954: /* recreate query from reply */
1.1.1.3 misho 955: pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
1.1.1.4 ! misho 956: if (!is_sign && server)
1.1 misho 957: {
958: header->ancount = htons(0);
959: header->nscount = htons(0);
960: header->arcount = htons(0);
961: if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
962: {
1.1.1.3 misho 963: header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
964: header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
965: if (forward->flags & FREC_CHECKING_DISABLED)
966: header->hb4 |= HB4_CD;
967: if (forward->flags & FREC_AD_QUESTION)
968: header->hb4 |= HB4_AD;
969: if (forward->flags & FREC_DO_QUESTION)
970: add_do_bit(header, nn, (unsigned char *)pheader + plen);
971: forward_query(-1, NULL, NULL, 0, header, nn, now, forward, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION);
1.1 misho 972: return;
973: }
974: }
975: }
1.1.1.2 misho 976:
977: server = forward->sentto;
1.1 misho 978: if ((forward->sentto->flags & SERV_TYPE) == 0)
979: {
1.1.1.2 misho 980: if (RCODE(header) == REFUSED)
1.1 misho 981: server = NULL;
982: else
983: {
984: struct server *last_server;
985:
986: /* find good server by address if possible, otherwise assume the last one we sent to */
987: for (last_server = daemon->servers; last_server; last_server = last_server->next)
988: if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
989: sockaddr_isequal(&last_server->addr, &serveraddr))
990: {
991: server = last_server;
992: break;
993: }
994: }
995: if (!option_bool(OPT_ALL_SERVERS))
996: daemon->last_server = server;
997: }
1.1.1.3 misho 998:
999: /* We tried resending to this server with a smaller maximum size and got an answer.
1.1.1.4 ! misho 1000: Make that permanent. To avoid reduxing the packet size for a single dropped packet,
1.1.1.3 misho 1001: only do this when we get a truncated answer, or one larger than the safe size. */
1.1.1.4 ! misho 1002: if (forward->sentto->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
1.1.1.3 misho 1003: ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
1.1.1.4 ! misho 1004: {
! 1005: forward->sentto->edns_pktsz = SAFE_PKTSZ;
! 1006: forward->sentto->pktsz_reduced = now;
! 1007: (void)prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
! 1008: my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
! 1009: }
! 1010:
! 1011:
1.1 misho 1012: /* If the answer is an error, keep the forward record in place in case
1013: we get a good reply from another server. Kill it when we've
1014: had replies from all to avoid filling the forwarding table when
1015: everything is broken */
1.1.1.3 misho 1016: if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
1.1 misho 1017: {
1.1.1.3 misho 1018: int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
1.1.1.4 ! misho 1019:
1.1.1.2 misho 1020: if (option_bool(OPT_NO_REBIND))
1021: check_rebind = !(forward->flags & FREC_NOREBIND);
1022:
1023: /* Don't cache replies where DNSSEC validation was turned off, either
1024: the upstream server told us so, or the original query specified it. */
1025: if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
1026: no_cache_dnssec = 1;
1027:
1028: #ifdef HAVE_DNSSEC
1.1.1.4 ! misho 1029: if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
1.1.1.3 misho 1030: option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
1.1.1.2 misho 1031: {
1.1.1.3 misho 1032: int status = 0;
1.1 misho 1033:
1.1.1.2 misho 1034: /* We've had a reply already, which we're validating. Ignore this duplicate */
1035: if (forward->blocking_query)
1036: return;
1.1.1.3 misho 1037:
1038: /* Truncated answer can't be validated.
1.1.1.4 ! misho 1039: If this is an answer to a DNSSEC-generated query, we still
! 1040: need to get the client to retry over TCP, so return
! 1041: an answer with the TC bit set, even if the actual answer fits.
! 1042: */
1.1.1.3 misho 1043: if (header->hb3 & HB3_TC)
1044: status = STAT_TRUNCATED;
1045:
1046: while (1)
1.1.1.2 misho 1047: {
1.1.1.3 misho 1048: /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
1049: would invite infinite loops, since the answers to DNSKEY and DS queries
1050: will not be cached, so they'll be repeated. */
1051: if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
1.1.1.2 misho 1052: {
1.1.1.3 misho 1053: if (forward->flags & FREC_DNSKEY_QUERY)
1054: status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1055: else if (forward->flags & FREC_DS_QUERY)
1056: status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1.1.1.2 misho 1057: else
1.1.1.3 misho 1058: status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
1.1.1.4 ! misho 1059: !option_bool(OPT_DNSSEC_IGN_NS) && (forward->sentto->flags & SERV_DO_DNSSEC),
! 1060: NULL, NULL, NULL);
! 1061: #ifdef HAVE_DUMPFILE
! 1062: if (status == STAT_BOGUS)
! 1063: dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
! 1064: header, (size_t)n, &serveraddr, NULL);
! 1065: #endif
1.1.1.2 misho 1066: }
1067:
1.1.1.3 misho 1068: /* Can't validate, as we're missing key data. Put this
1069: answer aside, whilst we get that. */
1070: if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
1.1.1.2 misho 1071: {
1.1.1.3 misho 1072: struct frec *new, *orig;
1.1.1.2 misho 1073:
1.1.1.3 misho 1074: /* Free any saved query */
1075: if (forward->stash)
1076: blockdata_free(forward->stash);
1077:
1078: /* Now save reply pending receipt of key data */
1079: if (!(forward->stash = blockdata_alloc((char *)header, n)))
1080: return;
1081: forward->stash_len = n;
1.1.1.2 misho 1082:
1.1.1.3 misho 1083: /* Find the original query that started it all.... */
1084: for (orig = forward; orig->dependent; orig = orig->dependent);
1.1.1.2 misho 1085:
1.1.1.4 ! misho 1086: /* Make sure we don't expire and free the orig frec during the
! 1087: allocation of a new one. */
! 1088: if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, orig)))
1.1.1.3 misho 1089: status = STAT_ABANDONED;
1.1.1.2 misho 1090: else
1091: {
1.1.1.4 ! misho 1092: int querytype, fd, type = SERV_DO_DNSSEC;
1.1.1.3 misho 1093: struct frec *next = new->next;
1094: char *domain;
1095:
1096: *new = *forward; /* copy everything, then overwrite */
1097: new->next = next;
1098: new->blocking_query = NULL;
1099:
1100: /* Find server to forward to. This will normally be the
1101: same as for the original query, but may be another if
1102: servers for domains are involved. */
1.1.1.4 ! misho 1103: if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
1.1.1.3 misho 1104: {
1.1.1.4 ! misho 1105: struct server *start, *new_server = NULL;
! 1106: start = server = forward->sentto;
! 1107:
! 1108: while (1)
! 1109: {
! 1110: if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
! 1111: ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
! 1112: !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
! 1113: {
! 1114: new_server = start;
! 1115: if (server == start)
! 1116: {
! 1117: new_server = NULL;
! 1118: break;
! 1119: }
! 1120: }
! 1121:
! 1122: if (!(start = start->next))
! 1123: start = daemon->servers;
! 1124: if (start == server)
! 1125: break;
! 1126: }
! 1127:
! 1128: if (new_server)
! 1129: server = new_server;
1.1.1.3 misho 1130: }
1.1.1.4 ! misho 1131:
1.1.1.3 misho 1132: new->sentto = server;
1133: new->rfd4 = NULL;
1134: new->rfd6 = NULL;
1.1.1.4 ! misho 1135: new->frec_src.next = NULL;
! 1136: new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
! 1137: new->forwardall = 0;
1.1.1.3 misho 1138:
1139: new->dependent = forward; /* to find query awaiting new one. */
1140: forward->blocking_query = new; /* for garbage cleaning */
1141: /* validate routines leave name of required record in daemon->keyname */
1142: if (status == STAT_NEED_KEY)
1143: {
1144: new->flags |= FREC_DNSKEY_QUERY;
1.1.1.4 ! misho 1145: querytype = T_DNSKEY;
1.1.1.3 misho 1146: }
1147: else
1.1.1.2 misho 1148: {
1.1.1.3 misho 1149: new->flags |= FREC_DS_QUERY;
1.1.1.4 ! misho 1150: querytype = T_DS;
1.1.1.2 misho 1151: }
1.1.1.4 ! misho 1152:
! 1153: nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
! 1154: daemon->keyname, forward->class, querytype, server->edns_pktsz);
! 1155:
! 1156: if (server->addr.sa.sa_family == AF_INET)
! 1157: log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (union all_addr *)&(server->addr.in.sin_addr),
! 1158: querystr("dnssec-query", querytype));
! 1159: else
! 1160: log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
! 1161: querystr("dnssec-query", querytype));
! 1162:
! 1163: memcpy(new->hash, hash_questions(header, nn, daemon->namebuff), HASH_SIZE);
1.1.1.3 misho 1164: new->new_id = get_id();
1165: header->id = htons(new->new_id);
1166: /* Save query for retransmission */
1167: new->stash = blockdata_alloc((char *)header, nn);
1168: new->stash_len = nn;
1169:
1170: /* Don't resend this. */
1171: daemon->srv_save = NULL;
1172:
1173: if (server->sfd)
1174: fd = server->sfd->fd;
1.1.1.2 misho 1175: else
1.1.1.3 misho 1176: {
1177: fd = -1;
1178: if (server->addr.sa.sa_family == AF_INET6)
1179: {
1180: if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1181: fd = new->rfd6->fd;
1182: }
1183: else
1184: {
1185: if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1186: fd = new->rfd4->fd;
1187: }
1188: }
1189:
1190: if (fd != -1)
1.1.1.2 misho 1191: {
1.1.1.3 misho 1192: #ifdef HAVE_CONNTRACK
1193: /* Copy connection mark of incoming query to outgoing connection. */
1194: if (option_bool(OPT_CONNTRACK))
1195: {
1196: unsigned int mark;
1.1.1.4 ! misho 1197: if (get_incoming_mark(&orig->frec_src.source, &orig->frec_src.dest, 0, &mark))
1.1.1.3 misho 1198: setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1199: }
1200: #endif
1.1.1.4 ! misho 1201:
! 1202: #ifdef HAVE_DUMPFILE
! 1203: dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
! 1204: #endif
! 1205:
1.1.1.3 misho 1206: while (retry_send(sendto(fd, (char *)header, nn, 0,
1207: &server->addr.sa,
1208: sa_len(&server->addr))));
1209: server->queries++;
1.1.1.2 misho 1210: }
1.1.1.3 misho 1211: }
1.1.1.2 misho 1212: return;
1213: }
1214:
1.1.1.3 misho 1215: /* Validated original answer, all done. */
1216: if (!forward->dependent)
1217: break;
1218:
1.1.1.4 ! misho 1219: /* validated subsidiary query, (and cached result)
1.1.1.3 misho 1220: pop that and return to the previous query we were working on. */
1.1.1.2 misho 1221: struct frec *prev = forward->dependent;
1222: free_frec(forward);
1223: forward = prev;
1224: forward->blocking_query = NULL; /* already gone */
1225: blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1226: n = forward->stash_len;
1227: }
1.1.1.3 misho 1228:
1229:
1230: no_cache_dnssec = 0;
1.1.1.2 misho 1231:
1232: if (status == STAT_TRUNCATED)
1233: header->hb3 |= HB3_TC;
1234: else
1235: {
1.1.1.3 misho 1236: char *result, *domain = "result";
1.1.1.2 misho 1237:
1.1.1.3 misho 1238: if (status == STAT_ABANDONED)
1239: {
1240: result = "ABANDONED";
1241: status = STAT_BOGUS;
1242: }
1.1.1.2 misho 1243: else
1244: result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1245:
1.1.1.3 misho 1246: if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1247: domain = daemon->namebuff;
1248:
1.1.1.4 ! misho 1249: log_query(F_SECSTAT, domain, NULL, result);
1.1.1.2 misho 1250: }
1251:
1252: if (status == STAT_SECURE)
1253: cache_secure = 1;
1254: else if (status == STAT_BOGUS)
1.1.1.3 misho 1255: {
1256: no_cache_dnssec = 1;
1257: bogusanswer = 1;
1258: }
1.1.1.2 misho 1259: }
1.1.1.4 ! misho 1260:
! 1261: #endif
! 1262:
1.1.1.2 misho 1263: /* restore CD bit to the value in the query */
1264: if (forward->flags & FREC_CHECKING_DISABLED)
1265: header->hb4 |= HB4_CD;
1266: else
1267: header->hb4 &= ~HB4_CD;
1.1.1.4 ! misho 1268:
! 1269: /* Never cache answers which are contingent on the source or MAC address EDSN0 option,
! 1270: since the cache is ignorant of such things. */
! 1271: if (forward->flags & FREC_NO_CACHE)
! 1272: no_cache_dnssec = 1;
1.1.1.2 misho 1273:
1.1.1.3 misho 1274: if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
1.1.1.2 misho 1275: forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1.1.1.4 ! misho 1276: forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->frec_src.source)))
1.1 misho 1277: {
1.1.1.4 ! misho 1278: struct frec_src *src;
! 1279:
! 1280: header->id = htons(forward->frec_src.orig_id);
1.1 misho 1281: header->hb4 |= HB4_RA; /* recursion if available */
1.1.1.3 misho 1282: #ifdef HAVE_DNSSEC
1283: /* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
1.1.1.4 ! misho 1284: greater than the no-EDNS0-implied 512 to have space for the RRSIGS. If, having stripped them and the EDNS0
1.1.1.3 misho 1285: header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1286: if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1287: {
1288: header->ancount = htons(0);
1289: header->nscount = htons(0);
1290: header->arcount = htons(0);
1291: header->hb3 |= HB3_TC;
1292: nn = resize_packet(header, nn, NULL, 0);
1293: }
1294: #endif
1.1.1.4 ! misho 1295:
! 1296: for (src = &forward->frec_src; src; src = src->next)
! 1297: {
! 1298: header->id = htons(src->orig_id);
! 1299:
! 1300: #ifdef HAVE_DUMPFILE
! 1301: dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source);
! 1302: #endif
! 1303:
! 1304: send_from(src->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
! 1305: &src->source, &src->dest, src->iface);
! 1306:
! 1307: if (option_bool(OPT_EXTRALOG) && src != &forward->frec_src)
! 1308: {
! 1309: daemon->log_display_id = src->log_id;
! 1310: daemon->log_source_addr = &src->source;
! 1311: log_query(F_UPSTREAM, "query", NULL, "duplicate");
! 1312: }
! 1313: }
1.1 misho 1314: }
1.1.1.4 ! misho 1315:
1.1 misho 1316: free_frec(forward); /* cancel */
1317: }
1318: }
1319:
1320:
1321: void receive_query(struct listener *listen, time_t now)
1322: {
1323: struct dns_header *header = (struct dns_header *)daemon->packet;
1324: union mysockaddr source_addr;
1.1.1.3 misho 1325: unsigned char *pheader;
1326: unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
1.1.1.4 ! misho 1327: union all_addr dst_addr;
1.1 misho 1328: struct in_addr netmask, dst_addr_4;
1329: size_t m;
1330: ssize_t n;
1.1.1.3 misho 1331: int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
1.1.1.2 misho 1332: #ifdef HAVE_AUTH
1333: int local_auth = 0;
1334: #endif
1.1 misho 1335: struct iovec iov[1];
1336: struct msghdr msg;
1337: struct cmsghdr *cmptr;
1338: union {
1339: struct cmsghdr align; /* this ensures alignment */
1340: char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1341: #if defined(HAVE_LINUX_NETWORK)
1342: char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
1343: #elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1344: char control[CMSG_SPACE(sizeof(struct in_addr)) +
1345: CMSG_SPACE(sizeof(unsigned int))];
1346: #elif defined(IP_RECVDSTADDR)
1347: char control[CMSG_SPACE(sizeof(struct in_addr)) +
1348: CMSG_SPACE(sizeof(struct sockaddr_dl))];
1349: #endif
1350: } control_u;
1.1.1.4 ! misho 1351: int family = listen->addr.sa.sa_family;
1.1.1.2 misho 1352: /* Can always get recvd interface for IPv6 */
1.1.1.4 ! misho 1353: int check_dst = !option_bool(OPT_NOWILD) || family == AF_INET6;
1.1.1.2 misho 1354:
1.1 misho 1355: /* packet buffer overwritten */
1356: daemon->srv_save = NULL;
1357:
1.1.1.4 ! misho 1358: dst_addr_4.s_addr = dst_addr.addr4.s_addr = 0;
1.1 misho 1359: netmask.s_addr = 0;
1360:
1361: if (option_bool(OPT_NOWILD) && listen->iface)
1362: {
1363: auth_dns = listen->iface->dns_auth;
1364:
1.1.1.4 ! misho 1365: if (family == AF_INET)
1.1 misho 1366: {
1.1.1.4 ! misho 1367: dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
1.1 misho 1368: netmask = listen->iface->netmask;
1369: }
1370: }
1371:
1372: iov[0].iov_base = daemon->packet;
1373: iov[0].iov_len = daemon->edns_pktsz;
1374:
1375: msg.msg_control = control_u.control;
1376: msg.msg_controllen = sizeof(control_u);
1377: msg.msg_flags = 0;
1378: msg.msg_name = &source_addr;
1379: msg.msg_namelen = sizeof(source_addr);
1380: msg.msg_iov = iov;
1381: msg.msg_iovlen = 1;
1382:
1383: if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
1384: return;
1385:
1386: if (n < (int)sizeof(struct dns_header) ||
1387: (msg.msg_flags & MSG_TRUNC) ||
1388: (header->hb3 & HB3_QR))
1389: return;
1.1.1.4 ! misho 1390:
! 1391: /* Clear buffer beyond request to avoid risk of
! 1392: information disclosure. */
! 1393: memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
1.1 misho 1394:
1.1.1.4 ! misho 1395: source_addr.sa.sa_family = family;
1.1.1.2 misho 1396:
1.1.1.4 ! misho 1397: if (family == AF_INET)
1.1.1.2 misho 1398: {
1399: /* Source-port == 0 is an error, we can't send back to that.
1400: http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1401: if (source_addr.in.sin_port == 0)
1402: return;
1403: }
1404: else
1405: {
1406: /* Source-port == 0 is an error, we can't send back to that. */
1407: if (source_addr.in6.sin6_port == 0)
1408: return;
1409: source_addr.in6.sin6_flowinfo = 0;
1410: }
1411:
1412: /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1413: if (option_bool(OPT_LOCAL_SERVICE))
1414: {
1415: struct addrlist *addr;
1.1.1.4 ! misho 1416:
! 1417: if (family == AF_INET6)
1.1.1.2 misho 1418: {
1419: for (addr = daemon->interface_addrs; addr; addr = addr->next)
1420: if ((addr->flags & ADDRLIST_IPV6) &&
1.1.1.4 ! misho 1421: is_same_net6(&addr->addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
1.1.1.2 misho 1422: break;
1423: }
1424: else
1425: {
1426: struct in_addr netmask;
1427: for (addr = daemon->interface_addrs; addr; addr = addr->next)
1428: {
1.1.1.3 misho 1429: netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
1.1.1.2 misho 1430: if (!(addr->flags & ADDRLIST_IPV6) &&
1.1.1.4 ! misho 1431: is_same_net(addr->addr.addr4, source_addr.in.sin_addr, netmask))
1.1.1.2 misho 1432: break;
1433: }
1434: }
1435: if (!addr)
1436: {
1437: static int warned = 0;
1438: if (!warned)
1439: {
1440: my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1441: warned = 1;
1442: }
1443: return;
1444: }
1445: }
1446:
1447: if (check_dst)
1.1 misho 1448: {
1449: struct ifreq ifr;
1450:
1451: if (msg.msg_controllen < sizeof(struct cmsghdr))
1452: return;
1453:
1454: #if defined(HAVE_LINUX_NETWORK)
1.1.1.4 ! misho 1455: if (family == AF_INET)
1.1 misho 1456: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1457: if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
1458: {
1459: union {
1460: unsigned char *c;
1461: struct in_pktinfo *p;
1462: } p;
1463: p.c = CMSG_DATA(cmptr);
1.1.1.4 ! misho 1464: dst_addr_4 = dst_addr.addr4 = p.p->ipi_spec_dst;
1.1 misho 1465: if_index = p.p->ipi_ifindex;
1466: }
1467: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1.1.1.4 ! misho 1468: if (family == AF_INET)
1.1 misho 1469: {
1470: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1471: {
1472: union {
1473: unsigned char *c;
1474: unsigned int *i;
1475: struct in_addr *a;
1476: #ifndef HAVE_SOLARIS_NETWORK
1477: struct sockaddr_dl *s;
1478: #endif
1479: } p;
1480: p.c = CMSG_DATA(cmptr);
1481: if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
1.1.1.4 ! misho 1482: dst_addr_4 = dst_addr.addr4 = *(p.a);
1.1 misho 1483: else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1484: #ifdef HAVE_SOLARIS_NETWORK
1485: if_index = *(p.i);
1486: #else
1487: if_index = p.s->sdl_index;
1488: #endif
1489: }
1490: }
1491: #endif
1492:
1.1.1.4 ! misho 1493: if (family == AF_INET6)
1.1 misho 1494: {
1495: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1496: if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
1497: {
1498: union {
1499: unsigned char *c;
1500: struct in6_pktinfo *p;
1501: } p;
1502: p.c = CMSG_DATA(cmptr);
1503:
1.1.1.4 ! misho 1504: dst_addr.addr6 = p.p->ipi6_addr;
1.1 misho 1505: if_index = p.p->ipi6_ifindex;
1506: }
1507: }
1508:
1509: /* enforce available interface configuration */
1510:
1511: if (!indextoname(listen->fd, if_index, ifr.ifr_name))
1512: return;
1513:
1.1.1.4 ! misho 1514: if (!iface_check(family, &dst_addr, ifr.ifr_name, &auth_dns))
1.1 misho 1515: {
1516: if (!option_bool(OPT_CLEVERBIND))
1.1.1.2 misho 1517: enumerate_interfaces(0);
1.1.1.4 ! misho 1518: if (!loopback_exception(listen->fd, family, &dst_addr, ifr.ifr_name) &&
! 1519: !label_exception(if_index, family, &dst_addr))
1.1 misho 1520: return;
1521: }
1522:
1.1.1.4 ! misho 1523: if (family == AF_INET && option_bool(OPT_LOCALISE))
1.1 misho 1524: {
1525: struct irec *iface;
1526:
1.1.1.4 ! misho 1527: /* get the netmask of the interface which has the address we were sent to.
! 1528: This is no necessarily the interface we arrived on. */
1.1 misho 1529:
1530: for (iface = daemon->interfaces; iface; iface = iface->next)
1531: if (iface->addr.sa.sa_family == AF_INET &&
1532: iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1533: break;
1534:
1535: /* interface may be new */
1536: if (!iface && !option_bool(OPT_CLEVERBIND))
1.1.1.2 misho 1537: enumerate_interfaces(0);
1.1 misho 1538:
1539: for (iface = daemon->interfaces; iface; iface = iface->next)
1540: if (iface->addr.sa.sa_family == AF_INET &&
1541: iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1542: break;
1543:
1544: /* If we failed, abandon localisation */
1545: if (iface)
1546: netmask = iface->netmask;
1547: else
1548: dst_addr_4.s_addr = 0;
1549: }
1550: }
1.1.1.3 misho 1551:
1552: /* log_query gets called indirectly all over the place, so
1553: pass these in global variables - sorry. */
1554: daemon->log_display_id = ++daemon->log_id;
1555: daemon->log_source_addr = &source_addr;
1.1.1.4 ! misho 1556:
! 1557: #ifdef HAVE_DUMPFILE
! 1558: dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
! 1559: #endif
! 1560:
1.1 misho 1561: if (extract_request(header, (size_t)n, daemon->namebuff, &type))
1562: {
1.1.1.2 misho 1563: #ifdef HAVE_AUTH
1564: struct auth_zone *zone;
1565: #endif
1566: char *types = querystr(auth_dns ? "auth" : "query", type);
1567:
1.1.1.4 ! misho 1568: if (family == AF_INET)
1.1 misho 1569: log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 1570: (union all_addr *)&source_addr.in.sin_addr, types);
1.1 misho 1571: else
1572: log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 1573: (union all_addr *)&source_addr.in6.sin6_addr, types);
1.1 misho 1574:
1575: #ifdef HAVE_AUTH
1.1.1.2 misho 1576: /* find queries for zones we're authoritative for, and answer them directly */
1.1.1.3 misho 1577: if (!auth_dns && !option_bool(OPT_LOCALISE))
1.1.1.2 misho 1578: for (zone = daemon->auth_zones; zone; zone = zone->next)
1579: if (in_zone(zone, daemon->namebuff, NULL))
1580: {
1581: auth_dns = 1;
1582: local_auth = 1;
1583: break;
1584: }
1585: #endif
1.1.1.3 misho 1586:
1587: #ifdef HAVE_LOOP
1588: /* Check for forwarding loop */
1589: if (detect_loop(daemon->namebuff, type))
1590: return;
1591: #endif
1.1.1.2 misho 1592: }
1593:
1.1.1.3 misho 1594: if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
1595: {
1596: unsigned short flags;
1597:
1598: have_pseudoheader = 1;
1599: GETSHORT(udp_size, pheader);
1600: pheader += 2; /* ext_rcode */
1601: GETSHORT(flags, pheader);
1602:
1603: if (flags & 0x8000)
1604: do_bit = 1;/* do bit */
1605:
1606: /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1607: (bounded by the maximum configured). If no EDNS0, then it
1608: defaults to 512 */
1609: if (udp_size > daemon->edns_pktsz)
1610: udp_size = daemon->edns_pktsz;
1.1.1.4 ! misho 1611: else if (udp_size < PACKETSZ)
! 1612: udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
1.1.1.3 misho 1613: }
1614:
1.1.1.2 misho 1615: #ifdef HAVE_AUTH
1.1 misho 1616: if (auth_dns)
1617: {
1.1.1.3 misho 1618: m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1619: local_auth, do_bit, have_pseudoheader);
1.1 misho 1620: if (m >= 1)
1.1.1.2 misho 1621: {
1622: send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1623: (char *)header, m, &source_addr, &dst_addr, if_index);
1.1.1.4 ! misho 1624: daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
1.1.1.2 misho 1625: }
1.1 misho 1626: }
1627: else
1628: #endif
1629: {
1.1.1.3 misho 1630: int ad_reqd = do_bit;
1631: /* RFC 6840 5.7 */
1632: if (header->hb4 & HB4_AD)
1633: ad_reqd = 1;
1634:
1635: m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1636: dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
1.1 misho 1637:
1638: if (m >= 1)
1639: {
1640: send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1641: (char *)header, m, &source_addr, &dst_addr, if_index);
1.1.1.4 ! misho 1642: daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
1.1 misho 1643: }
1644: else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
1.1.1.2 misho 1645: header, (size_t)n, now, NULL, ad_reqd, do_bit))
1.1.1.4 ! misho 1646: daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
1.1 misho 1647: else
1.1.1.4 ! misho 1648: daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
1.1 misho 1649: }
1650: }
1651:
1.1.1.2 misho 1652: #ifdef HAVE_DNSSEC
1.1.1.4 ! misho 1653: /* Recurse up the key hierarchy */
1.1.1.3 misho 1654: static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
1655: int class, char *name, char *keyname, struct server *server,
1656: int have_mark, unsigned int mark, int *keycount)
1.1.1.2 misho 1657: {
1.1.1.3 misho 1658: int new_status;
1659: unsigned char *packet = NULL;
1660: unsigned char *payload = NULL;
1661: struct dns_header *new_header = NULL;
1662: u16 *length = NULL;
1.1.1.4 ! misho 1663:
1.1.1.2 misho 1664: while (1)
1665: {
1.1.1.3 misho 1666: int type = SERV_DO_DNSSEC;
1667: char *domain;
1668: size_t m;
1.1.1.2 misho 1669: unsigned char c1, c2;
1.1.1.4 ! misho 1670: struct server *firstsendto = NULL;
! 1671:
1.1.1.3 misho 1672: /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1.1.1.2 misho 1673: if (--(*keycount) == 0)
1.1.1.3 misho 1674: new_status = STAT_ABANDONED;
1675: else if (status == STAT_NEED_KEY)
1676: new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1677: else if (status == STAT_NEED_DS)
1678: new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1679: else
1.1.1.4 ! misho 1680: new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
! 1681: !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
! 1682: NULL, NULL, NULL);
1.1.1.3 misho 1683:
1684: if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1685: break;
1.1.1.2 misho 1686:
1.1.1.3 misho 1687: /* Can't validate because we need a key/DS whose name now in keyname.
1688: Make query for same, and recurse to validate */
1689: if (!packet)
1.1.1.2 misho 1690: {
1.1.1.3 misho 1691: packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1692: payload = &packet[2];
1693: new_header = (struct dns_header *)payload;
1694: length = (u16 *)packet;
1.1.1.2 misho 1695: }
1696:
1.1.1.3 misho 1697: if (!packet)
1.1.1.2 misho 1698: {
1.1.1.3 misho 1699: new_status = STAT_ABANDONED;
1700: break;
1.1.1.2 misho 1701: }
1.1.1.4 ! misho 1702:
1.1.1.3 misho 1703: m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
1.1.1.4 ! misho 1704: new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, server->edns_pktsz);
1.1.1.3 misho 1705:
1706: *length = htons(m);
1.1.1.2 misho 1707:
1.1.1.3 misho 1708: /* Find server to forward to. This will normally be the
1709: same as for the original query, but may be another if
1710: servers for domains are involved. */
1.1.1.4 ! misho 1711: if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
1.1.1.3 misho 1712: {
1.1.1.4 ! misho 1713: new_status = STAT_ABANDONED;
! 1714: break;
! 1715: }
! 1716:
! 1717: while (1)
! 1718: {
! 1719: int data_sent = 0;
! 1720:
! 1721: if (!firstsendto)
! 1722: firstsendto = server;
! 1723: else
1.1.1.3 misho 1724: {
1.1.1.4 ! misho 1725: if (!(server = server->next))
! 1726: server = daemon->servers;
! 1727: if (server == firstsendto)
1.1.1.3 misho 1728: {
1.1.1.4 ! misho 1729: /* can't find server to accept our query. */
! 1730: new_status = STAT_ABANDONED;
! 1731: break;
1.1.1.3 misho 1732: }
1733: }
1.1.1.4 ! misho 1734:
! 1735: if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
! 1736: (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
! 1737: (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
! 1738: continue;
! 1739:
! 1740: retry:
! 1741: /* may need to make new connection. */
! 1742: if (server->tcpfd == -1)
1.1.1.2 misho 1743: {
1.1.1.4 ! misho 1744: if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
! 1745: continue; /* No good, next server */
! 1746:
1.1.1.3 misho 1747: #ifdef HAVE_CONNTRACK
1.1.1.4 ! misho 1748: /* Copy connection mark of incoming query to outgoing connection. */
! 1749: if (have_mark)
! 1750: setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1.1.1.3 misho 1751: #endif
1.1.1.4 ! misho 1752:
! 1753: if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1))
! 1754: {
! 1755: close(server->tcpfd);
! 1756: server->tcpfd = -1;
! 1757: continue; /* No good, next server */
1.1.1.2 misho 1758: }
1.1.1.4 ! misho 1759:
! 1760: #ifdef MSG_FASTOPEN
! 1761: while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
! 1762: MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
! 1763:
! 1764: if (errno == 0)
! 1765: data_sent = 1;
! 1766: #endif
! 1767:
! 1768: if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
! 1769: {
! 1770: close(server->tcpfd);
! 1771: server->tcpfd = -1;
! 1772: continue; /* No good, next server */
! 1773: }
! 1774:
! 1775: server->flags &= ~SERV_GOT_TCP;
! 1776: }
! 1777:
! 1778: if ((!data_sent && !read_write(server->tcpfd, packet, m + sizeof(u16), 0)) ||
! 1779: !read_write(server->tcpfd, &c1, 1, 1) ||
! 1780: !read_write(server->tcpfd, &c2, 1, 1) ||
! 1781: !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
! 1782: {
! 1783: close(server->tcpfd);
! 1784: server->tcpfd = -1;
! 1785: /* We get data then EOF, reopen connection to same server,
! 1786: else try next. This avoids DoS from a server which accepts
! 1787: connections and then closes them. */
! 1788: if (server->flags & SERV_GOT_TCP)
! 1789: goto retry;
! 1790: else
! 1791: continue;
1.1.1.2 misho 1792: }
1793:
1.1.1.4 ! misho 1794:
! 1795: if (server->addr.sa.sa_family == AF_INET)
! 1796: log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (union all_addr *)&(server->addr.in.sin_addr),
! 1797: querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
! 1798: else
! 1799: log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
! 1800: querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
! 1801:
! 1802: server->flags |= SERV_GOT_TCP;
! 1803:
! 1804: m = (c1 << 8) | c2;
! 1805: new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1.1.1.3 misho 1806: break;
1.1.1.2 misho 1807: }
1.1.1.3 misho 1808:
1809: if (new_status != STAT_OK)
1810: break;
1.1.1.2 misho 1811: }
1.1.1.4 ! misho 1812:
1.1.1.3 misho 1813: if (packet)
1814: free(packet);
1815:
1.1.1.2 misho 1816: return new_status;
1817: }
1818: #endif
1819:
1820:
1.1 misho 1821: /* The daemon forks before calling this: it should deal with one connection,
1.1.1.4 ! misho 1822: blocking as necessary, and then return. Note, need to be a bit careful
1.1 misho 1823: about resources for debug mode, when the fork is suppressed: that's
1824: done by the caller. */
1825: unsigned char *tcp_request(int confd, time_t now,
1826: union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
1827: {
1828: size_t size = 0;
1829: int norebind = 0;
1.1.1.2 misho 1830: #ifdef HAVE_AUTH
1831: int local_auth = 0;
1832: #endif
1.1.1.3 misho 1833: int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
1.1.1.4 ! misho 1834: int check_subnet, cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
1.1 misho 1835: size_t m;
1836: unsigned short qtype;
1837: unsigned int gotname;
1838: unsigned char c1, c2;
1.1.1.2 misho 1839: /* Max TCP packet + slop + size */
1840: unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1841: unsigned char *payload = &packet[2];
1842: /* largest field in header is 16-bits, so this is still sufficiently aligned */
1843: struct dns_header *header = (struct dns_header *)payload;
1844: u16 *length = (u16 *)packet;
1.1 misho 1845: struct server *last_server;
1846: struct in_addr dst_addr_4;
1847: union mysockaddr peer_addr;
1848: socklen_t peer_len = sizeof(union mysockaddr);
1.1.1.3 misho 1849: int query_count = 0;
1850: unsigned char *pheader;
1851: unsigned int mark = 0;
1852: int have_mark = 0;
1853:
1854: (void)mark;
1855: (void)have_mark;
1856:
1.1 misho 1857: if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1858: return packet;
1.1.1.3 misho 1859:
1860: #ifdef HAVE_CONNTRACK
1861: /* Get connection mark of incoming query to set on outgoing connections. */
1862: if (option_bool(OPT_CONNTRACK))
1863: {
1.1.1.4 ! misho 1864: union all_addr local;
! 1865:
1.1.1.3 misho 1866: if (local_addr->sa.sa_family == AF_INET6)
1.1.1.4 ! misho 1867: local.addr6 = local_addr->in6.sin6_addr;
1.1.1.3 misho 1868: else
1.1.1.4 ! misho 1869: local.addr4 = local_addr->in.sin_addr;
1.1.1.3 misho 1870:
1871: have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1872: }
1873: #endif
1874:
1.1.1.2 misho 1875: /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1876: if (option_bool(OPT_LOCAL_SERVICE))
1877: {
1878: struct addrlist *addr;
1.1.1.4 ! misho 1879:
1.1.1.2 misho 1880: if (peer_addr.sa.sa_family == AF_INET6)
1881: {
1882: for (addr = daemon->interface_addrs; addr; addr = addr->next)
1883: if ((addr->flags & ADDRLIST_IPV6) &&
1.1.1.4 ! misho 1884: is_same_net6(&addr->addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
1.1.1.2 misho 1885: break;
1886: }
1887: else
1888: {
1889: struct in_addr netmask;
1890: for (addr = daemon->interface_addrs; addr; addr = addr->next)
1891: {
1.1.1.3 misho 1892: netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
1.1.1.2 misho 1893: if (!(addr->flags & ADDRLIST_IPV6) &&
1.1.1.4 ! misho 1894: is_same_net(addr->addr.addr4, peer_addr.in.sin_addr, netmask))
1.1.1.2 misho 1895: break;
1896: }
1897: }
1898: if (!addr)
1899: {
1900: my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1901: return packet;
1902: }
1903: }
1.1 misho 1904:
1905: while (1)
1906: {
1.1.1.3 misho 1907: if (query_count == TCP_MAX_QUERIES ||
1908: !packet ||
1.1 misho 1909: !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1910: !(size = c1 << 8 | c2) ||
1.1.1.2 misho 1911: !read_write(confd, payload, size, 1))
1.1 misho 1912: return packet;
1913:
1914: if (size < (int)sizeof(struct dns_header))
1915: continue;
1.1.1.4 ! misho 1916:
! 1917: /* Clear buffer beyond request to avoid risk of
! 1918: information disclosure. */
! 1919: memset(payload + size, 0, 65536 - size);
1.1 misho 1920:
1.1.1.3 misho 1921: query_count++;
1.1 misho 1922:
1.1.1.3 misho 1923: /* log_query gets called indirectly all over the place, so
1924: pass these in global variables - sorry. */
1925: daemon->log_display_id = ++daemon->log_id;
1926: daemon->log_source_addr = &peer_addr;
1927:
1.1 misho 1928: /* save state of "cd" flag in query */
1.1.1.2 misho 1929: if ((checking_disabled = header->hb4 & HB4_CD))
1930: no_cache_dnssec = 1;
1.1 misho 1931:
1932: if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
1933: {
1.1.1.2 misho 1934: #ifdef HAVE_AUTH
1935: struct auth_zone *zone;
1936: #endif
1937: char *types = querystr(auth_dns ? "auth" : "query", qtype);
1.1 misho 1938:
1939: if (peer_addr.sa.sa_family == AF_INET)
1940: log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 1941: (union all_addr *)&peer_addr.in.sin_addr, types);
1.1 misho 1942: else
1943: log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 1944: (union all_addr *)&peer_addr.in6.sin6_addr, types);
1.1.1.2 misho 1945:
1946: #ifdef HAVE_AUTH
1947: /* find queries for zones we're authoritative for, and answer them directly */
1.1.1.3 misho 1948: if (!auth_dns && !option_bool(OPT_LOCALISE))
1.1.1.2 misho 1949: for (zone = daemon->auth_zones; zone; zone = zone->next)
1950: if (in_zone(zone, daemon->namebuff, NULL))
1951: {
1952: auth_dns = 1;
1953: local_auth = 1;
1954: break;
1955: }
1956: #endif
1.1 misho 1957: }
1958:
1959: if (local_addr->sa.sa_family == AF_INET)
1960: dst_addr_4 = local_addr->in.sin_addr;
1961: else
1962: dst_addr_4.s_addr = 0;
1963:
1.1.1.3 misho 1964: do_bit = 0;
1965:
1966: if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
1967: {
1968: unsigned short flags;
1969:
1970: have_pseudoheader = 1;
1971: pheader += 4; /* udp_size, ext_rcode */
1972: GETSHORT(flags, pheader);
1973:
1974: if (flags & 0x8000)
1975: do_bit = 1; /* do bit */
1976: }
1977:
1.1 misho 1978: #ifdef HAVE_AUTH
1979: if (auth_dns)
1.1.1.3 misho 1980: m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1981: local_auth, do_bit, have_pseudoheader);
1.1 misho 1982: else
1983: #endif
1984: {
1.1.1.3 misho 1985: int ad_reqd = do_bit;
1986: /* RFC 6840 5.7 */
1987: if (header->hb4 & HB4_AD)
1988: ad_reqd = 1;
1989:
1990: /* m > 0 if answered from cache */
1991: m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1992: dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
1.1 misho 1993:
1994: /* Do this by steam now we're not in the select() loop */
1.1.1.3 misho 1995: check_log_writer(1);
1.1 misho 1996:
1997: if (m == 0)
1998: {
1999: unsigned int flags = 0;
1.1.1.4 ! misho 2000: union all_addr *addrp = NULL;
1.1.1.3 misho 2001: int type = SERV_DO_DNSSEC;
1.1 misho 2002: char *domain = NULL;
1.1.1.4 ! misho 2003: unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
! 2004:
! 2005: size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet, &cacheable);
1.1.1.3 misho 2006:
1.1 misho 2007: if (gotname)
2008: flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
1.1.1.4 ! misho 2009:
! 2010: #ifdef HAVE_DNSSEC
! 2011: if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
! 2012: {
! 2013: size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
! 2014:
! 2015: /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
! 2016: this allows it to select auth servers when one is returning bad data. */
! 2017: if (option_bool(OPT_DNSSEC_DEBUG))
! 2018: header->hb4 |= HB4_CD;
! 2019: }
! 2020: #endif
! 2021:
! 2022: /* Check if we added a pheader on forwarding - may need to
! 2023: strip it from the reply. */
! 2024: if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
! 2025: added_pheader = 1;
! 2026:
1.1.1.3 misho 2027: type &= ~SERV_DO_DNSSEC;
2028:
1.1 misho 2029: if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
2030: last_server = daemon->servers;
2031: else
2032: last_server = daemon->last_server;
2033:
2034: if (!flags && last_server)
2035: {
2036: struct server *firstsendto = NULL;
1.1.1.4 ! misho 2037: unsigned char hash[HASH_SIZE];
! 2038: memcpy(hash, hash_questions(header, (unsigned int)size, daemon->namebuff), HASH_SIZE);
! 2039:
1.1 misho 2040: /* Loop round available servers until we succeed in connecting to one.
1.1.1.4 ! misho 2041: Note that this code subtly ensures that consecutive queries on this connection
1.1 misho 2042: which can go to the same server, do so. */
2043: while (1)
2044: {
1.1.1.4 ! misho 2045: int data_sent = 0;
! 2046:
1.1 misho 2047: if (!firstsendto)
2048: firstsendto = last_server;
2049: else
2050: {
2051: if (!(last_server = last_server->next))
2052: last_server = daemon->servers;
2053:
2054: if (last_server == firstsendto)
2055: break;
2056: }
2057:
2058: /* server for wrong domain */
2059: if (type != (last_server->flags & SERV_TYPE) ||
1.1.1.3 misho 2060: (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
2061: (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1.1 misho 2062: continue;
1.1.1.4 ! misho 2063:
! 2064: retry:
! 2065: *length = htons(size);
! 2066:
1.1 misho 2067: if (last_server->tcpfd == -1)
2068: {
2069: if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
2070: continue;
2071:
1.1.1.3 misho 2072: #ifdef HAVE_CONNTRACK
2073: /* Copy connection mark of incoming query to outgoing connection. */
2074: if (have_mark)
2075: setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1.1.1.4 ! misho 2076: #endif
1.1.1.3 misho 2077:
1.1.1.4 ! misho 2078: if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1)))
1.1 misho 2079: {
2080: close(last_server->tcpfd);
2081: last_server->tcpfd = -1;
2082: continue;
2083: }
2084:
1.1.1.4 ! misho 2085: #ifdef MSG_FASTOPEN
! 2086: while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
! 2087: MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
! 2088:
! 2089: if (errno == 0)
! 2090: data_sent = 1;
! 2091: #endif
! 2092:
! 2093: if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
1.1.1.2 misho 2094: {
1.1.1.4 ! misho 2095: close(last_server->tcpfd);
! 2096: last_server->tcpfd = -1;
! 2097: continue;
1.1.1.2 misho 2098: }
1.1.1.4 ! misho 2099:
! 2100: last_server->flags &= ~SERV_GOT_TCP;
1.1 misho 2101: }
2102:
1.1.1.2 misho 2103: /* get query name again for logging - may have been overwritten */
2104: if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
2105: strcpy(daemon->namebuff, "query");
1.1 misho 2106:
1.1.1.4 ! misho 2107: if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
1.1 misho 2108: !read_write(last_server->tcpfd, &c1, 1, 1) ||
1.1.1.2 misho 2109: !read_write(last_server->tcpfd, &c2, 1, 1) ||
2110: !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
1.1 misho 2111: {
2112: close(last_server->tcpfd);
2113: last_server->tcpfd = -1;
1.1.1.4 ! misho 2114: /* We get data then EOF, reopen connection to same server,
! 2115: else try next. This avoids DoS from a server which accepts
! 2116: connections and then closes them. */
! 2117: if (last_server->flags & SERV_GOT_TCP)
! 2118: goto retry;
! 2119: else
! 2120: continue;
! 2121: }
1.1 misho 2122:
1.1.1.4 ! misho 2123: last_server->flags |= SERV_GOT_TCP;
! 2124:
1.1 misho 2125: m = (c1 << 8) | c2;
2126:
2127: if (last_server->addr.sa.sa_family == AF_INET)
2128: log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 2129: (union all_addr *)&last_server->addr.in.sin_addr, NULL);
1.1 misho 2130: else
2131: log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1.1.1.4 ! misho 2132: (union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
1.1.1.2 misho 2133:
2134: #ifdef HAVE_DNSSEC
1.1.1.3 misho 2135: if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
1.1.1.2 misho 2136: {
2137: int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
1.1.1.3 misho 2138: int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
2139: last_server, have_mark, mark, &keycount);
2140: char *result, *domain = "result";
2141:
2142: if (status == STAT_ABANDONED)
2143: {
2144: result = "ABANDONED";
2145: status = STAT_BOGUS;
2146: }
1.1.1.2 misho 2147: else
2148: result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
2149:
1.1.1.3 misho 2150: if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
2151: domain = daemon->namebuff;
2152:
1.1.1.4 ! misho 2153: log_query(F_SECSTAT, domain, NULL, result);
1.1.1.2 misho 2154:
2155: if (status == STAT_BOGUS)
1.1.1.3 misho 2156: {
2157: no_cache_dnssec = 1;
2158: bogusanswer = 1;
2159: }
2160:
1.1.1.2 misho 2161: if (status == STAT_SECURE)
2162: cache_secure = 1;
2163: }
2164: #endif
2165:
2166: /* restore CD bit to the value in the query */
2167: if (checking_disabled)
2168: header->hb4 |= HB4_CD;
2169: else
2170: header->hb4 &= ~HB4_CD;
1.1 misho 2171:
2172: /* There's no point in updating the cache, since this process will exit and
2173: lose the information after a few queries. We make this call for the alias and
2174: bogus-nxdomain side-effects. */
2175: /* If the crc of the question section doesn't match the crc we sent, then
2176: someone might be attempting to insert bogus values into the cache by
2177: sending replies containing questions and bogus answers. */
1.1.1.4 ! misho 2178: if (memcmp(hash, hash_questions(header, (unsigned int)m, daemon->namebuff), HASH_SIZE) != 0)
1.1.1.2 misho 2179: {
2180: m = 0;
2181: break;
2182: }
2183:
1.1.1.4 ! misho 2184: /* Never cache answers which are contingent on the source or MAC address EDSN0 option,
! 2185: since the cache is ignorant of such things. */
! 2186: if (!cacheable)
! 2187: no_cache_dnssec = 1;
! 2188:
1.1.1.2 misho 2189: m = process_reply(header, now, last_server, (unsigned int)m,
1.1.1.3 misho 2190: option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
2191: ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
1.1 misho 2192:
2193: break;
2194: }
2195: }
2196:
2197: /* In case of local answer or no connections made. */
2198: if (m == 0)
1.1.1.4 ! misho 2199: {
! 2200: m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
! 2201: if (have_pseudoheader)
! 2202: m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
! 2203: }
1.1 misho 2204: }
2205: }
2206:
1.1.1.3 misho 2207: check_log_writer(1);
1.1 misho 2208:
1.1.1.2 misho 2209: *length = htons(m);
2210:
2211: if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
1.1 misho 2212: return packet;
2213: }
2214: }
2215:
2216: static struct frec *allocate_frec(time_t now)
2217: {
2218: struct frec *f;
2219:
2220: if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
2221: {
2222: f->next = daemon->frec_list;
2223: f->time = now;
2224: f->sentto = NULL;
2225: f->rfd4 = NULL;
2226: f->flags = 0;
2227: f->rfd6 = NULL;
1.1.1.2 misho 2228: #ifdef HAVE_DNSSEC
2229: f->dependent = NULL;
2230: f->blocking_query = NULL;
2231: f->stash = NULL;
2232: #endif
1.1 misho 2233: daemon->frec_list = f;
2234: }
2235:
2236: return f;
2237: }
2238:
1.1.1.3 misho 2239: struct randfd *allocate_rfd(int family)
1.1 misho 2240: {
2241: static int finger = 0;
2242: int i;
2243:
2244: /* limit the number of sockets we have open to avoid starvation of
2245: (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2246:
2247: for (i = 0; i < RANDOM_SOCKS; i++)
2248: if (daemon->randomsocks[i].refcount == 0)
2249: {
2250: if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2251: break;
2252:
2253: daemon->randomsocks[i].refcount = 1;
2254: daemon->randomsocks[i].family = family;
2255: return &daemon->randomsocks[i];
2256: }
2257:
2258: /* No free ones or cannot get new socket, grab an existing one */
2259: for (i = 0; i < RANDOM_SOCKS; i++)
2260: {
2261: int j = (i+finger) % RANDOM_SOCKS;
2262: if (daemon->randomsocks[j].refcount != 0 &&
2263: daemon->randomsocks[j].family == family &&
2264: daemon->randomsocks[j].refcount != 0xffff)
2265: {
2266: finger = j;
2267: daemon->randomsocks[j].refcount++;
2268: return &daemon->randomsocks[j];
2269: }
2270: }
2271:
2272: return NULL; /* doom */
2273: }
1.1.1.3 misho 2274:
2275: void free_rfd(struct randfd *rfd)
2276: {
2277: if (rfd && --(rfd->refcount) == 0)
2278: close(rfd->fd);
2279: }
2280:
1.1 misho 2281: static void free_frec(struct frec *f)
2282: {
1.1.1.4 ! misho 2283: struct frec_src *last;
! 2284:
! 2285: /* add back to freelist if not the record builtin to every frec. */
! 2286: for (last = f->frec_src.next; last && last->next; last = last->next) ;
! 2287: if (last)
! 2288: {
! 2289: last->next = daemon->free_frec_src;
! 2290: daemon->free_frec_src = f->frec_src.next;
! 2291: }
! 2292:
! 2293: f->frec_src.next = NULL;
1.1.1.3 misho 2294: free_rfd(f->rfd4);
1.1 misho 2295: f->rfd4 = NULL;
2296: f->sentto = NULL;
2297: f->flags = 0;
1.1.1.3 misho 2298: free_rfd(f->rfd6);
1.1 misho 2299: f->rfd6 = NULL;
1.1.1.2 misho 2300:
2301: #ifdef HAVE_DNSSEC
2302: if (f->stash)
2303: {
2304: blockdata_free(f->stash);
2305: f->stash = NULL;
2306: }
2307:
2308: /* Anything we're waiting on is pointless now, too */
2309: if (f->blocking_query)
2310: free_frec(f->blocking_query);
2311: f->blocking_query = NULL;
2312: f->dependent = NULL;
2313: #endif
1.1 misho 2314: }
2315:
1.1.1.4 ! misho 2316:
! 2317:
1.1 misho 2318: /* if wait==NULL return a free or older than TIMEOUT record.
2319: else return *wait zero if one available, or *wait is delay to
2320: when the oldest in-use record will expire. Impose an absolute
1.1.1.2 misho 2321: limit of 4*TIMEOUT before we wipe things (for random sockets).
1.1.1.4 ! misho 2322: If force is non-NULL, always return a result, even if we have
! 2323: to allocate above the limit, and never free the record pointed
! 2324: to by the force argument. */
! 2325: struct frec *get_new_frec(time_t now, int *wait, struct frec *force)
1.1 misho 2326: {
2327: struct frec *f, *oldest, *target;
2328: int count;
2329:
2330: if (wait)
2331: *wait = 0;
2332:
2333: for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
2334: if (!f->sentto)
2335: target = f;
2336: else
2337: {
1.1.1.3 misho 2338: #ifdef HAVE_DNSSEC
2339: /* Don't free DNSSEC sub-queries here, as we may end up with
2340: dangling references to them. They'll go when their "real" query
2341: is freed. */
1.1.1.4 ! misho 2342: if (!f->dependent && f != force)
1.1.1.3 misho 2343: #endif
2344: {
2345: if (difftime(now, f->time) >= 4*TIMEOUT)
2346: {
2347: free_frec(f);
2348: target = f;
2349: }
2350:
2351:
2352: if (!oldest || difftime(f->time, oldest->time) <= 0)
2353: oldest = f;
2354: }
1.1 misho 2355: }
2356:
2357: if (target)
2358: {
2359: target->time = now;
2360: return target;
2361: }
2362:
2363: /* can't find empty one, use oldest if there is one
2364: and it's older than timeout */
1.1.1.4 ! misho 2365: if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
1.1 misho 2366: {
2367: /* keep stuff for twice timeout if we can by allocating a new
2368: record instead */
2369: if (difftime(now, oldest->time) < 2*TIMEOUT &&
2370: count <= daemon->ftabsize &&
2371: (f = allocate_frec(now)))
2372: return f;
2373:
2374: if (!wait)
2375: {
2376: free_frec(oldest);
2377: oldest->time = now;
2378: }
2379: return oldest;
2380: }
2381:
2382: /* none available, calculate time 'till oldest record expires */
1.1.1.2 misho 2383: if (!force && count > daemon->ftabsize)
1.1 misho 2384: {
1.1.1.2 misho 2385: static time_t last_log = 0;
2386:
1.1 misho 2387: if (oldest && wait)
2388: *wait = oldest->time + (time_t)TIMEOUT - now;
1.1.1.2 misho 2389:
2390: if ((int)difftime(now, last_log) > 5)
2391: {
2392: last_log = now;
2393: my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2394: }
2395:
1.1 misho 2396: return NULL;
2397: }
2398:
2399: if (!(f = allocate_frec(now)) && wait)
2400: /* wait one second on malloc failure */
2401: *wait = 1;
2402:
2403: return f; /* OK if malloc fails and this is NULL */
2404: }
1.1.1.4 ! misho 2405:
! 2406: static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash)
1.1 misho 2407: {
2408: struct frec *f;
2409:
2410: for(f = daemon->frec_list; f; f = f->next)
2411: if (f->sentto && f->new_id == id &&
1.1.1.4 ! misho 2412: (memcmp(hash, f->hash, HASH_SIZE) == 0))
! 2413: {
! 2414: /* sent from random port */
! 2415: if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
! 2416: return f;
! 2417:
! 2418: if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd)
! 2419: return f;
! 2420:
! 2421: /* sent to upstream from bound socket. */
! 2422: if (f->sentto->sfd && f->sentto->sfd->fd == fd)
! 2423: return f;
! 2424: }
1.1 misho 2425:
2426: return NULL;
2427: }
2428:
2429: static struct frec *lookup_frec_by_sender(unsigned short id,
2430: union mysockaddr *addr,
1.1.1.2 misho 2431: void *hash)
1.1 misho 2432: {
2433: struct frec *f;
1.1.1.4 ! misho 2434: struct frec_src *src;
! 2435:
! 2436: for (f = daemon->frec_list; f; f = f->next)
! 2437: if (f->sentto &&
! 2438: !(f->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) &&
! 2439: memcmp(hash, f->hash, HASH_SIZE) == 0)
! 2440: for (src = &f->frec_src; src; src = src->next)
! 2441: if (src->orig_id == id &&
! 2442: sockaddr_isequal(&src->source, addr))
! 2443: return f;
! 2444:
! 2445: return NULL;
! 2446: }
! 2447:
! 2448: static struct frec *lookup_frec_by_query(void *hash, unsigned int flags)
! 2449: {
! 2450: struct frec *f;
! 2451:
! 2452: /* FREC_DNSKEY and FREC_DS_QUERY are never set in flags, so the test below
! 2453: ensures that no frec created for internal DNSSEC query can be returned here.
! 2454:
! 2455: Similarly FREC_NO_CACHE is never set in flags, so a query which is
! 2456: contigent on a particular source address EDNS0 option will never be matched. */
! 2457:
! 2458: #define FLAGMASK (FREC_CHECKING_DISABLED | FREC_AD_QUESTION | FREC_DO_QUESTION \
! 2459: | FREC_HAS_PHEADER | FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_NO_CACHE)
1.1 misho 2460:
2461: for(f = daemon->frec_list; f; f = f->next)
2462: if (f->sentto &&
1.1.1.4 ! misho 2463: (f->flags & FLAGMASK) == flags &&
! 2464: memcmp(hash, f->hash, HASH_SIZE) == 0)
1.1 misho 2465: return f;
1.1.1.4 ! misho 2466:
1.1 misho 2467: return NULL;
1.1.1.3 misho 2468: }
1.1.1.4 ! misho 2469:
1.1.1.3 misho 2470: /* Send query packet again, if we can. */
2471: void resend_query()
2472: {
2473: if (daemon->srv_save)
2474: {
2475: int fd;
2476:
2477: if (daemon->srv_save->sfd)
2478: fd = daemon->srv_save->sfd->fd;
2479: else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2480: fd = daemon->rfd_save->fd;
2481: else
2482: return;
2483:
2484: while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2485: &daemon->srv_save->addr.sa,
2486: sa_len(&daemon->srv_save->addr))));
2487: }
1.1 misho 2488: }
2489:
2490: /* A server record is going away, remove references to it */
2491: void server_gone(struct server *server)
2492: {
2493: struct frec *f;
2494:
2495: for (f = daemon->frec_list; f; f = f->next)
2496: if (f->sentto && f->sentto == server)
2497: free_frec(f);
2498:
2499: if (daemon->last_server == server)
2500: daemon->last_server = NULL;
2501:
2502: if (daemon->srv_save == server)
2503: daemon->srv_save = NULL;
2504: }
2505:
2506: /* return unique random ids. */
1.1.1.2 misho 2507: static unsigned short get_id(void)
1.1 misho 2508: {
2509: unsigned short ret = 0;
1.1.1.4 ! misho 2510: struct frec *f;
1.1 misho 2511:
1.1.1.4 ! misho 2512: while (1)
! 2513: {
! 2514: ret = rand16();
! 2515:
! 2516: /* ensure id is unique. */
! 2517: for (f = daemon->frec_list; f; f = f->next)
! 2518: if (f->sentto && f->new_id == ret)
! 2519: break;
! 2520:
! 2521: if (!f)
! 2522: return ret;
! 2523: }
1.1 misho 2524: }
2525:
2526:
2527:
2528:
2529:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>