2  * Copyright (c) 2011-2019 Apple Inc. All rights reserved. 
   4  * Licensed under the Apache License, Version 2.0 (the "License"); 
   5  * you may not use this file except in compliance with the License. 
   6  * You may obtain a copy of the License at 
   8  *     http://www.apache.org/licenses/LICENSE-2.0 
  10  * Unless required by applicable law or agreed to in writing, software 
  11  * distributed under the License is distributed on an "AS IS" BASIS, 
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13  * See the License for the specific language governing permissions and 
  14  * limitations under the License. 
  17 #include "mDNSEmbeddedAPI.h" 
  18 #include "mDNSMacOSX.h" 
  20 #include <sys/types.h> 
  22 #include <sys/event.h> 
  23 #include <netinet/tcp.h> 
  25 extern mDNS mDNSStorage
; 
  27 #define ValidSocket(s) ((s) >= 0) 
  29 // Global to store the 4 DNS Proxy Listeners (UDPv4/6, TCPv4/6) 
  30 static int dp_listener
[4]; 
  32 #define NUM_PROXY_TCP_CONNS 100 
  42 // returns -1 for failures including the other end closing the socket 
  43 // returns 0 if successful in reading data, but still not read the data fully 
  44 // returns 1 if successful in reading all the data 
  45 mDNSlocal 
int ProxyTCPRead(ProxyTCPInfo_t 
*tcpInfo
) 
  50     if (tcpInfo
->nread 
< 2)         // First read the two-byte length preceeding the DNS message 
  52         mDNSu8 
*lenptr 
= (mDNSu8 
*)&tcpInfo
->replyLen
; 
  53         n 
= mDNSPlatformReadTCP(&tcpInfo
->sock
, lenptr 
+ tcpInfo
->nread
, 2 - tcpInfo
->nread
, &closed
); 
  56             LogMsg("ProxyTCPRead: attempt to read message length failed"); 
  61         if (tcpInfo
->nread 
< 2) 
  63             LogMsg("ProxyTCPRead: nread %d, n %d", tcpInfo
->nread
, n
); 
  67         tcpInfo
->replyLen 
= (mDNSu16
)((mDNSu16
)lenptr
[0] << 8 | lenptr
[1]); 
  68         if (tcpInfo
->replyLen 
< sizeof(DNSMessageHeader
)) 
  70             LogMsg("ProxyTCPRead: Message length too short (%d bytes)", tcpInfo
->replyLen
); 
  74         tcpInfo
->reply 
= (DNSMessage 
*) mallocL("ProxyTCPInfo", tcpInfo
->replyLen
); 
  77             LogMsg("ProxyTCPRead: Memory failure"); 
  82     n 
= mDNSPlatformReadTCP(&tcpInfo
->sock
, ((char *)tcpInfo
->reply
) + (tcpInfo
->nread 
- 2), tcpInfo
->replyLen 
- (tcpInfo
->nread 
- 2), &closed
); 
  86         LogMsg("ProxyTCPRead: read failure n %d, closed %d", n
, closed
); 
  90     if ((tcpInfo
->nread 
- 2) != tcpInfo
->replyLen
) 
  96 mDNSlocal 
void ProxyTCPSocketCallBack(int s1
, short filter
, void *context
, __unused mDNSBool encounteredEOF
) 
  99     struct sockaddr_storage from
; 
 100     struct sockaddr_storage to
; 
 101     mDNSAddr senderAddr
, destAddr
; 
 102     mDNSIPPort senderPort
; 
 103     ProxyTCPInfo_t 
*ti 
= (ProxyTCPInfo_t 
*)context
; 
 104     TCPSocket 
*sock 
= &ti
->sock
; 
 105     struct tcp_info tcp_if
; 
 106     socklen_t size 
= sizeof(tcp_if
); 
 111     ret 
= ProxyTCPRead(ti
); 
 114         mDNSPlatformDisposeProxyContext(ti
); 
 119         debugf("ProxyTCPReceive: Not yet read completely Actual length %d, Read length %d", ti
->replyLen
, ti
->nread
); 
 122     // We read all the data and hence not interested in read events anymore 
 123     KQueueSet(s1
, EV_DELETE
, EVFILT_READ
, &sock
->kqEntry
); 
 125     mDNSPlatformMemZero(&to
, sizeof(to
)); 
 126     mDNSPlatformMemZero(&from
, sizeof(from
)); 
 127     socklen_t len 
= sizeof(to
); 
 128     ret 
= getsockname(s1
, (struct sockaddr
*) &to
, &len
); 
 131         LogMsg("ProxyTCPReceive: getsockname(fd=%d) errno %d", s1
, errno
); 
 132         mDNSPlatformDisposeProxyContext(ti
); 
 135     ret 
= getpeername(s1
, (struct sockaddr
*) &from
, &len
); 
 138         LogMsg("ProxyTCPReceive: getpeername(fd=%d) errno %d", s1
, errno
); 
 139         mDNSPlatformDisposeProxyContext(ti
); 
 142     if (getsockopt(s1
, IPPROTO_TCP
, TCP_INFO
, &tcp_if
, &size
) != 0) 
 144         LogMsg("ProxyTCPReceive: getsockopt for TCP_INFO failed (fd=%d) errno %d", s1
, errno
); 
 147     intf_id 
= tcp_if
.tcpi_last_outif
; 
 149     if (from
.ss_family 
== AF_INET
) 
 151         struct sockaddr_in 
*s 
= (struct sockaddr_in
*)&from
; 
 153         senderAddr
.type 
= mDNSAddrType_IPv4
; 
 154         senderAddr
.ip
.v4
.NotAnInteger 
= s
->sin_addr
.s_addr
; 
 155         senderPort
.NotAnInteger 
= s
->sin_port
; 
 157         s 
= (struct sockaddr_in 
*)&to
; 
 158         destAddr
.type 
= mDNSAddrType_IPv4
; 
 159         destAddr
.ip
.v4
.NotAnInteger 
= s
->sin_addr
.s_addr
; 
 161         LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d", 
 162                 ti
->replyLen
, &senderAddr
, &destAddr
, s1
, NULL
, intf_id
); 
 164     else if (from
.ss_family 
== AF_INET6
) 
 166         struct sockaddr_in6 
*sin6 
= (struct sockaddr_in6
*)&from
; 
 167         senderAddr
.type 
= mDNSAddrType_IPv6
; 
 168         senderAddr
.ip
.v6 
= *(mDNSv6Addr
*)&sin6
->sin6_addr
; 
 169         senderPort
.NotAnInteger 
= sin6
->sin6_port
; 
 171         sin6 
= (struct sockaddr_in6 
*)&to
; 
 172         destAddr
.type 
= mDNSAddrType_IPv6
; 
 173         destAddr
.ip
.v6 
= *(mDNSv6Addr
*)&sin6
->sin6_addr
; 
 175         LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d", 
 176                 ti
->replyLen
, &senderAddr
, &destAddr
, s1
, NULL
, intf_id
); 
 180         LogMsg("ProxyTCPReceive from is unknown address family %d", from
.ss_family
); 
 181         mDNSPlatformDisposeProxyContext(ti
); 
 185     // We pass sock for the TCPSocket and the "ti" for context as that's what we want to free at the end. 
 186     // In the UDP case, there is just a single socket and nothing to free. Hence, the context (last argument) 
 188     ti
->sock
.m
->p
->TCPProxyCallback(sock
, ti
->reply
, (mDNSu8 
*)ti
->reply 
+ ti
->replyLen
, &senderAddr
, senderPort
, &destAddr
, 
 189         UnicastDNSPort
, (mDNSInterfaceID
)(uintptr_t)intf_id
, ti
); 
 192 mDNSlocal 
void ProxyTCPAccept(int s1
, short filter
, void *context
, __unused mDNSBool encounteredEOF
) 
 195     struct sockaddr_storage ss
; 
 196     socklen_t sslen 
= sizeof(ss
); 
 198     TCPSocket 
*listenSock 
= (TCPSocket 
*)context
; 
 202     while ((newfd 
= accept(s1
, (struct sockaddr 
*)&ss
, &sslen
)) != -1) 
 206         // Even though we just need a single KQueueEntry, for simplicity we re-use 
 208         ProxyTCPInfo_t 
* const ti 
= (ProxyTCPInfo_t 
*)callocL("ProxyTCPContext", sizeof(*ti
)); 
 211             LogMsg("ProxyTCPAccept: cannot allocate TCPSocket"); 
 215         TCPSocket 
* const sock 
= &ti
->sock
; 
 217         sock
->m  
= listenSock
->m
; 
 219         fcntl(newfd
, F_SETFL
, fcntl(newfd
, F_GETFL
, 0) | O_NONBLOCK
); // set non-blocking 
 220         if (ss
.ss_family 
== AF_INET
) 
 222             // Receive interface identifiers 
 223             err 
= setsockopt(newfd
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
)); 
 226                 LogMsg("ProxyTCPAccept: IP_RECVIF %d errno %d (%s)", newfd
, errno
, strerror(errno
)); 
 227                 mDNSPlatformDisposeProxyContext(ti
); 
 234             // We want to receive destination addresses and receive interface identifiers 
 235             err 
= setsockopt(newfd
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
, &on
, sizeof(on
)); 
 238                 LogMsg("ProxyTCPAccept: IP_RECVPKTINFO %d errno %d (%s)", newfd
, errno
, strerror(errno
)); 
 239                 mDNSPlatformDisposeProxyContext(ti
); 
 244         // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address 
 245         // from which we can infer the destination address family. Hence we need to remember that here. 
 246         // Instead of remembering the address family, we remember the right fd. 
 248         sock
->kqEntry
.KQcallback 
= ProxyTCPSocketCallBack
; 
 249         sock
->kqEntry
.KQcontext  
= ti
; 
 250         sock
->kqEntry
.KQtask     
= "TCP Proxy packet reception"; 
 251 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 
 252         sock
->kqEntry
.readSource 
= mDNSNULL
; 
 253         sock
->kqEntry
.writeSource 
= mDNSNULL
; 
 254         sock
->kqEntry
.fdClosed 
= mDNSfalse
; 
 256         sock
->connected 
= mDNStrue
; 
 257         sock
->m 
= listenSock
->m
; 
 258         KQueueSet(newfd
, EV_ADD
, EVFILT_READ
, &sock
->kqEntry
); 
 262 mDNSlocal mStatus 
SetupUDPProxySocket(int skt
, KQSocketSet 
*cp
, u_short sa_family
, mDNSBool useBackgroundTrafficClass
) 
 264     int         *s        
= (sa_family 
== AF_INET
) ? &cp
->sktv4 
: &cp
->sktv6
; 
 265     KQueueEntry 
*k        
= (sa_family 
== AF_INET
) ? &cp
->kqsv4 
: &cp
->kqsv6
; 
 267     mStatus err 
= mStatus_NoError
; 
 269     cp
->m 
= &mDNSStorage
; 
 270     cp
->closeFlag 
= mDNSNULL
; 
 272     // set default traffic class 
 273     // setTrafficClass(skt, mDNSfalse); 
 274     (void) useBackgroundTrafficClass
; 
 276     if (sa_family 
== AF_INET
) 
 278         err 
= setsockopt(skt
, IPPROTO_IP
, IP_RECVDSTADDR
, &on
, sizeof(on
)); 
 281             LogMsg("SetupUDPProxySocket: IP_RECVDSTADDR %d errno %d (%s)", skt
, errno
, strerror(errno
)); 
 285         // We want to receive interface identifiers 
 286         err 
= setsockopt(skt
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
)); 
 289             LogMsg("SetupUDPProxySocket: IP_RECVIF %d errno %d (%s)", skt
, errno
, strerror(errno
)); 
 293     else if (sa_family 
== AF_INET6
) 
 295         // We want to receive destination addresses and receive interface identifiers 
 296         err 
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
, &on
, sizeof(on
)); 
 299             LogMsg("SetupUDPProxySocket: IPV6_RECVPKTINFO %d errno %d (%s)", skt
, errno
, strerror(errno
)); 
 303         // We want to receive packet hop count value so we can check it 
 304         err 
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_RECVHOPLIMIT
, &on
, sizeof(on
)); 
 307             LogMsg("SetupUDPProxySocket: IPV6_RECVHOPLIMIT %d errno %d (%s)", skt
, errno
, strerror(errno
)); 
 313         LogMsg("SetupUDPProxySocket: wrong family %d", sa_family
); 
 317     if (fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
) < 0) 
 319         LogMsg("SetupUDPProxySocket: fnctl failed %d", errno
); 
 324     //k->KQcallback = ProxyUDPSocketCallBack; 
 325     k
->KQcallback  
= myKQSocketCallBack
; 
 327     k
->KQtask      
= "UDP Proxy packet reception"; 
 328 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 
 329     k
->readSource  
= mDNSNULL
; 
 330     k
->writeSource 
= mDNSNULL
; 
 331     k
->fdClosed    
= mDNSfalse
; 
 334     KQueueSet(*s
, EV_ADD
, EVFILT_READ
, k
); 
 339 mDNSlocal mStatus 
SetupTCPProxySocket(int skt
, TCPSocket 
*sock
, u_short sa_family
, mDNSBool useBackgroundTrafficClass
) 
 342     mDNS 
*m 
= &mDNSStorage
; 
 344     // for TCP sockets, the traffic class is set once and not changed 
 345     // setTrafficClass(skt, useBackgroundTrafficClass); 
 346     (void) useBackgroundTrafficClass
; 
 349     // All the socket setup has already been done  
 350     err 
= listen(skt
, NUM_PROXY_TCP_CONNS
); 
 353         LogMsg("SetupTCPProxySocket: listen %d errno %d (%s)", skt
, errno
, strerror(errno
)); 
 356     fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
); // set non-blocking 
 359     sock
->kqEntry
.KQcallback  
= ProxyTCPAccept
; 
 360     sock
->kqEntry
.KQcontext   
= sock
; 
 361     sock
->kqEntry
.KQtask      
= "TCP Accept"; 
 362 #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM 
 363     sock
->kqEntry
.readSource  
= mDNSNULL
; 
 364     sock
->kqEntry
.writeSource 
= mDNSNULL
; 
 365     sock
->kqEntry
.fdClosed    
= mDNSfalse
; 
 368     KQueueSet(skt
, EV_ADD
, EVFILT_READ
, &sock
->kqEntry
); 
 369     return mStatus_NoError
; 
 372 mDNSlocal 
void BindDPSocket(int fd
, int sa_family
, int type
) 
 377     if (type 
== SOCK_STREAM
) 
 379         err 
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof(on
)); 
 382             const int setsockopt_errno 
= errno
; 
 383             LogRedact(MDNS_LOG_CATEGORY_DEFAULT
, MDNS_LOG_DEFAULT
, 
 384                 "BindDPSocket: setsockopt SO_REUSEADDR failed for " PUB_S 
" %d errno %d (" PUB_S 
")", 
 385                 (sa_family 
== AF_INET
) ? "IPv4" : "IPv6", fd
, setsockopt_errno
, strerror(setsockopt_errno
)); 
 389     if (sa_family 
== AF_INET
) 
 391         struct sockaddr_in addr
; 
 393         memset(&addr
, 0, sizeof(addr
)); 
 394         addr
.sin_family 
= AF_INET
; 
 395         addr
.sin_port 
= htons(53); 
 397         err 
= bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)); 
 400             LogMsg("BindDPSocket: bind %d errno %d (%s)", fd
, errno
, strerror(errno
)); 
 406         struct sockaddr_in6 addr6
; 
 408         // We want to receive only IPv6 packets. Without this option we get IPv4 packets too, 
 409         // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address 
 410         err 
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
, sizeof(on
)); 
 413             LogMsg("DPFBindSocket: setsockopt IPV6_V6ONLY %d errno %d (%s)", fd
, errno
, strerror(errno
)); 
 416         memset(&addr6
, 0, sizeof(addr6
)); 
 417         addr6
.sin6_family 
= AF_INET6
; 
 418         addr6
.sin6_port 
= htons(53); 
 420         err 
= bind(fd
, (struct sockaddr
*) &addr6
, sizeof(addr6
)); 
 423             LogMsg("BindDPSocket: bind6 %d errno %d (%s)", fd
, errno
, strerror(errno
)); 
 429 // Setup DNS Proxy Skts in main kevent loop and set the skt options 
 430 mDNSlocal 
void SetupDNSProxySkts(int fd
[4]) 
 432     mDNS 
*const m 
= &mDNSStorage
; 
 438     udpSS       
= &m
->p
->UDPProxy
.ss
; 
 439     udpSS
->port 
= UnicastDNSPort
; 
 440     v4 
= &m
->p
->TCPProxyV4
; 
 441     v6 
= &m
->p
->TCPProxyV6
; 
 443     v4
->port 
= UnicastDNSPort
; 
 445     v6
->port 
= UnicastDNSPort
; 
 447     LogMsg("SetupDNSProxySkts: %d, %d, %d, %d", fd
[0], fd
[1], fd
[2], fd
[3]); 
 449     // myKQSocketCallBack checks for proxy and calls the m->p->ProxyCallback instead of mDNSCoreReceive 
 450     udpSS
->proxy 
= mDNStrue
; 
 451     err 
= SetupUDPProxySocket(fd
[0], udpSS
, AF_INET
, mDNSfalse
); 
 453         LogMsg("SetupDNSProxySkts: ERROR!! UDPv4 Socket"); 
 455     err 
= SetupUDPProxySocket(fd
[1], udpSS
, AF_INET6
, mDNSfalse
); 
 457         LogMsg("SetupDNSProxySkts: ERROR!! UDPv6 Socket"); 
 459     err 
= SetupTCPProxySocket(fd
[2], v4
, AF_INET
, mDNSfalse
); 
 461         LogMsg("SetupDNSProxySkts: ERROR!! TCPv4 Socket"); 
 463     err 
= SetupTCPProxySocket(fd
[3], v6
, AF_INET6
, mDNSfalse
); 
 465         LogMsg("SetupDNSProxySkts: ERROR!! TCPv6 Socket"); 
 467     for (i 
= 0; i 
< 4; i
++) 
 468         dp_listener
[i
] = fd
[i
];    
 471 // Create and bind the DNS Proxy Skts for use 
 472 mDNSexport 
void mDNSPlatformInitDNSProxySkts(ProxyCallback UDPCallback
, ProxyCallback TCPCallback
) 
 476     dpskt
[0] = socket(AF_INET
,  SOCK_DGRAM
,  IPPROTO_UDP
); 
 477     dpskt
[1] = socket(AF_INET6
, SOCK_DGRAM
,  IPPROTO_UDP
); 
 478     dpskt
[2] = socket(AF_INET
,  SOCK_STREAM
, IPPROTO_TCP
); 
 479     dpskt
[3] = socket(AF_INET6
, SOCK_STREAM
, IPPROTO_TCP
); 
 481     // Close all DNS Proxy skts in case any of them are invalid 
 482     if (!ValidSocket(dpskt
[0]) || !ValidSocket(dpskt
[1]) || 
 483         !ValidSocket(dpskt
[2]) || !ValidSocket(dpskt
[3])) 
 485         if (ValidSocket(dpskt
[0])) 
 487         if (ValidSocket(dpskt
[1])) 
 489         if (ValidSocket(dpskt
[2])) 
 491         if (ValidSocket(dpskt
[3])) 
 495     BindDPSocket(dpskt
[0], AF_INET
, SOCK_DGRAM
); 
 496     BindDPSocket(dpskt
[1], AF_INET6
, SOCK_DGRAM
); 
 497     BindDPSocket(dpskt
[2], AF_INET
, SOCK_STREAM
); 
 498     BindDPSocket(dpskt
[3], AF_INET6
, SOCK_STREAM
); 
 500     LogInfo("mDNSPlatformInitDNSProxySkts: Opened Listener Sockets for DNS Proxy : %d, %d, %d, %d",  
 501              dpskt
[0], dpskt
[1], dpskt
[2], dpskt
[3]); 
 503     mDNSStorage
.p
->UDPProxyCallback 
= UDPCallback
; 
 504     mDNSStorage
.p
->TCPProxyCallback 
= TCPCallback
; 
 506     SetupDNSProxySkts(dpskt
); 
 509 mDNSexport 
void mDNSPlatformCloseDNSProxySkts(mDNS 
*const m
) 
 513     for (i 
= 0; i 
< 4; i
++) 
 514         close(dp_listener
[i
]); 
 515     LogInfo("mDNSPlatformCloseDNSProxySkts: Closing DNS Proxy Listener Sockets");   
 518 mDNSexport 
void mDNSPlatformDisposeProxyContext(void *context
) 
 526     ti 
= (ProxyTCPInfo_t 
*)context
; 
 531         mDNSPlatformCloseFD(&sock
->kqEntry
, sock
->fd
); 
 536         freeL("ProxyTCPInfoLen", ti
->reply
); 
 537     freeL("ProxyTCPContext", ti
); 
 543 // c-file-style: "bsd" 
 546 // indent-tabs-mode: nil