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