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