4b22b9337f359bfd063322244f5336cc7c6ffcfars/* -*- Mode: C; tab-width: 4 -*-
4b22b9337f359bfd063322244f5336cc7c6ffcfars *
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4b22b9337f359bfd063322244f5336cc7c6ffcfars *
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Licensed under the Apache License, Version 2.0 (the "License");
4b22b9337f359bfd063322244f5336cc7c6ffcfars * you may not use this file except in compliance with the License.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * You may obtain a copy of the License at
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *
4b22b9337f359bfd063322244f5336cc7c6ffcfars * http://www.apache.org/licenses/LICENSE-2.0
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Unless required by applicable law or agreed to in writing, software
4b22b9337f359bfd063322244f5336cc7c6ffcfars * distributed under the License is distributed on an "AS IS" BASIS,
4b22b9337f359bfd063322244f5336cc7c6ffcfars * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * See the License for the specific language governing permissions and
4b22b9337f359bfd063322244f5336cc7c6ffcfars * limitations under the License.
3ee6e1231b28188bebd1d5bb4a32a673f5820322Richard Lowe */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include "mDNSUNP.h"
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <errno.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <assert.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <string.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <stdlib.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <sys/uio.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <sys/ioctl.h>
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#include <signal.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <unistd.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <stdio.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
4b22b9337f359bfd063322244f5336cc7c6ffcfars macro, usually defined in <sys/param.h> or someplace like that, to make sure the
4b22b9337f359bfd063322244f5336cc7c6ffcfars CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
4b22b9337f359bfd063322244f5336cc7c6ffcfars should be set to the name of the header to include to get the ALIGN(P) macro.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef NEED_ALIGN_MACRO
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include NEED_ALIGN_MACRO
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome other platforms don't even have that include file. So,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if we haven't yet got a definition, let's try to find
4b22b9337f359bfd063322244f5336cc7c6ffcfars <sys/sockio.h>.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef SIOCGIFCONF
4b22b9337f359bfd063322244f5336cc7c6ffcfars #include <sys/sockio.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome/* sockaddr_dl is only referenced if we're using IP_RECVIF,
4b22b9337f359bfd063322244f5336cc7c6ffcfars so only include the header in that case.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef IP_RECVIF
4b22b9337f359bfd063322244f5336cc7c6ffcfars #include <net/if_dl.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if !HAVE_SOLARIS
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <net/if_var.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#else
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <alloca.h>
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif /* !HAVE_SOLARIS */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <netinet/in_var.h>
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <netdb.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <arpa/inet.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* Converts a prefix length to IPv6 network mask */
4b22b9337f359bfd063322244f5336cc7c6ffcfarsvoid plen_to_mask(int plen, char *addr) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int i;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int colons=7; /* Number of colons in IPv6 address */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int bits_in_block=16; /* Bits per IPv6 block */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome for(i=0; i<=colons; i++) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int block, ones=0xffff, ones_in_block;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (plen>bits_in_block) ones_in_block=bits_in_block;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else ones_in_block=plen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome block = ones & (ones << (bits_in_block-ones_in_block));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome plen -= ones_in_block;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* Gets IPv6 interface information from the /proc filesystem in linux*/
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstruct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome FILE *fp = NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome char addr[8][5];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int flags, myflags, index, plen, scope;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome char ifname[9], lastname[IFNAMSIZ];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome char addr6[32+7+1]; /* don't forget the seven ':' */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct addrinfo hints, *res0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int err;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int sockfd = -1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct ifreq ifr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome res0=NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifihead = NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = &ifihead;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome lastname[0] = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (sockfd < 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome while (fscanf(fp,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome addr[0],addr[1],addr[2],addr[3],
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome addr[4],addr[5],addr[6],addr[7],
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome &index, &plen, &scope, &flags, ifname) != EOF) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome myflags = 0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (doaliases == 0)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome continue; /* already processed this interface */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome myflags = IFI_ALIAS;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(lastname, ifname, IFNAMSIZ);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ifi == NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipold = *ifipnext; /* need this later */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifiptr = ifipnext;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifi; /* prev points to this new one */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome addr[0],addr[1],addr[2],addr[3],
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome addr[4],addr[5],addr[6],addr[7]);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add address of the interface */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memset(&hints, 0, sizeof(hints));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome hints.ai_family = AF_INET6;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome hints.ai_flags = AI_NUMERICHOST;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome err = getaddrinfo(addr6, NULL, &hints, &res0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (err) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ifi->ifi_addr == NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add netmask of the interface */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome char ipv6addr[INET6_ADDRSTRLEN];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome plen_to_mask(plen, ipv6addr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome if (ifi->ifi_netmask == NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=family;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_scope_id=scope;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome inet_pton(family, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add interface name */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_name, ifname, IFI_NAME);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add interface index */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_index = index;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add interface flags*/
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (errno == EADDRNOTAVAIL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /*
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * If the main interface is configured with no IP address but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * an alias interface exists with an IP address, you get
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * EADDRNOTAVAIL for the main interface
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi->ifi_addr);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome free(ifi->ifi_netmask);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = ifiptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifipold;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome continue;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome } else {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_flags = ifr.ifr_flags;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome freeaddrinfo(res0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome res0=NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto done;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomegotError:
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ifihead != NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free_ifi_info(ifihead);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifihead = NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (res0 != NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome freeaddrinfo(res0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome res0=NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soomedone:
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (sockfd != -1) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome assert(close(sockfd) == 0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome if (fp != NULL) {
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome fclose(fp);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return(ifihead); /* pointer to first structure in linked list */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if HAVE_SOLARIS
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/*
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Converts prefix length to network mask. Assumes
4b22b9337f359bfd063322244f5336cc7c6ffcfars * addr points to a zeroed out buffer and prefix <= sizeof(addr)
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Unlike plen_to_mask returns netmask in binary form and not
4b22b9337f359bfd063322244f5336cc7c6ffcfars * in text form.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstatic void plen_to_netmask(int prefix, unsigned char *addr) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (; prefix > 8; prefix -= 8)
4b22b9337f359bfd063322244f5336cc7c6ffcfars *addr++ = 0xff;
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (; prefix > 0; prefix--)
4b22b9337f359bfd063322244f5336cc7c6ffcfars *addr = (*addr >> 1) | 0x80;
4b22b9337f359bfd063322244f5336cc7c6ffcfars}
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/*
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * This function goes through all the IP interfaces associated with a
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * physical interface and finds the best matched one for use by mDNS.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Returns NULL when none of the IP interfaces associated with a physical
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * interface are usable. Otherwise returns the best matched interface
4b22b9337f359bfd063322244f5336cc7c6ffcfars * information and a pointer to the best matched lifreq.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstruct ifi_info *
4b22b9337f359bfd063322244f5336cc7c6ffcfarsselect_src_ifi_info_solaris(int sockfd, int numifs,
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifreq *lifrlist, const char *curifname,
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifreq **best_lifr)
4b22b9337f359bfd063322244f5336cc7c6ffcfars{
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifreq *lifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifreq lifrcopy;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct ifi_info *ifi;
4b22b9337f359bfd063322244f5336cc7c6ffcfars char *chptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars char cmpifname[LIFNAMSIZ];
4b22b9337f359bfd063322244f5336cc7c6ffcfars int i;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome uint64_t best_lifrflags = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars uint64_t ifflags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars *best_lifr = NULL;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Check all logical interfaces associated with the physical
4b22b9337f359bfd063322244f5336cc7c6ffcfars * interface and figure out which one works best for us.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (i = numifs, lifr = lifrlist; i > 0; --i, ++lifr) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strlcpy(cmpifname, lifr->lifr_name, sizeof(cmpifname)) >= sizeof(cmpifname))
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* skip interface */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Strip logical interface number before checking ifname */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((chptr = strchr(cmpifname, ':')) != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars *chptr = '\0';
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Check ifname to see if the logical interface is associated
4b22b9337f359bfd063322244f5336cc7c6ffcfars * with the physical interface we are interested in.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strcmp(cmpifname, curifname) != 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifrcopy = *lifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGLIFFLAGS, &lifrcopy) < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* interface removed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (errno == ENXIO)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(NULL);
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifflags = lifrcopy.lifr_flags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* ignore address if not up */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((ifflags & IFF_UP) == 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars /*
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Avoid address if any of the following flags are set:
4b22b9337f359bfd063322244f5336cc7c6ffcfars * IFF_NOXMIT: no packets transmitted over interface
4b22b9337f359bfd063322244f5336cc7c6ffcfars * IFF_NOLOCAL: no address
4b22b9337f359bfd063322244f5336cc7c6ffcfars * IFF_PRIVATE: is not advertised
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifflags & (IFF_NOXMIT | IFF_NOLOCAL | IFF_PRIVATE))
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /* A DHCP client will have IFF_UP set yet the address is zero. Ignore */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (lifr->lifr_addr.ss_family == AF_INET) {
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome struct sockaddr_in *sinptr;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome sinptr = (struct sockaddr_in *) &lifr->lifr_addr;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome if (sinptr->sin_addr.s_addr == INADDR_ANY)
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome continue;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome }
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (*best_lifr != NULL) {
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Check if we found a better interface by checking
4b22b9337f359bfd063322244f5336cc7c6ffcfars * the flags. If flags are identical we prefer
4b22b9337f359bfd063322244f5336cc7c6ffcfars * the new found interface.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars uint64_t diff_flags = best_lifrflags ^ ifflags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* If interface has a different set of flags */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (diff_flags != 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Check flags in increasing order of ones we prefer */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Address temporary? */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((diff_flags & IFF_TEMPORARY) &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars (ifflags & IFF_TEMPORARY))
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Deprecated address? */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((diff_flags & IFF_DEPRECATED) &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars (ifflags & IFF_DEPRECATED))
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Last best-matched interface address has preferred? */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((diff_flags & IFF_PREFERRED) &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars ((ifflags & IFF_PREFERRED) == 0))
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Set best match interface & flags */
4b22b9337f359bfd063322244f5336cc7c6ffcfars *best_lifr = lifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars best_lifrflags = ifflags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (*best_lifr == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(NULL);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Found a match: return the interface information */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi = calloc(1, sizeof(struct ifi_info));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(NULL);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome ifi->ifi_flags = best_lifrflags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_index = if_nametoindex((*best_lifr)->lifr_name);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strlcpy(ifi->ifi_name, (*best_lifr)->lifr_name, sizeof(ifi->ifi_name)) >= sizeof(ifi->ifi_name)) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi);
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(NULL);
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(ifi);
4b22b9337f359bfd063322244f5336cc7c6ffcfars}
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Returns a list of IP interface information on Solaris. The function
4b22b9337f359bfd063322244f5336cc7c6ffcfars * returns all IP interfaces on the system with IPv4 address assigned
4b22b9337f359bfd063322244f5336cc7c6ffcfars * when passed AF_INET and returns IP interfaces with IPv6 address assigned
4b22b9337f359bfd063322244f5336cc7c6ffcfars * when AF_INET6 is passed.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstruct ifi_info *get_ifi_info_solaris(int family)
4b22b9337f359bfd063322244f5336cc7c6ffcfars{
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct ifi_info *ifi, *ifihead, **ifipnext;
4b22b9337f359bfd063322244f5336cc7c6ffcfars int sockfd;
4b22b9337f359bfd063322244f5336cc7c6ffcfars int len;
4b22b9337f359bfd063322244f5336cc7c6ffcfars char *buf;
4b22b9337f359bfd063322244f5336cc7c6ffcfars char *cptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars char ifname[LIFNAMSIZ], cmpifname[LIFNAMSIZ];
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in *sinptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifnum lifn;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifconf lifc;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifreq *lifrp, *best_lifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct lifreq lifrcopy;
4b22b9337f359bfd063322244f5336cc7c6ffcfars int numifs, nlifr, n;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(AF_INET6) && HAVE_IPV6
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in6 *sinptr6;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifihead = NULL;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars sockfd = socket(family, SOCK_DGRAM, 0);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sockfd < 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfarsagain:
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifn.lifn_family = family;
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifn.lifn_flags = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGLIFNUM, &lifn) < 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars /*
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Pad interface count to detect & retrieve any
4b22b9337f359bfd063322244f5336cc7c6ffcfars * additional interfaces between IFNUM & IFCONF calls.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifn.lifn_count += 4;
4b22b9337f359bfd063322244f5336cc7c6ffcfars numifs = lifn.lifn_count;
4b22b9337f359bfd063322244f5336cc7c6ffcfars len = numifs * sizeof (struct lifreq);
4b22b9337f359bfd063322244f5336cc7c6ffcfars buf = alloca(len);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifc.lifc_family = family;
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifc.lifc_len = len;
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifc.lifc_buf = buf;
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifc.lifc_flags = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGLIFCONF, &lifc) < 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars nlifr = lifc.lifc_len / sizeof(struct lifreq);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (nlifr >= numifs)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto again;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifrp = lifc.lifc_req;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifipnext = &ifihead;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (n = nlifr; n > 0; n--, lifrp++) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (lifrp->lifr_addr.ss_family != family)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * See if we have already processed the interface
4b22b9337f359bfd063322244f5336cc7c6ffcfars * by checking the interface names.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strlcpy(ifname, lifrp->lifr_name, sizeof(ifname)) >= sizeof(ifname))
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((cptr = strchr(ifname, ':')) != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars *cptr = '\0';
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * If any of the interfaces found so far share the physical
4b22b9337f359bfd063322244f5336cc7c6ffcfars * interface name then we have already processed the interface.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (ifi = ifihead; ifi != NULL; ifi = ifi->ifi_next) {
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Retrieve physical interface name */
4b22b9337f359bfd063322244f5336cc7c6ffcfars (void) strlcpy(cmpifname, ifi->ifi_name, sizeof(cmpifname));
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Strip logical interface number before checking ifname */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((cptr = strchr(cmpifname, ':')) != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars *cptr = '\0';
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strcmp(cmpifname, ifname) == 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* already processed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
4b22b9337f359bfd063322244f5336cc7c6ffcfars * New interface, find the one with the preferred source
4b22b9337f359bfd063322244f5336cc7c6ffcfars * address for our use in Multicast DNS.
4b22b9337f359bfd063322244f5336cc7c6ffcfars */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((ifi = select_src_ifi_info_solaris(sockfd, nlifr,
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifc.lifc_req, ifname, &best_lifr)) == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars assert(best_lifr != NULL);
4b22b9337f359bfd063322244f5336cc7c6ffcfars assert((best_lifr->lifr_addr.ss_family == AF_INET6) ||
4b22b9337f359bfd063322244f5336cc7c6ffcfars (best_lifr->lifr_addr.ss_family == AF_INET));
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars switch (best_lifr->lifr_addr.ss_family) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(AF_INET6) && HAVE_IPV6
4b22b9337f359bfd063322244f5336cc7c6ffcfars case AF_INET6:
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr6 = (struct sockaddr_in6 *) &best_lifr->lifr_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_addr = malloc(sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_netmask == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr6 = (struct sockaddr_in6 *)(ifi->ifi_netmask);
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr6->sin6_family = AF_INET6;
4b22b9337f359bfd063322244f5336cc7c6ffcfars plen_to_netmask(best_lifr->lifr_addrlen,
4b22b9337f359bfd063322244f5336cc7c6ffcfars (unsigned char *) &(sinptr6->sin6_addr));
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars case AF_INET:
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr = (struct sockaddr_in *) &best_lifr->lifr_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_addr = malloc(sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars lifrcopy = *best_lifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGLIFNETMASK, &lifrcopy) < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* interface removed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (errno == ENXIO) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi->ifi_addr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi);
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_netmask = malloc(sizeof(struct sockaddr_in));
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome if (ifi->ifi_netmask == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr = (struct sockaddr_in *) &lifrcopy.lifr_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr->sin_family = AF_INET;
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars default:
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* never reached */
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars *ifipnext = ifi; /* prev points to this new one */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars (void) close(sockfd);
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(ifihead); /* pointer to first structure in linked list */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfarsgotError:
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sockfd != -1)
4b22b9337f359bfd063322244f5336cc7c6ffcfars (void) close(sockfd);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifihead != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars free_ifi_info(ifihead);
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(NULL);
4b22b9337f359bfd063322244f5336cc7c6ffcfars}
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* HAVE_SOLARIS */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstruct ifi_info *get_ifi_info(int family, int doaliases)
4b22b9337f359bfd063322244f5336cc7c6ffcfars{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int junk;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int sockfd, sockf6, len, lastlen, flags, myflags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef NOT_HAVE_IF_NAMETOINDEX
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int index = 200;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct ifconf ifc;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct ifreq *ifr, ifrcopy;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in *sinptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(AF_INET6) && HAVE_IPV6
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in6 *sinptr6;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#elif HAVE_SOLARIS
4b22b9337f359bfd063322244f5336cc7c6ffcfars return get_ifi_info_solaris(family);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars sockfd = -1;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sockf6 = -1;
4b22b9337f359bfd063322244f5336cc7c6ffcfars buf = NULL;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifihead = NULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars sockfd = socket(AF_INET, SOCK_DGRAM, 0);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sockfd < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars lastlen = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
4b22b9337f359bfd063322244f5336cc7c6ffcfars for ( ; ; ) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars buf = (char*)malloc(len);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (buf == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifc.ifc_len = len;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifc.ifc_buf = buf;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (errno != EINVAL || lastlen != 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars } else {
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifc.ifc_len == lastlen)
4b22b9337f359bfd063322244f5336cc7c6ffcfars break; /* success, len has not changed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars lastlen = ifc.ifc_len;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars len += 10 * sizeof(struct ifreq); /* increment */
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(buf);
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifihead = NULL;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifipnext = &ifihead;
4b22b9337f359bfd063322244f5336cc7c6ffcfars lastname[0] = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end get_ifi_info1 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include get_ifi_info2 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifr = (struct ifreq *) ptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Advance to next one in buffer */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
4b22b9337f359bfd063322244f5336cc7c6ffcfars ptr += sizeof(struct ifreq);
4b22b9337f359bfd063322244f5336cc7c6ffcfars else
4b22b9337f359bfd063322244f5336cc7c6ffcfars ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars// fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifr->ifr_addr.sa_family != family)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* ignore if not desired address family */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars myflags = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars *cptr = 0; /* replace colon will null */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (doaliases == 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* already processed this interface */
4b22b9337f359bfd063322244f5336cc7c6ffcfars myflags = IFI_ALIAS;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifrcopy = *ifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars flags = ifrcopy.ifr_flags;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ((flags & IFF_UP) == 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* ignore if interface not up */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipold = *ifipnext; /* need this later */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifiptr = ifipnext;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifi; /* prev points to this new one */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_flags = flags; /* IFF_xxx values */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_myflags = myflags; /* IFI_xxx values */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef NOT_HAVE_IF_NAMETOINDEX
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_index = if_nametoindex(ifr->ifr_name);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#else
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifrcopy = *ifr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef SIOCGIFINDEX
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_index = ifrcopy.ifr_index;
4b22b9337f359bfd063322244f5336cc7c6ffcfars else
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_name[IFI_NAME-1] = '\0';
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end get_ifi_info2 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include get_ifi_info3 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars switch (ifr->ifr_addr.sa_family) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars case AF_INET:
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef SIOCGIFNETMASK
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (errno == EADDRNOTAVAIL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /*
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * If the main interface is configured with no IP address but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * an alias interface exists with an IP address, you get
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * EADDRNOTAVAIL for the main interface
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi->ifi_addr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = ifiptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifipold;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome continue;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome } else {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ifi->ifi_netmask == NULL) goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef NOT_HAVE_SA_LEN
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_len = sizeof(struct sockaddr_in);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_family = AF_INET;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef SIOCGIFBRDADDR
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (flags & IFF_BROADCAST) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef NOT_HAVE_SA_LEN
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_len = sizeof( struct sockaddr_in );
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_family = AF_INET;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_brdaddr == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef SIOCGIFDSTADDR
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (flags & IFF_POINTOPOINT) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef NOT_HAVE_SA_LEN
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_len = sizeof( struct sockaddr_in );
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_family = AF_INET;
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_dstaddr == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(AF_INET6) && HAVE_IPV6
4b22b9337f359bfd063322244f5336cc7c6ffcfars case AF_INET6:
4b22b9337f359bfd063322244f5336cc7c6ffcfars sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr == NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto gotError;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* We need to strip that out */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef SIOCGIFNETMASK_IN6
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct in6_ifreq ifr6;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (sockf6 == -1)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memset(&ifr6, 0, sizeof(ifr6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name ));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (errno == EADDRNOTAVAIL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /*
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * If the main interface is configured with no IP address but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * an alias interface exists with an IP address, you get
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * EADDRNOTAVAIL for the main interface
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi->ifi_addr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = ifiptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifipold;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome continue;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome } else {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ifi->ifi_netmask == NULL) goto gotError;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars default:
4b22b9337f359bfd063322244f5336cc7c6ffcfars break;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars goto done;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfarsgotError:
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifihead != NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars free_ifi_info(ifihead);
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifihead = NULL;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfarsdone:
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (buf != NULL) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(buf);
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sockfd != -1) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars junk = close(sockfd);
4b22b9337f359bfd063322244f5336cc7c6ffcfars assert(junk == 0);
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sockf6 != -1) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars junk = close(sockf6);
4b22b9337f359bfd063322244f5336cc7c6ffcfars assert(junk == 0);
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(ifihead); /* pointer to first structure in linked list */
4b22b9337f359bfd063322244f5336cc7c6ffcfars}
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end get_ifi_info3 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include free_ifi_info */
4b22b9337f359bfd063322244f5336cc7c6ffcfarsvoid
4b22b9337f359bfd063322244f5336cc7c6ffcfarsfree_ifi_info(struct ifi_info *ifihead)
4b22b9337f359bfd063322244f5336cc7c6ffcfars{
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct ifi_info *ifi, *ifinext;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_addr != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi->ifi_addr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ifi->ifi_netmask != NULL)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome free(ifi->ifi_netmask);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_brdaddr != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi->ifi_brdaddr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (ifi->ifi_dstaddr != NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi->ifi_dstaddr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */
4b22b9337f359bfd063322244f5336cc7c6ffcfars free(ifi); /* the ifi_info{} itself */
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars}
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end free_ifi_info */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soomessize_t
4b22b9337f359bfd063322244f5336cc7c6ffcfarsrecvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
4b22b9337f359bfd063322244f5336cc7c6ffcfars{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct msghdr msg;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct iovec iov[1];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ssize_t n;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef CMSG_FIRSTHDR
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct cmsghdr *cmptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars union {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct cmsghdr cm;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome char control[1024];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome pad64_t align8; /* ensure structure is 8-byte aligned on sparc */
4b22b9337f359bfd063322244f5336cc7c6ffcfars } control_un;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_control = (void *) control_un.control;
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_controllen = sizeof(control_un.control);
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_flags = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#else
4b22b9337f359bfd063322244f5336cc7c6ffcfars memset(&msg, 0, sizeof(msg)); /* make certain msg_accrightslen = 0 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* CMSG_FIRSTHDR */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_name = (char *) sa;
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_namelen = *salenptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars iov[0].iov_base = (char *)ptr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars iov[0].iov_len = nbytes;
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_iov = iov;
4b22b9337f359bfd063322244f5336cc7c6ffcfars msg.msg_iovlen = 1;
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars *salenptr = msg.msg_namelen; /* pass back results */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (pktp) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* 0.0.0.0, i/f = -1 */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* We set the interface to -1 so that the caller can
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome tell whether we returned a meaningful value or
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome just some default. Previously this code just
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome set the value to 0, but I'm concerned that 0
4b22b9337f359bfd063322244f5336cc7c6ffcfars might be a valid interface value.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
4b22b9337f359bfd063322244f5336cc7c6ffcfars memset(pktp, 0, sizeof(struct my_in_pktinfo));
4b22b9337f359bfd063322244f5336cc7c6ffcfars pktp->ipi_ifindex = -1;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end recvfrom_flags1 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include recvfrom_flags2 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef CMSG_FIRSTHDR
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
4b22b9337f359bfd063322244f5336cc7c6ffcfars *flagsp = 0; /* pass back results */
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#else
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars *flagsp = msg.msg_flags; /* pass back results */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
4b22b9337f359bfd063322244f5336cc7c6ffcfars (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
4b22b9337f359bfd063322244f5336cc7c6ffcfars cmptr = CMSG_NXTHDR(&msg, cmptr)) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef IP_PKTINFO
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if in_pktinfo_definition_is_missing
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct in_pktinfo
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int ipi_ifindex;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct in_addr ipi_spec_dst;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct in_addr ipi_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome };
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (cmptr->cmsg_level == IPPROTO_IP &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars cmptr->cmsg_type == IP_PKTINFO) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct in_pktinfo *tmp;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin->sin_family = AF_INET;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin->sin_addr = tmp->ipi_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin->sin_port = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars pktp->ipi_ifindex = tmp->ipi_ifindex;
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef IP_RECVDSTADDR
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (cmptr->cmsg_level == IPPROTO_IP &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars cmptr->cmsg_type == IP_RECVDSTADDR) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin->sin_family = AF_INET;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin->sin_port = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef IP_RECVIF
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (cmptr->cmsg_level == IPPROTO_IP &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars cmptr->cmsg_type == IP_RECVIF) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef HAVE_BROKEN_RECVIF_NAME
4b22b9337f359bfd063322244f5336cc7c6ffcfars int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
4b22b9337f359bfd063322244f5336cc7c6ffcfars strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /*
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * the is memcpy used for sparc? no idea;)
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * pktp->ipi_ifindex = sdl->sdl_index;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome (void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#ifdef HAVE_BROKEN_RECVIF_NAME
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (sdl->sdl_index == 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome pktp->ipi_ifindex = *(uint_t*)sdl;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
4b22b9337f359bfd063322244f5336cc7c6ffcfars // null terminated because of memset above
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef IP_RECVTTL
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (cmptr->cmsg_level == IPPROTO_IP &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars cmptr->cmsg_type == IP_RECVTTL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ttl = *(u_char*)CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars else if (cmptr->cmsg_level == IPPROTO_IP &&
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ttl = *(int*)CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(IPV6_PKTINFO) && HAVE_IPV6
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (cmptr->cmsg_level == IPPROTO_IPV6 &&
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome cmptr->cmsg_type == IPV6_PKTINFO) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin6->sin6_family = AF_INET6;
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifndef NOT_HAVE_SA_LEN
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin6->sin6_len = sizeof(*sin6);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin6->sin6_addr = ip6_info->ipi6_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin6->sin6_flowinfo = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin6->sin6_scope_id = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars sin6->sin6_port = 0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome pktp->ipi_ifindex = ip6_info->ipi6_ifindex;
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (cmptr->cmsg_level == IPPROTO_IPV6 &&
4b22b9337f359bfd063322244f5336cc7c6ffcfars cmptr->cmsg_type == IPV6_HOPLIMIT) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ttl = *(int*)CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue;
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif
4b22b9337f359bfd063322244f5336cc7c6ffcfars assert(0); // unknown ancillary data
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* CMSG_FIRSTHDR */
4b22b9337f359bfd063322244f5336cc7c6ffcfars}
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars// **********************************************************************************************
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars// daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
4b22b9337f359bfd063322244f5336cc7c6ffcfars// Returns 0 on success, -1 on failure.
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfars#ifdef NOT_HAVE_DAEMON
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <fcntl.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars#include <sys/stat.h>
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#include <sys/signal.h>
4b22b9337f359bfd063322244f5336cc7c6ffcfars
4b22b9337f359bfd063322244f5336cc7c6ffcfarsint daemon(int nochdir, int noclose)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome switch (fork())
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome case -1: return (-1); // Fork failed
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome case 0: break; // Child -- continue
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome default: _exit(0); // Parent -- exit
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (setsid() == -1) return(-1);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome signal(SIGHUP, SIG_IGN);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome switch (fork()) // Fork again, primarily for reasons of Unix trivia
4b22b9337f359bfd063322244f5336cc7c6ffcfars {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome case -1: return (-1); // Fork failed
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome case 0: break; // Child -- continue
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome default: _exit(0); // Parent -- exit
4b22b9337f359bfd063322244f5336cc7c6ffcfars }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!nochdir) (void)chdir("/");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome umask(0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!noclose)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int fd = open("/dev/null", O_RDWR, 0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != -1)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Avoid unnecessarily duplicating a file descriptor to itself
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)close (fd);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return (0);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* NOT_HAVE_DAEMON */