]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/forward.c
1 /* dnsmasq is Copyright (c) 2000 - 2003 Simon Kelley
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.
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.
13 /* Author's email: simon@thekelleys.org.uk */
17 static struct frec
*frec_list
;
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 static unsigned short get_id(void);
25 /* May be called more than once. */
26 void forward_init(int first
)
32 for (f
= frec_list
; f
; f
= f
->next
)
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 */
38 static void send_from(int fd
, int nowild
, char *packet
, int len
,
39 union mysockaddr
*to
, struct all_addr
*source
)
43 struct cmsghdr
*cmptr
;
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
))];
52 char control6
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
56 iov
[0].iov_base
= packet
;
61 msg
.msg_control
= NULL
;
62 msg
.msg_controllen
= 0;
66 msg
.msg_control
= &control_u
;
67 msg
.msg_controllen
= sizeof(control_u
);
71 msg
.msg_namelen
= sa_len(to
);
75 cmptr
= CMSG_FIRSTHDR(&msg
);
77 #if defined(IP_PKTINFO)
78 if (!nowild
&& to
->sa
.sa_family
== AF_INET
)
80 struct in_pktinfo
*pkt
= (struct in_pktinfo
*)CMSG_DATA(cmptr
);
82 pkt
->ipi_spec_dst
= source
->addr
.addr4
;
83 msg
.msg_controllen
= cmptr
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
84 cmptr
->cmsg_level
= SOL_IP
;
85 cmptr
->cmsg_type
= IP_PKTINFO
;
87 #elif defined(IP_SENDSRCADDR)
88 if (!nowild
&& to
->sa
.sa_family
== AF_INET
)
90 struct in_addr
*a
= (struct in_addr
*)CMSG_DATA(cmptr
);
91 *a
= source
->addr
.addr4
;
92 msg
.msg_controllen
= cmptr
->cmsg_len
= CMSG_LEN(sizeof(struct in_addr
));
93 cmptr
->cmsg_level
= IPPROTO_IP
;
94 cmptr
->cmsg_type
= IP_SENDSRCADDR
;
99 if (!nowild
&& to
->sa
.sa_family
== AF_INET6
)
101 struct in6_pktinfo
*pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmptr
);
102 pkt
->ipi6_ifindex
= 0;
103 pkt
->ipi6_addr
= source
->addr
.addr6
;
104 msg
.msg_controllen
= cmptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
105 cmptr
->cmsg_type
= IPV6_PKTINFO
;
106 cmptr
->cmsg_level
= IPV6_LEVEL
;
110 sendmsg(fd
, &msg
, 0);
114 /* returns new last_server */
115 static struct server
*forward_query(int udpfd
, union mysockaddr
*udpaddr
,
116 struct all_addr
*dst_addr
, HEADER
*header
,
117 int plen
, unsigned int options
, char *dnamebuff
,
118 struct server
*servers
, struct server
*last_server
,
119 time_t now
, unsigned long local_ttl
)
121 struct frec
*forward
;
125 struct all_addr
*addrp
= NULL
;
126 unsigned short flags
= 0;
127 unsigned short gotname
= extract_request(header
, (unsigned int)plen
, dnamebuff
);
129 /* may be recursion not speced or no servers available. */
130 if (!header
->rd
|| !servers
)
132 else if ((forward
= lookup_frec_by_sender(ntohs(header
->id
), udpaddr
)))
134 /* retry on existing query, send to next server */
135 domain
= forward
->sentto
->domain
;
136 type
= forward
->sentto
->flags
& SERV_TYPE
;
137 if (!(forward
->sentto
= forward
->sentto
->next
))
138 forward
->sentto
= servers
; /* at end of list, recycle */
139 header
->id
= htons(forward
->new_id
);
145 /* If the query ends in the domain in one of our servers, set
146 domain to point to that name. We find the largest match to allow both
147 domain.org and sub.domain.org to exist. */
149 unsigned int namelen
= strlen(dnamebuff
);
150 unsigned int matchlen
= 0;
152 for (serv
=servers
; serv
; serv
=serv
->next
)
153 /* domain matches take priority over NODOTS matches */
154 if ((serv
->flags
& SERV_FOR_NODOTS
) && type
!= SERV_HAS_DOMAIN
&& !strchr(dnamebuff
, '.'))
156 if (serv
->flags
& SERV_LITERAL_ADDRESS
)
158 /* flags gets set if server is in fact an answer */
159 unsigned short sflag
= serv
->addr
.sa
.sa_family
== AF_INET
? F_IPV4
: F_IPV6
;
160 if (sflag
& gotname
) /* only OK if addrfamily == query */
162 type
= SERV_FOR_NODOTS
;
164 if (serv
->addr
.sa
.sa_family
== AF_INET
)
165 addrp
= (struct all_addr
*)&serv
->addr
.in
.sin_addr
;
168 addrp
= (struct all_addr
*)&serv
->addr
.in6
.sin6_addr
;
175 else if (serv
->flags
& SERV_HAS_DOMAIN
)
177 unsigned int domainlen
= strlen(serv
->domain
);
178 if (namelen
>= domainlen
&&
179 hostname_isequal(dnamebuff
+ namelen
- domainlen
, serv
->domain
) &&
180 domainlen
> matchlen
)
182 if (serv
->flags
& SERV_LITERAL_ADDRESS
)
183 { /* flags gets set if server is in fact an answer */
184 unsigned short sflag
= serv
->addr
.sa
.sa_family
== AF_INET
? F_IPV4
: F_IPV6
;
185 if ((sflag
| F_QUERY
) & gotname
) /* only OK if addrfamily == query */
187 type
= SERV_HAS_DOMAIN
;
189 domain
= serv
->domain
;
190 matchlen
= domainlen
;
191 if (serv
->addr
.sa
.sa_family
== AF_INET
)
192 addrp
= (struct all_addr
*)&serv
->addr
.in
.sin_addr
;
195 addrp
= (struct all_addr
*)&serv
->addr
.in6
.sin6_addr
;
201 flags
= 0; /* may be better match from previous literal */
202 domain
= serv
->domain
;
203 matchlen
= domainlen
;
204 type
= SERV_HAS_DOMAIN
;
210 if (flags
) /* flags set here means a literal found */
213 log_query(F_CONFIG
| F_FORWARD
| F_NEG
, dnamebuff
, NULL
);
215 log_query(F_CONFIG
| F_FORWARD
| flags
, dnamebuff
, addrp
);
219 /* we may by policy not forward names without a domain part */
220 if (gotname
&& (options
& OPT_NODOTS_LOCAL
) && !strchr(dnamebuff
, '.'))
222 else if (!(forward
= get_new_frec(now
)))
223 /* table full - server failure. */
229 /* In strict_order mode, or when using domain specific servers
230 always try servers in the order specified in resolv.conf,
231 otherwise, use the one last known to work. */
233 if (type
!= 0 || (options
& OPT_ORDER
))
234 forward
->sentto
= servers
;
236 forward
->sentto
= last_server
;
238 forward
->source
= *udpaddr
;
239 forward
->dest
= *dst_addr
;
240 forward
->new_id
= get_id();
242 forward
->orig_id
= ntohs(header
->id
);
243 header
->id
= htons(forward
->new_id
);
247 /* check for send errors here (no route to host)
248 if we fail to send to all nameservers, send back an error
249 packet straight away (helps modem users when offline) */
251 if (!flags
&& forward
)
253 struct server
*firstsentto
= forward
->sentto
;
259 if (forward
->sentto
->addr
.sa
.sa_family
== AF_INET
)
261 logflags
= F_SERVER
| F_IPV4
| F_FORWARD
;
262 addrp
= (struct all_addr
*)&forward
->sentto
->addr
.in
.sin_addr
;
267 logflags
= F_SERVER
| F_IPV6
| F_FORWARD
;
268 addrp
= (struct all_addr
*)&forward
->sentto
->addr
.in6
.sin6_addr
;
271 /* only send to servers dealing with our domain.
272 domain may be NULL, in which case server->domain
273 must be NULL also. */
275 if (type
== (forward
->sentto
->flags
& SERV_TYPE
) &&
276 (type
!= SERV_HAS_DOMAIN
|| hostname_isequal(domain
, forward
->sentto
->domain
)))
278 if (forward
->sentto
->flags
& SERV_NO_ADDR
)
279 flags
= F_NOERR
; /* NULL servers are OK. */
280 else if (!(forward
->sentto
->flags
& SERV_LITERAL_ADDRESS
) &&
281 sendto(forward
->sentto
->sfd
->fd
, (char *)header
, plen
, 0,
282 &forward
->sentto
->addr
.sa
,
283 sa_len(&forward
->sentto
->addr
)) != -1)
285 log_query(logflags
, gotname
? dnamebuff
: "query", addrp
);
286 /* for no-domain, don't update last_server */
287 return domain
? last_server
: (forward
->sentto
->next
? forward
->sentto
->next
: servers
);
291 if (!(forward
->sentto
= forward
->sentto
->next
))
292 forward
->sentto
= servers
;
294 /* check if we tried all without success */
295 if (forward
->sentto
== firstsentto
)
299 /* could not send on, prepare to return */
300 header
->id
= htons(forward
->orig_id
);
301 forward
->new_id
= 0; /* cancel */
304 /* could not send on, return empty answer or address if known for whole domain */
305 plen
= setup_reply(header
, (unsigned int)plen
, addrp
, flags
, local_ttl
);
306 send_from(udpfd
, options
& OPT_NOWILD
, (char *)header
, plen
, udpaddr
, dst_addr
);
308 if (flags
& (F_NOERR
| F_NXDOMAIN
))
309 log_query(F_CONFIG
| F_FORWARD
| F_NEG
| gotname
| (flags
& F_NXDOMAIN
), dnamebuff
, NULL
);
314 /* returns new last_server */
315 struct server
*reply_query(int fd
, int options
, char *packet
, time_t now
,
316 char *dnamebuff
, struct server
*last_server
,
317 struct bogus_addr
*bogus_nxdomain
, struct doctor
*doctors
)
319 /* packet from peer server, extract data for cache, and send to
320 original requester */
321 struct frec
*forward
;
323 int n
= recv(fd
, packet
, PACKETSZ
, 0);
325 header
= (HEADER
*)packet
;
326 if (n
>= (int)sizeof(HEADER
) && header
->qr
)
328 if ((forward
= lookup_frec(ntohs(header
->id
))))
330 if (header
->rcode
== NOERROR
|| header
->rcode
== NXDOMAIN
)
332 if (!forward
->sentto
->domain
)
333 last_server
= forward
->sentto
; /* known good */
334 if (header
->opcode
== QUERY
)
336 if (!(bogus_nxdomain
&&
337 header
->rcode
== NOERROR
&&
338 check_for_bogus_wildcard(header
, (unsigned int)n
, dnamebuff
, bogus_nxdomain
, now
)))
340 if (header
->rcode
== NOERROR
&& ntohs(header
->ancount
) != 0)
341 extract_addresses(header
, (unsigned int)n
, dnamebuff
, now
, doctors
);
342 else if (!(options
& OPT_NO_NEG
))
343 extract_neg_addrs(header
, (unsigned int)n
, dnamebuff
, now
);
347 header
->id
= htons(forward
->orig_id
);
348 /* There's no point returning an upstream reply marked as truncated,
349 since that will prod the resolver into moving to TCP - which we
351 header
->tc
= 0; /* goodbye truncate */
352 send_from(forward
->fd
, options
& OPT_NOWILD
, packet
, n
, &forward
->source
, &forward
->dest
);
353 forward
->new_id
= 0; /* cancel */
360 struct server
*receive_query(struct listener
*listen
, char *packet
, char *mxname
,
361 char *mxtarget
, unsigned int options
, time_t now
,
362 unsigned long local_ttl
, char *namebuff
,
363 struct iname
*names
, struct iname
*addrs
, struct iname
*except
,
364 struct server
*last_server
, struct server
*servers
)
366 HEADER
*header
= (HEADER
*)packet
;
367 union mysockaddr source_addr
;
369 struct all_addr dst_addr
;
370 int m
, n
, if_index
= 0;
373 struct cmsghdr
*cmptr
;
375 struct cmsghdr align
; /* this ensures alignment */
377 char control6
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
379 #if defined(IP_PKTINFO)
380 char control
[CMSG_SPACE(sizeof(struct in_pktinfo
))];
381 #elif defined(IP_RECVDSTADDR)
382 char control
[CMSG_SPACE(sizeof(struct in_addr
)) +
383 CMSG_SPACE(sizeof(struct sockaddr_dl
))];
387 iov
[0].iov_base
= packet
;
388 iov
[0].iov_len
= PACKETSZ
;
390 msg
.msg_control
= control_u
.control
;
391 msg
.msg_controllen
= sizeof(control_u
);
393 msg
.msg_name
= &source_addr
;
394 msg
.msg_namelen
= sizeof(source_addr
);
398 n
= recvmsg(listen
->fd
, &msg
, 0);
400 source_addr
.sa
.sa_family
= listen
->family
;
402 if (listen
->family
== AF_INET6
)
403 source_addr
.in6
.sin6_flowinfo
= htonl(0);
406 if (!(options
& OPT_NOWILD
) && msg
.msg_controllen
< sizeof(struct cmsghdr
))
409 #if defined(IP_PKTINFO)
410 if (!(options
& OPT_NOWILD
) && listen
->family
== AF_INET
)
411 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
412 if (cmptr
->cmsg_level
== SOL_IP
&& cmptr
->cmsg_type
== IP_PKTINFO
)
414 dst_addr
.addr
.addr4
= ((struct in_pktinfo
*)CMSG_DATA(cmptr
))->ipi_spec_dst
;
415 if_index
= ((struct in_pktinfo
*)CMSG_DATA(cmptr
))->ipi_ifindex
;
417 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
418 if (!(options
& OPT_NOWILD
) && listen
->family
== AF_INET
)
420 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
421 if (cmptr
->cmsg_level
== IPPROTO_IP
&& cmptr
->cmsg_type
== IP_RECVDSTADDR
)
422 dst_addr
.addr
.addr4
= *((struct in_addr
*)CMSG_DATA(cmptr
));
423 else if (cmptr
->cmsg_level
== IPPROTO_IP
&& cmptr
->cmsg_type
== IP_RECVIF
)
424 if_index
= ((struct sockaddr_dl
*)CMSG_DATA(cmptr
))->sdl_index
;
429 if (!(options
& OPT_NOWILD
) && listen
->family
== AF_INET6
)
431 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
432 if (cmptr
->cmsg_level
== IPV6_LEVEL
&& cmptr
->cmsg_type
== IPV6_PKTINFO
)
434 dst_addr
.addr
.addr6
= ((struct in6_pktinfo
*)CMSG_DATA(cmptr
))->ipi6_addr
;
435 if_index
=((struct in6_pktinfo
*)CMSG_DATA(cmptr
))->ipi6_ifindex
;
440 if (n
< (int)sizeof(HEADER
) || header
->qr
)
443 /* enforce available interface configuration */
444 if (!(options
& OPT_NOWILD
))
454 ifr
.ifr_ifindex
= if_index
;
455 if (ioctl(listen
->fd
, SIOCGIFNAME
, &ifr
) == -1)
458 if (!if_indextoname(if_index
, ifr
.ifr_name
))
463 for (tmp
= except
; tmp
; tmp
= tmp
->next
)
464 if (tmp
->name
&& (strcmp(tmp
->name
, ifr
.ifr_name
) == 0))
469 for (tmp
= names
; tmp
; tmp
= tmp
->next
)
470 if (tmp
->name
&& (strcmp(tmp
->name
, ifr
.ifr_name
) == 0))
473 for (tmp
= addrs
; tmp
; tmp
= tmp
->next
)
474 if (tmp
->addr
.sa
.sa_family
== listen
->family
)
476 if (tmp
->addr
.sa
.sa_family
== AF_INET
&&
477 tmp
->addr
.in
.sin_addr
.s_addr
== dst_addr
.addr
.addr4
.s_addr
)
480 else if (tmp
->addr
.sa
.sa_family
== AF_INET6
&&
481 memcmp(&tmp
->addr
.in6
.sin6_addr
,
482 &dst_addr
.addr
.addr6
,
483 sizeof(struct in6_addr
)) == 0)
492 if (extract_request(header
, (unsigned int)n
, namebuff
))
494 if (listen
->family
== AF_INET
)
495 log_query(F_QUERY
| F_IPV4
| F_FORWARD
, namebuff
,
496 (struct all_addr
*)&source_addr
.in
.sin_addr
);
499 log_query(F_QUERY
| F_IPV6
| F_FORWARD
, namebuff
,
500 (struct all_addr
*)&source_addr
.in6
.sin6_addr
);
504 m
= answer_request (header
, ((char *) header
) + PACKETSZ
, (unsigned int)n
,
505 mxname
, mxtarget
, options
, now
, local_ttl
, namebuff
);
507 send_from(listen
->fd
, options
& OPT_NOWILD
, (char *)header
, m
, &source_addr
, &dst_addr
);
509 last_server
= forward_query(listen
->fd
, &source_addr
, &dst_addr
,
510 header
, n
, options
, namebuff
, servers
,
511 last_server
, now
, local_ttl
);
515 static struct frec
*get_new_frec(time_t now
)
517 struct frec
*f
= frec_list
, *oldest
= NULL
;
518 time_t oldtime
= now
;
520 static time_t warntime
= 0;
530 if (difftime(f
->time
, oldtime
) <= 0)
540 /* can't find empty one, use oldest if there is one
541 and it's older than timeout */
542 if (oldest
&& difftime(now
, oldtime
) > TIMEOUT
)
549 { /* limit logging rate so syslog isn't DOSed either */
550 if (!warntime
|| difftime(now
, warntime
) > LOGRATE
)
553 syslog(LOG_WARNING
, "forwarding table overflow: check for server loops.");
558 if ((f
= (struct frec
*)malloc(sizeof(struct frec
))))
564 return f
; /* OK if malloc fails and this is NULL */
567 static struct frec
*lookup_frec(unsigned short id
)
571 for(f
= frec_list
; f
; f
= f
->next
)
578 static struct frec
*lookup_frec_by_sender(unsigned short id
,
579 union mysockaddr
*addr
)
583 for(f
= frec_list
; f
; f
= f
->next
)
586 sockaddr_isequal(&f
->source
, addr
))
593 /* return unique random ids between 1 and 65535 */
594 static unsigned short get_id(void)
596 unsigned short ret
= 0;
602 /* scrap ids already in use */
603 if ((ret
!= 0) && lookup_frec(ret
))