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