blob: cdd11d302ff5138782404732d63e35f849f2104b [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,
29 union mysockaddr *to, struct all_addr *source,
Simon Kelley50303b12012-04-04 22:13:17 +010030 unsigned int iface)
Simon Kelley9e4abcb2004-01-22 19:47:41 +000031{
Simon Kelley44a2a312004-03-10 20:04:35 +000032 struct msghdr msg;
33 struct iovec iov[1];
Simon Kelley44a2a312004-03-10 20:04:35 +000034 union {
35 struct cmsghdr align; /* this ensures alignment */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010036#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +000037 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
38#elif defined(IP_SENDSRCADDR)
39 char control[CMSG_SPACE(sizeof(struct in_addr))];
40#endif
41#ifdef HAVE_IPV6
42 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
43#endif
44 } control_u;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010045
Simon Kelley44a2a312004-03-10 20:04:35 +000046 iov[0].iov_base = packet;
47 iov[0].iov_len = len;
48
Simon Kelleyfeba5c12004-07-27 20:28:58 +010049 msg.msg_control = NULL;
50 msg.msg_controllen = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +000051 msg.msg_flags = 0;
52 msg.msg_name = to;
53 msg.msg_namelen = sa_len(to);
54 msg.msg_iov = iov;
55 msg.msg_iovlen = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010056
Simon Kelley26128d22004-11-14 16:43:54 +000057 if (!nowild)
Simon Kelleyfeba5c12004-07-27 20:28:58 +010058 {
Simon Kelley26128d22004-11-14 16:43:54 +000059 struct cmsghdr *cmptr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +010060 msg.msg_control = &control_u;
61 msg.msg_controllen = sizeof(control_u);
Simon Kelley26128d22004-11-14 16:43:54 +000062 cmptr = CMSG_FIRSTHDR(&msg);
Simon Kelley44a2a312004-03-10 20:04:35 +000063
Simon Kelley26128d22004-11-14 16:43:54 +000064 if (to->sa.sa_family == AF_INET)
65 {
Simon Kelley5e9e0ef2006-04-17 14:24:29 +010066#if defined(HAVE_LINUX_NETWORK)
Simon Kelley8ef5ada2010-06-03 19:42:45 +010067 struct in_pktinfo p;
68 p.ipi_ifindex = 0;
69 p.ipi_spec_dst = source->addr.addr4;
70 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Simon Kelley26128d22004-11-14 16:43:54 +000071 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
Simon Kelleyc72daea2012-01-05 21:33:27 +000072 cmptr->cmsg_level = IPPROTO_IP;
Simon Kelley26128d22004-11-14 16:43:54 +000073 cmptr->cmsg_type = IP_PKTINFO;
74#elif defined(IP_SENDSRCADDR)
Simon Kelley8ef5ada2010-06-03 19:42:45 +010075 memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
Simon Kelley26128d22004-11-14 16:43:54 +000076 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
77 cmptr->cmsg_level = IPPROTO_IP;
78 cmptr->cmsg_type = IP_SENDSRCADDR;
Simon Kelley44a2a312004-03-10 20:04:35 +000079#endif
Simon Kelley26128d22004-11-14 16:43:54 +000080 }
Simon Kelley26128d22004-11-14 16:43:54 +000081 else
Simon Kelleyb8187c82005-11-26 21:46:27 +000082#ifdef HAVE_IPV6
Simon Kelley26128d22004-11-14 16:43:54 +000083 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +010084 struct in6_pktinfo p;
85 p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
86 p.ipi6_addr = source->addr.addr6;
87 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
Simon Kelley26128d22004-11-14 16:43:54 +000088 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
Simon Kelley316e2732010-01-22 20:16:09 +000089 cmptr->cmsg_type = daemon->v6pktinfo;
Simon Kelleyc72daea2012-01-05 21:33:27 +000090 cmptr->cmsg_level = IPPROTO_IPV6;
Simon Kelley26128d22004-11-14 16:43:54 +000091 }
Simon Kelley3d8df262005-08-29 12:19:27 +010092#else
Simon Kelleyc72daea2012-01-05 21:33:27 +000093 (void)iface; /* eliminate warning */
Simon Kelley26128d22004-11-14 16:43:54 +000094#endif
95 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +010096
Simon Kelleyff841eb2015-03-11 21:36:30 +000097 while (retry_send(sendmsg(fd, &msg, 0)));
98
99 /* If interface is still in DAD, EINVAL results - ignore that. */
100 if (errno != 0 && errno != EINVAL)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100101 {
Simon Kelley50303b12012-04-04 22:13:17 +0100102 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
Simon Kelley29689cf2012-03-22 14:01:00 +0000103 return 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100104 }
Simon Kelley29d28dd2012-12-03 14:05:59 +0000105
Simon Kelley29689cf2012-03-22 14:01:00 +0000106 return 1;
Simon Kelley44a2a312004-03-10 20:04:35 +0000107}
108
Simon Kelley367341f2016-01-12 15:58:23 +0000109static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
110 char *qdomain, int *type, char **domain, int *norebind)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100111
112{
113 /* If the query ends in the domain in one of our servers, set
114 domain to point to that name. We find the largest match to allow both
115 domain.org and sub.domain.org to exist. */
116
117 unsigned int namelen = strlen(qdomain);
118 unsigned int matchlen = 0;
119 struct server *serv;
Simon Kelley28866e92011-02-14 20:19:14 +0000120 unsigned int flags = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100121
Simon Kelley3be34542004-09-11 19:12:13 +0100122 for (serv = daemon->servers; serv; serv=serv->next)
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100123 if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
124 continue;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100125 /* domain matches take priority over NODOTS matches */
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100126 else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100127 {
Simon Kelley28866e92011-02-14 20:19:14 +0000128 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100129 *type = SERV_FOR_NODOTS;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100130 if (serv->flags & SERV_NO_ADDR)
Simon Kelley36717ee2004-09-20 19:20:58 +0100131 flags = F_NXDOMAIN;
132 else if (serv->flags & SERV_LITERAL_ADDRESS)
133 {
134 if (sflag & qtype)
135 {
136 flags = sflag;
137 if (serv->addr.sa.sa_family == AF_INET)
138 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100139#ifdef HAVE_IPV6
Simon Kelley36717ee2004-09-20 19:20:58 +0100140 else
141 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100142#endif
Simon Kelley36717ee2004-09-20 19:20:58 +0100143 }
Simon Kelley824af852008-02-12 20:43:05 +0000144 else if (!flags || (flags & F_NXDOMAIN))
Simon Kelley36717ee2004-09-20 19:20:58 +0100145 flags = F_NOERR;
146 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100147 }
148 else if (serv->flags & SERV_HAS_DOMAIN)
149 {
150 unsigned int domainlen = strlen(serv->domain);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000151 char *matchstart = qdomain + namelen - domainlen;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100152 if (namelen >= domainlen &&
Simon Kelleyb8187c82005-11-26 21:46:27 +0000153 hostname_isequal(matchstart, serv->domain) &&
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100154 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100155 {
Simon Kelley92be34a2016-01-16 18:39:54 +0000156 if ((serv->flags & SERV_NO_REBIND) && norebind)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100157 *norebind = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000158 else
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100159 {
Simon Kelley28866e92011-02-14 20:19:14 +0000160 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
161 /* implement priority rules for --address and --server for same domain.
162 --address wins if the address is for the correct AF
163 --server wins otherwise. */
164 if (domainlen != 0 && domainlen == matchlen)
Simon Kelley36717ee2004-09-20 19:20:58 +0100165 {
Simon Kelley28866e92011-02-14 20:19:14 +0000166 if ((serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100167 {
Simon Kelley28866e92011-02-14 20:19:14 +0000168 if (!(sflag & qtype) && flags == 0)
169 continue;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100170 }
Simon Kelley28866e92011-02-14 20:19:14 +0000171 else
172 {
173 if (flags & (F_IPV4 | F_IPV6))
174 continue;
175 }
Simon Kelley36717ee2004-09-20 19:20:58 +0100176 }
Simon Kelley28866e92011-02-14 20:19:14 +0000177
178 if (domainlen >= matchlen)
179 {
Simon Kelley367341f2016-01-12 15:58:23 +0000180 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
Simon Kelley28866e92011-02-14 20:19:14 +0000181 *domain = serv->domain;
182 matchlen = domainlen;
183 if (serv->flags & SERV_NO_ADDR)
184 flags = F_NXDOMAIN;
185 else if (serv->flags & SERV_LITERAL_ADDRESS)
186 {
187 if (sflag & qtype)
188 {
189 flags = sflag;
190 if (serv->addr.sa.sa_family == AF_INET)
191 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
192#ifdef HAVE_IPV6
193 else
194 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
195#endif
196 }
197 else if (!flags || (flags & F_NXDOMAIN))
198 flags = F_NOERR;
199 }
200 else
201 flags = 0;
202 }
203 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100204 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100205 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100206
Simon Kelleybf05f8f2017-05-09 22:37:46 +0100207 if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) &&
Simon Kelley28866e92011-02-14 20:19:14 +0000208 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
Simon Kelley7de060b2011-08-26 17:24:52 +0100209 /* don't forward A or AAAA queries for simple names, except the empty name */
210 flags = F_NOERR;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100211
Simon Kelley5aabfc72007-08-29 11:24:47 +0100212 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
Simon Kelleyc1bb8502004-08-11 18:40:17 +0100213 flags = F_NOERR;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100214
Simon Kelley824af852008-02-12 20:43:05 +0000215 if (flags)
216 {
217 int logflags = 0;
218
219 if (flags == F_NXDOMAIN || flags == F_NOERR)
220 logflags = F_NEG | qtype;
221
Simon Kelley1a6bca82008-07-11 11:11:42 +0100222 log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
Simon Kelley824af852008-02-12 20:43:05 +0000223 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100224 else if ((*type) & SERV_USE_RESOLV)
225 {
226 *type = 0; /* use normal servers for this domain */
227 *domain = NULL;
228 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100229 return flags;
230}
Simon Kelley44a2a312004-03-10 20:04:35 +0000231
Simon Kelley824af852008-02-12 20:43:05 +0000232static int forward_query(int udpfd, union mysockaddr *udpaddr,
233 struct all_addr *dst_addr, unsigned int dst_iface,
Simon Kelley83349b82014-02-10 21:02:01 +0000234 struct dns_header *header, size_t plen, time_t now,
Simon Kelley613ad152014-02-25 23:02:28 +0000235 struct frec *forward, int ad_reqd, int do_bit)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000236{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000237 char *domain = NULL;
Simon Kelley367341f2016-01-12 15:58:23 +0000238 int type = SERV_DO_DNSSEC, norebind = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000239 struct all_addr *addrp = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000240 unsigned int flags = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100241 struct server *start = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000242#ifdef HAVE_DNSSEC
243 void *hash = hash_questions(header, plen, daemon->namebuff);
Simon Kelley367341f2016-01-12 15:58:23 +0000244 int do_dnssec = 0;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000245#else
246 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
247 void *hash = &crc;
248#endif
249 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
250
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000251 (void)do_bit;
252
Simon Kelley3d8df262005-08-29 12:19:27 +0100253 /* may be no servers available. */
Simon Kelleyd05dd582016-01-19 21:23:30 +0000254 if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000255 {
Simon Kelleya77cec82015-05-08 16:25:38 +0100256 /* If we didn't get an answer advertising a maximal packet in EDNS,
257 fall back to 1280, which should work everywhere on IPv6.
258 If that generates an answer, it will become the new default
259 for this server */
260 forward->flags |= FREC_TEST_PKTSZ;
261
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000262#ifdef HAVE_DNSSEC
Simon Kelleydac74312014-02-13 16:43:49 +0000263 /* If we've already got an answer to this query, but we're awaiting keys for validation,
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000264 there's no point retrying the query, retry the key query instead...... */
265 if (forward->blocking_query)
266 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000267 int fd, is_sign;
268 unsigned char *pheader;
Simon Kelleya77cec82015-05-08 16:25:38 +0100269
270 forward->flags &= ~FREC_TEST_PKTSZ;
271
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000272 while (forward->blocking_query)
273 forward = forward->blocking_query;
Simon Kelleya77cec82015-05-08 16:25:38 +0100274
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000275 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
276 plen = forward->stash_len;
277
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000278 forward->flags |= FREC_TEST_PKTSZ;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000279 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000280 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000281
Simon Kelley2b291912014-03-21 11:13:55 +0000282 if (forward->sentto->addr.sa.sa_family == AF_INET)
Simon Kelley25cf5e32015-01-09 15:53:03 +0000283 log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000284#ifdef HAVE_IPV6
285 else
Simon Kelley25cf5e32015-01-09 15:53:03 +0000286 log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000287#endif
288
289 if (forward->sentto->sfd)
290 fd = forward->sentto->sfd->fd;
291 else
292 {
293#ifdef HAVE_IPV6
294 if (forward->sentto->addr.sa.sa_family == AF_INET6)
295 fd = forward->rfd6->fd;
296 else
297#endif
298 fd = forward->rfd4->fd;
299 }
300
Simon Kelleyff841eb2015-03-11 21:36:30 +0000301 while (retry_send( sendto(fd, (char *)header, plen, 0,
302 &forward->sentto->addr.sa,
303 sa_len(&forward->sentto->addr))));
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000304
305 return 1;
306 }
307#endif
308
Simon Kelleyde379512004-06-22 20:23:33 +0100309 /* retry on existing query, send to all available servers */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000310 domain = forward->sentto->domain;
Simon Kelley824af852008-02-12 20:43:05 +0000311 forward->sentto->failed_queries++;
Simon Kelley28866e92011-02-14 20:19:14 +0000312 if (!option_bool(OPT_ORDER))
Simon Kelleyde379512004-06-22 20:23:33 +0100313 {
Simon Kelley0a852542005-03-23 20:28:59 +0000314 forward->forwardall = 1;
Simon Kelley3be34542004-09-11 19:12:13 +0100315 daemon->last_server = NULL;
Simon Kelleyde379512004-06-22 20:23:33 +0100316 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000317 type = forward->sentto->flags & SERV_TYPE;
Simon Kelley367341f2016-01-12 15:58:23 +0000318#ifdef HAVE_DNSSEC
319 do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
320#endif
321
Simon Kelleyde379512004-06-22 20:23:33 +0100322 if (!(start = forward->sentto->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100323 start = daemon->servers; /* at end of list, recycle */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000324 header->id = htons(forward->new_id);
325 }
326 else
327 {
328 if (gotname)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100329 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000330
Simon Kelley367341f2016-01-12 15:58:23 +0000331#ifdef HAVE_DNSSEC
332 do_dnssec = type & SERV_DO_DNSSEC;
Simon Kelleyf7443d72016-01-19 20:29:57 +0000333#endif
334 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +0000335
Simon Kelleyd05dd582016-01-19 21:23:30 +0000336 if (daemon->servers && !flags)
337 forward = get_new_frec(now, NULL, 0);
338 /* table full - flags == 0, return REFUSED */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000339
340 if (forward)
341 {
Simon Kelley0a852542005-03-23 20:28:59 +0000342 forward->source = *udpaddr;
343 forward->dest = *dst_addr;
344 forward->iface = dst_iface;
Simon Kelley0a852542005-03-23 20:28:59 +0000345 forward->orig_id = ntohs(header->id);
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000346 forward->new_id = get_id();
Simon Kelley832af0b2007-01-21 20:01:28 +0000347 forward->fd = udpfd;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000348 memcpy(forward->hash, hash, HASH_SIZE);
Simon Kelley0a852542005-03-23 20:28:59 +0000349 forward->forwardall = 0;
Simon Kelleyed4c0762013-10-08 20:46:34 +0100350 forward->flags = 0;
Simon Kelley28866e92011-02-14 20:19:14 +0000351 if (norebind)
352 forward->flags |= FREC_NOREBIND;
Simon Kelley572b41e2011-02-18 18:11:18 +0000353 if (header->hb4 & HB4_CD)
Simon Kelley28866e92011-02-14 20:19:14 +0000354 forward->flags |= FREC_CHECKING_DISABLED;
Simon Kelley83349b82014-02-10 21:02:01 +0000355 if (ad_reqd)
356 forward->flags |= FREC_AD_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000357#ifdef HAVE_DNSSEC
358 forward->work_counter = DNSSEC_WORK;
Simon Kelley613ad152014-02-25 23:02:28 +0000359 if (do_bit)
360 forward->flags |= FREC_DO_QUESTION;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000361#endif
Simon Kelley613ad152014-02-25 23:02:28 +0000362
Simon Kelley28866e92011-02-14 20:19:14 +0000363 header->id = htons(forward->new_id);
364
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100365 /* In strict_order mode, always try servers in the order
366 specified in resolv.conf, if a domain is given
367 always try all the available servers,
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000368 otherwise, use the one last known to work. */
369
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100370 if (type == 0)
371 {
Simon Kelley28866e92011-02-14 20:19:14 +0000372 if (option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100373 start = daemon->servers;
374 else if (!(start = daemon->last_server) ||
375 daemon->forwardcount++ > FORWARD_TEST ||
376 difftime(now, daemon->forwardtime) > FORWARD_TIME)
377 {
378 start = daemon->servers;
379 forward->forwardall = 1;
380 daemon->forwardcount = 0;
381 daemon->forwardtime = now;
382 }
383 }
384 else
Simon Kelleyde379512004-06-22 20:23:33 +0100385 {
Simon Kelley3be34542004-09-11 19:12:13 +0100386 start = daemon->servers;
Simon Kelley28866e92011-02-14 20:19:14 +0000387 if (!option_bool(OPT_ORDER))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100388 forward->forwardall = 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100389 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000390 }
391 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100392
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000393 /* check for send errors here (no route to host)
394 if we fail to send to all nameservers, send back an error
395 packet straight away (helps modem users when offline) */
396
397 if (!flags && forward)
398 {
Simon Kelleyde379512004-06-22 20:23:33 +0100399 struct server *firstsentto = start;
Simon Kelley33702ab2015-12-28 23:17:15 +0000400 int subnet, forwarded = 0;
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000401 size_t edns0_len;
Simon Kelley6fd5d792017-10-13 22:26:40 +0100402 unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000403 unsigned char *pheader;
404
Simon Kelley25cf5e32015-01-09 15:53:03 +0000405 /* If a query is retried, use the log_id for the retry when logging the answer. */
406 forward->log_id = daemon->log_id;
407
Simon Kelley6fd5d792017-10-13 22:26:40 +0100408 plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
Simon Kelley33702ab2015-12-28 23:17:15 +0000409
Simon Kelley6fd5d792017-10-13 22:26:40 +0100410 if (subnet)
411 forward->flags |= FREC_HAS_SUBNET;
Simon Kelley33702ab2015-12-28 23:17:15 +0000412
Simon Kelley3a237152013-12-12 12:15:50 +0000413#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000414 if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000415 {
Simon Kelley6fd5d792017-10-13 22:26:40 +0100416 plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
417
Simon Kelley5b3bf922014-01-25 17:03:07 +0000418 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
419 this allows it to select auth servers when one is returning bad data. */
420 if (option_bool(OPT_DNSSEC_DEBUG))
421 header->hb4 |= HB4_CD;
Simon Kelley613ad152014-02-25 23:02:28 +0000422
Simon Kelley0fc2f312014-01-08 10:26:58 +0000423 }
Simon Kelley3a237152013-12-12 12:15:50 +0000424#endif
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000425
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000426 if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
Simon Kelley6fd5d792017-10-13 22:26:40 +0100427 {
428 /* If there wasn't a PH before, and there is now, we added it. */
429 if (!oph)
430 forward->flags |= FREC_ADDED_PHEADER;
431
432 /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
433 if (edns0_len > 11)
434 forward->flags |= FREC_HAS_EXTRADATA;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000435
436 /* Reduce udp size on retransmits. */
437 if (forward->flags & FREC_TEST_PKTSZ)
438 PUTSHORT(SAFE_PKTSZ, pheader);
Simon Kelley6fd5d792017-10-13 22:26:40 +0100439 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100440
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000441 while (1)
442 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000443 /* only send to servers dealing with our domain.
444 domain may be NULL, in which case server->domain
445 must be NULL also. */
446
Simon Kelleyde379512004-06-22 20:23:33 +0100447 if (type == (start->flags & SERV_TYPE) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100448 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100449 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000450 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100451 int fd;
452
453 /* find server socket to use, may need to get random one. */
454 if (start->sfd)
455 fd = start->sfd->fd;
456 else
457 {
458#ifdef HAVE_IPV6
459 if (start->addr.sa.sa_family == AF_INET6)
460 {
461 if (!forward->rfd6 &&
462 !(forward->rfd6 = allocate_rfd(AF_INET6)))
463 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100464 daemon->rfd_save = forward->rfd6;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100465 fd = forward->rfd6->fd;
466 }
467 else
468#endif
469 {
470 if (!forward->rfd4 &&
471 !(forward->rfd4 = allocate_rfd(AF_INET)))
472 break;
Simon Kelley3927da42008-07-20 15:10:39 +0100473 daemon->rfd_save = forward->rfd4;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100474 fd = forward->rfd4->fd;
475 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100476
477#ifdef HAVE_CONNTRACK
478 /* Copy connection mark of incoming query to outgoing connection. */
479 if (option_bool(OPT_CONNTRACK))
480 {
481 unsigned int mark;
Giacomo Tazzari797a7af2013-04-22 13:16:37 +0100482 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
Simon Kelley7de060b2011-08-26 17:24:52 +0100483 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
484 }
485#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100486 }
487
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000488#ifdef HAVE_DNSSEC
Simon Kelley5bb88f02015-12-21 16:23:47 +0000489 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000490 {
491 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
492 packet size to 512. But that won't provide space for the RRSIGS in many cases.
493 The RRSIGS will be stripped out before the answer goes back, so the packet should
494 shrink again. So, if we added a do-bit, bump the udp packet size to the value
Simon Kelley5aa5f0f2015-12-21 17:20:35 +0000495 known to be OK for this server. We check returned size after stripping and set
496 the truncated bit if it's still too big. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000497 unsigned char *pheader;
498 int is_sign;
Simon Kelley5bb88f02015-12-21 16:23:47 +0000499 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000500 PUTSHORT(start->edns_pktsz, pheader);
501 }
502#endif
503
Simon Kelleyff841eb2015-03-11 21:36:30 +0000504 if (retry_send(sendto(fd, (char *)header, plen, 0,
505 &start->addr.sa,
506 sa_len(&start->addr))))
507 continue;
508
509 if (errno == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000510 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000511 /* Keep info in case we want to re-send this packet */
512 daemon->srv_save = start;
513 daemon->packet_len = plen;
514
Simon Kelleyde379512004-06-22 20:23:33 +0100515 if (!gotname)
Simon Kelley3be34542004-09-11 19:12:13 +0100516 strcpy(daemon->namebuff, "query");
Simon Kelleyde379512004-06-22 20:23:33 +0100517 if (start->addr.sa.sa_family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +0100518 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +0100519 (struct all_addr *)&start->addr.in.sin_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100520#ifdef HAVE_IPV6
521 else
Simon Kelley3be34542004-09-11 19:12:13 +0100522 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +0100523 (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
Simon Kelleyde379512004-06-22 20:23:33 +0100524#endif
Simon Kelley824af852008-02-12 20:43:05 +0000525 start->queries++;
Simon Kelleyde379512004-06-22 20:23:33 +0100526 forwarded = 1;
527 forward->sentto = start;
Simon Kelley0a852542005-03-23 20:28:59 +0000528 if (!forward->forwardall)
Simon Kelleyde379512004-06-22 20:23:33 +0100529 break;
Simon Kelley0a852542005-03-23 20:28:59 +0000530 forward->forwardall++;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000531 }
532 }
533
Simon Kelleyde379512004-06-22 20:23:33 +0100534 if (!(start = start->next))
Simon Kelley3be34542004-09-11 19:12:13 +0100535 start = daemon->servers;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000536
Simon Kelleyde379512004-06-22 20:23:33 +0100537 if (start == firstsentto)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000538 break;
539 }
540
Simon Kelleyde379512004-06-22 20:23:33 +0100541 if (forwarded)
Simon Kelley824af852008-02-12 20:43:05 +0000542 return 1;
Simon Kelleyde379512004-06-22 20:23:33 +0100543
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000544 /* could not send on, prepare to return */
545 header->id = htons(forward->orig_id);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100546 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000547 }
548
549 /* could not send on, return empty answer or address if known for whole domain */
Simon Kelleyb8187c82005-11-26 21:46:27 +0000550 if (udpfd != -1)
551 {
Simon Kelleycdeda282006-03-16 20:16:06 +0000552 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
Simon Kelley54dd3932012-06-20 11:23:38 +0100553 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 +0000554 }
555
Simon Kelley824af852008-02-12 20:43:05 +0000556 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000557}
558
Simon Kelleyed4c0762013-10-08 20:46:34 +0100559static 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 +0100560 int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
561 int check_subnet, union mysockaddr *query_source)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100562{
Simon Kelley36717ee2004-09-20 19:20:58 +0100563 unsigned char *pheader, *sizep;
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000564 char **sets = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +0000565 int munged = 0, is_sign;
Simon Kelleycdeda282006-03-16 20:16:06 +0000566 size_t plen;
Simon Kelleya6004d72017-10-25 17:48:19 +0100567
Simon Kelley83349b82014-02-10 21:02:01 +0000568 (void)ad_reqd;
Simon Kelley982faf42015-04-03 21:42:30 +0100569 (void)do_bit;
570 (void)bogusanswer;
Simon Kelley83349b82014-02-10 21:02:01 +0000571
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000572#ifdef HAVE_IPSET
Simon Kelley82a14af2014-04-13 20:48:57 +0100573 if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000574 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100575 /* Similar algorithm to search_servers. */
576 struct ipsets *ipset_pos;
577 unsigned int namelen = strlen(daemon->namebuff);
578 unsigned int matchlen = 0;
579 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
Simon Kelley6c0cb852014-01-17 14:40:46 +0000580 {
Simon Kelley82a14af2014-04-13 20:48:57 +0100581 unsigned int domainlen = strlen(ipset_pos->domain);
582 char *matchstart = daemon->namebuff + namelen - domainlen;
583 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
584 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
585 domainlen >= matchlen)
586 {
587 matchlen = domainlen;
588 sets = ipset_pos->sets;
589 }
Simon Kelley6c0cb852014-01-17 14:40:46 +0000590 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000591 }
592#endif
593
Simon Kelley5bb88f02015-12-21 16:23:47 +0000594 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100595 {
Simon Kelleyed4c0762013-10-08 20:46:34 +0100596 if (check_subnet && !check_source(header, plen, pheader, query_source))
597 {
598 my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
599 return 0;
600 }
Simon Kelley613ad152014-02-25 23:02:28 +0000601
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000602 if (!is_sign)
Simon Kelley613ad152014-02-25 23:02:28 +0000603 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000604 if (added_pheader)
605 {
606 /* client didn't send EDNS0, we added one, strip it off before returning answer. */
607 n = rrfilter(header, n, 0);
608 pheader = NULL;
609 }
610 else
611 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000612 unsigned short udpsz;
613
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000614 /* If upstream is advertising a larger UDP packet size
615 than we allow, trim it so that we don't get overlarge
616 requests for the client. We can't do this for signed packets. */
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000617 GETSHORT(udpsz, sizep);
618 if (udpsz > daemon->edns_pktsz)
Simon Kelley33702ab2015-12-28 23:17:15 +0000619 {
620 sizep -= 2;
621 PUTSHORT(daemon->edns_pktsz, sizep);
622 }
623
624#ifdef HAVE_DNSSEC
625 /* If the client didn't set the do bit, but we did, reset it. */
626 if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
627 {
628 unsigned short flags;
629 sizep += 2; /* skip RCODE */
630 GETSHORT(flags, sizep);
631 flags &= ~0x8000;
632 sizep -= 2;
633 PUTSHORT(flags, sizep);
634 }
635#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000636 }
Simon Kelley613ad152014-02-25 23:02:28 +0000637 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100638 }
Simon Kelley83349b82014-02-10 21:02:01 +0000639
Simon Kelley28866e92011-02-14 20:19:14 +0000640 /* RFC 4035 sect 4.6 para 3 */
Giovanni Bajo237724c2012-04-05 02:46:52 +0200641 if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
Simon Kelley795501b2014-01-08 18:11:55 +0000642 header->hb4 &= ~HB4_AD;
Simon Kelley3a237152013-12-12 12:15:50 +0000643
Simon Kelley572b41e2011-02-18 18:11:18 +0000644 if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
Simon Kelley8938ae02014-05-01 17:46:25 +0100645 return resize_packet(header, n, pheader, plen);
Simon Kelley36717ee2004-09-20 19:20:58 +0100646
Simon Kelley0a852542005-03-23 20:28:59 +0000647 /* Complain loudly if the upstream server is non-recursive. */
Simon Kelley92be34a2016-01-16 18:39:54 +0000648 if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
Simon Kelley0a852542005-03-23 20:28:59 +0000649 server && !(server->flags & SERV_WARNED_RECURSIVE))
650 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100651 prettyprint_addr(&server->addr, daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100652 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
Simon Kelley28866e92011-02-14 20:19:14 +0000653 if (!option_bool(OPT_LOG))
Simon Kelley0a852542005-03-23 20:28:59 +0000654 server->flags |= SERV_WARNED_RECURSIVE;
655 }
Giovanni Bajoe292e932012-04-22 14:32:02 +0200656
Simon Kelley572b41e2011-02-18 18:11:18 +0000657 if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100658 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100659 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100660 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000661 SET_RCODE(header, NXDOMAIN);
662 header->hb3 &= ~HB3_AA;
Simon Kelley6938f342014-01-26 22:47:39 +0000663 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100664 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100665 else
Simon Kelley36717ee2004-09-20 19:20:58 +0100666 {
Simon Kelley6938f342014-01-26 22:47:39 +0000667 int doctored = 0;
668
Simon Kelley572b41e2011-02-18 18:11:18 +0000669 if (RCODE(header) == NXDOMAIN &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100670 extract_request(header, n, daemon->namebuff, NULL) &&
Simon Kelley5aabfc72007-08-29 11:24:47 +0100671 check_for_local_domain(daemon->namebuff, now))
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100672 {
Simon Kelley36717ee2004-09-20 19:20:58 +0100673 /* if we forwarded a query for a locally known name (because it was for
674 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
675 since we know that the domain exists, even if upstream doesn't */
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100676 munged = 1;
Simon Kelley572b41e2011-02-18 18:11:18 +0000677 header->hb3 |= HB3_AA;
678 SET_RCODE(header, NOERROR);
Simon Kelley6938f342014-01-26 22:47:39 +0000679 cache_secure = 0;
Simon Kelley36717ee2004-09-20 19:20:58 +0100680 }
Simon Kelley832af0b2007-01-21 20:01:28 +0000681
Simon Kelley373e9172017-12-01 22:40:56 +0000682 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 +0000683 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100684 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
Simon Kelley824af852008-02-12 20:43:05 +0000685 munged = 1;
Simon Kelley6938f342014-01-26 22:47:39 +0000686 cache_secure = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000687 }
Simon Kelley6938f342014-01-26 22:47:39 +0000688
689 if (doctored)
690 cache_secure = 0;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100691 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100692
Simon Kelleya25720a2014-01-14 23:13:55 +0000693#ifdef HAVE_DNSSEC
Simon Kelley33702ab2015-12-28 23:17:15 +0000694 if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
Simon Kelleya25720a2014-01-14 23:13:55 +0000695 {
Simon Kelley33702ab2015-12-28 23:17:15 +0000696 /* Bogus reply, turn into SERVFAIL */
697 SET_RCODE(header, SERVFAIL);
698 munged = 1;
Simon Kelleya25720a2014-01-14 23:13:55 +0000699 }
Simon Kelley6938f342014-01-26 22:47:39 +0000700
701 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000702 {
703 header->hb4 &= ~HB4_AD;
704
705 if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
706 header->hb4 |= HB4_AD;
707
708 /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
709 if (!do_bit)
710 n = rrfilter(header, n, 1);
711 }
Simon Kelleya25720a2014-01-14 23:13:55 +0000712#endif
713
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100714 /* do this after extract_addresses. Ensure NODATA reply and remove
715 nameserver info. */
716
717 if (munged)
718 {
719 header->ancount = htons(0);
720 header->nscount = htons(0);
721 header->arcount = htons(0);
Simon Kelley150162b2015-03-27 09:58:26 +0000722 header->hb3 &= ~HB3_TC;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100723 }
724
Simon Kelley36717ee2004-09-20 19:20:58 +0100725 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
726 sections of the packet. Find the new length here and put back pseudoheader
727 if it was removed. */
728 return resize_packet(header, n, pheader, plen);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100729}
730
Simon Kelley3be34542004-09-11 19:12:13 +0100731/* sets new last_server */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100732void reply_query(int fd, int family, time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000733{
734 /* packet from peer server, extract data for cache, and send to
735 original requester */
Simon Kelley572b41e2011-02-18 18:11:18 +0000736 struct dns_header *header;
Simon Kelleyde379512004-06-22 20:23:33 +0100737 union mysockaddr serveraddr;
Simon Kelley832af0b2007-01-21 20:01:28 +0000738 struct frec *forward;
Simon Kelleyde379512004-06-22 20:23:33 +0100739 socklen_t addrlen = sizeof(serveraddr);
Simon Kelley60b68062014-01-08 12:10:28 +0000740 ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
Simon Kelleycdeda282006-03-16 20:16:06 +0000741 size_t nn;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100742 struct server *server;
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000743 void *hash;
744#ifndef HAVE_DNSSEC
745 unsigned int crc;
746#endif
747
Simon Kelleycdeda282006-03-16 20:16:06 +0000748 /* packet buffer overwritten */
749 daemon->srv_save = NULL;
Simon Kelley832af0b2007-01-21 20:01:28 +0000750
Simon Kelleyde379512004-06-22 20:23:33 +0100751 /* Determine the address of the server replying so that we can mark that as good */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100752 serveraddr.sa.sa_family = family;
Simon Kelleyde379512004-06-22 20:23:33 +0100753#ifdef HAVE_IPV6
754 if (serveraddr.sa.sa_family == AF_INET6)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100755 serveraddr.in6.sin6_flowinfo = 0;
Simon Kelleyde379512004-06-22 20:23:33 +0100756#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000757
Simon Kelley490f9072014-03-24 22:04:42 +0000758 header = (struct dns_header *)daemon->packet;
759
760 if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
761 return;
762
Simon Kelley1a6bca82008-07-11 11:11:42 +0100763 /* spoof check: answer must come from known server, */
764 for (server = daemon->servers; server; server = server->next)
765 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
766 sockaddr_isequal(&server->addr, &serveraddr))
767 break;
Simon Kelley490f9072014-03-24 22:04:42 +0000768
769 if (!server)
770 return;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000771
772 /* If sufficient time has elapsed, try and expand UDP buffer size again. */
773 if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
774 server->edns_pktsz = daemon->edns_pktsz;
775
Simon Kelley8a9be9e2014-01-25 23:17:21 +0000776#ifdef HAVE_DNSSEC
777 hash = hash_questions(header, n, daemon->namebuff);
778#else
779 hash = &crc;
780 crc = questions_crc(header, n, daemon->namebuff);
781#endif
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100782
Simon Kelley490f9072014-03-24 22:04:42 +0000783 if (!(forward = lookup_frec(ntohs(header->id), hash)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100784 return;
Simon Kelley490f9072014-03-24 22:04:42 +0000785
Simon Kelley25cf5e32015-01-09 15:53:03 +0000786 /* log_query gets called indirectly all over the place, so
787 pass these in global variables - sorry. */
788 daemon->log_display_id = forward->log_id;
789 daemon->log_source_addr = &forward->source;
790
Glen Huang32fc6db2014-12-27 15:28:12 +0000791 if (daemon->ignore_addr && RCODE(header) == NOERROR &&
792 check_for_ignored_address(header, n, daemon->ignore_addr))
793 return;
794
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000795 /* Note: if we send extra options in the EDNS0 header, we can't recreate
796 the query from the reply. */
Simon Kelley2ae195f2015-01-18 22:20:48 +0000797 if (RCODE(header) == REFUSED &&
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000798 forward->forwardall == 0 &&
799 !(forward->flags & FREC_HAS_EXTRADATA))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100800 /* for broken servers, attempt to send to another one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000801 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100802 unsigned char *pheader;
803 size_t plen;
804 int is_sign;
Simon Kelleyef3d1372017-12-05 22:37:29 +0000805
806 /* In strict order mode, there must be a server later in the chain
807 left to send to, otherwise without the forwardall mechanism,
808 code further on will cycle around the list forwever if they
809 all return REFUSED. Note that server is always non-NULL before
810 this executes. */
811 if (option_bool(OPT_ORDER))
812 for (server = forward->sentto->next; server; server = server->next)
813 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
814 break;
815
Simon Kelley1a6bca82008-07-11 11:11:42 +0100816 /* recreate query from reply */
Simon Kelley5bb88f02015-12-21 16:23:47 +0000817 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
Simon Kelleyef3d1372017-12-05 22:37:29 +0000818 if (!is_sign && server)
Simon Kelley832af0b2007-01-21 20:01:28 +0000819 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100820 header->ancount = htons(0);
821 header->nscount = htons(0);
822 header->arcount = htons(0);
823 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
824 {
swiggerbd7bfa22015-06-01 20:54:59 +0100825 header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000826 header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
Simon Kelley1801a292016-01-17 21:53:57 +0000827 if (forward->flags & FREC_CHECKING_DISABLED)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000828 header->hb4 |= HB4_CD;
Simon Kelley1801a292016-01-17 21:53:57 +0000829 if (forward->flags & FREC_AD_QUESTION)
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000830 header->hb4 |= HB4_AD;
831 if (forward->flags & FREC_DO_QUESTION)
Simon Kelley33702ab2015-12-28 23:17:15 +0000832 add_do_bit(header, nn, (unsigned char *)pheader + plen);
Simon Kelleyfa14bec2015-12-20 17:12:16 +0000833 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 +0100834 return;
835 }
836 }
837 }
Simon Kelley3a237152013-12-12 12:15:50 +0000838
839 server = forward->sentto;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100840 if ((forward->sentto->flags & SERV_TYPE) == 0)
841 {
Simon Kelley51967f92014-03-25 21:07:00 +0000842 if (RCODE(header) == REFUSED)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100843 server = NULL;
844 else
845 {
846 struct server *last_server;
Simon Kelley832af0b2007-01-21 20:01:28 +0000847
Simon Kelley1a6bca82008-07-11 11:11:42 +0100848 /* find good server by address if possible, otherwise assume the last one we sent to */
849 for (last_server = daemon->servers; last_server; last_server = last_server->next)
850 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
851 sockaddr_isequal(&last_server->addr, &serveraddr))
852 {
853 server = last_server;
854 break;
855 }
856 }
Simon Kelley28866e92011-02-14 20:19:14 +0000857 if (!option_bool(OPT_ALL_SERVERS))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100858 daemon->last_server = server;
859 }
Simon Kelleya77cec82015-05-08 16:25:38 +0100860
861 /* We tried resending to this server with a smaller maximum size and got an answer.
Ville Skyttäfaaf3062018-01-14 17:32:52 +0000862 Make that permanent. To avoid reduxing the packet size for a single dropped packet,
Simon Kelley86fa1042015-05-10 13:50:59 +0100863 only do this when we get a truncated answer, or one larger than the safe size. */
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000864 if (server && server->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
Simon Kelley86fa1042015-05-10 13:50:59 +0100865 ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
Simon Kelley22dee512017-10-13 22:54:00 +0100866 {
867 server->edns_pktsz = SAFE_PKTSZ;
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000868 server->pktsz_reduced = now;
Simon Kelley22dee512017-10-13 22:54:00 +0100869 prettyprint_addr(&server->addr, daemon->addrbuff);
Simon Kelleyebedcba2017-10-29 20:54:17 +0000870 my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
Simon Kelley22dee512017-10-13 22:54:00 +0100871 }
Simon Kelleyc1a4e252018-01-19 22:00:05 +0000872
873
Simon Kelley1a6bca82008-07-11 11:11:42 +0100874 /* If the answer is an error, keep the forward record in place in case
875 we get a good reply from another server. Kill it when we've
876 had replies from all to avoid filling the forwarding table when
877 everything is broken */
Baptiste Jonglez68f63122017-02-06 21:09:11 +0000878 if (forward->forwardall == 0 || --forward->forwardall == 1 ||
879 (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100880 {
Simon Kelleyfe3992f2015-04-03 21:25:05 +0100881 int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleya6004d72017-10-25 17:48:19 +0100882
Simon Kelley3a237152013-12-12 12:15:50 +0000883 if (option_bool(OPT_NO_REBIND))
884 check_rebind = !(forward->flags & FREC_NOREBIND);
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100885
Simon Kelley3a237152013-12-12 12:15:50 +0000886 /* Don't cache replies where DNSSEC validation was turned off, either
887 the upstream server told us so, or the original query specified it. */
888 if ((header->hb4 & HB4_CD) || (forward->flags & FREC_CHECKING_DISABLED))
889 no_cache_dnssec = 1;
890
891#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +0000892 if (server && (server->flags & SERV_DO_DNSSEC) &&
Simon Kelley57573712016-01-11 22:50:00 +0000893 option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
Simon Kelley3a237152013-12-12 12:15:50 +0000894 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000895 int status = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000896
897 /* We've had a reply already, which we're validating. Ignore this duplicate */
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000898 if (forward->blocking_query)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000899 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000900
901 /* Truncated answer can't be validated.
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100902 If this is an answer to a DNSSEC-generated query, we still
903 need to get the client to retry over TCP, so return
904 an answer with the TC bit set, even if the actual answer fits.
905 */
Simon Kelley9a31b682015-12-15 10:20:39 +0000906 if (header->hb3 & HB3_TC)
907 status = STAT_TRUNCATED;
908
909 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000910 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000911 /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
912 would invite infinite loops, since the answers to DNSKEY and DS queries
913 will not be cached, so they'll be repeated. */
914 if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000915 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000916 if (forward->flags & FREC_DNSKEY_QUERY)
917 status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
918 else if (forward->flags & FREC_DS_QUERY)
919 status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000920 else
Simon Kelley9a31b682015-12-15 10:20:39 +0000921 status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
Simon Kelleya6004d72017-10-25 17:48:19 +0100922 option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
Simon Kelley373e9172017-12-01 22:40:56 +0000923 NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000924 }
Simon Kelley0fc2f312014-01-08 10:26:58 +0000925
Simon Kelley9a31b682015-12-15 10:20:39 +0000926 /* Can't validate, as we're missing key data. Put this
927 answer aside, whilst we get that. */
928 if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
Simon Kelley3a237152013-12-12 12:15:50 +0000929 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000930 struct frec *new, *orig;
Simon Kelley9d633042013-12-13 15:36:55 +0000931
Simon Kelley9a31b682015-12-15 10:20:39 +0000932 /* Free any saved query */
933 if (forward->stash)
934 blockdata_free(forward->stash);
935
936 /* Now save reply pending receipt of key data */
937 if (!(forward->stash = blockdata_alloc((char *)header, n)))
Simon Kelley97e618a2015-01-07 21:55:43 +0000938 return;
Simon Kelley9a31b682015-12-15 10:20:39 +0000939 forward->stash_len = n;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000940
Simon Kelley9a31b682015-12-15 10:20:39 +0000941 /* Find the original query that started it all.... */
942 for (orig = forward; orig->dependent; orig = orig->dependent);
Simon Kelley7fa836e2014-02-10 20:11:24 +0000943
Simon Kelley9a31b682015-12-15 10:20:39 +0000944 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
945 status = STAT_ABANDONED;
Simon Kelleye0c0ad32014-01-16 22:42:07 +0000946 else
Simon Kelley3a237152013-12-12 12:15:50 +0000947 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000948 int fd, type = SERV_DO_DNSSEC;
Simon Kelley9a31b682015-12-15 10:20:39 +0000949 struct frec *next = new->next;
Simon Kelley92be34a2016-01-16 18:39:54 +0000950 char *domain;
951
Simon Kelley9a31b682015-12-15 10:20:39 +0000952 *new = *forward; /* copy everything, then overwrite */
953 new->next = next;
954 new->blocking_query = NULL;
Simon Kelley92be34a2016-01-16 18:39:54 +0000955
956 /* Find server to forward to. This will normally be the
957 same as for the original query, but may be another if
958 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100959 if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
Simon Kelley92be34a2016-01-16 18:39:54 +0000960 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +0000961 struct server *start = server, *new_server = NULL;
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100962
963 while (1)
964 {
965 if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
966 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
967 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
968 {
969 new_server = start;
970 if (server == start)
971 {
972 new_server = NULL;
973 break;
974 }
975 }
976
977 if (!(start = start->next))
978 start = daemon->servers;
979 if (start == server)
980 break;
981 }
982
983 if (new_server)
984 server = new_server;
Simon Kelley92be34a2016-01-16 18:39:54 +0000985 }
Simon Kelley09f3b2c2017-05-09 01:34:02 +0100986
Simon Kelley9a31b682015-12-15 10:20:39 +0000987 new->sentto = server;
988 new->rfd4 = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +0000989#ifdef HAVE_IPV6
Simon Kelley9a31b682015-12-15 10:20:39 +0000990 new->rfd6 = NULL;
Simon Kelley7fa836e2014-02-10 20:11:24 +0000991#endif
Simon Kelley9a31b682015-12-15 10:20:39 +0000992 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
993
994 new->dependent = forward; /* to find query awaiting new one. */
995 forward->blocking_query = new; /* for garbage cleaning */
996 /* validate routines leave name of required record in daemon->keyname */
997 if (status == STAT_NEED_KEY)
Simon Kelley7fa836e2014-02-10 20:11:24 +0000998 {
Simon Kelley9a31b682015-12-15 10:20:39 +0000999 new->flags |= FREC_DNSKEY_QUERY;
Simon Kelley33702ab2015-12-28 23:17:15 +00001000 nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
Simon Kelley9a31b682015-12-15 10:20:39 +00001001 daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
Simon Kelleyf1668d22014-01-08 16:53:27 +00001002 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001003 else
1004 {
1005 new->flags |= FREC_DS_QUERY;
Simon Kelley33702ab2015-12-28 23:17:15 +00001006 nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
Simon Kelley9a31b682015-12-15 10:20:39 +00001007 daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
1008 }
1009 if ((hash = hash_questions(header, nn, daemon->namebuff)))
1010 memcpy(new->hash, hash, HASH_SIZE);
1011 new->new_id = get_id();
1012 header->id = htons(new->new_id);
1013 /* Save query for retransmission */
1014 new->stash = blockdata_alloc((char *)header, nn);
1015 new->stash_len = nn;
1016
1017 /* Don't resend this. */
1018 daemon->srv_save = NULL;
1019
1020 if (server->sfd)
1021 fd = server->sfd->fd;
1022 else
1023 {
1024 fd = -1;
1025#ifdef HAVE_IPV6
1026 if (server->addr.sa.sa_family == AF_INET6)
1027 {
1028 if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1029 fd = new->rfd6->fd;
1030 }
1031 else
1032#endif
1033 {
1034 if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1035 fd = new->rfd4->fd;
1036 }
1037 }
1038
1039 if (fd != -1)
1040 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001041#ifdef HAVE_CONNTRACK
1042 /* Copy connection mark of incoming query to outgoing connection. */
1043 if (option_bool(OPT_CONNTRACK))
1044 {
1045 unsigned int mark;
1046 if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
1047 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1048 }
1049#endif
Simon Kelley9a31b682015-12-15 10:20:39 +00001050 while (retry_send(sendto(fd, (char *)header, nn, 0,
1051 &server->addr.sa,
1052 sa_len(&server->addr))));
1053 server->queries++;
1054 }
1055 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001056 return;
Simon Kelley3a237152013-12-12 12:15:50 +00001057 }
Simon Kelley3a237152013-12-12 12:15:50 +00001058
Simon Kelley9a31b682015-12-15 10:20:39 +00001059 /* Validated original answer, all done. */
1060 if (!forward->dependent)
1061 break;
1062
Josh Soref730c6742017-02-06 16:14:04 +00001063 /* validated subsidiary query, (and cached result)
Simon Kelley9a31b682015-12-15 10:20:39 +00001064 pop that and return to the previous query we were working on. */
Simon Kelley0744ca62014-01-25 16:40:15 +00001065 struct frec *prev = forward->dependent;
1066 free_frec(forward);
1067 forward = prev;
1068 forward->blocking_query = NULL; /* already gone */
1069 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1070 n = forward->stash_len;
Simon Kelley3a237152013-12-12 12:15:50 +00001071 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001072
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001073
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001074 no_cache_dnssec = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001075
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001076 if (status == STAT_TRUNCATED)
Simon Kelley0744ca62014-01-25 16:40:15 +00001077 header->hb3 |= HB3_TC;
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001078 else
Simon Kelley7fa836e2014-02-10 20:11:24 +00001079 {
Simon Kelley554b5802015-04-17 22:50:20 +01001080 char *result, *domain = "result";
Simon Kelley7fa836e2014-02-10 20:11:24 +00001081
Simon Kelley9a31b682015-12-15 10:20:39 +00001082 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001083 {
1084 result = "ABANDONED";
1085 status = STAT_BOGUS;
1086 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001087 else
1088 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
1089
Simon Kelley554b5802015-04-17 22:50:20 +01001090 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1091 domain = daemon->namebuff;
Simon Kelley9a31b682015-12-15 10:20:39 +00001092
Simon Kelley554b5802015-04-17 22:50:20 +01001093 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001094 }
Simon Kelley5d3b87a2014-01-20 11:57:23 +00001095
Simon Kelley3a237152013-12-12 12:15:50 +00001096 if (status == STAT_SECURE)
1097 cache_secure = 1;
Simon Kelley3a237152013-12-12 12:15:50 +00001098 else if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001099 {
1100 no_cache_dnssec = 1;
1101 bogusanswer = 1;
1102 }
Simon Kelley3a237152013-12-12 12:15:50 +00001103 }
Simon Kelley83349b82014-02-10 21:02:01 +00001104#endif
1105
1106 /* restore CD bit to the value in the query */
1107 if (forward->flags & FREC_CHECKING_DISABLED)
1108 header->hb4 |= HB4_CD;
1109 else
1110 header->hb4 &= ~HB4_CD;
Simon Kelley3a237152013-12-12 12:15:50 +00001111
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001112 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 +00001113 forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
1114 forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
Simon Kelley832af0b2007-01-21 20:01:28 +00001115 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001116 header->id = htons(forward->orig_id);
Simon Kelley572b41e2011-02-18 18:11:18 +00001117 header->hb4 |= HB4_RA; /* recursion if available */
Simon Kelley5aa5f0f2015-12-21 17:20:35 +00001118#ifdef HAVE_DNSSEC
1119 /* 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 +01001120 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 +00001121 header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
1122 if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
1123 {
1124 header->ancount = htons(0);
1125 header->nscount = htons(0);
1126 header->arcount = htons(0);
1127 header->hb3 |= HB3_TC;
1128 nn = resize_packet(header, nn, NULL, 0);
1129 }
1130#endif
Simon Kelley54dd3932012-06-20 11:23:38 +01001131 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
Simon Kelley50303b12012-04-04 22:13:17 +01001132 &forward->source, &forward->dest, forward->iface);
Simon Kelley832af0b2007-01-21 20:01:28 +00001133 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001134 free_frec(forward); /* cancel */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001135 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001136}
Simon Kelley44a2a312004-03-10 20:04:35 +00001137
Simon Kelley1a6bca82008-07-11 11:11:42 +01001138
Simon Kelley5aabfc72007-08-29 11:24:47 +01001139void receive_query(struct listener *listen, time_t now)
Simon Kelley44a2a312004-03-10 20:04:35 +00001140{
Simon Kelley572b41e2011-02-18 18:11:18 +00001141 struct dns_header *header = (struct dns_header *)daemon->packet;
Simon Kelley44a2a312004-03-10 20:04:35 +00001142 union mysockaddr source_addr;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001143 unsigned char *pheader;
1144 unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
Simon Kelley44a2a312004-03-10 20:04:35 +00001145 struct all_addr dst_addr;
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001146 struct in_addr netmask, dst_addr_4;
Simon Kelleycdeda282006-03-16 20:16:06 +00001147 size_t m;
1148 ssize_t n;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001149 int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001150#ifdef HAVE_AUTH
1151 int local_auth = 0;
1152#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001153 struct iovec iov[1];
1154 struct msghdr msg;
1155 struct cmsghdr *cmptr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001156 union {
1157 struct cmsghdr align; /* this ensures alignment */
1158#ifdef HAVE_IPV6
1159 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1160#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001161#if defined(HAVE_LINUX_NETWORK)
Simon Kelley44a2a312004-03-10 20:04:35 +00001162 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
Simon Kelley824af852008-02-12 20:43:05 +00001163#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
1164 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1165 CMSG_SPACE(sizeof(unsigned int))];
Simon Kelley44a2a312004-03-10 20:04:35 +00001166#elif defined(IP_RECVDSTADDR)
1167 char control[CMSG_SPACE(sizeof(struct in_addr)) +
1168 CMSG_SPACE(sizeof(struct sockaddr_dl))];
1169#endif
1170 } control_u;
Simon Kelley2329bef2013-12-03 13:41:16 +00001171#ifdef HAVE_IPV6
1172 /* Can always get recvd interface for IPv6 */
1173 int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
1174#else
1175 int check_dst = !option_bool(OPT_NOWILD);
1176#endif
1177
Simon Kelleycdeda282006-03-16 20:16:06 +00001178 /* packet buffer overwritten */
1179 daemon->srv_save = NULL;
1180
Hans Dedecker98906272014-12-09 22:22:53 +00001181 dst_addr_4.s_addr = dst_addr.addr.addr4.s_addr = 0;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001182 netmask.s_addr = 0;
1183
Simon Kelley7e5664b2013-04-05 16:57:41 +01001184 if (option_bool(OPT_NOWILD) && listen->iface)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001185 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001186 auth_dns = listen->iface->dns_auth;
1187
1188 if (listen->family == AF_INET)
1189 {
Hans Dedecker98906272014-12-09 22:22:53 +00001190 dst_addr_4 = dst_addr.addr.addr4 = listen->iface->addr.in.sin_addr;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001191 netmask = listen->iface->netmask;
1192 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +00001193 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001194
Simon Kelley3be34542004-09-11 19:12:13 +01001195 iov[0].iov_base = daemon->packet;
1196 iov[0].iov_len = daemon->edns_pktsz;
Simon Kelley44a2a312004-03-10 20:04:35 +00001197
1198 msg.msg_control = control_u.control;
1199 msg.msg_controllen = sizeof(control_u);
1200 msg.msg_flags = 0;
1201 msg.msg_name = &source_addr;
1202 msg.msg_namelen = sizeof(source_addr);
1203 msg.msg_iov = iov;
1204 msg.msg_iovlen = 1;
1205
Simon Kelleyde379512004-06-22 20:23:33 +01001206 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
Simon Kelley3be34542004-09-11 19:12:13 +01001207 return;
Simon Kelley44a2a312004-03-10 20:04:35 +00001208
Simon Kelley572b41e2011-02-18 18:11:18 +00001209 if (n < (int)sizeof(struct dns_header) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001210 (msg.msg_flags & MSG_TRUNC) ||
Simon Kelley572b41e2011-02-18 18:11:18 +00001211 (header->hb3 & HB3_QR))
Simon Kelley3be34542004-09-11 19:12:13 +01001212 return;
Simon Kelley63437ff2017-09-06 22:34:21 +01001213
1214 /* Clear buffer beyond request to avoid risk of
1215 information disclosure. */
1216 memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
Simon Kelley44a2a312004-03-10 20:04:35 +00001217
Simon Kelley26128d22004-11-14 16:43:54 +00001218 source_addr.sa.sa_family = listen->family;
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001219
1220 if (listen->family == AF_INET)
1221 {
1222 /* Source-port == 0 is an error, we can't send back to that.
1223 http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
1224 if (source_addr.in.sin_port == 0)
1225 return;
1226 }
Simon Kelley26128d22004-11-14 16:43:54 +00001227#ifdef HAVE_IPV6
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001228 else
1229 {
1230 /* Source-port == 0 is an error, we can't send back to that. */
1231 if (source_addr.in6.sin6_port == 0)
1232 return;
1233 source_addr.in6.sin6_flowinfo = 0;
1234 }
Simon Kelley26128d22004-11-14 16:43:54 +00001235#endif
Simon Kelley2a7a2b82014-03-22 19:18:06 +00001236
Simon Kelleyc8a80482014-03-05 14:29:54 +00001237 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1238 if (option_bool(OPT_LOCAL_SERVICE))
1239 {
1240 struct addrlist *addr;
1241#ifdef HAVE_IPV6
1242 if (listen->family == AF_INET6)
1243 {
1244 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1245 if ((addr->flags & ADDRLIST_IPV6) &&
1246 is_same_net6(&addr->addr.addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
1247 break;
1248 }
1249 else
1250#endif
1251 {
1252 struct in_addr netmask;
1253 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1254 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001255 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001256 if (!(addr->flags & ADDRLIST_IPV6) &&
1257 is_same_net(addr->addr.addr.addr4, source_addr.in.sin_addr, netmask))
1258 break;
1259 }
1260 }
1261 if (!addr)
1262 {
Simon Kelley0c8584e2014-03-12 20:12:56 +00001263 static int warned = 0;
1264 if (!warned)
1265 {
1266 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1267 warned = 1;
1268 }
Simon Kelleyc8a80482014-03-05 14:29:54 +00001269 return;
1270 }
1271 }
1272
Simon Kelley2329bef2013-12-03 13:41:16 +00001273 if (check_dst)
Simon Kelley44a2a312004-03-10 20:04:35 +00001274 {
Simon Kelley8a911cc2004-03-16 18:35:52 +00001275 struct ifreq ifr;
1276
Simon Kelley26128d22004-11-14 16:43:54 +00001277 if (msg.msg_controllen < sizeof(struct cmsghdr))
1278 return;
1279
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001280#if defined(HAVE_LINUX_NETWORK)
Simon Kelley26128d22004-11-14 16:43:54 +00001281 if (listen->family == AF_INET)
1282 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001283 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
Simon Kelley26128d22004-11-14 16:43:54 +00001284 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001285 union {
1286 unsigned char *c;
1287 struct in_pktinfo *p;
1288 } p;
1289 p.c = CMSG_DATA(cmptr);
1290 dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
1291 if_index = p.p->ipi_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001292 }
1293#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1294 if (listen->family == AF_INET)
1295 {
1296 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001297 {
1298 union {
1299 unsigned char *c;
1300 unsigned int *i;
1301 struct in_addr *a;
1302#ifndef HAVE_SOLARIS_NETWORK
1303 struct sockaddr_dl *s;
Simon Kelley824af852008-02-12 20:43:05 +00001304#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001305 } p;
1306 p.c = CMSG_DATA(cmptr);
1307 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
1308 dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
1309 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
1310#ifdef HAVE_SOLARIS_NETWORK
1311 if_index = *(p.i);
1312#else
1313 if_index = p.s->sdl_index;
1314#endif
1315 }
Simon Kelley26128d22004-11-14 16:43:54 +00001316 }
1317#endif
1318
1319#ifdef HAVE_IPV6
1320 if (listen->family == AF_INET6)
1321 {
1322 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelleyc72daea2012-01-05 21:33:27 +00001323 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
Simon Kelley26128d22004-11-14 16:43:54 +00001324 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001325 union {
1326 unsigned char *c;
1327 struct in6_pktinfo *p;
1328 } p;
1329 p.c = CMSG_DATA(cmptr);
1330
1331 dst_addr.addr.addr6 = p.p->ipi6_addr;
1332 if_index = p.p->ipi6_ifindex;
Simon Kelley26128d22004-11-14 16:43:54 +00001333 }
1334 }
1335#endif
1336
1337 /* enforce available interface configuration */
1338
Simon Kelleye25db1f2013-01-29 22:10:26 +00001339 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
Simon Kelley832af0b2007-01-21 20:01:28 +00001340 return;
1341
Simon Kelleye25db1f2013-01-29 22:10:26 +00001342 if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
1343 {
1344 if (!option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001345 enumerate_interfaces(0);
Simon Kelley3f2873d2013-05-14 11:28:47 +01001346 if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
1347 !label_exception(if_index, listen->family, &dst_addr))
Simon Kelleye25db1f2013-01-29 22:10:26 +00001348 return;
1349 }
1350
Simon Kelley552af8b2012-02-29 20:10:31 +00001351 if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
1352 {
1353 struct irec *iface;
1354
Josh Soref730c6742017-02-06 16:14:04 +00001355 /* get the netmask of the interface which has the address we were sent to.
klemens43517fc2017-02-19 15:53:37 +00001356 This is no necessarily the interface we arrived on. */
Simon Kelley552af8b2012-02-29 20:10:31 +00001357
1358 for (iface = daemon->interfaces; iface; iface = iface->next)
1359 if (iface->addr.sa.sa_family == AF_INET &&
1360 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1361 break;
1362
1363 /* interface may be new */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001364 if (!iface && !option_bool(OPT_CLEVERBIND))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001365 enumerate_interfaces(0);
Simon Kelley552af8b2012-02-29 20:10:31 +00001366
1367 for (iface = daemon->interfaces; iface; iface = iface->next)
1368 if (iface->addr.sa.sa_family == AF_INET &&
1369 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
1370 break;
1371
1372 /* If we failed, abandon localisation */
1373 if (iface)
1374 netmask = iface->netmask;
1375 else
1376 dst_addr_4.s_addr = 0;
1377 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001378 }
Simon Kelley25cf5e32015-01-09 15:53:03 +00001379
1380 /* log_query gets called indirectly all over the place, so
1381 pass these in global variables - sorry. */
1382 daemon->log_display_id = ++daemon->log_id;
1383 daemon->log_source_addr = &source_addr;
Simon Kelley44a2a312004-03-10 20:04:35 +00001384
Simon Kelleycdeda282006-03-16 20:16:06 +00001385 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
Simon Kelley44a2a312004-03-10 20:04:35 +00001386 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001387#ifdef HAVE_AUTH
1388 struct auth_zone *zone;
1389#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001390 char *types = querystr(auth_dns ? "auth" : "query", type);
1391
Simon Kelley44a2a312004-03-10 20:04:35 +00001392 if (listen->family == AF_INET)
Simon Kelley3be34542004-09-11 19:12:13 +01001393 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +01001394 (struct all_addr *)&source_addr.in.sin_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001395#ifdef HAVE_IPV6
1396 else
Simon Kelley3be34542004-09-11 19:12:13 +01001397 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
Simon Kelley1a6bca82008-07-11 11:11:42 +01001398 (struct all_addr *)&source_addr.in6.sin6_addr, types);
Simon Kelley44a2a312004-03-10 20:04:35 +00001399#endif
Simon Kelley44a2a312004-03-10 20:04:35 +00001400
Simon Kelley4820dce2012-12-18 18:30:30 +00001401#ifdef HAVE_AUTH
Simon Kelleyb485ed92013-10-18 22:00:39 +01001402 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001403 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001404 for (zone = daemon->auth_zones; zone; zone = zone->next)
1405 if (in_zone(zone, daemon->namebuff, NULL))
1406 {
1407 auth_dns = 1;
1408 local_auth = 1;
1409 break;
1410 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001411#endif
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001412
1413#ifdef HAVE_LOOP
1414 /* Check for forwarding loop */
1415 if (detect_loop(daemon->namebuff, type))
1416 return;
1417#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001418 }
1419
Simon Kelley5bb88f02015-12-21 16:23:47 +00001420 if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001421 {
1422 unsigned short flags;
1423
1424 have_pseudoheader = 1;
1425 GETSHORT(udp_size, pheader);
1426 pheader += 2; /* ext_rcode */
1427 GETSHORT(flags, pheader);
1428
1429 if (flags & 0x8000)
1430 do_bit = 1;/* do bit */
1431
1432 /* If the client provides an EDNS0 UDP size, use that to limit our reply.
1433 (bounded by the maximum configured). If no EDNS0, then it
1434 defaults to 512 */
1435 if (udp_size > daemon->edns_pktsz)
1436 udp_size = daemon->edns_pktsz;
Simon Kelleya3303e12017-09-07 20:45:00 +01001437 else if (udp_size < PACKETSZ)
1438 udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001439 }
1440
Simon Kelleyb485ed92013-10-18 22:00:39 +01001441#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001442 if (auth_dns)
Simon Kelley824af852008-02-12 20:43:05 +00001443 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001444 m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr,
1445 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001446 if (m >= 1)
Simon Kelleyb485ed92013-10-18 22:00:39 +01001447 {
1448 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1449 (char *)header, m, &source_addr, &dst_addr, if_index);
1450 daemon->auth_answer++;
1451 }
Simon Kelley824af852008-02-12 20:43:05 +00001452 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001453 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001454#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001455 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001456 int ad_reqd = do_bit;
1457 /* RFC 6840 5.7 */
1458 if (header->hb4 & HB4_AD)
1459 ad_reqd = 1;
1460
1461 m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
1462 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001463
1464 if (m >= 1)
1465 {
1466 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
1467 (char *)header, m, &source_addr, &dst_addr, if_index);
1468 daemon->local_answer++;
1469 }
1470 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
Simon Kelley613ad152014-02-25 23:02:28 +00001471 header, (size_t)n, now, NULL, ad_reqd, do_bit))
Simon Kelley4f7b3042012-11-28 21:27:02 +00001472 daemon->queries_forwarded++;
1473 else
1474 daemon->local_answer++;
1475 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001476}
1477
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001478#ifdef HAVE_DNSSEC
Josh Soref730c6742017-02-06 16:14:04 +00001479/* Recurse up the key hierarchy */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001480static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001481 int class, char *name, char *keyname, struct server *server,
1482 int have_mark, unsigned int mark, int *keycount)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001483{
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001484 int new_status;
Simon Kelley9a31b682015-12-15 10:20:39 +00001485 unsigned char *packet = NULL;
Simon Kelley9a31b682015-12-15 10:20:39 +00001486 unsigned char *payload = NULL;
1487 struct dns_header *new_header = NULL;
1488 u16 *length = NULL;
Simon Kelley361dfe52017-02-10 21:12:30 +00001489
Simon Kelley9a31b682015-12-15 10:20:39 +00001490 while (1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001491 {
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001492 int type = SERV_DO_DNSSEC;
1493 char *domain;
1494 size_t m;
1495 unsigned char c1, c2;
Simon Kelley361dfe52017-02-10 21:12:30 +00001496 struct server *firstsendto = NULL;
1497
Simon Kelley9a31b682015-12-15 10:20:39 +00001498 /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1499 if (--(*keycount) == 0)
1500 new_status = STAT_ABANDONED;
1501 else if (status == STAT_NEED_KEY)
1502 new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1503 else if (status == STAT_NEED_DS)
1504 new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1505 else
James Bottomleye33b4872017-03-17 21:44:10 +00001506 new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
Simon Kelleya6004d72017-10-25 17:48:19 +01001507 option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
Simon Kelley373e9172017-12-01 22:40:56 +00001508 NULL, NULL);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001509
Simon Kelley9a31b682015-12-15 10:20:39 +00001510 if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1511 break;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001512
Simon Kelley9a31b682015-12-15 10:20:39 +00001513 /* Can't validate because we need a key/DS whose name now in keyname.
1514 Make query for same, and recurse to validate */
Simon Kelley7fa836e2014-02-10 20:11:24 +00001515 if (!packet)
Simon Kelley9a31b682015-12-15 10:20:39 +00001516 {
1517 packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1518 payload = &packet[2];
1519 new_header = (struct dns_header *)payload;
1520 length = (u16 *)packet;
1521 }
1522
1523 if (!packet)
1524 {
1525 new_status = STAT_ABANDONED;
1526 break;
1527 }
1528
Simon Kelley33702ab2015-12-28 23:17:15 +00001529 m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
Simon Kelleya77cec82015-05-08 16:25:38 +01001530 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001531
Simon Kelley7fa836e2014-02-10 20:11:24 +00001532 *length = htons(m);
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001533
1534 /* Find server to forward to. This will normally be the
1535 same as for the original query, but may be another if
1536 servers for domains are involved. */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001537 if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001538 {
Simon Kelley9a31b682015-12-15 10:20:39 +00001539 new_status = STAT_ABANDONED;
1540 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001541 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001542
Simon Kelley361dfe52017-02-10 21:12:30 +00001543 while (1)
1544 {
1545 if (!firstsendto)
1546 firstsendto = server;
1547 else
1548 {
1549 if (!(server = server->next))
1550 server = daemon->servers;
1551 if (server == firstsendto)
1552 {
1553 /* can't find server to accept our query. */
1554 new_status = STAT_ABANDONED;
1555 break;
1556 }
1557 }
1558
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001559 if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
Simon Kelley361dfe52017-02-10 21:12:30 +00001560 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
1561 (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
1562 continue;
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001563
1564 retry:
1565 /* may need to make new connection. */
1566 if (server->tcpfd == -1)
1567 {
1568 if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
Simon Kelley361dfe52017-02-10 21:12:30 +00001569 continue; /* No good, next server */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001570
1571#ifdef HAVE_CONNTRACK
1572 /* Copy connection mark of incoming query to outgoing connection. */
1573 if (have_mark)
1574 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1575#endif
1576
Simon Kelley9d6918d2017-10-13 17:55:09 +01001577 if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1) ||
Simon Kelley09f3b2c2017-05-09 01:34:02 +01001578 connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
1579 {
1580 close(server->tcpfd);
1581 server->tcpfd = -1;
1582 continue; /* No good, next server */
1583 }
1584
1585 server->flags &= ~SERV_GOT_TCP;
1586 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001587
1588 if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
1589 !read_write(server->tcpfd, &c1, 1, 1) ||
1590 !read_write(server->tcpfd, &c2, 1, 1) ||
1591 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1592 {
1593 close(server->tcpfd);
1594 server->tcpfd = -1;
1595 /* We get data then EOF, reopen connection to same server,
1596 else try next. This avoids DoS from a server which accepts
1597 connections and then closes them. */
1598 if (server->flags & SERV_GOT_TCP)
1599 goto retry;
1600 else
1601 continue;
1602 }
1603
1604 server->flags |= SERV_GOT_TCP;
1605
1606 m = (c1 << 8) | c2;
1607 new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
1608 break;
1609 }
Simon Kelley9a31b682015-12-15 10:20:39 +00001610
1611 if (new_status != STAT_OK)
1612 break;
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001613 }
Simon Kelley361dfe52017-02-10 21:12:30 +00001614
Simon Kelley9a31b682015-12-15 10:20:39 +00001615 if (packet)
1616 free(packet);
1617
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001618 return new_status;
1619}
1620#endif
1621
1622
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001623/* The daemon forks before calling this: it should deal with one connection,
Josh Soref730c6742017-02-06 16:14:04 +00001624 blocking as necessary, and then return. Note, need to be a bit careful
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001625 about resources for debug mode, when the fork is suppressed: that's
1626 done by the caller. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001627unsigned char *tcp_request(int confd, time_t now,
Simon Kelley4f7b3042012-11-28 21:27:02 +00001628 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001629{
Simon Kelley28866e92011-02-14 20:19:14 +00001630 size_t size = 0;
1631 int norebind = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001632#ifdef HAVE_AUTH
Simon Kelley19b16892013-10-20 10:19:39 +01001633 int local_auth = 0;
Vladislav Grishenko3b195962013-11-26 11:08:21 +00001634#endif
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001635 int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001636 int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
Simon Kelleycdeda282006-03-16 20:16:06 +00001637 size_t m;
Simon Kelleyee86ce62012-12-07 11:54:46 +00001638 unsigned short qtype;
1639 unsigned int gotname;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001640 unsigned char c1, c2;
Simon Kelley4b5ea122013-04-22 10:18:26 +01001641 /* Max TCP packet + slop + size */
1642 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
1643 unsigned char *payload = &packet[2];
1644 /* largest field in header is 16-bits, so this is still sufficiently aligned */
1645 struct dns_header *header = (struct dns_header *)payload;
1646 u16 *length = (u16 *)packet;
Simon Kelley3be34542004-09-11 19:12:13 +01001647 struct server *last_server;
Simon Kelley7de060b2011-08-26 17:24:52 +01001648 struct in_addr dst_addr_4;
1649 union mysockaddr peer_addr;
1650 socklen_t peer_len = sizeof(union mysockaddr);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001651 int query_count = 0;
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001652 unsigned char *pheader;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001653 unsigned int mark = 0;
1654 int have_mark = 0;
Simon Kelley25cf5e32015-01-09 15:53:03 +00001655
Simon Kelleyd05dd582016-01-19 21:23:30 +00001656 (void)mark;
1657 (void)have_mark;
1658
Simon Kelley7de060b2011-08-26 17:24:52 +01001659 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
1660 return packet;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001661
1662#ifdef HAVE_CONNTRACK
1663 /* Get connection mark of incoming query to set on outgoing connections. */
1664 if (option_bool(OPT_CONNTRACK))
1665 {
1666 struct all_addr local;
1667#ifdef HAVE_IPV6
1668 if (local_addr->sa.sa_family == AF_INET6)
1669 local.addr.addr6 = local_addr->in6.sin6_addr;
1670 else
1671#endif
1672 local.addr.addr4 = local_addr->in.sin_addr;
1673
1674 have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
1675 }
1676#endif
1677
Simon Kelleyc8a80482014-03-05 14:29:54 +00001678 /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
1679 if (option_bool(OPT_LOCAL_SERVICE))
1680 {
1681 struct addrlist *addr;
1682#ifdef HAVE_IPV6
1683 if (peer_addr.sa.sa_family == AF_INET6)
1684 {
1685 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1686 if ((addr->flags & ADDRLIST_IPV6) &&
1687 is_same_net6(&addr->addr.addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
1688 break;
1689 }
1690 else
1691#endif
1692 {
1693 struct in_addr netmask;
1694 for (addr = daemon->interface_addrs; addr; addr = addr->next)
1695 {
Richard Genoud15b1b7e2014-09-17 21:12:00 +01001696 netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
Simon Kelleyc8a80482014-03-05 14:29:54 +00001697 if (!(addr->flags & ADDRLIST_IPV6) &&
1698 is_same_net(addr->addr.addr.addr4, peer_addr.in.sin_addr, netmask))
1699 break;
1700 }
1701 }
1702 if (!addr)
1703 {
1704 my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
1705 return packet;
1706 }
1707 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001708
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001709 while (1)
1710 {
Simon Kelley25cf5e32015-01-09 15:53:03 +00001711 if (query_count == TCP_MAX_QUERIES ||
1712 !packet ||
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001713 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
1714 !(size = c1 << 8 | c2) ||
Simon Kelley4b5ea122013-04-22 10:18:26 +01001715 !read_write(confd, payload, size, 1))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001716 return packet;
1717
Simon Kelley572b41e2011-02-18 18:11:18 +00001718 if (size < (int)sizeof(struct dns_header))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001719 continue;
Simon Kelley63437ff2017-09-06 22:34:21 +01001720
1721 /* Clear buffer beyond request to avoid risk of
1722 information disclosure. */
1723 memset(payload + size, 0, 65536 - size);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001724
Simon Kelley25cf5e32015-01-09 15:53:03 +00001725 query_count++;
1726
1727 /* log_query gets called indirectly all over the place, so
1728 pass these in global variables - sorry. */
1729 daemon->log_display_id = ++daemon->log_id;
1730 daemon->log_source_addr = &peer_addr;
1731
Simon Kelley28866e92011-02-14 20:19:14 +00001732 /* save state of "cd" flag in query */
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001733 if ((checking_disabled = header->hb4 & HB4_CD))
1734 no_cache_dnssec = 1;
Simon Kelley28866e92011-02-14 20:19:14 +00001735
Simon Kelley3be34542004-09-11 19:12:13 +01001736 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001737 {
Simon Kelleyb485ed92013-10-18 22:00:39 +01001738#ifdef HAVE_AUTH
1739 struct auth_zone *zone;
1740#endif
Simon Kelley610e7822014-02-06 14:45:17 +00001741 char *types = querystr(auth_dns ? "auth" : "query", qtype);
Simon Kelley7de060b2011-08-26 17:24:52 +01001742
1743 if (peer_addr.sa.sa_family == AF_INET)
1744 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
1745 (struct all_addr *)&peer_addr.in.sin_addr, types);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001746#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001747 else
1748 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
1749 (struct all_addr *)&peer_addr.in6.sin6_addr, types);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001750#endif
Simon Kelleyb485ed92013-10-18 22:00:39 +01001751
1752#ifdef HAVE_AUTH
1753 /* find queries for zones we're authoritative for, and answer them directly */
Simon Kelley3a3965a2015-08-09 17:45:06 +01001754 if (!auth_dns && !option_bool(OPT_LOCALISE))
Simon Kelley6008bdb2013-10-21 21:47:03 +01001755 for (zone = daemon->auth_zones; zone; zone = zone->next)
1756 if (in_zone(zone, daemon->namebuff, NULL))
1757 {
1758 auth_dns = 1;
1759 local_auth = 1;
1760 break;
1761 }
Simon Kelleyb485ed92013-10-18 22:00:39 +01001762#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001763 }
1764
Simon Kelley7de060b2011-08-26 17:24:52 +01001765 if (local_addr->sa.sa_family == AF_INET)
1766 dst_addr_4 = local_addr->in.sin_addr;
1767 else
1768 dst_addr_4.s_addr = 0;
1769
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001770 do_bit = 0;
1771
Simon Kelley5bb88f02015-12-21 16:23:47 +00001772 if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001773 {
1774 unsigned short flags;
1775
1776 have_pseudoheader = 1;
1777 pheader += 4; /* udp_size, ext_rcode */
1778 GETSHORT(flags, pheader);
1779
1780 if (flags & 0x8000)
Simon Kelley5bb88f02015-12-21 16:23:47 +00001781 do_bit = 1; /* do bit */
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001782 }
1783
Simon Kelley4820dce2012-12-18 18:30:30 +00001784#ifdef HAVE_AUTH
Simon Kelley4f7b3042012-11-28 21:27:02 +00001785 if (auth_dns)
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001786 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr,
1787 local_auth, do_bit, have_pseudoheader);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001788 else
Simon Kelley4820dce2012-12-18 18:30:30 +00001789#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001790 {
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001791 int ad_reqd = do_bit;
1792 /* RFC 6840 5.7 */
1793 if (header->hb4 & HB4_AD)
1794 ad_reqd = 1;
1795
1796 /* m > 0 if answered from cache */
1797 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
1798 dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001799
Simon Kelley4f7b3042012-11-28 21:27:02 +00001800 /* Do this by steam now we're not in the select() loop */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001801 check_log_writer(1);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001802
1803 if (m == 0)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001804 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001805 unsigned int flags = 0;
1806 struct all_addr *addrp = NULL;
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001807 int type = SERV_DO_DNSSEC;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001808 char *domain = NULL;
Simon Kelley6fd5d792017-10-13 22:26:40 +01001809 unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
Simon Kelleyed4c0762013-10-08 20:46:34 +01001810
Simon Kelley6fd5d792017-10-13 22:26:40 +01001811 size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
1812
Simon Kelley4f7b3042012-11-28 21:27:02 +00001813 if (gotname)
1814 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
Simon Kelley6fd5d792017-10-13 22:26:40 +01001815
1816#ifdef HAVE_DNSSEC
1817 if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
1818 {
1819 size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
1820
1821 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1822 this allows it to select auth servers when one is returning bad data. */
1823 if (option_bool(OPT_DNSSEC_DEBUG))
1824 header->hb4 |= HB4_CD;
1825 }
1826#endif
1827
1828 /* Check if we added a pheader on forwarding - may need to
1829 strip it from the reply. */
1830 if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
1831 added_pheader = 1;
1832
Simon Kelley367341f2016-01-12 15:58:23 +00001833 type &= ~SERV_DO_DNSSEC;
Simon Kelley367341f2016-01-12 15:58:23 +00001834
Simon Kelley4f7b3042012-11-28 21:27:02 +00001835 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
1836 last_server = daemon->servers;
1837 else
1838 last_server = daemon->last_server;
1839
1840 if (!flags && last_server)
1841 {
1842 struct server *firstsendto = NULL;
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001843#ifdef HAVE_DNSSEC
Simon Kelley703c7ff2014-01-25 23:46:23 +00001844 unsigned char *newhash, hash[HASH_SIZE];
Simon Kelley63758382014-04-16 22:20:55 +01001845 if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001846 memcpy(hash, newhash, HASH_SIZE);
Tomas Hozzab37f8b92014-03-25 20:52:28 +00001847 else
1848 memset(hash, 0, HASH_SIZE);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001849#else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001850 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001851#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +00001852 /* Loop round available servers until we succeed in connecting to one.
Josh Soref730c6742017-02-06 16:14:04 +00001853 Note that this code subtly ensures that consecutive queries on this connection
Simon Kelley4f7b3042012-11-28 21:27:02 +00001854 which can go to the same server, do so. */
1855 while (1)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001856 {
Simon Kelley4f7b3042012-11-28 21:27:02 +00001857 if (!firstsendto)
1858 firstsendto = last_server;
1859 else
1860 {
1861 if (!(last_server = last_server->next))
1862 last_server = daemon->servers;
1863
1864 if (last_server == firstsendto)
1865 break;
1866 }
1867
1868 /* server for wrong domain */
1869 if (type != (last_server->flags & SERV_TYPE) ||
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001870 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
1871 (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
Simon Kelley7de060b2011-08-26 17:24:52 +01001872 continue;
Simon Kelley361dfe52017-02-10 21:12:30 +00001873
1874 retry:
Simon Kelley4f7b3042012-11-28 21:27:02 +00001875 if (last_server->tcpfd == -1)
1876 {
1877 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
1878 continue;
1879
Karl Vogele9828b62014-10-03 21:45:15 +01001880#ifdef HAVE_CONNTRACK
1881 /* Copy connection mark of incoming query to outgoing connection. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001882 if (have_mark)
1883 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
Karl Vogele9828b62014-10-03 21:45:15 +01001884#endif
1885
Simon Kelley9d6918d2017-10-13 17:55:09 +01001886 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00001887 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
1888 {
1889 close(last_server->tcpfd);
1890 last_server->tcpfd = -1;
1891 continue;
1892 }
1893
Simon Kelley361dfe52017-02-10 21:12:30 +00001894 last_server->flags &= ~SERV_GOT_TCP;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001895 }
1896
Simon Kelley4b5ea122013-04-22 10:18:26 +01001897 *length = htons(size);
Simon Kelley1fc02682014-04-29 12:30:18 +01001898
1899 /* get query name again for logging - may have been overwritten */
1900 if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
1901 strcpy(daemon->namebuff, "query");
Simon Kelley4f7b3042012-11-28 21:27:02 +00001902
Simon Kelley4b5ea122013-04-22 10:18:26 +01001903 if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
Simon Kelley4f7b3042012-11-28 21:27:02 +00001904 !read_write(last_server->tcpfd, &c1, 1, 1) ||
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001905 !read_write(last_server->tcpfd, &c2, 1, 1) ||
1906 !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
Simon Kelley7de060b2011-08-26 17:24:52 +01001907 {
1908 close(last_server->tcpfd);
1909 last_server->tcpfd = -1;
Simon Kelley361dfe52017-02-10 21:12:30 +00001910 /* We get data then EOF, reopen connection to same server,
1911 else try next. This avoids DoS from a server which accepts
1912 connections and then closes them. */
1913 if (last_server->flags & SERV_GOT_TCP)
1914 goto retry;
1915 else
1916 continue;
1917 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001918
Simon Kelley361dfe52017-02-10 21:12:30 +00001919 last_server->flags |= SERV_GOT_TCP;
1920
Simon Kelley4f7b3042012-11-28 21:27:02 +00001921 m = (c1 << 8) | c2;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001922
Simon Kelley4f7b3042012-11-28 21:27:02 +00001923 if (last_server->addr.sa.sa_family == AF_INET)
1924 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1925 (struct all_addr *)&last_server->addr.in.sin_addr, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001926#ifdef HAVE_IPV6
Simon Kelley4f7b3042012-11-28 21:27:02 +00001927 else
1928 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1929 (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001930#endif
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001931
1932#ifdef HAVE_DNSSEC
Simon Kelley367341f2016-01-12 15:58:23 +00001933 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001934 {
Simon Kelley7fa836e2014-02-10 20:11:24 +00001935 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
Simon Kelleyf344dbc2016-01-18 18:04:17 +00001936 int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
1937 last_server, have_mark, mark, &keycount);
Simon Kelley554b5802015-04-17 22:50:20 +01001938 char *result, *domain = "result";
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001939
Simon Kelley9a31b682015-12-15 10:20:39 +00001940 if (status == STAT_ABANDONED)
Simon Kelley150162b2015-03-27 09:58:26 +00001941 {
1942 result = "ABANDONED";
1943 status = STAT_BOGUS;
1944 }
Simon Kelley7fa836e2014-02-10 20:11:24 +00001945 else
1946 result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
Simon Kelleye66b4df2015-04-28 20:45:57 +01001947
1948 if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
1949 domain = daemon->namebuff;
Simon Kelley554b5802015-04-17 22:50:20 +01001950
1951 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
Simon Kelley7fa836e2014-02-10 20:11:24 +00001952
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001953 if (status == STAT_BOGUS)
Simon Kelleyfe3992f2015-04-03 21:25:05 +01001954 {
1955 no_cache_dnssec = 1;
1956 bogusanswer = 1;
1957 }
1958
Simon Kelley7d7b7b32014-01-08 15:53:35 +00001959 if (status == STAT_SECURE)
1960 cache_secure = 1;
1961 }
1962#endif
1963
1964 /* restore CD bit to the value in the query */
1965 if (checking_disabled)
1966 header->hb4 |= HB4_CD;
1967 else
1968 header->hb4 &= ~HB4_CD;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001969
1970 /* There's no point in updating the cache, since this process will exit and
1971 lose the information after a few queries. We make this call for the alias and
1972 bogus-nxdomain side-effects. */
1973 /* If the crc of the question section doesn't match the crc we sent, then
1974 someone might be attempting to insert bogus values into the cache by
1975 sending replies containing questions and bogus answers. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001976#ifdef HAVE_DNSSEC
1977 newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
1978 if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
Simon Kelley703c7ff2014-01-25 23:46:23 +00001979 {
1980 m = 0;
1981 break;
1982 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001983#else
1984 if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
Simon Kelley703c7ff2014-01-25 23:46:23 +00001985 {
1986 m = 0;
1987 break;
1988 }
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001989#endif
1990
1991 m = process_reply(header, now, last_server, (unsigned int)m,
Simon Kelleye66b4df2015-04-28 20:45:57 +01001992 option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
Simon Kelleyfa14bec2015-12-20 17:12:16 +00001993 ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
Simon Kelley4f7b3042012-11-28 21:27:02 +00001994
1995 break;
1996 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001997 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00001998
1999 /* In case of local answer or no connections made. */
2000 if (m == 0)
2001 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002002 }
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002003 }
Simon Kelley4f7b3042012-11-28 21:27:02 +00002004
Simon Kelleyb842bc92015-07-12 21:09:11 +01002005 check_log_writer(1);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002006
Simon Kelley4b5ea122013-04-22 10:18:26 +01002007 *length = htons(m);
2008
2009 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002010 return packet;
2011 }
2012}
2013
Simon Kelley16972692006-10-16 20:04:18 +01002014static struct frec *allocate_frec(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002015{
Simon Kelley16972692006-10-16 20:04:18 +01002016 struct frec *f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002017
Simon Kelley5aabfc72007-08-29 11:24:47 +01002018 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002019 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002020 f->next = daemon->frec_list;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002021 f->time = now;
Simon Kelley832af0b2007-01-21 20:01:28 +00002022 f->sentto = NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002023 f->rfd4 = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002024 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002025#ifdef HAVE_IPV6
2026 f->rfd6 = NULL;
2027#endif
Simon Kelley3a237152013-12-12 12:15:50 +00002028#ifdef HAVE_DNSSEC
Simon Kelley97bc7982014-01-31 10:19:52 +00002029 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002030 f->blocking_query = NULL;
Simon Kelley4619d942014-01-16 19:53:06 +00002031 f->stash = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002032#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002033 daemon->frec_list = f;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002034 }
Simon Kelley16972692006-10-16 20:04:18 +01002035
2036 return f;
2037}
2038
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002039struct randfd *allocate_rfd(int family)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002040{
2041 static int finger = 0;
2042 int i;
2043
2044 /* limit the number of sockets we have open to avoid starvation of
2045 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
2046
2047 for (i = 0; i < RANDOM_SOCKS; i++)
Simon Kelley9009d742008-11-14 20:04:27 +00002048 if (daemon->randomsocks[i].refcount == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002049 {
Simon Kelley9009d742008-11-14 20:04:27 +00002050 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
2051 break;
2052
Simon Kelley1a6bca82008-07-11 11:11:42 +01002053 daemon->randomsocks[i].refcount = 1;
2054 daemon->randomsocks[i].family = family;
2055 return &daemon->randomsocks[i];
2056 }
2057
Simon Kelley9009d742008-11-14 20:04:27 +00002058 /* No free ones or cannot get new socket, grab an existing one */
Simon Kelley1a6bca82008-07-11 11:11:42 +01002059 for (i = 0; i < RANDOM_SOCKS; i++)
2060 {
2061 int j = (i+finger) % RANDOM_SOCKS;
Simon Kelley9009d742008-11-14 20:04:27 +00002062 if (daemon->randomsocks[j].refcount != 0 &&
2063 daemon->randomsocks[j].family == family &&
2064 daemon->randomsocks[j].refcount != 0xffff)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002065 {
2066 finger = j;
2067 daemon->randomsocks[j].refcount++;
2068 return &daemon->randomsocks[j];
2069 }
2070 }
2071
2072 return NULL; /* doom */
2073}
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002074
2075void free_rfd(struct randfd *rfd)
2076{
2077 if (rfd && --(rfd->refcount) == 0)
2078 close(rfd->fd);
2079}
2080
Simon Kelley1a6bca82008-07-11 11:11:42 +01002081static void free_frec(struct frec *f)
2082{
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002083 free_rfd(f->rfd4);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002084 f->rfd4 = NULL;
2085 f->sentto = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00002086 f->flags = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +01002087
2088#ifdef HAVE_IPV6
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01002089 free_rfd(f->rfd6);
Simon Kelley1a6bca82008-07-11 11:11:42 +01002090 f->rfd6 = NULL;
2091#endif
Simon Kelley3a237152013-12-12 12:15:50 +00002092
2093#ifdef HAVE_DNSSEC
2094 if (f->stash)
Simon Kelley0fc2f312014-01-08 10:26:58 +00002095 {
2096 blockdata_free(f->stash);
2097 f->stash = NULL;
2098 }
Simon Kelley3a237152013-12-12 12:15:50 +00002099
2100 /* Anything we're waiting on is pointless now, too */
2101 if (f->blocking_query)
2102 free_frec(f->blocking_query);
2103 f->blocking_query = NULL;
Simon Kelley39048ad2014-01-21 17:33:58 +00002104 f->dependent = NULL;
Simon Kelley3a237152013-12-12 12:15:50 +00002105#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +01002106}
2107
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002108
2109
Simon Kelley16972692006-10-16 20:04:18 +01002110/* if wait==NULL return a free or older than TIMEOUT record.
2111 else return *wait zero if one available, or *wait is delay to
Simon Kelley1a6bca82008-07-11 11:11:42 +01002112 when the oldest in-use record will expire. Impose an absolute
Simon Kelley3a237152013-12-12 12:15:50 +00002113 limit of 4*TIMEOUT before we wipe things (for random sockets).
2114 If force is set, always return a result, even if we have
2115 to allocate above the limit. */
2116struct frec *get_new_frec(time_t now, int *wait, int force)
Simon Kelley16972692006-10-16 20:04:18 +01002117{
Simon Kelley1a6bca82008-07-11 11:11:42 +01002118 struct frec *f, *oldest, *target;
Simon Kelley16972692006-10-16 20:04:18 +01002119 int count;
2120
2121 if (wait)
2122 *wait = 0;
2123
Simon Kelley1a6bca82008-07-11 11:11:42 +01002124 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
Simon Kelley832af0b2007-01-21 20:01:28 +00002125 if (!f->sentto)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002126 target = f;
2127 else
Simon Kelley16972692006-10-16 20:04:18 +01002128 {
Simon Kelley9a31b682015-12-15 10:20:39 +00002129#ifdef HAVE_DNSSEC
2130 /* Don't free DNSSEC sub-queries here, as we may end up with
2131 dangling references to them. They'll go when their "real" query
2132 is freed. */
2133 if (!f->dependent)
2134#endif
2135 {
2136 if (difftime(now, f->time) >= 4*TIMEOUT)
2137 {
2138 free_frec(f);
2139 target = f;
2140 }
2141
2142
2143 if (!oldest || difftime(f->time, oldest->time) <= 0)
2144 oldest = f;
2145 }
Simon Kelley16972692006-10-16 20:04:18 +01002146 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01002147
2148 if (target)
2149 {
2150 target->time = now;
2151 return target;
2152 }
Simon Kelley16972692006-10-16 20:04:18 +01002153
2154 /* can't find empty one, use oldest if there is one
2155 and it's older than timeout */
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002156 if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
Simon Kelley16972692006-10-16 20:04:18 +01002157 {
2158 /* keep stuff for twice timeout if we can by allocating a new
2159 record instead */
2160 if (difftime(now, oldest->time) < 2*TIMEOUT &&
2161 count <= daemon->ftabsize &&
2162 (f = allocate_frec(now)))
2163 return f;
2164
2165 if (!wait)
2166 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002167 free_frec(oldest);
Simon Kelley16972692006-10-16 20:04:18 +01002168 oldest->time = now;
2169 }
2170 return oldest;
2171 }
2172
2173 /* none available, calculate time 'till oldest record expires */
Simon Kelley3a237152013-12-12 12:15:50 +00002174 if (!force && count > daemon->ftabsize)
Simon Kelley16972692006-10-16 20:04:18 +01002175 {
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002176 static time_t last_log = 0;
2177
Simon Kelley16972692006-10-16 20:04:18 +01002178 if (oldest && wait)
2179 *wait = oldest->time + (time_t)TIMEOUT - now;
Marcelo Salhab Brogliato0da5e892013-05-31 11:49:06 +01002180
2181 if ((int)difftime(now, last_log) > 5)
2182 {
2183 last_log = now;
2184 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
2185 }
2186
Simon Kelley16972692006-10-16 20:04:18 +01002187 return NULL;
2188 }
2189
2190 if (!(f = allocate_frec(now)) && wait)
2191 /* wait one second on malloc failure */
2192 *wait = 1;
2193
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002194 return f; /* OK if malloc fails and this is NULL */
2195}
Simon Kelley09f3b2c2017-05-09 01:34:02 +01002196
Simon Kelley832af0b2007-01-21 20:01:28 +00002197/* crc is all-ones if not known. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002198static struct frec *lookup_frec(unsigned short id, void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002199{
2200 struct frec *f;
2201
Simon Kelley1a6bca82008-07-11 11:11:42 +01002202 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002203 if (f->sentto && f->new_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002204 (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002205 return f;
2206
2207 return NULL;
2208}
2209
2210static struct frec *lookup_frec_by_sender(unsigned short id,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002211 union mysockaddr *addr,
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002212 void *hash)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002213{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01002214 struct frec *f;
2215
Simon Kelley1a6bca82008-07-11 11:11:42 +01002216 for(f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002217 if (f->sentto &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002218 f->orig_id == id &&
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002219 memcmp(hash, f->hash, HASH_SIZE) == 0 &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002220 sockaddr_isequal(&f->source, addr))
2221 return f;
2222
2223 return NULL;
2224}
Simon Kelley47a95162014-07-08 22:22:02 +01002225
2226/* Send query packet again, if we can. */
2227void resend_query()
2228{
2229 if (daemon->srv_save)
2230 {
2231 int fd;
2232
2233 if (daemon->srv_save->sfd)
2234 fd = daemon->srv_save->sfd->fd;
2235 else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
2236 fd = daemon->rfd_save->fd;
2237 else
2238 return;
2239
Simon Kelleyff841eb2015-03-11 21:36:30 +00002240 while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
2241 &daemon->srv_save->addr.sa,
2242 sa_len(&daemon->srv_save->addr))));
Simon Kelley47a95162014-07-08 22:22:02 +01002243 }
2244}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002245
Simon Kelley849a8352006-06-09 21:02:31 +01002246/* A server record is going away, remove references to it */
Simon Kelley5aabfc72007-08-29 11:24:47 +01002247void server_gone(struct server *server)
Simon Kelley849a8352006-06-09 21:02:31 +01002248{
2249 struct frec *f;
2250
Simon Kelley1a6bca82008-07-11 11:11:42 +01002251 for (f = daemon->frec_list; f; f = f->next)
Simon Kelley832af0b2007-01-21 20:01:28 +00002252 if (f->sentto && f->sentto == server)
Simon Kelley1a6bca82008-07-11 11:11:42 +01002253 free_frec(f);
Simon Kelley849a8352006-06-09 21:02:31 +01002254
2255 if (daemon->last_server == server)
2256 daemon->last_server = NULL;
2257
2258 if (daemon->srv_save == server)
2259 daemon->srv_save = NULL;
2260}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002261
Simon Kelley316e2732010-01-22 20:16:09 +00002262/* return unique random ids. */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002263static unsigned short get_id(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002264{
2265 unsigned short ret = 0;
Simon Kelley832af0b2007-01-21 20:01:28 +00002266
Simon Kelley316e2732010-01-22 20:16:09 +00002267 do
Simon Kelley832af0b2007-01-21 20:01:28 +00002268 ret = rand16();
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002269 while (lookup_frec(ret, NULL));
Simon Kelley832af0b2007-01-21 20:01:28 +00002270
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002271 return ret;
2272}
2273
2274
2275
2276
2277