source: rtems-libbsd/mDNSResponder/mDNSMacOSX/DNSProxySupport.c @ f761b29

55-freebsd-126-freebsd-12
Last change on this file since f761b29 was f761b29, checked in by Sebastian Huber <sebastian.huber@…>, on 09/19/18 at 06:52:21

mDNSResponder: Update to v625.41.2

The sources can be obtained via:

https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-625.41.2.tar.gz

Update #3522.

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