blob: ed9c8f69e2ce720d15e935e3408dbd4fb0ee714a [file] [log] [blame]
Simon Kelley2a8710a2020-01-05 16:40:06 +00001/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley8a9be9e2014-01-25 23:17:21 +000019static struct frec *lookup_frec(unsigned short id, void *hash);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +010021 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +000022 void *hash);
23static unsigned short get_id(void);
Simon Kelley1a6bca82008-07-11 11:11:42 +010024static void free_frec(struct frec *f);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000025
Simon Kelley824af852008-02-12 20:43:05 +000026/* Send a UDP packet with its source address set as "source"
Simon Kelley44a2a312004-03-10 20:04:35 +000027 unless nowild is true, when we just send it with the kernel default */
Simon Kelley29689cf2012-03-22 14:01:00 +000028int send_from(int fd, int nowild, char *packet, size_t len,
Simon Kelleycc921df2019-01-02 22:48:59 +000029 union mysockaddr *to, union all_addr *source,
Simon Kelley50303b12012-04-04 22:13:17 +010030 unsigned int iface)
Simon Kelley9e4abcb2004-01-22 19:47:41 +000031{
Simon Kelley44a2a312004-03-10 20:04:35 +000032 struct msghdr msg;
33 struct iovec iov[1];
Simon Kelley44a2a312004-03-10 20:04:35 +000034 union {
35 struct cmsghdr align; /* this ensures alignment */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010036#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +000037 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
38#elif defined(IP_SENDSRCADDR)
39 char control[CMSG_SPACE(sizeof(struct in_addr))];
40#endif
Simon Kelley44a2a312004-03-10 20:04:35 +000041 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
Simon Kelley44a2a312004-03-10 20:04:35 +000042 } control_u;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010043
Simon Kelley44a2a312004-03-10 20:04:35 +000044 iov[0].iov_base = packet;
45 iov[0].iov_len = len;
46
Simon Kelleyfeba5c12004-07-27 20:28:58 +010047 msg.msg_control = NULL;
48 msg.msg_controllen = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +000049 msg.msg_flags = 0;
50 msg.msg_name = to;
51 msg.msg_namelen = sa_len(to);
52 msg.msg_iov = iov;
53 msg.msg_iovlen = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010054
Simon Kelley26128d22004-11-14 16:43:54 +000055 if (!nowild)
Simon Kelleyfeba5c12004-07-27 20:28:58 +010056 {
Simon Kelley26128d22004-11-14 16:43:54 +000057 struct cmsghdr *cmptr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010058 msg.msg_control = &control_u;
59 msg.msg_controllen = sizeof(control_u);
Simon Kelley26128d22004-11-14 16:43:54 +000060 cmptr = CMSG_FIRSTHDR(&msg);
Simon Kelley44a2a312004-03-10 20:04:35 +000061
Simon Kelley26128d22004-11-14 16:43:54 +000062 if (to->sa.sa_family == AF_INET)
63 {
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010064#if defined(HAVE_LINUX_NETWORK)
Simon Kelley8ef5ada2010-06-03 19:42:45 +010065 struct in_pktinfo p;
66 p.ipi_ifindex = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +000067 p.ipi_spec_dst = source->addr4;
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010068 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
Simon Kelley8ef5ada2010-06-03 19:42:45 +010069 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010070 cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
Simon Kelleyc72daea2012-01-05 21:33:27 +000071 cmptr->cmsg_level = IPPROTO_IP;
Simon Kelley26128d22004-11-14 16:43:54 +000072 cmptr->cmsg_type = IP_PKTINFO;
73#elif defined(IP_SENDSRCADDR)
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010074 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
Simon Kelleycc921df2019-01-02 22:48:59 +000075 memcpy(CMSG_DATA(cmptr), &(source->addr4), sizeof(source->addr4));
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010076 cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
Simon Kelley26128d22004-11-14 16:43:54 +000077 cmptr->cmsg_level = IPPROTO_IP;
78 cmptr->cmsg_type = IP_SENDSRCADDR;
Simon Kelley44a2a312004-03-10 20:04:35 +000079#endif
Simon Kelley26128d22004-11-14 16:43:54 +000080 }
Simon Kelley26128d22004-11-14 16:43:54 +000081 else
82 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +010083 struct in6_pktinfo p;
84 p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
Simon Kelleycc921df2019-01-02 22:48:59 +000085 p.ipi6_addr = source->addr6;
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010086 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
Simon Kelley8ef5ada2010-06-03 19:42:45 +010087 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Jérémie Courrèges-Anglasc6cc4552019-03-22 10:56:13 +010088 cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
Simon Kelley316e2732010-01-22 20:16:09 +000089 cmptr->cmsg_type = daemon->v6pktinfo;
Simon Kelleyc72daea2012-01-05 21:33:27 +000090 cmptr->cmsg_level = IPPROTO_IPV6;
Simon Kelley26128d22004-11-14 16:43:54 +000091 }
Simon Kelley26128d22004-11-14 16:43:54 +000092 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +010093
Simon Kelleyff841eb2015-03-11 21:36:30 +000094 while (retry_send(sendmsg(fd, &msg, 0)));
95
96 /* If interface is still in DAD, EINVAL results - ignore that. */
97 if (errno != 0 && errno != EINVAL)
Simon Kelleyfeba5c12004-07-27 20:28:58 +010098 {
Simon Kelley50303b12012-04-04 22:13:17 +010099 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
Simon Kelley29689cf2012-03-22 14:01:00 +0000100 return 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100101 }
Simon Kelley29d28dd2012-12-03 14:05:59 +0000102
Simon Kelley29689cf2012-03-22 14:01:00 +0000103 return 1;
Simon Kelley44a2a312004-03-10 20:04:35 +0000104}
105
Simon Kelleycc921df2019-01-02 22:48:59 +0000106static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned int qtype,
Simon Kelley367341f2016-01-12 15:58:23 +0000107 char *qdomain, int *type, char **domain, int *norebind)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100108
109{
110 /* If the query ends in the domain in one of our servers, set
111 domain to point to that name. We find the largest match to allow both
112 domain.org and sub.domain.org to exist. */
113
114 unsigned int namelen = strlen(qdomain);
115 unsigned int matchlen = 0;
116 struct server *serv;
Simon Kelley28866e92011-02-14 20:19:14 +0000117 unsigned int flags = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +0000118 static union all_addr zero;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100119
Simon Kelley3be34542004-09-11 19:12:13 +0100120 for (serv = daemon->servers; serv; serv=serv->next)
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100121 if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
122 continue;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100123 /* domain matches take priority over NODOTS matches */
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100124 else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100125 {
Simon Kelley28866e92011-02-14 20:19:14 +0000126 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100127 *type = SERV_FOR_NODOTS;
Sung Paea914d0a2019-12-30 17:07:37 -0600128 if ((serv->flags & SERV_NO_REBIND) && norebind)
129 *norebind = 1;
130 else if (serv->flags & SERV_NO_ADDR)
Simon Kelley36717ee2004-09-20 19:20:58 +0100131 flags = F_NXDOMAIN;
Simon Kelleyda8b6512018-09-03 23:18:36 +0100132 else if (serv->flags & SERV_LITERAL_ADDRESS)
Simon Kelley36717ee2004-09-20 19:20:58 +0100133 {
Simon Kelleyda8b6512018-09-03 23:18:36 +0100134 /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
135 if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
136 {
137 memset(&zero, 0, sizeof(zero));
138 flags = qtype;
139 *addrpp = &zero;
140 }
141 else if (sflag & qtype)
Simon Kelley36717ee2004-09-20 19:20:58 +0100142 {
143 flags = sflag;
144 if (serv->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000145 *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
Simon Kelley36717ee2004-09-20 19:20:58 +0100146 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000147 *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelley36717ee2004-09-20 19:20:58 +0100148 }
Simon Kelley824af852008-02-12 20:43:05 +0000149 else if (!flags || (flags & F_NXDOMAIN))
Simon Kelley36717ee2004-09-20 19:20:58 +0100150 flags = F_NOERR;
151 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100152 }
153 else if (serv->flags & SERV_HAS_DOMAIN)
154 {
155 unsigned int domainlen = strlen(serv->domain);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000156 char *matchstart = qdomain + namelen - domainlen;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100157 if (namelen >= domainlen &&
Simon Kelleyb8187c82005-11-26 21:46:27 +0000158 hostname_isequal(matchstart, serv->domain) &&
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100159 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100160 {
Simon Kelley92be34a2016-01-16 18:39:54 +0000161 if ((serv->flags & SERV_NO_REBIND) && norebind)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100162 *norebind = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000163 else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100164 {
Simon Kelley28866e92011-02-14 20:19:14 +0000165 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
166 /* implement priority rules for --address and --server for same domain.
167 --address wins if the address is for the correct AF
168 --server wins otherwise. */
169 if (domainlen != 0 && domainlen == matchlen)
Simon Kelley36717ee2004-09-20 19:20:58 +0100170 {
Simon Kelley28866e92011-02-14 20:19:14 +0000171 if ((serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100172 {
Simon Kelley28866e92011-02-14 20:19:14 +0000173 if (!(sflag & qtype) && flags == 0)
174 continue;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100175 }
Simon Kelley28866e92011-02-14 20:19:14 +0000176 else
177 {
178 if (flags & (F_IPV4 | F_IPV6))
179 continue;
180 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100181 }
Simon Kelley28866e92011-02-14 20:19:14 +0000182
183 if (domainlen >= matchlen)
184 {
Simon Kelley367341f2016-01-12 15:58:23 +0000185 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
Simon Kelley28866e92011-02-14 20:19:14 +0000186 *domain = serv->domain;
187 matchlen = domainlen;
188 if (serv->flags & SERV_NO_ADDR)
189 flags = F_NXDOMAIN;
190 else if (serv->flags & SERV_LITERAL_ADDRESS)
191 {
Simon Kelleyda8b6512018-09-03 23:18:36 +0100192 /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
193 if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
194 {
195 memset(&zero, 0, sizeof(zero));
196 flags = qtype;
197 *addrpp = &zero;
198 }
199 else if (sflag & qtype)
Simon Kelley28866e92011-02-14 20:19:14 +0000200 {
201 flags = sflag;
202 if (serv->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000203 *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000204 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000205 *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000206 }
207 else if (!flags || (flags & F_NXDOMAIN))
208 flags = F_NOERR;
209 }
210 else
211 flags = 0;
212 }
213 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100214 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100215 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100216
Simon Kelleybf05f8f2017-05-09 22:37:46 +0100217 if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) &&
Simon Kelley28866e92011-02-14 20:19:14 +0000218 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
Simon Kelley7de060b2011-08-26 17:24:52 +0100219 /* don't forward A or AAAA queries for simple names, except the empty name */
220 flags = F_NOERR;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100221
Simon Kelley5aabfc72007-08-29 11:24:47 +0100222 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
Simon Kelleyc1bb8502004-08-11 18:40:17 +0100223 flags = F_NOERR;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100224
Simon Kelley824af852008-02-12 20:43:05 +0000225 if (flags)
226 {
Simon Kelleyc346f612018-09-04 21:14:18 +0100227 if (flags == F_NXDOMAIN || flags == F_NOERR)
228 log_query(flags | qtype | F_NEG | F_CONFIG | F_FORWARD, qdomain, NULL, NULL);
229 else
230 {
231 /* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */
232 if (flags & F_IPV4)
233 log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL);
Simon Kelleyc346f612018-09-04 21:14:18 +0100234 if (flags & F_IPV6)
235 log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL);
Simon Kelleyc346f612018-09-04 21:14:18 +0100236 }
Simon Kelley824af852008-02-12 20:43:05 +0000237 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100238 else if ((*type) & SERV_USE_RESOLV)
239 {
240 *type = 0; /* use normal servers for this domain */
241 *domain = NULL;
242 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100243 return flags;
244}
Simon Kelley44a2a312004-03-10 20:04:35 +0000245
Simon Kelley824af852008-02-12 20:43:05 +0000246static int forward_query(int udpfd, union mysockaddr *udpaddr,
Simon Kelleycc921df2019-01-02 22:48:59 +0000247 union all_addr *dst_addr, unsigned int dst_iface,
Simon Kelley83349b82014-02-10 21:02:01 +0000248 struct dns_header *header, size_t plen, time_t now,
Simon Kelley613ad152014-02-25 23:02:28 +0000249 struct frec *forward, int ad_reqd, int do_bit)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000250{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000251 char *domain = NULL;
Simon Kelley367341f2016-01-12 15:58:23 +0000252 int type = SERV_DO_DNSSEC, norebind = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +0000253 union all_addr *addrp = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000254 unsigned int flags = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100255 struct server *start = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000256#ifdef HAVE_DNSSEC
257 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley367341f2016-01-12 15:58:23 +0000258 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000259#else
260 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
261 void *hash = &crc;
262#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 Kelleyd05dd582016-01-19 21:23:30 +0000268 if (forward || (hash && (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)
348 forward = get_new_frec(now, NULL, 0);
349 /* 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 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100676 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;
769#ifndef HAVE_DNSSEC
770 unsigned int crc;
771#endif
772
Simon Kelleycdeda282006-03-16 20:16:06 +0000773 /* packet buffer overwritten */
774 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000775
Simon Kelleyde379512004-06-22 20:23:33 +0100776 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelleyee875042018-10-23 22:10:17 +0100777 if ((serveraddr.sa.sa_family = family) == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100778 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000779
Simon Kelley490f9072014-03-24 22:04:42 +0000780 header = (struct dns_header *)daemon->packet;
Simon Kelley6b173352018-05-08 18:32:14 +0100781
Simon Kelley490f9072014-03-24 22:04:42 +0000782 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
783 return;
784
Simon Kelley1a6bca82008-07-11 11:11:42 +0100785 /* spoof check: answer must come from known server, */
786 for (server = daemon->servers; server; server = server->next)
787 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
788 sockaddr_isequal(&server->addr, &serveraddr))
789 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000790
791 if (!server)
792 return;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000793
794 /* If sufficient time has elapsed, try and expand UDP buffer size again. */
795 if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
796 server->edns_pktsz = daemon->edns_pktsz;
797
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000798#ifdef HAVE_DNSSEC
799 hash = hash_questions(header, n, daemon->namebuff);
800#else
801 hash = &crc;
802 crc = questions_crc(header, n, daemon->namebuff);
803#endif
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100804
Simon Kelley490f9072014-03-24 22:04:42 +0000805 if (!(forward = lookup_frec(ntohs(header->id), hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100806 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000807
Simon Kelley6b173352018-05-08 18:32:14 +0100808#ifdef HAVE_DUMPFILE
809 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
810 (void *)header, n, &serveraddr, NULL);
811#endif
Simon Kelleya0088e82018-05-10 21:43:14 +0100812
Simon Kelley25cf5e32015-01-09 15:53:03 +0000813 /* log_query gets called indirectly all over the place, so
814 pass these in global variables - sorry. */
815 daemon->log_display_id = forward->log_id;
816 daemon->log_source_addr = &forward->source;
817
Glen Huang32fc6db2014-12-27 15:28:12 +0000818 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
819 check_for_ignored_address(header, n, daemon->ignore_addr))
820 return;
821
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000822 /* Note: if we send extra options in the EDNS0 header, we can't recreate
823 the query from the reply. */
Simon Kelley34e26e12018-05-10 20:54:57 +0100824 if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000825 forward->forwardall == 0 &&
826 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100827 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000828 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100829 unsigned char *pheader;
830 size_t plen;
831 int is_sign;
Simon Kelleyef3d1372017-12-05 22:37:29 +0000832
Simon Kelley1f60a182018-05-11 16:44:16 +0100833#ifdef HAVE_DNSSEC
Simon Kelleya0088e82018-05-10 21:43:14 +0100834 /* For DNSSEC originated queries, just retry the query to the same server. */
835 if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
836 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100837 struct server *start;
838
Simon Kelleya0088e82018-05-10 21:43:14 +0100839 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
840 plen = forward->stash_len;
841
842 forward->forwardall = 2; /* only retry once */
Simon Kelley1f60a182018-05-11 16:44:16 +0100843 start = forward->sentto;
844
845 /* for non-domain specific servers, see if we can find another to try. */
846 if ((forward->sentto->flags & SERV_TYPE) == 0)
847 while (1)
848 {
849 if (!(start = start->next))
850 start = daemon->servers;
851 if (start == forward->sentto)
852 break;
853
854 if ((start->flags & SERV_TYPE) == 0 &&
855 (start->flags & SERV_DO_DNSSEC))
856 break;
857 }
858
859
860 if (start->sfd)
861 fd = start->sfd->fd;
Simon Kelleya0088e82018-05-10 21:43:14 +0100862 else
863 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100864 if (start->addr.sa.sa_family == AF_INET6)
865 {
866 /* may have changed family */
867 if (!forward->rfd6)
868 forward->rfd6 = allocate_rfd(AF_INET6);
869 fd = forward->rfd6->fd;
870 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100871 else
Simon Kelley1f60a182018-05-11 16:44:16 +0100872 {
873 /* may have changed family */
874 if (!forward->rfd4)
875 forward->rfd4 = allocate_rfd(AF_INET);
876 fd = forward->rfd4->fd;
877 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100878 }
Simon Kelleye3002bf2019-10-11 23:30:08 +0100879
880#ifdef HAVE_DUMPFILE
881 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
882#endif
883
Simon Kelleya0088e82018-05-10 21:43:14 +0100884 while (retry_send(sendto(fd, (char *)header, plen, 0,
Simon Kelley1f60a182018-05-11 16:44:16 +0100885 &start->addr.sa,
886 sa_len(&start->addr))));
Simon Kelleya0088e82018-05-10 21:43:14 +0100887
Simon Kelleye27825b2018-05-11 17:20:47 +0100888 if (start->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000889 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 +0100890 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000891 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 +0100892
Simon Kelleya0088e82018-05-10 21:43:14 +0100893 return;
894 }
Simon Kelley1f60a182018-05-11 16:44:16 +0100895#endif
896
Simon Kelleyef3d1372017-12-05 22:37:29 +0000897 /* In strict order mode, there must be a server later in the chain
898 left to send to, otherwise without the forwardall mechanism,
899 code further on will cycle around the list forwever if they
900 all return REFUSED. Note that server is always non-NULL before
901 this executes. */
902 if (option_bool(OPT_ORDER))
903 for (server = forward->sentto->next; server; server = server->next)
904 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
905 break;
906
Simon Kelley1a6bca82008-07-11 11:11:42 +0100907 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000908 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelleyef3d1372017-12-05 22:37:29 +0000909 if (!is_sign && server)
Simon Kelley832af0b2007-01-21 20:01:28 +0000910 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100911 header->ancount = htons(0);
912 header->nscount = htons(0);
913 header->arcount = htons(0);
914 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
915 {
swiggerbd7bfa22015-06-01 20:54:59 +0100916 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000917 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000918 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000919 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000920 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000921 header->hb4 |= HB4_AD;
922 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000923 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000924 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 +0100925 return;
926 }
927 }
928 }
Simon Kelley3a237152013-12-12 12:15:50 +0000929
930 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100931 if ((forward->sentto->flags & SERV_TYPE) == 0)
932 {
Simon Kelley51967f92014-03-25 21:07:00 +0000933 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100934 server = NULL;
935 else
936 {
937 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000938
Simon Kelley1a6bca82008-07-11 11:11:42 +0100939 /* find good server by address if possible, otherwise assume the last one we sent to */
940 for (last_server = daemon->servers; last_server; last_server = last_server->next)
941 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
942 sockaddr_isequal(&last_server->addr, &serveraddr))
943 {
944 server = last_server;
945 break;
946 }
947 }
Simon Kelley28866e92011-02-14 20:19:14 +0000948 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100949 daemon->last_server = server;
950 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100951
952 /* We tried resending to this server with a smaller maximum size and got an answer.
Ville Skyttäfaaf3062018-01-14 17:32:52 +0000953 Make that permanent. To avoid reduxing the packet size for a single dropped packet,
Simon Kelley86fa1042015-05-10 13:50:59 +0100954 only do this when we get a truncated answer, or one larger than the safe size. */
Simon Kelley04db1482019-10-11 23:22:17 +0100955 if (forward->sentto->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
Simon Kelley86fa1042015-05-10 13:50:59 +0100956 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelley22dee512017-10-13 22:54:00 +0100957 {
Simon Kelley04db1482019-10-11 23:22:17 +0100958 forward->sentto->edns_pktsz = SAFE_PKTSZ;
959 forward->sentto->pktsz_reduced = now;
960 prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
Simon Kelleyebedcba2017-10-29 20:54:17 +0000961 my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
Simon Kelley22dee512017-10-13 22:54:00 +0100962 }
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000963
964
Simon Kelley1a6bca82008-07-11 11:11:42 +0100965 /* If the answer is an error, keep the forward record in place in case
966 we get a good reply from another server. Kill it when we've
967 had replies from all to avoid filling the forwarding table when
968 everything is broken */
Simon Kelley122392e2018-10-31 22:24:02 +0000969 if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100970 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100971 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleya6004d72017-10-25 17:48:19 +0100972
Simon Kelley3a237152013-12-12 12:15:50 +0000973 if (option_bool(OPT_NO_REBIND))
974 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100975
Simon Kelley3a237152013-12-12 12:15:50 +0000976 /* Don't cache replies where DNSSEC validation was turned off, either
977 the upstream server told us so, or the original query specified it. */
978 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
979 no_cache_dnssec = 1;
980
981#ifdef HAVE_DNSSEC
Simon Kelley04db1482019-10-11 23:22:17 +0100982 if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000983 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000984 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000985 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000986
987 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000988 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000989 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000990
991 /* Truncated answer can't be validated.
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100992 If this is an answer to a DNSSEC-generated query, we still
993 need to get the client to retry over TCP, so return
994 an answer with the TC bit set, even if the actual answer fits.
995 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000996 if (header->hb3 & HB3_TC)
997 status = STAT_TRUNCATED;
998
999 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001000 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001001 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
1002 would invite infinite loops, since the answers to DNSKEY and DS queries
1003 will not be cached, so they'll be repeated. */
1004 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001005 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001006 if (forward->flags & FREC_DNSKEY_QUERY)
1007 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1008 else if (forward->flags & FREC_DS_QUERY)
1009 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001010 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001011 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
Simon Kelley203ce0a2019-10-12 21:41:20 +01001012 !option_bool(OPT_DNSSEC_IGN_NS) && (forward->sentto->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001013 NULL, NULL, NULL);
Simon Kelley6b173352018-05-08 18:32:14 +01001014#ifdef HAVE_DUMPFILE
1015 if (status == STAT_BOGUS)
1016 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
1017 header, (size_t)n, &serveraddr, NULL);
1018#endif
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001019 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001020
Simon Kelley9a31b682015-12-15 10:20:39 +00001021 /* Can't validate, as we're missing key data. Put this
1022 answer aside, whilst we get that. */
1023 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +00001024 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001025 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +00001026
Simon Kelley9a31b682015-12-15 10:20:39 +00001027 /* Free any saved query */
1028 if (forward->stash)
1029 blockdata_free(forward->stash);
1030
1031 /* Now save reply pending receipt of key data */
1032 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +00001033 return;
Simon Kelley9a31b682015-12-15 10:20:39 +00001034 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001035
Simon Kelley9a31b682015-12-15 10:20:39 +00001036 /* Find the original query that started it all.... */
1037 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001038
Simon Kelley9a31b682015-12-15 10:20:39 +00001039 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
1040 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001041 else
Simon Kelley3a237152013-12-12 12:15:50 +00001042 {
Simon Kelleye1791f32018-10-06 23:23:23 +01001043 int querytype, fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +00001044 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +00001045 char *domain;
1046
Simon Kelley9a31b682015-12-15 10:20:39 +00001047 *new = *forward; /* copy everything, then overwrite */
1048 new->next = next;
1049 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +00001050
1051 /* Find server to forward to. This will normally be the
1052 same as for the original query, but may be another if
1053 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001054 if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
Simon Kelley92be34a2016-01-16 18:39:54 +00001055 {
Simon Kelley203ce0a2019-10-12 21:41:20 +01001056 struct server *start, *new_server = NULL;
1057 start = server = forward->sentto;
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001058
1059 while (1)
1060 {
1061 if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
Simon Kelley1f60a182018-05-11 16:44:16 +01001062 ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001063 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1064 {
1065 new_server = start;
1066 if (server == start)
1067 {
1068 new_server = NULL;
1069 break;
1070 }
1071 }
1072
1073 if (!(start = start->next))
1074 start = daemon->servers;
1075 if (start == server)
1076 break;
1077 }
1078
1079 if (new_server)
1080 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +00001081 }
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001082
Simon Kelley9a31b682015-12-15 10:20:39 +00001083 new->sentto = server;
1084 new->rfd4 = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001085 new->rfd6 = NULL;
Simon Kelleya0088e82018-05-10 21:43:14 +01001086 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
1087 new->forwardall = 0;
Simon Kelley9a31b682015-12-15 10:20:39 +00001088
1089 new->dependent = forward; /* to find query awaiting new one. */
1090 forward->blocking_query = new; /* for garbage cleaning */
1091 /* validate routines leave name of required record in daemon->keyname */
1092 if (status == STAT_NEED_KEY)
Simon Kelley7fa836e2014-02-10 20:11:24 +00001093 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001094 new->flags |= FREC_DNSKEY_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001095 querytype = T_DNSKEY;
Simon Kelleyf1668d22014-01-08 16:53:27 +00001096 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001097 else
1098 {
1099 new->flags |= FREC_DS_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001100 querytype = T_DS;
Simon Kelley9a31b682015-12-15 10:20:39 +00001101 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001102
1103 nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
1104 daemon->keyname, forward->class, querytype, server->edns_pktsz);
1105
1106 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001107 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 +01001108 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001109 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001110 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 +01001111 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001112
Simon Kelley9a31b682015-12-15 10:20:39 +00001113 if ((hash = hash_questions(header, nn, daemon->namebuff)))
1114 memcpy(new->hash, hash, HASH_SIZE);
1115 new->new_id = get_id();
1116 header->id = htons(new->new_id);
1117 /* Save query for retransmission */
1118 new->stash = blockdata_alloc((char *)header, nn);
1119 new->stash_len = nn;
1120
1121 /* Don't resend this. */
1122 daemon->srv_save = NULL;
1123
1124 if (server->sfd)
1125 fd = server->sfd->fd;
1126 else
1127 {
1128 fd = -1;
Simon Kelley9a31b682015-12-15 10:20:39 +00001129 if (server->addr.sa.sa_family == AF_INET6)
1130 {
1131 if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1132 fd = new->rfd6->fd;
1133 }
1134 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001135 {
1136 if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1137 fd = new->rfd4->fd;
1138 }
1139 }
1140
1141 if (fd != -1)
1142 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001143#ifdef HAVE_CONNTRACK
1144 /* Copy connection mark of incoming query to outgoing connection. */
1145 if (option_bool(OPT_CONNTRACK))
1146 {
1147 unsigned int mark;
1148 if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
1149 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1150 }
1151#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001152
1153#ifdef HAVE_DUMPFILE
1154 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
1155#endif
1156
Simon Kelley9a31b682015-12-15 10:20:39 +00001157 while (retry_send(sendto(fd, (char *)header, nn, 0,
1158 &server->addr.sa,
1159 sa_len(&server->addr))));
1160 server->queries++;
1161 }
1162 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001163 return;
Simon Kelley3a237152013-12-12 12:15:50 +00001164 }
Simon Kelley3a237152013-12-12 12:15:50 +00001165
Simon Kelley9a31b682015-12-15 10:20:39 +00001166 /* Validated original answer, all done. */
1167 if (!forward->dependent)
1168 break;
1169
Josh Soref730c6742017-02-06 16:14:04 +00001170 /* validated subsidiary query, (and cached result)
Simon Kelley9a31b682015-12-15 10:20:39 +00001171 pop that and return to the previous query we were working on. */
Simon Kelley0744ca62014-01-25 16:40:15 +00001172 struct frec *prev = forward->dependent;
1173 free_frec(forward);
1174 forward = prev;
1175 forward->blocking_query = NULL; /* already gone */
1176 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1177 n = forward->stash_len;
Simon Kelley3a237152013-12-12 12:15:50 +00001178 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001179
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001180
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001181 no_cache_dnssec = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001182
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001183 if (status == STAT_TRUNCATED)
Simon Kelley0744ca62014-01-25 16:40:15 +00001184 header->hb3 |= HB3_TC;
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001185 else
Simon Kelley7fa836e2014-02-10 20:11:24 +00001186 {
Simon Kelley554b5802015-04-17 22:50:20 +01001187 char *result, *domain = "result";
Simon Kelley7fa836e2014-02-10 20:11:24 +00001188
Simon Kelley9a31b682015-12-15 10:20:39 +00001189 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001190 {
1191 result = "ABANDONED";
1192 status = STAT_BOGUS;
1193 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001194 else
1195 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1196
Simon Kelley554b5802015-04-17 22:50:20 +01001197 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1198 domain = daemon->namebuff;
Simon Kelley9a31b682015-12-15 10:20:39 +00001199
Simon Kelley07ed5852018-05-04 21:52:22 +01001200 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001201 }
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001202
Simon Kelley3a237152013-12-12 12:15:50 +00001203 if (status == STAT_SECURE)
1204 cache_secure = 1;
Simon Kelley3a237152013-12-12 12:15:50 +00001205 else if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001206 {
1207 no_cache_dnssec = 1;
1208 bogusanswer = 1;
1209 }
Simon Kelley3a237152013-12-12 12:15:50 +00001210 }
Simon Kelley04db1482019-10-11 23:22:17 +01001211
Simon Kelley6b173352018-05-08 18:32:14 +01001212#endif
1213
Simon Kelley83349b82014-02-10 21:02:01 +00001214 /* restore CD bit to the value in the query */
1215 if (forward->flags & FREC_CHECKING_DISABLED)
1216 header->hb4 |= HB4_CD;
1217 else
1218 header->hb4 &= ~HB4_CD;
Simon Kelley3a237152013-12-12 12:15:50 +00001219
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001220 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 +00001221 forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1222 forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
Simon Kelley832af0b2007-01-21 20:01:28 +00001223 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001224 header->id = htons(forward->orig_id);
Simon Kelley572b41e2011-02-18 18:11:18 +00001225 header->hb4 |= HB4_RA; /* recursion if available */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001226#ifdef HAVE_DNSSEC
1227 /* 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 +01001228 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 +00001229 header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1230 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1231 {
1232 header->ancount = htons(0);
1233 header->nscount = htons(0);
1234 header->arcount = htons(0);
1235 header->hb3 |= HB3_TC;
1236 nn = resize_packet(header, nn, NULL, 0);
1237 }
1238#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001239
1240#ifdef HAVE_DUMPFILE
1241 dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
1242#endif
1243
Simon Kelley54dd3932012-06-20 11:23:38 +01001244 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
Simon Kelley50303b12012-04-04 22:13:17 +01001245 &forward->source, &forward->dest, forward->iface);
Simon Kelley832af0b2007-01-21 20:01:28 +00001246 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001247 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001248 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001249}
Simon Kelley44a2a312004-03-10 20:04:35 +00001250
Simon Kelley1a6bca82008-07-11 11:11:42 +01001251
Simon Kelley5aabfc72007-08-29 11:24:47 +01001252void receive_query(struct listener *listen, time_t now)
Simon Kelley44a2a312004-03-10 20:04:35 +00001253{
Simon Kelley572b41e2011-02-18 18:11:18 +00001254 struct dns_header *header = (struct dns_header *)daemon->packet;
Simon Kelley44a2a312004-03-10 20:04:35 +00001255 union mysockaddr source_addr;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001256 unsigned char *pheader;
1257 unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
Simon Kelleycc921df2019-01-02 22:48:59 +00001258 union all_addr dst_addr;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001259 struct in_addr netmask, dst_addr_4;
Simon Kelleycdeda282006-03-16 20:16:06 +00001260 size_t m;
1261 ssize_t n;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001262 int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001263#ifdef HAVE_AUTH
1264 int local_auth = 0;
1265#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001266 struct iovec iov[1];
1267 struct msghdr msg;
1268 struct cmsghdr *cmptr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001269 union {
1270 struct cmsghdr align; /* this ensures alignment */
Simon Kelley44a2a312004-03-10 20:04:35 +00001271 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001272#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +00001273 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
Simon Kelley824af852008-02-12 20:43:05 +00001274#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1275 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1276 CMSG_SPACE(sizeof(unsigned int))];
Simon Kelley44a2a312004-03-10 20:04:35 +00001277#elif defined(IP_RECVDSTADDR)
1278 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1279 CMSG_SPACE(sizeof(struct sockaddr_dl))];
1280#endif
1281 } control_u;
Simon Kelley2329bef2013-12-03 13:41:16 +00001282 /* Can always get recvd interface for IPv6 */
1283 int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
Simon Kelley2329bef2013-12-03 13:41:16 +00001284
Simon Kelleycdeda282006-03-16 20:16:06 +00001285 /* packet buffer overwritten */
1286 daemon->srv_save = NULL;
1287
Simon Kelleycc921df2019-01-02 22:48:59 +00001288 dst_addr_4.s_addr = dst_addr.addr4.s_addr = 0;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001289 netmask.s_addr = 0;
1290
Simon Kelley7e5664b2013-04-05 16:57:41 +01001291 if (option_bool(OPT_NOWILD) && listen->iface)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001292 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001293 auth_dns = listen->iface->dns_auth;
1294
1295 if (listen->family == AF_INET)
1296 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001297 dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001298 netmask = listen->iface->netmask;
1299 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001300 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001301
Simon Kelley3be34542004-09-11 19:12:13 +01001302 iov[0].iov_base = daemon->packet;
1303 iov[0].iov_len = daemon->edns_pktsz;
Simon Kelley44a2a312004-03-10 20:04:35 +00001304
1305 msg.msg_control = control_u.control;
1306 msg.msg_controllen = sizeof(control_u);
1307 msg.msg_flags = 0;
1308 msg.msg_name = &source_addr;
1309 msg.msg_namelen = sizeof(source_addr);
1310 msg.msg_iov = iov;
1311 msg.msg_iovlen = 1;
1312
Simon Kelleyde379512004-06-22 20:23:33 +01001313 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
Simon Kelley3be34542004-09-11 19:12:13 +01001314 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001315
Simon Kelley572b41e2011-02-18 18:11:18 +00001316 if (n < (int)sizeof(struct dns_header) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001317 (msg.msg_flags & MSG_TRUNC) ||
Simon Kelley572b41e2011-02-18 18:11:18 +00001318 (header->hb3 & HB3_QR))
Simon Kelley3be34542004-09-11 19:12:13 +01001319 return;
Simon Kelley63437ff2017-09-06 22:34:21 +01001320
1321 /* Clear buffer beyond request to avoid risk of
1322 information disclosure. */
1323 memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
Simon Kelley44a2a312004-03-10 20:04:35 +00001324
Simon Kelley26128d22004-11-14 16:43:54 +00001325 source_addr.sa.sa_family = listen->family;
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001326
1327 if (listen->family == AF_INET)
1328 {
1329 /* Source-port == 0 is an error, we can't send back to that.
1330 http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1331 if (source_addr.in.sin_port == 0)
1332 return;
1333 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001334 else
1335 {
1336 /* Source-port == 0 is an error, we can't send back to that. */
1337 if (source_addr.in6.sin6_port == 0)
1338 return;
1339 source_addr.in6.sin6_flowinfo = 0;
1340 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001341
Simon Kelleyc8a80482014-03-05 14:29:54 +00001342 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1343 if (option_bool(OPT_LOCAL_SERVICE))
1344 {
1345 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001346
Simon Kelleyc8a80482014-03-05 14:29:54 +00001347 if (listen->family == AF_INET6)
1348 {
1349 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1350 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001351 is_same_net6(&addr->addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001352 break;
1353 }
1354 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001355 {
1356 struct in_addr netmask;
1357 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1358 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001359 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001360 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001361 is_same_net(addr->addr.addr4, source_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001362 break;
1363 }
1364 }
1365 if (!addr)
1366 {
Simon Kelley0c8584e2014-03-12 20:12:56 +00001367 static int warned = 0;
1368 if (!warned)
1369 {
1370 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1371 warned = 1;
1372 }
Simon Kelleyc8a80482014-03-05 14:29:54 +00001373 return;
1374 }
1375 }
1376
Simon Kelley2329bef2013-12-03 13:41:16 +00001377 if (check_dst)
Simon Kelley44a2a312004-03-10 20:04:35 +00001378 {
Simon Kelley8a911cc2004-03-16 18:35:52 +00001379 struct ifreq ifr;
1380
Simon Kelley26128d22004-11-14 16:43:54 +00001381 if (msg.msg_controllen < sizeof(struct cmsghdr))
1382 return;
1383
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001384#if defined(HAVE_LINUX_NETWORK)
Simon Kelley26128d22004-11-14 16:43:54 +00001385 if (listen->family == AF_INET)
1386 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001387 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
Simon Kelley26128d22004-11-14 16:43:54 +00001388 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001389 union {
1390 unsigned char *c;
1391 struct in_pktinfo *p;
1392 } p;
1393 p.c = CMSG_DATA(cmptr);
Simon Kelleycc921df2019-01-02 22:48:59 +00001394 dst_addr_4 = dst_addr.addr4 = p.p->ipi_spec_dst;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001395 if_index = p.p->ipi_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001396 }
1397#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1398 if (listen->family == AF_INET)
1399 {
1400 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001401 {
1402 union {
1403 unsigned char *c;
1404 unsigned int *i;
1405 struct in_addr *a;
1406#ifndef HAVE_SOLARIS_NETWORK
1407 struct sockaddr_dl *s;
Simon Kelley824af852008-02-12 20:43:05 +00001408#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001409 } p;
1410 p.c = CMSG_DATA(cmptr);
1411 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
Simon Kelleycc921df2019-01-02 22:48:59 +00001412 dst_addr_4 = dst_addr.addr4 = *(p.a);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001413 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1414#ifdef HAVE_SOLARIS_NETWORK
1415 if_index = *(p.i);
1416#else
1417 if_index = p.s->sdl_index;
1418#endif
1419 }
Simon Kelley26128d22004-11-14 16:43:54 +00001420 }
1421#endif
1422
Simon Kelley26128d22004-11-14 16:43:54 +00001423 if (listen->family == AF_INET6)
1424 {
1425 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001426 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
Simon Kelley26128d22004-11-14 16:43:54 +00001427 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001428 union {
1429 unsigned char *c;
1430 struct in6_pktinfo *p;
1431 } p;
1432 p.c = CMSG_DATA(cmptr);
1433
Simon Kelleycc921df2019-01-02 22:48:59 +00001434 dst_addr.addr6 = p.p->ipi6_addr;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001435 if_index = p.p->ipi6_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001436 }
1437 }
Simon Kelley26128d22004-11-14 16:43:54 +00001438
1439 /* enforce available interface configuration */
1440
Simon Kelleye25db1f2013-01-29 22:10:26 +00001441 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
Simon Kelley832af0b2007-01-21 20:01:28 +00001442 return;
1443
Simon Kelleye25db1f2013-01-29 22:10:26 +00001444 if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
1445 {
1446 if (!option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001447 enumerate_interfaces(0);
Simon Kelley3f2873d2013-05-14 11:28:47 +01001448 if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
1449 !label_exception(if_index, listen->family, &dst_addr))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001450 return;
1451 }
1452
Simon Kelley552af8b2012-02-29 20:10:31 +00001453 if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
1454 {
1455 struct irec *iface;
1456
Josh Soref730c6742017-02-06 16:14:04 +00001457 /* get the netmask of the interface which has the address we were sent to.
klemens43517fc2017-02-19 15:53:37 +00001458 This is no necessarily the interface we arrived on. */
Simon Kelley552af8b2012-02-29 20:10:31 +00001459
1460 for (iface = daemon->interfaces; iface; iface = iface->next)
1461 if (iface->addr.sa.sa_family == AF_INET &&
1462 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1463 break;
1464
1465 /* interface may be new */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001466 if (!iface && !option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001467 enumerate_interfaces(0);
Simon Kelley552af8b2012-02-29 20:10:31 +00001468
1469 for (iface = daemon->interfaces; iface; iface = iface->next)
1470 if (iface->addr.sa.sa_family == AF_INET &&
1471 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1472 break;
1473
1474 /* If we failed, abandon localisation */
1475 if (iface)
1476 netmask = iface->netmask;
1477 else
1478 dst_addr_4.s_addr = 0;
1479 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001480 }
Simon Kelley25cf5e32015-01-09 15:53:03 +00001481
1482 /* log_query gets called indirectly all over the place, so
1483 pass these in global variables - sorry. */
1484 daemon->log_display_id = ++daemon->log_id;
1485 daemon->log_source_addr = &source_addr;
Simon Kelley6b173352018-05-08 18:32:14 +01001486
1487#ifdef HAVE_DUMPFILE
1488 dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
1489#endif
1490
Simon Kelleycdeda282006-03-16 20:16:06 +00001491 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
Simon Kelley44a2a312004-03-10 20:04:35 +00001492 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001493#ifdef HAVE_AUTH
1494 struct auth_zone *zone;
1495#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001496 char *types = querystr(auth_dns ? "auth" : "query", type);
1497
Simon Kelley44a2a312004-03-10 20:04:35 +00001498 if (listen->family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +01001499 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001500 (union all_addr *)&source_addr.in.sin_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001501 else
Simon Kelley3be34542004-09-11 19:12:13 +01001502 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001503 (union all_addr *)&source_addr.in6.sin6_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001504
Simon Kelley4820dce2012-12-18 18:30:30 +00001505#ifdef HAVE_AUTH
Simon Kelleyb485ed92013-10-18 22:00:39 +01001506 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001507 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001508 for (zone = daemon->auth_zones; zone; zone = zone->next)
1509 if (in_zone(zone, daemon->namebuff, NULL))
1510 {
1511 auth_dns = 1;
1512 local_auth = 1;
1513 break;
1514 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001515#endif
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001516
1517#ifdef HAVE_LOOP
1518 /* Check for forwarding loop */
1519 if (detect_loop(daemon->namebuff, type))
1520 return;
1521#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001522 }
1523
Simon Kelley5bb88f02015-12-21 16:23:47 +00001524 if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001525 {
1526 unsigned short flags;
1527
1528 have_pseudoheader = 1;
1529 GETSHORT(udp_size, pheader);
1530 pheader += 2; /* ext_rcode */
1531 GETSHORT(flags, pheader);
1532
1533 if (flags & 0x8000)
1534 do_bit = 1;/* do bit */
1535
1536 /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1537 (bounded by the maximum configured). If no EDNS0, then it
1538 defaults to 512 */
1539 if (udp_size > daemon->edns_pktsz)
1540 udp_size = daemon->edns_pktsz;
Simon Kelleya3303e12017-09-07 20:45:00 +01001541 else if (udp_size < PACKETSZ)
1542 udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001543 }
1544
Simon Kelleyb485ed92013-10-18 22:00:39 +01001545#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001546 if (auth_dns)
Simon Kelley824af852008-02-12 20:43:05 +00001547 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001548 m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1549 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001550 if (m >= 1)
Simon Kelleyb485ed92013-10-18 22:00:39 +01001551 {
1552 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1553 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001554 daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
Simon Kelleyb485ed92013-10-18 22:00:39 +01001555 }
Simon Kelley824af852008-02-12 20:43:05 +00001556 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001557 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001558#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001559 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001560 int ad_reqd = do_bit;
1561 /* RFC 6840 5.7 */
1562 if (header->hb4 & HB4_AD)
1563 ad_reqd = 1;
1564
1565 m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1566 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001567
1568 if (m >= 1)
1569 {
1570 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1571 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001572 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001573 }
1574 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
Simon Kelley613ad152014-02-25 23:02:28 +00001575 header, (size_t)n, now, NULL, ad_reqd, do_bit))
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001576 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001577 else
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001578 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001579 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001580}
1581
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001582#ifdef HAVE_DNSSEC
Josh Soref730c6742017-02-06 16:14:04 +00001583/* Recurse up the key hierarchy */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001584static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001585 int class, char *name, char *keyname, struct server *server,
1586 int have_mark, unsigned int mark, int *keycount)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001587{
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001588 int new_status;
Simon Kelley9a31b682015-12-15 10:20:39 +00001589 unsigned char *packet = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001590 unsigned char *payload = NULL;
1591 struct dns_header *new_header = NULL;
1592 u16 *length = NULL;
Simon Kelley361dfe52017-02-10 21:12:30 +00001593
Simon Kelley9a31b682015-12-15 10:20:39 +00001594 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001595 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001596 int type = SERV_DO_DNSSEC;
1597 char *domain;
1598 size_t m;
1599 unsigned char c1, c2;
Simon Kelley361dfe52017-02-10 21:12:30 +00001600 struct server *firstsendto = NULL;
1601
Simon Kelley9a31b682015-12-15 10:20:39 +00001602 /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1603 if (--(*keycount) == 0)
1604 new_status = STAT_ABANDONED;
1605 else if (status == STAT_NEED_KEY)
1606 new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1607 else if (status == STAT_NEED_DS)
1608 new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1609 else
James Bottomleye33b4872017-03-17 21:44:10 +00001610 new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
Simon Kelleya6918532018-04-15 16:20:52 +01001611 !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001612 NULL, NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001613
Simon Kelley9a31b682015-12-15 10:20:39 +00001614 if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1615 break;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001616
Simon Kelley9a31b682015-12-15 10:20:39 +00001617 /* Can't validate because we need a key/DS whose name now in keyname.
1618 Make query for same, and recurse to validate */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001619 if (!packet)
Simon Kelley9a31b682015-12-15 10:20:39 +00001620 {
1621 packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1622 payload = &packet[2];
1623 new_header = (struct dns_header *)payload;
1624 length = (u16 *)packet;
1625 }
1626
1627 if (!packet)
1628 {
1629 new_status = STAT_ABANDONED;
1630 break;
1631 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001632
Simon Kelley33702ab2015-12-28 23:17:15 +00001633 m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
Simon Kelleye1791f32018-10-06 23:23:23 +01001634 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, server->edns_pktsz);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001635
Simon Kelley7fa836e2014-02-10 20:11:24 +00001636 *length = htons(m);
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001637
1638 /* Find server to forward to. This will normally be the
1639 same as for the original query, but may be another if
1640 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001641 if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001642 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001643 new_status = STAT_ABANDONED;
1644 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001645 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001646
Simon Kelley361dfe52017-02-10 21:12:30 +00001647 while (1)
1648 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001649 int data_sent = 0;
1650
Simon Kelley361dfe52017-02-10 21:12:30 +00001651 if (!firstsendto)
1652 firstsendto = server;
1653 else
1654 {
1655 if (!(server = server->next))
1656 server = daemon->servers;
1657 if (server == firstsendto)
1658 {
1659 /* can't find server to accept our query. */
1660 new_status = STAT_ABANDONED;
1661 break;
1662 }
1663 }
1664
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001665 if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001666 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1667 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1668 continue;
Simon Kelleye1791f32018-10-06 23:23:23 +01001669
1670 retry:
1671 /* may need to make new connection. */
1672 if (server->tcpfd == -1)
1673 {
1674 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1675 continue; /* No good, next server */
1676
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001677#ifdef HAVE_CONNTRACK
Simon Kelleye1791f32018-10-06 23:23:23 +01001678 /* Copy connection mark of incoming query to outgoing connection. */
1679 if (have_mark)
1680 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001681#endif
Simon Kelleye1791f32018-10-06 23:23:23 +01001682
Simon Kelley608aa9f2019-03-10 22:44:15 +00001683 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1))
1684 {
1685 close(server->tcpfd);
1686 server->tcpfd = -1;
1687 continue; /* No good, next server */
1688 }
1689
1690#ifdef MSG_FASTOPEN
1691 while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
1692 MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
1693
1694 if (errno == 0)
1695 data_sent = 1;
1696#endif
1697
1698 if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
Simon Kelleye1791f32018-10-06 23:23:23 +01001699 {
1700 close(server->tcpfd);
1701 server->tcpfd = -1;
1702 continue; /* No good, next server */
1703 }
1704
1705 server->flags &= ~SERV_GOT_TCP;
1706 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001707
Simon Kelley608aa9f2019-03-10 22:44:15 +00001708 if ((!data_sent && !read_write(server->tcpfd, packet, m + sizeof(u16), 0)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001709 !read_write(server->tcpfd, &c1, 1, 1) ||
1710 !read_write(server->tcpfd, &c2, 1, 1) ||
1711 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1712 {
1713 close(server->tcpfd);
1714 server->tcpfd = -1;
1715 /* We get data then EOF, reopen connection to same server,
1716 else try next. This avoids DoS from a server which accepts
1717 connections and then closes them. */
1718 if (server->flags & SERV_GOT_TCP)
1719 goto retry;
1720 else
1721 continue;
1722 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001723
1724
1725 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001726 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (union all_addr *)&(server->addr.in.sin_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001727 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelleye1791f32018-10-06 23:23:23 +01001728 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001729 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001730 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelley361dfe52017-02-10 21:12:30 +00001731
1732 server->flags |= SERV_GOT_TCP;
1733
1734 m = (c1 << 8) | c2;
1735 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1736 break;
1737 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001738
1739 if (new_status != STAT_OK)
1740 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001741 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001742
Simon Kelley9a31b682015-12-15 10:20:39 +00001743 if (packet)
1744 free(packet);
1745
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001746 return new_status;
1747}
1748#endif
1749
1750
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001751/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001752 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001753 about resources for debug mode, when the fork is suppressed: that's
1754 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001755unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001756 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001757{
Simon Kelley28866e92011-02-14 20:19:14 +00001758 size_t size = 0;
1759 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001760#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001761 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001762#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001763 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001764 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001765 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001766 unsigned short qtype;
1767 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001768 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001769 /* Max TCP packet + slop + size */
1770 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1771 unsigned char *payload = &packet[2];
1772 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1773 struct dns_header *header = (struct dns_header *)payload;
1774 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001775 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001776 struct in_addr dst_addr_4;
1777 union mysockaddr peer_addr;
1778 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001779 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001780 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001781 unsigned int mark = 0;
1782 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001783
Simon Kelleyd05dd582016-01-19 21:23:30 +00001784 (void)mark;
1785 (void)have_mark;
1786
Simon Kelley7de060b2011-08-26 17:24:52 +01001787 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1788 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001789
1790#ifdef HAVE_CONNTRACK
1791 /* Get connection mark of incoming query to set on outgoing connections. */
1792 if (option_bool(OPT_CONNTRACK))
1793 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001794 union all_addr local;
Simon Kelleyee875042018-10-23 22:10:17 +01001795
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001796 if (local_addr->sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001797 local.addr6 = local_addr->in6.sin6_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001798 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001799 local.addr4 = local_addr->in.sin_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001800
1801 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1802 }
1803#endif
1804
Simon Kelleyc8a80482014-03-05 14:29:54 +00001805 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1806 if (option_bool(OPT_LOCAL_SERVICE))
1807 {
1808 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001809
Simon Kelleyc8a80482014-03-05 14:29:54 +00001810 if (peer_addr.sa.sa_family == AF_INET6)
1811 {
1812 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1813 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001814 is_same_net6(&addr->addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001815 break;
1816 }
1817 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001818 {
1819 struct in_addr netmask;
1820 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1821 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001822 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001823 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001824 is_same_net(addr->addr.addr4, peer_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001825 break;
1826 }
1827 }
1828 if (!addr)
1829 {
1830 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1831 return packet;
1832 }
1833 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001834
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001835 while (1)
1836 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001837 if (query_count == TCP_MAX_QUERIES ||
1838 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001839 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1840 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001841 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001842 return packet;
1843
Simon Kelley572b41e2011-02-18 18:11:18 +00001844 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001845 continue;
Simon Kelley63437ff2017-09-06 22:34:21 +01001846
1847 /* Clear buffer beyond request to avoid risk of
1848 information disclosure. */
1849 memset(payload + size, 0, 65536 - size);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001850
Simon Kelley25cf5e32015-01-09 15:53:03 +00001851 query_count++;
1852
1853 /* log_query gets called indirectly all over the place, so
1854 pass these in global variables - sorry. */
1855 daemon->log_display_id = ++daemon->log_id;
1856 daemon->log_source_addr = &peer_addr;
1857
Simon Kelley28866e92011-02-14 20:19:14 +00001858 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001859 if ((checking_disabled = header->hb4 & HB4_CD))
1860 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001861
Simon Kelley3be34542004-09-11 19:12:13 +01001862 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001863 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001864#ifdef HAVE_AUTH
1865 struct auth_zone *zone;
1866#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001867 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001868
1869 if (peer_addr.sa.sa_family == AF_INET)
1870 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001871 (union all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelley7de060b2011-08-26 17:24:52 +01001872 else
1873 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001874 (union all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001875
1876#ifdef HAVE_AUTH
1877 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001878 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001879 for (zone = daemon->auth_zones; zone; zone = zone->next)
1880 if (in_zone(zone, daemon->namebuff, NULL))
1881 {
1882 auth_dns = 1;
1883 local_auth = 1;
1884 break;
1885 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001886#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001887 }
1888
Simon Kelley7de060b2011-08-26 17:24:52 +01001889 if (local_addr->sa.sa_family == AF_INET)
1890 dst_addr_4 = local_addr->in.sin_addr;
1891 else
1892 dst_addr_4.s_addr = 0;
1893
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001894 do_bit = 0;
1895
Simon Kelley5bb88f02015-12-21 16:23:47 +00001896 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001897 {
1898 unsigned short flags;
1899
1900 have_pseudoheader = 1;
1901 pheader += 4; /* udp_size, ext_rcode */
1902 GETSHORT(flags, pheader);
1903
1904 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001905 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001906 }
1907
Simon Kelley4820dce2012-12-18 18:30:30 +00001908#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001909 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001910 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1911 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001912 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001913#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001914 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001915 int ad_reqd = do_bit;
1916 /* RFC 6840 5.7 */
1917 if (header->hb4 & HB4_AD)
1918 ad_reqd = 1;
1919
1920 /* m > 0 if answered from cache */
1921 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1922 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001923
Simon Kelley4f7b3042012-11-28 21:27:02 +00001924 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001925 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001926
1927 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001928 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001929 unsigned int flags = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +00001930 union all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001931 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001932 char *domain = NULL;
Simon Kelley6fd5d792017-10-13 22:26:40 +01001933 unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
Simon Kelleyed4c0762013-10-08 20:46:34 +01001934
Simon Kelley6fd5d792017-10-13 22:26:40 +01001935 size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
1936
Simon Kelley4f7b3042012-11-28 21:27:02 +00001937 if (gotname)
1938 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley6fd5d792017-10-13 22:26:40 +01001939
1940#ifdef HAVE_DNSSEC
1941 if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
1942 {
1943 size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1944
1945 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1946 this allows it to select auth servers when one is returning bad data. */
1947 if (option_bool(OPT_DNSSEC_DEBUG))
1948 header->hb4 |= HB4_CD;
1949 }
1950#endif
1951
1952 /* Check if we added a pheader on forwarding - may need to
1953 strip it from the reply. */
1954 if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
1955 added_pheader = 1;
1956
Simon Kelley367341f2016-01-12 15:58:23 +00001957 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001958
Simon Kelley4f7b3042012-11-28 21:27:02 +00001959 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1960 last_server = daemon->servers;
1961 else
1962 last_server = daemon->last_server;
1963
1964 if (!flags && last_server)
1965 {
1966 struct server *firstsendto = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001967#ifdef HAVE_DNSSEC
Simon Kelley703c7ff2014-01-25 23:46:23 +00001968 unsigned char *newhash, hash[HASH_SIZE];
Simon Kelley63758382014-04-16 22:20:55 +01001969 if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001970 memcpy(hash, newhash, HASH_SIZE);
Tomas Hozzab37f8b92014-03-25 20:52:28 +00001971 else
1972 memset(hash, 0, HASH_SIZE);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001973#else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001974 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001975#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001976 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001977 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001978 which can go to the same server, do so. */
1979 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001980 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001981 int data_sent = 0;
1982
Simon Kelley4f7b3042012-11-28 21:27:02 +00001983 if (!firstsendto)
1984 firstsendto = last_server;
1985 else
1986 {
1987 if (!(last_server = last_server->next))
1988 last_server = daemon->servers;
1989
1990 if (last_server == firstsendto)
1991 break;
1992 }
1993
1994 /* server for wrong domain */
1995 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001996 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
1997 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01001998 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00001999
2000 retry:
Simon Kelley608aa9f2019-03-10 22:44:15 +00002001 *length = htons(size);
2002
Simon Kelley4f7b3042012-11-28 21:27:02 +00002003 if (last_server->tcpfd == -1)
2004 {
2005 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
2006 continue;
2007
Karl Vogele9828b62014-10-03 21:45:15 +01002008#ifdef HAVE_CONNTRACK
2009 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002010 if (have_mark)
2011 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley608aa9f2019-03-10 22:44:15 +00002012#endif
Karl Vogele9828b62014-10-03 21:45:15 +01002013
Simon Kelley608aa9f2019-03-10 22:44:15 +00002014 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1)))
2015 {
2016 close(last_server->tcpfd);
2017 last_server->tcpfd = -1;
2018 continue;
2019 }
2020
2021#ifdef MSG_FASTOPEN
2022 while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
2023 MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
2024
2025 if (errno == 0)
2026 data_sent = 1;
2027#endif
2028
2029 if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
Simon Kelley4f7b3042012-11-28 21:27:02 +00002030 {
2031 close(last_server->tcpfd);
2032 last_server->tcpfd = -1;
2033 continue;
2034 }
2035
Simon Kelley361dfe52017-02-10 21:12:30 +00002036 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002037 }
2038
Simon Kelley1fc02682014-04-29 12:30:18 +01002039 /* get query name again for logging - may have been overwritten */
2040 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
2041 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00002042
Simon Kelley608aa9f2019-03-10 22:44:15 +00002043 if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00002044 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002045 !read_write(last_server->tcpfd, &c2, 1, 1) ||
2046 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01002047 {
2048 close(last_server->tcpfd);
2049 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00002050 /* We get data then EOF, reopen connection to same server,
2051 else try next. This avoids DoS from a server which accepts
2052 connections and then closes them. */
2053 if (last_server->flags & SERV_GOT_TCP)
2054 goto retry;
2055 else
2056 continue;
2057 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002058
Simon Kelley361dfe52017-02-10 21:12:30 +00002059 last_server->flags |= SERV_GOT_TCP;
2060
Simon Kelley4f7b3042012-11-28 21:27:02 +00002061 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002062
Simon Kelley4f7b3042012-11-28 21:27:02 +00002063 if (last_server->addr.sa.sa_family == AF_INET)
2064 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002065 (union all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002066 else
2067 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002068 (union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002069
2070#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00002071 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002072 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00002073 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002074 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
2075 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01002076 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002077
Simon Kelley9a31b682015-12-15 10:20:39 +00002078 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00002079 {
2080 result = "ABANDONED";
2081 status = STAT_BOGUS;
2082 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00002083 else
2084 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01002085
2086 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
2087 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01002088
Simon Kelley07ed5852018-05-04 21:52:22 +01002089 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00002090
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002091 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002092 {
2093 no_cache_dnssec = 1;
2094 bogusanswer = 1;
2095 }
2096
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002097 if (status == STAT_SECURE)
2098 cache_secure = 1;
2099 }
2100#endif
2101
2102 /* restore CD bit to the value in the query */
2103 if (checking_disabled)
2104 header->hb4 |= HB4_CD;
2105 else
2106 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002107
2108 /* There's no point in updating the cache, since this process will exit and
2109 lose the information after a few queries. We make this call for the alias and
2110 bogus-nxdomain side-effects. */
2111 /* If the crc of the question section doesn't match the crc we sent, then
2112 someone might be attempting to insert bogus values into the cache by
2113 sending replies containing questions and bogus answers. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002114#ifdef HAVE_DNSSEC
2115 newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
2116 if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00002117 {
2118 m = 0;
2119 break;
2120 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002121#else
2122 if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
Simon Kelley703c7ff2014-01-25 23:46:23 +00002123 {
2124 m = 0;
2125 break;
2126 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002127#endif
2128
2129 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01002130 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00002131 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002132
2133 break;
2134 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002135 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002136
2137 /* In case of local answer or no connections made. */
2138 if (m == 0)
Simon Kelley1682d152018-08-03 20:38:18 +01002139 {
2140 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
2141 if (have_pseudoheader)
2142 m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
2143 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002144 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002145 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002146
Simon Kelleyb842bc92015-07-12 21:09:11 +01002147 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002148
Simon Kelley4b5ea122013-04-22 10:18:26 +01002149 *length = htons(m);
2150
2151 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002152 return packet;
2153 }
2154}
2155
Simon Kelley16972692006-10-16 20:04:18 +01002156static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002157{
Simon Kelley16972692006-10-16 20:04:18 +01002158 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002159
Simon Kelley5aabfc72007-08-29 11:24:47 +01002160 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002161 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002162 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002163 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00002164 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002165 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002166 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002167 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002168#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002169 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002170 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002171 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002172#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002173 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002174 }
Simon Kelley16972692006-10-16 20:04:18 +01002175
2176 return f;
2177}
2178
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002179struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002180{
2181 static int finger = 0;
2182 int i;
2183
2184 /* limit the number of sockets we have open to avoid starvation of
2185 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2186
2187 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002188 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002189 {
Simon Kelley9009d742008-11-14 20:04:27 +00002190 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2191 break;
2192
Simon Kelley1a6bca82008-07-11 11:11:42 +01002193 daemon->randomsocks[i].refcount = 1;
2194 daemon->randomsocks[i].family = family;
2195 return &daemon->randomsocks[i];
2196 }
2197
Simon Kelley9009d742008-11-14 20:04:27 +00002198 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002199 for (i = 0; i < RANDOM_SOCKS; i++)
2200 {
2201 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002202 if (daemon->randomsocks[j].refcount != 0 &&
2203 daemon->randomsocks[j].family == family &&
2204 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002205 {
2206 finger = j;
2207 daemon->randomsocks[j].refcount++;
2208 return &daemon->randomsocks[j];
2209 }
2210 }
2211
2212 return NULL; /* doom */
2213}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002214
2215void free_rfd(struct randfd *rfd)
2216{
2217 if (rfd && --(rfd->refcount) == 0)
2218 close(rfd->fd);
2219}
2220
Simon Kelley1a6bca82008-07-11 11:11:42 +01002221static void free_frec(struct frec *f)
2222{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002223 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002224 f->rfd4 = NULL;
2225 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002226 f->flags = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002227 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002228 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002229
2230#ifdef HAVE_DNSSEC
2231 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002232 {
2233 blockdata_free(f->stash);
2234 f->stash = NULL;
2235 }
Simon Kelley3a237152013-12-12 12:15:50 +00002236
2237 /* Anything we're waiting on is pointless now, too */
2238 if (f->blocking_query)
2239 free_frec(f->blocking_query);
2240 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002241 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002242#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002243}
2244
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002245
2246
Simon Kelley16972692006-10-16 20:04:18 +01002247/* if wait==NULL return a free or older than TIMEOUT record.
2248 else return *wait zero if one available, or *wait is delay to
Simon Kelley1a6bca82008-07-11 11:11:42 +01002249 when the oldest in-use record will expire. Impose an absolute
Simon Kelley3a237152013-12-12 12:15:50 +00002250 limit of 4*TIMEOUT before we wipe things (for random sockets).
2251 If force is set, always return a result, even if we have
2252 to allocate above the limit. */
2253struct frec *get_new_frec(time_t now, int *wait, int force)
Simon Kelley16972692006-10-16 20:04:18 +01002254{
Simon Kelley1a6bca82008-07-11 11:11:42 +01002255 struct frec *f, *oldest, *target;
Simon Kelley16972692006-10-16 20:04:18 +01002256 int count;
2257
2258 if (wait)
2259 *wait = 0;
2260
Simon Kelley1a6bca82008-07-11 11:11:42 +01002261 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
Simon Kelley832af0b2007-01-21 20:01:28 +00002262 if (!f->sentto)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002263 target = f;
2264 else
Simon Kelley16972692006-10-16 20:04:18 +01002265 {
Simon Kelley9a31b682015-12-15 10:20:39 +00002266#ifdef HAVE_DNSSEC
2267 /* Don't free DNSSEC sub-queries here, as we may end up with
2268 dangling references to them. They'll go when their "real" query
2269 is freed. */
2270 if (!f->dependent)
2271#endif
2272 {
2273 if (difftime(now, f->time) >= 4*TIMEOUT)
2274 {
2275 free_frec(f);
2276 target = f;
2277 }
2278
2279
2280 if (!oldest || difftime(f->time, oldest->time) <= 0)
2281 oldest = f;
2282 }
Simon Kelley16972692006-10-16 20:04:18 +01002283 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01002284
2285 if (target)
2286 {
2287 target->time = now;
2288 return target;
2289 }
Simon Kelley16972692006-10-16 20:04:18 +01002290
2291 /* can't find empty one, use oldest if there is one
2292 and it's older than timeout */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002293 if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
Simon Kelley16972692006-10-16 20:04:18 +01002294 {
2295 /* keep stuff for twice timeout if we can by allocating a new
2296 record instead */
2297 if (difftime(now, oldest->time) < 2*TIMEOUT &&
2298 count <= daemon->ftabsize &&
2299 (f = allocate_frec(now)))
2300 return f;
2301
2302 if (!wait)
2303 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002304 free_frec(oldest);
Simon Kelley16972692006-10-16 20:04:18 +01002305 oldest->time = now;
2306 }
2307 return oldest;
2308 }
2309
2310 /* none available, calculate time 'till oldest record expires */
Simon Kelley3a237152013-12-12 12:15:50 +00002311 if (!force && count > daemon->ftabsize)
Simon Kelley16972692006-10-16 20:04:18 +01002312 {
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002313 static time_t last_log = 0;
2314
Simon Kelley16972692006-10-16 20:04:18 +01002315 if (oldest && wait)
2316 *wait = oldest->time + (time_t)TIMEOUT - now;
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002317
2318 if ((int)difftime(now, last_log) > 5)
2319 {
2320 last_log = now;
2321 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2322 }
2323
Simon Kelley16972692006-10-16 20:04:18 +01002324 return NULL;
2325 }
2326
2327 if (!(f = allocate_frec(now)) && wait)
2328 /* wait one second on malloc failure */
2329 *wait = 1;
2330
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002331 return f; /* OK if malloc fails and this is NULL */
2332}
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002333
Simon Kelley832af0b2007-01-21 20:01:28 +00002334/* crc is all-ones if not known. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002335static struct frec *lookup_frec(unsigned short id, void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002336{
2337 struct frec *f;
2338
Simon Kelley1a6bca82008-07-11 11:11:42 +01002339 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002340 if (f->sentto && f->new_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002341 (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002342 return f;
2343
2344 return NULL;
2345}
2346
2347static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002348 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002349 void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002350{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002351 struct frec *f;
2352
Simon Kelley1a6bca82008-07-11 11:11:42 +01002353 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002354 if (f->sentto &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002355 f->orig_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002356 memcmp(hash, f->hash, HASH_SIZE) == 0 &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002357 sockaddr_isequal(&f->source, addr))
2358 return f;
2359
2360 return NULL;
2361}
Simon Kelley47a95162014-07-08 22:22:02 +01002362
2363/* Send query packet again, if we can. */
2364void resend_query()
2365{
2366 if (daemon->srv_save)
2367 {
2368 int fd;
2369
2370 if (daemon->srv_save->sfd)
2371 fd = daemon->srv_save->sfd->fd;
2372 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2373 fd = daemon->rfd_save->fd;
2374 else
2375 return;
2376
Simon Kelleyff841eb2015-03-11 21:36:30 +00002377 while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2378 &daemon->srv_save->addr.sa,
2379 sa_len(&daemon->srv_save->addr))));
Simon Kelley47a95162014-07-08 22:22:02 +01002380 }
2381}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002382
Simon Kelley849a8352006-06-09 21:02:31 +01002383/* A server record is going away, remove references to it */
Simon Kelley5aabfc72007-08-29 11:24:47 +01002384void server_gone(struct server *server)
Simon Kelley849a8352006-06-09 21:02:31 +01002385{
2386 struct frec *f;
2387
Simon Kelley1a6bca82008-07-11 11:11:42 +01002388 for (f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002389 if (f->sentto && f->sentto == server)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002390 free_frec(f);
Simon Kelley849a8352006-06-09 21:02:31 +01002391
2392 if (daemon->last_server == server)
2393 daemon->last_server = NULL;
2394
2395 if (daemon->srv_save == server)
2396 daemon->srv_save = NULL;
2397}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002398
Simon Kelley316e2732010-01-22 20:16:09 +00002399/* return unique random ids. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002400static unsigned short get_id(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002401{
2402 unsigned short ret = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +00002403
Simon Kelley316e2732010-01-22 20:16:09 +00002404 do
Simon Kelley832af0b2007-01-21 20:01:28 +00002405 ret = rand16();
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002406 while (lookup_frec(ret, NULL));
Simon Kelley832af0b2007-01-21 20:01:28 +00002407
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002408 return ret;
2409}
2410
2411
2412
2413
2414