]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/forward.c
import of dnsmasq-2.17.tar.gz
[people/ms/dnsmasq.git] / src / forward.c
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
17 static struct frec *frec_list;
18
19 static struct frec *get_new_frec(time_t now);
20 static struct frec *lookup_frec(unsigned short id);
21 static struct frec *lookup_frec_by_sender(unsigned short id,
22 union mysockaddr *addr,
23 unsigned int crc);
24 static unsigned short get_id(void);
25
26 /* May be called more than once. */
27 void forward_init(int first)
28 {
29 struct frec *f;
30
31 if (first)
32 frec_list = NULL;
33 for (f = frec_list; f; f = f->next)
34 f->new_id = 0;
35 }
36
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 */
39 static void send_from(int fd, int nowild, char *packet, int len,
40 union mysockaddr *to, struct all_addr *source,
41 unsigned int iface)
42 {
43 struct msghdr msg;
44 struct iovec iov[1];
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;
56
57 iov[0].iov_base = packet;
58 iov[0].iov_len = len;
59
60 msg.msg_control = NULL;
61 msg.msg_controllen = 0;
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;
67
68 if (!nowild)
69 {
70 struct cmsghdr *cmptr;
71 msg.msg_control = &control_u;
72 msg.msg_controllen = sizeof(control_u);
73 cmptr = CMSG_FIRSTHDR(&msg);
74
75 if (to->sa.sa_family == AF_INET)
76 {
77 #if defined(IP_PKTINFO)
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;
84 #elif defined(IP_SENDSRCADDR)
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;
90 #endif
91 }
92
93 #ifdef HAVE_IPV6
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 }
103 #endif
104 }
105
106 retry:
107 if (sendmsg(fd, &msg, 0) == -1)
108 {
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;
119 }
120 }
121
122 static unsigned short search_servers(struct daemon *daemon, time_t now, struct all_addr **addrpp,
123 unsigned short qtype, char *qdomain, int *type, char **domain)
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
135 for (serv = daemon->servers; serv; serv=serv->next)
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;
141 if (serv->flags & SERV_NO_ADDR)
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;
150 #ifdef HAVE_IPV6
151 else
152 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
153 #endif
154 }
155 else if (!flags)
156 flags = F_NOERR;
157 }
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;
170 if (serv->flags & SERV_NO_ADDR)
171 flags = F_NXDOMAIN;
172 else if (serv->flags & SERV_LITERAL_ADDRESS)
173 {
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;
179 #ifdef HAVE_IPV6
180 else
181 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
182 #endif
183 }
184 else if (!flags)
185 flags = F_NOERR;
186 }
187 }
188 }
189
190 if (flags & ~(F_NOERR | F_NXDOMAIN)) /* flags set here means a literal found */
191 {
192 if (flags & F_QUERY)
193 log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0, NULL, 0);
194 else
195 log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0, NULL, 0);
196 }
197 else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.'))
198 flags = F_NXDOMAIN;
199
200 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon->mxnames))
201 flags = F_NOERR;
202
203 if (flags == F_NXDOMAIN || flags == F_NOERR)
204 log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0, NULL, 0);
205
206 return flags;
207 }
208
209 /* returns new last_server */
210 static 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)
213 {
214 struct frec *forward;
215 char *domain = NULL;
216 int forwardall = 0, type = 0;
217 struct all_addr *addrp = NULL;
218 unsigned short flags = 0;
219 unsigned short gotname = extract_request(header, (unsigned int)plen, daemon->namebuff, NULL);
220 struct server *start = NULL;
221 unsigned int crc = questions_crc(header,(unsigned int)plen);
222
223 /* may be recursion not speced or no servers available. */
224 if (!header->rd || !daemon->servers)
225 forward = NULL;
226 else if ((forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
227 {
228 /* retry on existing query, send to all available servers */
229 domain = forward->sentto->domain;
230 if (!(daemon->options & OPT_ORDER))
231 {
232 forwardall = 1;
233 daemon->last_server = NULL;
234 }
235 type = forward->sentto->flags & SERV_TYPE;
236 if (!(start = forward->sentto->next))
237 start = daemon->servers; /* at end of list, recycle */
238 header->id = htons(forward->new_id);
239 }
240 else
241 {
242 if (gotname)
243 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
244
245 if (!flags && !(forward = get_new_frec(now)))
246 /* table full - server failure. */
247 flags = F_NEG;
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
255 if (type != 0 || (daemon->options & OPT_ORDER))
256 start = daemon->servers;
257 else if (!(start = daemon->last_server))
258 {
259 start = daemon->servers;
260 forwardall = 1;
261 }
262
263 forward->source = *udpaddr;
264 forward->dest = *dst_addr;
265 forward->iface = dst_iface;
266 forward->new_id = get_id();
267 forward->fd = udpfd;
268 forward->orig_id = ntohs(header->id);
269 forward->crc = crc;
270 header->id = htons(forward->new_id);
271 }
272 }
273
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 {
280 struct server *firstsentto = start;
281 int forwarded = 0;
282
283 while (1)
284 {
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
289 if (type == (start->flags & SERV_TYPE) &&
290 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
291 !(start->flags & SERV_LITERAL_ADDRESS))
292 {
293 if (sendto(start->sfd->fd, (char *)header, plen, 0,
294 &start->addr.sa,
295 sa_len(&start->addr)) == -1)
296 {
297 if (retry_send())
298 continue;
299 }
300 else
301 {
302 if (!gotname)
303 strcpy(daemon->namebuff, "query");
304 if (start->addr.sa.sa_family == AF_INET)
305 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
306 (struct all_addr *)&start->addr.in.sin_addr, 0,
307 NULL, 0);
308 #ifdef HAVE_IPV6
309 else
310 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
311 (struct all_addr *)&start->addr.in6.sin6_addr, 0,
312 NULL, 0);
313 #endif
314 forwarded = 1;
315 forward->sentto = start;
316 if (!forwardall)
317 break;
318 }
319 }
320
321 if (!(start = start->next))
322 start = daemon->servers;
323
324 if (start == firstsentto)
325 break;
326 }
327
328 if (forwarded)
329 return;
330
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 */
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);
339
340 return;
341 }
342
343 static int process_reply(struct daemon *daemon, HEADER *header, time_t now,
344 union mysockaddr *serveraddr, unsigned int n)
345 {
346 unsigned char *pheader, *sizep;
347 unsigned int plen, munged = 0;
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
353 if ((pheader = find_pseudoheader(header, n, &plen, &sizep)))
354 {
355 unsigned short udpsz;
356 unsigned char *psave = sizep;
357
358 GETSHORT(udpsz, sizep);
359 if (udpsz > daemon->edns_pktsz)
360 PUTSHORT(daemon->edns_pktsz, psave);
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
379 if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN))
380 return n;
381
382 if (daemon->bogus_addr && header->rcode != NXDOMAIN &&
383 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
384 {
385 munged = 1;
386 header->rcode = NXDOMAIN;
387 header->aa = 0;
388 }
389 else
390 {
391 if (header->rcode == NXDOMAIN &&
392 extract_request(header, n, daemon->namebuff, NULL) &&
393 check_for_local_domain(daemon->namebuff, now, daemon->mxnames))
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 */
398 munged = 1;
399 header->aa = 1;
400 header->rcode = NOERROR;
401 }
402
403 extract_addresses(header, n, daemon->namebuff, now, daemon);
404 }
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
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);
420 }
421
422 /* sets new last_server */
423 void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
424 {
425 /* packet from peer server, extract data for cache, and send to
426 original requester */
427 struct frec *forward;
428 HEADER *header;
429 union mysockaddr serveraddr;
430 socklen_t addrlen = sizeof(serveraddr);
431 int n = recvfrom(sfd->fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
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
439
440 header = (HEADER *)daemon->packet;
441 forward = lookup_frec(ntohs(header->id));
442
443 if (n >= (int)sizeof(HEADER) && header->qr && forward)
444 {
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 {
448 struct server *last_server;
449 daemon->last_server = forward->sentto;
450 for (last_server = daemon->servers; last_server; last_server = last_server->next)
451 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
452 sockaddr_isequal(&last_server->addr, &serveraddr))
453 {
454 daemon->last_server = last_server;
455 break;
456 }
457 }
458
459 if ((n = process_reply(daemon, header, now, &serveraddr, (unsigned int)n)))
460 {
461 header->id = htons(forward->orig_id);
462 header->ra = 1; /* recursion if available */
463 send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, n,
464 &forward->source, &forward->dest, forward->iface);
465 forward->new_id = 0; /* cancel */
466 }
467 }
468 }
469
470 void receive_query(struct listener *listen, struct daemon *daemon, time_t now)
471 {
472 HEADER *header = (HEADER *)daemon->packet;
473 union mysockaddr source_addr;
474 unsigned short type;
475 struct iname *tmp;
476 struct all_addr dst_addr;
477 int m, n, if_index = 0;
478 struct iovec iov[1];
479 struct msghdr msg;
480 struct cmsghdr *cmptr;
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
494 iov[0].iov_base = daemon->packet;
495 iov[0].iov_len = daemon->edns_pktsz;
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
505 if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
506 return;
507
508 if (n < (int)sizeof(HEADER) || header->qr)
509 return;
510
511 source_addr.sa.sa_family = listen->family;
512 #ifdef HAVE_IPV6
513 if (listen->family == AF_INET6)
514 source_addr.in6.sin6_flowinfo = htonl(0);
515 #endif
516
517 if (!(daemon->options & OPT_NOWILD))
518 {
519 struct ifreq ifr;
520
521 if (msg.msg_controllen < sizeof(struct cmsghdr))
522 return;
523
524 #if defined(IP_PKTINFO)
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)
534 {
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;
540 }
541 #endif
542
543 #ifdef HAVE_IPV6
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 }
553 #endif
554
555 /* enforce available interface configuration */
556
557 if (if_index == 0)
558 return;
559
560 if (daemon->if_except || daemon->if_names)
561 {
562 #ifdef SIOCGIFNAME
563 ifr.ifr_ifindex = if_index;
564 if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
565 return;
566 #else
567 if (!if_indextoname(if_index, ifr.ifr_name))
568 return;
569 #endif
570 }
571
572 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
573 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
574 return;
575
576 if (daemon->if_names || daemon->if_addrs)
577 {
578 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
579 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
580 break;
581 if (!tmp)
582 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
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)
597 return;
598 }
599 }
600
601 if (extract_request(header, (unsigned int)n, daemon->namebuff, &type))
602 {
603 if (listen->family == AF_INET)
604 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
605 (struct all_addr *)&source_addr.in.sin_addr, type, NULL, 0);
606 #ifdef HAVE_IPV6
607 else
608 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
609 (struct all_addr *)&source_addr.in6.sin6_addr, type, NULL, 0);
610 #endif
611 }
612
613 m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, daemon, now);
614 if (m >= 1)
615 send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index);
616 else
617 forward_query(daemon, listen->fd, &source_addr, &dst_addr, if_index,
618 header, n, now);
619 }
620
621 static 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 {
637 if (retry_send())
638 goto retry;
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. */
650 char *tcp_request(struct daemon *daemon, int confd, time_t now)
651 {
652 int size = 0, m;
653 unsigned short qtype, gotname;
654 unsigned char c1, c2;
655 /* Max TCP packet + slop */
656 char *packet = malloc(65536 + MAXDNAME + RRFIXEDSZ);
657 HEADER *header;
658 struct server *last_server;
659
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
673 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
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)
681 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
682 (struct all_addr *)&peer_addr.in.sin_addr, qtype, NULL, 0);
683 #ifdef HAVE_IPV6
684 else
685 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
686 (struct all_addr *)&peer_addr.in6.sin6_addr, qtype, NULL, 0);
687 #endif
688 }
689 }
690
691 /* m > 0 if answered from cache */
692 m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, daemon, now);
693
694 if (m == 0)
695 {
696 unsigned short flags = 0;
697 struct all_addr *addrp = NULL;
698 int type = 0;
699 char *domain = NULL;
700
701 if (gotname)
702 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
703
704 if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server)
705 last_server = daemon->servers;
706 else
707 last_server = daemon->last_server;
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))
723 last_server = daemon->servers;
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)
764 strcpy(daemon->namebuff, "query");
765 if (last_server->addr.sa.sa_family == AF_INET)
766 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
767 (struct all_addr *)&last_server->addr.in.sin_addr, 0, NULL, 0);
768 #ifdef HAVE_IPV6
769 else
770 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
771 (struct all_addr *)&last_server->addr.in6.sin6_addr, 0, NULL, 0);
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. */
777 m = process_reply(daemon, header, now, &last_server->addr, (unsigned int)m);
778
779 break;
780 }
781 }
782
783 /* In case of local answer or no connections made. */
784 if (m == 0)
785 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
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
797 static 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
849 static 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
860 static struct frec *lookup_frec_by_sender(unsigned short id,
861 union mysockaddr *addr,
862 unsigned int crc)
863 {
864 struct frec *f;
865
866 for(f = frec_list; f; f = f->next)
867 if (f->new_id &&
868 f->orig_id == id &&
869 f->crc == crc &&
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 */
878 static 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