]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/forward.c
import of dnsmasq-2.31.tar.gz
[people/ms/dnsmasq.git] / src / forward.c
CommitLineData
f6b7dc47 1/* dnsmasq is Copyright (c) 2000 - 2005 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
5 the Free Software Foundation; version 2 dated June, 1991.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11*/
12
9e4abcb5
SK
13#include "dnsmasq.h"
14
15static struct frec *frec_list;
16
17static struct frec *get_new_frec(time_t now);
18static struct frec *lookup_frec(unsigned short id);
19static struct frec *lookup_frec_by_sender(unsigned short id,
fd9fa481
SK
20 union mysockaddr *addr,
21 unsigned int crc);
9e4abcb5
SK
22static unsigned short get_id(void);
23
24/* May be called more than once. */
25void forward_init(int first)
26{
27 struct frec *f;
feba5c1d 28
9e4abcb5
SK
29 if (first)
30 frec_list = NULL;
31 for (f = frec_list; f; f = f->next)
32 f->new_id = 0;
33}
34
44a2a316
SK
35/* Send a UDP packet with it's source address set as "source"
36 unless nowild is true, when we just send it with the kernel default */
cdeda28f 37static void send_from(int fd, int nowild, char *packet, size_t len,
dfa666f2
SK
38 union mysockaddr *to, struct all_addr *source,
39 unsigned int iface)
9e4abcb5 40{
44a2a316
SK
41 struct msghdr msg;
42 struct iovec iov[1];
44a2a316
SK
43 union {
44 struct cmsghdr align; /* this ensures alignment */
5e9e0efb 45#if defined(HAVE_LINUX_NETWORK)
44a2a316
SK
46 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
47#elif defined(IP_SENDSRCADDR)
48 char control[CMSG_SPACE(sizeof(struct in_addr))];
49#endif
50#ifdef HAVE_IPV6
51 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
52#endif
53 } control_u;
feba5c1d 54
44a2a316
SK
55 iov[0].iov_base = packet;
56 iov[0].iov_len = len;
57
feba5c1d
SK
58 msg.msg_control = NULL;
59 msg.msg_controllen = 0;
44a2a316
SK
60 msg.msg_flags = 0;
61 msg.msg_name = to;
62 msg.msg_namelen = sa_len(to);
63 msg.msg_iov = iov;
64 msg.msg_iovlen = 1;
feba5c1d 65
26128d27 66 if (!nowild)
44a2a316 67 {
26128d27 68 struct cmsghdr *cmptr;
feba5c1d
SK
69 msg.msg_control = &control_u;
70 msg.msg_controllen = sizeof(control_u);
26128d27
SK
71 cmptr = CMSG_FIRSTHDR(&msg);
72
73 if (to->sa.sa_family == AF_INET)
74 {
5e9e0efb 75#if defined(HAVE_LINUX_NETWORK)
26128d27
SK
76 struct in_pktinfo *pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
77 pkt->ipi_ifindex = 0;
78 pkt->ipi_spec_dst = source->addr.addr4;
79 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
80 cmptr->cmsg_level = SOL_IP;
81 cmptr->cmsg_type = IP_PKTINFO;
44a2a316 82#elif defined(IP_SENDSRCADDR)
26128d27
SK
83 struct in_addr *a = (struct in_addr *)CMSG_DATA(cmptr);
84 *a = source->addr.addr4;
85 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
86 cmptr->cmsg_level = IPPROTO_IP;
87 cmptr->cmsg_type = IP_SENDSRCADDR;
44a2a316 88#endif
26128d27 89 }
26128d27 90 else
b8187c80 91#ifdef HAVE_IPV6
26128d27
SK
92 {
93 struct in6_pktinfo *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr);
94 pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
95 pkt->ipi6_addr = source->addr.addr6;
96 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
97 cmptr->cmsg_type = IPV6_PKTINFO;
98 cmptr->cmsg_level = IPV6_LEVEL;
99 }
3d8df260
SK
100#else
101 iface = 0; /* eliminate warning */
44a2a316 102#endif
26128d27 103 }
feba5c1d 104
fd9fa481
SK
105 retry:
106 if (sendmsg(fd, &msg, 0) == -1)
feba5c1d 107 {
fd9fa481
SK
108 /* certain Linux kernels seem to object to setting the source address in the IPv6 stack
109 by returning EINVAL from sendmsg. In that case, try again without setting the
110 source address, since it will nearly alway be correct anyway. IPv6 stinks. */
111 if (errno == EINVAL && msg.msg_controllen)
112 {
113 msg.msg_controllen = 0;
114 goto retry;
115 }
116 if (retry_send())
117 goto retry;
feba5c1d 118 }
9e4abcb5 119}
44a2a316 120
36717eee
SK
121static unsigned short search_servers(struct daemon *daemon, time_t now, struct all_addr **addrpp,
122 unsigned short qtype, char *qdomain, int *type, char **domain)
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;
132 unsigned short flags = 0;
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
SK
137 {
138 unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
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
SK
153 }
154 else if (!flags)
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
SK
163 hostname_isequal(matchstart, serv->domain) &&
164 domainlen >= matchlen &&
cdeda28f 165 (domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' ))
feba5c1d
SK
166 {
167 unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
168 *type = SERV_HAS_DOMAIN;
169 *domain = serv->domain;
170 matchlen = domainlen;
feba5c1d 171 if (serv->flags & SERV_NO_ADDR)
36717eee
SK
172 flags = F_NXDOMAIN;
173 else if (serv->flags & SERV_LITERAL_ADDRESS)
feba5c1d 174 {
36717eee
SK
175 if ((sflag | F_QUERY ) & qtype)
176 {
177 flags = qtype;
178 if (serv->addr.sa.sa_family == AF_INET)
179 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
feba5c1d 180#ifdef HAVE_IPV6
36717eee
SK
181 else
182 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
feba5c1d 183#endif
36717eee
SK
184 }
185 else if (!flags)
186 flags = F_NOERR;
feba5c1d
SK
187 }
188 }
189 }
190
36717eee 191 if (flags & ~(F_NOERR | F_NXDOMAIN)) /* flags set here means a literal found */
feba5c1d
SK
192 {
193 if (flags & F_QUERY)
fd9fa481 194 log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0, NULL, 0);
feba5c1d 195 else
fd9fa481 196 log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0, NULL, 0);
feba5c1d 197 }
3d8df260 198 else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
36717eee
SK
199 flags = F_NXDOMAIN;
200
f6b7dc47 201 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon))
c1bb8504 202 flags = F_NOERR;
feba5c1d 203
36717eee 204 if (flags == F_NXDOMAIN || flags == F_NOERR)
fd9fa481 205 log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0, NULL, 0);
feba5c1d
SK
206
207 return flags;
208}
44a2a316 209
9e4abcb5 210/* returns new last_server */
3be34541
SK
211static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *udpaddr,
212 struct all_addr *dst_addr, unsigned int dst_iface,
cdeda28f 213 HEADER *header, size_t plen, time_t now, struct frec *forward)
9e4abcb5 214{
9e4abcb5 215 char *domain = NULL;
0a852541 216 int type = 0;
9e4abcb5 217 struct all_addr *addrp = NULL;
cdeda28f 218 unsigned int crc = questions_crc(header, plen, daemon->namebuff);
9e4abcb5 219 unsigned short flags = 0;
cdeda28f 220 unsigned short gotname = extract_request(header, plen, daemon->namebuff, NULL);
de37951c 221 struct server *start = NULL;
3d8df260
SK
222
223 /* may be no servers available. */
224 if (!daemon->servers)
9e4abcb5 225 forward = NULL;
b8187c80 226 else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
9e4abcb5 227 {
de37951c 228 /* retry on existing query, send to all available servers */
9e4abcb5 229 domain = forward->sentto->domain;
3be34541 230 if (!(daemon->options & OPT_ORDER))
de37951c 231 {
0a852541 232 forward->forwardall = 1;
3be34541 233 daemon->last_server = NULL;
de37951c 234 }
9e4abcb5 235 type = forward->sentto->flags & SERV_TYPE;
de37951c 236 if (!(start = forward->sentto->next))
3be34541 237 start = daemon->servers; /* at end of list, recycle */
9e4abcb5
SK
238 header->id = htons(forward->new_id);
239 }
240 else
241 {
242 if (gotname)
36717eee 243 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
9e4abcb5 244
feba5c1d
SK
245 if (!flags && !(forward = get_new_frec(now)))
246 /* table full - server failure. */
247 flags = F_NEG;
9e4abcb5
SK
248
249 if (forward)
250 {
0a852541
SK
251 forward->source = *udpaddr;
252 forward->dest = *dst_addr;
253 forward->iface = dst_iface;
254 forward->new_id = get_id();
255 forward->fd = udpfd;
256 forward->orig_id = ntohs(header->id);
257 forward->crc = crc;
258 forward->forwardall = 0;
259 header->id = htons(forward->new_id);
260
9e4abcb5
SK
261 /* In strict_order mode, or when using domain specific servers
262 always try servers in the order specified in resolv.conf,
263 otherwise, use the one last known to work. */
264
3be34541
SK
265 if (type != 0 || (daemon->options & OPT_ORDER))
266 start = daemon->servers;
267 else if (!(start = daemon->last_server))
de37951c 268 {
3be34541 269 start = daemon->servers;
0a852541 270 forward->forwardall = 1;
de37951c 271 }
9e4abcb5
SK
272 }
273 }
feba5c1d 274
9e4abcb5
SK
275 /* check for send errors here (no route to host)
276 if we fail to send to all nameservers, send back an error
277 packet straight away (helps modem users when offline) */
278
279 if (!flags && forward)
280 {
de37951c
SK
281 struct server *firstsentto = start;
282 int forwarded = 0;
283
9e4abcb5
SK
284 while (1)
285 {
9e4abcb5
SK
286 /* only send to servers dealing with our domain.
287 domain may be NULL, in which case server->domain
288 must be NULL also. */
289
de37951c 290 if (type == (start->flags & SERV_TYPE) &&
fd9fa481
SK
291 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
292 !(start->flags & SERV_LITERAL_ADDRESS))
9e4abcb5 293 {
fd9fa481 294 if (sendto(start->sfd->fd, (char *)header, plen, 0,
feba5c1d 295 &start->addr.sa,
fd9fa481
SK
296 sa_len(&start->addr)) == -1)
297 {
298 if (retry_send())
299 continue;
300 }
301 else
9e4abcb5 302 {
cdeda28f
SK
303 /* Keep info in case we want to re-send this packet */
304 daemon->srv_save = start;
305 daemon->packet_len = plen;
306
de37951c 307 if (!gotname)
3be34541 308 strcpy(daemon->namebuff, "query");
de37951c 309 if (start->addr.sa.sa_family == AF_INET)
3be34541 310 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481
SK
311 (struct all_addr *)&start->addr.in.sin_addr, 0,
312 NULL, 0);
de37951c
SK
313#ifdef HAVE_IPV6
314 else
3be34541 315 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481
SK
316 (struct all_addr *)&start->addr.in6.sin6_addr, 0,
317 NULL, 0);
de37951c
SK
318#endif
319 forwarded = 1;
320 forward->sentto = start;
0a852541 321 if (!forward->forwardall)
de37951c 322 break;
0a852541 323 forward->forwardall++;
9e4abcb5
SK
324 }
325 }
326
de37951c 327 if (!(start = start->next))
3be34541 328 start = daemon->servers;
9e4abcb5 329
de37951c 330 if (start == firstsentto)
9e4abcb5
SK
331 break;
332 }
333
de37951c 334 if (forwarded)
3be34541 335 return;
de37951c 336
9e4abcb5
SK
337 /* could not send on, prepare to return */
338 header->id = htons(forward->orig_id);
339 forward->new_id = 0; /* cancel */
340 }
341
342 /* could not send on, return empty answer or address if known for whole domain */
b8187c80
SK
343 if (udpfd != -1)
344 {
cdeda28f 345 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
b8187c80
SK
346 send_from(udpfd, daemon->options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface);
347 }
348
3be34541 349 return;
9e4abcb5
SK
350}
351
cdeda28f 352static size_t process_reply(struct daemon *daemon, HEADER *header, time_t now,
5e9e0efb 353 unsigned int query_crc, struct server *server, size_t n)
feba5c1d 354{
36717eee 355 unsigned char *pheader, *sizep;
cdeda28f
SK
356 int munged = 0;
357 size_t plen;
358
feba5c1d
SK
359 /* If upstream is advertising a larger UDP packet size
360 than we allow, trim it so that we don't get overlarge
361 requests for the client. */
362
36717eee 363 if ((pheader = find_pseudoheader(header, n, &plen, &sizep)))
feba5c1d
SK
364 {
365 unsigned short udpsz;
36717eee 366 unsigned char *psave = sizep;
feba5c1d 367
36717eee 368 GETSHORT(udpsz, sizep);
3be34541
SK
369 if (udpsz > daemon->edns_pktsz)
370 PUTSHORT(daemon->edns_pktsz, psave);
feba5c1d
SK
371 }
372
0a852541
SK
373 if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN))
374 return n;
375
feba5c1d 376 /* Complain loudly if the upstream server is non-recursive. */
0a852541
SK
377 if (!header->ra && header->rcode == NOERROR && ntohs(header->ancount) == 0 &&
378 server && !(server->flags & SERV_WARNED_RECURSIVE))
feba5c1d 379 {
3d8df260 380 prettyprint_addr(&server->addr, daemon->namebuff);
b8187c80 381 syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
0a852541
SK
382 if (!(daemon->options & OPT_LOG))
383 server->flags |= SERV_WARNED_RECURSIVE;
384 }
385
fd9fa481
SK
386 if (daemon->bogus_addr && header->rcode != NXDOMAIN &&
387 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
feba5c1d 388 {
fd9fa481
SK
389 munged = 1;
390 header->rcode = NXDOMAIN;
391 header->aa = 0;
36717eee 392 }
fd9fa481 393 else
36717eee 394 {
fd9fa481
SK
395 if (header->rcode == NXDOMAIN &&
396 extract_request(header, n, daemon->namebuff, NULL) &&
f6b7dc47 397 check_for_local_domain(daemon->namebuff, now, daemon))
36717eee
SK
398 {
399 /* if we forwarded a query for a locally known name (because it was for
400 an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
401 since we know that the domain exists, even if upstream doesn't */
fd9fa481
SK
402 munged = 1;
403 header->aa = 1;
404 header->rcode = NOERROR;
feba5c1d 405 }
fd9fa481 406
0a852541
SK
407 /* If the crc of the question section doesn't match the crc we sent, then
408 someone might be attempting to insert bogus values into the cache by
409 sending replies containing questions and bogus answers. */
410 if (query_crc == questions_crc(header, n, daemon->namebuff))
411 extract_addresses(header, n, daemon->namebuff, now, daemon);
feba5c1d 412 }
fd9fa481
SK
413
414 /* do this after extract_addresses. Ensure NODATA reply and remove
415 nameserver info. */
416
417 if (munged)
418 {
419 header->ancount = htons(0);
420 header->nscount = htons(0);
421 header->arcount = htons(0);
422 }
423
36717eee
SK
424 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
425 sections of the packet. Find the new length here and put back pseudoheader
426 if it was removed. */
427 return resize_packet(header, n, pheader, plen);
feba5c1d
SK
428}
429
3be34541
SK
430/* sets new last_server */
431void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
9e4abcb5
SK
432{
433 /* packet from peer server, extract data for cache, and send to
434 original requester */
435 struct frec *forward;
436 HEADER *header;
de37951c
SK
437 union mysockaddr serveraddr;
438 socklen_t addrlen = sizeof(serveraddr);
cdeda28f
SK
439 ssize_t n = recvfrom(sfd->fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
440 size_t nn;
441
442 /* packet buffer overwritten */
443 daemon->srv_save = NULL;
444
de37951c
SK
445 /* Determine the address of the server replying so that we can mark that as good */
446 serveraddr.sa.sa_family = sfd->source_addr.sa.sa_family;
447#ifdef HAVE_IPV6
448 if (serveraddr.sa.sa_family == AF_INET6)
5e9e0efb 449 serveraddr.in6.sin6_flowinfo = 0;
de37951c 450#endif
9e4abcb5 451
3be34541 452 header = (HEADER *)daemon->packet;
fd9fa481
SK
453 forward = lookup_frec(ntohs(header->id));
454
455 if (n >= (int)sizeof(HEADER) && header->qr && forward)
9e4abcb5 456 {
0a852541
SK
457 struct server *server = forward->sentto;
458
b8187c80
SK
459 if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0)
460 /* for broken servers, attempt to send to another one. */
461 {
462 unsigned char *pheader;
cdeda28f
SK
463 size_t plen;
464
b8187c80 465 /* recreate query from reply */
cdeda28f 466 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL);
b8187c80
SK
467 header->ancount = htons(0);
468 header->nscount = htons(0);
469 header->arcount = htons(0);
cdeda28f 470 if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
b8187c80
SK
471 {
472 forward->forwardall = 1;
473 header->qr = 0;
474 header->tc = 0;
475 forward_query(daemon, -1, NULL, NULL, 0, header, nn, now, forward);
476 return;
477 }
478 }
479
0a852541
SK
480 if ((forward->sentto->flags & SERV_TYPE) == 0)
481 {
482 if (header->rcode == SERVFAIL || header->rcode == REFUSED)
483 server = NULL;
484 else
b8187c80
SK
485 {
486 struct server *last_server;
487 /* find good server by address if possible, otherwise assume the last one we sent to */
488 for (last_server = daemon->servers; last_server; last_server = last_server->next)
489 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
490 sockaddr_isequal(&last_server->addr, &serveraddr))
491 {
492 server = last_server;
493 break;
494 }
495 }
0a852541
SK
496 daemon->last_server = server;
497 }
b8187c80 498
0a852541
SK
499 /* If the answer is an error, keep the forward record in place in case
500 we get a good reply from another server. Kill it when we've
501 had replies from all to avoid filling the forwarding table when
502 everything is broken */
503 if (forward->forwardall == 0 || --forward->forwardall == 1 ||
504 (header->rcode != REFUSED && header->rcode != SERVFAIL))
b8187c80 505 {
cdeda28f 506 if ((nn = process_reply(daemon, header, now, forward->crc, server, (size_t)n)))
b8187c80
SK
507 {
508 header->id = htons(forward->orig_id);
509 header->ra = 1; /* recursion if available */
cdeda28f 510 send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn,
b8187c80
SK
511 &forward->source, &forward->dest, forward->iface);
512 }
513 forward->new_id = 0; /* cancel */
514 }
9e4abcb5 515 }
9e4abcb5 516}
44a2a316 517
3be34541 518void receive_query(struct listener *listen, struct daemon *daemon, time_t now)
44a2a316 519{
3be34541 520 HEADER *header = (HEADER *)daemon->packet;
44a2a316 521 union mysockaddr source_addr;
c1bb8504 522 unsigned short type;
44a2a316 523 struct all_addr dst_addr;
f6b7dc47 524 struct in_addr netmask, dst_addr_4;
cdeda28f
SK
525 size_t m;
526 ssize_t n;
527 int if_index = 0;
44a2a316
SK
528 struct iovec iov[1];
529 struct msghdr msg;
530 struct cmsghdr *cmptr;
44a2a316
SK
531 union {
532 struct cmsghdr align; /* this ensures alignment */
533#ifdef HAVE_IPV6
534 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
535#endif
5e9e0efb 536#if defined(HAVE_LINUX_NETWORK)
44a2a316
SK
537 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
538#elif defined(IP_RECVDSTADDR)
539 char control[CMSG_SPACE(sizeof(struct in_addr)) +
540 CMSG_SPACE(sizeof(struct sockaddr_dl))];
541#endif
542 } control_u;
543
cdeda28f
SK
544 /* packet buffer overwritten */
545 daemon->srv_save = NULL;
546
f6b7dc47
SK
547 if (listen->family == AF_INET && (daemon->options & OPT_NOWILD))
548 {
549 dst_addr_4 = listen->iface->addr.in.sin_addr;
550 netmask = listen->iface->netmask;
551 }
552 else
3d8df260
SK
553 {
554 dst_addr_4.s_addr = 0;
555 netmask.s_addr = 0;
556 }
f6b7dc47 557
3be34541
SK
558 iov[0].iov_base = daemon->packet;
559 iov[0].iov_len = daemon->edns_pktsz;
44a2a316
SK
560
561 msg.msg_control = control_u.control;
562 msg.msg_controllen = sizeof(control_u);
563 msg.msg_flags = 0;
564 msg.msg_name = &source_addr;
565 msg.msg_namelen = sizeof(source_addr);
566 msg.msg_iov = iov;
567 msg.msg_iovlen = 1;
568
de37951c 569 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
3be34541 570 return;
44a2a316 571
5e9e0efb
SK
572 if (n < (int)sizeof(HEADER) ||
573 (msg.msg_flags & MSG_TRUNC) ||
574 header->qr)
26128d27
SK
575 return;
576
44a2a316
SK
577 source_addr.sa.sa_family = listen->family;
578#ifdef HAVE_IPV6
579 if (listen->family == AF_INET6)
5e9e0efb 580 source_addr.in6.sin6_flowinfo = 0;
44a2a316
SK
581#endif
582
26128d27
SK
583 if (!(daemon->options & OPT_NOWILD))
584 {
585 struct ifreq ifr;
586
587 if (msg.msg_controllen < sizeof(struct cmsghdr))
588 return;
44a2a316 589
5e9e0efb 590#if defined(HAVE_LINUX_NETWORK)
26128d27
SK
591 if (listen->family == AF_INET)
592 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
593 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
594 {
f6b7dc47 595 dst_addr_4 = dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
26128d27
SK
596 if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
597 }
598#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
599 if (listen->family == AF_INET)
44a2a316 600 {
26128d27
SK
601 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
602 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
f6b7dc47 603 dst_addr_4 = dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
26128d27
SK
604 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
605 if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
44a2a316 606 }
44a2a316 607#endif
26128d27 608
44a2a316 609#ifdef HAVE_IPV6
26128d27
SK
610 if (listen->family == AF_INET6)
611 {
612 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
613 if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
614 {
615 dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
616 if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
617 }
618 }
44a2a316 619#endif
26128d27
SK
620
621 /* enforce available interface configuration */
622
8a911ccc 623 if (if_index == 0)
3be34541 624 return;
44a2a316 625
f6b7dc47 626 if (daemon->if_except || daemon->if_names || (daemon->options & OPT_LOCALISE))
8a911ccc
SK
627 {
628#ifdef SIOCGIFNAME
629 ifr.ifr_ifindex = if_index;
630 if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
3be34541 631 return;
8a911ccc
SK
632#else
633 if (!if_indextoname(if_index, ifr.ifr_name))
3be34541 634 return;
8a911ccc 635#endif
f6b7dc47
SK
636
637 if (listen->family == AF_INET &&
638 (daemon->options & OPT_LOCALISE) &&
639 ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1)
640 return;
641
642 netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
8a911ccc
SK
643 }
644
5e9e0efb
SK
645 if (!iface_check(daemon, listen->family, &dst_addr, ifr.ifr_name))
646 return;
44a2a316
SK
647 }
648
cdeda28f 649 if (extract_request(header, (size_t)n, daemon->namebuff, &type))
44a2a316
SK
650 {
651 if (listen->family == AF_INET)
3be34541 652 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481 653 (struct all_addr *)&source_addr.in.sin_addr, type, NULL, 0);
44a2a316
SK
654#ifdef HAVE_IPV6
655 else
3be34541 656 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481 657 (struct all_addr *)&source_addr.in6.sin6_addr, type, NULL, 0);
44a2a316
SK
658#endif
659 }
660
cdeda28f 661 m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, daemon,
f6b7dc47 662 dst_addr_4, netmask, now);
44a2a316 663 if (m >= 1)
3be34541 664 send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index);
44a2a316 665 else
3be34541 666 forward_query(daemon, listen->fd, &source_addr, &dst_addr, if_index,
cdeda28f 667 header, (size_t)n, now, NULL);
44a2a316
SK
668}
669
3d8df260 670static int read_write(int fd, unsigned char *packet, int size, int rw)
feba5c1d 671{
cdeda28f 672 ssize_t n, done;
feba5c1d
SK
673
674 for (done = 0; done < size; done += n)
675 {
676 retry:
677 if (rw)
678 n = read(fd, &packet[done], (size_t)(size - done));
679 else
680 n = write(fd, &packet[done], (size_t)(size - done));
681
682 if (n == 0)
683 return 0;
684 else if (n == -1)
685 {
5e9e0efb 686 if (errno == EINTR)
feba5c1d 687 goto retry;
feba5c1d
SK
688 else
689 return 0;
690 }
691 }
692 return 1;
693}
694
695/* The daemon forks before calling this: it should deal with one connection,
696 blocking as neccessary, and then return. Note, need to be a bit careful
697 about resources for debug mode, when the fork is suppressed: that's
698 done by the caller. */
3d8df260
SK
699unsigned char *tcp_request(struct daemon *daemon, int confd, time_t now,
700 struct in_addr local_addr, struct in_addr netmask)
feba5c1d 701{
cdeda28f
SK
702 int size = 0;
703 size_t m;
c1bb8504 704 unsigned short qtype, gotname;
feba5c1d
SK
705 unsigned char c1, c2;
706 /* Max TCP packet + slop */
3d8df260 707 unsigned char *packet = malloc(65536 + MAXDNAME + RRFIXEDSZ);
feba5c1d 708 HEADER *header;
3be34541
SK
709 struct server *last_server;
710
feba5c1d
SK
711 while (1)
712 {
713 if (!packet ||
714 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
715 !(size = c1 << 8 | c2) ||
716 !read_write(confd, packet, size, 1))
717 return packet;
718
719 if (size < (int)sizeof(HEADER))
720 continue;
721
722 header = (HEADER *)packet;
723
3be34541 724 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
feba5c1d
SK
725 {
726 union mysockaddr peer_addr;
727 socklen_t peer_len = sizeof(union mysockaddr);
728
729 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1)
730 {
731 if (peer_addr.sa.sa_family == AF_INET)
3be34541 732 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481 733 (struct all_addr *)&peer_addr.in.sin_addr, qtype, NULL, 0);
feba5c1d
SK
734#ifdef HAVE_IPV6
735 else
3be34541 736 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481 737 (struct all_addr *)&peer_addr.in6.sin6_addr, qtype, NULL, 0);
feba5c1d
SK
738#endif
739 }
740 }
741
742 /* m > 0 if answered from cache */
f6b7dc47
SK
743 m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, daemon,
744 local_addr, netmask, now);
feba5c1d
SK
745
746 if (m == 0)
747 {
748 unsigned short flags = 0;
feba5c1d
SK
749 struct all_addr *addrp = NULL;
750 int type = 0;
751 char *domain = NULL;
752
753 if (gotname)
36717eee 754 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
feba5c1d 755
3be34541
SK
756 if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server)
757 last_server = daemon->servers;
758 else
759 last_server = daemon->last_server;
feba5c1d
SK
760
761 if (!flags && last_server)
762 {
763 struct server *firstsendto = NULL;
0a852541
SK
764 unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
765
feba5c1d
SK
766 /* Loop round available servers until we succeed in connecting to one.
767 Note that this code subtley ensures that consecutive queries on this connection
768 which can go to the same server, do so. */
769 while (1)
770 {
771 if (!firstsendto)
772 firstsendto = last_server;
773 else
774 {
775 if (!(last_server = last_server->next))
3be34541 776 last_server = daemon->servers;
feba5c1d
SK
777
778 if (last_server == firstsendto)
779 break;
780 }
781
782 /* server for wrong domain */
783 if (type != (last_server->flags & SERV_TYPE) ||
784 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
785 continue;
786
787 if ((last_server->tcpfd == -1) &&
788 (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 &&
789 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
790 {
791 close(last_server->tcpfd);
792 last_server->tcpfd = -1;
793 }
794
795 if (last_server->tcpfd == -1)
796 continue;
797
798 c1 = size >> 8;
799 c2 = size;
800
801 if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
802 !read_write(last_server->tcpfd, &c2, 1, 0) ||
803 !read_write(last_server->tcpfd, packet, size, 0) ||
804 !read_write(last_server->tcpfd, &c1, 1, 1) ||
805 !read_write(last_server->tcpfd, &c2, 1, 1))
806 {
807 close(last_server->tcpfd);
808 last_server->tcpfd = -1;
809 continue;
810 }
811
812 m = (c1 << 8) | c2;
813 if (!read_write(last_server->tcpfd, packet, m, 1))
814 return packet;
815
816 if (!gotname)
3be34541 817 strcpy(daemon->namebuff, "query");
feba5c1d 818 if (last_server->addr.sa.sa_family == AF_INET)
3be34541 819 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481 820 (struct all_addr *)&last_server->addr.in.sin_addr, 0, NULL, 0);
feba5c1d
SK
821#ifdef HAVE_IPV6
822 else
3be34541 823 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481 824 (struct all_addr *)&last_server->addr.in6.sin6_addr, 0, NULL, 0);
feba5c1d
SK
825#endif
826
827 /* There's no point in updating the cache, since this process will exit and
828 lose the information after one query. We make this call for the alias and
829 bogus-nxdomain side-effects. */
0a852541 830 m = process_reply(daemon, header, now, crc, last_server, (unsigned int)m);
feba5c1d
SK
831
832 break;
833 }
834 }
835
836 /* In case of local answer or no connections made. */
837 if (m == 0)
3be34541 838 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
feba5c1d
SK
839 }
840
841 c1 = m>>8;
842 c2 = m;
843 if (!read_write(confd, &c1, 1, 0) ||
844 !read_write(confd, &c2, 1, 0) ||
845 !read_write(confd, packet, m, 0))
846 return packet;
847 }
848}
849
9e4abcb5
SK
850static struct frec *get_new_frec(time_t now)
851{
852 struct frec *f = frec_list, *oldest = NULL;
853 time_t oldtime = now;
854 int count = 0;
855 static time_t warntime = 0;
856
857 while (f)
858 {
859 if (f->new_id == 0)
860 {
861 f->time = now;
862 return f;
863 }
864
865 if (difftime(f->time, oldtime) <= 0)
866 {
867 oldtime = f->time;
868 oldest = f;
869 }
870
871 count++;
872 f = f->next;
873 }
874
875 /* can't find empty one, use oldest if there is one
876 and it's older than timeout */
877 if (oldest && difftime(now, oldtime) > TIMEOUT)
878 {
879 oldest->time = now;
880 return oldest;
881 }
882
883 if (count > FTABSIZ)
884 { /* limit logging rate so syslog isn't DOSed either */
885 if (!warntime || difftime(now, warntime) > LOGRATE)
886 {
887 warntime = now;
b8187c80 888 syslog(LOG_WARNING, _("forwarding table overflow: check for server loops."));
9e4abcb5
SK
889 }
890 return NULL;
891 }
892
893 if ((f = (struct frec *)malloc(sizeof(struct frec))))
894 {
895 f->next = frec_list;
896 f->time = now;
5e9e0efb 897 f->new_id = 0;
9e4abcb5
SK
898 frec_list = f;
899 }
900 return f; /* OK if malloc fails and this is NULL */
901}
902
903static struct frec *lookup_frec(unsigned short id)
904{
905 struct frec *f;
906
907 for(f = frec_list; f; f = f->next)
908 if (f->new_id == id)
909 return f;
910
911 return NULL;
912}
913
914static struct frec *lookup_frec_by_sender(unsigned short id,
fd9fa481
SK
915 union mysockaddr *addr,
916 unsigned int crc)
9e4abcb5 917{
feba5c1d
SK
918 struct frec *f;
919
9e4abcb5
SK
920 for(f = frec_list; f; f = f->next)
921 if (f->new_id &&
922 f->orig_id == id &&
fd9fa481 923 f->crc == crc &&
9e4abcb5
SK
924 sockaddr_isequal(&f->source, addr))
925 return f;
926
927 return NULL;
928}
929
930
931/* return unique random ids between 1 and 65535 */
932static unsigned short get_id(void)
933{
934 unsigned short ret = 0;
935
936 while (ret == 0)
937 {
938 ret = rand16();
939
940 /* scrap ids already in use */
941 if ((ret != 0) && lookup_frec(ret))
942 ret = 0;
943 }
944
945 return ret;
946}
947
948
949
950
951