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