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