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