]>
git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSPosix/mDNSUNP.c
1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2018 Apple Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include <sys/ioctl.h>
30 /* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
31 macro, usually defined in <sys/param.h> or someplace like that, to make sure the
32 CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
33 should be set to the name of the header to include to get the ALIGN(P) macro.
35 #ifdef NEED_ALIGN_MACRO
36 #include NEED_ALIGN_MACRO
39 /* sockaddr_dl is only referenced if we're using IP_RECVIF,
40 so only include the header in that case.
44 #include <net/if_dl.h>
48 recvfrom_flags(int fd
, void *ptr
, size_t nbytes
, int *flagsp
,
49 struct sockaddr
*sa
, socklen_t
*salenptr
, struct my_in_pktinfo
*pktp
, u_char
*ttl
)
56 struct cmsghdr
*cmptr
;
62 *ttl
= 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
64 msg
.msg_control
= control_un
.control
;
65 msg
.msg_controllen
= sizeof(control_un
.control
);
68 memset(&msg
, 0, sizeof(msg
)); /* make certain msg_accrightslen = 0 */
69 #endif /* CMSG_FIRSTHDR */
71 msg
.msg_name
= (char *) sa
;
72 msg
.msg_namelen
= *salenptr
;
73 iov
[0].iov_base
= (char *)ptr
;
74 iov
[0].iov_len
= nbytes
;
78 if ( (n
= recvmsg(fd
, &msg
, *flagsp
)) < 0)
81 *salenptr
= msg
.msg_namelen
; /* pass back results */
83 /* 0.0.0.0, i/f = -1 */
84 /* We set the interface to -1 so that the caller can
85 tell whether we returned a meaningful value or
86 just some default. Previously this code just
87 set the value to 0, but I'm concerned that 0
88 might be a valid interface value.
90 memset(pktp
, 0, sizeof(struct my_in_pktinfo
));
91 pktp
->ipi_ifindex
= -1;
93 /* end recvfrom_flags1 */
95 /* include recvfrom_flags2 */
97 #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
98 *flagsp
= 0; /* pass back results */
102 *flagsp
= msg
.msg_flags
; /* pass back results */
103 if (msg
.msg_controllen
< (socklen_t
)sizeof(struct cmsghdr
) ||
104 (msg
.msg_flags
& MSG_CTRUNC
) || pktp
== NULL
)
107 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
!= NULL
;
108 cmptr
= CMSG_NXTHDR(&msg
, cmptr
)) {
111 #if in_pktinfo_definition_is_missing
115 struct in_addr ipi_spec_dst
;
116 struct in_addr ipi_addr
;
119 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
120 cmptr
->cmsg_type
== IP_PKTINFO
) {
121 struct in_pktinfo
*tmp
;
122 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&pktp
->ipi_addr
;
124 tmp
= (struct in_pktinfo
*) CMSG_DATA(cmptr
);
125 sin
->sin_family
= AF_INET
;
126 sin
->sin_addr
= tmp
->ipi_addr
;
128 pktp
->ipi_ifindex
= tmp
->ipi_ifindex
;
133 #ifdef IP_RECVDSTADDR
134 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
135 cmptr
->cmsg_type
== IP_RECVDSTADDR
) {
136 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&pktp
->ipi_addr
;
138 sin
->sin_family
= AF_INET
;
139 sin
->sin_addr
= *(struct in_addr
*)CMSG_DATA(cmptr
);
146 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
147 cmptr
->cmsg_type
== IP_RECVIF
) {
148 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*) CMSG_DATA(cmptr
);
149 #ifndef HAVE_BROKEN_RECVIF_NAME
150 int nameLen
= (sdl
->sdl_nlen
< IFI_NAME
- 1) ? sdl
->sdl_nlen
: (IFI_NAME
- 1);
151 strncpy(pktp
->ipi_ifname
, sdl
->sdl_data
, nameLen
);
153 pktp
->ipi_ifindex
= sdl
->sdl_index
;
154 #ifdef HAVE_BROKEN_RECVIF_NAME
155 if (sdl
->sdl_index
== 0) {
156 pktp
->ipi_ifindex
= *(uint_t
*)sdl
;
159 assert(pktp
->ipi_ifname
[IFI_NAME
- 1] == 0);
160 // null terminated because of memset above
166 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
167 cmptr
->cmsg_type
== IP_RECVTTL
) {
168 *ttl
= *(u_char
*)CMSG_DATA(cmptr
);
171 else if (cmptr
->cmsg_level
== IPPROTO_IP
&&
172 cmptr
->cmsg_type
== IP_TTL
) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
173 *ttl
= *(int*)CMSG_DATA(cmptr
);
178 #if defined(IPV6_PKTINFO) && HAVE_IPV6
179 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&&
180 cmptr
->cmsg_type
== IPV6_2292_PKTINFO
) {
181 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&pktp
->ipi_addr
;
182 struct in6_pktinfo
*ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmptr
);
184 sin6
->sin6_family
= AF_INET6
;
185 #ifndef NOT_HAVE_SA_LEN
186 sin6
->sin6_len
= sizeof(*sin6
);
188 sin6
->sin6_addr
= ip6_info
->ipi6_addr
;
189 sin6
->sin6_flowinfo
= 0;
190 sin6
->sin6_scope_id
= 0;
192 pktp
->ipi_ifindex
= ip6_info
->ipi6_ifindex
;
197 #if defined(IPV6_HOPLIMIT) && HAVE_IPV6
198 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&&
199 cmptr
->cmsg_type
== IPV6_2292_HOPLIMIT
) {
200 *ttl
= *(int*)CMSG_DATA(cmptr
);
204 assert(0); // unknown ancillary data
207 #endif /* CMSG_FIRSTHDR */
210 // **********************************************************************************************
212 // daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
213 // Returns 0 on success, -1 on failure.
215 #ifdef NOT_HAVE_DAEMON
217 #include <sys/stat.h>
218 #include <sys/signal.h>
220 int daemon(int nochdir
, int noclose
)
224 case -1: return (-1); // Fork failed
225 case 0: break; // Child -- continue
226 default: _exit(0); // Parent -- exit
229 if (setsid() == -1) return(-1);
231 signal(SIGHUP
, SIG_IGN
);
233 switch (fork()) // Fork again, primarily for reasons of Unix trivia
235 case -1: return (-1); // Fork failed
236 case 0: break; // Child -- continue
237 default: _exit(0); // Parent -- exit
240 if (!nochdir
) (void)chdir("/");
245 int fd
= open("/dev/null", O_RDWR
, 0);
248 // Avoid unnecessarily duplicating a file descriptor to itself
249 if (fd
!= STDIN_FILENO
) (void)dup2(fd
, STDIN_FILENO
);
250 if (fd
!= STDOUT_FILENO
) (void)dup2(fd
, STDOUT_FILENO
);
251 if (fd
!= STDERR_FILENO
) (void)dup2(fd
, STDERR_FILENO
);
252 if (fd
!= STDIN_FILENO
&& fd
!= STDOUT_FILENO
&& fd
!= STDERR_FILENO
)
258 #endif /* NOT_HAVE_DAEMON */