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