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