147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* -*- Mode: C; tab-width: 4 -*-
247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * you may not use this file except in compliance with the License.
747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * You may obtain a copy of the License at
847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *     http://www.apache.org/licenses/LICENSE-2.0
1047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *
1147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
1247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
1347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * See the License for the specific language governing permissions and
1547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * limitations under the License.
1647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
1747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
1847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSUNP.h"
1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h>
2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <assert.h>
2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h>
2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdlib.h>
2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/uio.h>
2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/ioctl.h>
2647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <signal.h>
2747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <unistd.h>
2847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdio.h>
2947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
3047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
3147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   macro, usually defined in <sys/param.h> or someplace like that, to make sure the
3247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
3347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   should be set to the name of the header to include to get the ALIGN(P) macro.
3447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt*/
3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef NEED_ALIGN_MACRO
3647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include NEED_ALIGN_MACRO
3747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
3847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
3947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
4047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   other platforms don't even have that include file.  So,
4147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   if we haven't yet got a definition, let's try to find
4247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   <sys/sockio.h>.
4347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt*/
4447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
4547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef SIOCGIFCONF
4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    #include <sys/sockio.h>
4747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* sockaddr_dl is only referenced if we're using IP_RECVIF,
5047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt   so only include the header in that case.
5147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt*/
5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  IP_RECVIF
5447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    #include <net/if_dl.h>
5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <net/if_var.h>
5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in_var.h>
6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netdb.h>
6547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/inet.h>
6647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* Converts a prefix length to IPv6 network mask */
6847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid plen_to_mask(int plen, char *addr) {
6947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
7047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int colons=7; /* Number of colons in IPv6 address */
7147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int bits_in_block=16; /* Bits per IPv6 block */
7247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for(i=0;i<=colons;i++) {
7347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int block, ones=0xffff, ones_in_block;
7447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (plen>bits_in_block) ones_in_block=bits_in_block;
7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else                    ones_in_block=plen;
7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		block = ones & (ones << (bits_in_block-ones_in_block));
7747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
7847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		plen -= ones_in_block;
7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* Gets IPv6 interface information from the /proc filesystem in linux*/
8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstruct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
8654bbef089d469dba7032c9cefa703647a0e917f1Dave Platt	FILE *fp = NULL;
8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char addr[8][5];
8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int flags, myflags, index, plen, scope;
8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char ifname[9], lastname[IFNAMSIZ];
9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char addr6[32+7+1]; /* don't forget the seven ':' */
9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct addrinfo hints, *res0;
9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct sockaddr_in6 *sin6;
9347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct in6_addr *addrptr;
9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err;
9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int sockfd = -1;
9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct ifreq ifr;
9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	res0=NULL;
9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ifihead = NULL;
10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ifipnext = &ifihead;
10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	lastname[0] = 0;
10247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (sockfd < 0) {
10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			goto gotError;
10747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		while (fscanf(fp,
10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					  "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					  addr[0],addr[1],addr[2],addr[3],
11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					  addr[4],addr[5],addr[6],addr[7],
11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					  &index, &plen, &scope, &flags, ifname) != EOF) {
11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			myflags = 0;
11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (doaliases == 0)
11747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					continue;   /* already processed this interface */
11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				myflags = IFI_ALIAS;
11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
1208d61c6ee30ea24755dfd111fb497c0533c0ff461Nick Kralevich			strncpy(lastname, ifname, IFNAMSIZ);
12147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ifi == NULL) {
12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				goto gotError;
12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifipold   = *ifipnext;       /* need this later */
12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifiptr    = ifipnext;
12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			*ifipnext = ifi;            /* prev points to this new one */
12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
13147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					addr[0],addr[1],addr[2],addr[3],
13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					addr[4],addr[5],addr[6],addr[7]);
13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			/* Add address of the interface */
13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			memset(&hints, 0, sizeof(hints));
13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			hints.ai_family = AF_INET6;
13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			hints.ai_flags = AI_NUMERICHOST;
13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			err = getaddrinfo(addr6, NULL, &hints, &res0);
14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (err) {
14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				goto gotError;
14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ifi->ifi_addr == NULL) {
14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				goto gotError;
14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
14947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			/* Add netmask of the interface */
15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			char ipv6addr[INET6_ADDRSTRLEN];
15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			plen_to_mask(plen, ipv6addr);
15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ifi->ifi_addr == NULL) {
15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				goto gotError;
15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			sin6=calloc(1, sizeof(struct sockaddr_in6));
15747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			addrptr=calloc(1, sizeof(struct in6_addr));
15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			inet_pton(family, ipv6addr, addrptr);
15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			sin6->sin6_family=family;
16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			sin6->sin6_addr=*addrptr;
16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			sin6->sin6_scope_id=scope;
16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
16347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			free(sin6);
16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
16547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			/* Add interface name */
1678d61c6ee30ea24755dfd111fb497c0533c0ff461Nick Kralevich			strncpy(ifi->ifi_name, ifname, IFI_NAME);
16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			/* Add interface index */
17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifi->ifi_index = index;
17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			/* Add interface flags*/
1738d61c6ee30ea24755dfd111fb497c0533c0ff461Nick Kralevich			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
17547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (errno == EADDRNOTAVAIL) {
17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					/*
17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					 * If the main interface is configured with no IP address but
17847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					 * an alias interface exists with an IP address, you get
17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					 * EADDRNOTAVAIL for the main interface
18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					 */
18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					free(ifi->ifi_addr);
18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					free(ifi);
18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					ifipnext  = ifiptr;
18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					*ifipnext = ifipold;
18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					continue;
18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				} else {
18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					goto gotError;
18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			ifi->ifi_flags = ifr.ifr_flags;
19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			freeaddrinfo(res0);
19247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			res0=NULL;
19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	goto done;
19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	gotError:
19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (ifihead != NULL) {
19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		free_ifi_info(ifihead);
20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		ifihead = NULL;
20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (res0 != NULL) {
20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		freeaddrinfo(res0);
20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		res0=NULL;
20547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	done:
20747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (sockfd != -1) {
208f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt// __ANDROID__ : replaced assert(close(..))
209f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		int sockfd_closed = close(sockfd);
210f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt		assert(sockfd_closed == 0);
21154bbef089d469dba7032c9cefa703647a0e917f1Dave Platt		}
21254bbef089d469dba7032c9cefa703647a0e917f1Dave Platt// __ANDROID__ : if fp was opened, it needs to be closed
21354bbef089d469dba7032c9cefa703647a0e917f1Dave Platt	if (fp != NULL) {
21454bbef089d469dba7032c9cefa703647a0e917f1Dave Platt		int fd_closed = fclose(fp);
21554bbef089d469dba7032c9cefa703647a0e917f1Dave Platt		assert(fd_closed == 0);
21654bbef089d469dba7032c9cefa703647a0e917f1Dave Platt		}
21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return(ifihead);    /* pointer to first structure in linked list */
21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstruct ifi_info *get_ifi_info(int family, int doaliases)
22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    int                 junk;
22447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct ifi_info     *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    int                 sockfd, sockf6, len, lastlen, flags, myflags;
22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef NOT_HAVE_IF_NAMETOINDEX
22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    int                 index = 200;
22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    char                *ptr, *buf, lastname[IFNAMSIZ], *cptr;
23047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct ifconf       ifc;
23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct ifreq        *ifr, ifrcopy;
23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct sockaddr_in  *sinptr;
23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(AF_INET6) && HAVE_IPV6
23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct sockaddr_in6 *sinptr6;
23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
23747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
23847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sockfd = -1;
24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    sockf6 = -1;
24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    buf = NULL;
24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    ifihead = NULL;
24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (sockfd < 0) {
24947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        goto gotError;
25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    lastlen = 0;
25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    len = 100 * sizeof(struct ifreq);   /* initial buffer size guess */
25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    for ( ; ; ) {
25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        buf = (char*)malloc(len);
25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (buf == NULL) {
25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            goto gotError;
25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifc.ifc_len = len;
26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifc.ifc_buf = buf;
26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
26247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            if (errno != EINVAL || lastlen != 0) {
26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                goto gotError;
26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            }
26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        } else {
26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            if (ifc.ifc_len == lastlen)
26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                break;      /* success, len has not changed */
26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            lastlen = ifc.ifc_len;
26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
27047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        len += 10 * sizeof(struct ifreq);   /* increment */
27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        free(buf);
27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    ifihead = NULL;
27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    ifipnext = &ifihead;
27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    lastname[0] = 0;
27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* end get_ifi_info1 */
27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* include get_ifi_info2 */
27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifr = (struct ifreq *) ptr;
28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        /* Advance to next one in buffer */
28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            ptr += sizeof(struct ifreq);
28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        else
28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//      fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ifr->ifr_addr.sa_family != family)
29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;   /* ignore if not desired address family */
29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        myflags = 0;
29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            *cptr = 0;      /* replace colon will null */
29647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            if (doaliases == 0)
29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                continue;   /* already processed this interface */
29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            myflags = IFI_ALIAS;
30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
30147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
30247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
30347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifrcopy = *ifr;
30447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
30547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            goto gotError;
30647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
30747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
30847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        flags = ifrcopy.ifr_flags;
30947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if ((flags & IFF_UP) == 0)
31047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;   /* ignore if interface not up */
31147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
31247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
31347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ifi == NULL) {
31447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            goto gotError;
31547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
31647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		ifipold   = *ifipnext;       /* need this later */
31747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		ifiptr    = ifipnext;
31847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*ifipnext = ifi;             /* prev points to this new one */
31947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		ifipnext  = &ifi->ifi_next;  /* pointer to next one goes here */
32047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
32147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifi->ifi_flags = flags;     /* IFF_xxx values */
32247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifi->ifi_myflags = myflags; /* IFI_xxx values */
32347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_IF_NAMETOINDEX
32447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifi->ifi_index = if_nametoindex(ifr->ifr_name);
32547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else
32647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifrcopy = *ifr;
32747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef SIOCGIFINDEX
32847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
32947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            ifi->ifi_index = ifrcopy.ifr_index;
33047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        else
33147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
33247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            ifi->ifi_index = index++;	/* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
33347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
33447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
33547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifi->ifi_name[IFI_NAME-1] = '\0';
33647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* end get_ifi_info2 */
33747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* include get_ifi_info3 */
33847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        switch (ifr->ifr_addr.sa_family) {
33947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        case AF_INET:
34047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
34147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            if (ifi->ifi_addr == NULL) {
34247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
34347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                if (ifi->ifi_addr == NULL) {
34447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    goto gotError;
34547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                }
34647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
34747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
34847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  SIOCGIFNETMASK
34947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
35047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					if (errno == EADDRNOTAVAIL) {
35147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						/*
35247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 * If the main interface is configured with no IP address but
35347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 * an alias interface exists with an IP address, you get
35447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 * EADDRNOTAVAIL for the main interface
35547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 */
35647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						free(ifi->ifi_addr);
35747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						free(ifi);
35847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						ifipnext  = ifiptr;
35947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						*ifipnext = ifipold;
36047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						continue;
36147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					} else {
36247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						goto gotError;
36347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					}
36447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
36547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
36647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
36747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (ifi->ifi_netmask == NULL) goto gotError;
36847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
36947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
37047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
37147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				sinptr->sin_len    = sizeof(struct sockaddr_in);
37247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
37347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				sinptr->sin_family = AF_INET;
37447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
37547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
37647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
37747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  SIOCGIFBRDADDR
37847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                if (flags & IFF_BROADCAST) {
37947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
38047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                        goto gotError;
38147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    }
38247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
38347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					/* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
38447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
38547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					sinptr->sin_len    = sizeof( struct sockaddr_in );
38647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
38747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					sinptr->sin_family = AF_INET;
38847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
38947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    if (ifi->ifi_brdaddr == NULL) {
39047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                        goto gotError;
39147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    }
39247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
39347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                }
39447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
39547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
39647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  SIOCGIFDSTADDR
39747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                if (flags & IFF_POINTOPOINT) {
39847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
39947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                        goto gotError;
40047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    }
40147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
40247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
40347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
40447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					sinptr->sin_len    = sizeof( struct sockaddr_in );
40547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
40647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					sinptr->sin_family = AF_INET;
40747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
40847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    if (ifi->ifi_dstaddr == NULL) {
40947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                        goto gotError;
41047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    }
41147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
41247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                }
41347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
41447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            }
41547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            break;
41647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
41747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(AF_INET6) && HAVE_IPV6
41847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        case AF_INET6:
41947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
42047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            if (ifi->ifi_addr == NULL) {
42147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
42247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                if (ifi->ifi_addr == NULL) {
42347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                    goto gotError;
42447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                }
42547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
42647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
42747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                /* We need to strip that out */
42847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
42947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                	sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
43047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt                memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
43147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
43247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  SIOCGIFNETMASK_IN6
43347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
43447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				struct in6_ifreq ifr6;
43547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (sockf6 == -1)
43647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
43747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				memset(&ifr6, 0, sizeof(ifr6));
43847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				memcpy(&ifr6.ifr_name,           &ifr->ifr_name, sizeof(ifr6.ifr_name          ));
43947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
44047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
44147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					if (errno == EADDRNOTAVAIL) {
44247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						/*
44347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 * If the main interface is configured with no IP address but
44447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 * an alias interface exists with an IP address, you get
44547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 * EADDRNOTAVAIL for the main interface
44647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						 */
44747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						free(ifi->ifi_addr);
44847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						free(ifi);
44947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						ifipnext  = ifiptr;
45047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						*ifipnext = ifipold;
45147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						continue;
45247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					} else {
45347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						goto gotError;
45447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					}
45547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
45647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
45747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (ifi->ifi_netmask == NULL) goto gotError;
45847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
45947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
46047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
46147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
46247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            }
46347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            break;
46447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
46547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
46647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        default:
46747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            break;
46847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
46947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
47047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    goto done;
47147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
47247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltgotError:
47347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (ifihead != NULL) {
47447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        free_ifi_info(ifihead);
47547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifihead = NULL;
47647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
47747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
47847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltdone:
47947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (buf != NULL) {
48047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        free(buf);
48147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
48247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (sockfd != -1) {
48347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        junk = close(sockfd);
48447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        assert(junk == 0);
48547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
48647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (sockf6 != -1) {
48747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        junk = close(sockf6);
48847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        assert(junk == 0);
48947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
49047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    return(ifihead);    /* pointer to first structure in linked list */
49147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
49247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* end get_ifi_info3 */
49347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
49447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* include free_ifi_info */
49547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid
49647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltfree_ifi_info(struct ifi_info *ifihead)
49747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
49847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct ifi_info *ifi, *ifinext;
49947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
50047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
50147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ifi->ifi_addr != NULL)
50247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            free(ifi->ifi_addr);
50347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ifi->ifi_netmask != NULL)
50447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            free(ifi->ifi_netmask);
50547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ifi->ifi_brdaddr != NULL)
50647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            free(ifi->ifi_brdaddr);
50747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (ifi->ifi_dstaddr != NULL)
50847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            free(ifi->ifi_dstaddr);
50947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        ifinext = ifi->ifi_next;    /* can't fetch ifi_next after free() */
51047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        free(ifi);                  /* the ifi_info{} itself */
51147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
51247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
51347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* end free_ifi_info */
51447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
51547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltssize_t
51647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltrecvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
51747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt               struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
51847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
51947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct msghdr   msg;
52047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct iovec    iov[1];
52147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    ssize_t         n;
52247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
52347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef CMSG_FIRSTHDR
52447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    struct cmsghdr  *cmptr;
52547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    union {
52647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt      struct cmsghdr    cm;
52747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt      char              control[1024];
52847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    } control_un;
52947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*ttl = 255;			// If kernel fails to provide TTL data then assume the TTL was 255 as it should be
53147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_control = control_un.control;
53347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_controllen = sizeof(control_un.control);
53447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_flags = 0;
53547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else
53647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    memset(&msg, 0, sizeof(msg));   /* make certain msg_accrightslen = 0 */
53747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif /* CMSG_FIRSTHDR */
53847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_name = (char *) sa;
54047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_namelen = *salenptr;
54147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    iov[0].iov_base = (char *)ptr;
54247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    iov[0].iov_len = nbytes;
54347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_iov = iov;
54447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    msg.msg_iovlen = 1;
54547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
54647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
54747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        return(n);
54847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
54947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    *salenptr = msg.msg_namelen;    /* pass back results */
55047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (pktp) {
55147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        /* 0.0.0.0, i/f = -1 */
55247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        /* We set the interface to -1 so that the caller can
55347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt           tell whether we returned a meaningful value or
55447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt           just some default.  Previously this code just
55547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt           set the value to 0, but I'm concerned that 0
55647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt           might be a valid interface value.
55747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        */
55847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        memset(pktp, 0, sizeof(struct my_in_pktinfo));
55947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        pktp->ipi_ifindex = -1;
56047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
56147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* end recvfrom_flags1 */
56247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* include recvfrom_flags2 */
56447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef CMSG_FIRSTHDR
56547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	#warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
56647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    *flagsp = 0;                    /* pass back results */
56747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    return(n);
56847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else
56947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
57047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    *flagsp = msg.msg_flags;        /* pass back results */
57147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
57247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
57347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        return(n);
57447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
57547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
57647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt         cmptr = CMSG_NXTHDR(&msg, cmptr)) {
57747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
57847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  IP_PKTINFO
57947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if in_pktinfo_definition_is_missing
58047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstruct in_pktinfo
58147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
58247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        int             ipi_ifindex;
58347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        struct in_addr  ipi_spec_dst;
58447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        struct in_addr  ipi_addr;
58547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt};
58647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
58747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (cmptr->cmsg_level == IPPROTO_IP &&
58847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type == IP_PKTINFO) {
58947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            struct in_pktinfo *tmp;
59047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
59147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
59247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
59347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin->sin_family = AF_INET;
59447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin->sin_addr = tmp->ipi_addr;
59547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin->sin_port = 0;
59647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            pktp->ipi_ifindex = tmp->ipi_ifindex;
59747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
59847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
59947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
60047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
60147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  IP_RECVDSTADDR
60247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (cmptr->cmsg_level == IPPROTO_IP &&
60347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type == IP_RECVDSTADDR) {
60447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
60547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
60647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin->sin_family = AF_INET;
60747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
60847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin->sin_port = 0;
60947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
61047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
61147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
61247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
61347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  IP_RECVIF
61447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (cmptr->cmsg_level == IPPROTO_IP &&
61547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type == IP_RECVIF) {
61647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            struct sockaddr_dl  *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
61747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef HAVE_BROKEN_RECVIF_NAME
61847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
61947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
62047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
62147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            pktp->ipi_ifindex = sdl->sdl_index;
62247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef HAVE_BROKEN_RECVIF_NAME
62347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (sdl->sdl_index == 0) {
62447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				pktp->ipi_ifindex = *(uint_t*)sdl;
62547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
62647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
62747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
62847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            // null terminated because of memset above
62947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
63047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
63147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
63247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
63347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef  IP_RECVTTL
63447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (cmptr->cmsg_level == IPPROTO_IP &&
63547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type == IP_RECVTTL) {
63647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			*ttl = *(u_char*)CMSG_DATA(cmptr);
63747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
63847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
63947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        else if (cmptr->cmsg_level == IPPROTO_IP &&
64047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type == IP_TTL) {		// some implementations seem to send IP_TTL instead of IP_RECVTTL
64147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			*ttl = *(int*)CMSG_DATA(cmptr);
64247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
64347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
64447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
64547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
64647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(IPV6_PKTINFO) && HAVE_IPV6
64747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (cmptr->cmsg_level == IPPROTO_IPV6 &&
64847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type  == IPV6_2292_PKTINFO) {
64947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
65047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
65147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
65247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin6->sin6_family   = AF_INET6;
65347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifndef NOT_HAVE_SA_LEN
65447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin6->sin6_len      = sizeof(*sin6);
65547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
65647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin6->sin6_addr     = ip6_info->ipi6_addr;
65747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin6->sin6_flowinfo = 0;
65847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin6->sin6_scope_id = 0;
65947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            sin6->sin6_port     = 0;
66047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			pktp->ipi_ifindex   = ip6_info->ipi6_ifindex;
66147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
66247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
66347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
66447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
66547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
66647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        if (cmptr->cmsg_level == IPPROTO_IPV6 &&
66747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            cmptr->cmsg_type == IPV6_2292_HOPLIMIT) {
66847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			*ttl = *(int*)CMSG_DATA(cmptr);
66947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt            continue;
67047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        }
67147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
67247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt        assert(0);  // unknown ancillary data
67347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
67447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    return(n);
67547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif /* CMSG_FIRSTHDR */
67647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
67747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
67847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// **********************************************************************************************
67947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
68047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
68147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Returns 0 on success, -1 on failure.
68247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
68347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef NOT_HAVE_DAEMON
68447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <fcntl.h>
68547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/stat.h>
68647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/signal.h>
68747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
68847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint daemon(int nochdir, int noclose)
68947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    {
69047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (fork())
69147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
69247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		case -1: return (-1);	// Fork failed
693dd52342e088715929196886494c5055f9186d5c3Robert Greenwalt		case 0: break;		// Child -- continue
694dd52342e088715929196886494c5055f9186d5c3Robert Greenwalt		default: _exit(0);	// Parent -- exit
69547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
69647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
69747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (setsid() == -1) return(-1);
69847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
69947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	signal(SIGHUP, SIG_IGN);
70047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
70147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (fork())				// Fork again, primarily for reasons of Unix trivia
70247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
70347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		case -1: return (-1);	// Fork failed
70447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		case 0:  break;			// Child -- continue
70547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		default: _exit(0);		// Parent -- exit
70647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
70747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
70847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (!nochdir) (void)chdir("/");
70947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	umask(0);
71047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
71147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (!noclose)
71247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
71347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int fd = open("/dev/null", O_RDWR, 0);
71447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (fd != -1)
71547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
71647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Avoid unnecessarily duplicating a file descriptor to itself
71747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
71847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
71947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
72047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
72147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				(void)close (fd);
72247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
72347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
72447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return (0);
72547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt    }
72647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif /* NOT_HAVE_DAEMON */
727