]>
git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSPosix/mDNSUNP.c
1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2004 Apple Computer, 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.
17 Change History (most recent first):
20 Revision 1.40 2009/01/13 05:31:34 mkrochma
21 <rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
23 Revision 1.39 2009/01/11 03:20:06 mkrochma
24 <rdar://problem/5797526> Fixes from Igor Seleznev to get mdnsd working on Solaris
26 Revision 1.38 2009/01/10 22:54:42 mkrochma
27 <rdar://problem/5797544> Fixes from Igor Seleznev to get mdnsd working on Linux
29 Revision 1.37 2008/10/23 22:33:24 cheshire
30 Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
32 Revision 1.36 2008/04/21 18:21:22 mkrochma
33 <rdar://problem/5877307> Need to free ifi_netmask
34 Submitted by Igor Seleznev
36 Revision 1.35 2007/11/15 21:36:19 cheshire
37 <rdar://problem/5289340> POSIX: Off by one overflow in get_ifi_info_linuxv6()
39 Revision 1.34 2006/08/14 23:24:47 cheshire
40 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
42 Revision 1.33 2006/03/13 23:14:21 cheshire
43 <rdar://problem/4427969> Compile problems on FreeBSD
44 Use <netinet/in_var.h> instead of <netinet6/in6_var.h>
46 Revision 1.32 2005/12/21 02:56:43 cheshire
47 <rdar://problem/4243433> get_ifi_info() should fake ifi_index when SIOCGIFINDEX undefined
49 Revision 1.31 2005/12/21 02:46:05 cheshire
50 <rdar://problem/4243514> mDNSUNP.c needs to include <sys/param.h> on 4.4BSD Lite
52 Revision 1.30 2005/11/29 20:03:02 mkrochma
53 Wrapped sin_len with #ifndef NOT_HAVE_SA_LEN
55 Revision 1.29 2005/11/12 02:23:10 cheshire
56 <rdar://problem/4317680> mDNSUNP.c needs to deal with lame results from SIOCGIFNETMASK, SIOCGIFBRDADDR and SIOCGIFDSTADDR
58 Revision 1.28 2005/10/31 22:09:45 cheshire
59 Buffer "char addr6[33]" was seven bytes too small
61 Revision 1.27 2005/06/29 15:54:21 cheshire
62 <rdar://problem/4113742> mDNSResponder-107.1 does not work on FreeBSD
63 Refine last checkin so that it (hopefully) doesn't break get_ifi_info() for every other OS
65 Revision 1.26 2005/04/08 21:43:59 ksekar
66 <rdar://problem/4083426> mDNSPosix (v98) retrieve interface list bug on AMD64 architecture
67 Submitted by Andrew de Quincey
69 Revision 1.25 2005/04/08 21:37:57 ksekar
70 <rdar://problem/3792767> get_ifi_info doesn't return IPv6 interfaces on Linux
72 Revision 1.24 2005/04/08 21:30:16 ksekar
73 <rdar://problem/4007457> Compiling problems with mDNSResponder-98 on Solaris/Sparc v9
74 Patch submitted by Bernd Kuhls
76 Revision 1.23 2004/12/01 04:25:05 cheshire
77 <rdar://problem/3872803> Darwin patches for Solaris and Suse
78 Provide daemon() for platforms that don't have it
80 Revision 1.22 2004/11/30 22:37:01 cheshire
81 Update copyright dates and add "Mode: C; tab-width: 4" headers
83 Revision 1.21 2004/11/08 22:13:59 rpantos
84 Create sockf6 lazily when v6 interface found.
86 Revision 1.20 2004/10/16 00:17:01 cheshire
87 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
89 Revision 1.19 2004/07/20 01:47:36 rpantos
90 NOT_HAVE_SA_LEN applies to v6, too. And use more-portable s6_addr.
92 Revision 1.18 2004/07/08 21:30:21 rpantos
94 Revision 1.17 2004/06/25 00:26:27 rpantos
95 Changes to fix the Posix build on Solaris.
97 Revision 1.16 2004/03/20 05:37:09 cheshire
98 Fix contributed by Terry Lambert & Alfred Perlstein:
99 Don't use uint8_t -- it requires stdint.h, which doesn't exist on FreeBSD 4.x
101 Revision 1.15 2004/02/14 01:09:45 rpantos
102 Just use HAVE_IPV6 rather than defined(HAVE_IPV6).
104 Revision 1.14 2003/12/11 18:53:40 cheshire
105 Fix compiler warning reported by Paul Guyot
107 Revision 1.13 2003/12/08 20:47:02 rpantos
108 Add support for mDNSResponder on Linux.
110 Revision 1.12 2003/09/02 20:47:13 cheshire
111 Fix signed/unsigned warning
113 Revision 1.11 2003/08/12 19:56:26 cheshire
116 Revision 1.10 2003/08/06 18:20:51 cheshire
119 Revision 1.9 2003/07/14 18:11:54 cheshire
120 Fix stricter compiler warnings
122 Revision 1.8 2003/07/02 21:19:59 cheshire
123 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
125 Revision 1.7 2003/03/20 21:10:31 cheshire
126 Fixes done at IETF 56 to make mDNSProxyResponderPosix run on Solaris
128 Revision 1.6 2003/03/13 03:46:21 cheshire
129 Fixes to make the code build on Linux
131 Revision 1.5 2003/02/07 03:02:02 cheshire
132 Submitted by: Mitsutaka Watanabe
133 The code saying "index += 1;" was effectively making up random interface index values.
134 The right way to find the correct interface index is if_nametoindex();
136 Revision 1.4 2002/12/23 22:13:31 jgraessl
138 Reviewed by: Stuart Cheshire
139 Initial IPv6 support for mDNSResponder.
141 Revision 1.3 2002/09/21 20:44:53 zarzycki
144 Revision 1.2 2002/09/19 04:20:44 cheshire
145 Remove high-ascii characters that confuse some systems
147 Revision 1.1 2002/09/17 06:24:34 cheshire
159 #include <sys/ioctl.h>
164 /* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
165 macro, usually defined in <sys/param.h> or someplace like that, to make sure the
166 CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
167 should be set to the name of the header to include to get the ALIGN(P) macro.
169 #ifdef NEED_ALIGN_MACRO
170 #include NEED_ALIGN_MACRO
173 /* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
174 other platforms don't even have that include file. So,
175 if we haven't yet got a definition, let's try to find
180 #include <sys/sockio.h>
183 /* sockaddr_dl is only referenced if we're using IP_RECVIF,
184 so only include the header in that case.
188 #include <net/if_dl.h>
191 #if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
192 #include <net/if_var.h>
193 #include <netinet/in_var.h>
194 // Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
197 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
199 #include <arpa/inet.h>
201 /* Converts a prefix length to IPv6 network mask */
202 void plen_to_mask(int plen
, char *addr
) {
204 int colons
=7; /* Number of colons in IPv6 address */
205 int bits_in_block
=16; /* Bits per IPv6 block */
206 for(i
=0;i
<=colons
;i
++) {
207 int block
, ones
=0xffff, ones_in_block
;
208 if(plen
>bits_in_block
) ones_in_block
=bits_in_block
;
209 else ones_in_block
=plen
;
210 block
= ones
& (ones
<< (bits_in_block
-ones_in_block
));
211 i
==0 ? sprintf(addr
, "%x", block
) : sprintf(addr
, "%s:%x", addr
, block
);
212 plen
-= ones_in_block
;
216 /* Gets IPv6 interface information from the /proc filesystem in linux*/
217 struct ifi_info
*get_ifi_info_linuxv6(int family
, int doaliases
)
219 struct ifi_info
*ifi
, *ifihead
, **ifipnext
;
222 int flags
, myflags
, index
, plen
, scope
;
223 char ifname
[9], lastname
[IFNAMSIZ
];
224 char addr6
[32+7+1]; /* don't forget the seven ':' */
225 struct addrinfo hints
, *res0
;
226 struct sockaddr_in6
*sin6
;
227 struct in6_addr
*addrptr
;
235 if ((fp
= fopen(PROC_IFINET6_PATH
, "r")) != NULL
) {
237 "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
238 addr
[0],addr
[1],addr
[2],addr
[3],
239 addr
[4],addr
[5],addr
[6],addr
[7],
240 &index
, &plen
, &scope
, &flags
, ifname
) != EOF
) {
243 if (strncmp(lastname
, ifname
, IFNAMSIZ
) == 0) {
245 continue; /* already processed this interface */
248 memcpy(lastname
, ifname
, IFNAMSIZ
);
249 ifi
= (struct ifi_info
*)calloc(1, sizeof(struct ifi_info
));
254 *ifipnext
= ifi
; /* prev points to this new one */
255 ifipnext
= &ifi
->ifi_next
; /* pointer to next one goes here */
257 sprintf(addr6
, "%s:%s:%s:%s:%s:%s:%s:%s",
258 addr
[0],addr
[1],addr
[2],addr
[3],
259 addr
[4],addr
[5],addr
[6],addr
[7]);
261 /* Add address of the interface */
262 memset(&hints
, 0, sizeof(hints
));
263 hints
.ai_family
= AF_INET6
;
264 hints
.ai_flags
= AI_NUMERICHOST
;
265 err
= getaddrinfo(addr6
, NULL
, &hints
, &res0
);
269 ifi
->ifi_addr
= calloc(1, sizeof(struct sockaddr_in6
));
270 if (ifi
->ifi_addr
== NULL
) {
273 memcpy(ifi
->ifi_addr
, res0
->ai_addr
, sizeof(struct sockaddr_in6
));
275 /* Add netmask of the interface */
276 char ipv6addr
[INET6_ADDRSTRLEN
];
277 plen_to_mask(plen
, ipv6addr
);
278 ifi
->ifi_netmask
= calloc(1, sizeof(struct sockaddr_in6
));
279 if (ifi
->ifi_addr
== NULL
) {
282 sin6
=calloc(1, sizeof(struct sockaddr_in6
));
283 addrptr
=calloc(1, sizeof(struct in6_addr
));
284 inet_pton(family
, ipv6addr
, addrptr
);
285 sin6
->sin6_family
=family
;
286 sin6
->sin6_addr
=*addrptr
;
287 sin6
->sin6_scope_id
=scope
;
288 memcpy(ifi
->ifi_netmask
, sin6
, sizeof(struct sockaddr_in6
));
292 /* Add interface name */
293 memcpy(ifi
->ifi_name
, ifname
, IFI_NAME
);
295 /* Add interface index */
296 ifi
->ifi_index
= index
;
298 /* If interface is in /proc then it is up*/
299 ifi
->ifi_flags
= IFF_UP
;
308 if (ifihead
!= NULL
) {
309 free_ifi_info(ifihead
);
317 return(ifihead
); /* pointer to first structure in linked list */
319 #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
321 struct ifi_info
*get_ifi_info(int family
, int doaliases
)
324 struct ifi_info
*ifi
, *ifihead
, **ifipnext
;
325 int sockfd
, sockf6
, len
, lastlen
, flags
, myflags
;
326 #ifdef NOT_HAVE_IF_NAMETOINDEX
329 char *ptr
, *buf
, lastname
[IFNAMSIZ
], *cptr
;
331 struct ifreq
*ifr
, ifrcopy
;
332 struct sockaddr_in
*sinptr
;
334 #if defined(AF_INET6) && HAVE_IPV6
335 struct sockaddr_in6
*sinptr6
;
338 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
339 if(family
== AF_INET6
) return get_ifi_info_linuxv6(family
, doaliases
);
347 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
353 len
= 100 * sizeof(struct ifreq
); /* initial buffer size guess */
355 buf
= (char*)malloc(len
);
361 if (ioctl(sockfd
, SIOCGIFCONF
, &ifc
) < 0) {
362 if (errno
!= EINVAL
|| lastlen
!= 0) {
366 if (ifc
.ifc_len
== lastlen
)
367 break; /* success, len has not changed */
368 lastlen
= ifc
.ifc_len
;
370 len
+= 10 * sizeof(struct ifreq
); /* increment */
376 /* end get_ifi_info1 */
378 /* include get_ifi_info2 */
379 for (ptr
= buf
; ptr
< buf
+ ifc
.ifc_len
; ) {
380 ifr
= (struct ifreq
*) ptr
;
382 /* Advance to next one in buffer */
383 if (sizeof(struct ifreq
) > sizeof(ifr
->ifr_name
) + GET_SA_LEN(ifr
->ifr_addr
))
384 ptr
+= sizeof(struct ifreq
);
386 ptr
+= sizeof(ifr
->ifr_name
) + GET_SA_LEN(ifr
->ifr_addr
);
388 // fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
390 if (ifr
->ifr_addr
.sa_family
!= family
)
391 continue; /* ignore if not desired address family */
394 if ( (cptr
= strchr(ifr
->ifr_name
, ':')) != NULL
)
395 *cptr
= 0; /* replace colon will null */
396 if (strncmp(lastname
, ifr
->ifr_name
, IFNAMSIZ
) == 0) {
398 continue; /* already processed this interface */
401 memcpy(lastname
, ifr
->ifr_name
, IFNAMSIZ
);
404 if (ioctl(sockfd
, SIOCGIFFLAGS
, &ifrcopy
) < 0) {
408 flags
= ifrcopy
.ifr_flags
;
409 if ((flags
& IFF_UP
) == 0)
410 continue; /* ignore if interface not up */
412 ifi
= (struct ifi_info
*)calloc(1, sizeof(struct ifi_info
));
416 *ifipnext
= ifi
; /* prev points to this new one */
417 ifipnext
= &ifi
->ifi_next
; /* pointer to next one goes here */
419 ifi
->ifi_flags
= flags
; /* IFF_xxx values */
420 ifi
->ifi_myflags
= myflags
; /* IFI_xxx values */
421 #ifndef NOT_HAVE_IF_NAMETOINDEX
422 ifi
->ifi_index
= if_nametoindex(ifr
->ifr_name
);
426 if ( 0 >= ioctl(sockfd
, SIOCGIFINDEX
, &ifrcopy
))
427 ifi
->ifi_index
= ifrcopy
.ifr_index
;
430 ifi
->ifi_index
= index
++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
432 memcpy(ifi
->ifi_name
, ifr
->ifr_name
, IFI_NAME
);
433 ifi
->ifi_name
[IFI_NAME
-1] = '\0';
434 /* end get_ifi_info2 */
435 /* include get_ifi_info3 */
436 switch (ifr
->ifr_addr
.sa_family
) {
438 sinptr
= (struct sockaddr_in
*) &ifr
->ifr_addr
;
439 if (ifi
->ifi_addr
== NULL
) {
440 ifi
->ifi_addr
= (struct sockaddr
*)calloc(1, sizeof(struct sockaddr_in
));
441 if (ifi
->ifi_addr
== NULL
) {
444 memcpy(ifi
->ifi_addr
, sinptr
, sizeof(struct sockaddr_in
));
446 #ifdef SIOCGIFNETMASK
447 if (ioctl(sockfd
, SIOCGIFNETMASK
, &ifrcopy
) < 0) goto gotError
;
448 ifi
->ifi_netmask
= (struct sockaddr
*)calloc(1, sizeof(struct sockaddr_in
));
449 if (ifi
->ifi_netmask
== NULL
) goto gotError
;
450 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_addr
;
451 /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
452 #ifndef NOT_HAVE_SA_LEN
453 sinptr
->sin_len
= sizeof(struct sockaddr_in
);
455 sinptr
->sin_family
= AF_INET
;
456 memcpy(ifi
->ifi_netmask
, sinptr
, sizeof(struct sockaddr_in
));
459 #ifdef SIOCGIFBRDADDR
460 if (flags
& IFF_BROADCAST
) {
461 if (ioctl(sockfd
, SIOCGIFBRDADDR
, &ifrcopy
) < 0) {
464 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_broadaddr
;
465 /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
466 #ifndef NOT_HAVE_SA_LEN
467 sinptr
->sin_len
= sizeof( struct sockaddr_in
);
469 sinptr
->sin_family
= AF_INET
;
470 ifi
->ifi_brdaddr
= (struct sockaddr
*)calloc(1, sizeof(struct sockaddr_in
));
471 if (ifi
->ifi_brdaddr
== NULL
) {
474 memcpy(ifi
->ifi_brdaddr
, sinptr
, sizeof(struct sockaddr_in
));
478 #ifdef SIOCGIFDSTADDR
479 if (flags
& IFF_POINTOPOINT
) {
480 if (ioctl(sockfd
, SIOCGIFDSTADDR
, &ifrcopy
) < 0) {
483 sinptr
= (struct sockaddr_in
*) &ifrcopy
.ifr_dstaddr
;
484 /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
485 #ifndef NOT_HAVE_SA_LEN
486 sinptr
->sin_len
= sizeof( struct sockaddr_in
);
488 sinptr
->sin_family
= AF_INET
;
489 ifi
->ifi_dstaddr
= (struct sockaddr
*)calloc(1, sizeof(struct sockaddr_in
));
490 if (ifi
->ifi_dstaddr
== NULL
) {
493 memcpy(ifi
->ifi_dstaddr
, sinptr
, sizeof(struct sockaddr_in
));
499 #if defined(AF_INET6) && HAVE_IPV6
501 sinptr6
= (struct sockaddr_in6
*) &ifr
->ifr_addr
;
502 if (ifi
->ifi_addr
== NULL
) {
503 ifi
->ifi_addr
= calloc(1, sizeof(struct sockaddr_in6
));
504 if (ifi
->ifi_addr
== NULL
) {
508 /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
509 /* We need to strip that out */
510 if (IN6_IS_ADDR_LINKLOCAL(&sinptr6
->sin6_addr
))
511 sinptr6
->sin6_addr
.s6_addr
[2] = sinptr6
->sin6_addr
.s6_addr
[3] = 0;
512 memcpy(ifi
->ifi_addr
, sinptr6
, sizeof(struct sockaddr_in6
));
514 #ifdef SIOCGIFNETMASK_IN6
516 struct in6_ifreq ifr6
;
518 sockf6
= socket(AF_INET6
, SOCK_DGRAM
, 0);
519 memset(&ifr6
, 0, sizeof(ifr6
));
520 memcpy(&ifr6
.ifr_name
, &ifr
->ifr_name
, sizeof(ifr6
.ifr_name
));
521 memcpy(&ifr6
.ifr_ifru
.ifru_addr
, &ifr
->ifr_addr
, sizeof(ifr6
.ifr_ifru
.ifru_addr
));
522 if (ioctl(sockf6
, SIOCGIFNETMASK_IN6
, &ifr6
) < 0) goto gotError
;
523 ifi
->ifi_netmask
= (struct sockaddr
*)calloc(1, sizeof(struct sockaddr_in6
));
524 if (ifi
->ifi_netmask
== NULL
) goto gotError
;
525 sinptr6
= (struct sockaddr_in6
*) &ifr6
.ifr_ifru
.ifru_addr
;
526 memcpy(ifi
->ifi_netmask
, sinptr6
, sizeof(struct sockaddr_in6
));
540 if (ifihead
!= NULL
) {
541 free_ifi_info(ifihead
);
550 junk
= close(sockfd
);
554 junk
= close(sockf6
);
557 return(ifihead
); /* pointer to first structure in linked list */
559 /* end get_ifi_info3 */
561 /* include free_ifi_info */
563 free_ifi_info(struct ifi_info
*ifihead
)
565 struct ifi_info
*ifi
, *ifinext
;
567 for (ifi
= ifihead
; ifi
!= NULL
; ifi
= ifinext
) {
568 if (ifi
->ifi_addr
!= NULL
)
570 if (ifi
->ifi_netmask
!= NULL
)
571 free(ifi
->ifi_netmask
);
572 if (ifi
->ifi_brdaddr
!= NULL
)
573 free(ifi
->ifi_brdaddr
);
574 if (ifi
->ifi_dstaddr
!= NULL
)
575 free(ifi
->ifi_dstaddr
);
576 ifinext
= ifi
->ifi_next
; /* can't fetch ifi_next after free() */
577 free(ifi
); /* the ifi_info{} itself */
580 /* end free_ifi_info */
583 recvfrom_flags(int fd
, void *ptr
, size_t nbytes
, int *flagsp
,
584 struct sockaddr
*sa
, socklen_t
*salenptr
, struct my_in_pktinfo
*pktp
, u_char
*ttl
)
591 struct cmsghdr
*cmptr
;
597 *ttl
= 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
599 msg
.msg_control
= control_un
.control
;
600 msg
.msg_controllen
= sizeof(control_un
.control
);
603 memset(&msg
, 0, sizeof(msg
)); /* make certain msg_accrightslen = 0 */
604 #endif /* CMSG_FIRSTHDR */
606 msg
.msg_name
= (char *) sa
;
607 msg
.msg_namelen
= *salenptr
;
608 iov
[0].iov_base
= (char *)ptr
;
609 iov
[0].iov_len
= nbytes
;
613 if ( (n
= recvmsg(fd
, &msg
, *flagsp
)) < 0)
616 *salenptr
= msg
.msg_namelen
; /* pass back results */
618 /* 0.0.0.0, i/f = -1 */
619 /* We set the interface to -1 so that the caller can
620 tell whether we returned a meaningful value or
621 just some default. Previously this code just
622 set the value to 0, but I'm concerned that 0
623 might be a valid interface value.
625 memset(pktp
, 0, sizeof(struct my_in_pktinfo
));
626 pktp
->ipi_ifindex
= -1;
628 /* end recvfrom_flags1 */
630 /* include recvfrom_flags2 */
631 #ifndef CMSG_FIRSTHDR
632 #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
633 *flagsp
= 0; /* pass back results */
637 *flagsp
= msg
.msg_flags
; /* pass back results */
638 if (msg
.msg_controllen
< (socklen_t
)sizeof(struct cmsghdr
) ||
639 (msg
.msg_flags
& MSG_CTRUNC
) || pktp
== NULL
)
642 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
!= NULL
;
643 cmptr
= CMSG_NXTHDR(&msg
, cmptr
)) {
646 #if in_pktinfo_definition_is_missing
650 struct in_addr ipi_spec_dst
;
651 struct in_addr ipi_addr
;
654 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
655 cmptr
->cmsg_type
== IP_PKTINFO
) {
656 struct in_pktinfo
*tmp
;
657 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&pktp
->ipi_addr
;
659 tmp
= (struct in_pktinfo
*) CMSG_DATA(cmptr
);
660 sin
->sin_family
= AF_INET
;
661 sin
->sin_addr
= tmp
->ipi_addr
;
663 pktp
->ipi_ifindex
= tmp
->ipi_ifindex
;
668 #ifdef IP_RECVDSTADDR
669 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
670 cmptr
->cmsg_type
== IP_RECVDSTADDR
) {
671 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&pktp
->ipi_addr
;
673 sin
->sin_family
= AF_INET
;
674 sin
->sin_addr
= *(struct in_addr
*)CMSG_DATA(cmptr
);
681 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
682 cmptr
->cmsg_type
== IP_RECVIF
) {
683 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*) CMSG_DATA(cmptr
);
684 #ifndef HAVE_BROKEN_RECVIF_NAME
685 int nameLen
= (sdl
->sdl_nlen
< IFI_NAME
- 1) ? sdl
->sdl_nlen
: (IFI_NAME
- 1);
686 strncpy(pktp
->ipi_ifname
, sdl
->sdl_data
, nameLen
);
688 pktp
->ipi_ifindex
= sdl
->sdl_index
;
689 #ifdef HAVE_BROKEN_RECVIF_NAME
690 if (sdl
->sdl_index
== 0) {
691 pktp
->ipi_ifindex
= *(uint_t
*)sdl
;
694 assert(pktp
->ipi_ifname
[IFI_NAME
- 1] == 0);
695 // null terminated because of memset above
701 if (cmptr
->cmsg_level
== IPPROTO_IP
&&
702 cmptr
->cmsg_type
== IP_RECVTTL
) {
703 *ttl
= *(u_char
*)CMSG_DATA(cmptr
);
706 else if (cmptr
->cmsg_level
== IPPROTO_IP
&&
707 cmptr
->cmsg_type
== IP_TTL
) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
708 *ttl
= *(int*)CMSG_DATA(cmptr
);
713 #if defined(IPV6_PKTINFO) && HAVE_IPV6
714 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&&
715 cmptr
->cmsg_type
== IPV6_PKTINFO
) {
716 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&pktp
->ipi_addr
;
717 struct in6_pktinfo
*ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmptr
);
719 sin6
->sin6_family
= AF_INET6
;
720 #ifndef NOT_HAVE_SA_LEN
721 sin6
->sin6_len
= sizeof(*sin6
);
723 sin6
->sin6_addr
= ip6_info
->ipi6_addr
;
724 sin6
->sin6_flowinfo
= 0;
725 sin6
->sin6_scope_id
= 0;
727 pktp
->ipi_ifindex
= ip6_info
->ipi6_ifindex
;
732 #if defined(IPV6_HOPLIMIT) && HAVE_IPV6
733 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&&
734 cmptr
->cmsg_type
== IPV6_HOPLIMIT
) {
735 *ttl
= *(int*)CMSG_DATA(cmptr
);
739 assert(0); // unknown ancillary data
742 #endif /* CMSG_FIRSTHDR */
745 // **********************************************************************************************
747 // daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
748 // Returns 0 on success, -1 on failure.
750 #ifdef NOT_HAVE_DAEMON
752 #include <sys/stat.h>
753 #include <sys/signal.h>
755 int daemon(int nochdir
, int noclose
)
759 case -1: return (-1); // Fork failed
760 case 0: break; // Child -- continue
761 default: _exit(0); // Parent -- exit
764 if (setsid() == -1) return(-1);
766 signal(SIGHUP
, SIG_IGN
);
768 switch (fork()) // Fork again, primarily for reasons of Unix trivia
770 case -1: return (-1); // Fork failed
771 case 0: break; // Child -- continue
772 default: _exit(0); // Parent -- exit
775 if (!nochdir
) (void)chdir("/");
780 int fd
= open("/dev/null", O_RDWR
, 0);
783 // Avoid unnecessarily duplicating a file descriptor to itself
784 if (fd
!= STDIN_FILENO
) (void)dup2(fd
, STDIN_FILENO
);
785 if (fd
!= STDOUT_FILENO
) (void)dup2(fd
, STDOUT_FILENO
);
786 if (fd
!= STDERR_FILENO
) (void)dup2(fd
, STDERR_FILENO
);
787 if (fd
!= STDIN_FILENO
&& fd
!= STDOUT_FILENO
&& fd
!= STDERR_FILENO
)
793 #endif /* NOT_HAVE_DAEMON */