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