//==========================================================================
|
//==========================================================================
|
//
|
//
|
// src/ifaddrs.c
|
// src/ifaddrs.c
|
//
|
//
|
//==========================================================================
|
//==========================================================================
|
//####BSDCOPYRIGHTBEGIN####
|
//####BSDCOPYRIGHTBEGIN####
|
//
|
//
|
// -------------------------------------------
|
// -------------------------------------------
|
//
|
//
|
// Portions of this software may have been derived from OpenBSD,
|
// Portions of this software may have been derived from OpenBSD,
|
// FreeBSD or other sources, and are covered by the appropriate
|
// FreeBSD or other sources, and are covered by the appropriate
|
// copyright disclaimers included herein.
|
// copyright disclaimers included herein.
|
//
|
//
|
// Portions created by Red Hat are
|
// Portions created by Red Hat are
|
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
|
//
|
//
|
// -------------------------------------------
|
// -------------------------------------------
|
//
|
//
|
//####BSDCOPYRIGHTEND####
|
//####BSDCOPYRIGHTEND####
|
//==========================================================================
|
//==========================================================================
|
|
|
//
|
//
|
// Adapted from KAME getifaddrs.c, if_nametoindex.c, if_indextoname.c
|
// Adapted from KAME getifaddrs.c, if_nametoindex.c, if_indextoname.c
|
//
|
//
|
|
|
/* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */
|
/* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */
|
/* $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $ */
|
/* $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $ */
|
/* $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $ */
|
/* $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $ */
|
|
|
/*
|
/*
|
* Copyright (c) 1995, 1999
|
* Copyright (c) 1995, 1999
|
* Berkeley Software Design, Inc. All rights reserved.
|
* Berkeley Software Design, Inc. All rights reserved.
|
*
|
*
|
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
* are met:
|
* are met:
|
* 1. Redistributions of source code must retain the above copyright
|
* 1. Redistributions of source code must retain the above copyright
|
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
*
|
*
|
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
*
|
*
|
* BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
|
* BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
|
*/
|
*/
|
|
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
|
|
#undef _KERNEL
|
#undef _KERNEL
|
#undef __INSIDE_NET
|
#undef __INSIDE_NET
|
#include <sys/param.h>
|
#include <sys/param.h>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
#include <sys/socket.h>
|
#include <sys/socket.h>
|
#include <net/if.h>
|
#include <net/if.h>
|
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
#include <errno.h>
|
#include <errno.h>
|
#include <netinet/in.h>
|
#include <netinet/in.h>
|
#include <net/netdb.h>
|
#include <net/netdb.h>
|
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
|
|
#if !defined(AF_LINK)
|
#if !defined(AF_LINK)
|
#define SA_LEN(sa) sizeof(struct sockaddr)
|
#define SA_LEN(sa) sizeof(struct sockaddr)
|
#endif
|
#endif
|
|
|
#if !defined(SA_LEN)
|
#if !defined(SA_LEN)
|
#define SA_LEN(sa) (sa)->sa_len
|
#define SA_LEN(sa) (sa)->sa_len
|
#endif
|
#endif
|
|
|
#define SALIGN (sizeof(long) - 1)
|
#define SALIGN (sizeof(long) - 1)
|
#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
|
#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
|
|
|
#ifndef ALIGNBYTES
|
#ifndef ALIGNBYTES
|
/*
|
/*
|
* On systems with a routing socket, ALIGNBYTES should match the value
|
* On systems with a routing socket, ALIGNBYTES should match the value
|
* that the kernel uses when building the messages.
|
* that the kernel uses when building the messages.
|
*/
|
*/
|
#define ALIGNBYTES XXX
|
#define ALIGNBYTES XXX
|
#endif
|
#endif
|
#ifndef ALIGN
|
#ifndef ALIGN
|
#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
#endif
|
#endif
|
|
|
int
|
int
|
getifaddrs(struct ifaddrs **pif)
|
getifaddrs(struct ifaddrs **pif)
|
{
|
{
|
int icnt = 1; // Interface count
|
int icnt = 1; // Interface count
|
int dcnt = 0; // Data [length] count
|
int dcnt = 0; // Data [length] count
|
int ncnt = 0; // Length of interface names
|
int ncnt = 0; // Length of interface names
|
char buf[1024];
|
char buf[1024];
|
int i, sock;
|
int i, sock;
|
struct ifconf ifc;
|
struct ifconf ifc;
|
struct ifreq *ifr, *lifr;
|
struct ifreq *ifr, *lifr;
|
char *data, *names;
|
char *data, *names;
|
struct ifaddrs *ifa, *ift;
|
struct ifaddrs *ifa, *ift;
|
|
|
ifc.ifc_buf = buf;
|
ifc.ifc_buf = buf;
|
ifc.ifc_len = sizeof(buf);
|
ifc.ifc_len = sizeof(buf);
|
|
|
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
return (-1);
|
return (-1);
|
i = ioctl(sock, SIOCGIFCONF, (char *)&ifc);
|
i = ioctl(sock, SIOCGIFCONF, (char *)&ifc);
|
close(sock);
|
close(sock);
|
if (i < 0)
|
if (i < 0)
|
return (-1);
|
return (-1);
|
|
|
ifr = ifc.ifc_req;
|
ifr = ifc.ifc_req;
|
lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
|
lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
|
|
|
while (ifr < lifr) {
|
while (ifr < lifr) {
|
struct sockaddr *sa;
|
struct sockaddr *sa;
|
|
|
sa = &ifr->ifr_addr;
|
sa = &ifr->ifr_addr;
|
++icnt;
|
++icnt;
|
dcnt += SA_RLEN(sa);
|
dcnt += SA_RLEN(sa);
|
ncnt += sizeof(ifr->ifr_name) + 1;
|
ncnt += sizeof(ifr->ifr_name) + 1;
|
|
|
if (SA_LEN(sa) < sizeof(*sa))
|
if (SA_LEN(sa) < sizeof(*sa))
|
ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
|
ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
|
else
|
else
|
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
|
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
|
}
|
}
|
|
|
if (icnt + dcnt + ncnt == 1) {
|
if (icnt + dcnt + ncnt == 1) {
|
// Nothing found
|
// Nothing found
|
*pif = NULL;
|
*pif = NULL;
|
free(buf);
|
free(buf);
|
return (0);
|
return (0);
|
}
|
}
|
data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
|
data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
|
if (data == NULL) {
|
if (data == NULL) {
|
free(buf);
|
free(buf);
|
return(-1);
|
return(-1);
|
}
|
}
|
|
|
ifa = (struct ifaddrs *)(void *)data;
|
ifa = (struct ifaddrs *)(void *)data;
|
data += sizeof(struct ifaddrs) * icnt;
|
data += sizeof(struct ifaddrs) * icnt;
|
names = data + dcnt;
|
names = data + dcnt;
|
|
|
memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
|
memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
|
ift = ifa;
|
ift = ifa;
|
|
|
ifr = ifc.ifc_req;
|
ifr = ifc.ifc_req;
|
lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
|
lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
|
|
|
while (ifr < lifr) {
|
while (ifr < lifr) {
|
struct sockaddr *sa;
|
struct sockaddr *sa;
|
|
|
ift->ifa_name = names;
|
ift->ifa_name = names;
|
names[sizeof(ifr->ifr_name)] = 0;
|
names[sizeof(ifr->ifr_name)] = 0;
|
strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
|
strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
|
while (*names++) ;
|
while (*names++) ;
|
|
|
ift->ifa_addr = (struct sockaddr *)data;
|
ift->ifa_addr = (struct sockaddr *)data;
|
sa = &ifr->ifr_addr;
|
sa = &ifr->ifr_addr;
|
memcpy(data, sa, SA_LEN(sa));
|
memcpy(data, sa, SA_LEN(sa));
|
data += SA_RLEN(sa);
|
data += SA_RLEN(sa);
|
|
|
if (SA_LEN(sa) < sizeof(*sa))
|
if (SA_LEN(sa) < sizeof(*sa))
|
ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
|
ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
|
else
|
else
|
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
|
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
|
ift = (ift->ifa_next = ift + 1);
|
ift = (ift->ifa_next = ift + 1);
|
}
|
}
|
|
|
if (--ift >= ifa) {
|
if (--ift >= ifa) {
|
ift->ifa_next = NULL;
|
ift->ifa_next = NULL;
|
*pif = ifa;
|
*pif = ifa;
|
} else {
|
} else {
|
*pif = NULL;
|
*pif = NULL;
|
free(ifa);
|
free(ifa);
|
}
|
}
|
return (0);
|
return (0);
|
}
|
}
|
|
|
void
|
void
|
freeifaddrs(struct ifaddrs *ifp)
|
freeifaddrs(struct ifaddrs *ifp)
|
{
|
{
|
free(ifp);
|
free(ifp);
|
}
|
}
|
|
|
void
|
void
|
_show_all_interfaces(void)
|
_show_all_interfaces(void)
|
{
|
{
|
struct ifaddrs *iflist, *ifp;
|
struct ifaddrs *iflist, *ifp;
|
char addr[64];
|
char addr[64];
|
int indx;
|
int indx;
|
|
|
if (getifaddrs(&iflist) < 0) {
|
if (getifaddrs(&iflist) < 0) {
|
diag_printf("Can't get interface information!!\n");
|
diag_printf("Can't get interface information!!\n");
|
return;
|
return;
|
}
|
}
|
ifp = iflist;
|
ifp = iflist;
|
while (ifp != (struct ifaddrs *)NULL) {
|
while (ifp != (struct ifaddrs *)NULL) {
|
if (ifp->ifa_addr->sa_family != AF_LINK) {
|
if (ifp->ifa_addr->sa_family != AF_LINK) {
|
getnameinfo (ifp->ifa_addr, ifp->ifa_addr->sa_len, addr, sizeof(addr), 0, 0, 0);
|
getnameinfo (ifp->ifa_addr, ifp->ifa_addr->sa_len, addr, sizeof(addr), 0, 0, 0);
|
diag_printf("%p - %s - %s\n", ifp, ifp->ifa_name, addr);
|
diag_printf("%p - %s - %s\n", ifp, ifp->ifa_name, addr);
|
}
|
}
|
ifp = ifp->ifa_next;
|
ifp = ifp->ifa_next;
|
}
|
}
|
indx = if_nametoindex(iflist->ifa_name);
|
indx = if_nametoindex(iflist->ifa_name);
|
diag_printf("indx(%s) = %d\n", iflist->ifa_name, indx);
|
diag_printf("indx(%s) = %d\n", iflist->ifa_name, indx);
|
if (indx > 0) {
|
if (indx > 0) {
|
if (if_indextoname(indx, addr)) {
|
if (if_indextoname(indx, addr)) {
|
diag_printf("index(%s) = %d/%s\n", iflist->ifa_name, indx, addr);
|
diag_printf("index(%s) = %d/%s\n", iflist->ifa_name, indx, addr);
|
} else {
|
} else {
|
diag_printf("index(%s) = %d: %s\n", iflist->ifa_name, indx, strerror(errno));
|
diag_printf("index(%s) = %d: %s\n", iflist->ifa_name, indx, strerror(errno));
|
}
|
}
|
} else {
|
} else {
|
diag_printf("index(%s): %s\n", iflist->ifa_name, strerror(errno));
|
diag_printf("index(%s): %s\n", iflist->ifa_name, strerror(errno));
|
}
|
}
|
freeifaddrs(iflist);
|
freeifaddrs(iflist);
|
}
|
}
|
|
|
/*
|
/*
|
* From RFC 2553:
|
* From RFC 2553:
|
*
|
*
|
* 4.1 Name-to-Index
|
* 4.1 Name-to-Index
|
*
|
*
|
*
|
*
|
* The first function maps an interface name into its corresponding
|
* The first function maps an interface name into its corresponding
|
* index.
|
* index.
|
*
|
*
|
* #include <net/if.h>
|
* #include <net/if.h>
|
*
|
*
|
* unsigned int if_nametoindex(const char *ifname);
|
* unsigned int if_nametoindex(const char *ifname);
|
*
|
*
|
* If the specified interface name does not exist, the return value is
|
* If the specified interface name does not exist, the return value is
|
* 0, and errno is set to ENXIO. If there was a system error (such as
|
* 0, and errno is set to ENXIO. If there was a system error (such as
|
* running out of memory), the return value is 0 and errno is set to the
|
* running out of memory), the return value is 0 and errno is set to the
|
* proper value (e.g., ENOMEM).
|
* proper value (e.g., ENOMEM).
|
*/
|
*/
|
|
|
unsigned int
|
unsigned int
|
if_nametoindex(const char *ifname)
|
if_nametoindex(const char *ifname)
|
{
|
{
|
struct ifaddrs *ifaddrs, *ifa;
|
struct ifaddrs *ifaddrs, *ifa;
|
unsigned int ni;
|
unsigned int ni;
|
|
|
if (getifaddrs(&ifaddrs) < 0)
|
if (getifaddrs(&ifaddrs) < 0)
|
return(0);
|
return(0);
|
|
|
ni = 0;
|
ni = 0;
|
|
|
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
if (ifa->ifa_addr &&
|
if (ifa->ifa_addr &&
|
ifa->ifa_addr->sa_family == AF_LINK &&
|
ifa->ifa_addr->sa_family == AF_LINK &&
|
strcmp(ifa->ifa_name, ifname) == 0) {
|
strcmp(ifa->ifa_name, ifname) == 0) {
|
ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
|
ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
freeifaddrs(ifaddrs);
|
freeifaddrs(ifaddrs);
|
if (!ni)
|
if (!ni)
|
errno = ENXIO;
|
errno = ENXIO;
|
return(ni);
|
return(ni);
|
}
|
}
|
|
|
/*
|
/*
|
* From RFC 2533:
|
* From RFC 2533:
|
*
|
*
|
* The second function maps an interface index into its corresponding
|
* The second function maps an interface index into its corresponding
|
* name.
|
* name.
|
*
|
*
|
* #include <net/if.h>
|
* #include <net/if.h>
|
*
|
*
|
* char *if_indextoname(unsigned int ifindex, char *ifname);
|
* char *if_indextoname(unsigned int ifindex, char *ifname);
|
*
|
*
|
* The ifname argument must point to a buffer of at least IF_NAMESIZE
|
* The ifname argument must point to a buffer of at least IF_NAMESIZE
|
* bytes into which the interface name corresponding to the specified
|
* bytes into which the interface name corresponding to the specified
|
* index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
|
* index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
|
* its value includes a terminating null byte at the end of the
|
* its value includes a terminating null byte at the end of the
|
* interface name.) This pointer is also the return value of the
|
* interface name.) This pointer is also the return value of the
|
* function. If there is no interface corresponding to the specified
|
* function. If there is no interface corresponding to the specified
|
* index, NULL is returned, and errno is set to ENXIO, if there was a
|
* index, NULL is returned, and errno is set to ENXIO, if there was a
|
* system error (such as running out of memory), if_indextoname returns
|
* system error (such as running out of memory), if_indextoname returns
|
* NULL and errno would be set to the proper value (e.g., ENOMEM).
|
* NULL and errno would be set to the proper value (e.g., ENOMEM).
|
*/
|
*/
|
|
|
char *
|
char *
|
if_indextoname(unsigned int ifindex, char *ifname)
|
if_indextoname(unsigned int ifindex, char *ifname)
|
{
|
{
|
struct ifaddrs *ifaddrs, *ifa;
|
struct ifaddrs *ifaddrs, *ifa;
|
int error = 0;
|
int error = 0;
|
|
|
if (getifaddrs(&ifaddrs) < 0)
|
if (getifaddrs(&ifaddrs) < 0)
|
return(NULL); /* getifaddrs properly set errno */
|
return(NULL); /* getifaddrs properly set errno */
|
|
|
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
if (ifa->ifa_addr &&
|
if (ifa->ifa_addr &&
|
ifa->ifa_addr->sa_family == AF_LINK &&
|
ifa->ifa_addr->sa_family == AF_LINK &&
|
ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
|
ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
|
break;
|
break;
|
}
|
}
|
|
|
if (ifa == NULL) {
|
if (ifa == NULL) {
|
error = ENXIO;
|
error = ENXIO;
|
ifname = NULL;
|
ifname = NULL;
|
}
|
}
|
else
|
else
|
strncpy(ifname, ifa->ifa_name, IFNAMSIZ);
|
strncpy(ifname, ifa->ifa_name, IFNAMSIZ);
|
|
|
freeifaddrs(ifaddrs);
|
freeifaddrs(ifaddrs);
|
|
|
errno = error;
|
errno = error;
|
return(ifname);
|
return(ifname);
|
}
|
}
|
|
|