Home | History | Annotate | Download | only in mDNSPosix
      1 /* -*- Mode: C; tab-width: 4 -*-
      2  *
      3  * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
      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  */
     17 
     18 #include "mDNSUNP.h"
     19 
     20 #include <errno.h>
     21 #include <assert.h>
     22 #include <string.h>
     23 #include <stdlib.h>
     24 #include <sys/uio.h>
     25 #include <sys/ioctl.h>
     26 #include <signal.h>
     27 #include <unistd.h>
     28 #include <stdio.h>
     29 
     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.
     34 */
     35 #ifdef NEED_ALIGN_MACRO
     36 #include NEED_ALIGN_MACRO
     37 #endif
     38 
     39 /* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
     40    other platforms don't even have that include file.  So,
     41    if we haven't yet got a definition, let's try to find
     42    <sys/sockio.h>.
     43 */
     44 
     45 #ifndef SIOCGIFCONF
     46     #include <sys/sockio.h>
     47 #endif
     48 
     49 /* sockaddr_dl is only referenced if we're using IP_RECVIF,
     50    so only include the header in that case.
     51 */
     52 
     53 #ifdef  IP_RECVIF
     54     #include <net/if_dl.h>
     55 #endif
     56 
     57 #if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
     58 #include <net/if_var.h>
     59 #include <netinet/in_var.h>
     60 // Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
     61 #endif
     62 
     63 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
     64 #include <netdb.h>
     65 #include <arpa/inet.h>
     66 
     67 /* Converts a prefix length to IPv6 network mask */
     68 void plen_to_mask(int plen, char *addr) {
     69 	int i;
     70 	int colons=7; /* Number of colons in IPv6 address */
     71 	int bits_in_block=16; /* Bits per IPv6 block */
     72 	for(i=0;i<=colons;i++) {
     73 		int block, ones=0xffff, ones_in_block;
     74 		if (plen>bits_in_block) ones_in_block=bits_in_block;
     75 		else                    ones_in_block=plen;
     76 		block = ones & (ones << (bits_in_block-ones_in_block));
     77 		i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
     78 		plen -= ones_in_block;
     79 		}
     80 	}
     81 
     82 /* Gets IPv6 interface information from the /proc filesystem in linux*/
     83 struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
     84 	{
     85 		struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
     86 	FILE *fp = NULL;
     87 	char addr[8][5];
     88 	int flags, myflags, index, plen, scope;
     89 	char ifname[IFNAMSIZ], lastname[IFNAMSIZ];
     90 	char addr6[32+7+1]; /* don't forget the seven ':' */
     91 	struct addrinfo hints, *res0;
     92 	struct sockaddr_in6 *sin6;
     93 	struct in6_addr *addrptr;
     94 	int err;
     95 	int sockfd = -1;
     96 	struct ifreq ifr;
     97 
     98 	res0=NULL;
     99 	ifihead = NULL;
    100 	ifipnext = &ifihead;
    101 	lastname[0] = 0;
    102 
    103 	if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
    104 		sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
    105 		if (sockfd < 0) {
    106 			goto gotError;
    107 		}
    108 		while (fscanf(fp,
    109 					  "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %15s\n",
    110 					  addr[0],addr[1],addr[2],addr[3],
    111 					  addr[4],addr[5],addr[6],addr[7],
    112 					  &index, &plen, &scope, &flags, ifname) != EOF) {
    113 
    114 			myflags = 0;
    115 			if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
    116 				if (doaliases == 0)
    117 					continue;   /* already processed this interface */
    118 				myflags = IFI_ALIAS;
    119 				}
    120 			strncpy(lastname, ifname, IFNAMSIZ);
    121 			ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
    122 			if (ifi == NULL) {
    123 				goto gotError;
    124 			}
    125 
    126 			ifipold   = *ifipnext;       /* need this later */
    127 			ifiptr    = ifipnext;
    128 			*ifipnext = ifi;            /* prev points to this new one */
    129 			ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
    130 
    131 			sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
    132 					addr[0],addr[1],addr[2],addr[3],
    133 					addr[4],addr[5],addr[6],addr[7]);
    134 
    135 			/* Add address of the interface */
    136 			memset(&hints, 0, sizeof(hints));
    137 			hints.ai_family = AF_INET6;
    138 			hints.ai_flags = AI_NUMERICHOST;
    139 			err = getaddrinfo(addr6, NULL, &hints, &res0);
    140 			if (err) {
    141 				goto gotError;
    142 				}
    143 			ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
    144 			if (ifi->ifi_addr == NULL) {
    145 				goto gotError;
    146 				}
    147 			memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
    148 
    149 			/* Add netmask of the interface */
    150 			char ipv6addr[INET6_ADDRSTRLEN];
    151 			plen_to_mask(plen, ipv6addr);
    152 			ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
    153 			if (ifi->ifi_addr == NULL) {
    154 				goto gotError;
    155 				}
    156 			sin6=calloc(1, sizeof(struct sockaddr_in6));
    157 			addrptr=calloc(1, sizeof(struct in6_addr));
    158 			inet_pton(family, ipv6addr, addrptr);
    159 			sin6->sin6_family=family;
    160 			sin6->sin6_addr=*addrptr;
    161 			sin6->sin6_scope_id=scope;
    162 			memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
    163 			free(sin6);
    164 
    165 
    166 			/* Add interface name */
    167 			strncpy(ifi->ifi_name, ifname, IFI_NAME);
    168 
    169 			/* Add interface index */
    170 			ifi->ifi_index = index;
    171 
    172 			/* Add interface flags*/
    173 			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    174 			if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
    175 				if (errno == EADDRNOTAVAIL) {
    176 					/*
    177 					 * If the main interface is configured with no IP address but
    178 					 * an alias interface exists with an IP address, you get
    179 					 * EADDRNOTAVAIL for the main interface
    180 					 */
    181 					free(ifi->ifi_addr);
    182 					free(ifi);
    183 					ifipnext  = ifiptr;
    184 					*ifipnext = ifipold;
    185 					continue;
    186 				} else {
    187 					goto gotError;
    188 				}
    189 			}
    190 			ifi->ifi_flags = ifr.ifr_flags;
    191 			freeaddrinfo(res0);
    192 			res0=NULL;
    193 			}
    194 		}
    195 	goto done;
    196 
    197 	gotError:
    198 	if (ifihead != NULL) {
    199 		free_ifi_info(ifihead);
    200 		ifihead = NULL;
    201 		}
    202 	if (res0 != NULL) {
    203 		freeaddrinfo(res0);
    204 		res0=NULL;
    205 		}
    206 	done:
    207 	if (sockfd != -1) {
    208 // __ANDROID__ : replaced assert(close(..))
    209 		int sockfd_closed = close(sockfd);
    210 		assert(sockfd_closed == 0);
    211 		}
    212 // __ANDROID__ : if fp was opened, it needs to be closed
    213 	if (fp != NULL) {
    214 		int fd_closed = fclose(fp);
    215 		assert(fd_closed == 0);
    216 		}
    217 	return(ifihead);    /* pointer to first structure in linked list */
    218 	}
    219 #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
    220 
    221 struct ifi_info *get_ifi_info(int family, int doaliases)
    222 {
    223     int                 junk;
    224     struct ifi_info     *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
    225     int                 sockfd, sockf6, len, lastlen, flags, myflags;
    226 #ifdef NOT_HAVE_IF_NAMETOINDEX
    227     int                 index = 200;
    228 #endif
    229     char                *ptr, *buf, lastname[IFNAMSIZ], *cptr;
    230     struct ifconf       ifc;
    231     struct ifreq        *ifr, ifrcopy;
    232     struct sockaddr_in  *sinptr;
    233 
    234 #if defined(AF_INET6) && HAVE_IPV6
    235     struct sockaddr_in6 *sinptr6;
    236 #endif
    237 
    238 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
    239  if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
    240 #endif
    241 
    242 	sockfd = -1;
    243     sockf6 = -1;
    244     buf = NULL;
    245     ifihead = NULL;
    246 
    247     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    248     if (sockfd < 0) {
    249         goto gotError;
    250     }
    251 
    252     lastlen = 0;
    253     len = 100 * sizeof(struct ifreq);   /* initial buffer size guess */
    254     for ( ; ; ) {
    255         buf = (char*)malloc(len);
    256         if (buf == NULL) {
    257             goto gotError;
    258         }
    259         ifc.ifc_len = len;
    260         ifc.ifc_buf = buf;
    261         if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
    262             if (errno != EINVAL || lastlen != 0) {
    263                 goto gotError;
    264             }
    265         } else {
    266             if (ifc.ifc_len == lastlen)
    267                 break;      /* success, len has not changed */
    268             lastlen = ifc.ifc_len;
    269         }
    270         len += 10 * sizeof(struct ifreq);   /* increment */
    271         free(buf);
    272     }
    273     ifihead = NULL;
    274     ifipnext = &ifihead;
    275     lastname[0] = 0;
    276 /* end get_ifi_info1 */
    277 
    278 /* include get_ifi_info2 */
    279     for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
    280         ifr = (struct ifreq *) ptr;
    281 
    282         /* Advance to next one in buffer */
    283         if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
    284             ptr += sizeof(struct ifreq);
    285         else
    286             ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
    287 
    288 //      fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
    289 
    290         if (ifr->ifr_addr.sa_family != family)
    291             continue;   /* ignore if not desired address family */
    292 
    293         myflags = 0;
    294         if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
    295             *cptr = 0;      /* replace colon will null */
    296         if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
    297             if (doaliases == 0)
    298                 continue;   /* already processed this interface */
    299             myflags = IFI_ALIAS;
    300         }
    301         memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
    302 
    303         ifrcopy = *ifr;
    304         if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
    305             goto gotError;
    306         }
    307 
    308         flags = ifrcopy.ifr_flags;
    309         if ((flags & IFF_UP) == 0)
    310             continue;   /* ignore if interface not up */
    311 
    312         ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
    313         if (ifi == NULL) {
    314             goto gotError;
    315         }
    316 		ifipold   = *ifipnext;       /* need this later */
    317 		ifiptr    = ifipnext;
    318 		*ifipnext = ifi;             /* prev points to this new one */
    319 		ifipnext  = &ifi->ifi_next;  /* pointer to next one goes here */
    320 
    321         ifi->ifi_flags = flags;     /* IFF_xxx values */
    322         ifi->ifi_myflags = myflags; /* IFI_xxx values */
    323 #ifndef NOT_HAVE_IF_NAMETOINDEX
    324         ifi->ifi_index = if_nametoindex(ifr->ifr_name);
    325 #else
    326         ifrcopy = *ifr;
    327 #ifdef SIOCGIFINDEX
    328 		if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
    329             ifi->ifi_index = ifrcopy.ifr_index;
    330         else
    331 #endif
    332             ifi->ifi_index = index++;	/* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
    333 #endif
    334         memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
    335         ifi->ifi_name[IFI_NAME-1] = '\0';
    336 /* end get_ifi_info2 */
    337 /* include get_ifi_info3 */
    338         switch (ifr->ifr_addr.sa_family) {
    339         case AF_INET:
    340             sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
    341             if (ifi->ifi_addr == NULL) {
    342                 ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
    343                 if (ifi->ifi_addr == NULL) {
    344                     goto gotError;
    345                 }
    346                 memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
    347 
    348 #ifdef  SIOCGIFNETMASK
    349 				if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
    350 					if (errno == EADDRNOTAVAIL) {
    351 						/*
    352 						 * If the main interface is configured with no IP address but
    353 						 * an alias interface exists with an IP address, you get
    354 						 * EADDRNOTAVAIL for the main interface
    355 						 */
    356 						free(ifi->ifi_addr);
    357 						free(ifi);
    358 						ifipnext  = ifiptr;
    359 						*ifipnext = ifipold;
    360 						continue;
    361 					} else {
    362 						goto gotError;
    363 					}
    364 				}
    365 
    366 				ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
    367 				if (ifi->ifi_netmask == NULL) goto gotError;
    368 				sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
    369 				/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
    370 #ifndef NOT_HAVE_SA_LEN
    371 				sinptr->sin_len    = sizeof(struct sockaddr_in);
    372 #endif
    373 				sinptr->sin_family = AF_INET;
    374 				memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
    375 #endif
    376 
    377 #ifdef  SIOCGIFBRDADDR
    378                 if (flags & IFF_BROADCAST) {
    379                     if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
    380                         goto gotError;
    381                     }
    382                     sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
    383 					/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
    384 #ifndef NOT_HAVE_SA_LEN
    385 					sinptr->sin_len    = sizeof( struct sockaddr_in );
    386 #endif
    387 					sinptr->sin_family = AF_INET;
    388                     ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
    389                     if (ifi->ifi_brdaddr == NULL) {
    390                         goto gotError;
    391                     }
    392                     memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
    393                 }
    394 #endif
    395 
    396 #ifdef  SIOCGIFDSTADDR
    397                 if (flags & IFF_POINTOPOINT) {
    398                     if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
    399                         goto gotError;
    400                     }
    401                     sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
    402                     /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
    403 #ifndef NOT_HAVE_SA_LEN
    404 					sinptr->sin_len    = sizeof( struct sockaddr_in );
    405 #endif
    406 					sinptr->sin_family = AF_INET;
    407                     ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
    408                     if (ifi->ifi_dstaddr == NULL) {
    409                         goto gotError;
    410                     }
    411                     memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
    412                 }
    413 #endif
    414             }
    415             break;
    416 
    417 #if defined(AF_INET6) && HAVE_IPV6
    418         case AF_INET6:
    419             sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
    420             if (ifi->ifi_addr == NULL) {
    421                 ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
    422                 if (ifi->ifi_addr == NULL) {
    423                     goto gotError;
    424                 }
    425 
    426                 /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
    427                 /* We need to strip that out */
    428                 if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
    429                 	sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
    430                 memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
    431 
    432 #ifdef  SIOCGIFNETMASK_IN6
    433 				{
    434 				struct in6_ifreq ifr6;
    435 				if (sockf6 == -1)
    436 					sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
    437 				memset(&ifr6, 0, sizeof(ifr6));
    438 				memcpy(&ifr6.ifr_name,           &ifr->ifr_name, sizeof(ifr6.ifr_name          ));
    439 				memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
    440 				if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
    441 					if (errno == EADDRNOTAVAIL) {
    442 						/*
    443 						 * If the main interface is configured with no IP address but
    444 						 * an alias interface exists with an IP address, you get
    445 						 * EADDRNOTAVAIL for the main interface
    446 						 */
    447 						free(ifi->ifi_addr);
    448 						free(ifi);
    449 						ifipnext  = ifiptr;
    450 						*ifipnext = ifipold;
    451 						continue;
    452 					} else {
    453 						goto gotError;
    454 					}
    455 				}
    456 				ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
    457 				if (ifi->ifi_netmask == NULL) goto gotError;
    458 				sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
    459 				memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
    460 				}
    461 #endif
    462             }
    463             break;
    464 #endif
    465 
    466         default:
    467             break;
    468         }
    469     }
    470     goto done;
    471 
    472 gotError:
    473     if (ifihead != NULL) {
    474         free_ifi_info(ifihead);
    475         ifihead = NULL;
    476     }
    477 
    478 done:
    479     if (buf != NULL) {
    480         free(buf);
    481     }
    482     if (sockfd != -1) {
    483         junk = close(sockfd);
    484         assert(junk == 0);
    485     }
    486     if (sockf6 != -1) {
    487         junk = close(sockf6);
    488         assert(junk == 0);
    489     }
    490     return(ifihead);    /* pointer to first structure in linked list */
    491 }
    492 /* end get_ifi_info3 */
    493 
    494 /* include free_ifi_info */
    495 void
    496 free_ifi_info(struct ifi_info *ifihead)
    497 {
    498     struct ifi_info *ifi, *ifinext;
    499 
    500     for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
    501         if (ifi->ifi_addr != NULL)
    502             free(ifi->ifi_addr);
    503         if (ifi->ifi_netmask != NULL)
    504             free(ifi->ifi_netmask);
    505         if (ifi->ifi_brdaddr != NULL)
    506             free(ifi->ifi_brdaddr);
    507         if (ifi->ifi_dstaddr != NULL)
    508             free(ifi->ifi_dstaddr);
    509         ifinext = ifi->ifi_next;    /* can't fetch ifi_next after free() */
    510         free(ifi);                  /* the ifi_info{} itself */
    511     }
    512 }
    513 /* end free_ifi_info */
    514 
    515 ssize_t
    516 recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
    517                struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
    518 {
    519     struct msghdr   msg;
    520     struct iovec    iov[1];
    521     ssize_t         n;
    522 
    523 #ifdef CMSG_FIRSTHDR
    524     struct cmsghdr  *cmptr;
    525     union {
    526       struct cmsghdr    cm;
    527       char              control[1024];
    528     } control_un;
    529 
    530 	*ttl = 255;			// If kernel fails to provide TTL data then assume the TTL was 255 as it should be
    531 
    532     msg.msg_control = control_un.control;
    533     msg.msg_controllen = sizeof(control_un.control);
    534     msg.msg_flags = 0;
    535 #else
    536     memset(&msg, 0, sizeof(msg));   /* make certain msg_accrightslen = 0 */
    537 #endif /* CMSG_FIRSTHDR */
    538 
    539     msg.msg_name = (char *) sa;
    540     msg.msg_namelen = *salenptr;
    541     iov[0].iov_base = (char *)ptr;
    542     iov[0].iov_len = nbytes;
    543     msg.msg_iov = iov;
    544     msg.msg_iovlen = 1;
    545 
    546     if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
    547         return(n);
    548 
    549     *salenptr = msg.msg_namelen;    /* pass back results */
    550     if (pktp) {
    551         /* 0.0.0.0, i/f = -1 */
    552         /* We set the interface to -1 so that the caller can
    553            tell whether we returned a meaningful value or
    554            just some default.  Previously this code just
    555            set the value to 0, but I'm concerned that 0
    556            might be a valid interface value.
    557         */
    558         memset(pktp, 0, sizeof(struct my_in_pktinfo));
    559         pktp->ipi_ifindex = -1;
    560     }
    561 /* end recvfrom_flags1 */
    562 
    563 /* include recvfrom_flags2 */
    564 #ifndef CMSG_FIRSTHDR
    565 	#warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
    566     *flagsp = 0;                    /* pass back results */
    567     return(n);
    568 #else
    569 
    570     *flagsp = msg.msg_flags;        /* pass back results */
    571     if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
    572         (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
    573         return(n);
    574 
    575     for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
    576          cmptr = CMSG_NXTHDR(&msg, cmptr)) {
    577 
    578 #ifdef  IP_PKTINFO
    579 #if in_pktinfo_definition_is_missing
    580 struct in_pktinfo
    581 {
    582         int             ipi_ifindex;
    583         struct in_addr  ipi_spec_dst;
    584         struct in_addr  ipi_addr;
    585 };
    586 #endif
    587         if (cmptr->cmsg_level == IPPROTO_IP &&
    588             cmptr->cmsg_type == IP_PKTINFO) {
    589             struct in_pktinfo *tmp;
    590             struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
    591 
    592             tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
    593             sin->sin_family = AF_INET;
    594             sin->sin_addr = tmp->ipi_addr;
    595             sin->sin_port = 0;
    596             pktp->ipi_ifindex = tmp->ipi_ifindex;
    597             continue;
    598         }
    599 #endif
    600 
    601 #ifdef  IP_RECVDSTADDR
    602         if (cmptr->cmsg_level == IPPROTO_IP &&
    603             cmptr->cmsg_type == IP_RECVDSTADDR) {
    604             struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
    605 
    606             sin->sin_family = AF_INET;
    607             sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
    608             sin->sin_port = 0;
    609             continue;
    610         }
    611 #endif
    612 
    613 #ifdef  IP_RECVIF
    614         if (cmptr->cmsg_level == IPPROTO_IP &&
    615             cmptr->cmsg_type == IP_RECVIF) {
    616             struct sockaddr_dl  *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
    617 #ifndef HAVE_BROKEN_RECVIF_NAME
    618             int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
    619             strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
    620 #endif
    621             pktp->ipi_ifindex = sdl->sdl_index;
    622 #ifdef HAVE_BROKEN_RECVIF_NAME
    623 			if (sdl->sdl_index == 0) {
    624 				pktp->ipi_ifindex = *(uint_t*)sdl;
    625 			}
    626 #endif
    627             assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
    628             // null terminated because of memset above
    629             continue;
    630         }
    631 #endif
    632 
    633 #ifdef  IP_RECVTTL
    634         if (cmptr->cmsg_level == IPPROTO_IP &&
    635             cmptr->cmsg_type == IP_RECVTTL) {
    636 			*ttl = *(u_char*)CMSG_DATA(cmptr);
    637             continue;
    638         }
    639         else if (cmptr->cmsg_level == IPPROTO_IP &&
    640             cmptr->cmsg_type == IP_TTL) {		// some implementations seem to send IP_TTL instead of IP_RECVTTL
    641 			*ttl = *(int*)CMSG_DATA(cmptr);
    642             continue;
    643         }
    644 #endif
    645 
    646 #if defined(IPV6_PKTINFO) && HAVE_IPV6
    647 		if (cmptr->cmsg_level == IPPROTO_IPV6 &&
    648             cmptr->cmsg_type  == IPV6_2292_PKTINFO) {
    649             struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
    650 			struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
    651 
    652             sin6->sin6_family   = AF_INET6;
    653 #ifndef NOT_HAVE_SA_LEN
    654             sin6->sin6_len      = sizeof(*sin6);
    655 #endif
    656             sin6->sin6_addr     = ip6_info->ipi6_addr;
    657             sin6->sin6_flowinfo = 0;
    658             sin6->sin6_scope_id = 0;
    659             sin6->sin6_port     = 0;
    660 			pktp->ipi_ifindex   = ip6_info->ipi6_ifindex;
    661             continue;
    662         }
    663 #endif
    664 
    665 #if defined(IPV6_HOPLIMIT) && HAVE_IPV6
    666         if (cmptr->cmsg_level == IPPROTO_IPV6 &&
    667             cmptr->cmsg_type == IPV6_2292_HOPLIMIT) {
    668 			*ttl = *(int*)CMSG_DATA(cmptr);
    669             continue;
    670         }
    671 #endif
    672         assert(0);  // unknown ancillary data
    673     }
    674     return(n);
    675 #endif /* CMSG_FIRSTHDR */
    676 }
    677 
    678 // **********************************************************************************************
    679 
    680 // daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
    681 // Returns 0 on success, -1 on failure.
    682 
    683 #ifdef NOT_HAVE_DAEMON
    684 #include <fcntl.h>
    685 #include <sys/stat.h>
    686 #include <sys/signal.h>
    687 
    688 int daemon(int nochdir, int noclose)
    689     {
    690 	switch (fork())
    691 		{
    692 		case -1: return (-1);	// Fork failed
    693 		case 0: break;		// Child -- continue
    694 		default: _exit(0);	// Parent -- exit
    695 		}
    696 
    697 	if (setsid() == -1) return(-1);
    698 
    699 	signal(SIGHUP, SIG_IGN);
    700 
    701 	switch (fork())				// Fork again, primarily for reasons of Unix trivia
    702 		{
    703 		case -1: return (-1);	// Fork failed
    704 		case 0:  break;			// Child -- continue
    705 		default: _exit(0);		// Parent -- exit
    706 		}
    707 
    708 	if (!nochdir) (void)chdir("/");
    709 	umask(0);
    710 
    711 	if (!noclose)
    712 		{
    713 		int fd = open("/dev/null", O_RDWR, 0);
    714 		if (fd != -1)
    715 			{
    716 			// Avoid unnecessarily duplicating a file descriptor to itself
    717 			if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
    718 			if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
    719 			if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
    720 			if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
    721 				(void)close (fd);
    722 			}
    723 		}
    724 	return (0);
    725     }
    726 #endif /* NOT_HAVE_DAEMON */
    727