• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
plen_to_mask(int plen,char * addr)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*/
get_ifi_info_linuxv6(int family,int doaliases)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[9], 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 %8s\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 
get_ifi_info(int family,int doaliases)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
free_ifi_info(struct ifi_info * ifihead)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
recvfrom_flags(int fd,void * ptr,size_t nbytes,int * flagsp,struct sockaddr * sa,socklen_t * salenptr,struct my_in_pktinfo * pktp,u_char * ttl)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 
daemon(int nochdir,int noclose)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