blob: 428d7e7f04aa9cc4ed4172569dbc4de1380a2ec8 [file] [log] [blame]
Simon Kelley2a8710a2020-01-05 16:40:06 +00001/* dnsmasq is Copyright (c) 2000-2020 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,
Simon Kelleycc921df2019-01-02 22:48:59 +000029 union mysockaddr *to, union 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
Simon Kelley44a2a312004-03-10 20:04:35 +000041 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
Simon Kelley44a2a312004-03-10 20:04:35 +000042 } control_u;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010043
Simon Kelley44a2a312004-03-10 20:04:35 +000044 iov[0].iov_base = packet;
45 iov[0].iov_len = len;
46
Simon Kelleyfeba5c12004-07-27 20:28:58 +010047 msg.msg_control = NULL;
48 msg.msg_controllen = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +000049 msg.msg_flags = 0;
50 msg.msg_name = to;
51 msg.msg_namelen = sa_len(to);
52 msg.msg_iov = iov;
53 msg.msg_iovlen = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010054
Simon Kelley26128d22004-11-14 16:43:54 +000055 if (!nowild)
Simon Kelleyfeba5c12004-07-27 20:28:58 +010056 {
Simon Kelley26128d22004-11-14 16:43:54 +000057 struct cmsghdr *cmptr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010058 msg.msg_control = &control_u;
59 msg.msg_controllen = sizeof(control_u);
Simon Kelley26128d22004-11-14 16:43:54 +000060 cmptr = CMSG_FIRSTHDR(&msg);
Simon Kelley44a2a312004-03-10 20:04:35 +000061
Simon Kelley26128d22004-11-14 16:43:54 +000062 if (to->sa.sa_family == AF_INET)
63 {
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010064#if defined(HAVE_LINUX_NETWORK)
Simon Kelley8ef5ada2010-06-03 19:42:45 +010065 struct in_pktinfo p;
66 p.ipi_ifindex = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +000067 p.ipi_spec_dst = source->addr4;
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010068 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
Simon Kelley8ef5ada2010-06-03 19:42:45 +010069 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010070 cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
Simon Kelleyc72daea2012-01-05 21:33:27 +000071 cmptr->cmsg_level = IPPROTO_IP;
Simon Kelley26128d22004-11-14 16:43:54 +000072 cmptr->cmsg_type = IP_PKTINFO;
73#elif defined(IP_SENDSRCADDR)
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010074 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
Simon Kelleycc921df2019-01-02 22:48:59 +000075 memcpy(CMSG_DATA(cmptr), &(source->addr4), sizeof(source->addr4));
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010076 cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
Simon Kelley26128d22004-11-14 16:43:54 +000077 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
82 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +010083 struct in6_pktinfo p;
84 p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
Simon Kelleycc921df2019-01-02 22:48:59 +000085 p.ipi6_addr = source->addr6;
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010086 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
Simon Kelley8ef5ada2010-06-03 19:42:45 +010087 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010088 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 Kelley26128d22004-11-14 16:43:54 +000092 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +010093
Simon Kelleyff841eb2015-03-11 21:36:30 +000094 while (retry_send(sendmsg(fd, &msg, 0)));
95
Brad Smithea3c60a2020-03-08 14:53:59 +000096 if (errno != 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +010097 {
Brad Smithea3c60a2020-03-08 14:53:59 +000098#ifdef HAVE_LINUX_NETWORK
99 /* If interface is still in DAD, EINVAL results - ignore that. */
100 if (errno != EINVAL)
101 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
102#endif
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 Kelleycc921df2019-01-02 22:48:59 +0000109static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned int qtype,
Simon Kelley367341f2016-01-12 15:58:23 +0000110 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 Kelleycc921df2019-01-02 22:48:59 +0000121 static union all_addr zero;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100122
Simon Kelley3be34542004-09-11 19:12:13 +0100123 for (serv = daemon->servers; serv; serv=serv->next)
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100124 if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
125 continue;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100126 /* domain matches take priority over NODOTS matches */
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100127 else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100128 {
Simon Kelley28866e92011-02-14 20:19:14 +0000129 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100130 *type = SERV_FOR_NODOTS;
Sung Paea914d0a2019-12-30 17:07:37 -0600131 if ((serv->flags & SERV_NO_REBIND) && norebind)
132 *norebind = 1;
133 else if (serv->flags & SERV_NO_ADDR)
Simon Kelley36717ee2004-09-20 19:20:58 +0100134 flags = F_NXDOMAIN;
Simon Kelleyda8b6512018-09-03 23:18:36 +0100135 else if (serv->flags & SERV_LITERAL_ADDRESS)
Simon Kelley36717ee2004-09-20 19:20:58 +0100136 {
Simon Kelleyda8b6512018-09-03 23:18:36 +0100137 /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
138 if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
139 {
140 memset(&zero, 0, sizeof(zero));
141 flags = qtype;
142 *addrpp = &zero;
143 }
144 else if (sflag & qtype)
Simon Kelley36717ee2004-09-20 19:20:58 +0100145 {
146 flags = sflag;
147 if (serv->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000148 *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
Simon Kelley36717ee2004-09-20 19:20:58 +0100149 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000150 *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelley36717ee2004-09-20 19:20:58 +0100151 }
Simon Kelley824af852008-02-12 20:43:05 +0000152 else if (!flags || (flags & F_NXDOMAIN))
Simon Kelley36717ee2004-09-20 19:20:58 +0100153 flags = F_NOERR;
154 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100155 }
156 else if (serv->flags & SERV_HAS_DOMAIN)
157 {
158 unsigned int domainlen = strlen(serv->domain);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000159 char *matchstart = qdomain + namelen - domainlen;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100160 if (namelen >= domainlen &&
Simon Kelleyb8187c82005-11-26 21:46:27 +0000161 hostname_isequal(matchstart, serv->domain) &&
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100162 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100163 {
Simon Kelley92be34a2016-01-16 18:39:54 +0000164 if ((serv->flags & SERV_NO_REBIND) && norebind)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100165 *norebind = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000166 else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100167 {
Simon Kelley28866e92011-02-14 20:19:14 +0000168 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
169 /* implement priority rules for --address and --server for same domain.
170 --address wins if the address is for the correct AF
171 --server wins otherwise. */
172 if (domainlen != 0 && domainlen == matchlen)
Simon Kelley36717ee2004-09-20 19:20:58 +0100173 {
Simon Kelley28866e92011-02-14 20:19:14 +0000174 if ((serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100175 {
Simon Kelley28866e92011-02-14 20:19:14 +0000176 if (!(sflag & qtype) && flags == 0)
177 continue;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100178 }
Simon Kelley28866e92011-02-14 20:19:14 +0000179 else
180 {
181 if (flags & (F_IPV4 | F_IPV6))
182 continue;
183 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100184 }
Simon Kelley28866e92011-02-14 20:19:14 +0000185
186 if (domainlen >= matchlen)
187 {
Simon Kelley367341f2016-01-12 15:58:23 +0000188 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
Simon Kelley28866e92011-02-14 20:19:14 +0000189 *domain = serv->domain;
190 matchlen = domainlen;
191 if (serv->flags & SERV_NO_ADDR)
192 flags = F_NXDOMAIN;
193 else if (serv->flags & SERV_LITERAL_ADDRESS)
194 {
Simon Kelleyda8b6512018-09-03 23:18:36 +0100195 /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
196 if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
197 {
198 memset(&zero, 0, sizeof(zero));
199 flags = qtype;
200 *addrpp = &zero;
201 }
202 else if (sflag & qtype)
Simon Kelley28866e92011-02-14 20:19:14 +0000203 {
204 flags = sflag;
205 if (serv->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000206 *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000207 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000208 *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000209 }
210 else if (!flags || (flags & F_NXDOMAIN))
211 flags = F_NOERR;
212 }
213 else
214 flags = 0;
215 }
216 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100217 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100218 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100219
Simon Kelleybf05f8f2017-05-09 22:37:46 +0100220 if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) &&
Simon Kelley28866e92011-02-14 20:19:14 +0000221 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
Simon Kelley7de060b2011-08-26 17:24:52 +0100222 /* don't forward A or AAAA queries for simple names, except the empty name */
223 flags = F_NOERR;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100224
Simon Kelley5aabfc72007-08-29 11:24:47 +0100225 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
Simon Kelleyc1bb8502004-08-11 18:40:17 +0100226 flags = F_NOERR;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100227
Simon Kelley824af852008-02-12 20:43:05 +0000228 if (flags)
229 {
Simon Kelleyc346f612018-09-04 21:14:18 +0100230 if (flags == F_NXDOMAIN || flags == F_NOERR)
231 log_query(flags | qtype | F_NEG | F_CONFIG | F_FORWARD, qdomain, NULL, NULL);
232 else
233 {
234 /* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */
235 if (flags & F_IPV4)
236 log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL);
Simon Kelleyc346f612018-09-04 21:14:18 +0100237 if (flags & F_IPV6)
238 log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL);
Simon Kelleyc346f612018-09-04 21:14:18 +0100239 }
Simon Kelley824af852008-02-12 20:43:05 +0000240 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100241 else if ((*type) & SERV_USE_RESOLV)
242 {
243 *type = 0; /* use normal servers for this domain */
244 *domain = NULL;
245 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100246 return flags;
247}
Simon Kelley44a2a312004-03-10 20:04:35 +0000248
Simon Kelley824af852008-02-12 20:43:05 +0000249static int forward_query(int udpfd, union mysockaddr *udpaddr,
Simon Kelleycc921df2019-01-02 22:48:59 +0000250 union all_addr *dst_addr, unsigned int dst_iface,
Simon Kelley83349b82014-02-10 21:02:01 +0000251 struct dns_header *header, size_t plen, time_t now,
Simon Kelley613ad152014-02-25 23:02:28 +0000252 struct frec *forward, int ad_reqd, int do_bit)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000253{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000254 char *domain = NULL;
Simon Kelley367341f2016-01-12 15:58:23 +0000255 int type = SERV_DO_DNSSEC, norebind = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +0000256 union all_addr *addrp = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000257 unsigned int flags = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100258 struct server *start = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000259#ifdef HAVE_DNSSEC
260 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley367341f2016-01-12 15:58:23 +0000261 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000262#else
263 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
264 void *hash = &crc;
265#endif
Simon Kelley1682d152018-08-03 20:38:18 +0100266 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
267 unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
268 (void)do_bit;
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000269
Simon Kelley3d8df262005-08-29 12:19:27 +0100270 /* may be no servers available. */
Simon Kelleyd05dd582016-01-19 21:23:30 +0000271 if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000272 {
Simon Kelleya77cec82015-05-08 16:25:38 +0100273 /* If we didn't get an answer advertising a maximal packet in EDNS,
274 fall back to 1280, which should work everywhere on IPv6.
275 If that generates an answer, it will become the new default
276 for this server */
277 forward->flags |= FREC_TEST_PKTSZ;
278
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000279#ifdef HAVE_DNSSEC
Simon Kelleydac74312014-02-13 16:43:49 +0000280 /* If we've already got an answer to this query, but we're awaiting keys for validation,
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000281 there's no point retrying the query, retry the key query instead...... */
282 if (forward->blocking_query)
283 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000284 int fd, is_sign;
285 unsigned char *pheader;
Simon Kelleya77cec82015-05-08 16:25:38 +0100286
287 forward->flags &= ~FREC_TEST_PKTSZ;
288
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000289 while (forward->blocking_query)
290 forward = forward->blocking_query;
Simon Kelleya77cec82015-05-08 16:25:38 +0100291
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000292 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
293 plen = forward->stash_len;
294
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000295 forward->flags |= FREC_TEST_PKTSZ;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000296 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000297 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000298
Simon Kelley2b291912014-03-21 11:13:55 +0000299 if (forward->sentto->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000300 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (union all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000301 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000302 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
Simon Kelleyee875042018-10-23 22:10:17 +0100303
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000304
305 if (forward->sentto->sfd)
306 fd = forward->sentto->sfd->fd;
307 else
308 {
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000309 if (forward->sentto->addr.sa.sa_family == AF_INET6)
310 fd = forward->rfd6->fd;
311 else
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000312 fd = forward->rfd4->fd;
313 }
314
Simon Kelleya0088e82018-05-10 21:43:14 +0100315 while (retry_send(sendto(fd, (char *)header, plen, 0,
316 &forward->sentto->addr.sa,
317 sa_len(&forward->sentto->addr))));
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000318
319 return 1;
320 }
321#endif
322
Simon Kelleyde379512004-06-22 20:23:33 +0100323 /* retry on existing query, send to all available servers */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000324 domain = forward->sentto->domain;
Simon Kelley824af852008-02-12 20:43:05 +0000325 forward->sentto->failed_queries++;
Simon Kelley28866e92011-02-14 20:19:14 +0000326 if (!option_bool(OPT_ORDER))
Simon Kelleyde379512004-06-22 20:23:33 +0100327 {
Simon Kelley0a852542005-03-23 20:28:59 +0000328 forward->forwardall = 1;
Simon Kelley3be34542004-09-11 19:12:13 +0100329 daemon->last_server = NULL;
Simon Kelleyde379512004-06-22 20:23:33 +0100330 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000331 type = forward->sentto->flags & SERV_TYPE;
Simon Kelley367341f2016-01-12 15:58:23 +0000332#ifdef HAVE_DNSSEC
333 do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
334#endif
335
Simon Kelleyde379512004-06-22 20:23:33 +0100336 if (!(start = forward->sentto->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100337 start = daemon->servers; /* at end of list, recycle */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000338 header->id = htons(forward->new_id);
339 }
340 else
341 {
342 if (gotname)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100343 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000344
Simon Kelley367341f2016-01-12 15:58:23 +0000345#ifdef HAVE_DNSSEC
346 do_dnssec = type & SERV_DO_DNSSEC;
Simon Kelleyf7443d72016-01-19 20:29:57 +0000347#endif
348 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +0000349
Simon Kelleyd05dd582016-01-19 21:23:30 +0000350 if (daemon->servers && !flags)
Simon Kelley8caf3d72020-04-04 17:00:32 +0100351 forward = get_new_frec(now, NULL, NULL);
Simon Kelleyd05dd582016-01-19 21:23:30 +0000352 /* table full - flags == 0, return REFUSED */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000353
354 if (forward)
355 {
Simon Kelley0a852542005-03-23 20:28:59 +0000356 forward->source = *udpaddr;
357 forward->dest = *dst_addr;
358 forward->iface = dst_iface;
Simon Kelley0a852542005-03-23 20:28:59 +0000359 forward->orig_id = ntohs(header->id);
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000360 forward->new_id = get_id();
Simon Kelley832af0b2007-01-21 20:01:28 +0000361 forward->fd = udpfd;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000362 memcpy(forward->hash, hash, HASH_SIZE);
Simon Kelley0a852542005-03-23 20:28:59 +0000363 forward->forwardall = 0;
Simon Kelleyed4c0762013-10-08 20:46:34 +0100364 forward->flags = 0;
Simon Kelley28866e92011-02-14 20:19:14 +0000365 if (norebind)
366 forward->flags |= FREC_NOREBIND;
Simon Kelley572b41e2011-02-18 18:11:18 +0000367 if (header->hb4 & HB4_CD)
Simon Kelley28866e92011-02-14 20:19:14 +0000368 forward->flags |= FREC_CHECKING_DISABLED;
Simon Kelley83349b82014-02-10 21:02:01 +0000369 if (ad_reqd)
370 forward->flags |= FREC_AD_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000371#ifdef HAVE_DNSSEC
372 forward->work_counter = DNSSEC_WORK;
Simon Kelley613ad152014-02-25 23:02:28 +0000373 if (do_bit)
374 forward->flags |= FREC_DO_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000375#endif
Simon Kelley613ad152014-02-25 23:02:28 +0000376
Simon Kelley28866e92011-02-14 20:19:14 +0000377 header->id = htons(forward->new_id);
378
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100379 /* In strict_order mode, always try servers in the order
380 specified in resolv.conf, if a domain is given
381 always try all the available servers,
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000382 otherwise, use the one last known to work. */
383
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100384 if (type == 0)
385 {
Simon Kelley28866e92011-02-14 20:19:14 +0000386 if (option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100387 start = daemon->servers;
388 else if (!(start = daemon->last_server) ||
389 daemon->forwardcount++ > FORWARD_TEST ||
390 difftime(now, daemon->forwardtime) > FORWARD_TIME)
391 {
392 start = daemon->servers;
393 forward->forwardall = 1;
394 daemon->forwardcount = 0;
395 daemon->forwardtime = now;
396 }
397 }
398 else
Simon Kelleyde379512004-06-22 20:23:33 +0100399 {
Simon Kelley3be34542004-09-11 19:12:13 +0100400 start = daemon->servers;
Simon Kelley28866e92011-02-14 20:19:14 +0000401 if (!option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100402 forward->forwardall = 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100403 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000404 }
405 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100406
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000407 /* check for send errors here (no route to host)
408 if we fail to send to all nameservers, send back an error
409 packet straight away (helps modem users when offline) */
410
411 if (!flags && forward)
412 {
Simon Kelleyde379512004-06-22 20:23:33 +0100413 struct server *firstsentto = start;
Simon Kelley33702ab2015-12-28 23:17:15 +0000414 int subnet, forwarded = 0;
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000415 size_t edns0_len;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000416 unsigned char *pheader;
417
Simon Kelley25cf5e32015-01-09 15:53:03 +0000418 /* If a query is retried, use the log_id for the retry when logging the answer. */
419 forward->log_id = daemon->log_id;
420
Simon Kelley6fd5d792017-10-13 22:26:40 +0100421 plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
Simon Kelley33702ab2015-12-28 23:17:15 +0000422
Simon Kelley6fd5d792017-10-13 22:26:40 +0100423 if (subnet)
424 forward->flags |= FREC_HAS_SUBNET;
Simon Kelley33702ab2015-12-28 23:17:15 +0000425
Simon Kelley3a237152013-12-12 12:15:50 +0000426#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000427 if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000428 {
Simon Kelley6fd5d792017-10-13 22:26:40 +0100429 plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
430
Simon Kelley5b3bf922014-01-25 17:03:07 +0000431 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
432 this allows it to select auth servers when one is returning bad data. */
433 if (option_bool(OPT_DNSSEC_DEBUG))
434 header->hb4 |= HB4_CD;
Simon Kelley613ad152014-02-25 23:02:28 +0000435
Simon Kelley0fc2f312014-01-08 10:26:58 +0000436 }
Simon Kelley3a237152013-12-12 12:15:50 +0000437#endif
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000438
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000439 if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
Simon Kelley6fd5d792017-10-13 22:26:40 +0100440 {
441 /* If there wasn't a PH before, and there is now, we added it. */
442 if (!oph)
443 forward->flags |= FREC_ADDED_PHEADER;
444
445 /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
446 if (edns0_len > 11)
447 forward->flags |= FREC_HAS_EXTRADATA;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000448
449 /* Reduce udp size on retransmits. */
450 if (forward->flags & FREC_TEST_PKTSZ)
451 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelley6fd5d792017-10-13 22:26:40 +0100452 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100453
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000454 while (1)
455 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000456 /* only send to servers dealing with our domain.
457 domain may be NULL, in which case server->domain
458 must be NULL also. */
459
Simon Kelleyde379512004-06-22 20:23:33 +0100460 if (type == (start->flags & SERV_TYPE) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100461 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100462 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000463 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100464 int fd;
465
466 /* find server socket to use, may need to get random one. */
467 if (start->sfd)
468 fd = start->sfd->fd;
469 else
470 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100471 if (start->addr.sa.sa_family == AF_INET6)
472 {
473 if (!forward->rfd6 &&
474 !(forward->rfd6 = allocate_rfd(AF_INET6)))
475 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100476 daemon->rfd_save = forward->rfd6;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100477 fd = forward->rfd6->fd;
478 }
479 else
Simon Kelley1a6bca82008-07-11 11:11:42 +0100480 {
481 if (!forward->rfd4 &&
482 !(forward->rfd4 = allocate_rfd(AF_INET)))
483 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100484 daemon->rfd_save = forward->rfd4;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100485 fd = forward->rfd4->fd;
486 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100487
488#ifdef HAVE_CONNTRACK
489 /* Copy connection mark of incoming query to outgoing connection. */
490 if (option_bool(OPT_CONNTRACK))
491 {
492 unsigned int mark;
Giacomo Tazzari797a7af2013-04-22 13:16:37 +0100493 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
Simon Kelley7de060b2011-08-26 17:24:52 +0100494 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
495 }
496#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100497 }
498
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000499#ifdef HAVE_DNSSEC
Simon Kelley5bb88f02015-12-21 16:23:47 +0000500 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000501 {
502 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
503 packet size to 512. But that won't provide space for the RRSIGS in many cases.
504 The RRSIGS will be stripped out before the answer goes back, so the packet should
505 shrink again. So, if we added a do-bit, bump the udp packet size to the value
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000506 known to be OK for this server. We check returned size after stripping and set
507 the truncated bit if it's still too big. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000508 unsigned char *pheader;
509 int is_sign;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000510 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000511 PUTSHORT(start->edns_pktsz, pheader);
512 }
513#endif
514
Simon Kelleyff841eb2015-03-11 21:36:30 +0000515 if (retry_send(sendto(fd, (char *)header, plen, 0,
516 &start->addr.sa,
517 sa_len(&start->addr))))
518 continue;
519
520 if (errno == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000521 {
Simon Kelley6b173352018-05-08 18:32:14 +0100522#ifdef HAVE_DUMPFILE
523 dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &start->addr);
524#endif
525
Simon Kelleycdeda282006-03-16 20:16:06 +0000526 /* Keep info in case we want to re-send this packet */
527 daemon->srv_save = start;
528 daemon->packet_len = plen;
529
Simon Kelleyde379512004-06-22 20:23:33 +0100530 if (!gotname)
Simon Kelley3be34542004-09-11 19:12:13 +0100531 strcpy(daemon->namebuff, "query");
Simon Kelleyde379512004-06-22 20:23:33 +0100532 if (start->addr.sa.sa_family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +0100533 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +0000534 (union all_addr *)&start->addr.in.sin_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100535 else
Simon Kelley3be34542004-09-11 19:12:13 +0100536 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +0000537 (union all_addr *)&start->addr.in6.sin6_addr, NULL);
Simon Kelley824af852008-02-12 20:43:05 +0000538 start->queries++;
Simon Kelleyde379512004-06-22 20:23:33 +0100539 forwarded = 1;
540 forward->sentto = start;
Simon Kelley0a852542005-03-23 20:28:59 +0000541 if (!forward->forwardall)
Simon Kelleyde379512004-06-22 20:23:33 +0100542 break;
Simon Kelley0a852542005-03-23 20:28:59 +0000543 forward->forwardall++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000544 }
545 }
546
Simon Kelleyde379512004-06-22 20:23:33 +0100547 if (!(start = start->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100548 start = daemon->servers;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000549
Simon Kelleyde379512004-06-22 20:23:33 +0100550 if (start == firstsentto)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000551 break;
552 }
553
Simon Kelleyde379512004-06-22 20:23:33 +0100554 if (forwarded)
Simon Kelley824af852008-02-12 20:43:05 +0000555 return 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100556
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000557 /* could not send on, prepare to return */
558 header->id = htons(forward->orig_id);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100559 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000560 }
561
562 /* could not send on, return empty answer or address if known for whole domain */
Simon Kelleyb8187c82005-11-26 21:46:27 +0000563 if (udpfd != -1)
564 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000565 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
Simon Kelley1682d152018-08-03 20:38:18 +0100566 if (oph)
567 plen = add_pseudoheader(header, plen, ((unsigned char *) header) + PACKETSZ, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
Simon Kelley54dd3932012-06-20 11:23:38 +0100568 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 +0000569 }
570
Simon Kelley824af852008-02-12 20:43:05 +0000571 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000572}
573
Simon Kelleyed4c0762013-10-08 20:46:34 +0100574static 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 +0100575 int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
576 int check_subnet, union mysockaddr *query_source)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100577{
Simon Kelley36717ee2004-09-20 19:20:58 +0100578 unsigned char *pheader, *sizep;
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000579 char **sets = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +0000580 int munged = 0, is_sign;
Simon Kelley07ed5852018-05-04 21:52:22 +0100581 unsigned int rcode = RCODE(header);
Simon Kelleycdeda282006-03-16 20:16:06 +0000582 size_t plen;
Simon Kelleya6004d72017-10-25 17:48:19 +0100583
Simon Kelley83349b82014-02-10 21:02:01 +0000584 (void)ad_reqd;
Simon Kelley982faf42015-04-03 21:42:30 +0100585 (void)do_bit;
586 (void)bogusanswer;
Simon Kelley83349b82014-02-10 21:02:01 +0000587
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000588#ifdef HAVE_IPSET
Simon Kelley82a14af2014-04-13 20:48:57 +0100589 if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000590 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100591 /* Similar algorithm to search_servers. */
592 struct ipsets *ipset_pos;
593 unsigned int namelen = strlen(daemon->namebuff);
594 unsigned int matchlen = 0;
595 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
Simon Kelley6c0cb852014-01-17 14:40:46 +0000596 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100597 unsigned int domainlen = strlen(ipset_pos->domain);
598 char *matchstart = daemon->namebuff + namelen - domainlen;
599 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
600 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
601 domainlen >= matchlen)
602 {
603 matchlen = domainlen;
604 sets = ipset_pos->sets;
605 }
Simon Kelley6c0cb852014-01-17 14:40:46 +0000606 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000607 }
608#endif
609
Simon Kelley5bb88f02015-12-21 16:23:47 +0000610 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100611 {
Simon Kelley07ed5852018-05-04 21:52:22 +0100612 /* Get extended RCODE. */
613 rcode |= sizep[2] << 4;
614
Simon Kelleyed4c0762013-10-08 20:46:34 +0100615 if (check_subnet && !check_source(header, plen, pheader, query_source))
616 {
617 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
618 return 0;
619 }
Simon Kelley613ad152014-02-25 23:02:28 +0000620
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000621 if (!is_sign)
Simon Kelley613ad152014-02-25 23:02:28 +0000622 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000623 if (added_pheader)
624 {
625 /* client didn't send EDNS0, we added one, strip it off before returning answer. */
626 n = rrfilter(header, n, 0);
627 pheader = NULL;
628 }
629 else
630 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000631 unsigned short udpsz;
632
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000633 /* If upstream is advertising a larger UDP packet size
634 than we allow, trim it so that we don't get overlarge
635 requests for the client. We can't do this for signed packets. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000636 GETSHORT(udpsz, sizep);
637 if (udpsz > daemon->edns_pktsz)
Simon Kelley33702ab2015-12-28 23:17:15 +0000638 {
639 sizep -= 2;
640 PUTSHORT(daemon->edns_pktsz, sizep);
641 }
642
643#ifdef HAVE_DNSSEC
644 /* If the client didn't set the do bit, but we did, reset it. */
645 if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
646 {
647 unsigned short flags;
648 sizep += 2; /* skip RCODE */
649 GETSHORT(flags, sizep);
650 flags &= ~0x8000;
651 sizep -= 2;
652 PUTSHORT(flags, sizep);
653 }
654#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000655 }
Simon Kelley613ad152014-02-25 23:02:28 +0000656 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100657 }
Simon Kelley83349b82014-02-10 21:02:01 +0000658
Simon Kelley28866e92011-02-14 20:19:14 +0000659 /* RFC 4035 sect 4.6 para 3 */
Giovanni Bajo237724c2012-04-05 02:46:52 +0200660 if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
Simon Kelley795501b2014-01-08 18:11:55 +0000661 header->hb4 &= ~HB4_AD;
Simon Kelley3a237152013-12-12 12:15:50 +0000662
Simon Kelley07ed5852018-05-04 21:52:22 +0100663 if (OPCODE(header) != QUERY)
Simon Kelley8938ae02014-05-01 17:46:25 +0100664 return resize_packet(header, n, pheader, plen);
Simon Kelley07ed5852018-05-04 21:52:22 +0100665
666 if (rcode != NOERROR && rcode != NXDOMAIN)
667 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000668 union all_addr a;
669 a.log.rcode = rcode;
Simon Kelley07ed5852018-05-04 21:52:22 +0100670 log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
671
672 return resize_packet(header, n, pheader, plen);
673 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100674
Simon Kelley0a852542005-03-23 20:28:59 +0000675 /* Complain loudly if the upstream server is non-recursive. */
Simon Kelley07ed5852018-05-04 21:52:22 +0100676 if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
Simon Kelley0a852542005-03-23 20:28:59 +0000677 server && !(server->flags & SERV_WARNED_RECURSIVE))
678 {
Petr Mensik51cdd1a2019-07-04 20:28:08 +0200679 (void)prettyprint_addr(&server->addr, daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100680 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
Simon Kelley28866e92011-02-14 20:19:14 +0000681 if (!option_bool(OPT_LOG))
Simon Kelley0a852542005-03-23 20:28:59 +0000682 server->flags |= SERV_WARNED_RECURSIVE;
683 }
Giovanni Bajoe292e932012-04-22 14:32:02 +0200684
Simon Kelley07ed5852018-05-04 21:52:22 +0100685 if (daemon->bogus_addr && rcode != NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100686 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100687 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100688 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000689 SET_RCODE(header, NXDOMAIN);
690 header->hb3 &= ~HB3_AA;
Simon Kelley6938f342014-01-26 22:47:39 +0000691 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100692 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100693 else
Simon Kelley36717ee2004-09-20 19:20:58 +0100694 {
Simon Kelley6938f342014-01-26 22:47:39 +0000695 int doctored = 0;
696
Simon Kelley07ed5852018-05-04 21:52:22 +0100697 if (rcode == NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100698 extract_request(header, n, daemon->namebuff, NULL) &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100699 check_for_local_domain(daemon->namebuff, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100700 {
Simon Kelley36717ee2004-09-20 19:20:58 +0100701 /* if we forwarded a query for a locally known name (because it was for
702 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
703 since we know that the domain exists, even if upstream doesn't */
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100704 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000705 header->hb3 |= HB3_AA;
706 SET_RCODE(header, NOERROR);
Simon Kelley6938f342014-01-26 22:47:39 +0000707 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100708 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000709
Simon Kelley373e9172017-12-01 22:40:56 +0000710 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 +0000711 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100712 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
Simon Kelley824af852008-02-12 20:43:05 +0000713 munged = 1;
Simon Kelley6938f342014-01-26 22:47:39 +0000714 cache_secure = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000715 }
Simon Kelley6938f342014-01-26 22:47:39 +0000716
717 if (doctored)
718 cache_secure = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100719 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100720
Simon Kelleya25720a2014-01-14 23:13:55 +0000721#ifdef HAVE_DNSSEC
Simon Kelley33702ab2015-12-28 23:17:15 +0000722 if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
Simon Kelleya25720a2014-01-14 23:13:55 +0000723 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000724 /* Bogus reply, turn into SERVFAIL */
725 SET_RCODE(header, SERVFAIL);
726 munged = 1;
Simon Kelleya25720a2014-01-14 23:13:55 +0000727 }
Simon Kelley6938f342014-01-26 22:47:39 +0000728
729 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000730 {
731 header->hb4 &= ~HB4_AD;
732
733 if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
734 header->hb4 |= HB4_AD;
735
736 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
737 if (!do_bit)
738 n = rrfilter(header, n, 1);
739 }
Simon Kelleya25720a2014-01-14 23:13:55 +0000740#endif
741
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100742 /* do this after extract_addresses. Ensure NODATA reply and remove
743 nameserver info. */
744
745 if (munged)
746 {
747 header->ancount = htons(0);
748 header->nscount = htons(0);
749 header->arcount = htons(0);
Simon Kelley150162b2015-03-27 09:58:26 +0000750 header->hb3 &= ~HB3_TC;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100751 }
752
Simon Kelley36717ee2004-09-20 19:20:58 +0100753 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
754 sections of the packet. Find the new length here and put back pseudoheader
755 if it was removed. */
756 return resize_packet(header, n, pheader, plen);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100757}
758
Simon Kelley3be34542004-09-11 19:12:13 +0100759/* sets new last_server */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100760void reply_query(int fd, int family, time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000761{
762 /* packet from peer server, extract data for cache, and send to
763 original requester */
Simon Kelley572b41e2011-02-18 18:11:18 +0000764 struct dns_header *header;
Simon Kelleyde379512004-06-22 20:23:33 +0100765 union mysockaddr serveraddr;
Simon Kelley832af0b2007-01-21 20:01:28 +0000766 struct frec *forward;
Simon Kelleyde379512004-06-22 20:23:33 +0100767 socklen_t addrlen = sizeof(serveraddr);
Simon Kelley60b68062014-01-08 12:10:28 +0000768 ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
Simon Kelleycdeda282006-03-16 20:16:06 +0000769 size_t nn;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100770 struct server *server;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000771 void *hash;
772#ifndef HAVE_DNSSEC
773 unsigned int crc;
774#endif
775
Simon Kelleycdeda282006-03-16 20:16:06 +0000776 /* packet buffer overwritten */
777 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000778
Simon Kelleyde379512004-06-22 20:23:33 +0100779 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelleyee875042018-10-23 22:10:17 +0100780 if ((serveraddr.sa.sa_family = family) == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100781 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000782
Simon Kelley490f9072014-03-24 22:04:42 +0000783 header = (struct dns_header *)daemon->packet;
Simon Kelley6b173352018-05-08 18:32:14 +0100784
Simon Kelley490f9072014-03-24 22:04:42 +0000785 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
786 return;
787
Simon Kelley1a6bca82008-07-11 11:11:42 +0100788 /* spoof check: answer must come from known server, */
789 for (server = daemon->servers; server; server = server->next)
790 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
791 sockaddr_isequal(&server->addr, &serveraddr))
792 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000793
794 if (!server)
795 return;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000796
797 /* If sufficient time has elapsed, try and expand UDP buffer size again. */
798 if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
799 server->edns_pktsz = daemon->edns_pktsz;
800
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000801#ifdef HAVE_DNSSEC
802 hash = hash_questions(header, n, daemon->namebuff);
803#else
804 hash = &crc;
805 crc = questions_crc(header, n, daemon->namebuff);
806#endif
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100807
Simon Kelley490f9072014-03-24 22:04:42 +0000808 if (!(forward = lookup_frec(ntohs(header->id), hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100809 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000810
Simon Kelley6b173352018-05-08 18:32:14 +0100811#ifdef HAVE_DUMPFILE
812 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
813 (void *)header, n, &serveraddr, NULL);
814#endif
Simon Kelleya0088e82018-05-10 21:43:14 +0100815
Simon Kelley25cf5e32015-01-09 15:53:03 +0000816 /* log_query gets called indirectly all over the place, so
817 pass these in global variables - sorry. */
818 daemon->log_display_id = forward->log_id;
819 daemon->log_source_addr = &forward->source;
820
Glen Huang32fc6db2014-12-27 15:28:12 +0000821 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
822 check_for_ignored_address(header, n, daemon->ignore_addr))
823 return;
824
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000825 /* Note: if we send extra options in the EDNS0 header, we can't recreate
826 the query from the reply. */
Simon Kelley34e26e12018-05-10 20:54:57 +0100827 if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000828 forward->forwardall == 0 &&
829 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100830 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000831 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100832 unsigned char *pheader;
833 size_t plen;
834 int is_sign;
Simon Kelleyef3d1372017-12-05 22:37:29 +0000835
Simon Kelley1f60a182018-05-11 16:44:16 +0100836#ifdef HAVE_DNSSEC
Simon Kelleya0088e82018-05-10 21:43:14 +0100837 /* For DNSSEC originated queries, just retry the query to the same server. */
838 if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
839 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100840 struct server *start;
841
Simon Kelleya0088e82018-05-10 21:43:14 +0100842 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
843 plen = forward->stash_len;
844
845 forward->forwardall = 2; /* only retry once */
Simon Kelley1f60a182018-05-11 16:44:16 +0100846 start = forward->sentto;
847
848 /* for non-domain specific servers, see if we can find another to try. */
849 if ((forward->sentto->flags & SERV_TYPE) == 0)
850 while (1)
851 {
852 if (!(start = start->next))
853 start = daemon->servers;
854 if (start == forward->sentto)
855 break;
856
857 if ((start->flags & SERV_TYPE) == 0 &&
858 (start->flags & SERV_DO_DNSSEC))
859 break;
860 }
861
862
863 if (start->sfd)
864 fd = start->sfd->fd;
Simon Kelleya0088e82018-05-10 21:43:14 +0100865 else
866 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100867 if (start->addr.sa.sa_family == AF_INET6)
868 {
869 /* may have changed family */
870 if (!forward->rfd6)
871 forward->rfd6 = allocate_rfd(AF_INET6);
872 fd = forward->rfd6->fd;
873 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100874 else
Simon Kelley1f60a182018-05-11 16:44:16 +0100875 {
876 /* may have changed family */
877 if (!forward->rfd4)
878 forward->rfd4 = allocate_rfd(AF_INET);
879 fd = forward->rfd4->fd;
880 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100881 }
Simon Kelleye3002bf2019-10-11 23:30:08 +0100882
883#ifdef HAVE_DUMPFILE
884 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
885#endif
886
Simon Kelleya0088e82018-05-10 21:43:14 +0100887 while (retry_send(sendto(fd, (char *)header, plen, 0,
Simon Kelley1f60a182018-05-11 16:44:16 +0100888 &start->addr.sa,
889 sa_len(&start->addr))));
Simon Kelleya0088e82018-05-10 21:43:14 +0100890
Simon Kelleye27825b2018-05-11 17:20:47 +0100891 if (start->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000892 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (union all_addr *)&start->addr.in.sin_addr, "dnssec");
Simon Kelleye27825b2018-05-11 17:20:47 +0100893 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000894 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&start->addr.in6.sin6_addr, "dnssec");
Simon Kelleye27825b2018-05-11 17:20:47 +0100895
Simon Kelleya0088e82018-05-10 21:43:14 +0100896 return;
897 }
Simon Kelley1f60a182018-05-11 16:44:16 +0100898#endif
899
Simon Kelleyef3d1372017-12-05 22:37:29 +0000900 /* In strict order mode, there must be a server later in the chain
901 left to send to, otherwise without the forwardall mechanism,
902 code further on will cycle around the list forwever if they
903 all return REFUSED. Note that server is always non-NULL before
904 this executes. */
905 if (option_bool(OPT_ORDER))
906 for (server = forward->sentto->next; server; server = server->next)
907 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
908 break;
909
Simon Kelley1a6bca82008-07-11 11:11:42 +0100910 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000911 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelleyef3d1372017-12-05 22:37:29 +0000912 if (!is_sign && server)
Simon Kelley832af0b2007-01-21 20:01:28 +0000913 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100914 header->ancount = htons(0);
915 header->nscount = htons(0);
916 header->arcount = htons(0);
917 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
918 {
swiggerbd7bfa22015-06-01 20:54:59 +0100919 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000920 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000921 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000922 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000923 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000924 header->hb4 |= HB4_AD;
925 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000926 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000927 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 +0100928 return;
929 }
930 }
931 }
Simon Kelley3a237152013-12-12 12:15:50 +0000932
933 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100934 if ((forward->sentto->flags & SERV_TYPE) == 0)
935 {
Simon Kelley51967f92014-03-25 21:07:00 +0000936 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100937 server = NULL;
938 else
939 {
940 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000941
Simon Kelley1a6bca82008-07-11 11:11:42 +0100942 /* find good server by address if possible, otherwise assume the last one we sent to */
943 for (last_server = daemon->servers; last_server; last_server = last_server->next)
944 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
945 sockaddr_isequal(&last_server->addr, &serveraddr))
946 {
947 server = last_server;
948 break;
949 }
950 }
Simon Kelley28866e92011-02-14 20:19:14 +0000951 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100952 daemon->last_server = server;
953 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100954
955 /* We tried resending to this server with a smaller maximum size and got an answer.
Ville Skyttäfaaf3062018-01-14 17:32:52 +0000956 Make that permanent. To avoid reduxing the packet size for a single dropped packet,
Simon Kelley86fa1042015-05-10 13:50:59 +0100957 only do this when we get a truncated answer, or one larger than the safe size. */
Simon Kelley04db1482019-10-11 23:22:17 +0100958 if (forward->sentto->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
Simon Kelley86fa1042015-05-10 13:50:59 +0100959 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelley22dee512017-10-13 22:54:00 +0100960 {
Simon Kelley04db1482019-10-11 23:22:17 +0100961 forward->sentto->edns_pktsz = SAFE_PKTSZ;
962 forward->sentto->pktsz_reduced = now;
Petr Mensik51cdd1a2019-07-04 20:28:08 +0200963 (void)prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
Simon Kelleyebedcba2017-10-29 20:54:17 +0000964 my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
Simon Kelley22dee512017-10-13 22:54:00 +0100965 }
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000966
967
Simon Kelley1a6bca82008-07-11 11:11:42 +0100968 /* If the answer is an error, keep the forward record in place in case
969 we get a good reply from another server. Kill it when we've
970 had replies from all to avoid filling the forwarding table when
971 everything is broken */
Simon Kelley122392e2018-10-31 22:24:02 +0000972 if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100973 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100974 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleya6004d72017-10-25 17:48:19 +0100975
Simon Kelley3a237152013-12-12 12:15:50 +0000976 if (option_bool(OPT_NO_REBIND))
977 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100978
Simon Kelley3a237152013-12-12 12:15:50 +0000979 /* Don't cache replies where DNSSEC validation was turned off, either
980 the upstream server told us so, or the original query specified it. */
981 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
982 no_cache_dnssec = 1;
983
984#ifdef HAVE_DNSSEC
Simon Kelley04db1482019-10-11 23:22:17 +0100985 if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000986 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000987 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000988 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000989
990 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000991 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000992 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000993
994 /* Truncated answer can't be validated.
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100995 If this is an answer to a DNSSEC-generated query, we still
996 need to get the client to retry over TCP, so return
997 an answer with the TC bit set, even if the actual answer fits.
998 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000999 if (header->hb3 & HB3_TC)
1000 status = STAT_TRUNCATED;
1001
1002 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001003 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001004 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
1005 would invite infinite loops, since the answers to DNSKEY and DS queries
1006 will not be cached, so they'll be repeated. */
1007 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001008 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001009 if (forward->flags & FREC_DNSKEY_QUERY)
1010 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1011 else if (forward->flags & FREC_DS_QUERY)
1012 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001013 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001014 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
Simon Kelley203ce0a2019-10-12 21:41:20 +01001015 !option_bool(OPT_DNSSEC_IGN_NS) && (forward->sentto->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001016 NULL, NULL, NULL);
Simon Kelley6b173352018-05-08 18:32:14 +01001017#ifdef HAVE_DUMPFILE
1018 if (status == STAT_BOGUS)
1019 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
1020 header, (size_t)n, &serveraddr, NULL);
1021#endif
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001022 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001023
Simon Kelley9a31b682015-12-15 10:20:39 +00001024 /* Can't validate, as we're missing key data. Put this
1025 answer aside, whilst we get that. */
1026 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +00001027 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001028 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +00001029
Simon Kelley9a31b682015-12-15 10:20:39 +00001030 /* Free any saved query */
1031 if (forward->stash)
1032 blockdata_free(forward->stash);
1033
1034 /* Now save reply pending receipt of key data */
1035 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +00001036 return;
Simon Kelley9a31b682015-12-15 10:20:39 +00001037 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001038
Simon Kelley9a31b682015-12-15 10:20:39 +00001039 /* Find the original query that started it all.... */
1040 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001041
Simon Kelley8caf3d72020-04-04 17:00:32 +01001042 /* Make sure we don't expire and free the orig frec during the
1043 allocation of a new one. */
1044 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, orig)))
Simon Kelley9a31b682015-12-15 10:20:39 +00001045 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001046 else
Simon Kelley3a237152013-12-12 12:15:50 +00001047 {
Simon Kelleye1791f32018-10-06 23:23:23 +01001048 int querytype, fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +00001049 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +00001050 char *domain;
1051
Simon Kelley9a31b682015-12-15 10:20:39 +00001052 *new = *forward; /* copy everything, then overwrite */
1053 new->next = next;
1054 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +00001055
1056 /* Find server to forward to. This will normally be the
1057 same as for the original query, but may be another if
1058 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001059 if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
Simon Kelley92be34a2016-01-16 18:39:54 +00001060 {
Simon Kelley203ce0a2019-10-12 21:41:20 +01001061 struct server *start, *new_server = NULL;
1062 start = server = forward->sentto;
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001063
1064 while (1)
1065 {
1066 if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
Simon Kelley1f60a182018-05-11 16:44:16 +01001067 ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001068 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1069 {
1070 new_server = start;
1071 if (server == start)
1072 {
1073 new_server = NULL;
1074 break;
1075 }
1076 }
1077
1078 if (!(start = start->next))
1079 start = daemon->servers;
1080 if (start == server)
1081 break;
1082 }
1083
1084 if (new_server)
1085 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +00001086 }
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001087
Simon Kelley9a31b682015-12-15 10:20:39 +00001088 new->sentto = server;
1089 new->rfd4 = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001090 new->rfd6 = NULL;
Simon Kelleya0088e82018-05-10 21:43:14 +01001091 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
1092 new->forwardall = 0;
Simon Kelley9a31b682015-12-15 10:20:39 +00001093
1094 new->dependent = forward; /* to find query awaiting new one. */
1095 forward->blocking_query = new; /* for garbage cleaning */
1096 /* validate routines leave name of required record in daemon->keyname */
1097 if (status == STAT_NEED_KEY)
Simon Kelley7fa836e2014-02-10 20:11:24 +00001098 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001099 new->flags |= FREC_DNSKEY_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001100 querytype = T_DNSKEY;
Simon Kelleyf1668d22014-01-08 16:53:27 +00001101 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001102 else
1103 {
1104 new->flags |= FREC_DS_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001105 querytype = T_DS;
Simon Kelley9a31b682015-12-15 10:20:39 +00001106 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001107
1108 nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
1109 daemon->keyname, forward->class, querytype, server->edns_pktsz);
1110
1111 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001112 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (union all_addr *)&(server->addr.in.sin_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001113 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001114 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001115 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001116 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001117
Simon Kelley9a31b682015-12-15 10:20:39 +00001118 if ((hash = hash_questions(header, nn, daemon->namebuff)))
1119 memcpy(new->hash, hash, HASH_SIZE);
1120 new->new_id = get_id();
1121 header->id = htons(new->new_id);
1122 /* Save query for retransmission */
1123 new->stash = blockdata_alloc((char *)header, nn);
1124 new->stash_len = nn;
1125
1126 /* Don't resend this. */
1127 daemon->srv_save = NULL;
1128
1129 if (server->sfd)
1130 fd = server->sfd->fd;
1131 else
1132 {
1133 fd = -1;
Simon Kelley9a31b682015-12-15 10:20:39 +00001134 if (server->addr.sa.sa_family == AF_INET6)
1135 {
1136 if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1137 fd = new->rfd6->fd;
1138 }
1139 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001140 {
1141 if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1142 fd = new->rfd4->fd;
1143 }
1144 }
1145
1146 if (fd != -1)
1147 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001148#ifdef HAVE_CONNTRACK
1149 /* Copy connection mark of incoming query to outgoing connection. */
1150 if (option_bool(OPT_CONNTRACK))
1151 {
1152 unsigned int mark;
1153 if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
1154 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1155 }
1156#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001157
1158#ifdef HAVE_DUMPFILE
1159 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
1160#endif
1161
Simon Kelley9a31b682015-12-15 10:20:39 +00001162 while (retry_send(sendto(fd, (char *)header, nn, 0,
1163 &server->addr.sa,
1164 sa_len(&server->addr))));
1165 server->queries++;
1166 }
1167 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001168 return;
Simon Kelley3a237152013-12-12 12:15:50 +00001169 }
Simon Kelley3a237152013-12-12 12:15:50 +00001170
Simon Kelley9a31b682015-12-15 10:20:39 +00001171 /* Validated original answer, all done. */
1172 if (!forward->dependent)
1173 break;
1174
Josh Soref730c6742017-02-06 16:14:04 +00001175 /* validated subsidiary query, (and cached result)
Simon Kelley9a31b682015-12-15 10:20:39 +00001176 pop that and return to the previous query we were working on. */
Simon Kelley0744ca62014-01-25 16:40:15 +00001177 struct frec *prev = forward->dependent;
1178 free_frec(forward);
1179 forward = prev;
1180 forward->blocking_query = NULL; /* already gone */
1181 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1182 n = forward->stash_len;
Simon Kelley3a237152013-12-12 12:15:50 +00001183 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001184
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001185
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001186 no_cache_dnssec = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001187
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001188 if (status == STAT_TRUNCATED)
Simon Kelley0744ca62014-01-25 16:40:15 +00001189 header->hb3 |= HB3_TC;
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001190 else
Simon Kelley7fa836e2014-02-10 20:11:24 +00001191 {
Simon Kelley554b5802015-04-17 22:50:20 +01001192 char *result, *domain = "result";
Simon Kelley7fa836e2014-02-10 20:11:24 +00001193
Simon Kelley9a31b682015-12-15 10:20:39 +00001194 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001195 {
1196 result = "ABANDONED";
1197 status = STAT_BOGUS;
1198 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001199 else
1200 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1201
Simon Kelley554b5802015-04-17 22:50:20 +01001202 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1203 domain = daemon->namebuff;
Simon Kelley9a31b682015-12-15 10:20:39 +00001204
Simon Kelley07ed5852018-05-04 21:52:22 +01001205 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001206 }
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001207
Simon Kelley3a237152013-12-12 12:15:50 +00001208 if (status == STAT_SECURE)
1209 cache_secure = 1;
Simon Kelley3a237152013-12-12 12:15:50 +00001210 else if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001211 {
1212 no_cache_dnssec = 1;
1213 bogusanswer = 1;
1214 }
Simon Kelley3a237152013-12-12 12:15:50 +00001215 }
Simon Kelley04db1482019-10-11 23:22:17 +01001216
Simon Kelley6b173352018-05-08 18:32:14 +01001217#endif
1218
Simon Kelley83349b82014-02-10 21:02:01 +00001219 /* restore CD bit to the value in the query */
1220 if (forward->flags & FREC_CHECKING_DISABLED)
1221 header->hb4 |= HB4_CD;
1222 else
1223 header->hb4 &= ~HB4_CD;
Simon Kelley3a237152013-12-12 12:15:50 +00001224
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001225 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 +00001226 forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1227 forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
Simon Kelley832af0b2007-01-21 20:01:28 +00001228 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001229 header->id = htons(forward->orig_id);
Simon Kelley572b41e2011-02-18 18:11:18 +00001230 header->hb4 |= HB4_RA; /* recursion if available */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001231#ifdef HAVE_DNSSEC
1232 /* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
Simon Kelley6fd5d792017-10-13 22:26:40 +01001233 greater than the no-EDNS0-implied 512 to have space for the RRSIGS. If, having stripped them and the EDNS0
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001234 header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1235 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1236 {
1237 header->ancount = htons(0);
1238 header->nscount = htons(0);
1239 header->arcount = htons(0);
1240 header->hb3 |= HB3_TC;
1241 nn = resize_packet(header, nn, NULL, 0);
1242 }
1243#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001244
1245#ifdef HAVE_DUMPFILE
1246 dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
1247#endif
1248
Simon Kelley54dd3932012-06-20 11:23:38 +01001249 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
Simon Kelley50303b12012-04-04 22:13:17 +01001250 &forward->source, &forward->dest, forward->iface);
Simon Kelley832af0b2007-01-21 20:01:28 +00001251 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001252 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001253 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001254}
Simon Kelley44a2a312004-03-10 20:04:35 +00001255
Simon Kelley1a6bca82008-07-11 11:11:42 +01001256
Simon Kelley5aabfc72007-08-29 11:24:47 +01001257void receive_query(struct listener *listen, time_t now)
Simon Kelley44a2a312004-03-10 20:04:35 +00001258{
Simon Kelley572b41e2011-02-18 18:11:18 +00001259 struct dns_header *header = (struct dns_header *)daemon->packet;
Simon Kelley44a2a312004-03-10 20:04:35 +00001260 union mysockaddr source_addr;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001261 unsigned char *pheader;
1262 unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
Simon Kelleycc921df2019-01-02 22:48:59 +00001263 union all_addr dst_addr;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001264 struct in_addr netmask, dst_addr_4;
Simon Kelleycdeda282006-03-16 20:16:06 +00001265 size_t m;
1266 ssize_t n;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001267 int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001268#ifdef HAVE_AUTH
1269 int local_auth = 0;
1270#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001271 struct iovec iov[1];
1272 struct msghdr msg;
1273 struct cmsghdr *cmptr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001274 union {
1275 struct cmsghdr align; /* this ensures alignment */
Simon Kelley44a2a312004-03-10 20:04:35 +00001276 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001277#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +00001278 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
Simon Kelley824af852008-02-12 20:43:05 +00001279#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1280 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1281 CMSG_SPACE(sizeof(unsigned int))];
Simon Kelley44a2a312004-03-10 20:04:35 +00001282#elif defined(IP_RECVDSTADDR)
1283 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1284 CMSG_SPACE(sizeof(struct sockaddr_dl))];
1285#endif
1286 } control_u;
Simon Kelley2329bef2013-12-03 13:41:16 +00001287 /* Can always get recvd interface for IPv6 */
1288 int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
Simon Kelley2329bef2013-12-03 13:41:16 +00001289
Simon Kelleycdeda282006-03-16 20:16:06 +00001290 /* packet buffer overwritten */
1291 daemon->srv_save = NULL;
1292
Simon Kelleycc921df2019-01-02 22:48:59 +00001293 dst_addr_4.s_addr = dst_addr.addr4.s_addr = 0;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001294 netmask.s_addr = 0;
1295
Simon Kelley7e5664b2013-04-05 16:57:41 +01001296 if (option_bool(OPT_NOWILD) && listen->iface)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001297 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001298 auth_dns = listen->iface->dns_auth;
1299
1300 if (listen->family == AF_INET)
1301 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001302 dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001303 netmask = listen->iface->netmask;
1304 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001305 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001306
Simon Kelley3be34542004-09-11 19:12:13 +01001307 iov[0].iov_base = daemon->packet;
1308 iov[0].iov_len = daemon->edns_pktsz;
Simon Kelley44a2a312004-03-10 20:04:35 +00001309
1310 msg.msg_control = control_u.control;
1311 msg.msg_controllen = sizeof(control_u);
1312 msg.msg_flags = 0;
1313 msg.msg_name = &source_addr;
1314 msg.msg_namelen = sizeof(source_addr);
1315 msg.msg_iov = iov;
1316 msg.msg_iovlen = 1;
1317
Simon Kelleyde379512004-06-22 20:23:33 +01001318 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
Simon Kelley3be34542004-09-11 19:12:13 +01001319 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001320
Simon Kelley572b41e2011-02-18 18:11:18 +00001321 if (n < (int)sizeof(struct dns_header) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001322 (msg.msg_flags & MSG_TRUNC) ||
Simon Kelley572b41e2011-02-18 18:11:18 +00001323 (header->hb3 & HB3_QR))
Simon Kelley3be34542004-09-11 19:12:13 +01001324 return;
Simon Kelley63437ff2017-09-06 22:34:21 +01001325
1326 /* Clear buffer beyond request to avoid risk of
1327 information disclosure. */
1328 memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
Simon Kelley44a2a312004-03-10 20:04:35 +00001329
Simon Kelley26128d22004-11-14 16:43:54 +00001330 source_addr.sa.sa_family = listen->family;
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001331
1332 if (listen->family == AF_INET)
1333 {
1334 /* Source-port == 0 is an error, we can't send back to that.
1335 http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1336 if (source_addr.in.sin_port == 0)
1337 return;
1338 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001339 else
1340 {
1341 /* Source-port == 0 is an error, we can't send back to that. */
1342 if (source_addr.in6.sin6_port == 0)
1343 return;
1344 source_addr.in6.sin6_flowinfo = 0;
1345 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001346
Simon Kelleyc8a80482014-03-05 14:29:54 +00001347 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1348 if (option_bool(OPT_LOCAL_SERVICE))
1349 {
1350 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001351
Simon Kelleyc8a80482014-03-05 14:29:54 +00001352 if (listen->family == AF_INET6)
1353 {
1354 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1355 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001356 is_same_net6(&addr->addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001357 break;
1358 }
1359 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001360 {
1361 struct in_addr netmask;
1362 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1363 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001364 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001365 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001366 is_same_net(addr->addr.addr4, source_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001367 break;
1368 }
1369 }
1370 if (!addr)
1371 {
Simon Kelley0c8584e2014-03-12 20:12:56 +00001372 static int warned = 0;
1373 if (!warned)
1374 {
1375 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1376 warned = 1;
1377 }
Simon Kelleyc8a80482014-03-05 14:29:54 +00001378 return;
1379 }
1380 }
1381
Simon Kelley2329bef2013-12-03 13:41:16 +00001382 if (check_dst)
Simon Kelley44a2a312004-03-10 20:04:35 +00001383 {
Simon Kelley8a911cc2004-03-16 18:35:52 +00001384 struct ifreq ifr;
1385
Simon Kelley26128d22004-11-14 16:43:54 +00001386 if (msg.msg_controllen < sizeof(struct cmsghdr))
1387 return;
1388
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001389#if defined(HAVE_LINUX_NETWORK)
Simon Kelley26128d22004-11-14 16:43:54 +00001390 if (listen->family == AF_INET)
1391 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001392 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
Simon Kelley26128d22004-11-14 16:43:54 +00001393 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001394 union {
1395 unsigned char *c;
1396 struct in_pktinfo *p;
1397 } p;
1398 p.c = CMSG_DATA(cmptr);
Simon Kelleycc921df2019-01-02 22:48:59 +00001399 dst_addr_4 = dst_addr.addr4 = p.p->ipi_spec_dst;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001400 if_index = p.p->ipi_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001401 }
1402#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1403 if (listen->family == AF_INET)
1404 {
1405 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001406 {
1407 union {
1408 unsigned char *c;
1409 unsigned int *i;
1410 struct in_addr *a;
1411#ifndef HAVE_SOLARIS_NETWORK
1412 struct sockaddr_dl *s;
Simon Kelley824af852008-02-12 20:43:05 +00001413#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001414 } p;
1415 p.c = CMSG_DATA(cmptr);
1416 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
Simon Kelleycc921df2019-01-02 22:48:59 +00001417 dst_addr_4 = dst_addr.addr4 = *(p.a);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001418 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1419#ifdef HAVE_SOLARIS_NETWORK
1420 if_index = *(p.i);
1421#else
1422 if_index = p.s->sdl_index;
1423#endif
1424 }
Simon Kelley26128d22004-11-14 16:43:54 +00001425 }
1426#endif
1427
Simon Kelley26128d22004-11-14 16:43:54 +00001428 if (listen->family == AF_INET6)
1429 {
1430 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001431 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
Simon Kelley26128d22004-11-14 16:43:54 +00001432 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001433 union {
1434 unsigned char *c;
1435 struct in6_pktinfo *p;
1436 } p;
1437 p.c = CMSG_DATA(cmptr);
1438
Simon Kelleycc921df2019-01-02 22:48:59 +00001439 dst_addr.addr6 = p.p->ipi6_addr;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001440 if_index = p.p->ipi6_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001441 }
1442 }
Simon Kelley26128d22004-11-14 16:43:54 +00001443
1444 /* enforce available interface configuration */
1445
Simon Kelleye25db1f2013-01-29 22:10:26 +00001446 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
Simon Kelley832af0b2007-01-21 20:01:28 +00001447 return;
1448
Simon Kelleye25db1f2013-01-29 22:10:26 +00001449 if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
1450 {
1451 if (!option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001452 enumerate_interfaces(0);
Simon Kelley3f2873d2013-05-14 11:28:47 +01001453 if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
1454 !label_exception(if_index, listen->family, &dst_addr))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001455 return;
1456 }
1457
Simon Kelley552af8b2012-02-29 20:10:31 +00001458 if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
1459 {
1460 struct irec *iface;
1461
Josh Soref730c6742017-02-06 16:14:04 +00001462 /* get the netmask of the interface which has the address we were sent to.
klemens43517fc2017-02-19 15:53:37 +00001463 This is no necessarily the interface we arrived on. */
Simon Kelley552af8b2012-02-29 20:10:31 +00001464
1465 for (iface = daemon->interfaces; iface; iface = iface->next)
1466 if (iface->addr.sa.sa_family == AF_INET &&
1467 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1468 break;
1469
1470 /* interface may be new */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001471 if (!iface && !option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001472 enumerate_interfaces(0);
Simon Kelley552af8b2012-02-29 20:10:31 +00001473
1474 for (iface = daemon->interfaces; iface; iface = iface->next)
1475 if (iface->addr.sa.sa_family == AF_INET &&
1476 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1477 break;
1478
1479 /* If we failed, abandon localisation */
1480 if (iface)
1481 netmask = iface->netmask;
1482 else
1483 dst_addr_4.s_addr = 0;
1484 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001485 }
Simon Kelley25cf5e32015-01-09 15:53:03 +00001486
1487 /* log_query gets called indirectly all over the place, so
1488 pass these in global variables - sorry. */
1489 daemon->log_display_id = ++daemon->log_id;
1490 daemon->log_source_addr = &source_addr;
Simon Kelley6b173352018-05-08 18:32:14 +01001491
1492#ifdef HAVE_DUMPFILE
1493 dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
1494#endif
1495
Simon Kelleycdeda282006-03-16 20:16:06 +00001496 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
Simon Kelley44a2a312004-03-10 20:04:35 +00001497 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001498#ifdef HAVE_AUTH
1499 struct auth_zone *zone;
1500#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001501 char *types = querystr(auth_dns ? "auth" : "query", type);
1502
Simon Kelley44a2a312004-03-10 20:04:35 +00001503 if (listen->family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +01001504 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001505 (union all_addr *)&source_addr.in.sin_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001506 else
Simon Kelley3be34542004-09-11 19:12:13 +01001507 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001508 (union all_addr *)&source_addr.in6.sin6_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001509
Simon Kelley4820dce2012-12-18 18:30:30 +00001510#ifdef HAVE_AUTH
Simon Kelleyb485ed92013-10-18 22:00:39 +01001511 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001512 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001513 for (zone = daemon->auth_zones; zone; zone = zone->next)
1514 if (in_zone(zone, daemon->namebuff, NULL))
1515 {
1516 auth_dns = 1;
1517 local_auth = 1;
1518 break;
1519 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001520#endif
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001521
1522#ifdef HAVE_LOOP
1523 /* Check for forwarding loop */
1524 if (detect_loop(daemon->namebuff, type))
1525 return;
1526#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001527 }
1528
Simon Kelley5bb88f02015-12-21 16:23:47 +00001529 if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001530 {
1531 unsigned short flags;
1532
1533 have_pseudoheader = 1;
1534 GETSHORT(udp_size, pheader);
1535 pheader += 2; /* ext_rcode */
1536 GETSHORT(flags, pheader);
1537
1538 if (flags & 0x8000)
1539 do_bit = 1;/* do bit */
1540
1541 /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1542 (bounded by the maximum configured). If no EDNS0, then it
1543 defaults to 512 */
1544 if (udp_size > daemon->edns_pktsz)
1545 udp_size = daemon->edns_pktsz;
Simon Kelleya3303e12017-09-07 20:45:00 +01001546 else if (udp_size < PACKETSZ)
1547 udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001548 }
1549
Simon Kelleyb485ed92013-10-18 22:00:39 +01001550#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001551 if (auth_dns)
Simon Kelley824af852008-02-12 20:43:05 +00001552 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001553 m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1554 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001555 if (m >= 1)
Simon Kelleyb485ed92013-10-18 22:00:39 +01001556 {
1557 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1558 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001559 daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
Simon Kelleyb485ed92013-10-18 22:00:39 +01001560 }
Simon Kelley824af852008-02-12 20:43:05 +00001561 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001562 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001563#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001564 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001565 int ad_reqd = do_bit;
1566 /* RFC 6840 5.7 */
1567 if (header->hb4 & HB4_AD)
1568 ad_reqd = 1;
1569
1570 m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1571 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001572
1573 if (m >= 1)
1574 {
1575 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1576 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001577 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001578 }
1579 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
Simon Kelley613ad152014-02-25 23:02:28 +00001580 header, (size_t)n, now, NULL, ad_reqd, do_bit))
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001581 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001582 else
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001583 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001584 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001585}
1586
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001587#ifdef HAVE_DNSSEC
Josh Soref730c6742017-02-06 16:14:04 +00001588/* Recurse up the key hierarchy */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001589static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001590 int class, char *name, char *keyname, struct server *server,
1591 int have_mark, unsigned int mark, int *keycount)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001592{
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001593 int new_status;
Simon Kelley9a31b682015-12-15 10:20:39 +00001594 unsigned char *packet = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001595 unsigned char *payload = NULL;
1596 struct dns_header *new_header = NULL;
1597 u16 *length = NULL;
Simon Kelley361dfe52017-02-10 21:12:30 +00001598
Simon Kelley9a31b682015-12-15 10:20:39 +00001599 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001600 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001601 int type = SERV_DO_DNSSEC;
1602 char *domain;
1603 size_t m;
1604 unsigned char c1, c2;
Simon Kelley361dfe52017-02-10 21:12:30 +00001605 struct server *firstsendto = NULL;
1606
Simon Kelley9a31b682015-12-15 10:20:39 +00001607 /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1608 if (--(*keycount) == 0)
1609 new_status = STAT_ABANDONED;
1610 else if (status == STAT_NEED_KEY)
1611 new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1612 else if (status == STAT_NEED_DS)
1613 new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1614 else
James Bottomleye33b4872017-03-17 21:44:10 +00001615 new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
Simon Kelleya6918532018-04-15 16:20:52 +01001616 !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001617 NULL, NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001618
Simon Kelley9a31b682015-12-15 10:20:39 +00001619 if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1620 break;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001621
Simon Kelley9a31b682015-12-15 10:20:39 +00001622 /* Can't validate because we need a key/DS whose name now in keyname.
1623 Make query for same, and recurse to validate */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001624 if (!packet)
Simon Kelley9a31b682015-12-15 10:20:39 +00001625 {
1626 packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1627 payload = &packet[2];
1628 new_header = (struct dns_header *)payload;
1629 length = (u16 *)packet;
1630 }
1631
1632 if (!packet)
1633 {
1634 new_status = STAT_ABANDONED;
1635 break;
1636 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001637
Simon Kelley33702ab2015-12-28 23:17:15 +00001638 m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
Simon Kelleye1791f32018-10-06 23:23:23 +01001639 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, server->edns_pktsz);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001640
Simon Kelley7fa836e2014-02-10 20:11:24 +00001641 *length = htons(m);
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001642
1643 /* Find server to forward to. This will normally be the
1644 same as for the original query, but may be another if
1645 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001646 if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001647 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001648 new_status = STAT_ABANDONED;
1649 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001650 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001651
Simon Kelley361dfe52017-02-10 21:12:30 +00001652 while (1)
1653 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001654 int data_sent = 0;
1655
Simon Kelley361dfe52017-02-10 21:12:30 +00001656 if (!firstsendto)
1657 firstsendto = server;
1658 else
1659 {
1660 if (!(server = server->next))
1661 server = daemon->servers;
1662 if (server == firstsendto)
1663 {
1664 /* can't find server to accept our query. */
1665 new_status = STAT_ABANDONED;
1666 break;
1667 }
1668 }
1669
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001670 if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001671 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1672 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1673 continue;
Simon Kelleye1791f32018-10-06 23:23:23 +01001674
1675 retry:
1676 /* may need to make new connection. */
1677 if (server->tcpfd == -1)
1678 {
1679 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1680 continue; /* No good, next server */
1681
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001682#ifdef HAVE_CONNTRACK
Simon Kelleye1791f32018-10-06 23:23:23 +01001683 /* Copy connection mark of incoming query to outgoing connection. */
1684 if (have_mark)
1685 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001686#endif
Simon Kelleye1791f32018-10-06 23:23:23 +01001687
Simon Kelley608aa9f2019-03-10 22:44:15 +00001688 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1))
1689 {
1690 close(server->tcpfd);
1691 server->tcpfd = -1;
1692 continue; /* No good, next server */
1693 }
1694
1695#ifdef MSG_FASTOPEN
1696 while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
1697 MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
1698
1699 if (errno == 0)
1700 data_sent = 1;
1701#endif
1702
1703 if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
Simon Kelleye1791f32018-10-06 23:23:23 +01001704 {
1705 close(server->tcpfd);
1706 server->tcpfd = -1;
1707 continue; /* No good, next server */
1708 }
1709
1710 server->flags &= ~SERV_GOT_TCP;
1711 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001712
Simon Kelley608aa9f2019-03-10 22:44:15 +00001713 if ((!data_sent && !read_write(server->tcpfd, packet, m + sizeof(u16), 0)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001714 !read_write(server->tcpfd, &c1, 1, 1) ||
1715 !read_write(server->tcpfd, &c2, 1, 1) ||
1716 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1717 {
1718 close(server->tcpfd);
1719 server->tcpfd = -1;
1720 /* We get data then EOF, reopen connection to same server,
1721 else try next. This avoids DoS from a server which accepts
1722 connections and then closes them. */
1723 if (server->flags & SERV_GOT_TCP)
1724 goto retry;
1725 else
1726 continue;
1727 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001728
1729
1730 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001731 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (union all_addr *)&(server->addr.in.sin_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001732 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelleye1791f32018-10-06 23:23:23 +01001733 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001734 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001735 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelley361dfe52017-02-10 21:12:30 +00001736
1737 server->flags |= SERV_GOT_TCP;
1738
1739 m = (c1 << 8) | c2;
1740 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1741 break;
1742 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001743
1744 if (new_status != STAT_OK)
1745 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001746 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001747
Simon Kelley9a31b682015-12-15 10:20:39 +00001748 if (packet)
1749 free(packet);
1750
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001751 return new_status;
1752}
1753#endif
1754
1755
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001756/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001757 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001758 about resources for debug mode, when the fork is suppressed: that's
1759 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001760unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001761 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001762{
Simon Kelley28866e92011-02-14 20:19:14 +00001763 size_t size = 0;
1764 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001765#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001766 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001767#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001768 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001769 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001770 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001771 unsigned short qtype;
1772 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001773 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001774 /* Max TCP packet + slop + size */
1775 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1776 unsigned char *payload = &packet[2];
1777 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1778 struct dns_header *header = (struct dns_header *)payload;
1779 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001780 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001781 struct in_addr dst_addr_4;
1782 union mysockaddr peer_addr;
1783 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001784 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001785 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001786 unsigned int mark = 0;
1787 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001788
Simon Kelleyd05dd582016-01-19 21:23:30 +00001789 (void)mark;
1790 (void)have_mark;
1791
Simon Kelley7de060b2011-08-26 17:24:52 +01001792 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1793 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001794
1795#ifdef HAVE_CONNTRACK
1796 /* Get connection mark of incoming query to set on outgoing connections. */
1797 if (option_bool(OPT_CONNTRACK))
1798 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001799 union all_addr local;
Simon Kelleyee875042018-10-23 22:10:17 +01001800
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001801 if (local_addr->sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001802 local.addr6 = local_addr->in6.sin6_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001803 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001804 local.addr4 = local_addr->in.sin_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001805
1806 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1807 }
1808#endif
1809
Simon Kelleyc8a80482014-03-05 14:29:54 +00001810 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1811 if (option_bool(OPT_LOCAL_SERVICE))
1812 {
1813 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001814
Simon Kelleyc8a80482014-03-05 14:29:54 +00001815 if (peer_addr.sa.sa_family == AF_INET6)
1816 {
1817 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1818 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001819 is_same_net6(&addr->addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001820 break;
1821 }
1822 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001823 {
1824 struct in_addr netmask;
1825 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1826 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001827 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001828 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001829 is_same_net(addr->addr.addr4, peer_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001830 break;
1831 }
1832 }
1833 if (!addr)
1834 {
1835 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1836 return packet;
1837 }
1838 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001839
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001840 while (1)
1841 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001842 if (query_count == TCP_MAX_QUERIES ||
1843 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001844 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1845 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001846 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001847 return packet;
1848
Simon Kelley572b41e2011-02-18 18:11:18 +00001849 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001850 continue;
Simon Kelley63437ff2017-09-06 22:34:21 +01001851
1852 /* Clear buffer beyond request to avoid risk of
1853 information disclosure. */
1854 memset(payload + size, 0, 65536 - size);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001855
Simon Kelley25cf5e32015-01-09 15:53:03 +00001856 query_count++;
1857
1858 /* log_query gets called indirectly all over the place, so
1859 pass these in global variables - sorry. */
1860 daemon->log_display_id = ++daemon->log_id;
1861 daemon->log_source_addr = &peer_addr;
1862
Simon Kelley28866e92011-02-14 20:19:14 +00001863 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001864 if ((checking_disabled = header->hb4 & HB4_CD))
1865 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001866
Simon Kelley3be34542004-09-11 19:12:13 +01001867 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001868 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001869#ifdef HAVE_AUTH
1870 struct auth_zone *zone;
1871#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001872 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001873
1874 if (peer_addr.sa.sa_family == AF_INET)
1875 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001876 (union all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelley7de060b2011-08-26 17:24:52 +01001877 else
1878 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001879 (union all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001880
1881#ifdef HAVE_AUTH
1882 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001883 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001884 for (zone = daemon->auth_zones; zone; zone = zone->next)
1885 if (in_zone(zone, daemon->namebuff, NULL))
1886 {
1887 auth_dns = 1;
1888 local_auth = 1;
1889 break;
1890 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001891#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001892 }
1893
Simon Kelley7de060b2011-08-26 17:24:52 +01001894 if (local_addr->sa.sa_family == AF_INET)
1895 dst_addr_4 = local_addr->in.sin_addr;
1896 else
1897 dst_addr_4.s_addr = 0;
1898
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001899 do_bit = 0;
1900
Simon Kelley5bb88f02015-12-21 16:23:47 +00001901 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001902 {
1903 unsigned short flags;
1904
1905 have_pseudoheader = 1;
1906 pheader += 4; /* udp_size, ext_rcode */
1907 GETSHORT(flags, pheader);
1908
1909 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001910 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001911 }
1912
Simon Kelley4820dce2012-12-18 18:30:30 +00001913#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001914 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001915 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1916 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001917 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001918#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001919 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001920 int ad_reqd = do_bit;
1921 /* RFC 6840 5.7 */
1922 if (header->hb4 & HB4_AD)
1923 ad_reqd = 1;
1924
1925 /* m > 0 if answered from cache */
1926 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1927 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001928
Simon Kelley4f7b3042012-11-28 21:27:02 +00001929 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001930 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001931
1932 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001933 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001934 unsigned int flags = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +00001935 union all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001936 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001937 char *domain = NULL;
Simon Kelley6fd5d792017-10-13 22:26:40 +01001938 unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
Simon Kelleyed4c0762013-10-08 20:46:34 +01001939
Simon Kelley6fd5d792017-10-13 22:26:40 +01001940 size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
1941
Simon Kelley4f7b3042012-11-28 21:27:02 +00001942 if (gotname)
1943 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley6fd5d792017-10-13 22:26:40 +01001944
1945#ifdef HAVE_DNSSEC
1946 if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
1947 {
1948 size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1949
1950 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1951 this allows it to select auth servers when one is returning bad data. */
1952 if (option_bool(OPT_DNSSEC_DEBUG))
1953 header->hb4 |= HB4_CD;
1954 }
1955#endif
1956
1957 /* Check if we added a pheader on forwarding - may need to
1958 strip it from the reply. */
1959 if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
1960 added_pheader = 1;
1961
Simon Kelley367341f2016-01-12 15:58:23 +00001962 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001963
Simon Kelley4f7b3042012-11-28 21:27:02 +00001964 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1965 last_server = daemon->servers;
1966 else
1967 last_server = daemon->last_server;
1968
1969 if (!flags && last_server)
1970 {
1971 struct server *firstsendto = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001972#ifdef HAVE_DNSSEC
Simon Kelley703c7ff2014-01-25 23:46:23 +00001973 unsigned char *newhash, hash[HASH_SIZE];
Simon Kelley63758382014-04-16 22:20:55 +01001974 if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001975 memcpy(hash, newhash, HASH_SIZE);
Tomas Hozzab37f8b92014-03-25 20:52:28 +00001976 else
1977 memset(hash, 0, HASH_SIZE);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001978#else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001979 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001980#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001981 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001982 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001983 which can go to the same server, do so. */
1984 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001985 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001986 int data_sent = 0;
1987
Simon Kelley4f7b3042012-11-28 21:27:02 +00001988 if (!firstsendto)
1989 firstsendto = last_server;
1990 else
1991 {
1992 if (!(last_server = last_server->next))
1993 last_server = daemon->servers;
1994
1995 if (last_server == firstsendto)
1996 break;
1997 }
1998
1999 /* server for wrong domain */
2000 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002001 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
2002 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01002003 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00002004
2005 retry:
Simon Kelley608aa9f2019-03-10 22:44:15 +00002006 *length = htons(size);
2007
Simon Kelley4f7b3042012-11-28 21:27:02 +00002008 if (last_server->tcpfd == -1)
2009 {
2010 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
2011 continue;
2012
Karl Vogele9828b62014-10-03 21:45:15 +01002013#ifdef HAVE_CONNTRACK
2014 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002015 if (have_mark)
2016 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley608aa9f2019-03-10 22:44:15 +00002017#endif
Karl Vogele9828b62014-10-03 21:45:15 +01002018
Simon Kelley608aa9f2019-03-10 22:44:15 +00002019 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1)))
2020 {
2021 close(last_server->tcpfd);
2022 last_server->tcpfd = -1;
2023 continue;
2024 }
2025
2026#ifdef MSG_FASTOPEN
2027 while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
2028 MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
2029
2030 if (errno == 0)
2031 data_sent = 1;
2032#endif
2033
2034 if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
Simon Kelley4f7b3042012-11-28 21:27:02 +00002035 {
2036 close(last_server->tcpfd);
2037 last_server->tcpfd = -1;
2038 continue;
2039 }
2040
Simon Kelley361dfe52017-02-10 21:12:30 +00002041 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002042 }
2043
Simon Kelley1fc02682014-04-29 12:30:18 +01002044 /* get query name again for logging - may have been overwritten */
2045 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
2046 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00002047
Simon Kelley608aa9f2019-03-10 22:44:15 +00002048 if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00002049 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002050 !read_write(last_server->tcpfd, &c2, 1, 1) ||
2051 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01002052 {
2053 close(last_server->tcpfd);
2054 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00002055 /* We get data then EOF, reopen connection to same server,
2056 else try next. This avoids DoS from a server which accepts
2057 connections and then closes them. */
2058 if (last_server->flags & SERV_GOT_TCP)
2059 goto retry;
2060 else
2061 continue;
2062 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002063
Simon Kelley361dfe52017-02-10 21:12:30 +00002064 last_server->flags |= SERV_GOT_TCP;
2065
Simon Kelley4f7b3042012-11-28 21:27:02 +00002066 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002067
Simon Kelley4f7b3042012-11-28 21:27:02 +00002068 if (last_server->addr.sa.sa_family == AF_INET)
2069 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002070 (union all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002071 else
2072 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002073 (union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002074
2075#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00002076 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002077 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00002078 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002079 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
2080 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01002081 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002082
Simon Kelley9a31b682015-12-15 10:20:39 +00002083 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00002084 {
2085 result = "ABANDONED";
2086 status = STAT_BOGUS;
2087 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00002088 else
2089 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01002090
2091 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
2092 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01002093
Simon Kelley07ed5852018-05-04 21:52:22 +01002094 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00002095
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002096 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002097 {
2098 no_cache_dnssec = 1;
2099 bogusanswer = 1;
2100 }
2101
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002102 if (status == STAT_SECURE)
2103 cache_secure = 1;
2104 }
2105#endif
2106
2107 /* restore CD bit to the value in the query */
2108 if (checking_disabled)
2109 header->hb4 |= HB4_CD;
2110 else
2111 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002112
2113 /* There's no point in updating the cache, since this process will exit and
2114 lose the information after a few queries. We make this call for the alias and
2115 bogus-nxdomain side-effects. */
2116 /* If the crc of the question section doesn't match the crc we sent, then
2117 someone might be attempting to insert bogus values into the cache by
2118 sending replies containing questions and bogus answers. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002119#ifdef HAVE_DNSSEC
2120 newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
2121 if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00002122 {
2123 m = 0;
2124 break;
2125 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002126#else
2127 if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
Simon Kelley703c7ff2014-01-25 23:46:23 +00002128 {
2129 m = 0;
2130 break;
2131 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002132#endif
2133
2134 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01002135 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00002136 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002137
2138 break;
2139 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002140 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002141
2142 /* In case of local answer or no connections made. */
2143 if (m == 0)
Simon Kelley1682d152018-08-03 20:38:18 +01002144 {
2145 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
2146 if (have_pseudoheader)
2147 m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
2148 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002149 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002150 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002151
Simon Kelleyb842bc92015-07-12 21:09:11 +01002152 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002153
Simon Kelley4b5ea122013-04-22 10:18:26 +01002154 *length = htons(m);
2155
2156 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002157 return packet;
2158 }
2159}
2160
Simon Kelley16972692006-10-16 20:04:18 +01002161static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002162{
Simon Kelley16972692006-10-16 20:04:18 +01002163 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002164
Simon Kelley5aabfc72007-08-29 11:24:47 +01002165 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002166 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002167 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002168 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00002169 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002170 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002171 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002172 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002173#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002174 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002175 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002176 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002177#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002178 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002179 }
Simon Kelley16972692006-10-16 20:04:18 +01002180
2181 return f;
2182}
2183
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002184struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002185{
2186 static int finger = 0;
2187 int i;
2188
2189 /* limit the number of sockets we have open to avoid starvation of
2190 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2191
2192 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002193 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002194 {
Simon Kelley9009d742008-11-14 20:04:27 +00002195 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2196 break;
2197
Simon Kelley1a6bca82008-07-11 11:11:42 +01002198 daemon->randomsocks[i].refcount = 1;
2199 daemon->randomsocks[i].family = family;
2200 return &daemon->randomsocks[i];
2201 }
2202
Simon Kelley9009d742008-11-14 20:04:27 +00002203 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002204 for (i = 0; i < RANDOM_SOCKS; i++)
2205 {
2206 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002207 if (daemon->randomsocks[j].refcount != 0 &&
2208 daemon->randomsocks[j].family == family &&
2209 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002210 {
2211 finger = j;
2212 daemon->randomsocks[j].refcount++;
2213 return &daemon->randomsocks[j];
2214 }
2215 }
2216
2217 return NULL; /* doom */
2218}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002219
2220void free_rfd(struct randfd *rfd)
2221{
2222 if (rfd && --(rfd->refcount) == 0)
2223 close(rfd->fd);
2224}
2225
Simon Kelley1a6bca82008-07-11 11:11:42 +01002226static void free_frec(struct frec *f)
2227{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002228 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002229 f->rfd4 = NULL;
2230 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002231 f->flags = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002232 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002233 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002234
2235#ifdef HAVE_DNSSEC
2236 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002237 {
2238 blockdata_free(f->stash);
2239 f->stash = NULL;
2240 }
Simon Kelley3a237152013-12-12 12:15:50 +00002241
2242 /* Anything we're waiting on is pointless now, too */
2243 if (f->blocking_query)
2244 free_frec(f->blocking_query);
2245 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002246 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002247#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002248}
2249
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002250
2251
Simon Kelley16972692006-10-16 20:04:18 +01002252/* if wait==NULL return a free or older than TIMEOUT record.
2253 else return *wait zero if one available, or *wait is delay to
Simon Kelley1a6bca82008-07-11 11:11:42 +01002254 when the oldest in-use record will expire. Impose an absolute
Simon Kelley3a237152013-12-12 12:15:50 +00002255 limit of 4*TIMEOUT before we wipe things (for random sockets).
Simon Kelley8caf3d72020-04-04 17:00:32 +01002256 If force is non-NULL, always return a result, even if we have
2257 to allocate above the limit, and never free the record pointed
2258 to by the force argument. */
2259struct frec *get_new_frec(time_t now, int *wait, struct frec *force)
Simon Kelley16972692006-10-16 20:04:18 +01002260{
Simon Kelley1a6bca82008-07-11 11:11:42 +01002261 struct frec *f, *oldest, *target;
Simon Kelley16972692006-10-16 20:04:18 +01002262 int count;
2263
2264 if (wait)
2265 *wait = 0;
2266
Simon Kelley1a6bca82008-07-11 11:11:42 +01002267 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
Simon Kelley832af0b2007-01-21 20:01:28 +00002268 if (!f->sentto)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002269 target = f;
2270 else
Simon Kelley16972692006-10-16 20:04:18 +01002271 {
Simon Kelley9a31b682015-12-15 10:20:39 +00002272#ifdef HAVE_DNSSEC
2273 /* Don't free DNSSEC sub-queries here, as we may end up with
2274 dangling references to them. They'll go when their "real" query
2275 is freed. */
Simon Kelley8caf3d72020-04-04 17:00:32 +01002276 if (!f->dependent && f != force)
Simon Kelley9a31b682015-12-15 10:20:39 +00002277#endif
2278 {
2279 if (difftime(now, f->time) >= 4*TIMEOUT)
2280 {
2281 free_frec(f);
2282 target = f;
2283 }
2284
2285
2286 if (!oldest || difftime(f->time, oldest->time) <= 0)
2287 oldest = f;
2288 }
Simon Kelley16972692006-10-16 20:04:18 +01002289 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01002290
2291 if (target)
2292 {
2293 target->time = now;
2294 return target;
2295 }
Simon Kelley16972692006-10-16 20:04:18 +01002296
2297 /* can't find empty one, use oldest if there is one
2298 and it's older than timeout */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002299 if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
Simon Kelley16972692006-10-16 20:04:18 +01002300 {
2301 /* keep stuff for twice timeout if we can by allocating a new
2302 record instead */
2303 if (difftime(now, oldest->time) < 2*TIMEOUT &&
2304 count <= daemon->ftabsize &&
2305 (f = allocate_frec(now)))
2306 return f;
2307
2308 if (!wait)
2309 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002310 free_frec(oldest);
Simon Kelley16972692006-10-16 20:04:18 +01002311 oldest->time = now;
2312 }
2313 return oldest;
2314 }
2315
2316 /* none available, calculate time 'till oldest record expires */
Simon Kelley3a237152013-12-12 12:15:50 +00002317 if (!force && count > daemon->ftabsize)
Simon Kelley16972692006-10-16 20:04:18 +01002318 {
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002319 static time_t last_log = 0;
2320
Simon Kelley16972692006-10-16 20:04:18 +01002321 if (oldest && wait)
2322 *wait = oldest->time + (time_t)TIMEOUT - now;
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002323
2324 if ((int)difftime(now, last_log) > 5)
2325 {
2326 last_log = now;
2327 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2328 }
2329
Simon Kelley16972692006-10-16 20:04:18 +01002330 return NULL;
2331 }
2332
2333 if (!(f = allocate_frec(now)) && wait)
2334 /* wait one second on malloc failure */
2335 *wait = 1;
2336
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002337 return f; /* OK if malloc fails and this is NULL */
2338}
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002339
Simon Kelley832af0b2007-01-21 20:01:28 +00002340/* crc is all-ones if not known. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002341static struct frec *lookup_frec(unsigned short id, void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002342{
2343 struct frec *f;
2344
Simon Kelley1a6bca82008-07-11 11:11:42 +01002345 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002346 if (f->sentto && f->new_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002347 (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002348 return f;
2349
2350 return NULL;
2351}
2352
2353static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002354 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002355 void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002356{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002357 struct frec *f;
2358
Simon Kelley1a6bca82008-07-11 11:11:42 +01002359 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002360 if (f->sentto &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002361 f->orig_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002362 memcmp(hash, f->hash, HASH_SIZE) == 0 &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002363 sockaddr_isequal(&f->source, addr))
2364 return f;
2365
2366 return NULL;
2367}
Simon Kelley47a95162014-07-08 22:22:02 +01002368
2369/* Send query packet again, if we can. */
2370void resend_query()
2371{
2372 if (daemon->srv_save)
2373 {
2374 int fd;
2375
2376 if (daemon->srv_save->sfd)
2377 fd = daemon->srv_save->sfd->fd;
2378 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2379 fd = daemon->rfd_save->fd;
2380 else
2381 return;
2382
Simon Kelleyff841eb2015-03-11 21:36:30 +00002383 while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2384 &daemon->srv_save->addr.sa,
2385 sa_len(&daemon->srv_save->addr))));
Simon Kelley47a95162014-07-08 22:22:02 +01002386 }
2387}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002388
Simon Kelley849a8352006-06-09 21:02:31 +01002389/* A server record is going away, remove references to it */
Simon Kelley5aabfc72007-08-29 11:24:47 +01002390void server_gone(struct server *server)
Simon Kelley849a8352006-06-09 21:02:31 +01002391{
2392 struct frec *f;
2393
Simon Kelley1a6bca82008-07-11 11:11:42 +01002394 for (f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002395 if (f->sentto && f->sentto == server)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002396 free_frec(f);
Simon Kelley849a8352006-06-09 21:02:31 +01002397
2398 if (daemon->last_server == server)
2399 daemon->last_server = NULL;
2400
2401 if (daemon->srv_save == server)
2402 daemon->srv_save = NULL;
2403}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002404
Simon Kelley316e2732010-01-22 20:16:09 +00002405/* return unique random ids. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002406static unsigned short get_id(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002407{
2408 unsigned short ret = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +00002409
Simon Kelley316e2732010-01-22 20:16:09 +00002410 do
Simon Kelley832af0b2007-01-21 20:01:28 +00002411 ret = rand16();
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002412 while (lookup_frec(ret, NULL));
Simon Kelley832af0b2007-01-21 20:01:28 +00002413
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002414 return ret;
2415}
2416
2417
2418
2419
2420