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