Imported Upstream version 878.70.2
[platform/upstream/mdnsresponder.git] / mDNSMacOSX / DNSProxySupport.c
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include "mDNSEmbeddedAPI.h"
19 #include "mDNSMacOSX.h"
20
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/event.h>
24 #include <netinet/tcp.h>
25
26 mDNSexport mDNS mDNSStorage;
27
28 #define ValidSocket(s) ((s) >= 0)
29
30 // Global to store the 4 DNS Proxy Listeners (UDPv4/6, TCPv4/6)
31 static int dp_listener[4];
32
33 #define NUM_PROXY_TCP_CONNS 100
34
35 typedef struct
36 {
37     TCPSocket   sock;
38     DNSMessage  *reply;
39     mDNSu16     replyLen;
40     mDNSu32     nread;
41 } ProxyTCPInfo_t;
42
43 // returns -1 for failures including the other end closing the socket
44 // returns 0 if successful in reading data, but still not read the data fully
45 // returns 1 if successful in reading all the data
46 mDNSlocal int ProxyTCPRead(ProxyTCPInfo_t *tcpInfo)
47 {
48     long n;
49     mDNSBool closed; 
50
51     if (tcpInfo->nread < 2)         // First read the two-byte length preceeding the DNS message
52     {
53         mDNSu8 *lenptr = (mDNSu8 *)&tcpInfo->replyLen;
54         n = mDNSPlatformReadTCP(&tcpInfo->sock, lenptr + tcpInfo->nread, 2 - tcpInfo->nread, &closed);
55         if (n < 0 || closed)
56         {
57             LogMsg("ProxyTCPRead: attempt to read message length failed");
58             return -1;
59         }
60
61         tcpInfo->nread += n;
62         if (tcpInfo->nread < 2)
63         {
64             LogMsg("ProxyTCPRead: nread %d, n %d", tcpInfo->nread, n);
65             return 0;
66         }
67
68         tcpInfo->replyLen = (mDNSu16)((mDNSu16)lenptr[0] << 8 | lenptr[1]);
69         if (tcpInfo->replyLen < sizeof(DNSMessageHeader))
70         {
71             LogMsg("ProxyTCPRead: Message length too short (%d bytes)", tcpInfo->replyLen);
72             return -1;
73         }
74
75         tcpInfo->reply = mallocL("ProxyTCPInfo", tcpInfo->replyLen);
76         if (!tcpInfo->reply)
77         {
78             LogMsg("ProxyTCPRead: Memory failure");
79             return -1;
80         }
81     }
82
83     n = mDNSPlatformReadTCP(&tcpInfo->sock, ((char *)tcpInfo->reply) + (tcpInfo->nread - 2), tcpInfo->replyLen - (tcpInfo->nread - 2), &closed);
84
85     if (n < 0 || closed)
86     {
87         LogMsg("ProxyTCPRead: read failure n %d, closed %d", n, closed);
88         return -1;
89     }
90     tcpInfo->nread += n;
91     if ((tcpInfo->nread - 2) != tcpInfo->replyLen)
92         return 0;
93     else 
94         return 1;
95 }
96
97 mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context, __unused mDNSBool encounteredEOF)
98 {
99     int ret;
100     struct sockaddr_storage from;
101     struct sockaddr_storage to;
102     mDNSAddr senderAddr, destAddr;
103     mDNSIPPort senderPort;
104     ProxyTCPInfo_t *ti = (ProxyTCPInfo_t *)context;
105     TCPSocket *sock = &ti->sock;
106     KQSocketSet *kq = &sock->ss;
107     struct tcp_info tcp_if;
108     socklen_t size = sizeof(tcp_if);
109     int32_t intf_id = 0;
110
111     (void) filter;
112
113     ret = ProxyTCPRead(ti);
114     if (ret == -1)
115     {
116         mDNSPlatformDisposeProxyContext(ti);
117         return; 
118     }
119     else if (!ret)
120     {
121         debugf("ProxyTCPReceive: Not yet read completely Actual length %d, Read length %d", ti->replyLen, ti->nread);
122         return;
123     }
124     // We read all the data and hence not interested in read events anymore
125     KQueueSet(s1, EV_DELETE, EVFILT_READ, sock->kqEntry);
126
127     mDNSPlatformMemZero(&to, sizeof(to));
128     mDNSPlatformMemZero(&from, sizeof(from));
129     socklen_t len = sizeof(to);
130     ret = getsockname(s1, (struct sockaddr*) &to, &len);
131     if (ret < 0)
132     {
133         LogMsg("ProxyTCPReceive: getsockname(fd=%d) errno %d", s1, errno);
134         mDNSPlatformDisposeProxyContext(ti);
135         return;
136     }
137     ret = getpeername(s1, (struct sockaddr*) &from, &len);
138     if (ret < 0)
139     {
140         LogMsg("ProxyTCPReceive: getpeername(fd=%d) errno %d", s1, errno);
141         mDNSPlatformDisposeProxyContext(ti);
142         return;
143     }
144     if (getsockopt(s1, IPPROTO_TCP, TCP_INFO, &tcp_if, &size) != 0)
145     {
146         LogMsg("ProxyTCPReceive: getsockopt for TCP_INFO failed (fd=%d) errno %d", s1, errno);
147         return;
148     }
149     intf_id = tcp_if.tcpi_last_outif;
150
151     if (from.ss_family == AF_INET)
152     {
153         struct sockaddr_in *s = (struct sockaddr_in*)&from;
154
155         senderAddr.type = mDNSAddrType_IPv4;
156         senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
157         senderPort.NotAnInteger = s->sin_port;
158
159         s = (struct sockaddr_in *)&to;
160         destAddr.type = mDNSAddrType_IPv4;
161         destAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
162
163         LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d",
164                 ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id);
165     }
166     else if (from.ss_family == AF_INET6)
167     {
168         struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
169         senderAddr.type = mDNSAddrType_IPv6;
170         senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
171         senderPort.NotAnInteger = sin6->sin6_port;
172
173         sin6 = (struct sockaddr_in6 *)&to;
174         destAddr.type = mDNSAddrType_IPv6;
175         destAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
176
177         LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d",
178                 ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id);
179     }
180     else
181     {
182         LogMsg("ProxyTCPReceive from is unknown address family %d", from.ss_family);
183         mDNSPlatformDisposeProxyContext(ti);
184         return;
185     }
186
187     // We pass sock for the TCPSocket and the "ti" for context as that's what we want to free at the end.
188     // In the UDP case, there is just a single socket and nothing to free. Hence, the context (last argument)
189     // would be NULL.
190     kq->m->p->TCPProxyCallback(sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr,
191         UnicastDNSPort, (mDNSInterfaceID)(uintptr_t)intf_id, ti);
192 }
193
194 mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context, __unused mDNSBool encounteredEOF)
195 {
196     int newfd;
197     struct sockaddr_storage ss;
198     socklen_t sslen = sizeof(ss);
199     const int on = 1;
200     KQSocketSet *listenSet = (KQSocketSet *)context;
201
202     (void) filter;
203
204     while ((newfd = accept(s1, (struct sockaddr *)&ss, &sslen)) != -1)
205     {
206         int err;
207         int *s;
208         KQueueEntry *k;
209         KQSocketSet *kq;
210
211         // Even though we just need a single KQueueEntry, for simplicity we re-use
212         // the KQSocketSet
213         ProxyTCPInfo_t *ti = mallocL("ProxyTCPContext", sizeof(ProxyTCPInfo_t));
214         if (!ti)
215         {
216             LogMsg("ProxyTCPAccept: cannot allocate TCPSocket");
217             close(newfd);
218             return;
219         }
220         mDNSPlatformMemZero(ti, sizeof(ProxyTCPInfo_t));
221         
222         TCPSocket *sock = &ti->sock;
223
224         kq = &sock->ss;
225         kq->sktv4 = -1;
226         kq->sktv6 = -1;
227         kq->m = listenSet->m;
228
229         fcntl(newfd, F_SETFL, fcntl(newfd, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
230         if (ss.ss_family == AF_INET)
231         {
232             s =  &kq->sktv4;
233             k =  &kq->kqsv4;
234             // Receive interface identifiers
235             err = setsockopt(newfd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
236             if (err)
237             {
238                 LogMsg("ProxyTCPAccept: IP_RECVIF %d errno %d (%s)", newfd, errno, strerror(errno));
239                 mDNSPlatformDisposeProxyContext(ti);
240                 close(newfd);
241                 return;
242             }
243         }
244         else
245         {
246             s =  &kq->sktv6;
247             k =  &kq->kqsv6;
248             // We want to receive destination addresses and receive interface identifiers
249             err = setsockopt(newfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
250             if (err)
251             {
252                 LogMsg("ProxyTCPAccept: IP_RECVPKTINFO %d errno %d (%s)", newfd, errno, strerror(errno));
253                 mDNSPlatformDisposeProxyContext(ti);
254                 close(newfd);
255                 return;
256             }
257         }
258         *s = newfd;
259         // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address
260         // from which we can infer the destination address family. Hence we need to remember that here.
261         // Instead of remembering the address family, we remember the right fd.
262         sock->fd = newfd;
263         sock->kqEntry = k;
264         k->KQcallback = ProxyTCPSocketCallBack;
265         k->KQcontext  = ti;
266         k->KQtask     = "TCP Proxy packet reception";
267 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
268         k->readSource = mDNSNULL;
269         k->writeSource = mDNSNULL;
270         k->fdClosed = mDNSfalse;
271 #endif
272         KQueueSet(*s, EV_ADD, EVFILT_READ, k);
273     }
274 }
275
276 mDNSlocal mStatus SetupUDPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
277 {
278     int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
279     KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
280     const int on = 1;
281     mStatus err = mStatus_NoError;
282
283     cp->m = &mDNSStorage;
284     cp->closeFlag = mDNSNULL;
285
286     // set default traffic class
287     // setTrafficClass(skt, mDNSfalse);
288     (void) useBackgroundTrafficClass;
289
290     if (sa_family == AF_INET)
291     {
292         err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
293         if (err < 0)
294         {
295             LogMsg("SetupUDPProxySocket: IP_RECVDSTADDR %d errno %d (%s)", skt, errno, strerror(errno));
296             return err;
297         }
298
299         // We want to receive interface identifiers
300         err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
301         if (err < 0)
302         {
303             LogMsg("SetupUDPProxySocket: IP_RECVIF %d errno %d (%s)", skt, errno, strerror(errno));
304             return err;
305         }
306     }
307     else if (sa_family == AF_INET6)
308     {
309         // We want to receive destination addresses and receive interface identifiers
310         err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
311         if (err < 0)
312         {
313             LogMsg("SetupUDPProxySocket: IPV6_RECVPKTINFO %d errno %d (%s)", skt, errno, strerror(errno));
314             return err;
315         }
316
317         // We want to receive packet hop count value so we can check it
318         err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
319         if (err < 0)
320         {
321             LogMsg("SetupUDPProxySocket: IPV6_RECVHOPLIMIT %d errno %d (%s)", skt, errno, strerror(errno));
322             return err;
323         }
324     }
325     else
326     {
327         LogMsg("SetupUDPProxySocket: wrong family %d", sa_family);
328         return -1;
329     }
330
331     if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) < 0)
332     {
333         LogMsg("SetupUDPProxySocket: fnctl failed %d", errno);
334         return -1;
335     }
336
337     *s = skt;
338     //k->KQcallback = ProxyUDPSocketCallBack;
339     k->KQcallback  = myKQSocketCallBack;
340     k->KQcontext   = cp;
341     k->KQtask      = "UDP Proxy packet reception";
342 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
343     k->readSource  = mDNSNULL;
344     k->writeSource = mDNSNULL;
345     k->fdClosed    = mDNSfalse;
346 #endif
347
348     KQueueSet(*s, EV_ADD, EVFILT_READ, k);
349
350     return(err);
351 }
352
353 mDNSlocal mStatus SetupTCPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
354 {
355     int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
356     KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
357     mStatus err;
358
359     cp->m = &mDNSStorage;
360     // XXX may not be used by the TCP codepath 
361     cp->closeFlag = mDNSNULL;
362
363     // for TCP sockets, the traffic class is set once and not changed
364     // setTrafficClass(skt, useBackgroundTrafficClass);
365     (void) useBackgroundTrafficClass;
366
367     // All the socket setup has already been done 
368     err = listen(skt, NUM_PROXY_TCP_CONNS);
369     if (err)
370     {
371         LogMsg("SetupTCPProxySocket: listen %d errno %d (%s)", skt, errno, strerror(errno));
372         return err;
373     }
374     fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
375     
376     *s = skt;
377     k->KQcallback  = ProxyTCPAccept;
378     k->KQcontext   = cp;
379     k->KQtask      = "TCP Accept";
380 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
381     k->readSource  = mDNSNULL;
382     k->writeSource = mDNSNULL;
383     k->fdClosed    = mDNSfalse;
384 #endif
385     KQueueSet(*s, EV_ADD, EVFILT_READ, k);
386     return mStatus_NoError;
387 }
388
389 mDNSlocal void BindDPSocket(int fd, int sa_family)
390 {
391     int err;
392     const int on = 1;
393
394     if (sa_family == AF_INET)
395     {
396         struct sockaddr_in addr;
397
398         err = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
399         if (err < 0) 
400             LogMsg("BindDPSocket: setsockopt SO_REUSEPORT failed for IPv4 %d errno %d (%s)", fd, errno, strerror(errno));
401
402         memset(&addr, 0, sizeof(addr));
403         addr.sin_family = AF_INET;
404         addr.sin_port = htons(53);
405
406         err = bind(fd, (struct sockaddr*) &addr, sizeof(addr));
407         if (err)
408         {
409             LogMsg("BindDPSocket: bind %d errno %d (%s)", fd, errno, strerror(errno));
410             return;
411         }
412     }
413     else
414     {
415         struct sockaddr_in6 addr6;
416
417         // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
418         // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
419         err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
420         if (err < 0)
421         {
422             LogMsg("DPFBindSocket: setsockopt IPV6_V6ONLY %d errno %d (%s)", fd, errno, strerror(errno));
423             return;
424         }
425         err = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
426         if (err < 0)
427             LogMsg("BindDPSocket: setsockopt SO_REUSEPORT failed for V6 %d errno %d (%s)", fd, errno, strerror(errno));
428
429         memset(&addr6, 0, sizeof(addr6));
430         addr6.sin6_family = AF_INET6;
431         addr6.sin6_port = htons(53);
432
433         err = bind(fd, (struct sockaddr*) &addr6, sizeof(addr6));
434         if (err)
435         {
436             LogMsg("BindDPSocket: bind6 %d errno %d (%s)", fd, errno, strerror(errno));
437             return;
438         }
439     }
440 }
441
442 // Setup DNS Proxy Skts in main kevent loop and set the skt options
443 mDNSlocal void SetupDNSProxySkts(int fd[4])
444 {
445     mDNS *const m = &mDNSStorage;
446         int i;
447     mStatus err;
448     KQSocketSet *udpSS;
449     KQSocketSet *tcpSS;
450
451     udpSS       = &m->p->UDPProxy.ss;
452     tcpSS       = &m->p->TCPProxy.ss;
453     udpSS->port = UnicastDNSPort;
454     tcpSS->port = UnicastDNSPort;
455
456     LogMsg("SetupDNSProxySkts: %d, %d, %d, %d", fd[0], fd[1], fd[2], fd[3]);
457
458     // myKQSocketCallBack checks for proxy and calls the m->p->ProxyCallback instead of mDNSCoreReceive
459     udpSS->proxy = mDNStrue;
460     err = SetupUDPProxySocket(fd[0], udpSS, AF_INET, mDNSfalse);
461     if (err)
462         LogMsg("SetupDNSProxySkts: ERROR!! UDPv4 Socket");
463
464     err = SetupUDPProxySocket(fd[1], udpSS, AF_INET6, mDNSfalse);
465     if (err)
466         LogMsg("SetupDNSProxySkts: ERROR!! UDPv6 Socket");
467
468     err = SetupTCPProxySocket(fd[2], tcpSS, AF_INET, mDNSfalse);
469     if (err)
470         LogMsg("SetupDNSProxySkts: ERROR!! TCPv4 Socket");
471
472     err = SetupTCPProxySocket(fd[3], tcpSS, AF_INET6, mDNSfalse);
473     if (err)
474         LogMsg("SetupDNSProxySkts: ERROR!! TCPv6 Socket");
475
476     for (i = 0; i < 4; i++)
477         dp_listener[i] = fd[i];   
478
479
480 // Create and bind the DNS Proxy Skts for use
481 mDNSexport void mDNSPlatformInitDNSProxySkts(ProxyCallback UDPCallback, ProxyCallback TCPCallback)
482 {
483     int dpskt[4];
484     
485     dpskt[0] = socket(AF_INET,  SOCK_DGRAM,  IPPROTO_UDP);
486     dpskt[1] = socket(AF_INET6, SOCK_DGRAM,  IPPROTO_UDP);
487     dpskt[2] = socket(AF_INET,  SOCK_STREAM, IPPROTO_TCP);
488     dpskt[3] = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
489
490     // Close all DNS Proxy skts in case any of them are invalid
491     if (!ValidSocket(dpskt[0]) || !ValidSocket(dpskt[1]) ||
492         !ValidSocket(dpskt[2]) || !ValidSocket(dpskt[3]))
493     {   
494         if (ValidSocket(dpskt[0]))
495             close(dpskt[0]);
496         if (ValidSocket(dpskt[1]))
497             close(dpskt[1]);
498         if (ValidSocket(dpskt[2]))
499             close(dpskt[2]);
500         if (ValidSocket(dpskt[3]))
501             close(dpskt[3]);
502     }
503
504     BindDPSocket(dpskt[0], AF_INET);
505     BindDPSocket(dpskt[1], AF_INET6);
506     BindDPSocket(dpskt[2], AF_INET);
507     BindDPSocket(dpskt[3], AF_INET6);
508
509     LogInfo("mDNSPlatformInitDNSProxySkts: Opened Listener Sockets for DNS Proxy : %d, %d, %d, %d", 
510              dpskt[0], dpskt[1], dpskt[2], dpskt[3]);
511
512     mDNSStorage.p->UDPProxyCallback = UDPCallback;
513     mDNSStorage.p->TCPProxyCallback = TCPCallback;
514
515     SetupDNSProxySkts(dpskt);
516 }
517
518 mDNSexport void mDNSPlatformCloseDNSProxySkts(mDNS *const m)
519 {
520     (void) m;
521     int i;
522     for (i = 0; i < 4; i++)
523         close(dp_listener[i]);
524     LogInfo("mDNSPlatformCloseDNSProxySkts: Closing DNS Proxy Listener Sockets");  
525 }
526
527 mDNSexport void mDNSPlatformDisposeProxyContext(void *context)
528 {
529     ProxyTCPInfo_t *ti;
530     TCPSocket *sock;
531     KQSocketSet *kq;
532
533     if (!context)
534         return;
535
536     ti = (ProxyTCPInfo_t *)context;
537     sock = &ti->sock;
538
539     kq = &sock->ss;
540     if (kq->sktv4 != -1)
541     {
542         shutdown(kq->sktv4, 2);
543         mDNSPlatformCloseFD(&kq->kqsv4, kq->sktv4);
544     }
545     if (kq->sktv6 != -1)
546     {
547         shutdown(kq->sktv6, 2);
548         mDNSPlatformCloseFD(&kq->kqsv6, kq->sktv6);
549     }
550     if (kq->closeFlag)
551         *kq->closeFlag = 1;
552
553     if (ti->reply)
554         freeL("ProxyTCPInfoLen", ti->reply);
555     freeL("ProxyTCPContext", ti);
556 }
557