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