blob: 50da09536f6cefba32ae87bc8d810df515423e48 [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 Kelley257ac0c2020-11-12 18:49:23 +000019static struct frec *lookup_frec(unsigned short id, int fd, int family, 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 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley2d765862020-11-12 22:06:07 +0000260#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000261 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000262#endif
Simon Kelley1682d152018-08-03 20:38:18 +0100263 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
264 unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
265 (void)do_bit;
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000266
Simon Kelley3d8df262005-08-29 12:19:27 +0100267 /* may be no servers available. */
Simon Kelley2d765862020-11-12 22:06:07 +0000268 if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000269 {
Simon Kelleya77cec82015-05-08 16:25:38 +0100270 /* If we didn't get an answer advertising a maximal packet in EDNS,
271 fall back to 1280, which should work everywhere on IPv6.
272 If that generates an answer, it will become the new default
273 for this server */
274 forward->flags |= FREC_TEST_PKTSZ;
275
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000276#ifdef HAVE_DNSSEC
Simon Kelleydac74312014-02-13 16:43:49 +0000277 /* If we've already got an answer to this query, but we're awaiting keys for validation,
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000278 there's no point retrying the query, retry the key query instead...... */
279 if (forward->blocking_query)
280 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000281 int fd, is_sign;
282 unsigned char *pheader;
Simon Kelleya77cec82015-05-08 16:25:38 +0100283
284 forward->flags &= ~FREC_TEST_PKTSZ;
285
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000286 while (forward->blocking_query)
287 forward = forward->blocking_query;
Simon Kelleya77cec82015-05-08 16:25:38 +0100288
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000289 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
290 plen = forward->stash_len;
291
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000292 forward->flags |= FREC_TEST_PKTSZ;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000293 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000294 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000295
Simon Kelley2b291912014-03-21 11:13:55 +0000296 if (forward->sentto->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000297 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 +0000298 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000299 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 +0100300
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000301
302 if (forward->sentto->sfd)
303 fd = forward->sentto->sfd->fd;
304 else
305 {
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000306 if (forward->sentto->addr.sa.sa_family == AF_INET6)
307 fd = forward->rfd6->fd;
308 else
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000309 fd = forward->rfd4->fd;
310 }
311
Simon Kelleya0088e82018-05-10 21:43:14 +0100312 while (retry_send(sendto(fd, (char *)header, plen, 0,
313 &forward->sentto->addr.sa,
314 sa_len(&forward->sentto->addr))));
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000315
316 return 1;
317 }
318#endif
319
Simon Kelleyde379512004-06-22 20:23:33 +0100320 /* retry on existing query, send to all available servers */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000321 domain = forward->sentto->domain;
Simon Kelley824af852008-02-12 20:43:05 +0000322 forward->sentto->failed_queries++;
Simon Kelley28866e92011-02-14 20:19:14 +0000323 if (!option_bool(OPT_ORDER))
Simon Kelleyde379512004-06-22 20:23:33 +0100324 {
Simon Kelley0a852542005-03-23 20:28:59 +0000325 forward->forwardall = 1;
Simon Kelley3be34542004-09-11 19:12:13 +0100326 daemon->last_server = NULL;
Simon Kelleyde379512004-06-22 20:23:33 +0100327 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000328 type = forward->sentto->flags & SERV_TYPE;
Simon Kelley367341f2016-01-12 15:58:23 +0000329#ifdef HAVE_DNSSEC
330 do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
331#endif
332
Simon Kelleyde379512004-06-22 20:23:33 +0100333 if (!(start = forward->sentto->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100334 start = daemon->servers; /* at end of list, recycle */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000335 header->id = htons(forward->new_id);
336 }
337 else
338 {
339 if (gotname)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100340 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000341
Simon Kelley367341f2016-01-12 15:58:23 +0000342#ifdef HAVE_DNSSEC
343 do_dnssec = type & SERV_DO_DNSSEC;
Simon Kelleyf7443d72016-01-19 20:29:57 +0000344#endif
345 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +0000346
Simon Kelleyd05dd582016-01-19 21:23:30 +0000347 if (daemon->servers && !flags)
Simon Kelley8caf3d72020-04-04 17:00:32 +0100348 forward = get_new_frec(now, NULL, NULL);
Simon Kelleyd05dd582016-01-19 21:23:30 +0000349 /* table full - flags == 0, return REFUSED */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000350
351 if (forward)
352 {
Simon Kelley0a852542005-03-23 20:28:59 +0000353 forward->source = *udpaddr;
354 forward->dest = *dst_addr;
355 forward->iface = dst_iface;
Simon Kelley0a852542005-03-23 20:28:59 +0000356 forward->orig_id = ntohs(header->id);
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000357 forward->new_id = get_id();
Simon Kelley832af0b2007-01-21 20:01:28 +0000358 forward->fd = udpfd;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000359 memcpy(forward->hash, hash, HASH_SIZE);
Simon Kelley0a852542005-03-23 20:28:59 +0000360 forward->forwardall = 0;
Simon Kelleyed4c0762013-10-08 20:46:34 +0100361 forward->flags = 0;
Simon Kelley28866e92011-02-14 20:19:14 +0000362 if (norebind)
363 forward->flags |= FREC_NOREBIND;
Simon Kelley572b41e2011-02-18 18:11:18 +0000364 if (header->hb4 & HB4_CD)
Simon Kelley28866e92011-02-14 20:19:14 +0000365 forward->flags |= FREC_CHECKING_DISABLED;
Simon Kelley83349b82014-02-10 21:02:01 +0000366 if (ad_reqd)
367 forward->flags |= FREC_AD_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000368#ifdef HAVE_DNSSEC
369 forward->work_counter = DNSSEC_WORK;
Simon Kelley613ad152014-02-25 23:02:28 +0000370 if (do_bit)
371 forward->flags |= FREC_DO_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000372#endif
Simon Kelley613ad152014-02-25 23:02:28 +0000373
Simon Kelley28866e92011-02-14 20:19:14 +0000374 header->id = htons(forward->new_id);
375
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100376 /* In strict_order mode, always try servers in the order
377 specified in resolv.conf, if a domain is given
378 always try all the available servers,
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000379 otherwise, use the one last known to work. */
380
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100381 if (type == 0)
382 {
Simon Kelley28866e92011-02-14 20:19:14 +0000383 if (option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100384 start = daemon->servers;
385 else if (!(start = daemon->last_server) ||
386 daemon->forwardcount++ > FORWARD_TEST ||
387 difftime(now, daemon->forwardtime) > FORWARD_TIME)
388 {
389 start = daemon->servers;
390 forward->forwardall = 1;
391 daemon->forwardcount = 0;
392 daemon->forwardtime = now;
393 }
394 }
395 else
Simon Kelleyde379512004-06-22 20:23:33 +0100396 {
Simon Kelley3be34542004-09-11 19:12:13 +0100397 start = daemon->servers;
Simon Kelley28866e92011-02-14 20:19:14 +0000398 if (!option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100399 forward->forwardall = 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100400 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000401 }
402 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100403
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000404 /* check for send errors here (no route to host)
405 if we fail to send to all nameservers, send back an error
406 packet straight away (helps modem users when offline) */
407
408 if (!flags && forward)
409 {
Simon Kelleyde379512004-06-22 20:23:33 +0100410 struct server *firstsentto = start;
Simon Kelley33702ab2015-12-28 23:17:15 +0000411 int subnet, forwarded = 0;
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000412 size_t edns0_len;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000413 unsigned char *pheader;
414
Simon Kelley25cf5e32015-01-09 15:53:03 +0000415 /* If a query is retried, use the log_id for the retry when logging the answer. */
416 forward->log_id = daemon->log_id;
417
Simon Kelley6fd5d792017-10-13 22:26:40 +0100418 plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
Simon Kelley33702ab2015-12-28 23:17:15 +0000419
Simon Kelley6fd5d792017-10-13 22:26:40 +0100420 if (subnet)
421 forward->flags |= FREC_HAS_SUBNET;
Simon Kelley33702ab2015-12-28 23:17:15 +0000422
Simon Kelley3a237152013-12-12 12:15:50 +0000423#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000424 if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000425 {
Simon Kelley6fd5d792017-10-13 22:26:40 +0100426 plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
427
Simon Kelley5b3bf922014-01-25 17:03:07 +0000428 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
429 this allows it to select auth servers when one is returning bad data. */
430 if (option_bool(OPT_DNSSEC_DEBUG))
431 header->hb4 |= HB4_CD;
Simon Kelley613ad152014-02-25 23:02:28 +0000432
Simon Kelley0fc2f312014-01-08 10:26:58 +0000433 }
Simon Kelley3a237152013-12-12 12:15:50 +0000434#endif
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000435
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000436 if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
Simon Kelley6fd5d792017-10-13 22:26:40 +0100437 {
438 /* If there wasn't a PH before, and there is now, we added it. */
439 if (!oph)
440 forward->flags |= FREC_ADDED_PHEADER;
441
442 /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
443 if (edns0_len > 11)
444 forward->flags |= FREC_HAS_EXTRADATA;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000445
446 /* Reduce udp size on retransmits. */
447 if (forward->flags & FREC_TEST_PKTSZ)
448 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelley6fd5d792017-10-13 22:26:40 +0100449 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100450
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000451 while (1)
452 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000453 /* only send to servers dealing with our domain.
454 domain may be NULL, in which case server->domain
455 must be NULL also. */
456
Simon Kelleyde379512004-06-22 20:23:33 +0100457 if (type == (start->flags & SERV_TYPE) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100458 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100459 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000460 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100461 int fd;
462
463 /* find server socket to use, may need to get random one. */
464 if (start->sfd)
465 fd = start->sfd->fd;
466 else
467 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100468 if (start->addr.sa.sa_family == AF_INET6)
469 {
470 if (!forward->rfd6 &&
471 !(forward->rfd6 = allocate_rfd(AF_INET6)))
472 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100473 daemon->rfd_save = forward->rfd6;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100474 fd = forward->rfd6->fd;
475 }
476 else
Simon Kelley1a6bca82008-07-11 11:11:42 +0100477 {
478 if (!forward->rfd4 &&
479 !(forward->rfd4 = allocate_rfd(AF_INET)))
480 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100481 daemon->rfd_save = forward->rfd4;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100482 fd = forward->rfd4->fd;
483 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100484
485#ifdef HAVE_CONNTRACK
486 /* Copy connection mark of incoming query to outgoing connection. */
487 if (option_bool(OPT_CONNTRACK))
488 {
489 unsigned int mark;
Giacomo Tazzari797a7af2013-04-22 13:16:37 +0100490 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
Simon Kelley7de060b2011-08-26 17:24:52 +0100491 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
492 }
493#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100494 }
495
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000496#ifdef HAVE_DNSSEC
Simon Kelley5bb88f02015-12-21 16:23:47 +0000497 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000498 {
499 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
500 packet size to 512. But that won't provide space for the RRSIGS in many cases.
501 The RRSIGS will be stripped out before the answer goes back, so the packet should
502 shrink again. So, if we added a do-bit, bump the udp packet size to the value
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000503 known to be OK for this server. We check returned size after stripping and set
504 the truncated bit if it's still too big. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000505 unsigned char *pheader;
506 int is_sign;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000507 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000508 PUTSHORT(start->edns_pktsz, pheader);
509 }
510#endif
511
Simon Kelleyff841eb2015-03-11 21:36:30 +0000512 if (retry_send(sendto(fd, (char *)header, plen, 0,
513 &start->addr.sa,
514 sa_len(&start->addr))))
515 continue;
516
517 if (errno == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000518 {
Simon Kelley6b173352018-05-08 18:32:14 +0100519#ifdef HAVE_DUMPFILE
520 dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &start->addr);
521#endif
522
Simon Kelleycdeda282006-03-16 20:16:06 +0000523 /* Keep info in case we want to re-send this packet */
524 daemon->srv_save = start;
525 daemon->packet_len = plen;
526
Simon Kelleyde379512004-06-22 20:23:33 +0100527 if (!gotname)
Simon Kelley3be34542004-09-11 19:12:13 +0100528 strcpy(daemon->namebuff, "query");
Simon Kelleyde379512004-06-22 20:23:33 +0100529 if (start->addr.sa.sa_family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +0100530 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +0000531 (union all_addr *)&start->addr.in.sin_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100532 else
Simon Kelley3be34542004-09-11 19:12:13 +0100533 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +0000534 (union all_addr *)&start->addr.in6.sin6_addr, NULL);
Simon Kelley824af852008-02-12 20:43:05 +0000535 start->queries++;
Simon Kelleyde379512004-06-22 20:23:33 +0100536 forwarded = 1;
537 forward->sentto = start;
Simon Kelley0a852542005-03-23 20:28:59 +0000538 if (!forward->forwardall)
Simon Kelleyde379512004-06-22 20:23:33 +0100539 break;
Simon Kelley0a852542005-03-23 20:28:59 +0000540 forward->forwardall++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000541 }
542 }
543
Simon Kelleyde379512004-06-22 20:23:33 +0100544 if (!(start = start->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100545 start = daemon->servers;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000546
Simon Kelleyde379512004-06-22 20:23:33 +0100547 if (start == firstsentto)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000548 break;
549 }
550
Simon Kelleyde379512004-06-22 20:23:33 +0100551 if (forwarded)
Simon Kelley824af852008-02-12 20:43:05 +0000552 return 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100553
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000554 /* could not send on, prepare to return */
555 header->id = htons(forward->orig_id);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100556 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000557 }
558
559 /* could not send on, return empty answer or address if known for whole domain */
Simon Kelleyb8187c82005-11-26 21:46:27 +0000560 if (udpfd != -1)
561 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000562 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
Simon Kelley1682d152018-08-03 20:38:18 +0100563 if (oph)
564 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 +0100565 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 +0000566 }
567
Simon Kelley824af852008-02-12 20:43:05 +0000568 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000569}
570
Simon Kelleyed4c0762013-10-08 20:46:34 +0100571static 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 +0100572 int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
573 int check_subnet, union mysockaddr *query_source)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100574{
Simon Kelley36717ee2004-09-20 19:20:58 +0100575 unsigned char *pheader, *sizep;
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000576 char **sets = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +0000577 int munged = 0, is_sign;
Simon Kelley07ed5852018-05-04 21:52:22 +0100578 unsigned int rcode = RCODE(header);
Simon Kelleycdeda282006-03-16 20:16:06 +0000579 size_t plen;
Simon Kelleya6004d72017-10-25 17:48:19 +0100580
Simon Kelley83349b82014-02-10 21:02:01 +0000581 (void)ad_reqd;
Simon Kelley982faf42015-04-03 21:42:30 +0100582 (void)do_bit;
583 (void)bogusanswer;
Simon Kelley83349b82014-02-10 21:02:01 +0000584
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000585#ifdef HAVE_IPSET
Simon Kelley82a14af2014-04-13 20:48:57 +0100586 if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000587 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100588 /* Similar algorithm to search_servers. */
589 struct ipsets *ipset_pos;
590 unsigned int namelen = strlen(daemon->namebuff);
591 unsigned int matchlen = 0;
592 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
Simon Kelley6c0cb852014-01-17 14:40:46 +0000593 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100594 unsigned int domainlen = strlen(ipset_pos->domain);
595 char *matchstart = daemon->namebuff + namelen - domainlen;
596 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
597 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
598 domainlen >= matchlen)
599 {
600 matchlen = domainlen;
601 sets = ipset_pos->sets;
602 }
Simon Kelley6c0cb852014-01-17 14:40:46 +0000603 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000604 }
605#endif
606
Simon Kelley5bb88f02015-12-21 16:23:47 +0000607 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100608 {
Simon Kelley07ed5852018-05-04 21:52:22 +0100609 /* Get extended RCODE. */
610 rcode |= sizep[2] << 4;
611
Simon Kelleyed4c0762013-10-08 20:46:34 +0100612 if (check_subnet && !check_source(header, plen, pheader, query_source))
613 {
614 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
615 return 0;
616 }
Simon Kelley613ad152014-02-25 23:02:28 +0000617
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000618 if (!is_sign)
Simon Kelley613ad152014-02-25 23:02:28 +0000619 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000620 if (added_pheader)
621 {
622 /* client didn't send EDNS0, we added one, strip it off before returning answer. */
623 n = rrfilter(header, n, 0);
624 pheader = NULL;
625 }
626 else
627 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000628 unsigned short udpsz;
629
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000630 /* If upstream is advertising a larger UDP packet size
631 than we allow, trim it so that we don't get overlarge
632 requests for the client. We can't do this for signed packets. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000633 GETSHORT(udpsz, sizep);
634 if (udpsz > daemon->edns_pktsz)
Simon Kelley33702ab2015-12-28 23:17:15 +0000635 {
636 sizep -= 2;
637 PUTSHORT(daemon->edns_pktsz, sizep);
638 }
639
640#ifdef HAVE_DNSSEC
641 /* If the client didn't set the do bit, but we did, reset it. */
642 if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
643 {
644 unsigned short flags;
645 sizep += 2; /* skip RCODE */
646 GETSHORT(flags, sizep);
647 flags &= ~0x8000;
648 sizep -= 2;
649 PUTSHORT(flags, sizep);
650 }
651#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000652 }
Simon Kelley613ad152014-02-25 23:02:28 +0000653 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100654 }
Simon Kelley83349b82014-02-10 21:02:01 +0000655
Simon Kelley28866e92011-02-14 20:19:14 +0000656 /* RFC 4035 sect 4.6 para 3 */
Giovanni Bajo237724c2012-04-05 02:46:52 +0200657 if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
Simon Kelley795501b2014-01-08 18:11:55 +0000658 header->hb4 &= ~HB4_AD;
Simon Kelley3a237152013-12-12 12:15:50 +0000659
Simon Kelley07ed5852018-05-04 21:52:22 +0100660 if (OPCODE(header) != QUERY)
Simon Kelley8938ae02014-05-01 17:46:25 +0100661 return resize_packet(header, n, pheader, plen);
Simon Kelley07ed5852018-05-04 21:52:22 +0100662
663 if (rcode != NOERROR && rcode != NXDOMAIN)
664 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000665 union all_addr a;
666 a.log.rcode = rcode;
Simon Kelley07ed5852018-05-04 21:52:22 +0100667 log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
668
669 return resize_packet(header, n, pheader, plen);
670 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100671
Simon Kelley0a852542005-03-23 20:28:59 +0000672 /* Complain loudly if the upstream server is non-recursive. */
Simon Kelley07ed5852018-05-04 21:52:22 +0100673 if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
Simon Kelley0a852542005-03-23 20:28:59 +0000674 server && !(server->flags & SERV_WARNED_RECURSIVE))
675 {
Petr Mensik51cdd1a2019-07-04 20:28:08 +0200676 (void)prettyprint_addr(&server->addr, daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100677 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
Simon Kelley28866e92011-02-14 20:19:14 +0000678 if (!option_bool(OPT_LOG))
Simon Kelley0a852542005-03-23 20:28:59 +0000679 server->flags |= SERV_WARNED_RECURSIVE;
680 }
Giovanni Bajoe292e932012-04-22 14:32:02 +0200681
Simon Kelley07ed5852018-05-04 21:52:22 +0100682 if (daemon->bogus_addr && rcode != NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100683 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100684 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100685 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000686 SET_RCODE(header, NXDOMAIN);
687 header->hb3 &= ~HB3_AA;
Simon Kelley6938f342014-01-26 22:47:39 +0000688 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100689 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100690 else
Simon Kelley36717ee2004-09-20 19:20:58 +0100691 {
Simon Kelley6938f342014-01-26 22:47:39 +0000692 int doctored = 0;
693
Simon Kelley07ed5852018-05-04 21:52:22 +0100694 if (rcode == NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100695 extract_request(header, n, daemon->namebuff, NULL) &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100696 check_for_local_domain(daemon->namebuff, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100697 {
Simon Kelley36717ee2004-09-20 19:20:58 +0100698 /* if we forwarded a query for a locally known name (because it was for
699 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
700 since we know that the domain exists, even if upstream doesn't */
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100701 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000702 header->hb3 |= HB3_AA;
703 SET_RCODE(header, NOERROR);
Simon Kelley6938f342014-01-26 22:47:39 +0000704 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100705 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000706
Simon Kelley373e9172017-12-01 22:40:56 +0000707 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 +0000708 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100709 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
Simon Kelley824af852008-02-12 20:43:05 +0000710 munged = 1;
Simon Kelley6938f342014-01-26 22:47:39 +0000711 cache_secure = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000712 }
Simon Kelley6938f342014-01-26 22:47:39 +0000713
714 if (doctored)
715 cache_secure = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100716 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100717
Simon Kelleya25720a2014-01-14 23:13:55 +0000718#ifdef HAVE_DNSSEC
Simon Kelley33702ab2015-12-28 23:17:15 +0000719 if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
Simon Kelleya25720a2014-01-14 23:13:55 +0000720 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000721 /* Bogus reply, turn into SERVFAIL */
722 SET_RCODE(header, SERVFAIL);
723 munged = 1;
Simon Kelleya25720a2014-01-14 23:13:55 +0000724 }
Simon Kelley6938f342014-01-26 22:47:39 +0000725
726 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000727 {
728 header->hb4 &= ~HB4_AD;
729
730 if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
731 header->hb4 |= HB4_AD;
732
733 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
734 if (!do_bit)
735 n = rrfilter(header, n, 1);
736 }
Simon Kelleya25720a2014-01-14 23:13:55 +0000737#endif
738
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100739 /* do this after extract_addresses. Ensure NODATA reply and remove
740 nameserver info. */
741
742 if (munged)
743 {
744 header->ancount = htons(0);
745 header->nscount = htons(0);
746 header->arcount = htons(0);
Simon Kelley150162b2015-03-27 09:58:26 +0000747 header->hb3 &= ~HB3_TC;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100748 }
749
Simon Kelley36717ee2004-09-20 19:20:58 +0100750 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
751 sections of the packet. Find the new length here and put back pseudoheader
752 if it was removed. */
753 return resize_packet(header, n, pheader, plen);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100754}
755
Simon Kelley3be34542004-09-11 19:12:13 +0100756/* sets new last_server */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100757void reply_query(int fd, int family, time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000758{
759 /* packet from peer server, extract data for cache, and send to
760 original requester */
Simon Kelley572b41e2011-02-18 18:11:18 +0000761 struct dns_header *header;
Simon Kelleyde379512004-06-22 20:23:33 +0100762 union mysockaddr serveraddr;
Simon Kelley832af0b2007-01-21 20:01:28 +0000763 struct frec *forward;
Simon Kelleyde379512004-06-22 20:23:33 +0100764 socklen_t addrlen = sizeof(serveraddr);
Simon Kelley60b68062014-01-08 12:10:28 +0000765 ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
Simon Kelleycdeda282006-03-16 20:16:06 +0000766 size_t nn;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100767 struct server *server;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000768 void *hash;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000769
Simon Kelleycdeda282006-03-16 20:16:06 +0000770 /* packet buffer overwritten */
771 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000772
Simon Kelleyde379512004-06-22 20:23:33 +0100773 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelleyee875042018-10-23 22:10:17 +0100774 if ((serveraddr.sa.sa_family = family) == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100775 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000776
Simon Kelley490f9072014-03-24 22:04:42 +0000777 header = (struct dns_header *)daemon->packet;
Simon Kelley6b173352018-05-08 18:32:14 +0100778
Simon Kelley490f9072014-03-24 22:04:42 +0000779 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
780 return;
781
Simon Kelley1a6bca82008-07-11 11:11:42 +0100782 /* spoof check: answer must come from known server, */
783 for (server = daemon->servers; server; server = server->next)
784 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
785 sockaddr_isequal(&server->addr, &serveraddr))
786 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000787
788 if (!server)
789 return;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000790
791 /* If sufficient time has elapsed, try and expand UDP buffer size again. */
792 if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
793 server->edns_pktsz = daemon->edns_pktsz;
794
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000795 hash = hash_questions(header, n, daemon->namebuff);
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100796
Simon Kelley257ac0c2020-11-12 18:49:23 +0000797 if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100798 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000799
Simon Kelley6b173352018-05-08 18:32:14 +0100800#ifdef HAVE_DUMPFILE
801 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
802 (void *)header, n, &serveraddr, NULL);
803#endif
Simon Kelleya0088e82018-05-10 21:43:14 +0100804
Simon Kelley25cf5e32015-01-09 15:53:03 +0000805 /* log_query gets called indirectly all over the place, so
806 pass these in global variables - sorry. */
807 daemon->log_display_id = forward->log_id;
808 daemon->log_source_addr = &forward->source;
809
Glen Huang32fc6db2014-12-27 15:28:12 +0000810 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
811 check_for_ignored_address(header, n, daemon->ignore_addr))
812 return;
813
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000814 /* Note: if we send extra options in the EDNS0 header, we can't recreate
815 the query from the reply. */
Simon Kelley34e26e12018-05-10 20:54:57 +0100816 if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000817 forward->forwardall == 0 &&
818 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100819 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000820 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100821 unsigned char *pheader;
822 size_t plen;
823 int is_sign;
Simon Kelleyef3d1372017-12-05 22:37:29 +0000824
Simon Kelley1f60a182018-05-11 16:44:16 +0100825#ifdef HAVE_DNSSEC
Simon Kelleya0088e82018-05-10 21:43:14 +0100826 if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
827 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100828 struct server *start;
829
Simon Kelleya0088e82018-05-10 21:43:14 +0100830 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
831 plen = forward->stash_len;
832
833 forward->forwardall = 2; /* only retry once */
Simon Kelley1f60a182018-05-11 16:44:16 +0100834 start = forward->sentto;
835
836 /* for non-domain specific servers, see if we can find another to try. */
837 if ((forward->sentto->flags & SERV_TYPE) == 0)
838 while (1)
839 {
840 if (!(start = start->next))
841 start = daemon->servers;
842 if (start == forward->sentto)
843 break;
844
845 if ((start->flags & SERV_TYPE) == 0 &&
846 (start->flags & SERV_DO_DNSSEC))
847 break;
848 }
849
850
Simon Kelley82446112020-11-15 22:13:25 +0000851 fd = -1;
852
Simon Kelley1f60a182018-05-11 16:44:16 +0100853 if (start->sfd)
854 fd = start->sfd->fd;
Simon Kelleya0088e82018-05-10 21:43:14 +0100855 else
856 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100857 if (start->addr.sa.sa_family == AF_INET6)
858 {
859 /* may have changed family */
Simon Kelley82446112020-11-15 22:13:25 +0000860 if (forward->rfd6 || (forward->rfd6 = allocate_rfd(AF_INET6)))
861 fd = forward->rfd6->fd;
Simon Kelley1f60a182018-05-11 16:44:16 +0100862 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100863 else
Simon Kelley1f60a182018-05-11 16:44:16 +0100864 {
865 /* may have changed family */
Simon Kelley82446112020-11-15 22:13:25 +0000866 if (forward->rfd4 || (forward->rfd4 = allocate_rfd(AF_INET)))
867 fd = forward->rfd4->fd;
Simon Kelley1f60a182018-05-11 16:44:16 +0100868 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100869 }
Simon Kelleye3002bf2019-10-11 23:30:08 +0100870
Simon Kelley82446112020-11-15 22:13:25 +0000871 /* Can't get socket. */
872 if (fd == -1)
873 return;
874
Simon Kelleye3002bf2019-10-11 23:30:08 +0100875#ifdef HAVE_DUMPFILE
876 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
877#endif
878
Simon Kelleya0088e82018-05-10 21:43:14 +0100879 while (retry_send(sendto(fd, (char *)header, plen, 0,
Simon Kelley1f60a182018-05-11 16:44:16 +0100880 &start->addr.sa,
881 sa_len(&start->addr))));
Simon Kelleya0088e82018-05-10 21:43:14 +0100882
Simon Kelleye27825b2018-05-11 17:20:47 +0100883 if (start->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000884 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 +0100885 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000886 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 +0100887
Simon Kelleya0088e82018-05-10 21:43:14 +0100888 return;
889 }
Simon Kelley1f60a182018-05-11 16:44:16 +0100890#endif
891
Simon Kelleyef3d1372017-12-05 22:37:29 +0000892 /* In strict order mode, there must be a server later in the chain
893 left to send to, otherwise without the forwardall mechanism,
894 code further on will cycle around the list forwever if they
895 all return REFUSED. Note that server is always non-NULL before
896 this executes. */
897 if (option_bool(OPT_ORDER))
898 for (server = forward->sentto->next; server; server = server->next)
899 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
900 break;
901
Simon Kelley1a6bca82008-07-11 11:11:42 +0100902 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000903 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelleyef3d1372017-12-05 22:37:29 +0000904 if (!is_sign && server)
Simon Kelley832af0b2007-01-21 20:01:28 +0000905 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100906 header->ancount = htons(0);
907 header->nscount = htons(0);
908 header->arcount = htons(0);
909 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
910 {
swiggerbd7bfa22015-06-01 20:54:59 +0100911 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000912 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000913 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000914 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000915 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000916 header->hb4 |= HB4_AD;
917 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000918 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000919 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 +0100920 return;
921 }
922 }
923 }
Simon Kelley3a237152013-12-12 12:15:50 +0000924
925 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100926 if ((forward->sentto->flags & SERV_TYPE) == 0)
927 {
Simon Kelley51967f92014-03-25 21:07:00 +0000928 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100929 server = NULL;
930 else
931 {
932 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000933
Simon Kelley1a6bca82008-07-11 11:11:42 +0100934 /* find good server by address if possible, otherwise assume the last one we sent to */
935 for (last_server = daemon->servers; last_server; last_server = last_server->next)
936 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
937 sockaddr_isequal(&last_server->addr, &serveraddr))
938 {
939 server = last_server;
940 break;
941 }
942 }
Simon Kelley28866e92011-02-14 20:19:14 +0000943 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100944 daemon->last_server = server;
945 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100946
947 /* We tried resending to this server with a smaller maximum size and got an answer.
Ville Skyttäfaaf3062018-01-14 17:32:52 +0000948 Make that permanent. To avoid reduxing the packet size for a single dropped packet,
Simon Kelley86fa1042015-05-10 13:50:59 +0100949 only do this when we get a truncated answer, or one larger than the safe size. */
Simon Kelley04db1482019-10-11 23:22:17 +0100950 if (forward->sentto->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
Simon Kelley86fa1042015-05-10 13:50:59 +0100951 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelley22dee512017-10-13 22:54:00 +0100952 {
Simon Kelley04db1482019-10-11 23:22:17 +0100953 forward->sentto->edns_pktsz = SAFE_PKTSZ;
954 forward->sentto->pktsz_reduced = now;
Petr Mensik51cdd1a2019-07-04 20:28:08 +0200955 (void)prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
Simon Kelleyebedcba2017-10-29 20:54:17 +0000956 my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
Simon Kelley22dee512017-10-13 22:54:00 +0100957 }
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000958
959
Simon Kelley1a6bca82008-07-11 11:11:42 +0100960 /* If the answer is an error, keep the forward record in place in case
961 we get a good reply from another server. Kill it when we've
962 had replies from all to avoid filling the forwarding table when
963 everything is broken */
Simon Kelley122392e2018-10-31 22:24:02 +0000964 if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100965 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100966 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleya6004d72017-10-25 17:48:19 +0100967
Simon Kelley3a237152013-12-12 12:15:50 +0000968 if (option_bool(OPT_NO_REBIND))
969 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100970
Simon Kelley3a237152013-12-12 12:15:50 +0000971 /* Don't cache replies where DNSSEC validation was turned off, either
972 the upstream server told us so, or the original query specified it. */
973 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
974 no_cache_dnssec = 1;
975
976#ifdef HAVE_DNSSEC
Simon Kelley04db1482019-10-11 23:22:17 +0100977 if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000978 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000979 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000980 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000981
982 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000983 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000984 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000985
986 /* Truncated answer can't be validated.
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100987 If this is an answer to a DNSSEC-generated query, we still
988 need to get the client to retry over TCP, so return
989 an answer with the TC bit set, even if the actual answer fits.
990 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000991 if (header->hb3 & HB3_TC)
992 status = STAT_TRUNCATED;
993
994 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000995 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000996 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
997 would invite infinite loops, since the answers to DNSKEY and DS queries
998 will not be cached, so they'll be repeated. */
999 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001000 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001001 if (forward->flags & FREC_DNSKEY_QUERY)
1002 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1003 else if (forward->flags & FREC_DS_QUERY)
1004 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001005 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001006 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
Simon Kelley203ce0a2019-10-12 21:41:20 +01001007 !option_bool(OPT_DNSSEC_IGN_NS) && (forward->sentto->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001008 NULL, NULL, NULL);
Simon Kelley6b173352018-05-08 18:32:14 +01001009#ifdef HAVE_DUMPFILE
1010 if (status == STAT_BOGUS)
1011 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
1012 header, (size_t)n, &serveraddr, NULL);
1013#endif
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001014 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001015
Simon Kelley9a31b682015-12-15 10:20:39 +00001016 /* Can't validate, as we're missing key data. Put this
1017 answer aside, whilst we get that. */
1018 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +00001019 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001020 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +00001021
Simon Kelley9a31b682015-12-15 10:20:39 +00001022 /* Free any saved query */
1023 if (forward->stash)
1024 blockdata_free(forward->stash);
1025
1026 /* Now save reply pending receipt of key data */
1027 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +00001028 return;
Simon Kelley9a31b682015-12-15 10:20:39 +00001029 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001030
Simon Kelley9a31b682015-12-15 10:20:39 +00001031 /* Find the original query that started it all.... */
1032 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001033
Simon Kelley8caf3d72020-04-04 17:00:32 +01001034 /* Make sure we don't expire and free the orig frec during the
1035 allocation of a new one. */
1036 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, orig)))
Simon Kelley9a31b682015-12-15 10:20:39 +00001037 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001038 else
Simon Kelley3a237152013-12-12 12:15:50 +00001039 {
Simon Kelleye1791f32018-10-06 23:23:23 +01001040 int querytype, fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +00001041 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +00001042 char *domain;
1043
Simon Kelley9a31b682015-12-15 10:20:39 +00001044 *new = *forward; /* copy everything, then overwrite */
1045 new->next = next;
1046 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +00001047
1048 /* Find server to forward to. This will normally be the
1049 same as for the original query, but may be another if
1050 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001051 if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
Simon Kelley92be34a2016-01-16 18:39:54 +00001052 {
Simon Kelley203ce0a2019-10-12 21:41:20 +01001053 struct server *start, *new_server = NULL;
1054 start = server = forward->sentto;
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001055
1056 while (1)
1057 {
1058 if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
Simon Kelley1f60a182018-05-11 16:44:16 +01001059 ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001060 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1061 {
1062 new_server = start;
1063 if (server == start)
1064 {
1065 new_server = NULL;
1066 break;
1067 }
1068 }
1069
1070 if (!(start = start->next))
1071 start = daemon->servers;
1072 if (start == server)
1073 break;
1074 }
1075
1076 if (new_server)
1077 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +00001078 }
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001079
Simon Kelley9a31b682015-12-15 10:20:39 +00001080 new->sentto = server;
1081 new->rfd4 = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001082 new->rfd6 = NULL;
Simon Kelleya0088e82018-05-10 21:43:14 +01001083 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
1084 new->forwardall = 0;
Simon Kelley9a31b682015-12-15 10:20:39 +00001085
1086 new->dependent = forward; /* to find query awaiting new one. */
1087 forward->blocking_query = new; /* for garbage cleaning */
1088 /* validate routines leave name of required record in daemon->keyname */
1089 if (status == STAT_NEED_KEY)
Simon Kelley7fa836e2014-02-10 20:11:24 +00001090 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001091 new->flags |= FREC_DNSKEY_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001092 querytype = T_DNSKEY;
Simon Kelleyf1668d22014-01-08 16:53:27 +00001093 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001094 else
1095 {
1096 new->flags |= FREC_DS_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001097 querytype = T_DS;
Simon Kelley9a31b682015-12-15 10:20:39 +00001098 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001099
1100 nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
1101 daemon->keyname, forward->class, querytype, server->edns_pktsz);
1102
1103 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001104 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 +01001105 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001106 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001107 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 +01001108 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001109
Simon Kelley2d765862020-11-12 22:06:07 +00001110 memcpy(new->hash, hash_questions(header, nn, daemon->namebuff), HASH_SIZE);
Simon Kelley9a31b682015-12-15 10:20:39 +00001111 new->new_id = get_id();
1112 header->id = htons(new->new_id);
1113 /* Save query for retransmission */
1114 new->stash = blockdata_alloc((char *)header, nn);
1115 new->stash_len = nn;
1116
1117 /* Don't resend this. */
1118 daemon->srv_save = NULL;
1119
1120 if (server->sfd)
1121 fd = server->sfd->fd;
1122 else
1123 {
1124 fd = -1;
Simon Kelley9a31b682015-12-15 10:20:39 +00001125 if (server->addr.sa.sa_family == AF_INET6)
1126 {
1127 if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1128 fd = new->rfd6->fd;
1129 }
1130 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001131 {
1132 if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1133 fd = new->rfd4->fd;
1134 }
1135 }
1136
1137 if (fd != -1)
1138 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001139#ifdef HAVE_CONNTRACK
1140 /* Copy connection mark of incoming query to outgoing connection. */
1141 if (option_bool(OPT_CONNTRACK))
1142 {
1143 unsigned int mark;
1144 if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
1145 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1146 }
1147#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001148
1149#ifdef HAVE_DUMPFILE
1150 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
1151#endif
1152
Simon Kelley9a31b682015-12-15 10:20:39 +00001153 while (retry_send(sendto(fd, (char *)header, nn, 0,
1154 &server->addr.sa,
1155 sa_len(&server->addr))));
1156 server->queries++;
1157 }
1158 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001159 return;
Simon Kelley3a237152013-12-12 12:15:50 +00001160 }
Simon Kelley3a237152013-12-12 12:15:50 +00001161
Simon Kelley9a31b682015-12-15 10:20:39 +00001162 /* Validated original answer, all done. */
1163 if (!forward->dependent)
1164 break;
1165
Josh Soref730c6742017-02-06 16:14:04 +00001166 /* validated subsidiary query, (and cached result)
Simon Kelley9a31b682015-12-15 10:20:39 +00001167 pop that and return to the previous query we were working on. */
Simon Kelley0744ca62014-01-25 16:40:15 +00001168 struct frec *prev = forward->dependent;
1169 free_frec(forward);
1170 forward = prev;
1171 forward->blocking_query = NULL; /* already gone */
1172 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1173 n = forward->stash_len;
Simon Kelley3a237152013-12-12 12:15:50 +00001174 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001175
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001176
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001177 no_cache_dnssec = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001178
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001179 if (status == STAT_TRUNCATED)
Simon Kelley0744ca62014-01-25 16:40:15 +00001180 header->hb3 |= HB3_TC;
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001181 else
Simon Kelley7fa836e2014-02-10 20:11:24 +00001182 {
Simon Kelley554b5802015-04-17 22:50:20 +01001183 char *result, *domain = "result";
Simon Kelley7fa836e2014-02-10 20:11:24 +00001184
Simon Kelley9a31b682015-12-15 10:20:39 +00001185 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001186 {
1187 result = "ABANDONED";
1188 status = STAT_BOGUS;
1189 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001190 else
1191 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1192
Simon Kelley554b5802015-04-17 22:50:20 +01001193 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1194 domain = daemon->namebuff;
Simon Kelley9a31b682015-12-15 10:20:39 +00001195
Simon Kelley07ed5852018-05-04 21:52:22 +01001196 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001197 }
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001198
Simon Kelley3a237152013-12-12 12:15:50 +00001199 if (status == STAT_SECURE)
1200 cache_secure = 1;
Simon Kelley3a237152013-12-12 12:15:50 +00001201 else if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001202 {
1203 no_cache_dnssec = 1;
1204 bogusanswer = 1;
1205 }
Simon Kelley3a237152013-12-12 12:15:50 +00001206 }
Simon Kelley04db1482019-10-11 23:22:17 +01001207
Simon Kelley6b173352018-05-08 18:32:14 +01001208#endif
1209
Simon Kelley83349b82014-02-10 21:02:01 +00001210 /* restore CD bit to the value in the query */
1211 if (forward->flags & FREC_CHECKING_DISABLED)
1212 header->hb4 |= HB4_CD;
1213 else
1214 header->hb4 &= ~HB4_CD;
Simon Kelley3a237152013-12-12 12:15:50 +00001215
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001216 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 +00001217 forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1218 forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
Simon Kelley832af0b2007-01-21 20:01:28 +00001219 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001220 header->id = htons(forward->orig_id);
Simon Kelley572b41e2011-02-18 18:11:18 +00001221 header->hb4 |= HB4_RA; /* recursion if available */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001222#ifdef HAVE_DNSSEC
1223 /* 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 +01001224 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 +00001225 header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1226 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1227 {
1228 header->ancount = htons(0);
1229 header->nscount = htons(0);
1230 header->arcount = htons(0);
1231 header->hb3 |= HB3_TC;
1232 nn = resize_packet(header, nn, NULL, 0);
1233 }
1234#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001235
1236#ifdef HAVE_DUMPFILE
1237 dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
1238#endif
1239
Simon Kelley54dd3932012-06-20 11:23:38 +01001240 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
Simon Kelley50303b12012-04-04 22:13:17 +01001241 &forward->source, &forward->dest, forward->iface);
Simon Kelley832af0b2007-01-21 20:01:28 +00001242 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001243 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001244 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001245}
Simon Kelley44a2a312004-03-10 20:04:35 +00001246
Simon Kelley1a6bca82008-07-11 11:11:42 +01001247
Simon Kelley5aabfc72007-08-29 11:24:47 +01001248void receive_query(struct listener *listen, time_t now)
Simon Kelley44a2a312004-03-10 20:04:35 +00001249{
Simon Kelley572b41e2011-02-18 18:11:18 +00001250 struct dns_header *header = (struct dns_header *)daemon->packet;
Simon Kelley44a2a312004-03-10 20:04:35 +00001251 union mysockaddr source_addr;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001252 unsigned char *pheader;
1253 unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
Simon Kelleycc921df2019-01-02 22:48:59 +00001254 union all_addr dst_addr;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001255 struct in_addr netmask, dst_addr_4;
Simon Kelleycdeda282006-03-16 20:16:06 +00001256 size_t m;
1257 ssize_t n;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001258 int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001259#ifdef HAVE_AUTH
1260 int local_auth = 0;
1261#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001262 struct iovec iov[1];
1263 struct msghdr msg;
1264 struct cmsghdr *cmptr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001265 union {
1266 struct cmsghdr align; /* this ensures alignment */
Simon Kelley44a2a312004-03-10 20:04:35 +00001267 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001268#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +00001269 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
Simon Kelley824af852008-02-12 20:43:05 +00001270#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1271 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1272 CMSG_SPACE(sizeof(unsigned int))];
Simon Kelley44a2a312004-03-10 20:04:35 +00001273#elif defined(IP_RECVDSTADDR)
1274 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1275 CMSG_SPACE(sizeof(struct sockaddr_dl))];
1276#endif
1277 } control_u;
Petr Menšík1c1b9252019-07-15 17:16:44 +02001278 int family = listen->addr.sa.sa_family;
Simon Kelley2329bef2013-12-03 13:41:16 +00001279 /* Can always get recvd interface for IPv6 */
Petr Menšík1c1b9252019-07-15 17:16:44 +02001280 int check_dst = !option_bool(OPT_NOWILD) || family == AF_INET6;
Simon Kelley2329bef2013-12-03 13:41:16 +00001281
Simon Kelleycdeda282006-03-16 20:16:06 +00001282 /* packet buffer overwritten */
1283 daemon->srv_save = NULL;
1284
Simon Kelleycc921df2019-01-02 22:48:59 +00001285 dst_addr_4.s_addr = dst_addr.addr4.s_addr = 0;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001286 netmask.s_addr = 0;
1287
Simon Kelley7e5664b2013-04-05 16:57:41 +01001288 if (option_bool(OPT_NOWILD) && listen->iface)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001289 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001290 auth_dns = listen->iface->dns_auth;
1291
Petr Menšík1c1b9252019-07-15 17:16:44 +02001292 if (family == AF_INET)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001293 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001294 dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001295 netmask = listen->iface->netmask;
1296 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001297 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001298
Simon Kelley3be34542004-09-11 19:12:13 +01001299 iov[0].iov_base = daemon->packet;
1300 iov[0].iov_len = daemon->edns_pktsz;
Simon Kelley44a2a312004-03-10 20:04:35 +00001301
1302 msg.msg_control = control_u.control;
1303 msg.msg_controllen = sizeof(control_u);
1304 msg.msg_flags = 0;
1305 msg.msg_name = &source_addr;
1306 msg.msg_namelen = sizeof(source_addr);
1307 msg.msg_iov = iov;
1308 msg.msg_iovlen = 1;
1309
Simon Kelleyde379512004-06-22 20:23:33 +01001310 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
Simon Kelley3be34542004-09-11 19:12:13 +01001311 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001312
Simon Kelley572b41e2011-02-18 18:11:18 +00001313 if (n < (int)sizeof(struct dns_header) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001314 (msg.msg_flags & MSG_TRUNC) ||
Simon Kelley572b41e2011-02-18 18:11:18 +00001315 (header->hb3 & HB3_QR))
Simon Kelley3be34542004-09-11 19:12:13 +01001316 return;
Simon Kelley63437ff2017-09-06 22:34:21 +01001317
1318 /* Clear buffer beyond request to avoid risk of
1319 information disclosure. */
1320 memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
Simon Kelley44a2a312004-03-10 20:04:35 +00001321
Petr Menšík1c1b9252019-07-15 17:16:44 +02001322 source_addr.sa.sa_family = family;
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001323
Petr Menšík1c1b9252019-07-15 17:16:44 +02001324 if (family == AF_INET)
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001325 {
1326 /* Source-port == 0 is an error, we can't send back to that.
1327 http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1328 if (source_addr.in.sin_port == 0)
1329 return;
1330 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001331 else
1332 {
1333 /* Source-port == 0 is an error, we can't send back to that. */
1334 if (source_addr.in6.sin6_port == 0)
1335 return;
1336 source_addr.in6.sin6_flowinfo = 0;
1337 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001338
Simon Kelleyc8a80482014-03-05 14:29:54 +00001339 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1340 if (option_bool(OPT_LOCAL_SERVICE))
1341 {
1342 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001343
Petr Menšík1c1b9252019-07-15 17:16:44 +02001344 if (family == AF_INET6)
Simon Kelleyc8a80482014-03-05 14:29:54 +00001345 {
1346 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1347 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001348 is_same_net6(&addr->addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001349 break;
1350 }
1351 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001352 {
1353 struct in_addr netmask;
1354 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1355 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001356 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001357 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001358 is_same_net(addr->addr.addr4, source_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001359 break;
1360 }
1361 }
1362 if (!addr)
1363 {
Simon Kelley0c8584e2014-03-12 20:12:56 +00001364 static int warned = 0;
1365 if (!warned)
1366 {
1367 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1368 warned = 1;
1369 }
Simon Kelleyc8a80482014-03-05 14:29:54 +00001370 return;
1371 }
1372 }
1373
Simon Kelley2329bef2013-12-03 13:41:16 +00001374 if (check_dst)
Simon Kelley44a2a312004-03-10 20:04:35 +00001375 {
Simon Kelley8a911cc2004-03-16 18:35:52 +00001376 struct ifreq ifr;
1377
Simon Kelley26128d22004-11-14 16:43:54 +00001378 if (msg.msg_controllen < sizeof(struct cmsghdr))
1379 return;
1380
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001381#if defined(HAVE_LINUX_NETWORK)
Petr Menšík1c1b9252019-07-15 17:16:44 +02001382 if (family == AF_INET)
Simon Kelley26128d22004-11-14 16:43:54 +00001383 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001384 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
Simon Kelley26128d22004-11-14 16:43:54 +00001385 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001386 union {
1387 unsigned char *c;
1388 struct in_pktinfo *p;
1389 } p;
1390 p.c = CMSG_DATA(cmptr);
Simon Kelleycc921df2019-01-02 22:48:59 +00001391 dst_addr_4 = dst_addr.addr4 = p.p->ipi_spec_dst;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001392 if_index = p.p->ipi_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001393 }
1394#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
Petr Menšík1c1b9252019-07-15 17:16:44 +02001395 if (family == AF_INET)
Simon Kelley26128d22004-11-14 16:43:54 +00001396 {
1397 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001398 {
1399 union {
1400 unsigned char *c;
1401 unsigned int *i;
1402 struct in_addr *a;
1403#ifndef HAVE_SOLARIS_NETWORK
1404 struct sockaddr_dl *s;
Simon Kelley824af852008-02-12 20:43:05 +00001405#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001406 } p;
1407 p.c = CMSG_DATA(cmptr);
1408 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
Simon Kelleycc921df2019-01-02 22:48:59 +00001409 dst_addr_4 = dst_addr.addr4 = *(p.a);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001410 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1411#ifdef HAVE_SOLARIS_NETWORK
1412 if_index = *(p.i);
1413#else
1414 if_index = p.s->sdl_index;
1415#endif
1416 }
Simon Kelley26128d22004-11-14 16:43:54 +00001417 }
1418#endif
1419
Petr Menšík1c1b9252019-07-15 17:16:44 +02001420 if (family == AF_INET6)
Simon Kelley26128d22004-11-14 16:43:54 +00001421 {
1422 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001423 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
Simon Kelley26128d22004-11-14 16:43:54 +00001424 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001425 union {
1426 unsigned char *c;
1427 struct in6_pktinfo *p;
1428 } p;
1429 p.c = CMSG_DATA(cmptr);
1430
Simon Kelleycc921df2019-01-02 22:48:59 +00001431 dst_addr.addr6 = p.p->ipi6_addr;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001432 if_index = p.p->ipi6_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001433 }
1434 }
Simon Kelley26128d22004-11-14 16:43:54 +00001435
1436 /* enforce available interface configuration */
1437
Simon Kelleye25db1f2013-01-29 22:10:26 +00001438 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
Simon Kelley832af0b2007-01-21 20:01:28 +00001439 return;
1440
Petr Menšík1c1b9252019-07-15 17:16:44 +02001441 if (!iface_check(family, &dst_addr, ifr.ifr_name, &auth_dns))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001442 {
1443 if (!option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001444 enumerate_interfaces(0);
Petr Menšík1c1b9252019-07-15 17:16:44 +02001445 if (!loopback_exception(listen->fd, family, &dst_addr, ifr.ifr_name) &&
1446 !label_exception(if_index, family, &dst_addr))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001447 return;
1448 }
1449
Petr Menšík1c1b9252019-07-15 17:16:44 +02001450 if (family == AF_INET && option_bool(OPT_LOCALISE))
Simon Kelley552af8b2012-02-29 20:10:31 +00001451 {
1452 struct irec *iface;
1453
Josh Soref730c6742017-02-06 16:14:04 +00001454 /* get the netmask of the interface which has the address we were sent to.
klemens43517fc2017-02-19 15:53:37 +00001455 This is no necessarily the interface we arrived on. */
Simon Kelley552af8b2012-02-29 20:10:31 +00001456
1457 for (iface = daemon->interfaces; iface; iface = iface->next)
1458 if (iface->addr.sa.sa_family == AF_INET &&
1459 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1460 break;
1461
1462 /* interface may be new */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001463 if (!iface && !option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001464 enumerate_interfaces(0);
Simon Kelley552af8b2012-02-29 20:10:31 +00001465
1466 for (iface = daemon->interfaces; iface; iface = iface->next)
1467 if (iface->addr.sa.sa_family == AF_INET &&
1468 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1469 break;
1470
1471 /* If we failed, abandon localisation */
1472 if (iface)
1473 netmask = iface->netmask;
1474 else
1475 dst_addr_4.s_addr = 0;
1476 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001477 }
Simon Kelley25cf5e32015-01-09 15:53:03 +00001478
1479 /* log_query gets called indirectly all over the place, so
1480 pass these in global variables - sorry. */
1481 daemon->log_display_id = ++daemon->log_id;
1482 daemon->log_source_addr = &source_addr;
Simon Kelley6b173352018-05-08 18:32:14 +01001483
1484#ifdef HAVE_DUMPFILE
1485 dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
1486#endif
1487
Simon Kelleycdeda282006-03-16 20:16:06 +00001488 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
Simon Kelley44a2a312004-03-10 20:04:35 +00001489 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001490#ifdef HAVE_AUTH
1491 struct auth_zone *zone;
1492#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001493 char *types = querystr(auth_dns ? "auth" : "query", type);
1494
Petr Menšík1c1b9252019-07-15 17:16:44 +02001495 if (family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +01001496 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001497 (union all_addr *)&source_addr.in.sin_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001498 else
Simon Kelley3be34542004-09-11 19:12:13 +01001499 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001500 (union all_addr *)&source_addr.in6.sin6_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001501
Simon Kelley4820dce2012-12-18 18:30:30 +00001502#ifdef HAVE_AUTH
Simon Kelleyb485ed92013-10-18 22:00:39 +01001503 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001504 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001505 for (zone = daemon->auth_zones; zone; zone = zone->next)
1506 if (in_zone(zone, daemon->namebuff, NULL))
1507 {
1508 auth_dns = 1;
1509 local_auth = 1;
1510 break;
1511 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001512#endif
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001513
1514#ifdef HAVE_LOOP
1515 /* Check for forwarding loop */
1516 if (detect_loop(daemon->namebuff, type))
1517 return;
1518#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001519 }
1520
Simon Kelley5bb88f02015-12-21 16:23:47 +00001521 if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001522 {
1523 unsigned short flags;
1524
1525 have_pseudoheader = 1;
1526 GETSHORT(udp_size, pheader);
1527 pheader += 2; /* ext_rcode */
1528 GETSHORT(flags, pheader);
1529
1530 if (flags & 0x8000)
1531 do_bit = 1;/* do bit */
1532
1533 /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1534 (bounded by the maximum configured). If no EDNS0, then it
1535 defaults to 512 */
1536 if (udp_size > daemon->edns_pktsz)
1537 udp_size = daemon->edns_pktsz;
Simon Kelleya3303e12017-09-07 20:45:00 +01001538 else if (udp_size < PACKETSZ)
1539 udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001540 }
1541
Simon Kelleyb485ed92013-10-18 22:00:39 +01001542#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001543 if (auth_dns)
Simon Kelley824af852008-02-12 20:43:05 +00001544 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001545 m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1546 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001547 if (m >= 1)
Simon Kelleyb485ed92013-10-18 22:00:39 +01001548 {
1549 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1550 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001551 daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
Simon Kelleyb485ed92013-10-18 22:00:39 +01001552 }
Simon Kelley824af852008-02-12 20:43:05 +00001553 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001554 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001555#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001556 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001557 int ad_reqd = do_bit;
1558 /* RFC 6840 5.7 */
1559 if (header->hb4 & HB4_AD)
1560 ad_reqd = 1;
1561
1562 m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1563 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001564
1565 if (m >= 1)
1566 {
1567 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1568 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001569 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001570 }
1571 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
Simon Kelley613ad152014-02-25 23:02:28 +00001572 header, (size_t)n, now, NULL, ad_reqd, do_bit))
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001573 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001574 else
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001575 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001576 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001577}
1578
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001579#ifdef HAVE_DNSSEC
Josh Soref730c6742017-02-06 16:14:04 +00001580/* Recurse up the key hierarchy */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001581static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001582 int class, char *name, char *keyname, struct server *server,
1583 int have_mark, unsigned int mark, int *keycount)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001584{
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001585 int new_status;
Simon Kelley9a31b682015-12-15 10:20:39 +00001586 unsigned char *packet = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001587 unsigned char *payload = NULL;
1588 struct dns_header *new_header = NULL;
1589 u16 *length = NULL;
Simon Kelley361dfe52017-02-10 21:12:30 +00001590
Simon Kelley9a31b682015-12-15 10:20:39 +00001591 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001592 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001593 int type = SERV_DO_DNSSEC;
1594 char *domain;
1595 size_t m;
1596 unsigned char c1, c2;
Simon Kelley361dfe52017-02-10 21:12:30 +00001597 struct server *firstsendto = NULL;
1598
Simon Kelley9a31b682015-12-15 10:20:39 +00001599 /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1600 if (--(*keycount) == 0)
1601 new_status = STAT_ABANDONED;
1602 else if (status == STAT_NEED_KEY)
1603 new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1604 else if (status == STAT_NEED_DS)
1605 new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1606 else
James Bottomleye33b4872017-03-17 21:44:10 +00001607 new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
Simon Kelleya6918532018-04-15 16:20:52 +01001608 !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001609 NULL, NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001610
Simon Kelley9a31b682015-12-15 10:20:39 +00001611 if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1612 break;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001613
Simon Kelley9a31b682015-12-15 10:20:39 +00001614 /* Can't validate because we need a key/DS whose name now in keyname.
1615 Make query for same, and recurse to validate */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001616 if (!packet)
Simon Kelley9a31b682015-12-15 10:20:39 +00001617 {
1618 packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1619 payload = &packet[2];
1620 new_header = (struct dns_header *)payload;
1621 length = (u16 *)packet;
1622 }
1623
1624 if (!packet)
1625 {
1626 new_status = STAT_ABANDONED;
1627 break;
1628 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001629
Simon Kelley33702ab2015-12-28 23:17:15 +00001630 m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
Simon Kelleye1791f32018-10-06 23:23:23 +01001631 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, server->edns_pktsz);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001632
Simon Kelley7fa836e2014-02-10 20:11:24 +00001633 *length = htons(m);
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001634
1635 /* Find server to forward to. This will normally be the
1636 same as for the original query, but may be another if
1637 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001638 if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001639 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001640 new_status = STAT_ABANDONED;
1641 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001642 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001643
Simon Kelley361dfe52017-02-10 21:12:30 +00001644 while (1)
1645 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001646 int data_sent = 0;
1647
Simon Kelley361dfe52017-02-10 21:12:30 +00001648 if (!firstsendto)
1649 firstsendto = server;
1650 else
1651 {
1652 if (!(server = server->next))
1653 server = daemon->servers;
1654 if (server == firstsendto)
1655 {
1656 /* can't find server to accept our query. */
1657 new_status = STAT_ABANDONED;
1658 break;
1659 }
1660 }
1661
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001662 if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001663 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1664 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1665 continue;
Simon Kelleye1791f32018-10-06 23:23:23 +01001666
1667 retry:
1668 /* may need to make new connection. */
1669 if (server->tcpfd == -1)
1670 {
1671 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1672 continue; /* No good, next server */
1673
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001674#ifdef HAVE_CONNTRACK
Simon Kelleye1791f32018-10-06 23:23:23 +01001675 /* Copy connection mark of incoming query to outgoing connection. */
1676 if (have_mark)
1677 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001678#endif
Simon Kelleye1791f32018-10-06 23:23:23 +01001679
Simon Kelley608aa9f2019-03-10 22:44:15 +00001680 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1))
1681 {
1682 close(server->tcpfd);
1683 server->tcpfd = -1;
1684 continue; /* No good, next server */
1685 }
1686
1687#ifdef MSG_FASTOPEN
1688 while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
1689 MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
1690
1691 if (errno == 0)
1692 data_sent = 1;
1693#endif
1694
1695 if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
Simon Kelleye1791f32018-10-06 23:23:23 +01001696 {
1697 close(server->tcpfd);
1698 server->tcpfd = -1;
1699 continue; /* No good, next server */
1700 }
1701
1702 server->flags &= ~SERV_GOT_TCP;
1703 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001704
Simon Kelley608aa9f2019-03-10 22:44:15 +00001705 if ((!data_sent && !read_write(server->tcpfd, packet, m + sizeof(u16), 0)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001706 !read_write(server->tcpfd, &c1, 1, 1) ||
1707 !read_write(server->tcpfd, &c2, 1, 1) ||
1708 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1709 {
1710 close(server->tcpfd);
1711 server->tcpfd = -1;
1712 /* We get data then EOF, reopen connection to same server,
1713 else try next. This avoids DoS from a server which accepts
1714 connections and then closes them. */
1715 if (server->flags & SERV_GOT_TCP)
1716 goto retry;
1717 else
1718 continue;
1719 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001720
1721
1722 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001723 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (union all_addr *)&(server->addr.in.sin_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001724 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelleye1791f32018-10-06 23:23:23 +01001725 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001726 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001727 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelley361dfe52017-02-10 21:12:30 +00001728
1729 server->flags |= SERV_GOT_TCP;
1730
1731 m = (c1 << 8) | c2;
1732 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1733 break;
1734 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001735
1736 if (new_status != STAT_OK)
1737 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001738 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001739
Simon Kelley9a31b682015-12-15 10:20:39 +00001740 if (packet)
1741 free(packet);
1742
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001743 return new_status;
1744}
1745#endif
1746
1747
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001748/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001749 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001750 about resources for debug mode, when the fork is suppressed: that's
1751 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001752unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001753 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001754{
Simon Kelley28866e92011-02-14 20:19:14 +00001755 size_t size = 0;
1756 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001757#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001758 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001759#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001760 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001761 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001762 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001763 unsigned short qtype;
1764 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001765 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001766 /* Max TCP packet + slop + size */
1767 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1768 unsigned char *payload = &packet[2];
1769 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1770 struct dns_header *header = (struct dns_header *)payload;
1771 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001772 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001773 struct in_addr dst_addr_4;
1774 union mysockaddr peer_addr;
1775 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001776 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001777 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001778 unsigned int mark = 0;
1779 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001780
Simon Kelleyd05dd582016-01-19 21:23:30 +00001781 (void)mark;
1782 (void)have_mark;
1783
Simon Kelley7de060b2011-08-26 17:24:52 +01001784 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1785 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001786
1787#ifdef HAVE_CONNTRACK
1788 /* Get connection mark of incoming query to set on outgoing connections. */
1789 if (option_bool(OPT_CONNTRACK))
1790 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001791 union all_addr local;
Simon Kelleyee875042018-10-23 22:10:17 +01001792
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001793 if (local_addr->sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001794 local.addr6 = local_addr->in6.sin6_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001795 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001796 local.addr4 = local_addr->in.sin_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001797
1798 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1799 }
1800#endif
1801
Simon Kelleyc8a80482014-03-05 14:29:54 +00001802 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1803 if (option_bool(OPT_LOCAL_SERVICE))
1804 {
1805 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001806
Simon Kelleyc8a80482014-03-05 14:29:54 +00001807 if (peer_addr.sa.sa_family == AF_INET6)
1808 {
1809 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1810 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001811 is_same_net6(&addr->addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001812 break;
1813 }
1814 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001815 {
1816 struct in_addr netmask;
1817 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1818 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001819 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001820 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001821 is_same_net(addr->addr.addr4, peer_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001822 break;
1823 }
1824 }
1825 if (!addr)
1826 {
1827 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1828 return packet;
1829 }
1830 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001831
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001832 while (1)
1833 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001834 if (query_count == TCP_MAX_QUERIES ||
1835 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001836 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1837 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001838 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001839 return packet;
1840
Simon Kelley572b41e2011-02-18 18:11:18 +00001841 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001842 continue;
Simon Kelley63437ff2017-09-06 22:34:21 +01001843
1844 /* Clear buffer beyond request to avoid risk of
1845 information disclosure. */
1846 memset(payload + size, 0, 65536 - size);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001847
Simon Kelley25cf5e32015-01-09 15:53:03 +00001848 query_count++;
1849
1850 /* log_query gets called indirectly all over the place, so
1851 pass these in global variables - sorry. */
1852 daemon->log_display_id = ++daemon->log_id;
1853 daemon->log_source_addr = &peer_addr;
1854
Simon Kelley28866e92011-02-14 20:19:14 +00001855 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001856 if ((checking_disabled = header->hb4 & HB4_CD))
1857 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001858
Simon Kelley3be34542004-09-11 19:12:13 +01001859 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001860 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001861#ifdef HAVE_AUTH
1862 struct auth_zone *zone;
1863#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001864 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001865
1866 if (peer_addr.sa.sa_family == AF_INET)
1867 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001868 (union all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelley7de060b2011-08-26 17:24:52 +01001869 else
1870 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001871 (union all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001872
1873#ifdef HAVE_AUTH
1874 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001875 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001876 for (zone = daemon->auth_zones; zone; zone = zone->next)
1877 if (in_zone(zone, daemon->namebuff, NULL))
1878 {
1879 auth_dns = 1;
1880 local_auth = 1;
1881 break;
1882 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001883#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001884 }
1885
Simon Kelley7de060b2011-08-26 17:24:52 +01001886 if (local_addr->sa.sa_family == AF_INET)
1887 dst_addr_4 = local_addr->in.sin_addr;
1888 else
1889 dst_addr_4.s_addr = 0;
1890
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001891 do_bit = 0;
1892
Simon Kelley5bb88f02015-12-21 16:23:47 +00001893 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001894 {
1895 unsigned short flags;
1896
1897 have_pseudoheader = 1;
1898 pheader += 4; /* udp_size, ext_rcode */
1899 GETSHORT(flags, pheader);
1900
1901 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001902 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001903 }
1904
Simon Kelley4820dce2012-12-18 18:30:30 +00001905#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001906 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001907 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1908 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001909 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001910#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001911 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001912 int ad_reqd = do_bit;
1913 /* RFC 6840 5.7 */
1914 if (header->hb4 & HB4_AD)
1915 ad_reqd = 1;
1916
1917 /* m > 0 if answered from cache */
1918 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1919 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001920
Simon Kelley4f7b3042012-11-28 21:27:02 +00001921 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001922 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001923
1924 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001925 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001926 unsigned int flags = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +00001927 union all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001928 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001929 char *domain = NULL;
Simon Kelley6fd5d792017-10-13 22:26:40 +01001930 unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
Simon Kelleyed4c0762013-10-08 20:46:34 +01001931
Simon Kelley6fd5d792017-10-13 22:26:40 +01001932 size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
1933
Simon Kelley4f7b3042012-11-28 21:27:02 +00001934 if (gotname)
1935 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley6fd5d792017-10-13 22:26:40 +01001936
1937#ifdef HAVE_DNSSEC
1938 if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
1939 {
1940 size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1941
1942 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1943 this allows it to select auth servers when one is returning bad data. */
1944 if (option_bool(OPT_DNSSEC_DEBUG))
1945 header->hb4 |= HB4_CD;
1946 }
1947#endif
1948
1949 /* Check if we added a pheader on forwarding - may need to
1950 strip it from the reply. */
1951 if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
1952 added_pheader = 1;
1953
Simon Kelley367341f2016-01-12 15:58:23 +00001954 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001955
Simon Kelley4f7b3042012-11-28 21:27:02 +00001956 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1957 last_server = daemon->servers;
1958 else
1959 last_server = daemon->last_server;
1960
1961 if (!flags && last_server)
1962 {
1963 struct server *firstsendto = NULL;
Simon Kelley2d765862020-11-12 22:06:07 +00001964 unsigned char hash[HASH_SIZE];
1965 memcpy(hash, hash_questions(header, (unsigned int)size, daemon->namebuff), HASH_SIZE);
1966
Simon Kelley4f7b3042012-11-28 21:27:02 +00001967 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001968 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001969 which can go to the same server, do so. */
1970 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001971 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001972 int data_sent = 0;
1973
Simon Kelley4f7b3042012-11-28 21:27:02 +00001974 if (!firstsendto)
1975 firstsendto = last_server;
1976 else
1977 {
1978 if (!(last_server = last_server->next))
1979 last_server = daemon->servers;
1980
1981 if (last_server == firstsendto)
1982 break;
1983 }
1984
1985 /* server for wrong domain */
1986 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001987 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
1988 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01001989 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00001990
1991 retry:
Simon Kelley608aa9f2019-03-10 22:44:15 +00001992 *length = htons(size);
1993
Simon Kelley4f7b3042012-11-28 21:27:02 +00001994 if (last_server->tcpfd == -1)
1995 {
1996 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1997 continue;
1998
Karl Vogele9828b62014-10-03 21:45:15 +01001999#ifdef HAVE_CONNTRACK
2000 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002001 if (have_mark)
2002 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley608aa9f2019-03-10 22:44:15 +00002003#endif
Karl Vogele9828b62014-10-03 21:45:15 +01002004
Simon Kelley608aa9f2019-03-10 22:44:15 +00002005 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1)))
2006 {
2007 close(last_server->tcpfd);
2008 last_server->tcpfd = -1;
2009 continue;
2010 }
2011
2012#ifdef MSG_FASTOPEN
2013 while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
2014 MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
2015
2016 if (errno == 0)
2017 data_sent = 1;
2018#endif
2019
2020 if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
Simon Kelley4f7b3042012-11-28 21:27:02 +00002021 {
2022 close(last_server->tcpfd);
2023 last_server->tcpfd = -1;
2024 continue;
2025 }
2026
Simon Kelley361dfe52017-02-10 21:12:30 +00002027 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002028 }
2029
Simon Kelley1fc02682014-04-29 12:30:18 +01002030 /* get query name again for logging - may have been overwritten */
2031 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
2032 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00002033
Simon Kelley608aa9f2019-03-10 22:44:15 +00002034 if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00002035 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002036 !read_write(last_server->tcpfd, &c2, 1, 1) ||
2037 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01002038 {
2039 close(last_server->tcpfd);
2040 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00002041 /* We get data then EOF, reopen connection to same server,
2042 else try next. This avoids DoS from a server which accepts
2043 connections and then closes them. */
2044 if (last_server->flags & SERV_GOT_TCP)
2045 goto retry;
2046 else
2047 continue;
2048 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002049
Simon Kelley361dfe52017-02-10 21:12:30 +00002050 last_server->flags |= SERV_GOT_TCP;
2051
Simon Kelley4f7b3042012-11-28 21:27:02 +00002052 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002053
Simon Kelley4f7b3042012-11-28 21:27:02 +00002054 if (last_server->addr.sa.sa_family == AF_INET)
2055 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002056 (union all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002057 else
2058 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002059 (union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002060
2061#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00002062 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002063 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00002064 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002065 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
2066 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01002067 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002068
Simon Kelley9a31b682015-12-15 10:20:39 +00002069 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00002070 {
2071 result = "ABANDONED";
2072 status = STAT_BOGUS;
2073 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00002074 else
2075 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01002076
2077 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
2078 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01002079
Simon Kelley07ed5852018-05-04 21:52:22 +01002080 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00002081
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002082 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002083 {
2084 no_cache_dnssec = 1;
2085 bogusanswer = 1;
2086 }
2087
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002088 if (status == STAT_SECURE)
2089 cache_secure = 1;
2090 }
2091#endif
2092
2093 /* restore CD bit to the value in the query */
2094 if (checking_disabled)
2095 header->hb4 |= HB4_CD;
2096 else
2097 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002098
2099 /* There's no point in updating the cache, since this process will exit and
2100 lose the information after a few queries. We make this call for the alias and
2101 bogus-nxdomain side-effects. */
2102 /* If the crc of the question section doesn't match the crc we sent, then
2103 someone might be attempting to insert bogus values into the cache by
2104 sending replies containing questions and bogus answers. */
Simon Kelley2d765862020-11-12 22:06:07 +00002105 if (memcmp(hash, hash_questions(header, (unsigned int)m, daemon->namebuff), HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00002106 {
2107 m = 0;
2108 break;
2109 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002110
2111 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01002112 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00002113 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002114
2115 break;
2116 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002117 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002118
2119 /* In case of local answer or no connections made. */
2120 if (m == 0)
Simon Kelley1682d152018-08-03 20:38:18 +01002121 {
2122 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
2123 if (have_pseudoheader)
2124 m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
2125 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002126 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002127 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002128
Simon Kelleyb842bc92015-07-12 21:09:11 +01002129 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002130
Simon Kelley4b5ea122013-04-22 10:18:26 +01002131 *length = htons(m);
2132
2133 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002134 return packet;
2135 }
2136}
2137
Simon Kelley16972692006-10-16 20:04:18 +01002138static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002139{
Simon Kelley16972692006-10-16 20:04:18 +01002140 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002141
Simon Kelley5aabfc72007-08-29 11:24:47 +01002142 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002143 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002144 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002145 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00002146 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002147 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002148 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002149 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002150#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002151 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002152 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002153 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002154#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002155 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002156 }
Simon Kelley16972692006-10-16 20:04:18 +01002157
2158 return f;
2159}
2160
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002161struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002162{
2163 static int finger = 0;
2164 int i;
2165
2166 /* limit the number of sockets we have open to avoid starvation of
2167 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2168
2169 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002170 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002171 {
Simon Kelley9009d742008-11-14 20:04:27 +00002172 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2173 break;
2174
Simon Kelley1a6bca82008-07-11 11:11:42 +01002175 daemon->randomsocks[i].refcount = 1;
2176 daemon->randomsocks[i].family = family;
2177 return &daemon->randomsocks[i];
2178 }
2179
Simon Kelley9009d742008-11-14 20:04:27 +00002180 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002181 for (i = 0; i < RANDOM_SOCKS; i++)
2182 {
2183 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002184 if (daemon->randomsocks[j].refcount != 0 &&
2185 daemon->randomsocks[j].family == family &&
2186 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002187 {
2188 finger = j;
2189 daemon->randomsocks[j].refcount++;
2190 return &daemon->randomsocks[j];
2191 }
2192 }
2193
2194 return NULL; /* doom */
2195}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002196
2197void free_rfd(struct randfd *rfd)
2198{
2199 if (rfd && --(rfd->refcount) == 0)
2200 close(rfd->fd);
2201}
2202
Simon Kelley1a6bca82008-07-11 11:11:42 +01002203static void free_frec(struct frec *f)
2204{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002205 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002206 f->rfd4 = NULL;
2207 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002208 f->flags = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002209 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002210 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002211
2212#ifdef HAVE_DNSSEC
2213 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002214 {
2215 blockdata_free(f->stash);
2216 f->stash = NULL;
2217 }
Simon Kelley3a237152013-12-12 12:15:50 +00002218
2219 /* Anything we're waiting on is pointless now, too */
2220 if (f->blocking_query)
2221 free_frec(f->blocking_query);
2222 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002223 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002224#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002225}
2226
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002227
2228
Simon Kelley16972692006-10-16 20:04:18 +01002229/* if wait==NULL return a free or older than TIMEOUT record.
2230 else return *wait zero if one available, or *wait is delay to
Simon Kelley1a6bca82008-07-11 11:11:42 +01002231 when the oldest in-use record will expire. Impose an absolute
Simon Kelley3a237152013-12-12 12:15:50 +00002232 limit of 4*TIMEOUT before we wipe things (for random sockets).
Simon Kelley8caf3d72020-04-04 17:00:32 +01002233 If force is non-NULL, always return a result, even if we have
2234 to allocate above the limit, and never free the record pointed
2235 to by the force argument. */
2236struct frec *get_new_frec(time_t now, int *wait, struct frec *force)
Simon Kelley16972692006-10-16 20:04:18 +01002237{
Simon Kelley1a6bca82008-07-11 11:11:42 +01002238 struct frec *f, *oldest, *target;
Simon Kelley16972692006-10-16 20:04:18 +01002239 int count;
2240
2241 if (wait)
2242 *wait = 0;
2243
Simon Kelley1a6bca82008-07-11 11:11:42 +01002244 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
Simon Kelley832af0b2007-01-21 20:01:28 +00002245 if (!f->sentto)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002246 target = f;
2247 else
Simon Kelley16972692006-10-16 20:04:18 +01002248 {
Simon Kelley9a31b682015-12-15 10:20:39 +00002249#ifdef HAVE_DNSSEC
2250 /* Don't free DNSSEC sub-queries here, as we may end up with
2251 dangling references to them. They'll go when their "real" query
2252 is freed. */
Simon Kelley8caf3d72020-04-04 17:00:32 +01002253 if (!f->dependent && f != force)
Simon Kelley9a31b682015-12-15 10:20:39 +00002254#endif
2255 {
2256 if (difftime(now, f->time) >= 4*TIMEOUT)
2257 {
2258 free_frec(f);
2259 target = f;
2260 }
2261
2262
2263 if (!oldest || difftime(f->time, oldest->time) <= 0)
2264 oldest = f;
2265 }
Simon Kelley16972692006-10-16 20:04:18 +01002266 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01002267
2268 if (target)
2269 {
2270 target->time = now;
2271 return target;
2272 }
Simon Kelley16972692006-10-16 20:04:18 +01002273
2274 /* can't find empty one, use oldest if there is one
2275 and it's older than timeout */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002276 if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
Simon Kelley16972692006-10-16 20:04:18 +01002277 {
2278 /* keep stuff for twice timeout if we can by allocating a new
2279 record instead */
2280 if (difftime(now, oldest->time) < 2*TIMEOUT &&
2281 count <= daemon->ftabsize &&
2282 (f = allocate_frec(now)))
2283 return f;
2284
2285 if (!wait)
2286 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002287 free_frec(oldest);
Simon Kelley16972692006-10-16 20:04:18 +01002288 oldest->time = now;
2289 }
2290 return oldest;
2291 }
2292
2293 /* none available, calculate time 'till oldest record expires */
Simon Kelley3a237152013-12-12 12:15:50 +00002294 if (!force && count > daemon->ftabsize)
Simon Kelley16972692006-10-16 20:04:18 +01002295 {
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002296 static time_t last_log = 0;
2297
Simon Kelley16972692006-10-16 20:04:18 +01002298 if (oldest && wait)
2299 *wait = oldest->time + (time_t)TIMEOUT - now;
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002300
2301 if ((int)difftime(now, last_log) > 5)
2302 {
2303 last_log = now;
2304 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2305 }
2306
Simon Kelley16972692006-10-16 20:04:18 +01002307 return NULL;
2308 }
2309
2310 if (!(f = allocate_frec(now)) && wait)
2311 /* wait one second on malloc failure */
2312 *wait = 1;
2313
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002314 return f; /* OK if malloc fails and this is NULL */
2315}
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002316
Simon Kelley257ac0c2020-11-12 18:49:23 +00002317static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002318{
2319 struct frec *f;
2320
Simon Kelley1a6bca82008-07-11 11:11:42 +01002321 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002322 if (f->sentto && f->new_id == id &&
Simon Kelley2d765862020-11-12 22:06:07 +00002323 (memcmp(hash, f->hash, HASH_SIZE) == 0))
Simon Kelley257ac0c2020-11-12 18:49:23 +00002324 {
2325 /* sent from random port */
2326 if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
2327 return f;
2328
2329 if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd)
2330 return f;
2331
2332 /* sent to upstream from bound socket. */
2333 if (f->sentto->sfd && f->sentto->sfd->fd == fd)
2334 return f;
2335 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002336
2337 return NULL;
2338}
2339
2340static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002341 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002342 void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002343{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002344 struct frec *f;
2345
Simon Kelley1a6bca82008-07-11 11:11:42 +01002346 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002347 if (f->sentto &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002348 f->orig_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002349 memcmp(hash, f->hash, HASH_SIZE) == 0 &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002350 sockaddr_isequal(&f->source, addr))
2351 return f;
2352
2353 return NULL;
2354}
Simon Kelley47a95162014-07-08 22:22:02 +01002355
2356/* Send query packet again, if we can. */
2357void resend_query()
2358{
2359 if (daemon->srv_save)
2360 {
2361 int fd;
2362
2363 if (daemon->srv_save->sfd)
2364 fd = daemon->srv_save->sfd->fd;
2365 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2366 fd = daemon->rfd_save->fd;
2367 else
2368 return;
2369
Simon Kelleyff841eb2015-03-11 21:36:30 +00002370 while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2371 &daemon->srv_save->addr.sa,
2372 sa_len(&daemon->srv_save->addr))));
Simon Kelley47a95162014-07-08 22:22:02 +01002373 }
2374}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002375
Simon Kelley849a8352006-06-09 21:02:31 +01002376/* A server record is going away, remove references to it */
Simon Kelley5aabfc72007-08-29 11:24:47 +01002377void server_gone(struct server *server)
Simon Kelley849a8352006-06-09 21:02:31 +01002378{
2379 struct frec *f;
2380
Simon Kelley1a6bca82008-07-11 11:11:42 +01002381 for (f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002382 if (f->sentto && f->sentto == server)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002383 free_frec(f);
Simon Kelley849a8352006-06-09 21:02:31 +01002384
2385 if (daemon->last_server == server)
2386 daemon->last_server = NULL;
2387
2388 if (daemon->srv_save == server)
2389 daemon->srv_save = NULL;
2390}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002391
Simon Kelley316e2732010-01-22 20:16:09 +00002392/* return unique random ids. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002393static unsigned short get_id(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002394{
2395 unsigned short ret = 0;
Simon Kelley257ac0c2020-11-12 18:49:23 +00002396 struct frec *f;
Simon Kelley832af0b2007-01-21 20:01:28 +00002397
Simon Kelley257ac0c2020-11-12 18:49:23 +00002398 while (1)
2399 {
2400 ret = rand16();
2401
2402 /* ensure id is unique. */
2403 for (f = daemon->frec_list; f; f = f->next)
2404 if (f->sentto && f->new_id == ret)
2405 break;
2406
2407 if (!f)
2408 return ret;
2409 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002410}
2411
2412
2413
2414
2415