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