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