blob: 83f392ddca27f845a1937dbcd73acd0d9800faa1 [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 Kelley09f3b2c2017-05-09 01:34:02 +0100123 if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
124 continue;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100125 /* domain matches take priority over NODOTS matches */
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100126 else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100127 {
Simon Kelley28866e92011-02-14 20:19:14 +0000128 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100129 *type = SERV_FOR_NODOTS;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100130 if (serv->flags & SERV_NO_ADDR)
Simon Kelley36717ee2004-09-20 19:20:58 +0100131 flags = F_NXDOMAIN;
132 else if (serv->flags & SERV_LITERAL_ADDRESS)
133 {
134 if (sflag & qtype)
135 {
136 flags = sflag;
137 if (serv->addr.sa.sa_family == AF_INET)
138 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100139#ifdef HAVE_IPV6
Simon Kelley36717ee2004-09-20 19:20:58 +0100140 else
141 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100142#endif
Simon Kelley36717ee2004-09-20 19:20:58 +0100143 }
Simon Kelley824af852008-02-12 20:43:05 +0000144 else if (!flags || (flags & F_NXDOMAIN))
Simon Kelley36717ee2004-09-20 19:20:58 +0100145 flags = F_NOERR;
146 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100147 }
148 else if (serv->flags & SERV_HAS_DOMAIN)
149 {
150 unsigned int domainlen = strlen(serv->domain);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000151 char *matchstart = qdomain + namelen - domainlen;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100152 if (namelen >= domainlen &&
Simon Kelleyb8187c82005-11-26 21:46:27 +0000153 hostname_isequal(matchstart, serv->domain) &&
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100154 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100155 {
Simon Kelley92be34a2016-01-16 18:39:54 +0000156 if ((serv->flags & SERV_NO_REBIND) && norebind)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100157 *norebind = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000158 else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100159 {
Simon Kelley28866e92011-02-14 20:19:14 +0000160 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
161 /* implement priority rules for --address and --server for same domain.
162 --address wins if the address is for the correct AF
163 --server wins otherwise. */
164 if (domainlen != 0 && domainlen == matchlen)
Simon Kelley36717ee2004-09-20 19:20:58 +0100165 {
Simon Kelley28866e92011-02-14 20:19:14 +0000166 if ((serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100167 {
Simon Kelley28866e92011-02-14 20:19:14 +0000168 if (!(sflag & qtype) && flags == 0)
169 continue;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100170 }
Simon Kelley28866e92011-02-14 20:19:14 +0000171 else
172 {
173 if (flags & (F_IPV4 | F_IPV6))
174 continue;
175 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100176 }
Simon Kelley28866e92011-02-14 20:19:14 +0000177
178 if (domainlen >= matchlen)
179 {
Simon Kelley367341f2016-01-12 15:58:23 +0000180 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
Simon Kelley28866e92011-02-14 20:19:14 +0000181 *domain = serv->domain;
182 matchlen = domainlen;
183 if (serv->flags & SERV_NO_ADDR)
184 flags = F_NXDOMAIN;
185 else if (serv->flags & SERV_LITERAL_ADDRESS)
186 {
187 if (sflag & qtype)
188 {
189 flags = sflag;
190 if (serv->addr.sa.sa_family == AF_INET)
191 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
192#ifdef HAVE_IPV6
193 else
194 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
195#endif
196 }
197 else if (!flags || (flags & F_NXDOMAIN))
198 flags = F_NOERR;
199 }
200 else
201 flags = 0;
202 }
203 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100204 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100205 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100206
Simon Kelleybf05f8f2017-05-09 22:37:46 +0100207 if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) &&
Simon Kelley28866e92011-02-14 20:19:14 +0000208 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
Simon Kelley7de060b2011-08-26 17:24:52 +0100209 /* don't forward A or AAAA queries for simple names, except the empty name */
210 flags = F_NOERR;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100211
Simon Kelley5aabfc72007-08-29 11:24:47 +0100212 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
Simon Kelleyc1bb8502004-08-11 18:40:17 +0100213 flags = F_NOERR;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100214
Simon Kelley824af852008-02-12 20:43:05 +0000215 if (flags)
216 {
217 int logflags = 0;
218
219 if (flags == F_NXDOMAIN || flags == F_NOERR)
220 logflags = F_NEG | qtype;
221
Simon Kelley1a6bca82008-07-11 11:11:42 +0100222 log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
Simon Kelley824af852008-02-12 20:43:05 +0000223 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100224 else if ((*type) & SERV_USE_RESOLV)
225 {
226 *type = 0; /* use normal servers for this domain */
227 *domain = NULL;
228 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100229 return flags;
230}
Simon Kelley44a2a312004-03-10 20:04:35 +0000231
Simon Kelley824af852008-02-12 20:43:05 +0000232static int forward_query(int udpfd, union mysockaddr *udpaddr,
233 struct all_addr *dst_addr, unsigned int dst_iface,
Simon Kelley83349b82014-02-10 21:02:01 +0000234 struct dns_header *header, size_t plen, time_t now,
Simon Kelley613ad152014-02-25 23:02:28 +0000235 struct frec *forward, int ad_reqd, int do_bit)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000236{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000237 char *domain = NULL;
Simon Kelley367341f2016-01-12 15:58:23 +0000238 int type = SERV_DO_DNSSEC, norebind = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000239 struct all_addr *addrp = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000240 unsigned int flags = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100241 struct server *start = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000242#ifdef HAVE_DNSSEC
243 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley367341f2016-01-12 15:58:23 +0000244 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000245#else
246 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
247 void *hash = &crc;
248#endif
249 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
250
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000251 (void)do_bit;
252
Simon Kelley3d8df262005-08-29 12:19:27 +0100253 /* may be no servers available. */
Simon Kelleyd05dd582016-01-19 21:23:30 +0000254 if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000255 {
Simon Kelleya77cec82015-05-08 16:25:38 +0100256 /* If we didn't get an answer advertising a maximal packet in EDNS,
257 fall back to 1280, which should work everywhere on IPv6.
258 If that generates an answer, it will become the new default
259 for this server */
260 forward->flags |= FREC_TEST_PKTSZ;
261
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000262#ifdef HAVE_DNSSEC
Simon Kelleydac74312014-02-13 16:43:49 +0000263 /* If we've already got an answer to this query, but we're awaiting keys for validation,
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000264 there's no point retrying the query, retry the key query instead...... */
265 if (forward->blocking_query)
266 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000267 int fd, is_sign;
268 unsigned char *pheader;
Simon Kelleya77cec82015-05-08 16:25:38 +0100269
270 forward->flags &= ~FREC_TEST_PKTSZ;
271
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000272 while (forward->blocking_query)
273 forward = forward->blocking_query;
Simon Kelleya77cec82015-05-08 16:25:38 +0100274
275 forward->flags |= FREC_TEST_PKTSZ;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000276
277 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
278 plen = forward->stash_len;
279
Simon Kelley5bb88f02015-12-21 16:23:47 +0000280 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000281 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelleya77cec82015-05-08 16:25:38 +0100282
Simon Kelley2b291912014-03-21 11:13:55 +0000283 if (forward->sentto->addr.sa.sa_family == AF_INET)
Simon Kelley25cf5e32015-01-09 15:53:03 +0000284 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 +0000285#ifdef HAVE_IPV6
286 else
Simon Kelley25cf5e32015-01-09 15:53:03 +0000287 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 +0000288#endif
289
290 if (forward->sentto->sfd)
291 fd = forward->sentto->sfd->fd;
292 else
293 {
294#ifdef HAVE_IPV6
295 if (forward->sentto->addr.sa.sa_family == AF_INET6)
296 fd = forward->rfd6->fd;
297 else
298#endif
299 fd = forward->rfd4->fd;
300 }
301
Simon Kelleyff841eb2015-03-11 21:36:30 +0000302 while (retry_send( sendto(fd, (char *)header, plen, 0,
303 &forward->sentto->addr.sa,
304 sa_len(&forward->sentto->addr))));
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000305
306 return 1;
307 }
308#endif
309
Simon Kelleyde379512004-06-22 20:23:33 +0100310 /* retry on existing query, send to all available servers */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000311 domain = forward->sentto->domain;
Simon Kelley824af852008-02-12 20:43:05 +0000312 forward->sentto->failed_queries++;
Simon Kelley28866e92011-02-14 20:19:14 +0000313 if (!option_bool(OPT_ORDER))
Simon Kelleyde379512004-06-22 20:23:33 +0100314 {
Simon Kelley0a852542005-03-23 20:28:59 +0000315 forward->forwardall = 1;
Simon Kelley3be34542004-09-11 19:12:13 +0100316 daemon->last_server = NULL;
Simon Kelleyde379512004-06-22 20:23:33 +0100317 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000318 type = forward->sentto->flags & SERV_TYPE;
Simon Kelley367341f2016-01-12 15:58:23 +0000319#ifdef HAVE_DNSSEC
320 do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
321#endif
322
Simon Kelleyde379512004-06-22 20:23:33 +0100323 if (!(start = forward->sentto->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100324 start = daemon->servers; /* at end of list, recycle */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000325 header->id = htons(forward->new_id);
326 }
327 else
328 {
329 if (gotname)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100330 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000331
Simon Kelley367341f2016-01-12 15:58:23 +0000332#ifdef HAVE_DNSSEC
333 do_dnssec = type & SERV_DO_DNSSEC;
Simon Kelleyf7443d72016-01-19 20:29:57 +0000334#endif
335 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +0000336
Simon Kelleyd05dd582016-01-19 21:23:30 +0000337 if (daemon->servers && !flags)
338 forward = get_new_frec(now, NULL, 0);
339 /* table full - flags == 0, return REFUSED */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000340
341 if (forward)
342 {
Simon Kelley0a852542005-03-23 20:28:59 +0000343 forward->source = *udpaddr;
344 forward->dest = *dst_addr;
345 forward->iface = dst_iface;
Simon Kelley0a852542005-03-23 20:28:59 +0000346 forward->orig_id = ntohs(header->id);
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000347 forward->new_id = get_id();
Simon Kelley832af0b2007-01-21 20:01:28 +0000348 forward->fd = udpfd;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000349 memcpy(forward->hash, hash, HASH_SIZE);
Simon Kelley0a852542005-03-23 20:28:59 +0000350 forward->forwardall = 0;
Simon Kelleyed4c0762013-10-08 20:46:34 +0100351 forward->flags = 0;
Simon Kelley28866e92011-02-14 20:19:14 +0000352 if (norebind)
353 forward->flags |= FREC_NOREBIND;
Simon Kelley572b41e2011-02-18 18:11:18 +0000354 if (header->hb4 & HB4_CD)
Simon Kelley28866e92011-02-14 20:19:14 +0000355 forward->flags |= FREC_CHECKING_DISABLED;
Simon Kelley83349b82014-02-10 21:02:01 +0000356 if (ad_reqd)
357 forward->flags |= FREC_AD_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000358#ifdef HAVE_DNSSEC
359 forward->work_counter = DNSSEC_WORK;
Simon Kelley613ad152014-02-25 23:02:28 +0000360 if (do_bit)
361 forward->flags |= FREC_DO_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000362#endif
Simon Kelley613ad152014-02-25 23:02:28 +0000363
Simon Kelley28866e92011-02-14 20:19:14 +0000364 header->id = htons(forward->new_id);
365
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100366 /* In strict_order mode, always try servers in the order
367 specified in resolv.conf, if a domain is given
368 always try all the available servers,
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000369 otherwise, use the one last known to work. */
370
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100371 if (type == 0)
372 {
Simon Kelley28866e92011-02-14 20:19:14 +0000373 if (option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100374 start = daemon->servers;
375 else if (!(start = daemon->last_server) ||
376 daemon->forwardcount++ > FORWARD_TEST ||
377 difftime(now, daemon->forwardtime) > FORWARD_TIME)
378 {
379 start = daemon->servers;
380 forward->forwardall = 1;
381 daemon->forwardcount = 0;
382 daemon->forwardtime = now;
383 }
384 }
385 else
Simon Kelleyde379512004-06-22 20:23:33 +0100386 {
Simon Kelley3be34542004-09-11 19:12:13 +0100387 start = daemon->servers;
Simon Kelley28866e92011-02-14 20:19:14 +0000388 if (!option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100389 forward->forwardall = 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100390 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000391 }
392 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100393
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000394 /* check for send errors here (no route to host)
395 if we fail to send to all nameservers, send back an error
396 packet straight away (helps modem users when offline) */
397
398 if (!flags && forward)
399 {
Simon Kelleyde379512004-06-22 20:23:33 +0100400 struct server *firstsentto = start;
Simon Kelley33702ab2015-12-28 23:17:15 +0000401 int subnet, forwarded = 0;
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000402 size_t edns0_len;
403
Simon Kelley25cf5e32015-01-09 15:53:03 +0000404 /* If a query is retried, use the log_id for the retry when logging the answer. */
405 forward->log_id = daemon->log_id;
406
Simon Kelley33702ab2015-12-28 23:17:15 +0000407 edns0_len = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
408
409 if (edns0_len != plen)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000410 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000411 plen = edns0_len;
412 forward->flags |= FREC_ADDED_PHEADER;
413
414 if (subnet)
415 forward->flags |= FREC_HAS_SUBNET;
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000416 }
Simon Kelley33702ab2015-12-28 23:17:15 +0000417
Simon Kelley3a237152013-12-12 12:15:50 +0000418#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000419 if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000420 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000421 size_t new = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
Simon Kelley613ad152014-02-25 23:02:28 +0000422
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000423 if (new != plen)
424 forward->flags |= FREC_ADDED_PHEADER;
425
426 plen = new;
427
Simon Kelley5b3bf922014-01-25 17:03:07 +0000428 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
429 this allows it to select auth servers when one is returning bad data. */
430 if (option_bool(OPT_DNSSEC_DEBUG))
431 header->hb4 |= HB4_CD;
Simon Kelley613ad152014-02-25 23:02:28 +0000432
Simon Kelley0fc2f312014-01-08 10:26:58 +0000433 }
Simon Kelley3a237152013-12-12 12:15:50 +0000434#endif
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000435
436 /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
437 if (find_pseudoheader(header, plen, &edns0_len, NULL, NULL, NULL) && edns0_len > 11)
438 forward->flags |= FREC_HAS_EXTRADATA;
Simon Kelleya77cec82015-05-08 16:25:38 +0100439
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000440 while (1)
441 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000442 /* only send to servers dealing with our domain.
443 domain may be NULL, in which case server->domain
444 must be NULL also. */
445
Simon Kelleyde379512004-06-22 20:23:33 +0100446 if (type == (start->flags & SERV_TYPE) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100447 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100448 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000449 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100450 int fd;
451
452 /* find server socket to use, may need to get random one. */
453 if (start->sfd)
454 fd = start->sfd->fd;
455 else
456 {
457#ifdef HAVE_IPV6
458 if (start->addr.sa.sa_family == AF_INET6)
459 {
460 if (!forward->rfd6 &&
461 !(forward->rfd6 = allocate_rfd(AF_INET6)))
462 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100463 daemon->rfd_save = forward->rfd6;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100464 fd = forward->rfd6->fd;
465 }
466 else
467#endif
468 {
469 if (!forward->rfd4 &&
470 !(forward->rfd4 = allocate_rfd(AF_INET)))
471 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100472 daemon->rfd_save = forward->rfd4;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100473 fd = forward->rfd4->fd;
474 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100475
476#ifdef HAVE_CONNTRACK
477 /* Copy connection mark of incoming query to outgoing connection. */
478 if (option_bool(OPT_CONNTRACK))
479 {
480 unsigned int mark;
Giacomo Tazzari797a7af2013-04-22 13:16:37 +0100481 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
Simon Kelley7de060b2011-08-26 17:24:52 +0100482 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
483 }
484#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100485 }
486
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000487#ifdef HAVE_DNSSEC
Simon Kelley5bb88f02015-12-21 16:23:47 +0000488 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000489 {
490 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
491 packet size to 512. But that won't provide space for the RRSIGS in many cases.
492 The RRSIGS will be stripped out before the answer goes back, so the packet should
493 shrink again. So, if we added a do-bit, bump the udp packet size to the value
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000494 known to be OK for this server. We check returned size after stripping and set
495 the truncated bit if it's still too big. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000496 unsigned char *pheader;
497 int is_sign;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000498 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000499 PUTSHORT(start->edns_pktsz, pheader);
500 }
501#endif
502
Simon Kelleyff841eb2015-03-11 21:36:30 +0000503 if (retry_send(sendto(fd, (char *)header, plen, 0,
504 &start->addr.sa,
505 sa_len(&start->addr))))
506 continue;
507
508 if (errno == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000509 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000510 /* Keep info in case we want to re-send this packet */
511 daemon->srv_save = start;
512 daemon->packet_len = plen;
513
Simon Kelleyde379512004-06-22 20:23:33 +0100514 if (!gotname)
Simon Kelley3be34542004-09-11 19:12:13 +0100515 strcpy(daemon->namebuff, "query");
Simon Kelleyde379512004-06-22 20:23:33 +0100516 if (start->addr.sa.sa_family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +0100517 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +0100518 (struct all_addr *)&start->addr.in.sin_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100519#ifdef HAVE_IPV6
520 else
Simon Kelley3be34542004-09-11 19:12:13 +0100521 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +0100522 (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100523#endif
Simon Kelley824af852008-02-12 20:43:05 +0000524 start->queries++;
Simon Kelleyde379512004-06-22 20:23:33 +0100525 forwarded = 1;
526 forward->sentto = start;
Simon Kelley0a852542005-03-23 20:28:59 +0000527 if (!forward->forwardall)
Simon Kelleyde379512004-06-22 20:23:33 +0100528 break;
Simon Kelley0a852542005-03-23 20:28:59 +0000529 forward->forwardall++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000530 }
531 }
532
Simon Kelleyde379512004-06-22 20:23:33 +0100533 if (!(start = start->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100534 start = daemon->servers;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000535
Simon Kelleyde379512004-06-22 20:23:33 +0100536 if (start == firstsentto)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000537 break;
538 }
539
Simon Kelleyde379512004-06-22 20:23:33 +0100540 if (forwarded)
Simon Kelley824af852008-02-12 20:43:05 +0000541 return 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100542
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000543 /* could not send on, prepare to return */
544 header->id = htons(forward->orig_id);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100545 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000546 }
547
548 /* could not send on, return empty answer or address if known for whole domain */
Simon Kelleyb8187c82005-11-26 21:46:27 +0000549 if (udpfd != -1)
550 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000551 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
Simon Kelley54dd3932012-06-20 11:23:38 +0100552 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 +0000553 }
554
Simon Kelley824af852008-02-12 20:43:05 +0000555 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000556}
557
Simon Kelleyed4c0762013-10-08 20:46:34 +0100558static 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 +0100559 int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
560 int check_subnet, union mysockaddr *query_source)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100561{
Simon Kelley36717ee2004-09-20 19:20:58 +0100562 unsigned char *pheader, *sizep;
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000563 char **sets = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +0000564 int munged = 0, is_sign;
Simon Kelleycdeda282006-03-16 20:16:06 +0000565 size_t plen;
566
Simon Kelley83349b82014-02-10 21:02:01 +0000567 (void)ad_reqd;
Simon Kelley982faf42015-04-03 21:42:30 +0100568 (void)do_bit;
569 (void)bogusanswer;
Simon Kelley83349b82014-02-10 21:02:01 +0000570
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000571#ifdef HAVE_IPSET
Simon Kelley82a14af2014-04-13 20:48:57 +0100572 if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000573 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100574 /* Similar algorithm to search_servers. */
575 struct ipsets *ipset_pos;
576 unsigned int namelen = strlen(daemon->namebuff);
577 unsigned int matchlen = 0;
578 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
Simon Kelley6c0cb852014-01-17 14:40:46 +0000579 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100580 unsigned int domainlen = strlen(ipset_pos->domain);
581 char *matchstart = daemon->namebuff + namelen - domainlen;
582 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
583 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
584 domainlen >= matchlen)
585 {
586 matchlen = domainlen;
587 sets = ipset_pos->sets;
588 }
Simon Kelley6c0cb852014-01-17 14:40:46 +0000589 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000590 }
591#endif
592
Simon Kelley5bb88f02015-12-21 16:23:47 +0000593 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100594 {
Simon Kelleyed4c0762013-10-08 20:46:34 +0100595 if (check_subnet && !check_source(header, plen, pheader, query_source))
596 {
597 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
598 return 0;
599 }
Simon Kelley613ad152014-02-25 23:02:28 +0000600
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000601 if (!is_sign)
Simon Kelley613ad152014-02-25 23:02:28 +0000602 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000603 if (added_pheader)
604 {
605 /* client didn't send EDNS0, we added one, strip it off before returning answer. */
606 n = rrfilter(header, n, 0);
607 pheader = NULL;
608 }
609 else
610 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000611 unsigned short udpsz;
612
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000613 /* If upstream is advertising a larger UDP packet size
614 than we allow, trim it so that we don't get overlarge
615 requests for the client. We can't do this for signed packets. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000616 GETSHORT(udpsz, sizep);
617 if (udpsz > daemon->edns_pktsz)
Simon Kelley33702ab2015-12-28 23:17:15 +0000618 {
619 sizep -= 2;
620 PUTSHORT(daemon->edns_pktsz, sizep);
621 }
622
623#ifdef HAVE_DNSSEC
624 /* If the client didn't set the do bit, but we did, reset it. */
625 if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
626 {
627 unsigned short flags;
628 sizep += 2; /* skip RCODE */
629 GETSHORT(flags, sizep);
630 flags &= ~0x8000;
631 sizep -= 2;
632 PUTSHORT(flags, sizep);
633 }
634#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000635 }
Simon Kelley613ad152014-02-25 23:02:28 +0000636 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100637 }
Simon Kelley83349b82014-02-10 21:02:01 +0000638
Simon Kelley28866e92011-02-14 20:19:14 +0000639 /* RFC 4035 sect 4.6 para 3 */
Giovanni Bajo237724c2012-04-05 02:46:52 +0200640 if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
Simon Kelley795501b2014-01-08 18:11:55 +0000641 header->hb4 &= ~HB4_AD;
Simon Kelley3a237152013-12-12 12:15:50 +0000642
Simon Kelley572b41e2011-02-18 18:11:18 +0000643 if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
Simon Kelley8938ae02014-05-01 17:46:25 +0100644 return resize_packet(header, n, pheader, plen);
Simon Kelley36717ee2004-09-20 19:20:58 +0100645
Simon Kelley0a852542005-03-23 20:28:59 +0000646 /* Complain loudly if the upstream server is non-recursive. */
Simon Kelley92be34a2016-01-16 18:39:54 +0000647 if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
Simon Kelley0a852542005-03-23 20:28:59 +0000648 server && !(server->flags & SERV_WARNED_RECURSIVE))
649 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100650 prettyprint_addr(&server->addr, daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100651 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
Simon Kelley28866e92011-02-14 20:19:14 +0000652 if (!option_bool(OPT_LOG))
Simon Kelley0a852542005-03-23 20:28:59 +0000653 server->flags |= SERV_WARNED_RECURSIVE;
654 }
Giovanni Bajoe292e932012-04-22 14:32:02 +0200655
Simon Kelley572b41e2011-02-18 18:11:18 +0000656 if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100657 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100658 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100659 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000660 SET_RCODE(header, NXDOMAIN);
661 header->hb3 &= ~HB3_AA;
Simon Kelley6938f342014-01-26 22:47:39 +0000662 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100663 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100664 else
Simon Kelley36717ee2004-09-20 19:20:58 +0100665 {
Simon Kelley6938f342014-01-26 22:47:39 +0000666 int doctored = 0;
667
Simon Kelley572b41e2011-02-18 18:11:18 +0000668 if (RCODE(header) == NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100669 extract_request(header, n, daemon->namebuff, NULL) &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100670 check_for_local_domain(daemon->namebuff, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100671 {
Simon Kelley36717ee2004-09-20 19:20:58 +0100672 /* if we forwarded a query for a locally known name (because it was for
673 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
674 since we know that the domain exists, even if upstream doesn't */
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100675 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000676 header->hb3 |= HB3_AA;
677 SET_RCODE(header, NOERROR);
Simon Kelley6938f342014-01-26 22:47:39 +0000678 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100679 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000680
Simon Kelley6938f342014-01-26 22:47:39 +0000681 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 +0000682 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100683 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
Simon Kelley824af852008-02-12 20:43:05 +0000684 munged = 1;
Simon Kelley6938f342014-01-26 22:47:39 +0000685 cache_secure = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000686 }
Simon Kelley6938f342014-01-26 22:47:39 +0000687
688 if (doctored)
689 cache_secure = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100690 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100691
Simon Kelleya25720a2014-01-14 23:13:55 +0000692#ifdef HAVE_DNSSEC
Simon Kelley33702ab2015-12-28 23:17:15 +0000693 if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
Simon Kelleya25720a2014-01-14 23:13:55 +0000694 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000695 /* Bogus reply, turn into SERVFAIL */
696 SET_RCODE(header, SERVFAIL);
697 munged = 1;
Simon Kelleya25720a2014-01-14 23:13:55 +0000698 }
Simon Kelley6938f342014-01-26 22:47:39 +0000699
700 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000701 {
702 header->hb4 &= ~HB4_AD;
703
704 if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
705 header->hb4 |= HB4_AD;
706
707 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
708 if (!do_bit)
709 n = rrfilter(header, n, 1);
710 }
Simon Kelleya25720a2014-01-14 23:13:55 +0000711#endif
712
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100713 /* do this after extract_addresses. Ensure NODATA reply and remove
714 nameserver info. */
715
716 if (munged)
717 {
718 header->ancount = htons(0);
719 header->nscount = htons(0);
720 header->arcount = htons(0);
Simon Kelley150162b2015-03-27 09:58:26 +0000721 header->hb3 &= ~HB3_TC;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100722 }
723
Simon Kelley36717ee2004-09-20 19:20:58 +0100724 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
725 sections of the packet. Find the new length here and put back pseudoheader
726 if it was removed. */
727 return resize_packet(header, n, pheader, plen);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100728}
729
Simon Kelley3be34542004-09-11 19:12:13 +0100730/* sets new last_server */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100731void reply_query(int fd, int family, time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000732{
733 /* packet from peer server, extract data for cache, and send to
734 original requester */
Simon Kelley572b41e2011-02-18 18:11:18 +0000735 struct dns_header *header;
Simon Kelleyde379512004-06-22 20:23:33 +0100736 union mysockaddr serveraddr;
Simon Kelley832af0b2007-01-21 20:01:28 +0000737 struct frec *forward;
Simon Kelleyde379512004-06-22 20:23:33 +0100738 socklen_t addrlen = sizeof(serveraddr);
Simon Kelley60b68062014-01-08 12:10:28 +0000739 ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
Simon Kelleycdeda282006-03-16 20:16:06 +0000740 size_t nn;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100741 struct server *server;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000742 void *hash;
743#ifndef HAVE_DNSSEC
744 unsigned int crc;
745#endif
746
Simon Kelleycdeda282006-03-16 20:16:06 +0000747 /* packet buffer overwritten */
748 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000749
Simon Kelleyde379512004-06-22 20:23:33 +0100750 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100751 serveraddr.sa.sa_family = family;
Simon Kelleyde379512004-06-22 20:23:33 +0100752#ifdef HAVE_IPV6
753 if (serveraddr.sa.sa_family == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100754 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100755#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000756
Simon Kelley490f9072014-03-24 22:04:42 +0000757 header = (struct dns_header *)daemon->packet;
758
759 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
760 return;
761
Simon Kelley1a6bca82008-07-11 11:11:42 +0100762 /* spoof check: answer must come from known server, */
763 for (server = daemon->servers; server; server = server->next)
764 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
765 sockaddr_isequal(&server->addr, &serveraddr))
766 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000767
768 if (!server)
769 return;
770
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000771#ifdef HAVE_DNSSEC
772 hash = hash_questions(header, n, daemon->namebuff);
773#else
774 hash = &crc;
775 crc = questions_crc(header, n, daemon->namebuff);
776#endif
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100777
Simon Kelley490f9072014-03-24 22:04:42 +0000778 if (!(forward = lookup_frec(ntohs(header->id), hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100779 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000780
Simon Kelley25cf5e32015-01-09 15:53:03 +0000781 /* log_query gets called indirectly all over the place, so
782 pass these in global variables - sorry. */
783 daemon->log_display_id = forward->log_id;
784 daemon->log_source_addr = &forward->source;
785
Glen Huang32fc6db2014-12-27 15:28:12 +0000786 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
787 check_for_ignored_address(header, n, daemon->ignore_addr))
788 return;
789
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000790 /* Note: if we send extra options in the EDNS0 header, we can't recreate
791 the query from the reply. */
Simon Kelley2ae195f2015-01-18 22:20:48 +0000792 if (RCODE(header) == REFUSED &&
Simon Kelley28866e92011-02-14 20:19:14 +0000793 !option_bool(OPT_ORDER) &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000794 forward->forwardall == 0 &&
795 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100796 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000797 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100798 unsigned char *pheader;
799 size_t plen;
800 int is_sign;
Simon Kelley832af0b2007-01-21 20:01:28 +0000801
Simon Kelley1a6bca82008-07-11 11:11:42 +0100802 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000803 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100804 if (!is_sign)
Simon Kelley832af0b2007-01-21 20:01:28 +0000805 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100806 header->ancount = htons(0);
807 header->nscount = htons(0);
808 header->arcount = htons(0);
809 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
810 {
swiggerbd7bfa22015-06-01 20:54:59 +0100811 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000812 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000813 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000814 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000815 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000816 header->hb4 |= HB4_AD;
817 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000818 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000819 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 +0100820 return;
821 }
822 }
823 }
Simon Kelley3a237152013-12-12 12:15:50 +0000824
825 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100826 if ((forward->sentto->flags & SERV_TYPE) == 0)
827 {
Simon Kelley51967f92014-03-25 21:07:00 +0000828 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100829 server = NULL;
830 else
831 {
832 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000833
Simon Kelley1a6bca82008-07-11 11:11:42 +0100834 /* find good server by address if possible, otherwise assume the last one we sent to */
835 for (last_server = daemon->servers; last_server; last_server = last_server->next)
836 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
837 sockaddr_isequal(&last_server->addr, &serveraddr))
838 {
839 server = last_server;
840 break;
841 }
842 }
Simon Kelley28866e92011-02-14 20:19:14 +0000843 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100844 daemon->last_server = server;
845 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100846
847 /* We tried resending to this server with a smaller maximum size and got an answer.
Simon Kelley86fa1042015-05-10 13:50:59 +0100848 Make that permanent. To avoid reduxing the packet size for an single dropped packet,
849 only do this when we get a truncated answer, or one larger than the safe size. */
850 if (server && (forward->flags & FREC_TEST_PKTSZ) &&
851 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelleya77cec82015-05-08 16:25:38 +0100852 server->edns_pktsz = SAFE_PKTSZ;
853
Simon Kelley1a6bca82008-07-11 11:11:42 +0100854 /* If the answer is an error, keep the forward record in place in case
855 we get a good reply from another server. Kill it when we've
856 had replies from all to avoid filling the forwarding table when
857 everything is broken */
Baptiste Jonglez68f63122017-02-06 21:09:11 +0000858 if (forward->forwardall == 0 || --forward->forwardall == 1 ||
859 (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100860 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100861 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100862
Simon Kelley3a237152013-12-12 12:15:50 +0000863 if (option_bool(OPT_NO_REBIND))
864 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100865
Simon Kelley3a237152013-12-12 12:15:50 +0000866 /* Don't cache replies where DNSSEC validation was turned off, either
867 the upstream server told us so, or the original query specified it. */
868 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
869 no_cache_dnssec = 1;
870
871#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000872 if (server && (server->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000873 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000874 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000875 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000876
877 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000878 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000879 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000880
881 /* Truncated answer can't be validated.
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100882 If this is an answer to a DNSSEC-generated query, we still
883 need to get the client to retry over TCP, so return
884 an answer with the TC bit set, even if the actual answer fits.
885 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000886 if (header->hb3 & HB3_TC)
887 status = STAT_TRUNCATED;
888
889 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000890 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000891 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
892 would invite infinite loops, since the answers to DNSKEY and DS queries
893 will not be cached, so they'll be repeated. */
894 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000895 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000896 if (forward->flags & FREC_DNSKEY_QUERY)
897 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
898 else if (forward->flags & FREC_DS_QUERY)
899 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000900 else
Simon Kelley9a31b682015-12-15 10:20:39 +0000901 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
Simon Kelleyff19b1a2017-05-21 21:15:32 +0100902 option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC), NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000903 }
Simon Kelley0fc2f312014-01-08 10:26:58 +0000904
Simon Kelley9a31b682015-12-15 10:20:39 +0000905 /* Can't validate, as we're missing key data. Put this
906 answer aside, whilst we get that. */
907 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +0000908 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000909 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +0000910
Simon Kelley9a31b682015-12-15 10:20:39 +0000911 /* Free any saved query */
912 if (forward->stash)
913 blockdata_free(forward->stash);
914
915 /* Now save reply pending receipt of key data */
916 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +0000917 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000918 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000919
Simon Kelley9a31b682015-12-15 10:20:39 +0000920 /* Find the original query that started it all.... */
921 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +0000922
Simon Kelley9a31b682015-12-15 10:20:39 +0000923 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
924 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000925 else
Simon Kelley3a237152013-12-12 12:15:50 +0000926 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000927 int fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +0000928 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +0000929 char *domain;
930
Simon Kelley9a31b682015-12-15 10:20:39 +0000931 *new = *forward; /* copy everything, then overwrite */
932 new->next = next;
933 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +0000934
935 /* Find server to forward to. This will normally be the
936 same as for the original query, but may be another if
937 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100938 if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
Simon Kelley92be34a2016-01-16 18:39:54 +0000939 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000940 struct server *start = server, *new_server = NULL;
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100941
942 while (1)
943 {
944 if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
945 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
946 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
947 {
948 new_server = start;
949 if (server == start)
950 {
951 new_server = NULL;
952 break;
953 }
954 }
955
956 if (!(start = start->next))
957 start = daemon->servers;
958 if (start == server)
959 break;
960 }
961
962 if (new_server)
963 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +0000964 }
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100965
Simon Kelley9a31b682015-12-15 10:20:39 +0000966 new->sentto = server;
967 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,
Simon Kelleyff19b1a2017-05-21 21:15:32 +01001480 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 Kelley09f3b2c2017-05-09 01:34:02 +01001509 if (search_servers(now, NULL, F_DNSSECOK, 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
Simon Kelley361dfe52017-02-10 21:12:30 +00001515 while (1)
1516 {
1517 if (!firstsendto)
1518 firstsendto = server;
1519 else
1520 {
1521 if (!(server = server->next))
1522 server = daemon->servers;
1523 if (server == firstsendto)
1524 {
1525 /* can't find server to accept our query. */
1526 new_status = STAT_ABANDONED;
1527 break;
1528 }
1529 }
1530
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001531 if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001532 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1533 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1534 continue;
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001535
1536 retry:
1537 /* may need to make new connection. */
1538 if (server->tcpfd == -1)
1539 {
1540 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
Simon Kelley361dfe52017-02-10 21:12:30 +00001541 continue; /* No good, next server */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001542
1543#ifdef HAVE_CONNTRACK
1544 /* Copy connection mark of incoming query to outgoing connection. */
1545 if (have_mark)
1546 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1547#endif
1548
1549 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 1) ||
1550 connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
1551 {
1552 close(server->tcpfd);
1553 server->tcpfd = -1;
1554 continue; /* No good, next server */
1555 }
1556
1557 server->flags &= ~SERV_GOT_TCP;
1558 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001559
1560 if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
1561 !read_write(server->tcpfd, &c1, 1, 1) ||
1562 !read_write(server->tcpfd, &c2, 1, 1) ||
1563 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1564 {
1565 close(server->tcpfd);
1566 server->tcpfd = -1;
1567 /* We get data then EOF, reopen connection to same server,
1568 else try next. This avoids DoS from a server which accepts
1569 connections and then closes them. */
1570 if (server->flags & SERV_GOT_TCP)
1571 goto retry;
1572 else
1573 continue;
1574 }
1575
1576 server->flags |= SERV_GOT_TCP;
1577
1578 m = (c1 << 8) | c2;
1579 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1580 break;
1581 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001582
1583 if (new_status != STAT_OK)
1584 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001585 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001586
Simon Kelley9a31b682015-12-15 10:20:39 +00001587 if (packet)
1588 free(packet);
1589
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001590 return new_status;
1591}
1592#endif
1593
1594
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001595/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001596 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001597 about resources for debug mode, when the fork is suppressed: that's
1598 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001599unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001600 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001601{
Simon Kelley28866e92011-02-14 20:19:14 +00001602 size_t size = 0;
1603 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001604#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001605 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001606#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001607 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001608 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001609 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001610 unsigned short qtype;
1611 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001612 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001613 /* Max TCP packet + slop + size */
1614 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1615 unsigned char *payload = &packet[2];
1616 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1617 struct dns_header *header = (struct dns_header *)payload;
1618 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001619 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001620 struct in_addr dst_addr_4;
1621 union mysockaddr peer_addr;
1622 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001623 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001624 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001625 unsigned int mark = 0;
1626 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001627
Simon Kelleyd05dd582016-01-19 21:23:30 +00001628 (void)mark;
1629 (void)have_mark;
1630
Simon Kelley7de060b2011-08-26 17:24:52 +01001631 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1632 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001633
1634#ifdef HAVE_CONNTRACK
1635 /* Get connection mark of incoming query to set on outgoing connections. */
1636 if (option_bool(OPT_CONNTRACK))
1637 {
1638 struct all_addr local;
1639#ifdef HAVE_IPV6
1640 if (local_addr->sa.sa_family == AF_INET6)
1641 local.addr.addr6 = local_addr->in6.sin6_addr;
1642 else
1643#endif
1644 local.addr.addr4 = local_addr->in.sin_addr;
1645
1646 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1647 }
1648#endif
1649
Simon Kelleyc8a80482014-03-05 14:29:54 +00001650 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1651 if (option_bool(OPT_LOCAL_SERVICE))
1652 {
1653 struct addrlist *addr;
1654#ifdef HAVE_IPV6
1655 if (peer_addr.sa.sa_family == AF_INET6)
1656 {
1657 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1658 if ((addr->flags & ADDRLIST_IPV6) &&
1659 is_same_net6(&addr->addr.addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
1660 break;
1661 }
1662 else
1663#endif
1664 {
1665 struct in_addr netmask;
1666 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1667 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001668 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001669 if (!(addr->flags & ADDRLIST_IPV6) &&
1670 is_same_net(addr->addr.addr.addr4, peer_addr.in.sin_addr, netmask))
1671 break;
1672 }
1673 }
1674 if (!addr)
1675 {
1676 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1677 return packet;
1678 }
1679 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001680
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001681 while (1)
1682 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001683 if (query_count == TCP_MAX_QUERIES ||
1684 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001685 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1686 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001687 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001688 return packet;
1689
Simon Kelley572b41e2011-02-18 18:11:18 +00001690 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001691 continue;
1692
Simon Kelley25cf5e32015-01-09 15:53:03 +00001693 query_count++;
1694
1695 /* log_query gets called indirectly all over the place, so
1696 pass these in global variables - sorry. */
1697 daemon->log_display_id = ++daemon->log_id;
1698 daemon->log_source_addr = &peer_addr;
1699
Simon Kelley28866e92011-02-14 20:19:14 +00001700 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001701 if ((checking_disabled = header->hb4 & HB4_CD))
1702 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001703
Simon Kelley3be34542004-09-11 19:12:13 +01001704 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001705 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001706#ifdef HAVE_AUTH
1707 struct auth_zone *zone;
1708#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001709 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001710
1711 if (peer_addr.sa.sa_family == AF_INET)
1712 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
1713 (struct all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001714#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001715 else
1716 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
1717 (struct all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001718#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001719
1720#ifdef HAVE_AUTH
1721 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001722 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001723 for (zone = daemon->auth_zones; zone; zone = zone->next)
1724 if (in_zone(zone, daemon->namebuff, NULL))
1725 {
1726 auth_dns = 1;
1727 local_auth = 1;
1728 break;
1729 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001730#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001731 }
1732
Simon Kelley7de060b2011-08-26 17:24:52 +01001733 if (local_addr->sa.sa_family == AF_INET)
1734 dst_addr_4 = local_addr->in.sin_addr;
1735 else
1736 dst_addr_4.s_addr = 0;
1737
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001738 do_bit = 0;
1739
Simon Kelley5bb88f02015-12-21 16:23:47 +00001740 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001741 {
1742 unsigned short flags;
1743
1744 have_pseudoheader = 1;
1745 pheader += 4; /* udp_size, ext_rcode */
1746 GETSHORT(flags, pheader);
1747
1748 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001749 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001750 }
1751
Simon Kelley4820dce2012-12-18 18:30:30 +00001752#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001753 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001754 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1755 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001756 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001757#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001758 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001759 int ad_reqd = do_bit;
1760 /* RFC 6840 5.7 */
1761 if (header->hb4 & HB4_AD)
1762 ad_reqd = 1;
1763
1764 /* m > 0 if answered from cache */
1765 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1766 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001767
Simon Kelley4f7b3042012-11-28 21:27:02 +00001768 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001769 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001770
1771 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001772 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001773 unsigned int flags = 0;
1774 struct all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001775 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001776 char *domain = NULL;
Simon Kelley33702ab2015-12-28 23:17:15 +00001777 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 +01001778
Simon Kelley33702ab2015-12-28 23:17:15 +00001779 if (size != new_size)
1780 {
1781 added_pheader = 1;
1782 size = new_size;
1783 }
1784
Simon Kelley4f7b3042012-11-28 21:27:02 +00001785 if (gotname)
1786 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
1787
Simon Kelley367341f2016-01-12 15:58:23 +00001788 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001789
Simon Kelley4f7b3042012-11-28 21:27:02 +00001790 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1791 last_server = daemon->servers;
1792 else
1793 last_server = daemon->last_server;
1794
1795 if (!flags && last_server)
1796 {
1797 struct server *firstsendto = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001798#ifdef HAVE_DNSSEC
Simon Kelley703c7ff2014-01-25 23:46:23 +00001799 unsigned char *newhash, hash[HASH_SIZE];
Simon Kelley63758382014-04-16 22:20:55 +01001800 if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001801 memcpy(hash, newhash, HASH_SIZE);
Tomas Hozzab37f8b92014-03-25 20:52:28 +00001802 else
1803 memset(hash, 0, HASH_SIZE);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001804#else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001805 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001806#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001807 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001808 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001809 which can go to the same server, do so. */
1810 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001811 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001812 if (!firstsendto)
1813 firstsendto = last_server;
1814 else
1815 {
1816 if (!(last_server = last_server->next))
1817 last_server = daemon->servers;
1818
1819 if (last_server == firstsendto)
1820 break;
1821 }
1822
1823 /* server for wrong domain */
1824 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001825 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
1826 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01001827 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00001828
1829 retry:
Simon Kelley4f7b3042012-11-28 21:27:02 +00001830 if (last_server->tcpfd == -1)
1831 {
1832 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1833 continue;
1834
Karl Vogele9828b62014-10-03 21:45:15 +01001835#ifdef HAVE_CONNTRACK
1836 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001837 if (have_mark)
1838 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Karl Vogele9828b62014-10-03 21:45:15 +01001839#endif
1840
Simon Kelley4f7b3042012-11-28 21:27:02 +00001841 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
1842 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
1843 {
1844 close(last_server->tcpfd);
1845 last_server->tcpfd = -1;
1846 continue;
1847 }
1848
Simon Kelley361dfe52017-02-10 21:12:30 +00001849 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001850 }
1851
Simon Kelley361dfe52017-02-10 21:12:30 +00001852#ifdef HAVE_DNSSEC
1853 if (option_bool(OPT_DNSSEC_VALID) && (last_server->flags & SERV_DO_DNSSEC))
1854 {
1855 new_size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1856
1857 if (size != new_size)
1858 {
1859 added_pheader = 1;
1860 size = new_size;
1861 }
1862
1863 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1864 this allows it to select auth servers when one is returning bad data. */
1865 if (option_bool(OPT_DNSSEC_DEBUG))
1866 header->hb4 |= HB4_CD;
1867 }
1868#endif
1869
Simon Kelley4b5ea122013-04-22 10:18:26 +01001870 *length = htons(size);
Simon Kelley1fc02682014-04-29 12:30:18 +01001871
1872 /* get query name again for logging - may have been overwritten */
1873 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
1874 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00001875
Simon Kelley4b5ea122013-04-22 10:18:26 +01001876 if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00001877 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001878 !read_write(last_server->tcpfd, &c2, 1, 1) ||
1879 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01001880 {
1881 close(last_server->tcpfd);
1882 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00001883 /* We get data then EOF, reopen connection to same server,
1884 else try next. This avoids DoS from a server which accepts
1885 connections and then closes them. */
1886 if (last_server->flags & SERV_GOT_TCP)
1887 goto retry;
1888 else
1889 continue;
1890 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001891
Simon Kelley361dfe52017-02-10 21:12:30 +00001892 last_server->flags |= SERV_GOT_TCP;
1893
Simon Kelley4f7b3042012-11-28 21:27:02 +00001894 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001895
Simon Kelley4f7b3042012-11-28 21:27:02 +00001896 if (last_server->addr.sa.sa_family == AF_INET)
1897 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1898 (struct all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001899#ifdef HAVE_IPV6
Simon Kelley4f7b3042012-11-28 21:27:02 +00001900 else
1901 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1902 (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001903#endif
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001904
1905#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00001906 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001907 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00001908 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001909 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
1910 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01001911 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001912
Simon Kelley9a31b682015-12-15 10:20:39 +00001913 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001914 {
1915 result = "ABANDONED";
1916 status = STAT_BOGUS;
1917 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001918 else
1919 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01001920
1921 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
1922 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01001923
1924 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001925
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001926 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001927 {
1928 no_cache_dnssec = 1;
1929 bogusanswer = 1;
1930 }
1931
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001932 if (status == STAT_SECURE)
1933 cache_secure = 1;
1934 }
1935#endif
1936
1937 /* restore CD bit to the value in the query */
1938 if (checking_disabled)
1939 header->hb4 |= HB4_CD;
1940 else
1941 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001942
1943 /* There's no point in updating the cache, since this process will exit and
1944 lose the information after a few queries. We make this call for the alias and
1945 bogus-nxdomain side-effects. */
1946 /* If the crc of the question section doesn't match the crc we sent, then
1947 someone might be attempting to insert bogus values into the cache by
1948 sending replies containing questions and bogus answers. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001949#ifdef HAVE_DNSSEC
1950 newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
1951 if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00001952 {
1953 m = 0;
1954 break;
1955 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001956#else
1957 if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
Simon Kelley703c7ff2014-01-25 23:46:23 +00001958 {
1959 m = 0;
1960 break;
1961 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001962#endif
1963
1964 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01001965 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001966 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001967
1968 break;
1969 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001970 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001971
1972 /* In case of local answer or no connections made. */
1973 if (m == 0)
1974 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001975 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001976 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001977
Simon Kelleyb842bc92015-07-12 21:09:11 +01001978 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001979
Simon Kelley4b5ea122013-04-22 10:18:26 +01001980 *length = htons(m);
1981
1982 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001983 return packet;
1984 }
1985}
1986
Simon Kelley16972692006-10-16 20:04:18 +01001987static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001988{
Simon Kelley16972692006-10-16 20:04:18 +01001989 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001990
Simon Kelley5aabfc72007-08-29 11:24:47 +01001991 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001992 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001993 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001994 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00001995 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001996 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00001997 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001998#ifdef HAVE_IPV6
1999 f->rfd6 = NULL;
2000#endif
Simon Kelley3a237152013-12-12 12:15:50 +00002001#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002002 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002003 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002004 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002005#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002006 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002007 }
Simon Kelley16972692006-10-16 20:04:18 +01002008
2009 return f;
2010}
2011
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002012struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002013{
2014 static int finger = 0;
2015 int i;
2016
2017 /* limit the number of sockets we have open to avoid starvation of
2018 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2019
2020 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002021 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002022 {
Simon Kelley9009d742008-11-14 20:04:27 +00002023 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2024 break;
2025
Simon Kelley1a6bca82008-07-11 11:11:42 +01002026 daemon->randomsocks[i].refcount = 1;
2027 daemon->randomsocks[i].family = family;
2028 return &daemon->randomsocks[i];
2029 }
2030
Simon Kelley9009d742008-11-14 20:04:27 +00002031 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002032 for (i = 0; i < RANDOM_SOCKS; i++)
2033 {
2034 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002035 if (daemon->randomsocks[j].refcount != 0 &&
2036 daemon->randomsocks[j].family == family &&
2037 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002038 {
2039 finger = j;
2040 daemon->randomsocks[j].refcount++;
2041 return &daemon->randomsocks[j];
2042 }
2043 }
2044
2045 return NULL; /* doom */
2046}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002047
2048void free_rfd(struct randfd *rfd)
2049{
2050 if (rfd && --(rfd->refcount) == 0)
2051 close(rfd->fd);
2052}
2053
Simon Kelley1a6bca82008-07-11 11:11:42 +01002054static void free_frec(struct frec *f)
2055{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002056 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002057 f->rfd4 = NULL;
2058 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002059 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002060
2061#ifdef HAVE_IPV6
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002062 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002063 f->rfd6 = NULL;
2064#endif
Simon Kelley3a237152013-12-12 12:15:50 +00002065
2066#ifdef HAVE_DNSSEC
2067 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002068 {
2069 blockdata_free(f->stash);
2070 f->stash = NULL;
2071 }
Simon Kelley3a237152013-12-12 12:15:50 +00002072
2073 /* Anything we're waiting on is pointless now, too */
2074 if (f->blocking_query)
2075 free_frec(f->blocking_query);
2076 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002077 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002078#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002079}
2080
Simon Kelley09f3b2c2017-05-09 01:34:02 +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 */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002129 if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
Simon Kelley16972692006-10-16 20:04:18 +01002130 {
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}
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002169
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