]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/forward.c
import of dnsmasq-2.19.tar.gz
[people/ms/dnsmasq.git] / src / forward.c
CommitLineData
9e4abcb5
SK
1/* dnsmasq is Copyright (c) 2000 - 2003 Simon Kelley
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
200 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon->mxnames))
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) &&
393 check_for_local_domain(daemon->namebuff, now, daemon->mxnames))
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;
8a911ccc 477 int m, n, if_index = 0;
44a2a316
SK
478 struct iovec iov[1];
479 struct msghdr msg;
480 struct cmsghdr *cmptr;
44a2a316
SK
481 union {
482 struct cmsghdr align; /* this ensures alignment */
483#ifdef HAVE_IPV6
484 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
485#endif
486#if defined(IP_PKTINFO)
487 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
488#elif defined(IP_RECVDSTADDR)
489 char control[CMSG_SPACE(sizeof(struct in_addr)) +
490 CMSG_SPACE(sizeof(struct sockaddr_dl))];
491#endif
492 } control_u;
493
3be34541
SK
494 iov[0].iov_base = daemon->packet;
495 iov[0].iov_len = daemon->edns_pktsz;
44a2a316
SK
496
497 msg.msg_control = control_u.control;
498 msg.msg_controllen = sizeof(control_u);
499 msg.msg_flags = 0;
500 msg.msg_name = &source_addr;
501 msg.msg_namelen = sizeof(source_addr);
502 msg.msg_iov = iov;
503 msg.msg_iovlen = 1;
504
de37951c 505 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
3be34541 506 return;
44a2a316 507
26128d27
SK
508 if (n < (int)sizeof(HEADER) || header->qr)
509 return;
510
44a2a316
SK
511 source_addr.sa.sa_family = listen->family;
512#ifdef HAVE_IPV6
513 if (listen->family == AF_INET6)
26128d27 514 source_addr.in6.sin6_flowinfo = htonl(0);
44a2a316
SK
515#endif
516
26128d27
SK
517 if (!(daemon->options & OPT_NOWILD))
518 {
519 struct ifreq ifr;
520
521 if (msg.msg_controllen < sizeof(struct cmsghdr))
522 return;
44a2a316
SK
523
524#if defined(IP_PKTINFO)
26128d27
SK
525 if (listen->family == AF_INET)
526 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
527 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
528 {
529 dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
530 if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
531 }
532#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
533 if (listen->family == AF_INET)
44a2a316 534 {
26128d27
SK
535 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
536 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
537 dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
538 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
539 if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
44a2a316 540 }
44a2a316 541#endif
26128d27 542
44a2a316 543#ifdef HAVE_IPV6
26128d27
SK
544 if (listen->family == AF_INET6)
545 {
546 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
547 if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
548 {
549 dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
550 if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
551 }
552 }
44a2a316 553#endif
26128d27
SK
554
555 /* enforce available interface configuration */
556
8a911ccc 557 if (if_index == 0)
3be34541 558 return;
44a2a316 559
3be34541 560 if (daemon->if_except || daemon->if_names)
8a911ccc
SK
561 {
562#ifdef SIOCGIFNAME
563 ifr.ifr_ifindex = if_index;
564 if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
3be34541 565 return;
8a911ccc
SK
566#else
567 if (!if_indextoname(if_index, ifr.ifr_name))
3be34541 568 return;
8a911ccc
SK
569#endif
570 }
571
3be34541 572 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
8a911ccc 573 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
3be34541 574 return;
9e4abcb5 575
3be34541 576 if (daemon->if_names || daemon->if_addrs)
44a2a316 577 {
3be34541 578 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
8a911ccc 579 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
44a2a316
SK
580 break;
581 if (!tmp)
3be34541 582 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
44a2a316
SK
583 if (tmp->addr.sa.sa_family == listen->family)
584 {
585 if (tmp->addr.sa.sa_family == AF_INET &&
586 tmp->addr.in.sin_addr.s_addr == dst_addr.addr.addr4.s_addr)
587 break;
588#ifdef HAVE_IPV6
589 else if (tmp->addr.sa.sa_family == AF_INET6 &&
590 memcmp(&tmp->addr.in6.sin6_addr,
591 &dst_addr.addr.addr6,
592 sizeof(struct in6_addr)) == 0)
593 break;
594#endif
595 }
596 if (!tmp)
3be34541 597 return;
44a2a316
SK
598 }
599 }
600
3be34541 601 if (extract_request(header, (unsigned int)n, daemon->namebuff, &type))
44a2a316
SK
602 {
603 if (listen->family == AF_INET)
3be34541 604 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481 605 (struct all_addr *)&source_addr.in.sin_addr, type, NULL, 0);
44a2a316
SK
606#ifdef HAVE_IPV6
607 else
3be34541 608 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481 609 (struct all_addr *)&source_addr.in6.sin6_addr, type, NULL, 0);
44a2a316
SK
610#endif
611 }
612
3be34541 613 m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, daemon, now);
44a2a316 614 if (m >= 1)
3be34541 615 send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index);
44a2a316 616 else
3be34541
SK
617 forward_query(daemon, listen->fd, &source_addr, &dst_addr, if_index,
618 header, n, now);
44a2a316
SK
619}
620
feba5c1d
SK
621static int read_write(int fd, char *packet, int size, int rw)
622{
623 int n, done;
624
625 for (done = 0; done < size; done += n)
626 {
627 retry:
628 if (rw)
629 n = read(fd, &packet[done], (size_t)(size - done));
630 else
631 n = write(fd, &packet[done], (size_t)(size - done));
632
633 if (n == 0)
634 return 0;
635 else if (n == -1)
636 {
fd9fa481 637 if (retry_send())
feba5c1d 638 goto retry;
feba5c1d
SK
639 else
640 return 0;
641 }
642 }
643 return 1;
644}
645
646/* The daemon forks before calling this: it should deal with one connection,
647 blocking as neccessary, and then return. Note, need to be a bit careful
648 about resources for debug mode, when the fork is suppressed: that's
649 done by the caller. */
3be34541 650char *tcp_request(struct daemon *daemon, int confd, time_t now)
feba5c1d
SK
651{
652 int size = 0, m;
c1bb8504 653 unsigned short qtype, gotname;
feba5c1d
SK
654 unsigned char c1, c2;
655 /* Max TCP packet + slop */
656 char *packet = malloc(65536 + MAXDNAME + RRFIXEDSZ);
657 HEADER *header;
3be34541
SK
658 struct server *last_server;
659
feba5c1d
SK
660 while (1)
661 {
662 if (!packet ||
663 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
664 !(size = c1 << 8 | c2) ||
665 !read_write(confd, packet, size, 1))
666 return packet;
667
668 if (size < (int)sizeof(HEADER))
669 continue;
670
671 header = (HEADER *)packet;
672
3be34541 673 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
feba5c1d
SK
674 {
675 union mysockaddr peer_addr;
676 socklen_t peer_len = sizeof(union mysockaddr);
677
678 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1)
679 {
680 if (peer_addr.sa.sa_family == AF_INET)
3be34541 681 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481 682 (struct all_addr *)&peer_addr.in.sin_addr, qtype, NULL, 0);
feba5c1d
SK
683#ifdef HAVE_IPV6
684 else
3be34541 685 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481 686 (struct all_addr *)&peer_addr.in6.sin6_addr, qtype, NULL, 0);
feba5c1d
SK
687#endif
688 }
689 }
690
691 /* m > 0 if answered from cache */
3be34541 692 m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, daemon, now);
feba5c1d
SK
693
694 if (m == 0)
695 {
696 unsigned short flags = 0;
feba5c1d
SK
697 struct all_addr *addrp = NULL;
698 int type = 0;
699 char *domain = NULL;
700
701 if (gotname)
36717eee 702 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
feba5c1d 703
3be34541
SK
704 if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server)
705 last_server = daemon->servers;
706 else
707 last_server = daemon->last_server;
feba5c1d
SK
708
709 if (!flags && last_server)
710 {
711 struct server *firstsendto = NULL;
712
713 /* Loop round available servers until we succeed in connecting to one.
714 Note that this code subtley ensures that consecutive queries on this connection
715 which can go to the same server, do so. */
716 while (1)
717 {
718 if (!firstsendto)
719 firstsendto = last_server;
720 else
721 {
722 if (!(last_server = last_server->next))
3be34541 723 last_server = daemon->servers;
feba5c1d
SK
724
725 if (last_server == firstsendto)
726 break;
727 }
728
729 /* server for wrong domain */
730 if (type != (last_server->flags & SERV_TYPE) ||
731 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
732 continue;
733
734 if ((last_server->tcpfd == -1) &&
735 (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 &&
736 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
737 {
738 close(last_server->tcpfd);
739 last_server->tcpfd = -1;
740 }
741
742 if (last_server->tcpfd == -1)
743 continue;
744
745 c1 = size >> 8;
746 c2 = size;
747
748 if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
749 !read_write(last_server->tcpfd, &c2, 1, 0) ||
750 !read_write(last_server->tcpfd, packet, size, 0) ||
751 !read_write(last_server->tcpfd, &c1, 1, 1) ||
752 !read_write(last_server->tcpfd, &c2, 1, 1))
753 {
754 close(last_server->tcpfd);
755 last_server->tcpfd = -1;
756 continue;
757 }
758
759 m = (c1 << 8) | c2;
760 if (!read_write(last_server->tcpfd, packet, m, 1))
761 return packet;
762
763 if (!gotname)
3be34541 764 strcpy(daemon->namebuff, "query");
feba5c1d 765 if (last_server->addr.sa.sa_family == AF_INET)
3be34541 766 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
fd9fa481 767 (struct all_addr *)&last_server->addr.in.sin_addr, 0, NULL, 0);
feba5c1d
SK
768#ifdef HAVE_IPV6
769 else
3be34541 770 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
fd9fa481 771 (struct all_addr *)&last_server->addr.in6.sin6_addr, 0, NULL, 0);
feba5c1d
SK
772#endif
773
774 /* There's no point in updating the cache, since this process will exit and
775 lose the information after one query. We make this call for the alias and
776 bogus-nxdomain side-effects. */
36717eee 777 m = process_reply(daemon, header, now, &last_server->addr, (unsigned int)m);
feba5c1d
SK
778
779 break;
780 }
781 }
782
783 /* In case of local answer or no connections made. */
784 if (m == 0)
3be34541 785 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
feba5c1d
SK
786 }
787
788 c1 = m>>8;
789 c2 = m;
790 if (!read_write(confd, &c1, 1, 0) ||
791 !read_write(confd, &c2, 1, 0) ||
792 !read_write(confd, packet, m, 0))
793 return packet;
794 }
795}
796
9e4abcb5
SK
797static struct frec *get_new_frec(time_t now)
798{
799 struct frec *f = frec_list, *oldest = NULL;
800 time_t oldtime = now;
801 int count = 0;
802 static time_t warntime = 0;
803
804 while (f)
805 {
806 if (f->new_id == 0)
807 {
808 f->time = now;
809 return f;
810 }
811
812 if (difftime(f->time, oldtime) <= 0)
813 {
814 oldtime = f->time;
815 oldest = f;
816 }
817
818 count++;
819 f = f->next;
820 }
821
822 /* can't find empty one, use oldest if there is one
823 and it's older than timeout */
824 if (oldest && difftime(now, oldtime) > TIMEOUT)
825 {
826 oldest->time = now;
827 return oldest;
828 }
829
830 if (count > FTABSIZ)
831 { /* limit logging rate so syslog isn't DOSed either */
832 if (!warntime || difftime(now, warntime) > LOGRATE)
833 {
834 warntime = now;
835 syslog(LOG_WARNING, "forwarding table overflow: check for server loops.");
836 }
837 return NULL;
838 }
839
840 if ((f = (struct frec *)malloc(sizeof(struct frec))))
841 {
842 f->next = frec_list;
843 f->time = now;
844 frec_list = f;
845 }
846 return f; /* OK if malloc fails and this is NULL */
847}
848
849static struct frec *lookup_frec(unsigned short id)
850{
851 struct frec *f;
852
853 for(f = frec_list; f; f = f->next)
854 if (f->new_id == id)
855 return f;
856
857 return NULL;
858}
859
860static struct frec *lookup_frec_by_sender(unsigned short id,
fd9fa481
SK
861 union mysockaddr *addr,
862 unsigned int crc)
9e4abcb5 863{
feba5c1d
SK
864 struct frec *f;
865
9e4abcb5
SK
866 for(f = frec_list; f; f = f->next)
867 if (f->new_id &&
868 f->orig_id == id &&
fd9fa481 869 f->crc == crc &&
9e4abcb5
SK
870 sockaddr_isequal(&f->source, addr))
871 return f;
872
873 return NULL;
874}
875
876
877/* return unique random ids between 1 and 65535 */
878static unsigned short get_id(void)
879{
880 unsigned short ret = 0;
881
882 while (ret == 0)
883 {
884 ret = rand16();
885
886 /* scrap ids already in use */
887 if ((ret != 0) && lookup_frec(ret))
888 ret = 0;
889 }
890
891 return ret;
892}
893
894
895
896
897