blob: a2a7bc7d920f8cfaf617f0bf2e7cabd7cf64800a [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 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;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100128 if (serv->flags & SERV_NO_ADDR)
Simon Kelley36717ee2004-09-20 19:20:58 +0100129 flags = F_NXDOMAIN;
Simon Kelleyda8b6512018-09-03 23:18:36 +0100130 else if (serv->flags & SERV_LITERAL_ADDRESS)
Simon Kelley36717ee2004-09-20 19:20:58 +0100131 {
Simon Kelleyda8b6512018-09-03 23:18:36 +0100132 /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
133 if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
134 {
135 memset(&zero, 0, sizeof(zero));
136 flags = qtype;
137 *addrpp = &zero;
138 }
139 else if (sflag & qtype)
Simon Kelley36717ee2004-09-20 19:20:58 +0100140 {
141 flags = sflag;
142 if (serv->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000143 *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
Simon Kelley36717ee2004-09-20 19:20:58 +0100144 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000145 *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelley36717ee2004-09-20 19:20:58 +0100146 }
Simon Kelley824af852008-02-12 20:43:05 +0000147 else if (!flags || (flags & F_NXDOMAIN))
Simon Kelley36717ee2004-09-20 19:20:58 +0100148 flags = F_NOERR;
149 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100150 }
151 else if (serv->flags & SERV_HAS_DOMAIN)
152 {
153 unsigned int domainlen = strlen(serv->domain);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000154 char *matchstart = qdomain + namelen - domainlen;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100155 if (namelen >= domainlen &&
Simon Kelleyb8187c82005-11-26 21:46:27 +0000156 hostname_isequal(matchstart, serv->domain) &&
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100157 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100158 {
Simon Kelley92be34a2016-01-16 18:39:54 +0000159 if ((serv->flags & SERV_NO_REBIND) && norebind)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100160 *norebind = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000161 else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100162 {
Simon Kelley28866e92011-02-14 20:19:14 +0000163 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
164 /* implement priority rules for --address and --server for same domain.
165 --address wins if the address is for the correct AF
166 --server wins otherwise. */
167 if (domainlen != 0 && domainlen == matchlen)
Simon Kelley36717ee2004-09-20 19:20:58 +0100168 {
Simon Kelley28866e92011-02-14 20:19:14 +0000169 if ((serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100170 {
Simon Kelley28866e92011-02-14 20:19:14 +0000171 if (!(sflag & qtype) && flags == 0)
172 continue;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100173 }
Simon Kelley28866e92011-02-14 20:19:14 +0000174 else
175 {
176 if (flags & (F_IPV4 | F_IPV6))
177 continue;
178 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100179 }
Simon Kelley28866e92011-02-14 20:19:14 +0000180
181 if (domainlen >= matchlen)
182 {
Simon Kelley367341f2016-01-12 15:58:23 +0000183 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
Simon Kelley28866e92011-02-14 20:19:14 +0000184 *domain = serv->domain;
185 matchlen = domainlen;
186 if (serv->flags & SERV_NO_ADDR)
187 flags = F_NXDOMAIN;
188 else if (serv->flags & SERV_LITERAL_ADDRESS)
189 {
Simon Kelleyda8b6512018-09-03 23:18:36 +0100190 /* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
191 if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
192 {
193 memset(&zero, 0, sizeof(zero));
194 flags = qtype;
195 *addrpp = &zero;
196 }
197 else if (sflag & qtype)
Simon Kelley28866e92011-02-14 20:19:14 +0000198 {
199 flags = sflag;
200 if (serv->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000201 *addrpp = (union all_addr *)&serv->addr.in.sin_addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000202 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000203 *addrpp = (union all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000204 }
205 else if (!flags || (flags & F_NXDOMAIN))
206 flags = F_NOERR;
207 }
208 else
209 flags = 0;
210 }
211 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100212 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100213 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100214
Simon Kelleybf05f8f2017-05-09 22:37:46 +0100215 if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) &&
Simon Kelley28866e92011-02-14 20:19:14 +0000216 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
Simon Kelley7de060b2011-08-26 17:24:52 +0100217 /* don't forward A or AAAA queries for simple names, except the empty name */
218 flags = F_NOERR;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100219
Simon Kelley5aabfc72007-08-29 11:24:47 +0100220 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
Simon Kelleyc1bb8502004-08-11 18:40:17 +0100221 flags = F_NOERR;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100222
Simon Kelley824af852008-02-12 20:43:05 +0000223 if (flags)
224 {
Simon Kelleyc346f612018-09-04 21:14:18 +0100225 if (flags == F_NXDOMAIN || flags == F_NOERR)
226 log_query(flags | qtype | F_NEG | F_CONFIG | F_FORWARD, qdomain, NULL, NULL);
227 else
228 {
229 /* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */
230 if (flags & F_IPV4)
231 log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL);
Simon Kelleyc346f612018-09-04 21:14:18 +0100232 if (flags & F_IPV6)
233 log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL);
Simon Kelleyc346f612018-09-04 21:14:18 +0100234 }
Simon Kelley824af852008-02-12 20:43:05 +0000235 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100236 else if ((*type) & SERV_USE_RESOLV)
237 {
238 *type = 0; /* use normal servers for this domain */
239 *domain = NULL;
240 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100241 return flags;
242}
Simon Kelley44a2a312004-03-10 20:04:35 +0000243
Simon Kelley824af852008-02-12 20:43:05 +0000244static int forward_query(int udpfd, union mysockaddr *udpaddr,
Simon Kelleycc921df2019-01-02 22:48:59 +0000245 union all_addr *dst_addr, unsigned int dst_iface,
Simon Kelley83349b82014-02-10 21:02:01 +0000246 struct dns_header *header, size_t plen, time_t now,
Simon Kelley613ad152014-02-25 23:02:28 +0000247 struct frec *forward, int ad_reqd, int do_bit)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000248{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000249 char *domain = NULL;
Simon Kelley367341f2016-01-12 15:58:23 +0000250 int type = SERV_DO_DNSSEC, norebind = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +0000251 union all_addr *addrp = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000252 unsigned int flags = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100253 struct server *start = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000254#ifdef HAVE_DNSSEC
255 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley367341f2016-01-12 15:58:23 +0000256 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000257#else
258 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
259 void *hash = &crc;
260#endif
Simon Kelley1682d152018-08-03 20:38:18 +0100261 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
262 unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
263 (void)do_bit;
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000264
Simon Kelley3d8df262005-08-29 12:19:27 +0100265 /* may be no servers available. */
Simon Kelleyd05dd582016-01-19 21:23:30 +0000266 if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000267 {
Simon Kelleya77cec82015-05-08 16:25:38 +0100268 /* If we didn't get an answer advertising a maximal packet in EDNS,
269 fall back to 1280, which should work everywhere on IPv6.
270 If that generates an answer, it will become the new default
271 for this server */
272 forward->flags |= FREC_TEST_PKTSZ;
273
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000274#ifdef HAVE_DNSSEC
Simon Kelleydac74312014-02-13 16:43:49 +0000275 /* If we've already got an answer to this query, but we're awaiting keys for validation,
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000276 there's no point retrying the query, retry the key query instead...... */
277 if (forward->blocking_query)
278 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000279 int fd, is_sign;
280 unsigned char *pheader;
Simon Kelleya77cec82015-05-08 16:25:38 +0100281
282 forward->flags &= ~FREC_TEST_PKTSZ;
283
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000284 while (forward->blocking_query)
285 forward = forward->blocking_query;
Simon Kelleya77cec82015-05-08 16:25:38 +0100286
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000287 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
288 plen = forward->stash_len;
289
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000290 forward->flags |= FREC_TEST_PKTSZ;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000291 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000292 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000293
Simon Kelley2b291912014-03-21 11:13:55 +0000294 if (forward->sentto->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000295 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 +0000296 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000297 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 +0100298
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000299
300 if (forward->sentto->sfd)
301 fd = forward->sentto->sfd->fd;
302 else
303 {
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000304 if (forward->sentto->addr.sa.sa_family == AF_INET6)
305 fd = forward->rfd6->fd;
306 else
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000307 fd = forward->rfd4->fd;
308 }
309
Simon Kelleya0088e82018-05-10 21:43:14 +0100310 while (retry_send(sendto(fd, (char *)header, plen, 0,
311 &forward->sentto->addr.sa,
312 sa_len(&forward->sentto->addr))));
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000313
314 return 1;
315 }
316#endif
317
Simon Kelleyde379512004-06-22 20:23:33 +0100318 /* retry on existing query, send to all available servers */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000319 domain = forward->sentto->domain;
Simon Kelley824af852008-02-12 20:43:05 +0000320 forward->sentto->failed_queries++;
Simon Kelley28866e92011-02-14 20:19:14 +0000321 if (!option_bool(OPT_ORDER))
Simon Kelleyde379512004-06-22 20:23:33 +0100322 {
Simon Kelley0a852542005-03-23 20:28:59 +0000323 forward->forwardall = 1;
Simon Kelley3be34542004-09-11 19:12:13 +0100324 daemon->last_server = NULL;
Simon Kelleyde379512004-06-22 20:23:33 +0100325 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000326 type = forward->sentto->flags & SERV_TYPE;
Simon Kelley367341f2016-01-12 15:58:23 +0000327#ifdef HAVE_DNSSEC
328 do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
329#endif
330
Simon Kelleyde379512004-06-22 20:23:33 +0100331 if (!(start = forward->sentto->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100332 start = daemon->servers; /* at end of list, recycle */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000333 header->id = htons(forward->new_id);
334 }
335 else
336 {
337 if (gotname)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100338 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000339
Simon Kelley367341f2016-01-12 15:58:23 +0000340#ifdef HAVE_DNSSEC
341 do_dnssec = type & SERV_DO_DNSSEC;
Simon Kelleyf7443d72016-01-19 20:29:57 +0000342#endif
343 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +0000344
Simon Kelleyd05dd582016-01-19 21:23:30 +0000345 if (daemon->servers && !flags)
346 forward = get_new_frec(now, NULL, 0);
347 /* table full - flags == 0, return REFUSED */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000348
349 if (forward)
350 {
Simon Kelley0a852542005-03-23 20:28:59 +0000351 forward->source = *udpaddr;
352 forward->dest = *dst_addr;
353 forward->iface = dst_iface;
Simon Kelley0a852542005-03-23 20:28:59 +0000354 forward->orig_id = ntohs(header->id);
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000355 forward->new_id = get_id();
Simon Kelley832af0b2007-01-21 20:01:28 +0000356 forward->fd = udpfd;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000357 memcpy(forward->hash, hash, HASH_SIZE);
Simon Kelley0a852542005-03-23 20:28:59 +0000358 forward->forwardall = 0;
Simon Kelleyed4c0762013-10-08 20:46:34 +0100359 forward->flags = 0;
Simon Kelley28866e92011-02-14 20:19:14 +0000360 if (norebind)
361 forward->flags |= FREC_NOREBIND;
Simon Kelley572b41e2011-02-18 18:11:18 +0000362 if (header->hb4 & HB4_CD)
Simon Kelley28866e92011-02-14 20:19:14 +0000363 forward->flags |= FREC_CHECKING_DISABLED;
Simon Kelley83349b82014-02-10 21:02:01 +0000364 if (ad_reqd)
365 forward->flags |= FREC_AD_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000366#ifdef HAVE_DNSSEC
367 forward->work_counter = DNSSEC_WORK;
Simon Kelley613ad152014-02-25 23:02:28 +0000368 if (do_bit)
369 forward->flags |= FREC_DO_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000370#endif
Simon Kelley613ad152014-02-25 23:02:28 +0000371
Simon Kelley28866e92011-02-14 20:19:14 +0000372 header->id = htons(forward->new_id);
373
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100374 /* In strict_order mode, always try servers in the order
375 specified in resolv.conf, if a domain is given
376 always try all the available servers,
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000377 otherwise, use the one last known to work. */
378
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100379 if (type == 0)
380 {
Simon Kelley28866e92011-02-14 20:19:14 +0000381 if (option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100382 start = daemon->servers;
383 else if (!(start = daemon->last_server) ||
384 daemon->forwardcount++ > FORWARD_TEST ||
385 difftime(now, daemon->forwardtime) > FORWARD_TIME)
386 {
387 start = daemon->servers;
388 forward->forwardall = 1;
389 daemon->forwardcount = 0;
390 daemon->forwardtime = now;
391 }
392 }
393 else
Simon Kelleyde379512004-06-22 20:23:33 +0100394 {
Simon Kelley3be34542004-09-11 19:12:13 +0100395 start = daemon->servers;
Simon Kelley28866e92011-02-14 20:19:14 +0000396 if (!option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100397 forward->forwardall = 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100398 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000399 }
400 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100401
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000402 /* check for send errors here (no route to host)
403 if we fail to send to all nameservers, send back an error
404 packet straight away (helps modem users when offline) */
405
406 if (!flags && forward)
407 {
Simon Kelleyde379512004-06-22 20:23:33 +0100408 struct server *firstsentto = start;
Simon Kelley33702ab2015-12-28 23:17:15 +0000409 int subnet, forwarded = 0;
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000410 size_t edns0_len;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000411 unsigned char *pheader;
412
Simon Kelley25cf5e32015-01-09 15:53:03 +0000413 /* If a query is retried, use the log_id for the retry when logging the answer. */
414 forward->log_id = daemon->log_id;
415
Simon Kelley6fd5d792017-10-13 22:26:40 +0100416 plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
Simon Kelley33702ab2015-12-28 23:17:15 +0000417
Simon Kelley6fd5d792017-10-13 22:26:40 +0100418 if (subnet)
419 forward->flags |= FREC_HAS_SUBNET;
Simon Kelley33702ab2015-12-28 23:17:15 +0000420
Simon Kelley3a237152013-12-12 12:15:50 +0000421#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000422 if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000423 {
Simon Kelley6fd5d792017-10-13 22:26:40 +0100424 plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
425
Simon Kelley5b3bf922014-01-25 17:03:07 +0000426 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
427 this allows it to select auth servers when one is returning bad data. */
428 if (option_bool(OPT_DNSSEC_DEBUG))
429 header->hb4 |= HB4_CD;
Simon Kelley613ad152014-02-25 23:02:28 +0000430
Simon Kelley0fc2f312014-01-08 10:26:58 +0000431 }
Simon Kelley3a237152013-12-12 12:15:50 +0000432#endif
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000433
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000434 if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
Simon Kelley6fd5d792017-10-13 22:26:40 +0100435 {
436 /* If there wasn't a PH before, and there is now, we added it. */
437 if (!oph)
438 forward->flags |= FREC_ADDED_PHEADER;
439
440 /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
441 if (edns0_len > 11)
442 forward->flags |= FREC_HAS_EXTRADATA;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000443
444 /* Reduce udp size on retransmits. */
445 if (forward->flags & FREC_TEST_PKTSZ)
446 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelley6fd5d792017-10-13 22:26:40 +0100447 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100448
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000449 while (1)
450 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000451 /* only send to servers dealing with our domain.
452 domain may be NULL, in which case server->domain
453 must be NULL also. */
454
Simon Kelleyde379512004-06-22 20:23:33 +0100455 if (type == (start->flags & SERV_TYPE) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100456 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100457 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000458 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100459 int fd;
460
461 /* find server socket to use, may need to get random one. */
462 if (start->sfd)
463 fd = start->sfd->fd;
464 else
465 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100466 if (start->addr.sa.sa_family == AF_INET6)
467 {
468 if (!forward->rfd6 &&
469 !(forward->rfd6 = allocate_rfd(AF_INET6)))
470 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100471 daemon->rfd_save = forward->rfd6;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100472 fd = forward->rfd6->fd;
473 }
474 else
Simon Kelley1a6bca82008-07-11 11:11:42 +0100475 {
476 if (!forward->rfd4 &&
477 !(forward->rfd4 = allocate_rfd(AF_INET)))
478 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100479 daemon->rfd_save = forward->rfd4;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100480 fd = forward->rfd4->fd;
481 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100482
483#ifdef HAVE_CONNTRACK
484 /* Copy connection mark of incoming query to outgoing connection. */
485 if (option_bool(OPT_CONNTRACK))
486 {
487 unsigned int mark;
Giacomo Tazzari797a7af2013-04-22 13:16:37 +0100488 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
Simon Kelley7de060b2011-08-26 17:24:52 +0100489 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
490 }
491#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100492 }
493
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000494#ifdef HAVE_DNSSEC
Simon Kelley5bb88f02015-12-21 16:23:47 +0000495 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000496 {
497 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
498 packet size to 512. But that won't provide space for the RRSIGS in many cases.
499 The RRSIGS will be stripped out before the answer goes back, so the packet should
500 shrink again. So, if we added a do-bit, bump the udp packet size to the value
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000501 known to be OK for this server. We check returned size after stripping and set
502 the truncated bit if it's still too big. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000503 unsigned char *pheader;
504 int is_sign;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000505 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000506 PUTSHORT(start->edns_pktsz, pheader);
507 }
508#endif
509
Simon Kelleyff841eb2015-03-11 21:36:30 +0000510 if (retry_send(sendto(fd, (char *)header, plen, 0,
511 &start->addr.sa,
512 sa_len(&start->addr))))
513 continue;
514
515 if (errno == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000516 {
Simon Kelley6b173352018-05-08 18:32:14 +0100517#ifdef HAVE_DUMPFILE
518 dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &start->addr);
519#endif
520
Simon Kelleycdeda282006-03-16 20:16:06 +0000521 /* Keep info in case we want to re-send this packet */
522 daemon->srv_save = start;
523 daemon->packet_len = plen;
524
Simon Kelleyde379512004-06-22 20:23:33 +0100525 if (!gotname)
Simon Kelley3be34542004-09-11 19:12:13 +0100526 strcpy(daemon->namebuff, "query");
Simon Kelleyde379512004-06-22 20:23:33 +0100527 if (start->addr.sa.sa_family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +0100528 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +0000529 (union all_addr *)&start->addr.in.sin_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100530 else
Simon Kelley3be34542004-09-11 19:12:13 +0100531 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +0000532 (union all_addr *)&start->addr.in6.sin6_addr, NULL);
Simon Kelley824af852008-02-12 20:43:05 +0000533 start->queries++;
Simon Kelleyde379512004-06-22 20:23:33 +0100534 forwarded = 1;
535 forward->sentto = start;
Simon Kelley0a852542005-03-23 20:28:59 +0000536 if (!forward->forwardall)
Simon Kelleyde379512004-06-22 20:23:33 +0100537 break;
Simon Kelley0a852542005-03-23 20:28:59 +0000538 forward->forwardall++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000539 }
540 }
541
Simon Kelleyde379512004-06-22 20:23:33 +0100542 if (!(start = start->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100543 start = daemon->servers;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000544
Simon Kelleyde379512004-06-22 20:23:33 +0100545 if (start == firstsentto)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000546 break;
547 }
548
Simon Kelleyde379512004-06-22 20:23:33 +0100549 if (forwarded)
Simon Kelley824af852008-02-12 20:43:05 +0000550 return 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100551
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000552 /* could not send on, prepare to return */
553 header->id = htons(forward->orig_id);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100554 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000555 }
556
557 /* could not send on, return empty answer or address if known for whole domain */
Simon Kelleyb8187c82005-11-26 21:46:27 +0000558 if (udpfd != -1)
559 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000560 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
Simon Kelley1682d152018-08-03 20:38:18 +0100561 if (oph)
562 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 +0100563 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 +0000564 }
565
Simon Kelley824af852008-02-12 20:43:05 +0000566 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000567}
568
Simon Kelleyed4c0762013-10-08 20:46:34 +0100569static 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 +0100570 int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
571 int check_subnet, union mysockaddr *query_source)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100572{
Simon Kelley36717ee2004-09-20 19:20:58 +0100573 unsigned char *pheader, *sizep;
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000574 char **sets = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +0000575 int munged = 0, is_sign;
Simon Kelley07ed5852018-05-04 21:52:22 +0100576 unsigned int rcode = RCODE(header);
Simon Kelleycdeda282006-03-16 20:16:06 +0000577 size_t plen;
Simon Kelleya6004d72017-10-25 17:48:19 +0100578
Simon Kelley83349b82014-02-10 21:02:01 +0000579 (void)ad_reqd;
Simon Kelley982faf42015-04-03 21:42:30 +0100580 (void)do_bit;
581 (void)bogusanswer;
Simon Kelley83349b82014-02-10 21:02:01 +0000582
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000583#ifdef HAVE_IPSET
Simon Kelley82a14af2014-04-13 20:48:57 +0100584 if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000585 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100586 /* Similar algorithm to search_servers. */
587 struct ipsets *ipset_pos;
588 unsigned int namelen = strlen(daemon->namebuff);
589 unsigned int matchlen = 0;
590 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
Simon Kelley6c0cb852014-01-17 14:40:46 +0000591 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100592 unsigned int domainlen = strlen(ipset_pos->domain);
593 char *matchstart = daemon->namebuff + namelen - domainlen;
594 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
595 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
596 domainlen >= matchlen)
597 {
598 matchlen = domainlen;
599 sets = ipset_pos->sets;
600 }
Simon Kelley6c0cb852014-01-17 14:40:46 +0000601 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000602 }
603#endif
604
Simon Kelley5bb88f02015-12-21 16:23:47 +0000605 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100606 {
Simon Kelley07ed5852018-05-04 21:52:22 +0100607 /* Get extended RCODE. */
608 rcode |= sizep[2] << 4;
609
Simon Kelleyed4c0762013-10-08 20:46:34 +0100610 if (check_subnet && !check_source(header, plen, pheader, query_source))
611 {
612 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
613 return 0;
614 }
Simon Kelley613ad152014-02-25 23:02:28 +0000615
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000616 if (!is_sign)
Simon Kelley613ad152014-02-25 23:02:28 +0000617 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000618 if (added_pheader)
619 {
620 /* client didn't send EDNS0, we added one, strip it off before returning answer. */
621 n = rrfilter(header, n, 0);
622 pheader = NULL;
623 }
624 else
625 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000626 unsigned short udpsz;
627
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000628 /* If upstream is advertising a larger UDP packet size
629 than we allow, trim it so that we don't get overlarge
630 requests for the client. We can't do this for signed packets. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000631 GETSHORT(udpsz, sizep);
632 if (udpsz > daemon->edns_pktsz)
Simon Kelley33702ab2015-12-28 23:17:15 +0000633 {
634 sizep -= 2;
635 PUTSHORT(daemon->edns_pktsz, sizep);
636 }
637
638#ifdef HAVE_DNSSEC
639 /* If the client didn't set the do bit, but we did, reset it. */
640 if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
641 {
642 unsigned short flags;
643 sizep += 2; /* skip RCODE */
644 GETSHORT(flags, sizep);
645 flags &= ~0x8000;
646 sizep -= 2;
647 PUTSHORT(flags, sizep);
648 }
649#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000650 }
Simon Kelley613ad152014-02-25 23:02:28 +0000651 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100652 }
Simon Kelley83349b82014-02-10 21:02:01 +0000653
Simon Kelley28866e92011-02-14 20:19:14 +0000654 /* RFC 4035 sect 4.6 para 3 */
Giovanni Bajo237724c2012-04-05 02:46:52 +0200655 if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
Simon Kelley795501b2014-01-08 18:11:55 +0000656 header->hb4 &= ~HB4_AD;
Simon Kelley3a237152013-12-12 12:15:50 +0000657
Simon Kelley07ed5852018-05-04 21:52:22 +0100658 if (OPCODE(header) != QUERY)
Simon Kelley8938ae02014-05-01 17:46:25 +0100659 return resize_packet(header, n, pheader, plen);
Simon Kelley07ed5852018-05-04 21:52:22 +0100660
661 if (rcode != NOERROR && rcode != NXDOMAIN)
662 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000663 union all_addr a;
664 a.log.rcode = rcode;
Simon Kelley07ed5852018-05-04 21:52:22 +0100665 log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
666
667 return resize_packet(header, n, pheader, plen);
668 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100669
Simon Kelley0a852542005-03-23 20:28:59 +0000670 /* Complain loudly if the upstream server is non-recursive. */
Simon Kelley07ed5852018-05-04 21:52:22 +0100671 if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
Simon Kelley0a852542005-03-23 20:28:59 +0000672 server && !(server->flags & SERV_WARNED_RECURSIVE))
673 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100674 prettyprint_addr(&server->addr, daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100675 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
Simon Kelley28866e92011-02-14 20:19:14 +0000676 if (!option_bool(OPT_LOG))
Simon Kelley0a852542005-03-23 20:28:59 +0000677 server->flags |= SERV_WARNED_RECURSIVE;
678 }
Giovanni Bajoe292e932012-04-22 14:32:02 +0200679
Simon Kelley07ed5852018-05-04 21:52:22 +0100680 if (daemon->bogus_addr && rcode != NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100681 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100682 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100683 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000684 SET_RCODE(header, NXDOMAIN);
685 header->hb3 &= ~HB3_AA;
Simon Kelley6938f342014-01-26 22:47:39 +0000686 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100687 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100688 else
Simon Kelley36717ee2004-09-20 19:20:58 +0100689 {
Simon Kelley6938f342014-01-26 22:47:39 +0000690 int doctored = 0;
691
Simon Kelley07ed5852018-05-04 21:52:22 +0100692 if (rcode == NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100693 extract_request(header, n, daemon->namebuff, NULL) &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100694 check_for_local_domain(daemon->namebuff, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100695 {
Simon Kelley36717ee2004-09-20 19:20:58 +0100696 /* if we forwarded a query for a locally known name (because it was for
697 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
698 since we know that the domain exists, even if upstream doesn't */
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100699 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000700 header->hb3 |= HB3_AA;
701 SET_RCODE(header, NOERROR);
Simon Kelley6938f342014-01-26 22:47:39 +0000702 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100703 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000704
Simon Kelley373e9172017-12-01 22:40:56 +0000705 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 +0000706 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100707 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
Simon Kelley824af852008-02-12 20:43:05 +0000708 munged = 1;
Simon Kelley6938f342014-01-26 22:47:39 +0000709 cache_secure = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000710 }
Simon Kelley6938f342014-01-26 22:47:39 +0000711
712 if (doctored)
713 cache_secure = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100714 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100715
Simon Kelleya25720a2014-01-14 23:13:55 +0000716#ifdef HAVE_DNSSEC
Simon Kelley33702ab2015-12-28 23:17:15 +0000717 if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
Simon Kelleya25720a2014-01-14 23:13:55 +0000718 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000719 /* Bogus reply, turn into SERVFAIL */
720 SET_RCODE(header, SERVFAIL);
721 munged = 1;
Simon Kelleya25720a2014-01-14 23:13:55 +0000722 }
Simon Kelley6938f342014-01-26 22:47:39 +0000723
724 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000725 {
726 header->hb4 &= ~HB4_AD;
727
728 if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
729 header->hb4 |= HB4_AD;
730
731 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
732 if (!do_bit)
733 n = rrfilter(header, n, 1);
734 }
Simon Kelleya25720a2014-01-14 23:13:55 +0000735#endif
736
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100737 /* do this after extract_addresses. Ensure NODATA reply and remove
738 nameserver info. */
739
740 if (munged)
741 {
742 header->ancount = htons(0);
743 header->nscount = htons(0);
744 header->arcount = htons(0);
Simon Kelley150162b2015-03-27 09:58:26 +0000745 header->hb3 &= ~HB3_TC;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100746 }
747
Simon Kelley36717ee2004-09-20 19:20:58 +0100748 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
749 sections of the packet. Find the new length here and put back pseudoheader
750 if it was removed. */
751 return resize_packet(header, n, pheader, plen);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100752}
753
Simon Kelley3be34542004-09-11 19:12:13 +0100754/* sets new last_server */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100755void reply_query(int fd, int family, time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000756{
757 /* packet from peer server, extract data for cache, and send to
758 original requester */
Simon Kelley572b41e2011-02-18 18:11:18 +0000759 struct dns_header *header;
Simon Kelleyde379512004-06-22 20:23:33 +0100760 union mysockaddr serveraddr;
Simon Kelley832af0b2007-01-21 20:01:28 +0000761 struct frec *forward;
Simon Kelleyde379512004-06-22 20:23:33 +0100762 socklen_t addrlen = sizeof(serveraddr);
Simon Kelley60b68062014-01-08 12:10:28 +0000763 ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
Simon Kelleycdeda282006-03-16 20:16:06 +0000764 size_t nn;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100765 struct server *server;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000766 void *hash;
767#ifndef HAVE_DNSSEC
768 unsigned int crc;
769#endif
770
Simon Kelleycdeda282006-03-16 20:16:06 +0000771 /* packet buffer overwritten */
772 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000773
Simon Kelleyde379512004-06-22 20:23:33 +0100774 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelleyee875042018-10-23 22:10:17 +0100775 if ((serveraddr.sa.sa_family = family) == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100776 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000777
Simon Kelley490f9072014-03-24 22:04:42 +0000778 header = (struct dns_header *)daemon->packet;
Simon Kelley6b173352018-05-08 18:32:14 +0100779
Simon Kelley490f9072014-03-24 22:04:42 +0000780 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
781 return;
782
Simon Kelley1a6bca82008-07-11 11:11:42 +0100783 /* spoof check: answer must come from known server, */
784 for (server = daemon->servers; server; server = server->next)
785 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
786 sockaddr_isequal(&server->addr, &serveraddr))
787 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000788
789 if (!server)
790 return;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000791
792 /* If sufficient time has elapsed, try and expand UDP buffer size again. */
793 if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
794 server->edns_pktsz = daemon->edns_pktsz;
795
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000796#ifdef HAVE_DNSSEC
797 hash = hash_questions(header, n, daemon->namebuff);
798#else
799 hash = &crc;
800 crc = questions_crc(header, n, daemon->namebuff);
801#endif
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100802
Simon Kelley490f9072014-03-24 22:04:42 +0000803 if (!(forward = lookup_frec(ntohs(header->id), hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100804 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000805
Simon Kelley6b173352018-05-08 18:32:14 +0100806#ifdef HAVE_DUMPFILE
807 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
808 (void *)header, n, &serveraddr, NULL);
809#endif
Simon Kelleya0088e82018-05-10 21:43:14 +0100810
Simon Kelley25cf5e32015-01-09 15:53:03 +0000811 /* log_query gets called indirectly all over the place, so
812 pass these in global variables - sorry. */
813 daemon->log_display_id = forward->log_id;
814 daemon->log_source_addr = &forward->source;
815
Glen Huang32fc6db2014-12-27 15:28:12 +0000816 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
817 check_for_ignored_address(header, n, daemon->ignore_addr))
818 return;
819
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000820 /* Note: if we send extra options in the EDNS0 header, we can't recreate
821 the query from the reply. */
Simon Kelley34e26e12018-05-10 20:54:57 +0100822 if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000823 forward->forwardall == 0 &&
824 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100825 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000826 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100827 unsigned char *pheader;
828 size_t plen;
829 int is_sign;
Simon Kelleyef3d1372017-12-05 22:37:29 +0000830
Simon Kelley1f60a182018-05-11 16:44:16 +0100831#ifdef HAVE_DNSSEC
Simon Kelleya0088e82018-05-10 21:43:14 +0100832 /* For DNSSEC originated queries, just retry the query to the same server. */
833 if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
834 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100835 struct server *start;
836
Simon Kelleya0088e82018-05-10 21:43:14 +0100837 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
838 plen = forward->stash_len;
839
840 forward->forwardall = 2; /* only retry once */
Simon Kelley1f60a182018-05-11 16:44:16 +0100841 start = forward->sentto;
842
843 /* for non-domain specific servers, see if we can find another to try. */
844 if ((forward->sentto->flags & SERV_TYPE) == 0)
845 while (1)
846 {
847 if (!(start = start->next))
848 start = daemon->servers;
849 if (start == forward->sentto)
850 break;
851
852 if ((start->flags & SERV_TYPE) == 0 &&
853 (start->flags & SERV_DO_DNSSEC))
854 break;
855 }
856
857
858 if (start->sfd)
859 fd = start->sfd->fd;
Simon Kelleya0088e82018-05-10 21:43:14 +0100860 else
861 {
Simon Kelley1f60a182018-05-11 16:44:16 +0100862 if (start->addr.sa.sa_family == AF_INET6)
863 {
864 /* may have changed family */
865 if (!forward->rfd6)
866 forward->rfd6 = allocate_rfd(AF_INET6);
867 fd = forward->rfd6->fd;
868 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100869 else
Simon Kelley1f60a182018-05-11 16:44:16 +0100870 {
871 /* may have changed family */
872 if (!forward->rfd4)
873 forward->rfd4 = allocate_rfd(AF_INET);
874 fd = forward->rfd4->fd;
875 }
Simon Kelleya0088e82018-05-10 21:43:14 +0100876 }
Simon Kelleye3002bf2019-10-11 23:30:08 +0100877
878#ifdef HAVE_DUMPFILE
879 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
880#endif
881
Simon Kelleya0088e82018-05-10 21:43:14 +0100882 while (retry_send(sendto(fd, (char *)header, plen, 0,
Simon Kelley1f60a182018-05-11 16:44:16 +0100883 &start->addr.sa,
884 sa_len(&start->addr))));
Simon Kelleya0088e82018-05-10 21:43:14 +0100885
Simon Kelleye27825b2018-05-11 17:20:47 +0100886 if (start->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +0000887 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 +0100888 else
Simon Kelleycc921df2019-01-02 22:48:59 +0000889 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 +0100890
Simon Kelleya0088e82018-05-10 21:43:14 +0100891 return;
892 }
Simon Kelley1f60a182018-05-11 16:44:16 +0100893#endif
894
Simon Kelleyef3d1372017-12-05 22:37:29 +0000895 /* In strict order mode, there must be a server later in the chain
896 left to send to, otherwise without the forwardall mechanism,
897 code further on will cycle around the list forwever if they
898 all return REFUSED. Note that server is always non-NULL before
899 this executes. */
900 if (option_bool(OPT_ORDER))
901 for (server = forward->sentto->next; server; server = server->next)
902 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
903 break;
904
Simon Kelley1a6bca82008-07-11 11:11:42 +0100905 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000906 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelleyef3d1372017-12-05 22:37:29 +0000907 if (!is_sign && server)
Simon Kelley832af0b2007-01-21 20:01:28 +0000908 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100909 header->ancount = htons(0);
910 header->nscount = htons(0);
911 header->arcount = htons(0);
912 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
913 {
swiggerbd7bfa22015-06-01 20:54:59 +0100914 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000915 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000916 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000917 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000918 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000919 header->hb4 |= HB4_AD;
920 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000921 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000922 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 +0100923 return;
924 }
925 }
926 }
Simon Kelley3a237152013-12-12 12:15:50 +0000927
928 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100929 if ((forward->sentto->flags & SERV_TYPE) == 0)
930 {
Simon Kelley51967f92014-03-25 21:07:00 +0000931 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100932 server = NULL;
933 else
934 {
935 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000936
Simon Kelley1a6bca82008-07-11 11:11:42 +0100937 /* find good server by address if possible, otherwise assume the last one we sent to */
938 for (last_server = daemon->servers; last_server; last_server = last_server->next)
939 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
940 sockaddr_isequal(&last_server->addr, &serveraddr))
941 {
942 server = last_server;
943 break;
944 }
945 }
Simon Kelley28866e92011-02-14 20:19:14 +0000946 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100947 daemon->last_server = server;
948 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100949
950 /* We tried resending to this server with a smaller maximum size and got an answer.
Ville Skyttäfaaf3062018-01-14 17:32:52 +0000951 Make that permanent. To avoid reduxing the packet size for a single dropped packet,
Simon Kelley86fa1042015-05-10 13:50:59 +0100952 only do this when we get a truncated answer, or one larger than the safe size. */
Simon Kelley04db1482019-10-11 23:22:17 +0100953 if (forward->sentto->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
Simon Kelley86fa1042015-05-10 13:50:59 +0100954 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelley22dee512017-10-13 22:54:00 +0100955 {
Simon Kelley04db1482019-10-11 23:22:17 +0100956 forward->sentto->edns_pktsz = SAFE_PKTSZ;
957 forward->sentto->pktsz_reduced = now;
958 prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
Simon Kelleyebedcba2017-10-29 20:54:17 +0000959 my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
Simon Kelley22dee512017-10-13 22:54:00 +0100960 }
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000961
962
Simon Kelley1a6bca82008-07-11 11:11:42 +0100963 /* If the answer is an error, keep the forward record in place in case
964 we get a good reply from another server. Kill it when we've
965 had replies from all to avoid filling the forwarding table when
966 everything is broken */
Simon Kelley122392e2018-10-31 22:24:02 +0000967 if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100968 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100969 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleya6004d72017-10-25 17:48:19 +0100970
Simon Kelley3a237152013-12-12 12:15:50 +0000971 if (option_bool(OPT_NO_REBIND))
972 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100973
Simon Kelley3a237152013-12-12 12:15:50 +0000974 /* Don't cache replies where DNSSEC validation was turned off, either
975 the upstream server told us so, or the original query specified it. */
976 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
977 no_cache_dnssec = 1;
978
979#ifdef HAVE_DNSSEC
Simon Kelley04db1482019-10-11 23:22:17 +0100980 if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000981 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000982 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000983 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000984
985 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000986 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000987 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000988
989 /* Truncated answer can't be validated.
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100990 If this is an answer to a DNSSEC-generated query, we still
991 need to get the client to retry over TCP, so return
992 an answer with the TC bit set, even if the actual answer fits.
993 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000994 if (header->hb3 & HB3_TC)
995 status = STAT_TRUNCATED;
996
997 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000998 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000999 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
1000 would invite infinite loops, since the answers to DNSKEY and DS queries
1001 will not be cached, so they'll be repeated. */
1002 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001003 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001004 if (forward->flags & FREC_DNSKEY_QUERY)
1005 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1006 else if (forward->flags & FREC_DS_QUERY)
1007 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001008 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001009 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
Simon Kelleya6918532018-04-15 16:20:52 +01001010 !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001011 NULL, NULL, NULL);
Simon Kelley6b173352018-05-08 18:32:14 +01001012#ifdef HAVE_DUMPFILE
1013 if (status == STAT_BOGUS)
1014 dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
1015 header, (size_t)n, &serveraddr, NULL);
1016#endif
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001017 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001018
Simon Kelley9a31b682015-12-15 10:20:39 +00001019 /* Can't validate, as we're missing key data. Put this
1020 answer aside, whilst we get that. */
1021 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +00001022 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001023 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +00001024
Simon Kelley9a31b682015-12-15 10:20:39 +00001025 /* Free any saved query */
1026 if (forward->stash)
1027 blockdata_free(forward->stash);
1028
1029 /* Now save reply pending receipt of key data */
1030 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +00001031 return;
Simon Kelley9a31b682015-12-15 10:20:39 +00001032 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001033
Simon Kelley9a31b682015-12-15 10:20:39 +00001034 /* Find the original query that started it all.... */
1035 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001036
Simon Kelley9a31b682015-12-15 10:20:39 +00001037 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
1038 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +00001039 else
Simon Kelley3a237152013-12-12 12:15:50 +00001040 {
Simon Kelleye1791f32018-10-06 23:23:23 +01001041 int querytype, fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +00001042 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +00001043 char *domain;
1044
Simon Kelley9a31b682015-12-15 10:20:39 +00001045 *new = *forward; /* copy everything, then overwrite */
1046 new->next = next;
1047 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +00001048
1049 /* Find server to forward to. This will normally be the
1050 same as for the original query, but may be another if
1051 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001052 if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
Simon Kelley92be34a2016-01-16 18:39:54 +00001053 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001054 struct server *start = server, *new_server = NULL;
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001055
1056 while (1)
1057 {
1058 if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
Simon Kelley1f60a182018-05-11 16:44:16 +01001059 ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001060 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1061 {
1062 new_server = start;
1063 if (server == start)
1064 {
1065 new_server = NULL;
1066 break;
1067 }
1068 }
1069
1070 if (!(start = start->next))
1071 start = daemon->servers;
1072 if (start == server)
1073 break;
1074 }
1075
1076 if (new_server)
1077 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +00001078 }
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001079
Simon Kelley9a31b682015-12-15 10:20:39 +00001080 new->sentto = server;
1081 new->rfd4 = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001082 new->rfd6 = NULL;
Simon Kelleya0088e82018-05-10 21:43:14 +01001083 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
1084 new->forwardall = 0;
Simon Kelley9a31b682015-12-15 10:20:39 +00001085
1086 new->dependent = forward; /* to find query awaiting new one. */
1087 forward->blocking_query = new; /* for garbage cleaning */
1088 /* validate routines leave name of required record in daemon->keyname */
1089 if (status == STAT_NEED_KEY)
Simon Kelley7fa836e2014-02-10 20:11:24 +00001090 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001091 new->flags |= FREC_DNSKEY_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001092 querytype = T_DNSKEY;
Simon Kelleyf1668d22014-01-08 16:53:27 +00001093 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001094 else
1095 {
1096 new->flags |= FREC_DS_QUERY;
Simon Kelleye1791f32018-10-06 23:23:23 +01001097 querytype = T_DS;
Simon Kelley9a31b682015-12-15 10:20:39 +00001098 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001099
1100 nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
1101 daemon->keyname, forward->class, querytype, server->edns_pktsz);
1102
1103 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001104 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (union all_addr *)&(server->addr.in.sin_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001105 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001106 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001107 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001108 querystr("dnssec-query", querytype));
Simon Kelleye1791f32018-10-06 23:23:23 +01001109
Simon Kelley9a31b682015-12-15 10:20:39 +00001110 if ((hash = hash_questions(header, nn, daemon->namebuff)))
1111 memcpy(new->hash, hash, HASH_SIZE);
1112 new->new_id = get_id();
1113 header->id = htons(new->new_id);
1114 /* Save query for retransmission */
1115 new->stash = blockdata_alloc((char *)header, nn);
1116 new->stash_len = nn;
1117
1118 /* Don't resend this. */
1119 daemon->srv_save = NULL;
1120
1121 if (server->sfd)
1122 fd = server->sfd->fd;
1123 else
1124 {
1125 fd = -1;
Simon Kelley9a31b682015-12-15 10:20:39 +00001126 if (server->addr.sa.sa_family == AF_INET6)
1127 {
1128 if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1129 fd = new->rfd6->fd;
1130 }
1131 else
Simon Kelley9a31b682015-12-15 10:20:39 +00001132 {
1133 if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1134 fd = new->rfd4->fd;
1135 }
1136 }
1137
1138 if (fd != -1)
1139 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001140#ifdef HAVE_CONNTRACK
1141 /* Copy connection mark of incoming query to outgoing connection. */
1142 if (option_bool(OPT_CONNTRACK))
1143 {
1144 unsigned int mark;
1145 if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
1146 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1147 }
1148#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001149
1150#ifdef HAVE_DUMPFILE
1151 dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
1152#endif
1153
Simon Kelley9a31b682015-12-15 10:20:39 +00001154 while (retry_send(sendto(fd, (char *)header, nn, 0,
1155 &server->addr.sa,
1156 sa_len(&server->addr))));
1157 server->queries++;
1158 }
1159 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001160 return;
Simon Kelley3a237152013-12-12 12:15:50 +00001161 }
Simon Kelley3a237152013-12-12 12:15:50 +00001162
Simon Kelley9a31b682015-12-15 10:20:39 +00001163 /* Validated original answer, all done. */
1164 if (!forward->dependent)
1165 break;
1166
Josh Soref730c6742017-02-06 16:14:04 +00001167 /* validated subsidiary query, (and cached result)
Simon Kelley9a31b682015-12-15 10:20:39 +00001168 pop that and return to the previous query we were working on. */
Simon Kelley0744ca62014-01-25 16:40:15 +00001169 struct frec *prev = forward->dependent;
1170 free_frec(forward);
1171 forward = prev;
1172 forward->blocking_query = NULL; /* already gone */
1173 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1174 n = forward->stash_len;
Simon Kelley3a237152013-12-12 12:15:50 +00001175 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001176
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001177
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001178 no_cache_dnssec = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001179
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001180 if (status == STAT_TRUNCATED)
Simon Kelley0744ca62014-01-25 16:40:15 +00001181 header->hb3 |= HB3_TC;
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001182 else
Simon Kelley7fa836e2014-02-10 20:11:24 +00001183 {
Simon Kelley554b5802015-04-17 22:50:20 +01001184 char *result, *domain = "result";
Simon Kelley7fa836e2014-02-10 20:11:24 +00001185
Simon Kelley9a31b682015-12-15 10:20:39 +00001186 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001187 {
1188 result = "ABANDONED";
1189 status = STAT_BOGUS;
1190 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001191 else
1192 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1193
Simon Kelley554b5802015-04-17 22:50:20 +01001194 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1195 domain = daemon->namebuff;
Simon Kelley9a31b682015-12-15 10:20:39 +00001196
Simon Kelley07ed5852018-05-04 21:52:22 +01001197 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001198 }
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001199
Simon Kelley3a237152013-12-12 12:15:50 +00001200 if (status == STAT_SECURE)
1201 cache_secure = 1;
Simon Kelley3a237152013-12-12 12:15:50 +00001202 else if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001203 {
1204 no_cache_dnssec = 1;
1205 bogusanswer = 1;
1206 }
Simon Kelley3a237152013-12-12 12:15:50 +00001207 }
Simon Kelley04db1482019-10-11 23:22:17 +01001208
Simon Kelley6b173352018-05-08 18:32:14 +01001209#endif
1210
Simon Kelley83349b82014-02-10 21:02:01 +00001211 /* restore CD bit to the value in the query */
1212 if (forward->flags & FREC_CHECKING_DISABLED)
1213 header->hb4 |= HB4_CD;
1214 else
1215 header->hb4 &= ~HB4_CD;
Simon Kelley3a237152013-12-12 12:15:50 +00001216
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001217 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 +00001218 forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1219 forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
Simon Kelley832af0b2007-01-21 20:01:28 +00001220 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001221 header->id = htons(forward->orig_id);
Simon Kelley572b41e2011-02-18 18:11:18 +00001222 header->hb4 |= HB4_RA; /* recursion if available */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001223#ifdef HAVE_DNSSEC
1224 /* 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 +01001225 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 +00001226 header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1227 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1228 {
1229 header->ancount = htons(0);
1230 header->nscount = htons(0);
1231 header->arcount = htons(0);
1232 header->hb3 |= HB3_TC;
1233 nn = resize_packet(header, nn, NULL, 0);
1234 }
1235#endif
Simon Kelley6b173352018-05-08 18:32:14 +01001236
1237#ifdef HAVE_DUMPFILE
1238 dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
1239#endif
1240
Simon Kelley54dd3932012-06-20 11:23:38 +01001241 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
Simon Kelley50303b12012-04-04 22:13:17 +01001242 &forward->source, &forward->dest, forward->iface);
Simon Kelley832af0b2007-01-21 20:01:28 +00001243 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001244 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001245 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001246}
Simon Kelley44a2a312004-03-10 20:04:35 +00001247
Simon Kelley1a6bca82008-07-11 11:11:42 +01001248
Simon Kelley5aabfc72007-08-29 11:24:47 +01001249void receive_query(struct listener *listen, time_t now)
Simon Kelley44a2a312004-03-10 20:04:35 +00001250{
Simon Kelley572b41e2011-02-18 18:11:18 +00001251 struct dns_header *header = (struct dns_header *)daemon->packet;
Simon Kelley44a2a312004-03-10 20:04:35 +00001252 union mysockaddr source_addr;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001253 unsigned char *pheader;
1254 unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
Simon Kelleycc921df2019-01-02 22:48:59 +00001255 union all_addr dst_addr;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001256 struct in_addr netmask, dst_addr_4;
Simon Kelleycdeda282006-03-16 20:16:06 +00001257 size_t m;
1258 ssize_t n;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001259 int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001260#ifdef HAVE_AUTH
1261 int local_auth = 0;
1262#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001263 struct iovec iov[1];
1264 struct msghdr msg;
1265 struct cmsghdr *cmptr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001266 union {
1267 struct cmsghdr align; /* this ensures alignment */
Simon Kelley44a2a312004-03-10 20:04:35 +00001268 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001269#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +00001270 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
Simon Kelley824af852008-02-12 20:43:05 +00001271#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1272 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1273 CMSG_SPACE(sizeof(unsigned int))];
Simon Kelley44a2a312004-03-10 20:04:35 +00001274#elif defined(IP_RECVDSTADDR)
1275 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1276 CMSG_SPACE(sizeof(struct sockaddr_dl))];
1277#endif
1278 } control_u;
Simon Kelley2329bef2013-12-03 13:41:16 +00001279 /* Can always get recvd interface for IPv6 */
1280 int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
Simon Kelley2329bef2013-12-03 13:41:16 +00001281
Simon Kelleycdeda282006-03-16 20:16:06 +00001282 /* packet buffer overwritten */
1283 daemon->srv_save = NULL;
1284
Simon Kelleycc921df2019-01-02 22:48:59 +00001285 dst_addr_4.s_addr = dst_addr.addr4.s_addr = 0;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001286 netmask.s_addr = 0;
1287
Simon Kelley7e5664b2013-04-05 16:57:41 +01001288 if (option_bool(OPT_NOWILD) && listen->iface)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001289 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001290 auth_dns = listen->iface->dns_auth;
1291
1292 if (listen->family == AF_INET)
1293 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001294 dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001295 netmask = listen->iface->netmask;
1296 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001297 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001298
Simon Kelley3be34542004-09-11 19:12:13 +01001299 iov[0].iov_base = daemon->packet;
1300 iov[0].iov_len = daemon->edns_pktsz;
Simon Kelley44a2a312004-03-10 20:04:35 +00001301
1302 msg.msg_control = control_u.control;
1303 msg.msg_controllen = sizeof(control_u);
1304 msg.msg_flags = 0;
1305 msg.msg_name = &source_addr;
1306 msg.msg_namelen = sizeof(source_addr);
1307 msg.msg_iov = iov;
1308 msg.msg_iovlen = 1;
1309
Simon Kelleyde379512004-06-22 20:23:33 +01001310 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
Simon Kelley3be34542004-09-11 19:12:13 +01001311 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001312
Simon Kelley572b41e2011-02-18 18:11:18 +00001313 if (n < (int)sizeof(struct dns_header) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001314 (msg.msg_flags & MSG_TRUNC) ||
Simon Kelley572b41e2011-02-18 18:11:18 +00001315 (header->hb3 & HB3_QR))
Simon Kelley3be34542004-09-11 19:12:13 +01001316 return;
Simon Kelley63437ff2017-09-06 22:34:21 +01001317
1318 /* Clear buffer beyond request to avoid risk of
1319 information disclosure. */
1320 memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
Simon Kelley44a2a312004-03-10 20:04:35 +00001321
Simon Kelley26128d22004-11-14 16:43:54 +00001322 source_addr.sa.sa_family = listen->family;
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001323
1324 if (listen->family == AF_INET)
1325 {
1326 /* Source-port == 0 is an error, we can't send back to that.
1327 http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1328 if (source_addr.in.sin_port == 0)
1329 return;
1330 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001331 else
1332 {
1333 /* Source-port == 0 is an error, we can't send back to that. */
1334 if (source_addr.in6.sin6_port == 0)
1335 return;
1336 source_addr.in6.sin6_flowinfo = 0;
1337 }
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001338
Simon Kelleyc8a80482014-03-05 14:29:54 +00001339 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1340 if (option_bool(OPT_LOCAL_SERVICE))
1341 {
1342 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001343
Simon Kelleyc8a80482014-03-05 14:29:54 +00001344 if (listen->family == AF_INET6)
1345 {
1346 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1347 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001348 is_same_net6(&addr->addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001349 break;
1350 }
1351 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001352 {
1353 struct in_addr netmask;
1354 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1355 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001356 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001357 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001358 is_same_net(addr->addr.addr4, source_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001359 break;
1360 }
1361 }
1362 if (!addr)
1363 {
Simon Kelley0c8584e2014-03-12 20:12:56 +00001364 static int warned = 0;
1365 if (!warned)
1366 {
1367 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1368 warned = 1;
1369 }
Simon Kelleyc8a80482014-03-05 14:29:54 +00001370 return;
1371 }
1372 }
1373
Simon Kelley2329bef2013-12-03 13:41:16 +00001374 if (check_dst)
Simon Kelley44a2a312004-03-10 20:04:35 +00001375 {
Simon Kelley8a911cc2004-03-16 18:35:52 +00001376 struct ifreq ifr;
1377
Simon Kelley26128d22004-11-14 16:43:54 +00001378 if (msg.msg_controllen < sizeof(struct cmsghdr))
1379 return;
1380
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001381#if defined(HAVE_LINUX_NETWORK)
Simon Kelley26128d22004-11-14 16:43:54 +00001382 if (listen->family == AF_INET)
1383 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001384 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
Simon Kelley26128d22004-11-14 16:43:54 +00001385 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001386 union {
1387 unsigned char *c;
1388 struct in_pktinfo *p;
1389 } p;
1390 p.c = CMSG_DATA(cmptr);
Simon Kelleycc921df2019-01-02 22:48:59 +00001391 dst_addr_4 = dst_addr.addr4 = p.p->ipi_spec_dst;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001392 if_index = p.p->ipi_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001393 }
1394#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1395 if (listen->family == AF_INET)
1396 {
1397 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001398 {
1399 union {
1400 unsigned char *c;
1401 unsigned int *i;
1402 struct in_addr *a;
1403#ifndef HAVE_SOLARIS_NETWORK
1404 struct sockaddr_dl *s;
Simon Kelley824af852008-02-12 20:43:05 +00001405#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001406 } p;
1407 p.c = CMSG_DATA(cmptr);
1408 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
Simon Kelleycc921df2019-01-02 22:48:59 +00001409 dst_addr_4 = dst_addr.addr4 = *(p.a);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001410 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1411#ifdef HAVE_SOLARIS_NETWORK
1412 if_index = *(p.i);
1413#else
1414 if_index = p.s->sdl_index;
1415#endif
1416 }
Simon Kelley26128d22004-11-14 16:43:54 +00001417 }
1418#endif
1419
Simon Kelley26128d22004-11-14 16:43:54 +00001420 if (listen->family == AF_INET6)
1421 {
1422 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001423 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
Simon Kelley26128d22004-11-14 16:43:54 +00001424 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001425 union {
1426 unsigned char *c;
1427 struct in6_pktinfo *p;
1428 } p;
1429 p.c = CMSG_DATA(cmptr);
1430
Simon Kelleycc921df2019-01-02 22:48:59 +00001431 dst_addr.addr6 = p.p->ipi6_addr;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001432 if_index = p.p->ipi6_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001433 }
1434 }
Simon Kelley26128d22004-11-14 16:43:54 +00001435
1436 /* enforce available interface configuration */
1437
Simon Kelleye25db1f2013-01-29 22:10:26 +00001438 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
Simon Kelley832af0b2007-01-21 20:01:28 +00001439 return;
1440
Simon Kelleye25db1f2013-01-29 22:10:26 +00001441 if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
1442 {
1443 if (!option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001444 enumerate_interfaces(0);
Simon Kelley3f2873d2013-05-14 11:28:47 +01001445 if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
1446 !label_exception(if_index, listen->family, &dst_addr))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001447 return;
1448 }
1449
Simon Kelley552af8b2012-02-29 20:10:31 +00001450 if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
1451 {
1452 struct irec *iface;
1453
Josh Soref730c6742017-02-06 16:14:04 +00001454 /* get the netmask of the interface which has the address we were sent to.
klemens43517fc2017-02-19 15:53:37 +00001455 This is no necessarily the interface we arrived on. */
Simon Kelley552af8b2012-02-29 20:10:31 +00001456
1457 for (iface = daemon->interfaces; iface; iface = iface->next)
1458 if (iface->addr.sa.sa_family == AF_INET &&
1459 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1460 break;
1461
1462 /* interface may be new */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001463 if (!iface && !option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001464 enumerate_interfaces(0);
Simon Kelley552af8b2012-02-29 20:10:31 +00001465
1466 for (iface = daemon->interfaces; iface; iface = iface->next)
1467 if (iface->addr.sa.sa_family == AF_INET &&
1468 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1469 break;
1470
1471 /* If we failed, abandon localisation */
1472 if (iface)
1473 netmask = iface->netmask;
1474 else
1475 dst_addr_4.s_addr = 0;
1476 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001477 }
Simon Kelley25cf5e32015-01-09 15:53:03 +00001478
1479 /* log_query gets called indirectly all over the place, so
1480 pass these in global variables - sorry. */
1481 daemon->log_display_id = ++daemon->log_id;
1482 daemon->log_source_addr = &source_addr;
Simon Kelley6b173352018-05-08 18:32:14 +01001483
1484#ifdef HAVE_DUMPFILE
1485 dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
1486#endif
1487
Simon Kelleycdeda282006-03-16 20:16:06 +00001488 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
Simon Kelley44a2a312004-03-10 20:04:35 +00001489 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001490#ifdef HAVE_AUTH
1491 struct auth_zone *zone;
1492#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001493 char *types = querystr(auth_dns ? "auth" : "query", type);
1494
Simon Kelley44a2a312004-03-10 20:04:35 +00001495 if (listen->family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +01001496 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001497 (union all_addr *)&source_addr.in.sin_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001498 else
Simon Kelley3be34542004-09-11 19:12:13 +01001499 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001500 (union all_addr *)&source_addr.in6.sin6_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001501
Simon Kelley4820dce2012-12-18 18:30:30 +00001502#ifdef HAVE_AUTH
Simon Kelleyb485ed92013-10-18 22:00:39 +01001503 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001504 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001505 for (zone = daemon->auth_zones; zone; zone = zone->next)
1506 if (in_zone(zone, daemon->namebuff, NULL))
1507 {
1508 auth_dns = 1;
1509 local_auth = 1;
1510 break;
1511 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001512#endif
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001513
1514#ifdef HAVE_LOOP
1515 /* Check for forwarding loop */
1516 if (detect_loop(daemon->namebuff, type))
1517 return;
1518#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001519 }
1520
Simon Kelley5bb88f02015-12-21 16:23:47 +00001521 if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001522 {
1523 unsigned short flags;
1524
1525 have_pseudoheader = 1;
1526 GETSHORT(udp_size, pheader);
1527 pheader += 2; /* ext_rcode */
1528 GETSHORT(flags, pheader);
1529
1530 if (flags & 0x8000)
1531 do_bit = 1;/* do bit */
1532
1533 /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1534 (bounded by the maximum configured). If no EDNS0, then it
1535 defaults to 512 */
1536 if (udp_size > daemon->edns_pktsz)
1537 udp_size = daemon->edns_pktsz;
Simon Kelleya3303e12017-09-07 20:45:00 +01001538 else if (udp_size < PACKETSZ)
1539 udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001540 }
1541
Simon Kelleyb485ed92013-10-18 22:00:39 +01001542#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001543 if (auth_dns)
Simon Kelley824af852008-02-12 20:43:05 +00001544 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001545 m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1546 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001547 if (m >= 1)
Simon Kelleyb485ed92013-10-18 22:00:39 +01001548 {
1549 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1550 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001551 daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
Simon Kelleyb485ed92013-10-18 22:00:39 +01001552 }
Simon Kelley824af852008-02-12 20:43:05 +00001553 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001554 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001555#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001556 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001557 int ad_reqd = do_bit;
1558 /* RFC 6840 5.7 */
1559 if (header->hb4 & HB4_AD)
1560 ad_reqd = 1;
1561
1562 m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1563 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001564
1565 if (m >= 1)
1566 {
1567 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1568 (char *)header, m, &source_addr, &dst_addr, if_index);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001569 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001570 }
1571 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
Simon Kelley613ad152014-02-25 23:02:28 +00001572 header, (size_t)n, now, NULL, ad_reqd, do_bit))
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001573 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001574 else
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001575 daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001576 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001577}
1578
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001579#ifdef HAVE_DNSSEC
Josh Soref730c6742017-02-06 16:14:04 +00001580/* Recurse up the key hierarchy */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001581static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001582 int class, char *name, char *keyname, struct server *server,
1583 int have_mark, unsigned int mark, int *keycount)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001584{
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001585 int new_status;
Simon Kelley9a31b682015-12-15 10:20:39 +00001586 unsigned char *packet = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001587 unsigned char *payload = NULL;
1588 struct dns_header *new_header = NULL;
1589 u16 *length = NULL;
Simon Kelley361dfe52017-02-10 21:12:30 +00001590
Simon Kelley9a31b682015-12-15 10:20:39 +00001591 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001592 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001593 int type = SERV_DO_DNSSEC;
1594 char *domain;
1595 size_t m;
1596 unsigned char c1, c2;
Simon Kelley361dfe52017-02-10 21:12:30 +00001597 struct server *firstsendto = NULL;
1598
Simon Kelley9a31b682015-12-15 10:20:39 +00001599 /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1600 if (--(*keycount) == 0)
1601 new_status = STAT_ABANDONED;
1602 else if (status == STAT_NEED_KEY)
1603 new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1604 else if (status == STAT_NEED_DS)
1605 new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1606 else
James Bottomleye33b4872017-03-17 21:44:10 +00001607 new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
Simon Kelleya6918532018-04-15 16:20:52 +01001608 !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
Simon Kelleyfef2f1c2019-08-29 21:59:00 +01001609 NULL, NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001610
Simon Kelley9a31b682015-12-15 10:20:39 +00001611 if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1612 break;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001613
Simon Kelley9a31b682015-12-15 10:20:39 +00001614 /* Can't validate because we need a key/DS whose name now in keyname.
1615 Make query for same, and recurse to validate */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001616 if (!packet)
Simon Kelley9a31b682015-12-15 10:20:39 +00001617 {
1618 packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1619 payload = &packet[2];
1620 new_header = (struct dns_header *)payload;
1621 length = (u16 *)packet;
1622 }
1623
1624 if (!packet)
1625 {
1626 new_status = STAT_ABANDONED;
1627 break;
1628 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001629
Simon Kelley33702ab2015-12-28 23:17:15 +00001630 m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
Simon Kelleye1791f32018-10-06 23:23:23 +01001631 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, server->edns_pktsz);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001632
Simon Kelley7fa836e2014-02-10 20:11:24 +00001633 *length = htons(m);
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001634
1635 /* Find server to forward to. This will normally be the
1636 same as for the original query, but may be another if
1637 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001638 if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001639 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001640 new_status = STAT_ABANDONED;
1641 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001642 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001643
Simon Kelley361dfe52017-02-10 21:12:30 +00001644 while (1)
1645 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001646 int data_sent = 0;
1647
Simon Kelley361dfe52017-02-10 21:12:30 +00001648 if (!firstsendto)
1649 firstsendto = server;
1650 else
1651 {
1652 if (!(server = server->next))
1653 server = daemon->servers;
1654 if (server == firstsendto)
1655 {
1656 /* can't find server to accept our query. */
1657 new_status = STAT_ABANDONED;
1658 break;
1659 }
1660 }
1661
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001662 if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001663 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1664 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1665 continue;
Simon Kelleye1791f32018-10-06 23:23:23 +01001666
1667 retry:
1668 /* may need to make new connection. */
1669 if (server->tcpfd == -1)
1670 {
1671 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1672 continue; /* No good, next server */
1673
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001674#ifdef HAVE_CONNTRACK
Simon Kelleye1791f32018-10-06 23:23:23 +01001675 /* Copy connection mark of incoming query to outgoing connection. */
1676 if (have_mark)
1677 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001678#endif
Simon Kelleye1791f32018-10-06 23:23:23 +01001679
Simon Kelley608aa9f2019-03-10 22:44:15 +00001680 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1))
1681 {
1682 close(server->tcpfd);
1683 server->tcpfd = -1;
1684 continue; /* No good, next server */
1685 }
1686
1687#ifdef MSG_FASTOPEN
1688 while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
1689 MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
1690
1691 if (errno == 0)
1692 data_sent = 1;
1693#endif
1694
1695 if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
Simon Kelleye1791f32018-10-06 23:23:23 +01001696 {
1697 close(server->tcpfd);
1698 server->tcpfd = -1;
1699 continue; /* No good, next server */
1700 }
1701
1702 server->flags &= ~SERV_GOT_TCP;
1703 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001704
Simon Kelley608aa9f2019-03-10 22:44:15 +00001705 if ((!data_sent && !read_write(server->tcpfd, packet, m + sizeof(u16), 0)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001706 !read_write(server->tcpfd, &c1, 1, 1) ||
1707 !read_write(server->tcpfd, &c2, 1, 1) ||
1708 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1709 {
1710 close(server->tcpfd);
1711 server->tcpfd = -1;
1712 /* We get data then EOF, reopen connection to same server,
1713 else try next. This avoids DoS from a server which accepts
1714 connections and then closes them. */
1715 if (server->flags & SERV_GOT_TCP)
1716 goto retry;
1717 else
1718 continue;
1719 }
Simon Kelleye1791f32018-10-06 23:23:23 +01001720
1721
1722 if (server->addr.sa.sa_family == AF_INET)
Simon Kelleycc921df2019-01-02 22:48:59 +00001723 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (union all_addr *)&(server->addr.in.sin_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001724 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelleye1791f32018-10-06 23:23:23 +01001725 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001726 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
Simon Kelleye1791f32018-10-06 23:23:23 +01001727 querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
Simon Kelley361dfe52017-02-10 21:12:30 +00001728
1729 server->flags |= SERV_GOT_TCP;
1730
1731 m = (c1 << 8) | c2;
1732 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1733 break;
1734 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001735
1736 if (new_status != STAT_OK)
1737 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001738 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001739
Simon Kelley9a31b682015-12-15 10:20:39 +00001740 if (packet)
1741 free(packet);
1742
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001743 return new_status;
1744}
1745#endif
1746
1747
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001748/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001749 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001750 about resources for debug mode, when the fork is suppressed: that's
1751 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001752unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001753 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001754{
Simon Kelley28866e92011-02-14 20:19:14 +00001755 size_t size = 0;
1756 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001757#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001758 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001759#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001760 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001761 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001762 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001763 unsigned short qtype;
1764 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001765 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001766 /* Max TCP packet + slop + size */
1767 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1768 unsigned char *payload = &packet[2];
1769 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1770 struct dns_header *header = (struct dns_header *)payload;
1771 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001772 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001773 struct in_addr dst_addr_4;
1774 union mysockaddr peer_addr;
1775 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001776 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001777 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001778 unsigned int mark = 0;
1779 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001780
Simon Kelleyd05dd582016-01-19 21:23:30 +00001781 (void)mark;
1782 (void)have_mark;
1783
Simon Kelley7de060b2011-08-26 17:24:52 +01001784 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1785 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001786
1787#ifdef HAVE_CONNTRACK
1788 /* Get connection mark of incoming query to set on outgoing connections. */
1789 if (option_bool(OPT_CONNTRACK))
1790 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001791 union all_addr local;
Simon Kelleyee875042018-10-23 22:10:17 +01001792
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001793 if (local_addr->sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001794 local.addr6 = local_addr->in6.sin6_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001795 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001796 local.addr4 = local_addr->in.sin_addr;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001797
1798 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1799 }
1800#endif
1801
Simon Kelleyc8a80482014-03-05 14:29:54 +00001802 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1803 if (option_bool(OPT_LOCAL_SERVICE))
1804 {
1805 struct addrlist *addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001806
Simon Kelleyc8a80482014-03-05 14:29:54 +00001807 if (peer_addr.sa.sa_family == AF_INET6)
1808 {
1809 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1810 if ((addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001811 is_same_net6(&addr->addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001812 break;
1813 }
1814 else
Simon Kelleyc8a80482014-03-05 14:29:54 +00001815 {
1816 struct in_addr netmask;
1817 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1818 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001819 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001820 if (!(addr->flags & ADDRLIST_IPV6) &&
Simon Kelleycc921df2019-01-02 22:48:59 +00001821 is_same_net(addr->addr.addr4, peer_addr.in.sin_addr, netmask))
Simon Kelleyc8a80482014-03-05 14:29:54 +00001822 break;
1823 }
1824 }
1825 if (!addr)
1826 {
1827 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1828 return packet;
1829 }
1830 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001831
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001832 while (1)
1833 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001834 if (query_count == TCP_MAX_QUERIES ||
1835 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001836 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1837 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001838 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001839 return packet;
1840
Simon Kelley572b41e2011-02-18 18:11:18 +00001841 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001842 continue;
Simon Kelley63437ff2017-09-06 22:34:21 +01001843
1844 /* Clear buffer beyond request to avoid risk of
1845 information disclosure. */
1846 memset(payload + size, 0, 65536 - size);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001847
Simon Kelley25cf5e32015-01-09 15:53:03 +00001848 query_count++;
1849
1850 /* log_query gets called indirectly all over the place, so
1851 pass these in global variables - sorry. */
1852 daemon->log_display_id = ++daemon->log_id;
1853 daemon->log_source_addr = &peer_addr;
1854
Simon Kelley28866e92011-02-14 20:19:14 +00001855 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001856 if ((checking_disabled = header->hb4 & HB4_CD))
1857 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001858
Simon Kelley3be34542004-09-11 19:12:13 +01001859 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001860 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001861#ifdef HAVE_AUTH
1862 struct auth_zone *zone;
1863#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001864 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001865
1866 if (peer_addr.sa.sa_family == AF_INET)
1867 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001868 (union all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelley7de060b2011-08-26 17:24:52 +01001869 else
1870 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00001871 (union all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001872
1873#ifdef HAVE_AUTH
1874 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001875 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001876 for (zone = daemon->auth_zones; zone; zone = zone->next)
1877 if (in_zone(zone, daemon->namebuff, NULL))
1878 {
1879 auth_dns = 1;
1880 local_auth = 1;
1881 break;
1882 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001883#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001884 }
1885
Simon Kelley7de060b2011-08-26 17:24:52 +01001886 if (local_addr->sa.sa_family == AF_INET)
1887 dst_addr_4 = local_addr->in.sin_addr;
1888 else
1889 dst_addr_4.s_addr = 0;
1890
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001891 do_bit = 0;
1892
Simon Kelley5bb88f02015-12-21 16:23:47 +00001893 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001894 {
1895 unsigned short flags;
1896
1897 have_pseudoheader = 1;
1898 pheader += 4; /* udp_size, ext_rcode */
1899 GETSHORT(flags, pheader);
1900
1901 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001902 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001903 }
1904
Simon Kelley4820dce2012-12-18 18:30:30 +00001905#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001906 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001907 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1908 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001909 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001910#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001911 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001912 int ad_reqd = do_bit;
1913 /* RFC 6840 5.7 */
1914 if (header->hb4 & HB4_AD)
1915 ad_reqd = 1;
1916
1917 /* m > 0 if answered from cache */
1918 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1919 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001920
Simon Kelley4f7b3042012-11-28 21:27:02 +00001921 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001922 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001923
1924 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001925 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001926 unsigned int flags = 0;
Simon Kelleycc921df2019-01-02 22:48:59 +00001927 union all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001928 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001929 char *domain = NULL;
Simon Kelley6fd5d792017-10-13 22:26:40 +01001930 unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
Simon Kelleyed4c0762013-10-08 20:46:34 +01001931
Simon Kelley6fd5d792017-10-13 22:26:40 +01001932 size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
1933
Simon Kelley4f7b3042012-11-28 21:27:02 +00001934 if (gotname)
1935 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley6fd5d792017-10-13 22:26:40 +01001936
1937#ifdef HAVE_DNSSEC
1938 if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
1939 {
1940 size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1941
1942 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1943 this allows it to select auth servers when one is returning bad data. */
1944 if (option_bool(OPT_DNSSEC_DEBUG))
1945 header->hb4 |= HB4_CD;
1946 }
1947#endif
1948
1949 /* Check if we added a pheader on forwarding - may need to
1950 strip it from the reply. */
1951 if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
1952 added_pheader = 1;
1953
Simon Kelley367341f2016-01-12 15:58:23 +00001954 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001955
Simon Kelley4f7b3042012-11-28 21:27:02 +00001956 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1957 last_server = daemon->servers;
1958 else
1959 last_server = daemon->last_server;
1960
1961 if (!flags && last_server)
1962 {
1963 struct server *firstsendto = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001964#ifdef HAVE_DNSSEC
Simon Kelley703c7ff2014-01-25 23:46:23 +00001965 unsigned char *newhash, hash[HASH_SIZE];
Simon Kelley63758382014-04-16 22:20:55 +01001966 if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001967 memcpy(hash, newhash, HASH_SIZE);
Tomas Hozzab37f8b92014-03-25 20:52:28 +00001968 else
1969 memset(hash, 0, HASH_SIZE);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001970#else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001971 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001972#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001973 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001974 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001975 which can go to the same server, do so. */
1976 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001977 {
Simon Kelley608aa9f2019-03-10 22:44:15 +00001978 int data_sent = 0;
1979
Simon Kelley4f7b3042012-11-28 21:27:02 +00001980 if (!firstsendto)
1981 firstsendto = last_server;
1982 else
1983 {
1984 if (!(last_server = last_server->next))
1985 last_server = daemon->servers;
1986
1987 if (last_server == firstsendto)
1988 break;
1989 }
1990
1991 /* server for wrong domain */
1992 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001993 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
1994 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01001995 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00001996
1997 retry:
Simon Kelley608aa9f2019-03-10 22:44:15 +00001998 *length = htons(size);
1999
Simon Kelley4f7b3042012-11-28 21:27:02 +00002000 if (last_server->tcpfd == -1)
2001 {
2002 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
2003 continue;
2004
Karl Vogele9828b62014-10-03 21:45:15 +01002005#ifdef HAVE_CONNTRACK
2006 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002007 if (have_mark)
2008 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Simon Kelley608aa9f2019-03-10 22:44:15 +00002009#endif
Karl Vogele9828b62014-10-03 21:45:15 +01002010
Simon Kelley608aa9f2019-03-10 22:44:15 +00002011 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1)))
2012 {
2013 close(last_server->tcpfd);
2014 last_server->tcpfd = -1;
2015 continue;
2016 }
2017
2018#ifdef MSG_FASTOPEN
2019 while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
2020 MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
2021
2022 if (errno == 0)
2023 data_sent = 1;
2024#endif
2025
2026 if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
Simon Kelley4f7b3042012-11-28 21:27:02 +00002027 {
2028 close(last_server->tcpfd);
2029 last_server->tcpfd = -1;
2030 continue;
2031 }
2032
Simon Kelley361dfe52017-02-10 21:12:30 +00002033 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002034 }
2035
Simon Kelley1fc02682014-04-29 12:30:18 +01002036 /* get query name again for logging - may have been overwritten */
2037 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
2038 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00002039
Simon Kelley608aa9f2019-03-10 22:44:15 +00002040 if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00002041 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002042 !read_write(last_server->tcpfd, &c2, 1, 1) ||
2043 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01002044 {
2045 close(last_server->tcpfd);
2046 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00002047 /* We get data then EOF, reopen connection to same server,
2048 else try next. This avoids DoS from a server which accepts
2049 connections and then closes them. */
2050 if (last_server->flags & SERV_GOT_TCP)
2051 goto retry;
2052 else
2053 continue;
2054 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002055
Simon Kelley361dfe52017-02-10 21:12:30 +00002056 last_server->flags |= SERV_GOT_TCP;
2057
Simon Kelley4f7b3042012-11-28 21:27:02 +00002058 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002059
Simon Kelley4f7b3042012-11-28 21:27:02 +00002060 if (last_server->addr.sa.sa_family == AF_INET)
2061 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002062 (union all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002063 else
2064 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelleycc921df2019-01-02 22:48:59 +00002065 (union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002066
2067#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00002068 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002069 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00002070 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00002071 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
2072 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01002073 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002074
Simon Kelley9a31b682015-12-15 10:20:39 +00002075 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00002076 {
2077 result = "ABANDONED";
2078 status = STAT_BOGUS;
2079 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00002080 else
2081 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01002082
2083 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
2084 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01002085
Simon Kelley07ed5852018-05-04 21:52:22 +01002086 log_query(F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00002087
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002088 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01002089 {
2090 no_cache_dnssec = 1;
2091 bogusanswer = 1;
2092 }
2093
Simon Kelley7d7b7b32014-01-08 15:53:35 +00002094 if (status == STAT_SECURE)
2095 cache_secure = 1;
2096 }
2097#endif
2098
2099 /* restore CD bit to the value in the query */
2100 if (checking_disabled)
2101 header->hb4 |= HB4_CD;
2102 else
2103 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00002104
2105 /* There's no point in updating the cache, since this process will exit and
2106 lose the information after a few queries. We make this call for the alias and
2107 bogus-nxdomain side-effects. */
2108 /* If the crc of the question section doesn't match the crc we sent, then
2109 someone might be attempting to insert bogus values into the cache by
2110 sending replies containing questions and bogus answers. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002111#ifdef HAVE_DNSSEC
2112 newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
2113 if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00002114 {
2115 m = 0;
2116 break;
2117 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002118#else
2119 if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
Simon Kelley703c7ff2014-01-25 23:46:23 +00002120 {
2121 m = 0;
2122 break;
2123 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002124#endif
2125
2126 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01002127 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00002128 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00002129
2130 break;
2131 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002132 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002133
2134 /* In case of local answer or no connections made. */
2135 if (m == 0)
Simon Kelley1682d152018-08-03 20:38:18 +01002136 {
2137 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
2138 if (have_pseudoheader)
2139 m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
2140 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002141 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002142 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002143
Simon Kelleyb842bc92015-07-12 21:09:11 +01002144 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002145
Simon Kelley4b5ea122013-04-22 10:18:26 +01002146 *length = htons(m);
2147
2148 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002149 return packet;
2150 }
2151}
2152
Simon Kelley16972692006-10-16 20:04:18 +01002153static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002154{
Simon Kelley16972692006-10-16 20:04:18 +01002155 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002156
Simon Kelley5aabfc72007-08-29 11:24:47 +01002157 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002158 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002159 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002160 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00002161 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002162 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002163 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002164 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002165#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002166 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002167 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002168 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002169#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002170 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002171 }
Simon Kelley16972692006-10-16 20:04:18 +01002172
2173 return f;
2174}
2175
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002176struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002177{
2178 static int finger = 0;
2179 int i;
2180
2181 /* limit the number of sockets we have open to avoid starvation of
2182 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2183
2184 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002185 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002186 {
Simon Kelley9009d742008-11-14 20:04:27 +00002187 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2188 break;
2189
Simon Kelley1a6bca82008-07-11 11:11:42 +01002190 daemon->randomsocks[i].refcount = 1;
2191 daemon->randomsocks[i].family = family;
2192 return &daemon->randomsocks[i];
2193 }
2194
Simon Kelley9009d742008-11-14 20:04:27 +00002195 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002196 for (i = 0; i < RANDOM_SOCKS; i++)
2197 {
2198 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002199 if (daemon->randomsocks[j].refcount != 0 &&
2200 daemon->randomsocks[j].family == family &&
2201 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002202 {
2203 finger = j;
2204 daemon->randomsocks[j].refcount++;
2205 return &daemon->randomsocks[j];
2206 }
2207 }
2208
2209 return NULL; /* doom */
2210}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002211
2212void free_rfd(struct randfd *rfd)
2213{
2214 if (rfd && --(rfd->refcount) == 0)
2215 close(rfd->fd);
2216}
2217
Simon Kelley1a6bca82008-07-11 11:11:42 +01002218static void free_frec(struct frec *f)
2219{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002220 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002221 f->rfd4 = NULL;
2222 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002223 f->flags = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002224 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002225 f->rfd6 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002226
2227#ifdef HAVE_DNSSEC
2228 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002229 {
2230 blockdata_free(f->stash);
2231 f->stash = NULL;
2232 }
Simon Kelley3a237152013-12-12 12:15:50 +00002233
2234 /* Anything we're waiting on is pointless now, too */
2235 if (f->blocking_query)
2236 free_frec(f->blocking_query);
2237 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002238 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002239#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002240}
2241
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002242
2243
Simon Kelley16972692006-10-16 20:04:18 +01002244/* if wait==NULL return a free or older than TIMEOUT record.
2245 else return *wait zero if one available, or *wait is delay to
Simon Kelley1a6bca82008-07-11 11:11:42 +01002246 when the oldest in-use record will expire. Impose an absolute
Simon Kelley3a237152013-12-12 12:15:50 +00002247 limit of 4*TIMEOUT before we wipe things (for random sockets).
2248 If force is set, always return a result, even if we have
2249 to allocate above the limit. */
2250struct frec *get_new_frec(time_t now, int *wait, int force)
Simon Kelley16972692006-10-16 20:04:18 +01002251{
Simon Kelley1a6bca82008-07-11 11:11:42 +01002252 struct frec *f, *oldest, *target;
Simon Kelley16972692006-10-16 20:04:18 +01002253 int count;
2254
2255 if (wait)
2256 *wait = 0;
2257
Simon Kelley1a6bca82008-07-11 11:11:42 +01002258 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
Simon Kelley832af0b2007-01-21 20:01:28 +00002259 if (!f->sentto)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002260 target = f;
2261 else
Simon Kelley16972692006-10-16 20:04:18 +01002262 {
Simon Kelley9a31b682015-12-15 10:20:39 +00002263#ifdef HAVE_DNSSEC
2264 /* Don't free DNSSEC sub-queries here, as we may end up with
2265 dangling references to them. They'll go when their "real" query
2266 is freed. */
2267 if (!f->dependent)
2268#endif
2269 {
2270 if (difftime(now, f->time) >= 4*TIMEOUT)
2271 {
2272 free_frec(f);
2273 target = f;
2274 }
2275
2276
2277 if (!oldest || difftime(f->time, oldest->time) <= 0)
2278 oldest = f;
2279 }
Simon Kelley16972692006-10-16 20:04:18 +01002280 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01002281
2282 if (target)
2283 {
2284 target->time = now;
2285 return target;
2286 }
Simon Kelley16972692006-10-16 20:04:18 +01002287
2288 /* can't find empty one, use oldest if there is one
2289 and it's older than timeout */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002290 if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
Simon Kelley16972692006-10-16 20:04:18 +01002291 {
2292 /* keep stuff for twice timeout if we can by allocating a new
2293 record instead */
2294 if (difftime(now, oldest->time) < 2*TIMEOUT &&
2295 count <= daemon->ftabsize &&
2296 (f = allocate_frec(now)))
2297 return f;
2298
2299 if (!wait)
2300 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002301 free_frec(oldest);
Simon Kelley16972692006-10-16 20:04:18 +01002302 oldest->time = now;
2303 }
2304 return oldest;
2305 }
2306
2307 /* none available, calculate time 'till oldest record expires */
Simon Kelley3a237152013-12-12 12:15:50 +00002308 if (!force && count > daemon->ftabsize)
Simon Kelley16972692006-10-16 20:04:18 +01002309 {
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002310 static time_t last_log = 0;
2311
Simon Kelley16972692006-10-16 20:04:18 +01002312 if (oldest && wait)
2313 *wait = oldest->time + (time_t)TIMEOUT - now;
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002314
2315 if ((int)difftime(now, last_log) > 5)
2316 {
2317 last_log = now;
2318 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2319 }
2320
Simon Kelley16972692006-10-16 20:04:18 +01002321 return NULL;
2322 }
2323
2324 if (!(f = allocate_frec(now)) && wait)
2325 /* wait one second on malloc failure */
2326 *wait = 1;
2327
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002328 return f; /* OK if malloc fails and this is NULL */
2329}
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002330
Simon Kelley832af0b2007-01-21 20:01:28 +00002331/* crc is all-ones if not known. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002332static struct frec *lookup_frec(unsigned short id, void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002333{
2334 struct frec *f;
2335
Simon Kelley1a6bca82008-07-11 11:11:42 +01002336 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002337 if (f->sentto && f->new_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002338 (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002339 return f;
2340
2341 return NULL;
2342}
2343
2344static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002345 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002346 void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002347{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002348 struct frec *f;
2349
Simon Kelley1a6bca82008-07-11 11:11:42 +01002350 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002351 if (f->sentto &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002352 f->orig_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002353 memcmp(hash, f->hash, HASH_SIZE) == 0 &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002354 sockaddr_isequal(&f->source, addr))
2355 return f;
2356
2357 return NULL;
2358}
Simon Kelley47a95162014-07-08 22:22:02 +01002359
2360/* Send query packet again, if we can. */
2361void resend_query()
2362{
2363 if (daemon->srv_save)
2364 {
2365 int fd;
2366
2367 if (daemon->srv_save->sfd)
2368 fd = daemon->srv_save->sfd->fd;
2369 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2370 fd = daemon->rfd_save->fd;
2371 else
2372 return;
2373
Simon Kelleyff841eb2015-03-11 21:36:30 +00002374 while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2375 &daemon->srv_save->addr.sa,
2376 sa_len(&daemon->srv_save->addr))));
Simon Kelley47a95162014-07-08 22:22:02 +01002377 }
2378}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002379
Simon Kelley849a8352006-06-09 21:02:31 +01002380/* A server record is going away, remove references to it */
Simon Kelley5aabfc72007-08-29 11:24:47 +01002381void server_gone(struct server *server)
Simon Kelley849a8352006-06-09 21:02:31 +01002382{
2383 struct frec *f;
2384
Simon Kelley1a6bca82008-07-11 11:11:42 +01002385 for (f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002386 if (f->sentto && f->sentto == server)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002387 free_frec(f);
Simon Kelley849a8352006-06-09 21:02:31 +01002388
2389 if (daemon->last_server == server)
2390 daemon->last_server = NULL;
2391
2392 if (daemon->srv_save == server)
2393 daemon->srv_save = NULL;
2394}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002395
Simon Kelley316e2732010-01-22 20:16:09 +00002396/* return unique random ids. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002397static unsigned short get_id(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002398{
2399 unsigned short ret = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +00002400
Simon Kelley316e2732010-01-22 20:16:09 +00002401 do
Simon Kelley832af0b2007-01-21 20:01:28 +00002402 ret = rand16();
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002403 while (lookup_frec(ret, NULL));
Simon Kelley832af0b2007-01-21 20:01:28 +00002404
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002405 return ret;
2406}
2407
2408
2409
2410
2411