]>
Commit | Line | Data |
---|---|---|
51601d48 A |
1 | /* -*- Mode: C; tab-width: 4 -*- |
2 | * | |
9f221bca | 3 | * Copyright (c) 2011-2013 Apple Inc. All rights reserved. |
51601d48 A |
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 | */ | |
9f221bca | 17 | |
51601d48 A |
18 | #include "mDNSEmbeddedAPI.h" |
19 | #include "mDNSMacOSX.h" | |
20 | ||
21 | #include <sys/types.h> | |
22 | #include <sys/time.h> | |
23 | #include <sys/event.h> | |
9f221bca | 24 | #include <netinet/tcp.h> |
51601d48 | 25 | |
12c5fa7a A |
26 | mDNSexport mDNS mDNSStorage; |
27 | ||
51601d48 A |
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 | ||
12c5fa7a | 97 | mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context, __unused mDNSBool encounteredEOF) |
51601d48 A |
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; | |
9f221bca A |
107 | struct tcp_info tcp_if; |
108 | socklen_t size = sizeof(tcp_if); | |
109 | int32_t intf_id = 0; | |
51601d48 A |
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 | } | |
9f221bca A |
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; | |
51601d48 A |
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 | ||
9f221bca A |
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); | |
51601d48 A |
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 | ||
9f221bca A |
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); | |
51601d48 A |
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. | |
12c5fa7a | 190 | kq->m->p->TCPProxyCallback(sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr, |
9f221bca | 191 | UnicastDNSPort, (mDNSInterfaceID)(uintptr_t)intf_id, ti); |
51601d48 A |
192 | } |
193 | ||
12c5fa7a | 194 | mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context, __unused mDNSBool encounteredEOF) |
51601d48 A |
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)); | |
9f221bca | 221 | |
51601d48 A |
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); | |
9f221bca | 240 | close(newfd); |
51601d48 A |
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); | |
9f221bca | 254 | close(newfd); |
51601d48 A |
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; | |
51601d48 A |
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 | ||
12c5fa7a | 276 | mDNSlocal mStatus SetupUDPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass) |
51601d48 A |
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; | |
51601d48 A |
281 | mStatus err = mStatus_NoError; |
282 | ||
12c5fa7a | 283 | cp->m = &mDNSStorage; |
51601d48 A |
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 | ||
12c5fa7a | 353 | mDNSlocal mStatus SetupTCPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass) |
51601d48 A |
354 | { |
355 | int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6; | |
356 | KQueueEntry *k = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6; | |
51601d48 A |
357 | mStatus err; |
358 | ||
12c5fa7a | 359 | cp->m = &mDNSStorage; |
51601d48 A |
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) | |
9f221bca | 400 | LogMsg("BindDPSocket: setsockopt SO_REUSEPORT failed for IPv4 %d errno %d (%s)", fd, errno, strerror(errno)); |
51601d48 A |
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 | |
12c5fa7a | 443 | mDNSlocal void SetupDNSProxySkts(int fd[4]) |
51601d48 | 444 | { |
12c5fa7a A |
445 | mDNS *const m = &mDNSStorage; |
446 | int i; | |
51601d48 A |
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; | |
12c5fa7a | 460 | err = SetupUDPProxySocket(fd[0], udpSS, AF_INET, mDNSfalse); |
51601d48 A |
461 | if (err) |
462 | LogMsg("SetupDNSProxySkts: ERROR!! UDPv4 Socket"); | |
463 | ||
12c5fa7a | 464 | err = SetupUDPProxySocket(fd[1], udpSS, AF_INET6, mDNSfalse); |
51601d48 A |
465 | if (err) |
466 | LogMsg("SetupDNSProxySkts: ERROR!! UDPv6 Socket"); | |
467 | ||
12c5fa7a | 468 | err = SetupTCPProxySocket(fd[2], tcpSS, AF_INET, mDNSfalse); |
51601d48 A |
469 | if (err) |
470 | LogMsg("SetupDNSProxySkts: ERROR!! TCPv4 Socket"); | |
471 | ||
12c5fa7a | 472 | err = SetupTCPProxySocket(fd[3], tcpSS, AF_INET6, mDNSfalse); |
51601d48 A |
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 | |
12c5fa7a | 481 | mDNSexport void mDNSPlatformInitDNSProxySkts(ProxyCallback UDPCallback, ProxyCallback TCPCallback) |
51601d48 A |
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 | ||
12c5fa7a A |
512 | mDNSStorage.p->UDPProxyCallback = UDPCallback; |
513 | mDNSStorage.p->TCPProxyCallback = TCPCallback; | |
51601d48 | 514 | |
12c5fa7a | 515 | SetupDNSProxySkts(dpskt); |
51601d48 A |
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 |