]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/forward.c
Add compile-time macro for DNSSEC support.
[people/ms/dnsmasq.git] / src / forward.c
CommitLineData
61744359 1/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
9e4abcb5
SK
2
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
824af85b
SK
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
9e4abcb5
SK
8 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.
824af85b 12
73a08a24
SK
13 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/>.
9e4abcb5
SK
15*/
16
9e4abcb5
SK
17#include "dnsmasq.h"
18
832af0ba 19static struct frec *lookup_frec(unsigned short id, unsigned int crc);
9e4abcb5 20static struct frec *lookup_frec_by_sender(unsigned short id,
fd9fa481
SK
21 union mysockaddr *addr,
22 unsigned int crc);
316e2730 23static unsigned short get_id(unsigned int crc);
1a6bca81
SK
24static void free_frec(struct frec *f);
25static struct randfd *allocate_rfd(int family);
9e4abcb5 26
824af85b 27/* Send a UDP packet with its source address set as "source"
44a2a316 28 unless nowild is true, when we just send it with the kernel default */
29689cfa
SK
29int send_from(int fd, int nowild, char *packet, size_t len,
30 union mysockaddr *to, struct all_addr *source,
50303b19 31 unsigned int iface)
9e4abcb5 32{
44a2a316
SK
33 struct msghdr msg;
34 struct iovec iov[1];
44a2a316
SK
35 union {
36 struct cmsghdr align; /* this ensures alignment */
5e9e0efb 37#if defined(HAVE_LINUX_NETWORK)
44a2a316
SK
38 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
39#elif defined(IP_SENDSRCADDR)
40 char control[CMSG_SPACE(sizeof(struct in_addr))];
41#endif
42#ifdef HAVE_IPV6
43 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
44#endif
45 } control_u;
feba5c1d 46
44a2a316
SK
47 iov[0].iov_base = packet;
48 iov[0].iov_len = len;
49
feba5c1d
SK
50 msg.msg_control = NULL;
51 msg.msg_controllen = 0;
44a2a316
SK
52 msg.msg_flags = 0;
53 msg.msg_name = to;
54 msg.msg_namelen = sa_len(to);
55 msg.msg_iov = iov;
56 msg.msg_iovlen = 1;
feba5c1d 57
26128d27 58 if (!nowild)
44a2a316 59 {
26128d27 60 struct cmsghdr *cmptr;
feba5c1d
SK
61 msg.msg_control = &control_u;
62 msg.msg_controllen = sizeof(control_u);
26128d27
SK
63 cmptr = CMSG_FIRSTHDR(&msg);
64
65 if (to->sa.sa_family == AF_INET)
66 {
5e9e0efb 67#if defined(HAVE_LINUX_NETWORK)
8ef5ada2
SK
68 struct in_pktinfo p;
69 p.ipi_ifindex = 0;
70 p.ipi_spec_dst = source->addr.addr4;
71 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
26128d27 72 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
c72daea8 73 cmptr->cmsg_level = IPPROTO_IP;
26128d27 74 cmptr->cmsg_type = IP_PKTINFO;
44a2a316 75#elif defined(IP_SENDSRCADDR)
8ef5ada2 76 memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
26128d27
SK
77 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
78 cmptr->cmsg_level = IPPROTO_IP;
79 cmptr->cmsg_type = IP_SENDSRCADDR;
44a2a316 80#endif
26128d27 81 }
26128d27 82 else
b8187c80 83#ifdef HAVE_IPV6
26128d27 84 {
8ef5ada2
SK
85 struct in6_pktinfo p;
86 p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
87 p.ipi6_addr = source->addr.addr6;
88 memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
26128d27 89 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
316e2730 90 cmptr->cmsg_type = daemon->v6pktinfo;
c72daea8 91 cmptr->cmsg_level = IPPROTO_IPV6;
26128d27 92 }
3d8df260 93#else
c72daea8 94 (void)iface; /* eliminate warning */
44a2a316 95#endif
26128d27 96 }
feba5c1d 97
29d28dda 98 while (sendmsg(fd, &msg, 0) == -1)
feba5c1d 99 {
fd9fa481 100 if (retry_send())
29d28dda 101 continue;
22d904db 102
29d28dda
SK
103 /* If interface is still in DAD, EINVAL results - ignore that. */
104 if (errno == EINVAL)
105 break;
29689cfa 106
29d28dda 107 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
29689cfa 108 return 0;
feba5c1d 109 }
29d28dda 110
29689cfa 111 return 1;
9e4abcb5 112}
44a2a316 113
28866e95
SK
114static unsigned int search_servers(time_t now, struct all_addr **addrpp,
115 unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind)
feba5c1d
SK
116
117{
118 /* If the query ends in the domain in one of our servers, set
119 domain to point to that name. We find the largest match to allow both
120 domain.org and sub.domain.org to exist. */
121
122 unsigned int namelen = strlen(qdomain);
123 unsigned int matchlen = 0;
124 struct server *serv;
28866e95 125 unsigned int flags = 0;
feba5c1d 126
3be34541 127 for (serv = daemon->servers; serv; serv=serv->next)
feba5c1d 128 /* domain matches take priority over NODOTS matches */
3d8df260 129 if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
feba5c1d 130 {
28866e95 131 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
feba5c1d 132 *type = SERV_FOR_NODOTS;
feba5c1d 133 if (serv->flags & SERV_NO_ADDR)
36717eee
SK
134 flags = F_NXDOMAIN;
135 else if (serv->flags & SERV_LITERAL_ADDRESS)
136 {
137 if (sflag & qtype)
138 {
139 flags = sflag;
140 if (serv->addr.sa.sa_family == AF_INET)
141 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
feba5c1d 142#ifdef HAVE_IPV6
36717eee
SK
143 else
144 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
feba5c1d 145#endif
36717eee 146 }
824af85b 147 else if (!flags || (flags & F_NXDOMAIN))
36717eee
SK
148 flags = F_NOERR;
149 }
feba5c1d
SK
150 }
151 else if (serv->flags & SERV_HAS_DOMAIN)
152 {
153 unsigned int domainlen = strlen(serv->domain);
b8187c80 154 char *matchstart = qdomain + namelen - domainlen;
feba5c1d 155 if (namelen >= domainlen &&
b8187c80 156 hostname_isequal(matchstart, serv->domain) &&
8ef5ada2 157 (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
feba5c1d 158 {
8ef5ada2
SK
159 if (serv->flags & SERV_NO_REBIND)
160 *norebind = 1;
28866e95 161 else
feba5c1d 162 {
28866e95
SK
163 unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
164 /* implement priority rules for --address and --server for same domain.
165 --address wins if the address is for the correct AF
166 --server wins otherwise. */
167 if (domainlen != 0 && domainlen == matchlen)
36717eee 168 {
28866e95 169 if ((serv->flags & SERV_LITERAL_ADDRESS))
8ef5ada2 170 {
28866e95
SK
171 if (!(sflag & qtype) && flags == 0)
172 continue;
173 }
174 else
175 {
176 if (flags & (F_IPV4 | F_IPV6))
177 continue;
178 }
179 }
180
181 if (domainlen >= matchlen)
182 {
183 *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
184 *domain = serv->domain;
185 matchlen = domainlen;
186 if (serv->flags & SERV_NO_ADDR)
187 flags = F_NXDOMAIN;
188 else if (serv->flags & SERV_LITERAL_ADDRESS)
189 {
190 if (sflag & qtype)
191 {
192 flags = sflag;
193 if (serv->addr.sa.sa_family == AF_INET)
194 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
feba5c1d 195#ifdef HAVE_IPV6
28866e95
SK
196 else
197 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
feba5c1d 198#endif
28866e95
SK
199 }
200 else if (!flags || (flags & F_NXDOMAIN))
201 flags = F_NOERR;
8ef5ada2 202 }
28866e95
SK
203 else
204 flags = 0;
205 }
206 }
8ef5ada2 207 }
feba5c1d 208 }
8ef5ada2 209
7de060b0 210 if (flags == 0 && !(qtype & F_QUERY) &&
28866e95 211 option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
7de060b0
SK
212 /* don't forward A or AAAA queries for simple names, except the empty name */
213 flags = F_NOERR;
8ef5ada2 214
5aabfc78 215 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
c1bb8504 216 flags = F_NOERR;
feba5c1d 217
824af85b
SK
218 if (flags)
219 {
220 int logflags = 0;
221
222 if (flags == F_NXDOMAIN || flags == F_NOERR)
223 logflags = F_NEG | qtype;
224
1a6bca81 225 log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
824af85b 226 }
8ef5ada2
SK
227 else if ((*type) & SERV_USE_RESOLV)
228 {
229 *type = 0; /* use normal servers for this domain */
230 *domain = NULL;
231 }
feba5c1d
SK
232 return flags;
233}
44a2a316 234
824af85b
SK
235static int forward_query(int udpfd, union mysockaddr *udpaddr,
236 struct all_addr *dst_addr, unsigned int dst_iface,
572b41eb 237 struct dns_header *header, size_t plen, time_t now, struct frec *forward)
9e4abcb5 238{
9e4abcb5 239 char *domain = NULL;
8ef5ada2 240 int type = 0, norebind = 0;
9e4abcb5 241 struct all_addr *addrp = NULL;
cdeda28f 242 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
28866e95
SK
243 unsigned int flags = 0;
244 unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
de37951c 245 struct server *start = NULL;
7de060b0 246
28866e95 247 /* RFC 4035: sect 4.6 para 2 */
572b41eb
SK
248 header->hb4 &= ~HB4_AD;
249
3d8df260
SK
250 /* may be no servers available. */
251 if (!daemon->servers)
9e4abcb5 252 forward = NULL;
b8187c80 253 else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
9e4abcb5 254 {
de37951c 255 /* retry on existing query, send to all available servers */
9e4abcb5 256 domain = forward->sentto->domain;
824af85b 257 forward->sentto->failed_queries++;
28866e95 258 if (!option_bool(OPT_ORDER))
de37951c 259 {
0a852541 260 forward->forwardall = 1;
3be34541 261 daemon->last_server = NULL;
de37951c 262 }
9e4abcb5 263 type = forward->sentto->flags & SERV_TYPE;
de37951c 264 if (!(start = forward->sentto->next))
3be34541 265 start = daemon->servers; /* at end of list, recycle */
9e4abcb5
SK
266 header->id = htons(forward->new_id);
267 }
268 else
269 {
270 if (gotname)
8ef5ada2 271 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
9e4abcb5 272
5aabfc78 273 if (!flags && !(forward = get_new_frec(now, NULL)))
feba5c1d
SK
274 /* table full - server failure. */
275 flags = F_NEG;
9e4abcb5
SK
276
277 if (forward)
278 {
0a852541
SK
279 forward->source = *udpaddr;
280 forward->dest = *dst_addr;
281 forward->iface = dst_iface;
0a852541 282 forward->orig_id = ntohs(header->id);
316e2730 283 forward->new_id = get_id(crc);
832af0ba 284 forward->fd = udpfd;
0a852541
SK
285 forward->crc = crc;
286 forward->forwardall = 0;
28866e95
SK
287 if (norebind)
288 forward->flags |= FREC_NOREBIND;
572b41eb 289 if (header->hb4 & HB4_CD)
28866e95 290 forward->flags |= FREC_CHECKING_DISABLED;
0a852541 291
28866e95
SK
292 header->id = htons(forward->new_id);
293
8ef5ada2
SK
294 /* In strict_order mode, always try servers in the order
295 specified in resolv.conf, if a domain is given
296 always try all the available servers,
9e4abcb5
SK
297 otherwise, use the one last known to work. */
298
8ef5ada2
SK
299 if (type == 0)
300 {
28866e95 301 if (option_bool(OPT_ORDER))
8ef5ada2
SK
302 start = daemon->servers;
303 else if (!(start = daemon->last_server) ||
304 daemon->forwardcount++ > FORWARD_TEST ||
305 difftime(now, daemon->forwardtime) > FORWARD_TIME)
306 {
307 start = daemon->servers;
308 forward->forwardall = 1;
309 daemon->forwardcount = 0;
310 daemon->forwardtime = now;
311 }
312 }
313 else
de37951c 314 {
3be34541 315 start = daemon->servers;
28866e95 316 if (!option_bool(OPT_ORDER))
8ef5ada2 317 forward->forwardall = 1;
de37951c 318 }
9e4abcb5
SK
319 }
320 }
feba5c1d 321
9e4abcb5
SK
322 /* check for send errors here (no route to host)
323 if we fail to send to all nameservers, send back an error
324 packet straight away (helps modem users when offline) */
325
326 if (!flags && forward)
327 {
de37951c
SK
328 struct server *firstsentto = start;
329 int forwarded = 0;
28866e95 330
797a7afb
GT
331 if (option_bool(OPT_ADD_MAC))
332 plen = add_mac(header, plen, ((char *) header) + PACKETSZ, &forward->source);
28866e95 333
9e4abcb5
SK
334 while (1)
335 {
9e4abcb5
SK
336 /* only send to servers dealing with our domain.
337 domain may be NULL, in which case server->domain
338 must be NULL also. */
339
de37951c 340 if (type == (start->flags & SERV_TYPE) &&
fd9fa481
SK
341 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
342 !(start->flags & SERV_LITERAL_ADDRESS))
9e4abcb5 343 {
1a6bca81
SK
344 int fd;
345
346 /* find server socket to use, may need to get random one. */
347 if (start->sfd)
348 fd = start->sfd->fd;
349 else
350 {
351#ifdef HAVE_IPV6
352 if (start->addr.sa.sa_family == AF_INET6)
353 {
354 if (!forward->rfd6 &&
355 !(forward->rfd6 = allocate_rfd(AF_INET6)))
356 break;
3927da46 357 daemon->rfd_save = forward->rfd6;
1a6bca81
SK
358 fd = forward->rfd6->fd;
359 }
360 else
361#endif
362 {
363 if (!forward->rfd4 &&
364 !(forward->rfd4 = allocate_rfd(AF_INET)))
365 break;
3927da46 366 daemon->rfd_save = forward->rfd4;
1a6bca81
SK
367 fd = forward->rfd4->fd;
368 }
7de060b0
SK
369
370#ifdef HAVE_CONNTRACK
371 /* Copy connection mark of incoming query to outgoing connection. */
372 if (option_bool(OPT_CONNTRACK))
373 {
374 unsigned int mark;
797a7afb 375 if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
7de060b0
SK
376 setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
377 }
378#endif
1a6bca81
SK
379 }
380
381 if (sendto(fd, (char *)header, plen, 0,
feba5c1d 382 &start->addr.sa,
fd9fa481
SK
383 sa_len(&start->addr)) == -1)
384 {
385 if (retry_send())
386 continue;
387 }
388 else
9e4abcb5 389 {
cdeda28f
SK
390 /* Keep info in case we want to re-send this packet */
391 daemon->srv_save = start;
392 daemon->packet_len = plen;
393
de37951c 394 if (!gotname)
3be34541 395 strcpy(daemon->namebuff, "query");
de37951c 396 if (start->addr.sa.sa_family == AF_INET)
3be34541 397 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1a6bca81 398 (struct all_addr *)&start->addr.in.sin_addr, NULL);
de37951c
SK
399#ifdef HAVE_IPV6
400 else
3be34541 401 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1a6bca81 402 (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
de37951c 403#endif
824af85b 404 start->queries++;
de37951c
SK
405 forwarded = 1;
406 forward->sentto = start;
0a852541 407 if (!forward->forwardall)
de37951c 408 break;
0a852541 409 forward->forwardall++;
9e4abcb5
SK
410 }
411 }
412
de37951c 413 if (!(start = start->next))
3be34541 414 start = daemon->servers;
9e4abcb5 415
de37951c 416 if (start == firstsentto)
9e4abcb5
SK
417 break;
418 }
419
de37951c 420 if (forwarded)
824af85b 421 return 1;
de37951c 422
9e4abcb5
SK
423 /* could not send on, prepare to return */
424 header->id = htons(forward->orig_id);
1a6bca81 425 free_frec(forward); /* cancel */
9e4abcb5
SK
426 }
427
428 /* could not send on, return empty answer or address if known for whole domain */
b8187c80
SK
429 if (udpfd != -1)
430 {
cdeda28f 431 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
54dd393f 432 send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
b8187c80
SK
433 }
434
824af85b 435 return 0;
9e4abcb5
SK
436}
437
572b41eb 438static size_t process_reply(struct dns_header *header, time_t now,
28866e95 439 struct server *server, size_t n, int check_rebind, int checking_disabled)
feba5c1d 440{
36717eee 441 unsigned char *pheader, *sizep;
13d86c73 442 char **sets = 0;
832af0ba 443 int munged = 0, is_sign;
cdeda28f
SK
444 size_t plen;
445
13d86c73
JD
446#ifdef HAVE_IPSET
447 /* Similar algorithm to search_servers. */
448 struct ipsets *ipset_pos;
449 unsigned int namelen = strlen(daemon->namebuff);
450 unsigned int matchlen = 0;
451 for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
452 {
453 unsigned int domainlen = strlen(ipset_pos->domain);
454 char *matchstart = daemon->namebuff + namelen - domainlen;
455 if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
456 (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
457 domainlen >= matchlen) {
458 matchlen = domainlen;
459 sets = ipset_pos->sets;
460 }
461 }
462#endif
463
feba5c1d 464 /* If upstream is advertising a larger UDP packet size
9009d746
SK
465 than we allow, trim it so that we don't get overlarge
466 requests for the client. We can't do this for signed packets. */
feba5c1d 467
832af0ba 468 if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
feba5c1d
SK
469 {
470 unsigned short udpsz;
36717eee 471 unsigned char *psave = sizep;
feba5c1d 472
36717eee 473 GETSHORT(udpsz, sizep);
3be34541
SK
474 if (udpsz > daemon->edns_pktsz)
475 PUTSHORT(daemon->edns_pktsz, psave);
feba5c1d
SK
476 }
477
28866e95
SK
478 /* RFC 4035 sect 4.6 para 3 */
479 if (!is_sign && !option_bool(OPT_DNSSEC))
572b41eb 480 header->hb4 &= ~HB4_AD;
28866e95 481
572b41eb 482 if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
0a852541
SK
483 return n;
484
feba5c1d 485 /* Complain loudly if the upstream server is non-recursive. */
572b41eb 486 if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 &&
0a852541 487 server && !(server->flags & SERV_WARNED_RECURSIVE))
feba5c1d 488 {
3d8df260 489 prettyprint_addr(&server->addr, daemon->namebuff);
f2621c7f 490 my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
28866e95 491 if (!option_bool(OPT_LOG))
0a852541
SK
492 server->flags |= SERV_WARNED_RECURSIVE;
493 }
494
572b41eb 495 if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
fd9fa481 496 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
feba5c1d 497 {
fd9fa481 498 munged = 1;
572b41eb
SK
499 SET_RCODE(header, NXDOMAIN);
500 header->hb3 &= ~HB3_AA;
36717eee 501 }
fd9fa481 502 else
36717eee 503 {
572b41eb 504 if (RCODE(header) == NXDOMAIN &&
fd9fa481 505 extract_request(header, n, daemon->namebuff, NULL) &&
5aabfc78 506 check_for_local_domain(daemon->namebuff, now))
36717eee
SK
507 {
508 /* if we forwarded a query for a locally known name (because it was for
509 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
510 since we know that the domain exists, even if upstream doesn't */
fd9fa481 511 munged = 1;
572b41eb
SK
512 header->hb3 |= HB3_AA;
513 SET_RCODE(header, NOERROR);
feba5c1d 514 }
832af0ba 515
13d86c73 516 if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, checking_disabled))
824af85b 517 {
8ef5ada2 518 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
824af85b
SK
519 munged = 1;
520 }
feba5c1d 521 }
fd9fa481
SK
522
523 /* do this after extract_addresses. Ensure NODATA reply and remove
524 nameserver info. */
525
526 if (munged)
527 {
528 header->ancount = htons(0);
529 header->nscount = htons(0);
530 header->arcount = htons(0);
531 }
532
36717eee
SK
533 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
534 sections of the packet. Find the new length here and put back pseudoheader
535 if it was removed. */
536 return resize_packet(header, n, pheader, plen);
feba5c1d
SK
537}
538
3be34541 539/* sets new last_server */
1a6bca81 540void reply_query(int fd, int family, time_t now)
9e4abcb5
SK
541{
542 /* packet from peer server, extract data for cache, and send to
543 original requester */
572b41eb 544 struct dns_header *header;
de37951c 545 union mysockaddr serveraddr;
832af0ba 546 struct frec *forward;
de37951c 547 socklen_t addrlen = sizeof(serveraddr);
1a6bca81 548 ssize_t n = recvfrom(fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
cdeda28f 549 size_t nn;
1a6bca81
SK
550 struct server *server;
551
cdeda28f
SK
552 /* packet buffer overwritten */
553 daemon->srv_save = NULL;
832af0ba 554
de37951c 555 /* Determine the address of the server replying so that we can mark that as good */
1a6bca81 556 serveraddr.sa.sa_family = family;
de37951c
SK
557#ifdef HAVE_IPV6
558 if (serveraddr.sa.sa_family == AF_INET6)
5e9e0efb 559 serveraddr.in6.sin6_flowinfo = 0;
de37951c 560#endif
9e4abcb5 561
1a6bca81
SK
562 /* spoof check: answer must come from known server, */
563 for (server = daemon->servers; server; server = server->next)
564 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
565 sockaddr_isequal(&server->addr, &serveraddr))
566 break;
567
572b41eb 568 header = (struct dns_header *)daemon->packet;
fd9fa481 569
1a6bca81 570 if (!server ||
572b41eb 571 n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) ||
1a6bca81
SK
572 !(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
573 return;
574
575 server = forward->sentto;
576
572b41eb 577 if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
28866e95 578 !option_bool(OPT_ORDER) &&
1a6bca81
SK
579 forward->forwardall == 0)
580 /* for broken servers, attempt to send to another one. */
9e4abcb5 581 {
1a6bca81
SK
582 unsigned char *pheader;
583 size_t plen;
584 int is_sign;
832af0ba 585
1a6bca81
SK
586 /* recreate query from reply */
587 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
588 if (!is_sign)
832af0ba 589 {
1a6bca81
SK
590 header->ancount = htons(0);
591 header->nscount = htons(0);
592 header->arcount = htons(0);
593 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
832af0ba 594 {
572b41eb 595 header->hb3 &= ~(HB3_QR | HB3_TC);
1a6bca81
SK
596 forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
597 return;
832af0ba 598 }
832af0ba 599 }
1a6bca81
SK
600 }
601
602 if ((forward->sentto->flags & SERV_TYPE) == 0)
603 {
572b41eb 604 if (RCODE(header) == SERVFAIL || RCODE(header) == REFUSED)
1a6bca81
SK
605 server = NULL;
606 else
b8187c80 607 {
1a6bca81
SK
608 struct server *last_server;
609
610 /* find good server by address if possible, otherwise assume the last one we sent to */
611 for (last_server = daemon->servers; last_server; last_server = last_server->next)
612 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
613 sockaddr_isequal(&last_server->addr, &serveraddr))
614 {
615 server = last_server;
616 break;
617 }
618 }
28866e95 619 if (!option_bool(OPT_ALL_SERVERS))
1a6bca81
SK
620 daemon->last_server = server;
621 }
622
623 /* If the answer is an error, keep the forward record in place in case
624 we get a good reply from another server. Kill it when we've
625 had replies from all to avoid filling the forwarding table when
626 everything is broken */
627 if (forward->forwardall == 0 || --forward->forwardall == 1 ||
572b41eb 628 (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
1a6bca81 629 {
28866e95 630 int check_rebind = !(forward->flags & FREC_NOREBIND);
8ef5ada2 631
28866e95 632 if (!option_bool(OPT_NO_REBIND))
8ef5ada2
SK
633 check_rebind = 0;
634
28866e95 635 if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, forward->flags & FREC_CHECKING_DISABLED)))
1a6bca81
SK
636 {
637 header->id = htons(forward->orig_id);
572b41eb 638 header->hb4 |= HB4_RA; /* recursion if available */
54dd393f 639 send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
50303b19 640 &forward->source, &forward->dest, forward->iface);
b8187c80 641 }
1a6bca81 642 free_frec(forward); /* cancel */
9e4abcb5 643 }
9e4abcb5 644}
44a2a316 645
1a6bca81 646
5aabfc78 647void receive_query(struct listener *listen, time_t now)
44a2a316 648{
572b41eb 649 struct dns_header *header = (struct dns_header *)daemon->packet;
44a2a316 650 union mysockaddr source_addr;
c1bb8504 651 unsigned short type;
44a2a316 652 struct all_addr dst_addr;
f6b7dc47 653 struct in_addr netmask, dst_addr_4;
cdeda28f
SK
654 size_t m;
655 ssize_t n;
656 int if_index = 0;
4f7b304f 657 int auth_dns = 0;
44a2a316
SK
658 struct iovec iov[1];
659 struct msghdr msg;
660 struct cmsghdr *cmptr;
44a2a316
SK
661 union {
662 struct cmsghdr align; /* this ensures alignment */
663#ifdef HAVE_IPV6
664 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
665#endif
5e9e0efb 666#if defined(HAVE_LINUX_NETWORK)
44a2a316 667 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
824af85b
SK
668#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
669 char control[CMSG_SPACE(sizeof(struct in_addr)) +
670 CMSG_SPACE(sizeof(unsigned int))];
44a2a316
SK
671#elif defined(IP_RECVDSTADDR)
672 char control[CMSG_SPACE(sizeof(struct in_addr)) +
673 CMSG_SPACE(sizeof(struct sockaddr_dl))];
674#endif
675 } control_u;
676
cdeda28f
SK
677 /* packet buffer overwritten */
678 daemon->srv_save = NULL;
679
4f7b304f
SK
680 dst_addr_4.s_addr = 0;
681 netmask.s_addr = 0;
682
7e5664bd 683 if (option_bool(OPT_NOWILD) && listen->iface)
3d8df260 684 {
4f7b304f
SK
685 auth_dns = listen->iface->dns_auth;
686
687 if (listen->family == AF_INET)
688 {
689 dst_addr_4 = listen->iface->addr.in.sin_addr;
690 netmask = listen->iface->netmask;
691 }
3d8df260 692 }
4f7b304f 693
3be34541
SK
694 iov[0].iov_base = daemon->packet;
695 iov[0].iov_len = daemon->edns_pktsz;
44a2a316
SK
696
697 msg.msg_control = control_u.control;
698 msg.msg_controllen = sizeof(control_u);
699 msg.msg_flags = 0;
700 msg.msg_name = &source_addr;
701 msg.msg_namelen = sizeof(source_addr);
702 msg.msg_iov = iov;
703 msg.msg_iovlen = 1;
704
de37951c 705 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
3be34541 706 return;
44a2a316 707
572b41eb 708 if (n < (int)sizeof(struct dns_header) ||
5e9e0efb 709 (msg.msg_flags & MSG_TRUNC) ||
572b41eb 710 (header->hb3 & HB3_QR))
26128d27
SK
711 return;
712
44a2a316
SK
713 source_addr.sa.sa_family = listen->family;
714#ifdef HAVE_IPV6
715 if (listen->family == AF_INET6)
5e9e0efb 716 source_addr.in6.sin6_flowinfo = 0;
44a2a316 717#endif
28866e95
SK
718
719 if (!option_bool(OPT_NOWILD))
26128d27
SK
720 {
721 struct ifreq ifr;
722
723 if (msg.msg_controllen < sizeof(struct cmsghdr))
724 return;
44a2a316 725
5e9e0efb 726#if defined(HAVE_LINUX_NETWORK)
26128d27
SK
727 if (listen->family == AF_INET)
728 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
c72daea8 729 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
26128d27 730 {
8ef5ada2
SK
731 union {
732 unsigned char *c;
733 struct in_pktinfo *p;
734 } p;
735 p.c = CMSG_DATA(cmptr);
736 dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
737 if_index = p.p->ipi_ifindex;
26128d27
SK
738 }
739#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
740 if (listen->family == AF_INET)
44a2a316 741 {
26128d27 742 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
8ef5ada2
SK
743 {
744 union {
745 unsigned char *c;
746 unsigned int *i;
747 struct in_addr *a;
748#ifndef HAVE_SOLARIS_NETWORK
749 struct sockaddr_dl *s;
750#endif
751 } p;
752 p.c = CMSG_DATA(cmptr);
753 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
754 dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
755 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
824af85b 756#ifdef HAVE_SOLARIS_NETWORK
8ef5ada2 757 if_index = *(p.i);
824af85b 758#else
8ef5ada2 759 if_index = p.s->sdl_index;
824af85b 760#endif
8ef5ada2 761 }
44a2a316 762 }
44a2a316 763#endif
26128d27 764
44a2a316 765#ifdef HAVE_IPV6
26128d27
SK
766 if (listen->family == AF_INET6)
767 {
768 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
c72daea8 769 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
26128d27 770 {
8ef5ada2
SK
771 union {
772 unsigned char *c;
773 struct in6_pktinfo *p;
774 } p;
775 p.c = CMSG_DATA(cmptr);
776
777 dst_addr.addr.addr6 = p.p->ipi6_addr;
778 if_index = p.p->ipi6_ifindex;
26128d27
SK
779 }
780 }
44a2a316 781#endif
26128d27
SK
782
783 /* enforce available interface configuration */
784
e25db1f2 785 if (!indextoname(listen->fd, if_index, ifr.ifr_name))
5e9e0efb 786 return;
832af0ba 787
e25db1f2
SK
788 if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
789 {
790 if (!option_bool(OPT_CLEVERBIND))
115ac3e4 791 enumerate_interfaces(0);
3f2873d4
SK
792 if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
793 !label_exception(if_index, listen->family, &dst_addr))
e25db1f2
SK
794 return;
795 }
796
552af8b9
SK
797 if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
798 {
799 struct irec *iface;
800
801 /* get the netmask of the interface whch has the address we were sent to.
802 This is no neccessarily the interface we arrived on. */
803
804 for (iface = daemon->interfaces; iface; iface = iface->next)
805 if (iface->addr.sa.sa_family == AF_INET &&
806 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
807 break;
808
809 /* interface may be new */
e25db1f2 810 if (!iface && !option_bool(OPT_CLEVERBIND))
115ac3e4 811 enumerate_interfaces(0);
552af8b9
SK
812
813 for (iface = daemon->interfaces; iface; iface = iface->next)
814 if (iface->addr.sa.sa_family == AF_INET &&
815 iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
816 break;
817
818 /* If we failed, abandon localisation */
819 if (iface)
820 netmask = iface->netmask;
821 else
822 dst_addr_4.s_addr = 0;
823 }
44a2a316
SK
824 }
825
cdeda28f 826 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
44a2a316 827 {
1a6bca81
SK
828 char types[20];
829
4f7b304f 830 querystr(auth_dns ? "auth" : "query", types, type);
1a6bca81 831
44a2a316 832 if (listen->family == AF_INET)
3be34541 833 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
1a6bca81 834 (struct all_addr *)&source_addr.in.sin_addr, types);
44a2a316
SK
835#ifdef HAVE_IPV6
836 else
3be34541 837 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
1a6bca81 838 (struct all_addr *)&source_addr.in6.sin6_addr, types);
44a2a316
SK
839#endif
840 }
841
4820dce9 842#ifdef HAVE_AUTH
4f7b304f 843 if (auth_dns)
824af85b 844 {
49678767 845 m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
4f7b304f
SK
846 if (m >= 1)
847 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
848 (char *)header, m, &source_addr, &dst_addr, if_index);
824af85b 849 }
44a2a316 850 else
4820dce9 851#endif
4f7b304f
SK
852 {
853 m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
854 dst_addr_4, netmask, now);
855
856 if (m >= 1)
857 {
858 send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
859 (char *)header, m, &source_addr, &dst_addr, if_index);
860 daemon->local_answer++;
861 }
862 else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
863 header, (size_t)n, now, NULL))
864 daemon->queries_forwarded++;
865 else
866 daemon->local_answer++;
867 }
44a2a316
SK
868}
869
feba5c1d
SK
870/* The daemon forks before calling this: it should deal with one connection,
871 blocking as neccessary, and then return. Note, need to be a bit careful
872 about resources for debug mode, when the fork is suppressed: that's
873 done by the caller. */
5aabfc78 874unsigned char *tcp_request(int confd, time_t now,
4f7b304f 875 union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
feba5c1d 876{
28866e95
SK
877 size_t size = 0;
878 int norebind = 0;
879 int checking_disabled;
cdeda28f 880 size_t m;
ee86ce68
SK
881 unsigned short qtype;
882 unsigned int gotname;
feba5c1d 883 unsigned char c1, c2;
4b5ea12e
SK
884 /* Max TCP packet + slop + size */
885 unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
886 unsigned char *payload = &packet[2];
887 /* largest field in header is 16-bits, so this is still sufficiently aligned */
888 struct dns_header *header = (struct dns_header *)payload;
889 u16 *length = (u16 *)packet;
3be34541 890 struct server *last_server;
7de060b0
SK
891 struct in_addr dst_addr_4;
892 union mysockaddr peer_addr;
893 socklen_t peer_len = sizeof(union mysockaddr);
3be34541 894
7de060b0
SK
895 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
896 return packet;
897
feba5c1d
SK
898 while (1)
899 {
900 if (!packet ||
901 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
902 !(size = c1 << 8 | c2) ||
4b5ea12e 903 !read_write(confd, payload, size, 1))
feba5c1d
SK
904 return packet;
905
572b41eb 906 if (size < (int)sizeof(struct dns_header))
feba5c1d
SK
907 continue;
908
28866e95 909 /* save state of "cd" flag in query */
572b41eb 910 checking_disabled = header->hb4 & HB4_CD;
28866e95
SK
911
912 /* RFC 4035: sect 4.6 para 2 */
572b41eb 913 header->hb4 &= ~HB4_AD;
feba5c1d 914
3be34541 915 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
feba5c1d 916 {
7de060b0 917 char types[20];
feba5c1d 918
4f7b304f 919 querystr(auth_dns ? "auth" : "query", types, qtype);
7de060b0
SK
920
921 if (peer_addr.sa.sa_family == AF_INET)
922 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
923 (struct all_addr *)&peer_addr.in.sin_addr, types);
feba5c1d 924#ifdef HAVE_IPV6
7de060b0
SK
925 else
926 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
927 (struct all_addr *)&peer_addr.in6.sin6_addr, types);
feba5c1d 928#endif
feba5c1d
SK
929 }
930
7de060b0
SK
931 if (local_addr->sa.sa_family == AF_INET)
932 dst_addr_4 = local_addr->in.sin_addr;
933 else
934 dst_addr_4.s_addr = 0;
935
4820dce9 936#ifdef HAVE_AUTH
4f7b304f 937 if (auth_dns)
49678767 938 m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
4f7b304f 939 else
4820dce9 940#endif
feba5c1d 941 {
4f7b304f
SK
942 /* m > 0 if answered from cache */
943 m = answer_request(header, ((char *) header) + 65536, (size_t)size,
944 dst_addr_4, netmask, now);
feba5c1d 945
4f7b304f
SK
946 /* Do this by steam now we're not in the select() loop */
947 check_log_writer(NULL);
948
949 if (m == 0)
feba5c1d 950 {
4f7b304f
SK
951 unsigned int flags = 0;
952 struct all_addr *addrp = NULL;
953 int type = 0;
954 char *domain = NULL;
feba5c1d 955
4f7b304f
SK
956 if (option_bool(OPT_ADD_MAC))
957 size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
958
959 if (gotname)
960 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
961
962 if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
963 last_server = daemon->servers;
964 else
965 last_server = daemon->last_server;
966
967 if (!flags && last_server)
968 {
969 struct server *firstsendto = NULL;
970 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
971
972 /* Loop round available servers until we succeed in connecting to one.
973 Note that this code subtley ensures that consecutive queries on this connection
974 which can go to the same server, do so. */
975 while (1)
feba5c1d 976 {
4f7b304f
SK
977 if (!firstsendto)
978 firstsendto = last_server;
979 else
980 {
981 if (!(last_server = last_server->next))
982 last_server = daemon->servers;
983
984 if (last_server == firstsendto)
985 break;
986 }
987
988 /* server for wrong domain */
989 if (type != (last_server->flags & SERV_TYPE) ||
990 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
7de060b0
SK
991 continue;
992
4f7b304f 993 if (last_server->tcpfd == -1)
7de060b0 994 {
4f7b304f
SK
995 if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
996 continue;
997
998 if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
999 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
1000 {
1001 close(last_server->tcpfd);
1002 last_server->tcpfd = -1;
1003 continue;
1004 }
1005
7de060b0 1006#ifdef HAVE_CONNTRACK
4f7b304f
SK
1007 /* Copy connection mark of incoming query to outgoing connection. */
1008 if (option_bool(OPT_CONNTRACK))
1009 {
1010 unsigned int mark;
1011 struct all_addr local;
7de060b0 1012#ifdef HAVE_IPV6
4f7b304f
SK
1013 if (local_addr->sa.sa_family == AF_INET6)
1014 local.addr.addr6 = local_addr->in6.sin6_addr;
1015 else
7de060b0 1016#endif
4f7b304f
SK
1017 local.addr.addr4 = local_addr->in.sin_addr;
1018
1019 if (get_incoming_mark(&peer_addr, &local, 1, &mark))
1020 setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
1021 }
7de060b0 1022#endif
4f7b304f
SK
1023 }
1024
4b5ea12e 1025 *length = htons(size);
4f7b304f 1026
4b5ea12e 1027 if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
4f7b304f
SK
1028 !read_write(last_server->tcpfd, &c1, 1, 1) ||
1029 !read_write(last_server->tcpfd, &c2, 1, 1))
1030 {
1031 close(last_server->tcpfd);
1032 last_server->tcpfd = -1;
1033 continue;
1034 }
1035
1036 m = (c1 << 8) | c2;
4b5ea12e 1037 if (!read_write(last_server->tcpfd, payload, m, 1))
4f7b304f
SK
1038 return packet;
1039
1040 if (!gotname)
1041 strcpy(daemon->namebuff, "query");
1042 if (last_server->addr.sa.sa_family == AF_INET)
1043 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
1044 (struct all_addr *)&last_server->addr.in.sin_addr, NULL);
feba5c1d 1045#ifdef HAVE_IPV6
4f7b304f
SK
1046 else
1047 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
1048 (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
feba5c1d 1049#endif
4f7b304f
SK
1050
1051 /* There's no point in updating the cache, since this process will exit and
1052 lose the information after a few queries. We make this call for the alias and
1053 bogus-nxdomain side-effects. */
1054 /* If the crc of the question section doesn't match the crc we sent, then
1055 someone might be attempting to insert bogus values into the cache by
1056 sending replies containing questions and bogus answers. */
1057 if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
1058 m = process_reply(header, now, last_server, (unsigned int)m,
1059 option_bool(OPT_NO_REBIND) && !norebind, checking_disabled);
1060
1061 break;
1062 }
feba5c1d 1063 }
4f7b304f
SK
1064
1065 /* In case of local answer or no connections made. */
1066 if (m == 0)
1067 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
feba5c1d 1068 }
feba5c1d 1069 }
4f7b304f 1070
5aabfc78 1071 check_log_writer(NULL);
feba5c1d 1072
4b5ea12e
SK
1073 *length = htons(m);
1074
1075 if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
feba5c1d
SK
1076 return packet;
1077 }
1078}
1079
1697269c 1080static struct frec *allocate_frec(time_t now)
9e4abcb5 1081{
1697269c
SK
1082 struct frec *f;
1083
5aabfc78 1084 if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
9e4abcb5 1085 {
1a6bca81 1086 f->next = daemon->frec_list;
1697269c 1087 f->time = now;
832af0ba 1088 f->sentto = NULL;
1a6bca81 1089 f->rfd4 = NULL;
28866e95 1090 f->flags = 0;
1a6bca81
SK
1091#ifdef HAVE_IPV6
1092 f->rfd6 = NULL;
1093#endif
1094 daemon->frec_list = f;
1697269c 1095 }
9e4abcb5 1096
1697269c
SK
1097 return f;
1098}
9e4abcb5 1099
1a6bca81
SK
1100static struct randfd *allocate_rfd(int family)
1101{
1102 static int finger = 0;
1103 int i;
1104
1105 /* limit the number of sockets we have open to avoid starvation of
1106 (eg) TFTP. Once we have a reasonable number, randomness should be OK */
1107
1108 for (i = 0; i < RANDOM_SOCKS; i++)
9009d746 1109 if (daemon->randomsocks[i].refcount == 0)
1a6bca81 1110 {
9009d746
SK
1111 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
1112 break;
1113
1a6bca81
SK
1114 daemon->randomsocks[i].refcount = 1;
1115 daemon->randomsocks[i].family = family;
1116 return &daemon->randomsocks[i];
1117 }
1118
9009d746 1119 /* No free ones or cannot get new socket, grab an existing one */
1a6bca81
SK
1120 for (i = 0; i < RANDOM_SOCKS; i++)
1121 {
1122 int j = (i+finger) % RANDOM_SOCKS;
9009d746
SK
1123 if (daemon->randomsocks[j].refcount != 0 &&
1124 daemon->randomsocks[j].family == family &&
1125 daemon->randomsocks[j].refcount != 0xffff)
1a6bca81
SK
1126 {
1127 finger = j;
1128 daemon->randomsocks[j].refcount++;
1129 return &daemon->randomsocks[j];
1130 }
1131 }
1132
1133 return NULL; /* doom */
1134}
1135
1136static void free_frec(struct frec *f)
1137{
1138 if (f->rfd4 && --(f->rfd4->refcount) == 0)
1139 close(f->rfd4->fd);
1140
1141 f->rfd4 = NULL;
1142 f->sentto = NULL;
28866e95 1143 f->flags = 0;
1a6bca81
SK
1144
1145#ifdef HAVE_IPV6
1146 if (f->rfd6 && --(f->rfd6->refcount) == 0)
1147 close(f->rfd6->fd);
1148
1149 f->rfd6 = NULL;
1150#endif
1151}
1152
1697269c
SK
1153/* if wait==NULL return a free or older than TIMEOUT record.
1154 else return *wait zero if one available, or *wait is delay to
1a6bca81
SK
1155 when the oldest in-use record will expire. Impose an absolute
1156 limit of 4*TIMEOUT before we wipe things (for random sockets) */
5aabfc78 1157struct frec *get_new_frec(time_t now, int *wait)
1697269c 1158{
1a6bca81 1159 struct frec *f, *oldest, *target;
1697269c
SK
1160 int count;
1161
1162 if (wait)
1163 *wait = 0;
1164
1a6bca81 1165 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++)
832af0ba 1166 if (!f->sentto)
1a6bca81
SK
1167 target = f;
1168 else
1697269c 1169 {
1a6bca81
SK
1170 if (difftime(now, f->time) >= 4*TIMEOUT)
1171 {
1172 free_frec(f);
1173 target = f;
1174 }
1175
1176 if (!oldest || difftime(f->time, oldest->time) <= 0)
1177 oldest = f;
1697269c 1178 }
1a6bca81
SK
1179
1180 if (target)
1181 {
1182 target->time = now;
1183 return target;
1184 }
9e4abcb5
SK
1185
1186 /* can't find empty one, use oldest if there is one
1187 and it's older than timeout */
1697269c 1188 if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
9e4abcb5 1189 {
1697269c
SK
1190 /* keep stuff for twice timeout if we can by allocating a new
1191 record instead */
1192 if (difftime(now, oldest->time) < 2*TIMEOUT &&
1193 count <= daemon->ftabsize &&
1194 (f = allocate_frec(now)))
1195 return f;
1196
1197 if (!wait)
1198 {
1a6bca81 1199 free_frec(oldest);
1697269c
SK
1200 oldest->time = now;
1201 }
9e4abcb5
SK
1202 return oldest;
1203 }
1204
1697269c 1205 /* none available, calculate time 'till oldest record expires */
208b65c5 1206 if (count > daemon->ftabsize)
1697269c 1207 {
0da5e897
MSB
1208 static time_t last_log = 0;
1209
1697269c
SK
1210 if (oldest && wait)
1211 *wait = oldest->time + (time_t)TIMEOUT - now;
0da5e897
MSB
1212
1213 if ((int)difftime(now, last_log) > 5)
1214 {
1215 last_log = now;
1216 my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
1217 }
1218
9e4abcb5
SK
1219 return NULL;
1220 }
1697269c
SK
1221
1222 if (!(f = allocate_frec(now)) && wait)
1223 /* wait one second on malloc failure */
1224 *wait = 1;
9e4abcb5 1225
9e4abcb5
SK
1226 return f; /* OK if malloc fails and this is NULL */
1227}
1228
832af0ba
SK
1229/* crc is all-ones if not known. */
1230static struct frec *lookup_frec(unsigned short id, unsigned int crc)
9e4abcb5
SK
1231{
1232 struct frec *f;
1233
1a6bca81 1234 for(f = daemon->frec_list; f; f = f->next)
832af0ba
SK
1235 if (f->sentto && f->new_id == id &&
1236 (f->crc == crc || crc == 0xffffffff))
9e4abcb5
SK
1237 return f;
1238
1239 return NULL;
1240}
1241
1242static struct frec *lookup_frec_by_sender(unsigned short id,
fd9fa481
SK
1243 union mysockaddr *addr,
1244 unsigned int crc)
9e4abcb5 1245{
feba5c1d
SK
1246 struct frec *f;
1247
1a6bca81 1248 for(f = daemon->frec_list; f; f = f->next)
832af0ba 1249 if (f->sentto &&
9e4abcb5 1250 f->orig_id == id &&
fd9fa481 1251 f->crc == crc &&
9e4abcb5
SK
1252 sockaddr_isequal(&f->source, addr))
1253 return f;
1254
1255 return NULL;
1256}
1257
849a8357 1258/* A server record is going away, remove references to it */
5aabfc78 1259void server_gone(struct server *server)
849a8357
SK
1260{
1261 struct frec *f;
1262
1a6bca81 1263 for (f = daemon->frec_list; f; f = f->next)
832af0ba 1264 if (f->sentto && f->sentto == server)
1a6bca81 1265 free_frec(f);
849a8357
SK
1266
1267 if (daemon->last_server == server)
1268 daemon->last_server = NULL;
1269
1270 if (daemon->srv_save == server)
1271 daemon->srv_save = NULL;
1272}
9e4abcb5 1273
316e2730
SK
1274/* return unique random ids. */
1275static unsigned short get_id(unsigned int crc)
9e4abcb5
SK
1276{
1277 unsigned short ret = 0;
832af0ba 1278
316e2730 1279 do
832af0ba
SK
1280 ret = rand16();
1281 while (lookup_frec(ret, crc));
1282
9e4abcb5
SK
1283 return ret;
1284}
1285
1286
1287
1288
1289