blob: 14cdfaa28fc9898845d72a6c67c1845177aa172f [file] [log] [blame]
Simon Kelleyc49778d2016-01-06 18:52:33 +00001/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
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
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 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.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 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/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley8a9be9e2014-01-25 23:17:21 +000019static struct frec *lookup_frec(unsigned short id, void *hash);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +010021 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +000022 void *hash);
23static unsigned short get_id(void);
Simon Kelley1a6bca82008-07-11 11:11:42 +010024static void free_frec(struct frec *f);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000025
Simon Kelley824af852008-02-12 20:43:05 +000026/* Send a UDP packet with its source address set as "source"
Simon Kelley44a2a312004-03-10 20:04:35 +000027 unless nowild is true, when we just send it with the kernel default */
Simon Kelley29689cf2012-03-22 14:01:00 +000028int send_from(int fd, int nowild, char *packet, size_t len,
29 union mysockaddr *to, struct all_addr *source,
Simon Kelley50303b12012-04-04 22:13:17 +010030 unsigned int iface)
Simon Kelley9e4abcb2004-01-22 19:47:41 +000031{
Simon Kelley44a2a312004-03-10 20:04:35 +000032 struct msghdr msg;
33 struct iovec iov[1];
Simon Kelley44a2a312004-03-10 20:04:35 +000034 union {
35 struct cmsghdr align; /* this ensures alignment */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010036#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +000037 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
38#elif defined(IP_SENDSRCADDR)
39 char control[CMSG_SPACE(sizeof(struct in_addr))];
40#endif
41#ifdef HAVE_IPV6
42 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
43#endif
44 } control_u;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010045
Simon Kelley44a2a312004-03-10 20:04:35 +000046 iov[0].iov_base = packet;
47 iov[0].iov_len = len;
48
Simon Kelleyfeba5c12004-07-27 20:28:58 +010049 msg.msg_control = NULL;
50 msg.msg_controllen = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +000051 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;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010056
Simon Kelley26128d22004-11-14 16:43:54 +000057 if (!nowild)
Simon Kelleyfeba5c12004-07-27 20:28:58 +010058 {
Simon Kelley26128d22004-11-14 16:43:54 +000059 struct cmsghdr *cmptr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010060 msg.msg_control = &control_u;
61 msg.msg_controllen = sizeof(control_u);
Simon Kelley26128d22004-11-14 16:43:54 +000062 cmptr = CMSG_FIRSTHDR(&msg);
Simon Kelley44a2a312004-03-10 20:04:35 +000063
Simon Kelley26128d22004-11-14 16:43:54 +000064 if (to->sa.sa_family == AF_INET)
65 {
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010066#if defined(HAVE_LINUX_NETWORK)
Simon Kelley8ef5ada2010-06-03 19:42:45 +010067 struct in_pktinfo p;
68 p.ipi_ifindex = 0;
69 p.ipi_spec_dst = source->addr.addr4;
70 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Simon Kelley26128d22004-11-14 16:43:54 +000071 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
Simon Kelleyc72daea2012-01-05 21:33:27 +000072 cmptr->cmsg_level = IPPROTO_IP;
Simon Kelley26128d22004-11-14 16:43:54 +000073 cmptr->cmsg_type = IP_PKTINFO;
74#elif defined(IP_SENDSRCADDR)
Simon Kelley8ef5ada2010-06-03 19:42:45 +010075 memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
Simon Kelley26128d22004-11-14 16:43:54 +000076 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
77 cmptr->cmsg_level = IPPROTO_IP;
78 cmptr->cmsg_type = IP_SENDSRCADDR;
Simon Kelley44a2a312004-03-10 20:04:35 +000079#endif
Simon Kelley26128d22004-11-14 16:43:54 +000080 }
Simon Kelley26128d22004-11-14 16:43:54 +000081 else
Simon Kelleyb8187c82005-11-26 21:46:27 +000082#ifdef HAVE_IPV6
Simon Kelley26128d22004-11-14 16:43:54 +000083 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +010084 struct in6_pktinfo p;
85 p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
86 p.ipi6_addr = source->addr.addr6;
87 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Simon Kelley26128d22004-11-14 16:43:54 +000088 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
Simon Kelley316e2732010-01-22 20:16:09 +000089 cmptr->cmsg_type = daemon->v6pktinfo;
Simon Kelleyc72daea2012-01-05 21:33:27 +000090 cmptr->cmsg_level = IPPROTO_IPV6;
Simon Kelley26128d22004-11-14 16:43:54 +000091 }
Simon Kelley3d8df262005-08-29 12:19:27 +010092#else
Simon Kelleyc72daea2012-01-05 21:33:27 +000093 (void)iface; /* eliminate warning */
Simon Kelley26128d22004-11-14 16:43:54 +000094#endif
95 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +010096
Simon Kelleyff841eb2015-03-11 21:36:30 +000097 while (retry_send(sendmsg(fd, &msg, 0)));
98
99 /* If interface is still in DAD, EINVAL results - ignore that. */
100 if (errno != 0 && errno != EINVAL)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100101 {
Simon Kelley50303b12012-04-04 22:13:17 +0100102 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
Simon Kelley29689cf2012-03-22 14:01:00 +0000103 return 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100104 }
Simon Kelley29d28dd2012-12-03 14:05:59 +0000105
Simon Kelley29689cf2012-03-22 14:01:00 +0000106 return 1;
Simon Kelley44a2a312004-03-10 20:04:35 +0000107}
108
Simon Kelley367341f2016-01-12 15:58:23 +0000109static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
110 char *qdomain, int *type, char **domain, int *norebind)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100111
112{
113 /* If the query ends in the domain in one of our servers, set
114 domain to point to that name. We find the largest match to allow both
115 domain.org and sub.domain.org to exist. */
116
117 unsigned int namelen = strlen(qdomain);
118 unsigned int matchlen = 0;
119 struct server *serv;
Simon Kelley28866e92011-02-14 20:19:14 +0000120 unsigned int flags = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100121
Simon Kelley3be34542004-09-11 19:12:13 +0100122 for (serv = daemon->servers; serv; serv=serv->next)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100123 /* domain matches take priority over NODOTS matches */
Simon Kelley3d8df262005-08-29 12:19:27 +0100124 if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100125 {
Simon Kelley28866e92011-02-14 20:19:14 +0000126 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100127 *type = SERV_FOR_NODOTS;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100128 if (serv->flags & SERV_NO_ADDR)
Simon Kelley36717ee2004-09-20 19:20:58 +0100129 flags = F_NXDOMAIN;
130 else if (serv->flags & SERV_LITERAL_ADDRESS)
131 {
132 if (sflag & qtype)
133 {
134 flags = sflag;
135 if (serv->addr.sa.sa_family == AF_INET)
136 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100137#ifdef HAVE_IPV6
Simon Kelley36717ee2004-09-20 19:20:58 +0100138 else
139 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100140#endif
Simon Kelley36717ee2004-09-20 19:20:58 +0100141 }
Simon Kelley824af852008-02-12 20:43:05 +0000142 else if (!flags || (flags & F_NXDOMAIN))
Simon Kelley36717ee2004-09-20 19:20:58 +0100143 flags = F_NOERR;
144 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100145 }
146 else if (serv->flags & SERV_HAS_DOMAIN)
147 {
148 unsigned int domainlen = strlen(serv->domain);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000149 char *matchstart = qdomain + namelen - domainlen;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100150 if (namelen >= domainlen &&
Simon Kelleyb8187c82005-11-26 21:46:27 +0000151 hostname_isequal(matchstart, serv->domain) &&
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100152 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100153 {
Simon Kelley92be34a2016-01-16 18:39:54 +0000154 if ((serv->flags & SERV_NO_REBIND) && norebind)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100155 *norebind = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000156 else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100157 {
Simon Kelley28866e92011-02-14 20:19:14 +0000158 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
159 /* implement priority rules for --address and --server for same domain.
160 --address wins if the address is for the correct AF
161 --server wins otherwise. */
162 if (domainlen != 0 && domainlen == matchlen)
Simon Kelley36717ee2004-09-20 19:20:58 +0100163 {
Simon Kelley28866e92011-02-14 20:19:14 +0000164 if ((serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100165 {
Simon Kelley28866e92011-02-14 20:19:14 +0000166 if (!(sflag & qtype) && flags == 0)
167 continue;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100168 }
Simon Kelley28866e92011-02-14 20:19:14 +0000169 else
170 {
171 if (flags & (F_IPV4 | F_IPV6))
172 continue;
173 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100174 }
Simon Kelley28866e92011-02-14 20:19:14 +0000175
176 if (domainlen >= matchlen)
177 {
Simon Kelley367341f2016-01-12 15:58:23 +0000178 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
Simon Kelley28866e92011-02-14 20:19:14 +0000179 *domain = serv->domain;
180 matchlen = domainlen;
181 if (serv->flags & SERV_NO_ADDR)
182 flags = F_NXDOMAIN;
183 else if (serv->flags & SERV_LITERAL_ADDRESS)
184 {
185 if (sflag & qtype)
186 {
187 flags = sflag;
188 if (serv->addr.sa.sa_family == AF_INET)
189 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
190#ifdef HAVE_IPV6
191 else
192 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
193#endif
194 }
195 else if (!flags || (flags & F_NXDOMAIN))
196 flags = F_NOERR;
197 }
198 else
199 flags = 0;
200 }
201 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100202 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100203 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100204
Simon Kelley7de060b2011-08-26 17:24:52 +0100205 if (flags == 0 && !(qtype & F_QUERY) &&
Simon Kelley28866e92011-02-14 20:19:14 +0000206 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
Simon Kelley7de060b2011-08-26 17:24:52 +0100207 /* don't forward A or AAAA queries for simple names, except the empty name */
208 flags = F_NOERR;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100209
Simon Kelley5aabfc72007-08-29 11:24:47 +0100210 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
Simon Kelleyc1bb8502004-08-11 18:40:17 +0100211 flags = F_NOERR;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100212
Simon Kelley824af852008-02-12 20:43:05 +0000213 if (flags)
214 {
215 int logflags = 0;
216
217 if (flags == F_NXDOMAIN || flags == F_NOERR)
218 logflags = F_NEG | qtype;
219
Simon Kelley1a6bca82008-07-11 11:11:42 +0100220 log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
Simon Kelley824af852008-02-12 20:43:05 +0000221 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100222 else if ((*type) & SERV_USE_RESOLV)
223 {
224 *type = 0; /* use normal servers for this domain */
225 *domain = NULL;
226 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100227 return flags;
228}
Simon Kelley44a2a312004-03-10 20:04:35 +0000229
Simon Kelley824af852008-02-12 20:43:05 +0000230static int forward_query(int udpfd, union mysockaddr *udpaddr,
231 struct all_addr *dst_addr, unsigned int dst_iface,
Simon Kelley83349b82014-02-10 21:02:01 +0000232 struct dns_header *header, size_t plen, time_t now,
Simon Kelley613ad152014-02-25 23:02:28 +0000233 struct frec *forward, int ad_reqd, int do_bit)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000234{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000235 char *domain = NULL;
Simon Kelley367341f2016-01-12 15:58:23 +0000236 int type = SERV_DO_DNSSEC, norebind = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000237 struct all_addr *addrp = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000238 unsigned int flags = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100239 struct server *start = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000240#ifdef HAVE_DNSSEC
241 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley367341f2016-01-12 15:58:23 +0000242 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000243#else
244 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
245 void *hash = &crc;
246#endif
247 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
248
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000249 (void)do_bit;
250
Simon Kelley3d8df262005-08-29 12:19:27 +0100251 /* may be no servers available. */
Simon Kelleyd05dd582016-01-19 21:23:30 +0000252 if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000253 {
Simon Kelleya77cec82015-05-08 16:25:38 +0100254 /* If we didn't get an answer advertising a maximal packet in EDNS,
255 fall back to 1280, which should work everywhere on IPv6.
256 If that generates an answer, it will become the new default
257 for this server */
258 forward->flags |= FREC_TEST_PKTSZ;
259
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000260#ifdef HAVE_DNSSEC
Simon Kelleydac74312014-02-13 16:43:49 +0000261 /* If we've already got an answer to this query, but we're awaiting keys for validation,
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000262 there's no point retrying the query, retry the key query instead...... */
263 if (forward->blocking_query)
264 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000265 int fd, is_sign;
266 unsigned char *pheader;
Simon Kelleya77cec82015-05-08 16:25:38 +0100267
268 forward->flags &= ~FREC_TEST_PKTSZ;
269
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000270 while (forward->blocking_query)
271 forward = forward->blocking_query;
Simon Kelleya77cec82015-05-08 16:25:38 +0100272
273 forward->flags |= FREC_TEST_PKTSZ;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000274
275 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
276 plen = forward->stash_len;
277
Simon Kelley5bb88f02015-12-21 16:23:47 +0000278 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000279 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelleya77cec82015-05-08 16:25:38 +0100280
Simon Kelley2b291912014-03-21 11:13:55 +0000281 if (forward->sentto->addr.sa.sa_family == AF_INET)
Simon Kelley25cf5e32015-01-09 15:53:03 +0000282 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000283#ifdef HAVE_IPV6
284 else
Simon Kelley25cf5e32015-01-09 15:53:03 +0000285 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000286#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
Simon Kelleyff841eb2015-03-11 21:36:30 +0000300 while (retry_send( sendto(fd, (char *)header, plen, 0,
301 &forward->sentto->addr.sa,
302 sa_len(&forward->sentto->addr))));
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000303
304 return 1;
305 }
306#endif
307
Simon Kelleyde379512004-06-22 20:23:33 +0100308 /* retry on existing query, send to all available servers */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000309 domain = forward->sentto->domain;
Simon Kelley824af852008-02-12 20:43:05 +0000310 forward->sentto->failed_queries++;
Simon Kelley28866e92011-02-14 20:19:14 +0000311 if (!option_bool(OPT_ORDER))
Simon Kelleyde379512004-06-22 20:23:33 +0100312 {
Simon Kelley0a852542005-03-23 20:28:59 +0000313 forward->forwardall = 1;
Simon Kelley3be34542004-09-11 19:12:13 +0100314 daemon->last_server = NULL;
Simon Kelleyde379512004-06-22 20:23:33 +0100315 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000316 type = forward->sentto->flags & SERV_TYPE;
Simon Kelley367341f2016-01-12 15:58:23 +0000317#ifdef HAVE_DNSSEC
318 do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
319#endif
320
Simon Kelleyde379512004-06-22 20:23:33 +0100321 if (!(start = forward->sentto->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100322 start = daemon->servers; /* at end of list, recycle */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000323 header->id = htons(forward->new_id);
324 }
325 else
326 {
327 if (gotname)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100328 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000329
Simon Kelley367341f2016-01-12 15:58:23 +0000330#ifdef HAVE_DNSSEC
331 do_dnssec = type & SERV_DO_DNSSEC;
Simon Kelleyf7443d72016-01-19 20:29:57 +0000332#endif
333 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +0000334
Simon Kelleyd05dd582016-01-19 21:23:30 +0000335 if (daemon->servers && !flags)
336 forward = get_new_frec(now, NULL, 0);
337 /* table full - flags == 0, return REFUSED */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000338
339 if (forward)
340 {
Simon Kelley0a852542005-03-23 20:28:59 +0000341 forward->source = *udpaddr;
342 forward->dest = *dst_addr;
343 forward->iface = dst_iface;
Simon Kelley0a852542005-03-23 20:28:59 +0000344 forward->orig_id = ntohs(header->id);
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000345 forward->new_id = get_id();
Simon Kelley832af0b2007-01-21 20:01:28 +0000346 forward->fd = udpfd;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000347 memcpy(forward->hash, hash, HASH_SIZE);
Simon Kelley0a852542005-03-23 20:28:59 +0000348 forward->forwardall = 0;
Simon Kelleyed4c0762013-10-08 20:46:34 +0100349 forward->flags = 0;
Simon Kelley28866e92011-02-14 20:19:14 +0000350 if (norebind)
351 forward->flags |= FREC_NOREBIND;
Simon Kelley572b41e2011-02-18 18:11:18 +0000352 if (header->hb4 & HB4_CD)
Simon Kelley28866e92011-02-14 20:19:14 +0000353 forward->flags |= FREC_CHECKING_DISABLED;
Simon Kelley83349b82014-02-10 21:02:01 +0000354 if (ad_reqd)
355 forward->flags |= FREC_AD_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000356#ifdef HAVE_DNSSEC
357 forward->work_counter = DNSSEC_WORK;
Simon Kelley613ad152014-02-25 23:02:28 +0000358 if (do_bit)
359 forward->flags |= FREC_DO_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000360#endif
Simon Kelley613ad152014-02-25 23:02:28 +0000361
Simon Kelley28866e92011-02-14 20:19:14 +0000362 header->id = htons(forward->new_id);
363
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100364 /* In strict_order mode, always try servers in the order
365 specified in resolv.conf, if a domain is given
366 always try all the available servers,
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000367 otherwise, use the one last known to work. */
368
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100369 if (type == 0)
370 {
Simon Kelley28866e92011-02-14 20:19:14 +0000371 if (option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100372 start = daemon->servers;
373 else if (!(start = daemon->last_server) ||
374 daemon->forwardcount++ > FORWARD_TEST ||
375 difftime(now, daemon->forwardtime) > FORWARD_TIME)
376 {
377 start = daemon->servers;
378 forward->forwardall = 1;
379 daemon->forwardcount = 0;
380 daemon->forwardtime = now;
381 }
382 }
383 else
Simon Kelleyde379512004-06-22 20:23:33 +0100384 {
Simon Kelley3be34542004-09-11 19:12:13 +0100385 start = daemon->servers;
Simon Kelley28866e92011-02-14 20:19:14 +0000386 if (!option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100387 forward->forwardall = 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100388 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000389 }
390 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100391
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000392 /* check for send errors here (no route to host)
393 if we fail to send to all nameservers, send back an error
394 packet straight away (helps modem users when offline) */
395
396 if (!flags && forward)
397 {
Simon Kelleyde379512004-06-22 20:23:33 +0100398 struct server *firstsentto = start;
Simon Kelley33702ab2015-12-28 23:17:15 +0000399 int subnet, forwarded = 0;
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000400 size_t edns0_len;
401
Simon Kelley25cf5e32015-01-09 15:53:03 +0000402 /* If a query is retried, use the log_id for the retry when logging the answer. */
403 forward->log_id = daemon->log_id;
404
Simon Kelley33702ab2015-12-28 23:17:15 +0000405 edns0_len = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
406
407 if (edns0_len != plen)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000408 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000409 plen = edns0_len;
410 forward->flags |= FREC_ADDED_PHEADER;
411
412 if (subnet)
413 forward->flags |= FREC_HAS_SUBNET;
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000414 }
Simon Kelley33702ab2015-12-28 23:17:15 +0000415
Simon Kelley3a237152013-12-12 12:15:50 +0000416#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000417 if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000418 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000419 size_t new = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
Simon Kelley613ad152014-02-25 23:02:28 +0000420
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000421 if (new != plen)
422 forward->flags |= FREC_ADDED_PHEADER;
423
424 plen = new;
425
Simon Kelley5b3bf922014-01-25 17:03:07 +0000426 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
427 this allows it to select auth servers when one is returning bad data. */
428 if (option_bool(OPT_DNSSEC_DEBUG))
429 header->hb4 |= HB4_CD;
Simon Kelley613ad152014-02-25 23:02:28 +0000430
Simon Kelley0fc2f312014-01-08 10:26:58 +0000431 }
Simon Kelley3a237152013-12-12 12:15:50 +0000432#endif
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000433
434 /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
435 if (find_pseudoheader(header, plen, &edns0_len, NULL, NULL, NULL) && edns0_len > 11)
436 forward->flags |= FREC_HAS_EXTRADATA;
Simon Kelleya77cec82015-05-08 16:25:38 +0100437
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000438 while (1)
439 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000440 /* only send to servers dealing with our domain.
441 domain may be NULL, in which case server->domain
442 must be NULL also. */
443
Simon Kelleyde379512004-06-22 20:23:33 +0100444 if (type == (start->flags & SERV_TYPE) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100445 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100446 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000447 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100448 int fd;
449
450 /* find server socket to use, may need to get random one. */
451 if (start->sfd)
452 fd = start->sfd->fd;
453 else
454 {
455#ifdef HAVE_IPV6
456 if (start->addr.sa.sa_family == AF_INET6)
457 {
458 if (!forward->rfd6 &&
459 !(forward->rfd6 = allocate_rfd(AF_INET6)))
460 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100461 daemon->rfd_save = forward->rfd6;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100462 fd = forward->rfd6->fd;
463 }
464 else
465#endif
466 {
467 if (!forward->rfd4 &&
468 !(forward->rfd4 = allocate_rfd(AF_INET)))
469 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100470 daemon->rfd_save = forward->rfd4;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100471 fd = forward->rfd4->fd;
472 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100473
474#ifdef HAVE_CONNTRACK
475 /* Copy connection mark of incoming query to outgoing connection. */
476 if (option_bool(OPT_CONNTRACK))
477 {
478 unsigned int mark;
Giacomo Tazzari797a7af2013-04-22 13:16:37 +0100479 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
Simon Kelley7de060b2011-08-26 17:24:52 +0100480 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
481 }
482#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100483 }
484
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000485#ifdef HAVE_DNSSEC
Simon Kelley5bb88f02015-12-21 16:23:47 +0000486 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000487 {
488 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
489 packet size to 512. But that won't provide space for the RRSIGS in many cases.
490 The RRSIGS will be stripped out before the answer goes back, so the packet should
491 shrink again. So, if we added a do-bit, bump the udp packet size to the value
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000492 known to be OK for this server. We check returned size after stripping and set
493 the truncated bit if it's still too big. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000494 unsigned char *pheader;
495 int is_sign;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000496 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000497 PUTSHORT(start->edns_pktsz, pheader);
498 }
499#endif
500
Simon Kelleyff841eb2015-03-11 21:36:30 +0000501 if (retry_send(sendto(fd, (char *)header, plen, 0,
502 &start->addr.sa,
503 sa_len(&start->addr))))
504 continue;
505
506 if (errno == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000507 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000508 /* Keep info in case we want to re-send this packet */
509 daemon->srv_save = start;
510 daemon->packet_len = plen;
511
Simon Kelleyde379512004-06-22 20:23:33 +0100512 if (!gotname)
Simon Kelley3be34542004-09-11 19:12:13 +0100513 strcpy(daemon->namebuff, "query");
Simon Kelleyde379512004-06-22 20:23:33 +0100514 if (start->addr.sa.sa_family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +0100515 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +0100516 (struct all_addr *)&start->addr.in.sin_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100517#ifdef HAVE_IPV6
518 else
Simon Kelley3be34542004-09-11 19:12:13 +0100519 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +0100520 (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100521#endif
Simon Kelley824af852008-02-12 20:43:05 +0000522 start->queries++;
Simon Kelleyde379512004-06-22 20:23:33 +0100523 forwarded = 1;
524 forward->sentto = start;
Simon Kelley0a852542005-03-23 20:28:59 +0000525 if (!forward->forwardall)
Simon Kelleyde379512004-06-22 20:23:33 +0100526 break;
Simon Kelley0a852542005-03-23 20:28:59 +0000527 forward->forwardall++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000528 }
529 }
530
Simon Kelleyde379512004-06-22 20:23:33 +0100531 if (!(start = start->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100532 start = daemon->servers;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000533
Simon Kelleyde379512004-06-22 20:23:33 +0100534 if (start == firstsentto)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000535 break;
536 }
537
Simon Kelleyde379512004-06-22 20:23:33 +0100538 if (forwarded)
Simon Kelley824af852008-02-12 20:43:05 +0000539 return 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100540
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000541 /* could not send on, prepare to return */
542 header->id = htons(forward->orig_id);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100543 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000544 }
545
546 /* could not send on, return empty answer or address if known for whole domain */
Simon Kelleyb8187c82005-11-26 21:46:27 +0000547 if (udpfd != -1)
548 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000549 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
Simon Kelley54dd3932012-06-20 11:23:38 +0100550 send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000551 }
552
Simon Kelley824af852008-02-12 20:43:05 +0000553 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000554}
555
Simon Kelleyed4c0762013-10-08 20:46:34 +0100556static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100557 int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
558 int check_subnet, union mysockaddr *query_source)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100559{
Simon Kelley36717ee2004-09-20 19:20:58 +0100560 unsigned char *pheader, *sizep;
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000561 char **sets = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +0000562 int munged = 0, is_sign;
Simon Kelleycdeda282006-03-16 20:16:06 +0000563 size_t plen;
564
Simon Kelley83349b82014-02-10 21:02:01 +0000565 (void)ad_reqd;
Simon Kelley982faf42015-04-03 21:42:30 +0100566 (void)do_bit;
567 (void)bogusanswer;
Simon Kelley83349b82014-02-10 21:02:01 +0000568
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000569#ifdef HAVE_IPSET
Simon Kelley82a14af2014-04-13 20:48:57 +0100570 if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000571 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100572 /* Similar algorithm to search_servers. */
573 struct ipsets *ipset_pos;
574 unsigned int namelen = strlen(daemon->namebuff);
575 unsigned int matchlen = 0;
576 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
Simon Kelley6c0cb852014-01-17 14:40:46 +0000577 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100578 unsigned int domainlen = strlen(ipset_pos->domain);
579 char *matchstart = daemon->namebuff + namelen - domainlen;
580 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
581 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
582 domainlen >= matchlen)
583 {
584 matchlen = domainlen;
585 sets = ipset_pos->sets;
586 }
Simon Kelley6c0cb852014-01-17 14:40:46 +0000587 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000588 }
589#endif
590
Simon Kelley5bb88f02015-12-21 16:23:47 +0000591 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100592 {
Simon Kelleyed4c0762013-10-08 20:46:34 +0100593 if (check_subnet && !check_source(header, plen, pheader, query_source))
594 {
595 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
596 return 0;
597 }
Simon Kelley613ad152014-02-25 23:02:28 +0000598
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000599 if (!is_sign)
Simon Kelley613ad152014-02-25 23:02:28 +0000600 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000601 if (added_pheader)
602 {
603 /* client didn't send EDNS0, we added one, strip it off before returning answer. */
604 n = rrfilter(header, n, 0);
605 pheader = NULL;
606 }
607 else
608 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000609 unsigned short udpsz;
610
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000611 /* If upstream is advertising a larger UDP packet size
612 than we allow, trim it so that we don't get overlarge
613 requests for the client. We can't do this for signed packets. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000614 GETSHORT(udpsz, sizep);
615 if (udpsz > daemon->edns_pktsz)
Simon Kelley33702ab2015-12-28 23:17:15 +0000616 {
617 sizep -= 2;
618 PUTSHORT(daemon->edns_pktsz, sizep);
619 }
620
621#ifdef HAVE_DNSSEC
622 /* If the client didn't set the do bit, but we did, reset it. */
623 if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
624 {
625 unsigned short flags;
626 sizep += 2; /* skip RCODE */
627 GETSHORT(flags, sizep);
628 flags &= ~0x8000;
629 sizep -= 2;
630 PUTSHORT(flags, sizep);
631 }
632#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000633 }
Simon Kelley613ad152014-02-25 23:02:28 +0000634 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100635 }
Simon Kelley83349b82014-02-10 21:02:01 +0000636
Simon Kelley28866e92011-02-14 20:19:14 +0000637 /* RFC 4035 sect 4.6 para 3 */
Giovanni Bajo237724c2012-04-05 02:46:52 +0200638 if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
Simon Kelley795501b2014-01-08 18:11:55 +0000639 header->hb4 &= ~HB4_AD;
Simon Kelley3a237152013-12-12 12:15:50 +0000640
Simon Kelley572b41e2011-02-18 18:11:18 +0000641 if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
Simon Kelley8938ae02014-05-01 17:46:25 +0100642 return resize_packet(header, n, pheader, plen);
Simon Kelley36717ee2004-09-20 19:20:58 +0100643
Simon Kelley0a852542005-03-23 20:28:59 +0000644 /* Complain loudly if the upstream server is non-recursive. */
Simon Kelley92be34a2016-01-16 18:39:54 +0000645 if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
Simon Kelley0a852542005-03-23 20:28:59 +0000646 server && !(server->flags & SERV_WARNED_RECURSIVE))
647 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100648 prettyprint_addr(&server->addr, daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100649 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
Simon Kelley28866e92011-02-14 20:19:14 +0000650 if (!option_bool(OPT_LOG))
Simon Kelley0a852542005-03-23 20:28:59 +0000651 server->flags |= SERV_WARNED_RECURSIVE;
652 }
Giovanni Bajoe292e932012-04-22 14:32:02 +0200653
Simon Kelley572b41e2011-02-18 18:11:18 +0000654 if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100655 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100656 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100657 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000658 SET_RCODE(header, NXDOMAIN);
659 header->hb3 &= ~HB3_AA;
Simon Kelley6938f342014-01-26 22:47:39 +0000660 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100661 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100662 else
Simon Kelley36717ee2004-09-20 19:20:58 +0100663 {
Simon Kelley6938f342014-01-26 22:47:39 +0000664 int doctored = 0;
665
Simon Kelley572b41e2011-02-18 18:11:18 +0000666 if (RCODE(header) == NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100667 extract_request(header, n, daemon->namebuff, NULL) &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100668 check_for_local_domain(daemon->namebuff, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100669 {
Simon Kelley36717ee2004-09-20 19:20:58 +0100670 /* if we forwarded a query for a locally known name (because it was for
671 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
672 since we know that the domain exists, even if upstream doesn't */
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100673 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000674 header->hb3 |= HB3_AA;
675 SET_RCODE(header, NOERROR);
Simon Kelley6938f342014-01-26 22:47:39 +0000676 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100677 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000678
Simon Kelley6938f342014-01-26 22:47:39 +0000679 if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
Simon Kelley824af852008-02-12 20:43:05 +0000680 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100681 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
Simon Kelley824af852008-02-12 20:43:05 +0000682 munged = 1;
Simon Kelley6938f342014-01-26 22:47:39 +0000683 cache_secure = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000684 }
Simon Kelley6938f342014-01-26 22:47:39 +0000685
686 if (doctored)
687 cache_secure = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100688 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100689
Simon Kelleya25720a2014-01-14 23:13:55 +0000690#ifdef HAVE_DNSSEC
Simon Kelley33702ab2015-12-28 23:17:15 +0000691 if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
Simon Kelleya25720a2014-01-14 23:13:55 +0000692 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000693 /* Bogus reply, turn into SERVFAIL */
694 SET_RCODE(header, SERVFAIL);
695 munged = 1;
Simon Kelleya25720a2014-01-14 23:13:55 +0000696 }
Simon Kelley6938f342014-01-26 22:47:39 +0000697
698 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000699 {
700 header->hb4 &= ~HB4_AD;
701
702 if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
703 header->hb4 |= HB4_AD;
704
705 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
706 if (!do_bit)
707 n = rrfilter(header, n, 1);
708 }
Simon Kelleya25720a2014-01-14 23:13:55 +0000709#endif
710
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100711 /* do this after extract_addresses. Ensure NODATA reply and remove
712 nameserver info. */
713
714 if (munged)
715 {
716 header->ancount = htons(0);
717 header->nscount = htons(0);
718 header->arcount = htons(0);
Simon Kelley150162b2015-03-27 09:58:26 +0000719 header->hb3 &= ~HB3_TC;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100720 }
721
Simon Kelley36717ee2004-09-20 19:20:58 +0100722 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
723 sections of the packet. Find the new length here and put back pseudoheader
724 if it was removed. */
725 return resize_packet(header, n, pheader, plen);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100726}
727
Simon Kelley3be34542004-09-11 19:12:13 +0100728/* sets new last_server */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100729void reply_query(int fd, int family, time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000730{
731 /* packet from peer server, extract data for cache, and send to
732 original requester */
Simon Kelley572b41e2011-02-18 18:11:18 +0000733 struct dns_header *header;
Simon Kelleyde379512004-06-22 20:23:33 +0100734 union mysockaddr serveraddr;
Simon Kelley832af0b2007-01-21 20:01:28 +0000735 struct frec *forward;
Simon Kelleyde379512004-06-22 20:23:33 +0100736 socklen_t addrlen = sizeof(serveraddr);
Simon Kelley60b68062014-01-08 12:10:28 +0000737 ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
Simon Kelleycdeda282006-03-16 20:16:06 +0000738 size_t nn;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100739 struct server *server;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000740 void *hash;
741#ifndef HAVE_DNSSEC
742 unsigned int crc;
743#endif
744
Simon Kelleycdeda282006-03-16 20:16:06 +0000745 /* packet buffer overwritten */
746 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000747
Simon Kelleyde379512004-06-22 20:23:33 +0100748 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100749 serveraddr.sa.sa_family = family;
Simon Kelleyde379512004-06-22 20:23:33 +0100750#ifdef HAVE_IPV6
751 if (serveraddr.sa.sa_family == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100752 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100753#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000754
Simon Kelley490f9072014-03-24 22:04:42 +0000755 header = (struct dns_header *)daemon->packet;
756
757 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
758 return;
759
Simon Kelley1a6bca82008-07-11 11:11:42 +0100760 /* spoof check: answer must come from known server, */
761 for (server = daemon->servers; server; server = server->next)
762 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
763 sockaddr_isequal(&server->addr, &serveraddr))
764 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000765
766 if (!server)
767 return;
768
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000769#ifdef HAVE_DNSSEC
770 hash = hash_questions(header, n, daemon->namebuff);
771#else
772 hash = &crc;
773 crc = questions_crc(header, n, daemon->namebuff);
774#endif
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100775
Simon Kelley490f9072014-03-24 22:04:42 +0000776 if (!(forward = lookup_frec(ntohs(header->id), hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100777 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000778
Simon Kelley25cf5e32015-01-09 15:53:03 +0000779 /* log_query gets called indirectly all over the place, so
780 pass these in global variables - sorry. */
781 daemon->log_display_id = forward->log_id;
782 daemon->log_source_addr = &forward->source;
783
Glen Huang32fc6db2014-12-27 15:28:12 +0000784 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
785 check_for_ignored_address(header, n, daemon->ignore_addr))
786 return;
787
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000788 /* Note: if we send extra options in the EDNS0 header, we can't recreate
789 the query from the reply. */
Simon Kelley2ae195f2015-01-18 22:20:48 +0000790 if (RCODE(header) == REFUSED &&
Simon Kelley28866e92011-02-14 20:19:14 +0000791 !option_bool(OPT_ORDER) &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000792 forward->forwardall == 0 &&
793 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100794 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000795 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100796 unsigned char *pheader;
797 size_t plen;
798 int is_sign;
Simon Kelley832af0b2007-01-21 20:01:28 +0000799
Simon Kelley1a6bca82008-07-11 11:11:42 +0100800 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000801 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100802 if (!is_sign)
Simon Kelley832af0b2007-01-21 20:01:28 +0000803 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100804 header->ancount = htons(0);
805 header->nscount = htons(0);
806 header->arcount = htons(0);
807 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
808 {
swiggerbd7bfa22015-06-01 20:54:59 +0100809 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000810 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000811 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000812 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000813 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000814 header->hb4 |= HB4_AD;
815 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000816 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000817 forward_query(-1, NULL, NULL, 0, header, nn, now, forward, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100818 return;
819 }
820 }
821 }
Simon Kelley3a237152013-12-12 12:15:50 +0000822
823 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100824 if ((forward->sentto->flags & SERV_TYPE) == 0)
825 {
Simon Kelley51967f92014-03-25 21:07:00 +0000826 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100827 server = NULL;
828 else
829 {
830 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000831
Simon Kelley1a6bca82008-07-11 11:11:42 +0100832 /* find good server by address if possible, otherwise assume the last one we sent to */
833 for (last_server = daemon->servers; last_server; last_server = last_server->next)
834 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
835 sockaddr_isequal(&last_server->addr, &serveraddr))
836 {
837 server = last_server;
838 break;
839 }
840 }
Simon Kelley28866e92011-02-14 20:19:14 +0000841 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100842 daemon->last_server = server;
843 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100844
845 /* We tried resending to this server with a smaller maximum size and got an answer.
Simon Kelley86fa1042015-05-10 13:50:59 +0100846 Make that permanent. To avoid reduxing the packet size for an single dropped packet,
847 only do this when we get a truncated answer, or one larger than the safe size. */
848 if (server && (forward->flags & FREC_TEST_PKTSZ) &&
849 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelleya77cec82015-05-08 16:25:38 +0100850 server->edns_pktsz = SAFE_PKTSZ;
851
Simon Kelley1a6bca82008-07-11 11:11:42 +0100852 /* If the answer is an error, keep the forward record in place in case
853 we get a good reply from another server. Kill it when we've
854 had replies from all to avoid filling the forwarding table when
855 everything is broken */
Baptiste Jonglez68f63122017-02-06 21:09:11 +0000856 if (forward->forwardall == 0 || --forward->forwardall == 1 ||
857 (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100858 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100859 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100860
Simon Kelley3a237152013-12-12 12:15:50 +0000861 if (option_bool(OPT_NO_REBIND))
862 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100863
Simon Kelley3a237152013-12-12 12:15:50 +0000864 /* Don't cache replies where DNSSEC validation was turned off, either
865 the upstream server told us so, or the original query specified it. */
866 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
867 no_cache_dnssec = 1;
868
869#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000870 if (server && (server->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000871 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000872 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000873 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000874
875 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000876 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000877 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000878
879 /* Truncated answer can't be validated.
Simon Kelley5d3b87a2014-01-20 11:57:23 +0000880 If this is an answer to a DNSSEC-generated query, we still
881 need to get the client to retry over TCP, so return
882 an answer with the TC bit set, even if the actual answer fits.
883 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000884 if (header->hb3 & HB3_TC)
885 status = STAT_TRUNCATED;
886
887 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000888 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000889 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
890 would invite infinite loops, since the answers to DNSKEY and DS queries
891 will not be cached, so they'll be repeated. */
892 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000893 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000894 if (forward->flags & FREC_DNSKEY_QUERY)
895 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
896 else if (forward->flags & FREC_DS_QUERY)
897 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000898 else
Simon Kelley9a31b682015-12-15 10:20:39 +0000899 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
James Bottomleye33b4872017-03-17 21:44:10 +0000900 option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags && SERV_DO_DNSSEC), NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000901 }
Simon Kelley0fc2f312014-01-08 10:26:58 +0000902
Simon Kelley9a31b682015-12-15 10:20:39 +0000903 /* Can't validate, as we're missing key data. Put this
904 answer aside, whilst we get that. */
905 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +0000906 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000907 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +0000908
Simon Kelley9a31b682015-12-15 10:20:39 +0000909 /* Free any saved query */
910 if (forward->stash)
911 blockdata_free(forward->stash);
912
913 /* Now save reply pending receipt of key data */
914 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +0000915 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000916 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000917
Simon Kelley9a31b682015-12-15 10:20:39 +0000918 /* Find the original query that started it all.... */
919 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +0000920
Simon Kelley9a31b682015-12-15 10:20:39 +0000921 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
922 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000923 else
Simon Kelley3a237152013-12-12 12:15:50 +0000924 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000925 int fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +0000926 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +0000927 char *domain;
928
Simon Kelley9a31b682015-12-15 10:20:39 +0000929 *new = *forward; /* copy everything, then overwrite */
930 new->next = next;
931 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +0000932
933 /* Find server to forward to. This will normally be the
934 same as for the original query, but may be another if
935 servers for domains are involved. */
936 if (search_servers(now, NULL, F_QUERY, daemon->keyname, &type, &domain, NULL) == 0)
937 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000938 struct server *start = server, *new_server = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +0000939 type &= ~SERV_DO_DNSSEC;
940
941 while (1)
942 {
943 if (type == (start->flags & SERV_TYPE) &&
944 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
945 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
946 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000947 new_server = start;
948 if (server == start)
949 {
950 new_server = NULL;
951 break;
952 }
Simon Kelley92be34a2016-01-16 18:39:54 +0000953 }
954
955 if (!(start = start->next))
956 start = daemon->servers;
957 if (start == server)
958 break;
959 }
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000960
961 if (new_server)
962 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +0000963 }
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000964
Simon Kelley9a31b682015-12-15 10:20:39 +0000965 new->sentto = server;
Simon Kelley92be34a2016-01-16 18:39:54 +0000966
Simon Kelley9a31b682015-12-15 10:20:39 +0000967 new->rfd4 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +0000968#ifdef HAVE_IPV6
Simon Kelley9a31b682015-12-15 10:20:39 +0000969 new->rfd6 = NULL;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000970#endif
Simon Kelley9a31b682015-12-15 10:20:39 +0000971 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
972
973 new->dependent = forward; /* to find query awaiting new one. */
974 forward->blocking_query = new; /* for garbage cleaning */
975 /* validate routines leave name of required record in daemon->keyname */
976 if (status == STAT_NEED_KEY)
Simon Kelley7fa836e2014-02-10 20:11:24 +0000977 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000978 new->flags |= FREC_DNSKEY_QUERY;
Simon Kelley33702ab2015-12-28 23:17:15 +0000979 nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
Simon Kelley9a31b682015-12-15 10:20:39 +0000980 daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
Simon Kelleyf1668d22014-01-08 16:53:27 +0000981 }
Simon Kelley9a31b682015-12-15 10:20:39 +0000982 else
983 {
984 new->flags |= FREC_DS_QUERY;
Simon Kelley33702ab2015-12-28 23:17:15 +0000985 nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
Simon Kelley9a31b682015-12-15 10:20:39 +0000986 daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
987 }
988 if ((hash = hash_questions(header, nn, daemon->namebuff)))
989 memcpy(new->hash, hash, HASH_SIZE);
990 new->new_id = get_id();
991 header->id = htons(new->new_id);
992 /* Save query for retransmission */
993 new->stash = blockdata_alloc((char *)header, nn);
994 new->stash_len = nn;
995
996 /* Don't resend this. */
997 daemon->srv_save = NULL;
998
999 if (server->sfd)
1000 fd = server->sfd->fd;
1001 else
1002 {
1003 fd = -1;
1004#ifdef HAVE_IPV6
1005 if (server->addr.sa.sa_family == AF_INET6)
1006 {
1007 if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1008 fd = new->rfd6->fd;
1009 }
1010 else
1011#endif
1012 {
1013 if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1014 fd = new->rfd4->fd;
1015 }
1016 }
1017
1018 if (fd != -1)
1019 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001020#ifdef HAVE_CONNTRACK
1021 /* Copy connection mark of incoming query to outgoing connection. */
1022 if (option_bool(OPT_CONNTRACK))
1023 {
1024 unsigned int mark;
1025 if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
1026 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1027 }
1028#endif
Simon Kelley9a31b682015-12-15 10:20:39 +00001029 while (retry_send(sendto(fd, (char *)header, nn, 0,
1030 &server->addr.sa,
1031 sa_len(&server->addr))));
1032 server->queries++;
1033 }
1034 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001035 return;
Simon Kelley3a237152013-12-12 12:15:50 +00001036 }
Simon Kelley3a237152013-12-12 12:15:50 +00001037
Simon Kelley9a31b682015-12-15 10:20:39 +00001038 /* Validated original answer, all done. */
1039 if (!forward->dependent)
1040 break;
1041
Josh Soref730c6742017-02-06 16:14:04 +00001042 /* validated subsidiary query, (and cached result)
Simon Kelley9a31b682015-12-15 10:20:39 +00001043 pop that and return to the previous query we were working on. */
Simon Kelley0744ca62014-01-25 16:40:15 +00001044 struct frec *prev = forward->dependent;
1045 free_frec(forward);
1046 forward = prev;
1047 forward->blocking_query = NULL; /* already gone */
1048 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1049 n = forward->stash_len;
Simon Kelley3a237152013-12-12 12:15:50 +00001050 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001051
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001052
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001053 no_cache_dnssec = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001054
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001055 if (status == STAT_TRUNCATED)
Simon Kelley0744ca62014-01-25 16:40:15 +00001056 header->hb3 |= HB3_TC;
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001057 else
Simon Kelley7fa836e2014-02-10 20:11:24 +00001058 {
Simon Kelley554b5802015-04-17 22:50:20 +01001059 char *result, *domain = "result";
Simon Kelley7fa836e2014-02-10 20:11:24 +00001060
Simon Kelley9a31b682015-12-15 10:20:39 +00001061 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001062 {
1063 result = "ABANDONED";
1064 status = STAT_BOGUS;
1065 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001066 else
1067 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1068
Simon Kelley554b5802015-04-17 22:50:20 +01001069 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1070 domain = daemon->namebuff;
Simon Kelley9a31b682015-12-15 10:20:39 +00001071
Simon Kelley554b5802015-04-17 22:50:20 +01001072 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001073 }
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001074
Simon Kelley3a237152013-12-12 12:15:50 +00001075 if (status == STAT_SECURE)
1076 cache_secure = 1;
Simon Kelley3a237152013-12-12 12:15:50 +00001077 else if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001078 {
1079 no_cache_dnssec = 1;
1080 bogusanswer = 1;
1081 }
Simon Kelley3a237152013-12-12 12:15:50 +00001082 }
Simon Kelley83349b82014-02-10 21:02:01 +00001083#endif
1084
1085 /* restore CD bit to the value in the query */
1086 if (forward->flags & FREC_CHECKING_DISABLED)
1087 header->hb4 |= HB4_CD;
1088 else
1089 header->hb4 &= ~HB4_CD;
Simon Kelley3a237152013-12-12 12:15:50 +00001090
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001091 if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelley613ad152014-02-25 23:02:28 +00001092 forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1093 forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
Simon Kelley832af0b2007-01-21 20:01:28 +00001094 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001095 header->id = htons(forward->orig_id);
Simon Kelley572b41e2011-02-18 18:11:18 +00001096 header->hb4 |= HB4_RA; /* recursion if available */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001097#ifdef HAVE_DNSSEC
1098 /* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
1099 greater than the no-EDNS0-implied 512 to have if space for the RRSIGS. If, having stripped them and the EDNS0
1100 header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1101 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1102 {
1103 header->ancount = htons(0);
1104 header->nscount = htons(0);
1105 header->arcount = htons(0);
1106 header->hb3 |= HB3_TC;
1107 nn = resize_packet(header, nn, NULL, 0);
1108 }
1109#endif
Simon Kelley54dd3932012-06-20 11:23:38 +01001110 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
Simon Kelley50303b12012-04-04 22:13:17 +01001111 &forward->source, &forward->dest, forward->iface);
Simon Kelley832af0b2007-01-21 20:01:28 +00001112 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001113 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001114 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001115}
Simon Kelley44a2a312004-03-10 20:04:35 +00001116
Simon Kelley1a6bca82008-07-11 11:11:42 +01001117
Simon Kelley5aabfc72007-08-29 11:24:47 +01001118void receive_query(struct listener *listen, time_t now)
Simon Kelley44a2a312004-03-10 20:04:35 +00001119{
Simon Kelley572b41e2011-02-18 18:11:18 +00001120 struct dns_header *header = (struct dns_header *)daemon->packet;
Simon Kelley44a2a312004-03-10 20:04:35 +00001121 union mysockaddr source_addr;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001122 unsigned char *pheader;
1123 unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
Simon Kelley44a2a312004-03-10 20:04:35 +00001124 struct all_addr dst_addr;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001125 struct in_addr netmask, dst_addr_4;
Simon Kelleycdeda282006-03-16 20:16:06 +00001126 size_t m;
1127 ssize_t n;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001128 int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001129#ifdef HAVE_AUTH
1130 int local_auth = 0;
1131#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001132 struct iovec iov[1];
1133 struct msghdr msg;
1134 struct cmsghdr *cmptr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001135 union {
1136 struct cmsghdr align; /* this ensures alignment */
1137#ifdef HAVE_IPV6
1138 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1139#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001140#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +00001141 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
Simon Kelley824af852008-02-12 20:43:05 +00001142#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1143 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1144 CMSG_SPACE(sizeof(unsigned int))];
Simon Kelley44a2a312004-03-10 20:04:35 +00001145#elif defined(IP_RECVDSTADDR)
1146 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1147 CMSG_SPACE(sizeof(struct sockaddr_dl))];
1148#endif
1149 } control_u;
Simon Kelley2329bef2013-12-03 13:41:16 +00001150#ifdef HAVE_IPV6
1151 /* Can always get recvd interface for IPv6 */
1152 int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
1153#else
1154 int check_dst = !option_bool(OPT_NOWILD);
1155#endif
1156
Simon Kelleycdeda282006-03-16 20:16:06 +00001157 /* packet buffer overwritten */
1158 daemon->srv_save = NULL;
1159
Hans Dedecker98906272014-12-09 22:22:53 +00001160 dst_addr_4.s_addr = dst_addr.addr.addr4.s_addr = 0;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001161 netmask.s_addr = 0;
1162
Simon Kelley7e5664b2013-04-05 16:57:41 +01001163 if (option_bool(OPT_NOWILD) && listen->iface)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001164 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001165 auth_dns = listen->iface->dns_auth;
1166
1167 if (listen->family == AF_INET)
1168 {
Hans Dedecker98906272014-12-09 22:22:53 +00001169 dst_addr_4 = dst_addr.addr.addr4 = listen->iface->addr.in.sin_addr;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001170 netmask = listen->iface->netmask;
1171 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001172 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001173
Simon Kelley3be34542004-09-11 19:12:13 +01001174 iov[0].iov_base = daemon->packet;
1175 iov[0].iov_len = daemon->edns_pktsz;
Simon Kelley44a2a312004-03-10 20:04:35 +00001176
1177 msg.msg_control = control_u.control;
1178 msg.msg_controllen = sizeof(control_u);
1179 msg.msg_flags = 0;
1180 msg.msg_name = &source_addr;
1181 msg.msg_namelen = sizeof(source_addr);
1182 msg.msg_iov = iov;
1183 msg.msg_iovlen = 1;
1184
Simon Kelleyde379512004-06-22 20:23:33 +01001185 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
Simon Kelley3be34542004-09-11 19:12:13 +01001186 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001187
Simon Kelley572b41e2011-02-18 18:11:18 +00001188 if (n < (int)sizeof(struct dns_header) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001189 (msg.msg_flags & MSG_TRUNC) ||
Simon Kelley572b41e2011-02-18 18:11:18 +00001190 (header->hb3 & HB3_QR))
Simon Kelley3be34542004-09-11 19:12:13 +01001191 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001192
Simon Kelley26128d22004-11-14 16:43:54 +00001193 source_addr.sa.sa_family = listen->family;
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001194
1195 if (listen->family == AF_INET)
1196 {
1197 /* Source-port == 0 is an error, we can't send back to that.
1198 http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1199 if (source_addr.in.sin_port == 0)
1200 return;
1201 }
Simon Kelley26128d22004-11-14 16:43:54 +00001202#ifdef HAVE_IPV6
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001203 else
1204 {
1205 /* Source-port == 0 is an error, we can't send back to that. */
1206 if (source_addr.in6.sin6_port == 0)
1207 return;
1208 source_addr.in6.sin6_flowinfo = 0;
1209 }
Simon Kelley26128d22004-11-14 16:43:54 +00001210#endif
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001211
Simon Kelleyc8a80482014-03-05 14:29:54 +00001212 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1213 if (option_bool(OPT_LOCAL_SERVICE))
1214 {
1215 struct addrlist *addr;
1216#ifdef HAVE_IPV6
1217 if (listen->family == AF_INET6)
1218 {
1219 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1220 if ((addr->flags & ADDRLIST_IPV6) &&
1221 is_same_net6(&addr->addr.addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
1222 break;
1223 }
1224 else
1225#endif
1226 {
1227 struct in_addr netmask;
1228 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1229 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001230 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001231 if (!(addr->flags & ADDRLIST_IPV6) &&
1232 is_same_net(addr->addr.addr.addr4, source_addr.in.sin_addr, netmask))
1233 break;
1234 }
1235 }
1236 if (!addr)
1237 {
Simon Kelley0c8584e2014-03-12 20:12:56 +00001238 static int warned = 0;
1239 if (!warned)
1240 {
1241 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1242 warned = 1;
1243 }
Simon Kelleyc8a80482014-03-05 14:29:54 +00001244 return;
1245 }
1246 }
1247
Simon Kelley2329bef2013-12-03 13:41:16 +00001248 if (check_dst)
Simon Kelley44a2a312004-03-10 20:04:35 +00001249 {
Simon Kelley8a911cc2004-03-16 18:35:52 +00001250 struct ifreq ifr;
1251
Simon Kelley26128d22004-11-14 16:43:54 +00001252 if (msg.msg_controllen < sizeof(struct cmsghdr))
1253 return;
1254
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001255#if defined(HAVE_LINUX_NETWORK)
Simon Kelley26128d22004-11-14 16:43:54 +00001256 if (listen->family == AF_INET)
1257 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001258 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
Simon Kelley26128d22004-11-14 16:43:54 +00001259 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001260 union {
1261 unsigned char *c;
1262 struct in_pktinfo *p;
1263 } p;
1264 p.c = CMSG_DATA(cmptr);
1265 dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
1266 if_index = p.p->ipi_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001267 }
1268#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1269 if (listen->family == AF_INET)
1270 {
1271 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001272 {
1273 union {
1274 unsigned char *c;
1275 unsigned int *i;
1276 struct in_addr *a;
1277#ifndef HAVE_SOLARIS_NETWORK
1278 struct sockaddr_dl *s;
Simon Kelley824af852008-02-12 20:43:05 +00001279#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001280 } p;
1281 p.c = CMSG_DATA(cmptr);
1282 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
1283 dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
1284 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1285#ifdef HAVE_SOLARIS_NETWORK
1286 if_index = *(p.i);
1287#else
1288 if_index = p.s->sdl_index;
1289#endif
1290 }
Simon Kelley26128d22004-11-14 16:43:54 +00001291 }
1292#endif
1293
1294#ifdef HAVE_IPV6
1295 if (listen->family == AF_INET6)
1296 {
1297 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001298 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
Simon Kelley26128d22004-11-14 16:43:54 +00001299 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001300 union {
1301 unsigned char *c;
1302 struct in6_pktinfo *p;
1303 } p;
1304 p.c = CMSG_DATA(cmptr);
1305
1306 dst_addr.addr.addr6 = p.p->ipi6_addr;
1307 if_index = p.p->ipi6_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001308 }
1309 }
1310#endif
1311
1312 /* enforce available interface configuration */
1313
Simon Kelleye25db1f2013-01-29 22:10:26 +00001314 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
Simon Kelley832af0b2007-01-21 20:01:28 +00001315 return;
1316
Simon Kelleye25db1f2013-01-29 22:10:26 +00001317 if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
1318 {
1319 if (!option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001320 enumerate_interfaces(0);
Simon Kelley3f2873d2013-05-14 11:28:47 +01001321 if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
1322 !label_exception(if_index, listen->family, &dst_addr))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001323 return;
1324 }
1325
Simon Kelley552af8b2012-02-29 20:10:31 +00001326 if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
1327 {
1328 struct irec *iface;
1329
Josh Soref730c6742017-02-06 16:14:04 +00001330 /* get the netmask of the interface which has the address we were sent to.
klemens43517fc2017-02-19 15:53:37 +00001331 This is no necessarily the interface we arrived on. */
Simon Kelley552af8b2012-02-29 20:10:31 +00001332
1333 for (iface = daemon->interfaces; iface; iface = iface->next)
1334 if (iface->addr.sa.sa_family == AF_INET &&
1335 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1336 break;
1337
1338 /* interface may be new */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001339 if (!iface && !option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001340 enumerate_interfaces(0);
Simon Kelley552af8b2012-02-29 20:10:31 +00001341
1342 for (iface = daemon->interfaces; iface; iface = iface->next)
1343 if (iface->addr.sa.sa_family == AF_INET &&
1344 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1345 break;
1346
1347 /* If we failed, abandon localisation */
1348 if (iface)
1349 netmask = iface->netmask;
1350 else
1351 dst_addr_4.s_addr = 0;
1352 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001353 }
Simon Kelley25cf5e32015-01-09 15:53:03 +00001354
1355 /* log_query gets called indirectly all over the place, so
1356 pass these in global variables - sorry. */
1357 daemon->log_display_id = ++daemon->log_id;
1358 daemon->log_source_addr = &source_addr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001359
Simon Kelleycdeda282006-03-16 20:16:06 +00001360 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
Simon Kelley44a2a312004-03-10 20:04:35 +00001361 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001362#ifdef HAVE_AUTH
1363 struct auth_zone *zone;
1364#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001365 char *types = querystr(auth_dns ? "auth" : "query", type);
1366
Simon Kelley44a2a312004-03-10 20:04:35 +00001367 if (listen->family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +01001368 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +01001369 (struct all_addr *)&source_addr.in.sin_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001370#ifdef HAVE_IPV6
1371 else
Simon Kelley3be34542004-09-11 19:12:13 +01001372 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +01001373 (struct all_addr *)&source_addr.in6.sin6_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001374#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001375
Simon Kelley4820dce2012-12-18 18:30:30 +00001376#ifdef HAVE_AUTH
Simon Kelleyb485ed92013-10-18 22:00:39 +01001377 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001378 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001379 for (zone = daemon->auth_zones; zone; zone = zone->next)
1380 if (in_zone(zone, daemon->namebuff, NULL))
1381 {
1382 auth_dns = 1;
1383 local_auth = 1;
1384 break;
1385 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001386#endif
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001387
1388#ifdef HAVE_LOOP
1389 /* Check for forwarding loop */
1390 if (detect_loop(daemon->namebuff, type))
1391 return;
1392#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001393 }
1394
Simon Kelley5bb88f02015-12-21 16:23:47 +00001395 if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001396 {
1397 unsigned short flags;
1398
1399 have_pseudoheader = 1;
1400 GETSHORT(udp_size, pheader);
1401 pheader += 2; /* ext_rcode */
1402 GETSHORT(flags, pheader);
1403
1404 if (flags & 0x8000)
1405 do_bit = 1;/* do bit */
1406
1407 /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1408 (bounded by the maximum configured). If no EDNS0, then it
1409 defaults to 512 */
1410 if (udp_size > daemon->edns_pktsz)
1411 udp_size = daemon->edns_pktsz;
1412 }
1413
Simon Kelleyb485ed92013-10-18 22:00:39 +01001414#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001415 if (auth_dns)
Simon Kelley824af852008-02-12 20:43:05 +00001416 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001417 m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1418 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001419 if (m >= 1)
Simon Kelleyb485ed92013-10-18 22:00:39 +01001420 {
1421 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1422 (char *)header, m, &source_addr, &dst_addr, if_index);
1423 daemon->auth_answer++;
1424 }
Simon Kelley824af852008-02-12 20:43:05 +00001425 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001426 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001427#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001428 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001429 int ad_reqd = do_bit;
1430 /* RFC 6840 5.7 */
1431 if (header->hb4 & HB4_AD)
1432 ad_reqd = 1;
1433
1434 m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1435 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001436
1437 if (m >= 1)
1438 {
1439 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1440 (char *)header, m, &source_addr, &dst_addr, if_index);
1441 daemon->local_answer++;
1442 }
1443 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
Simon Kelley613ad152014-02-25 23:02:28 +00001444 header, (size_t)n, now, NULL, ad_reqd, do_bit))
Simon Kelley4f7b3042012-11-28 21:27:02 +00001445 daemon->queries_forwarded++;
1446 else
1447 daemon->local_answer++;
1448 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001449}
1450
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001451#ifdef HAVE_DNSSEC
Josh Soref730c6742017-02-06 16:14:04 +00001452/* Recurse up the key hierarchy */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001453static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001454 int class, char *name, char *keyname, struct server *server,
1455 int have_mark, unsigned int mark, int *keycount)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001456{
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001457 int new_status;
Simon Kelley9a31b682015-12-15 10:20:39 +00001458 unsigned char *packet = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001459 unsigned char *payload = NULL;
1460 struct dns_header *new_header = NULL;
1461 u16 *length = NULL;
Simon Kelley361dfe52017-02-10 21:12:30 +00001462
Simon Kelley9a31b682015-12-15 10:20:39 +00001463 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001464 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001465 int type = SERV_DO_DNSSEC;
1466 char *domain;
1467 size_t m;
1468 unsigned char c1, c2;
Simon Kelley361dfe52017-02-10 21:12:30 +00001469 struct server *firstsendto = NULL;
1470
Simon Kelley9a31b682015-12-15 10:20:39 +00001471 /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1472 if (--(*keycount) == 0)
1473 new_status = STAT_ABANDONED;
1474 else if (status == STAT_NEED_KEY)
1475 new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1476 else if (status == STAT_NEED_DS)
1477 new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1478 else
James Bottomleye33b4872017-03-17 21:44:10 +00001479 new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
1480 option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags && SERV_DO_DNSSEC), NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001481
Simon Kelley9a31b682015-12-15 10:20:39 +00001482 if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1483 break;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001484
Simon Kelley9a31b682015-12-15 10:20:39 +00001485 /* Can't validate because we need a key/DS whose name now in keyname.
1486 Make query for same, and recurse to validate */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001487 if (!packet)
Simon Kelley9a31b682015-12-15 10:20:39 +00001488 {
1489 packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1490 payload = &packet[2];
1491 new_header = (struct dns_header *)payload;
1492 length = (u16 *)packet;
1493 }
1494
1495 if (!packet)
1496 {
1497 new_status = STAT_ABANDONED;
1498 break;
1499 }
1500
Simon Kelley33702ab2015-12-28 23:17:15 +00001501 m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
Simon Kelleya77cec82015-05-08 16:25:38 +01001502 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001503
Simon Kelley7fa836e2014-02-10 20:11:24 +00001504 *length = htons(m);
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001505
1506 /* Find server to forward to. This will normally be the
1507 same as for the original query, but may be another if
1508 servers for domains are involved. */
Simon Kelley361dfe52017-02-10 21:12:30 +00001509 if (search_servers(now, NULL, F_QUERY, keyname, &type, &domain, NULL) != 0)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001510 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001511 new_status = STAT_ABANDONED;
1512 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001513 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001514
1515 type &= ~SERV_DO_DNSSEC;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001516
Simon Kelley361dfe52017-02-10 21:12:30 +00001517 while (1)
1518 {
1519 if (!firstsendto)
1520 firstsendto = server;
1521 else
1522 {
1523 if (!(server = server->next))
1524 server = daemon->servers;
1525 if (server == firstsendto)
1526 {
1527 /* can't find server to accept our query. */
1528 new_status = STAT_ABANDONED;
1529 break;
1530 }
1531 }
1532
1533 if (type != (server->flags & SERV_TYPE) ||
1534 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1535 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1536 continue;
1537
1538 retry:
1539 /* may need to make new connection. */
1540 if (server->tcpfd == -1)
1541 {
1542 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1543 continue; /* No good, next server */
1544
1545#ifdef HAVE_CONNTRACK
1546 /* Copy connection mark of incoming query to outgoing connection. */
1547 if (have_mark)
1548 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1549#endif
1550
1551 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 1) ||
1552 connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
1553 {
1554 close(server->tcpfd);
1555 server->tcpfd = -1;
1556 continue; /* No good, next server */
1557 }
1558
1559 server->flags &= ~SERV_GOT_TCP;
1560 }
1561
1562 if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
1563 !read_write(server->tcpfd, &c1, 1, 1) ||
1564 !read_write(server->tcpfd, &c2, 1, 1) ||
1565 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1566 {
1567 close(server->tcpfd);
1568 server->tcpfd = -1;
1569 /* We get data then EOF, reopen connection to same server,
1570 else try next. This avoids DoS from a server which accepts
1571 connections and then closes them. */
1572 if (server->flags & SERV_GOT_TCP)
1573 goto retry;
1574 else
1575 continue;
1576 }
1577
1578 server->flags |= SERV_GOT_TCP;
1579
1580 m = (c1 << 8) | c2;
1581 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1582 break;
1583 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001584
1585 if (new_status != STAT_OK)
1586 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001587 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001588
Simon Kelley9a31b682015-12-15 10:20:39 +00001589 if (packet)
1590 free(packet);
1591
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001592 return new_status;
1593}
1594#endif
1595
1596
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001597/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001598 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001599 about resources for debug mode, when the fork is suppressed: that's
1600 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001601unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001602 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001603{
Simon Kelley28866e92011-02-14 20:19:14 +00001604 size_t size = 0;
1605 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001606#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001607 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001608#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001609 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001610 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001611 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001612 unsigned short qtype;
1613 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001614 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001615 /* Max TCP packet + slop + size */
1616 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1617 unsigned char *payload = &packet[2];
1618 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1619 struct dns_header *header = (struct dns_header *)payload;
1620 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001621 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001622 struct in_addr dst_addr_4;
1623 union mysockaddr peer_addr;
1624 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001625 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001626 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001627 unsigned int mark = 0;
1628 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001629
Simon Kelleyd05dd582016-01-19 21:23:30 +00001630 (void)mark;
1631 (void)have_mark;
1632
Simon Kelley7de060b2011-08-26 17:24:52 +01001633 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1634 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001635
1636#ifdef HAVE_CONNTRACK
1637 /* Get connection mark of incoming query to set on outgoing connections. */
1638 if (option_bool(OPT_CONNTRACK))
1639 {
1640 struct all_addr local;
1641#ifdef HAVE_IPV6
1642 if (local_addr->sa.sa_family == AF_INET6)
1643 local.addr.addr6 = local_addr->in6.sin6_addr;
1644 else
1645#endif
1646 local.addr.addr4 = local_addr->in.sin_addr;
1647
1648 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1649 }
1650#endif
1651
Simon Kelleyc8a80482014-03-05 14:29:54 +00001652 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1653 if (option_bool(OPT_LOCAL_SERVICE))
1654 {
1655 struct addrlist *addr;
1656#ifdef HAVE_IPV6
1657 if (peer_addr.sa.sa_family == AF_INET6)
1658 {
1659 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1660 if ((addr->flags & ADDRLIST_IPV6) &&
1661 is_same_net6(&addr->addr.addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
1662 break;
1663 }
1664 else
1665#endif
1666 {
1667 struct in_addr netmask;
1668 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1669 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001670 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001671 if (!(addr->flags & ADDRLIST_IPV6) &&
1672 is_same_net(addr->addr.addr.addr4, peer_addr.in.sin_addr, netmask))
1673 break;
1674 }
1675 }
1676 if (!addr)
1677 {
1678 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1679 return packet;
1680 }
1681 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001682
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001683 while (1)
1684 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001685 if (query_count == TCP_MAX_QUERIES ||
1686 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001687 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1688 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001689 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001690 return packet;
1691
Simon Kelley572b41e2011-02-18 18:11:18 +00001692 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001693 continue;
1694
Simon Kelley25cf5e32015-01-09 15:53:03 +00001695 query_count++;
1696
1697 /* log_query gets called indirectly all over the place, so
1698 pass these in global variables - sorry. */
1699 daemon->log_display_id = ++daemon->log_id;
1700 daemon->log_source_addr = &peer_addr;
1701
Simon Kelley28866e92011-02-14 20:19:14 +00001702 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001703 if ((checking_disabled = header->hb4 & HB4_CD))
1704 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001705
Simon Kelley3be34542004-09-11 19:12:13 +01001706 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001707 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001708#ifdef HAVE_AUTH
1709 struct auth_zone *zone;
1710#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001711 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001712
1713 if (peer_addr.sa.sa_family == AF_INET)
1714 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
1715 (struct all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001716#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001717 else
1718 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
1719 (struct all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001720#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001721
1722#ifdef HAVE_AUTH
1723 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001724 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001725 for (zone = daemon->auth_zones; zone; zone = zone->next)
1726 if (in_zone(zone, daemon->namebuff, NULL))
1727 {
1728 auth_dns = 1;
1729 local_auth = 1;
1730 break;
1731 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001732#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001733 }
1734
Simon Kelley7de060b2011-08-26 17:24:52 +01001735 if (local_addr->sa.sa_family == AF_INET)
1736 dst_addr_4 = local_addr->in.sin_addr;
1737 else
1738 dst_addr_4.s_addr = 0;
1739
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001740 do_bit = 0;
1741
Simon Kelley5bb88f02015-12-21 16:23:47 +00001742 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001743 {
1744 unsigned short flags;
1745
1746 have_pseudoheader = 1;
1747 pheader += 4; /* udp_size, ext_rcode */
1748 GETSHORT(flags, pheader);
1749
1750 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001751 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001752 }
1753
Simon Kelley4820dce2012-12-18 18:30:30 +00001754#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001755 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001756 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1757 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001758 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001759#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001760 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001761 int ad_reqd = do_bit;
1762 /* RFC 6840 5.7 */
1763 if (header->hb4 & HB4_AD)
1764 ad_reqd = 1;
1765
1766 /* m > 0 if answered from cache */
1767 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1768 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001769
Simon Kelley4f7b3042012-11-28 21:27:02 +00001770 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001771 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001772
1773 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001774 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001775 unsigned int flags = 0;
1776 struct all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001777 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001778 char *domain = NULL;
Simon Kelley33702ab2015-12-28 23:17:15 +00001779 size_t new_size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
Simon Kelleyed4c0762013-10-08 20:46:34 +01001780
Simon Kelley33702ab2015-12-28 23:17:15 +00001781 if (size != new_size)
1782 {
1783 added_pheader = 1;
1784 size = new_size;
1785 }
1786
Simon Kelley4f7b3042012-11-28 21:27:02 +00001787 if (gotname)
1788 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
1789
Simon Kelley367341f2016-01-12 15:58:23 +00001790 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001791
Simon Kelley4f7b3042012-11-28 21:27:02 +00001792 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1793 last_server = daemon->servers;
1794 else
1795 last_server = daemon->last_server;
1796
1797 if (!flags && last_server)
1798 {
1799 struct server *firstsendto = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001800#ifdef HAVE_DNSSEC
Simon Kelley703c7ff2014-01-25 23:46:23 +00001801 unsigned char *newhash, hash[HASH_SIZE];
Simon Kelley63758382014-04-16 22:20:55 +01001802 if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001803 memcpy(hash, newhash, HASH_SIZE);
Tomas Hozzab37f8b92014-03-25 20:52:28 +00001804 else
1805 memset(hash, 0, HASH_SIZE);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001806#else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001807 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001808#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001809 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001810 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001811 which can go to the same server, do so. */
1812 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001813 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001814 if (!firstsendto)
1815 firstsendto = last_server;
1816 else
1817 {
1818 if (!(last_server = last_server->next))
1819 last_server = daemon->servers;
1820
1821 if (last_server == firstsendto)
1822 break;
1823 }
1824
1825 /* server for wrong domain */
1826 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001827 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
1828 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01001829 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00001830
1831 retry:
Simon Kelley4f7b3042012-11-28 21:27:02 +00001832 if (last_server->tcpfd == -1)
1833 {
1834 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1835 continue;
1836
Karl Vogele9828b62014-10-03 21:45:15 +01001837#ifdef HAVE_CONNTRACK
1838 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001839 if (have_mark)
1840 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Karl Vogele9828b62014-10-03 21:45:15 +01001841#endif
1842
Simon Kelley4f7b3042012-11-28 21:27:02 +00001843 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
1844 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
1845 {
1846 close(last_server->tcpfd);
1847 last_server->tcpfd = -1;
1848 continue;
1849 }
1850
Simon Kelley361dfe52017-02-10 21:12:30 +00001851 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001852 }
1853
Simon Kelley361dfe52017-02-10 21:12:30 +00001854#ifdef HAVE_DNSSEC
1855 if (option_bool(OPT_DNSSEC_VALID) && (last_server->flags & SERV_DO_DNSSEC))
1856 {
1857 new_size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1858
1859 if (size != new_size)
1860 {
1861 added_pheader = 1;
1862 size = new_size;
1863 }
1864
1865 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1866 this allows it to select auth servers when one is returning bad data. */
1867 if (option_bool(OPT_DNSSEC_DEBUG))
1868 header->hb4 |= HB4_CD;
1869 }
1870#endif
1871
Simon Kelley4b5ea122013-04-22 10:18:26 +01001872 *length = htons(size);
Simon Kelley1fc02682014-04-29 12:30:18 +01001873
1874 /* get query name again for logging - may have been overwritten */
1875 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
1876 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00001877
Simon Kelley4b5ea122013-04-22 10:18:26 +01001878 if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00001879 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001880 !read_write(last_server->tcpfd, &c2, 1, 1) ||
1881 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01001882 {
1883 close(last_server->tcpfd);
1884 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00001885 /* We get data then EOF, reopen connection to same server,
1886 else try next. This avoids DoS from a server which accepts
1887 connections and then closes them. */
1888 if (last_server->flags & SERV_GOT_TCP)
1889 goto retry;
1890 else
1891 continue;
1892 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001893
Simon Kelley361dfe52017-02-10 21:12:30 +00001894 last_server->flags |= SERV_GOT_TCP;
1895
Simon Kelley4f7b3042012-11-28 21:27:02 +00001896 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001897
Simon Kelley4f7b3042012-11-28 21:27:02 +00001898 if (last_server->addr.sa.sa_family == AF_INET)
1899 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1900 (struct all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001901#ifdef HAVE_IPV6
Simon Kelley4f7b3042012-11-28 21:27:02 +00001902 else
1903 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1904 (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001905#endif
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001906
1907#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00001908 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001909 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00001910 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001911 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
1912 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01001913 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001914
Simon Kelley9a31b682015-12-15 10:20:39 +00001915 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001916 {
1917 result = "ABANDONED";
1918 status = STAT_BOGUS;
1919 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001920 else
1921 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01001922
1923 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
1924 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01001925
1926 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001927
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001928 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001929 {
1930 no_cache_dnssec = 1;
1931 bogusanswer = 1;
1932 }
1933
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001934 if (status == STAT_SECURE)
1935 cache_secure = 1;
1936 }
1937#endif
1938
1939 /* restore CD bit to the value in the query */
1940 if (checking_disabled)
1941 header->hb4 |= HB4_CD;
1942 else
1943 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001944
1945 /* There's no point in updating the cache, since this process will exit and
1946 lose the information after a few queries. We make this call for the alias and
1947 bogus-nxdomain side-effects. */
1948 /* If the crc of the question section doesn't match the crc we sent, then
1949 someone might be attempting to insert bogus values into the cache by
1950 sending replies containing questions and bogus answers. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001951#ifdef HAVE_DNSSEC
1952 newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
1953 if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00001954 {
1955 m = 0;
1956 break;
1957 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001958#else
1959 if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
Simon Kelley703c7ff2014-01-25 23:46:23 +00001960 {
1961 m = 0;
1962 break;
1963 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001964#endif
1965
1966 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01001967 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001968 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001969
1970 break;
1971 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001972 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001973
1974 /* In case of local answer or no connections made. */
1975 if (m == 0)
1976 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001977 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001978 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001979
Simon Kelleyb842bc92015-07-12 21:09:11 +01001980 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001981
Simon Kelley4b5ea122013-04-22 10:18:26 +01001982 *length = htons(m);
1983
1984 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001985 return packet;
1986 }
1987}
1988
Simon Kelley16972692006-10-16 20:04:18 +01001989static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001990{
Simon Kelley16972692006-10-16 20:04:18 +01001991 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001992
Simon Kelley5aabfc72007-08-29 11:24:47 +01001993 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001994 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001995 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001996 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00001997 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001998 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00001999 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002000#ifdef HAVE_IPV6
2001 f->rfd6 = NULL;
2002#endif
Simon Kelley3a237152013-12-12 12:15:50 +00002003#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002004 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002005 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002006 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002007#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002008 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002009 }
Simon Kelley16972692006-10-16 20:04:18 +01002010
2011 return f;
2012}
2013
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002014struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002015{
2016 static int finger = 0;
2017 int i;
2018
2019 /* limit the number of sockets we have open to avoid starvation of
2020 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2021
2022 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002023 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002024 {
Simon Kelley9009d742008-11-14 20:04:27 +00002025 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2026 break;
2027
Simon Kelley1a6bca82008-07-11 11:11:42 +01002028 daemon->randomsocks[i].refcount = 1;
2029 daemon->randomsocks[i].family = family;
2030 return &daemon->randomsocks[i];
2031 }
2032
Simon Kelley9009d742008-11-14 20:04:27 +00002033 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002034 for (i = 0; i < RANDOM_SOCKS; i++)
2035 {
2036 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002037 if (daemon->randomsocks[j].refcount != 0 &&
2038 daemon->randomsocks[j].family == family &&
2039 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002040 {
2041 finger = j;
2042 daemon->randomsocks[j].refcount++;
2043 return &daemon->randomsocks[j];
2044 }
2045 }
2046
2047 return NULL; /* doom */
2048}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002049
2050void free_rfd(struct randfd *rfd)
2051{
2052 if (rfd && --(rfd->refcount) == 0)
2053 close(rfd->fd);
2054}
2055
Simon Kelley1a6bca82008-07-11 11:11:42 +01002056static void free_frec(struct frec *f)
2057{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002058 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002059 f->rfd4 = NULL;
2060 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002061 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002062
2063#ifdef HAVE_IPV6
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002064 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002065 f->rfd6 = NULL;
2066#endif
Simon Kelley3a237152013-12-12 12:15:50 +00002067
2068#ifdef HAVE_DNSSEC
2069 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002070 {
2071 blockdata_free(f->stash);
2072 f->stash = NULL;
2073 }
Simon Kelley3a237152013-12-12 12:15:50 +00002074
2075 /* Anything we're waiting on is pointless now, too */
2076 if (f->blocking_query)
2077 free_frec(f->blocking_query);
2078 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002079 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002080#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002081}
2082
Simon Kelley16972692006-10-16 20:04:18 +01002083/* if wait==NULL return a free or older than TIMEOUT record.
2084 else return *wait zero if one available, or *wait is delay to
Simon Kelley1a6bca82008-07-11 11:11:42 +01002085 when the oldest in-use record will expire. Impose an absolute
Simon Kelley3a237152013-12-12 12:15:50 +00002086 limit of 4*TIMEOUT before we wipe things (for random sockets).
2087 If force is set, always return a result, even if we have
2088 to allocate above the limit. */
2089struct frec *get_new_frec(time_t now, int *wait, int force)
Simon Kelley16972692006-10-16 20:04:18 +01002090{
Simon Kelley1a6bca82008-07-11 11:11:42 +01002091 struct frec *f, *oldest, *target;
Simon Kelley16972692006-10-16 20:04:18 +01002092 int count;
2093
2094 if (wait)
2095 *wait = 0;
2096
Simon Kelley1a6bca82008-07-11 11:11:42 +01002097 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
Simon Kelley832af0b2007-01-21 20:01:28 +00002098 if (!f->sentto)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002099 target = f;
2100 else
Simon Kelley16972692006-10-16 20:04:18 +01002101 {
Simon Kelley9a31b682015-12-15 10:20:39 +00002102#ifdef HAVE_DNSSEC
2103 /* Don't free DNSSEC sub-queries here, as we may end up with
2104 dangling references to them. They'll go when their "real" query
2105 is freed. */
2106 if (!f->dependent)
2107#endif
2108 {
2109 if (difftime(now, f->time) >= 4*TIMEOUT)
2110 {
2111 free_frec(f);
2112 target = f;
2113 }
2114
2115
2116 if (!oldest || difftime(f->time, oldest->time) <= 0)
2117 oldest = f;
2118 }
Simon Kelley16972692006-10-16 20:04:18 +01002119 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01002120
2121 if (target)
2122 {
2123 target->time = now;
2124 return target;
2125 }
Simon Kelley16972692006-10-16 20:04:18 +01002126
2127 /* can't find empty one, use oldest if there is one
2128 and it's older than timeout */
2129 if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
2130 {
2131 /* keep stuff for twice timeout if we can by allocating a new
2132 record instead */
2133 if (difftime(now, oldest->time) < 2*TIMEOUT &&
2134 count <= daemon->ftabsize &&
2135 (f = allocate_frec(now)))
2136 return f;
2137
2138 if (!wait)
2139 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002140 free_frec(oldest);
Simon Kelley16972692006-10-16 20:04:18 +01002141 oldest->time = now;
2142 }
2143 return oldest;
2144 }
2145
2146 /* none available, calculate time 'till oldest record expires */
Simon Kelley3a237152013-12-12 12:15:50 +00002147 if (!force && count > daemon->ftabsize)
Simon Kelley16972692006-10-16 20:04:18 +01002148 {
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002149 static time_t last_log = 0;
2150
Simon Kelley16972692006-10-16 20:04:18 +01002151 if (oldest && wait)
2152 *wait = oldest->time + (time_t)TIMEOUT - now;
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002153
2154 if ((int)difftime(now, last_log) > 5)
2155 {
2156 last_log = now;
2157 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2158 }
2159
Simon Kelley16972692006-10-16 20:04:18 +01002160 return NULL;
2161 }
2162
2163 if (!(f = allocate_frec(now)) && wait)
2164 /* wait one second on malloc failure */
2165 *wait = 1;
2166
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002167 return f; /* OK if malloc fails and this is NULL */
2168}
2169
Simon Kelley832af0b2007-01-21 20:01:28 +00002170/* crc is all-ones if not known. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002171static struct frec *lookup_frec(unsigned short id, void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002172{
2173 struct frec *f;
2174
Simon Kelley1a6bca82008-07-11 11:11:42 +01002175 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002176 if (f->sentto && f->new_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002177 (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002178 return f;
2179
2180 return NULL;
2181}
2182
2183static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002184 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002185 void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002186{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002187 struct frec *f;
2188
Simon Kelley1a6bca82008-07-11 11:11:42 +01002189 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002190 if (f->sentto &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002191 f->orig_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002192 memcmp(hash, f->hash, HASH_SIZE) == 0 &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002193 sockaddr_isequal(&f->source, addr))
2194 return f;
2195
2196 return NULL;
2197}
Simon Kelley47a95162014-07-08 22:22:02 +01002198
2199/* Send query packet again, if we can. */
2200void resend_query()
2201{
2202 if (daemon->srv_save)
2203 {
2204 int fd;
2205
2206 if (daemon->srv_save->sfd)
2207 fd = daemon->srv_save->sfd->fd;
2208 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2209 fd = daemon->rfd_save->fd;
2210 else
2211 return;
2212
Simon Kelleyff841eb2015-03-11 21:36:30 +00002213 while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2214 &daemon->srv_save->addr.sa,
2215 sa_len(&daemon->srv_save->addr))));
Simon Kelley47a95162014-07-08 22:22:02 +01002216 }
2217}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002218
Simon Kelley849a8352006-06-09 21:02:31 +01002219/* A server record is going away, remove references to it */
Simon Kelley5aabfc72007-08-29 11:24:47 +01002220void server_gone(struct server *server)
Simon Kelley849a8352006-06-09 21:02:31 +01002221{
2222 struct frec *f;
2223
Simon Kelley1a6bca82008-07-11 11:11:42 +01002224 for (f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002225 if (f->sentto && f->sentto == server)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002226 free_frec(f);
Simon Kelley849a8352006-06-09 21:02:31 +01002227
2228 if (daemon->last_server == server)
2229 daemon->last_server = NULL;
2230
2231 if (daemon->srv_save == server)
2232 daemon->srv_save = NULL;
2233}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002234
Simon Kelley316e2732010-01-22 20:16:09 +00002235/* return unique random ids. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002236static unsigned short get_id(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002237{
2238 unsigned short ret = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +00002239
Simon Kelley316e2732010-01-22 20:16:09 +00002240 do
Simon Kelley832af0b2007-01-21 20:01:28 +00002241 ret = rand16();
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002242 while (lookup_frec(ret, NULL));
Simon Kelley832af0b2007-01-21 20:01:28 +00002243
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002244 return ret;
2245}
2246
2247
2248
2249
2250