mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-29 16:44:03 +00:00
add getifaddrs(3) from bsdi. this is a magic function which lets you grab
interface addresses in a portable manner, without headache of SIOCGIFCONF or sysctl. it is in bsdi/openbsd/netbsd already. from kame tree (actually, mandatory for latest kame tree).
This commit is contained in:
parent
3b8a8567a1
commit
23ba01423e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62606
@ -10,7 +10,7 @@ CLEANFILES= osreldate.h version vers.c
|
||||
SUBDIR= rpcsvc
|
||||
FILES= a.out.h ar.h assert.h bitstring.h ctype.h db.h dirent.h disktab.h \
|
||||
dlfcn.h elf.h err.h fnmatch.h fstab.h \
|
||||
fts.h glob.h grp.h strhash.h histedit.h ieeefp.h iso646.h \
|
||||
fts.h glob.h grp.h strhash.h histedit.h ieeefp.h ifaddrs.h iso646.h \
|
||||
limits.h link.h locale.h malloc.h memory.h mpool.h \
|
||||
ndbm.h netdb.h nl_types.h nlist.h objformat.h \
|
||||
paths.h pthread.h pthread_np.h pwd.h \
|
||||
|
56
include/ifaddrs.h
Normal file
56
include/ifaddrs.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
u_int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs __P((struct ifaddrs **));
|
||||
extern void freeifaddrs __P((struct ifaddrs *));
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
@ -6,7 +6,7 @@
|
||||
|
||||
SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c getaddrinfo.c \
|
||||
gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
|
||||
getnameinfo.c \
|
||||
getifaddrs.c getnameinfo.c \
|
||||
getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
|
||||
getproto.c getprotoent.c getprotoname.c getservbyname.c \
|
||||
getservbyport.c getservent.c herror.c inet_addr.c ifname.c \
|
||||
@ -28,7 +28,7 @@ CFLAGS+=-DINET6
|
||||
|
||||
.if ${LIB} == "c"
|
||||
MAN3+= addr2ascii.3 byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 \
|
||||
getipnodebyname.3 \
|
||||
getifaddrs.3 getipnodebyname.3 \
|
||||
getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 if_indextoname.3 \
|
||||
inet.3 inet6_option_space.3 inet6_rthdr_space.3 linkaddr.3 \
|
||||
rcmd.3 resolver.3
|
||||
@ -44,6 +44,7 @@ MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
|
||||
gethostbyname.3 gethostbyname2.3 gethostbyname.3 gethostent.3 \
|
||||
gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \
|
||||
gethostbyname.3 sethostent.3
|
||||
MLINKS+=getifaddrs.3 freeifaddrs.3
|
||||
MLINKS+=getipnodebyname.3 getipnodebyaddr.3 getipnodebyname.3 freehostent.3
|
||||
MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
|
||||
getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
|
||||
|
163
lib/libc/net/getifaddrs.3
Normal file
163
lib/libc/net/getifaddrs.3
Normal file
@ -0,0 +1,163 @@
|
||||
.\" $FreeBSD$
|
||||
.\" $KAME: getifaddrs.3,v 1.4 2000/05/17 14:13:14 itojun Exp $
|
||||
.\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
.\"
|
||||
.\" Copyright (c) 1995, 1999
|
||||
.\" Berkeley Software Design, Inc. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" 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
|
||||
.\" SUCH DAMAGE.
|
||||
.Dd "October 12, 1995"
|
||||
.Dt GETIFADDRS 3
|
||||
.Sh NAME
|
||||
.Nm getifaddrs
|
||||
.Nd get interface addresses
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/types.h>
|
||||
.Fd #include <sys/socket.h>
|
||||
.Fd #include <ifaddrs.h>
|
||||
.Ft int
|
||||
.Fn getifaddrs "struct ifaddrs **ifap"
|
||||
.Ft void
|
||||
.Fn freeifaddrs "struct ifaddrs *ifp"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn getifaddrs
|
||||
function stores a reference to a linked list of the network interfaces
|
||||
on the local machine in the memory referenced by
|
||||
.Fa ifap .
|
||||
The list consists of
|
||||
.Nm ifaddrs
|
||||
structures, as defined in the include file
|
||||
.Aq Pa ifaddrs.h .
|
||||
The
|
||||
.Nm ifaddrs
|
||||
structure contains at least the following entries:
|
||||
.Bd -literal
|
||||
struct ifaddrs *ifa_next; /* Pointer to next struct */
|
||||
char *ifa_name; /* Interface name */
|
||||
u_int ifa_flags; /* Interface flags */
|
||||
struct sockaddr *ifa_addr; /* Interface address */
|
||||
struct sockaddr *ifa_netmask; /* Interface netmask */
|
||||
struct sockaddr *ifa_broadaddr; /* Interface broadcast address */
|
||||
struct sockaddr *ifa_dstaddr; /* P2P interface destination */
|
||||
void *ifa_data; /* Address specific data */
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_next
|
||||
field contains a pointer to the next structure on the list.
|
||||
This field is
|
||||
.Dv NULL
|
||||
in last structure on the list.
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_name
|
||||
field contains the interface name.
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_flags
|
||||
field contains the interface flags, as set by
|
||||
.Xr ifconfig 8
|
||||
utility.
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_addr
|
||||
field references either the address of the interface or the link level
|
||||
address of the interface, if one exists, otherwise it is NULL.
|
||||
(The
|
||||
.Li sa_family
|
||||
field of the
|
||||
.Li ifa_addr
|
||||
field should be consulted to determine the format of the
|
||||
.Li ifa_addr
|
||||
address.)
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_netmask
|
||||
field references the netmask associated with
|
||||
.Li ifa_addr ,
|
||||
if one is set, otherwise it is NULL.
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_broadaddr
|
||||
field,
|
||||
which should only be referenced for non-P2P interfaces,
|
||||
references the broadcast address associated with
|
||||
.Li ifa_addr ,
|
||||
if one exists, otherwise it is NULL.
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_dstaddr
|
||||
field references the destination address on a P2P interface,
|
||||
if one exists, otherwise it is NULL.
|
||||
.Pp
|
||||
The
|
||||
.Li ifa_data
|
||||
field references address family specific data. For
|
||||
.Dv AF_LINK
|
||||
addresses it contains a pointer to the
|
||||
.Fa struct if_data
|
||||
.Pq as defined in include file Aq Pa net/if.h
|
||||
which contains various interface attributes and statistics.
|
||||
For all other address families, it contains a pointer to the
|
||||
.Fa struct ifa_data
|
||||
.Pq as defined in include file Aq Pa net/if.h
|
||||
which contains per-address interface statistics.
|
||||
.Pp
|
||||
The data returned by
|
||||
.Fn getifaddrs
|
||||
is dynamically allocated and should be freed using
|
||||
.Fn freeifaddrs
|
||||
when no longer needed.
|
||||
.Sh RETURN VALUES
|
||||
Upon successful completion, a value of 0 is returned.
|
||||
Otherwise, a value of -1 is returned and
|
||||
.Va errno
|
||||
is set to indicate the error.
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn getifaddrs
|
||||
may fail and set
|
||||
.Va errno
|
||||
for any of the errors specified for the library routines
|
||||
.Xr ioctl 2 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr malloc 3
|
||||
or
|
||||
.Xr sysctl 3 .
|
||||
.Sh BUGS
|
||||
If both
|
||||
.Aq Pa net/if.h
|
||||
and
|
||||
.Aq Pa ifaddrs.h
|
||||
are being included,
|
||||
.Aq Pa net/if.h
|
||||
.Em must
|
||||
be included before
|
||||
.Aq Pa ifaddrs.h .
|
||||
.Sh SEE ALSO
|
||||
.Xr ioctl 2 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr sysctl 3 ,
|
||||
.Xr networking 4 ,
|
||||
.Xr ifconfig 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
implementation first appeared in BSDI BSD/OS.
|
379
lib/libc/net/getifaddrs.c
Normal file
379
lib/libc/net/getifaddrs.c
Normal file
@ -0,0 +1,379 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
/*
|
||||
* NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform
|
||||
* try-and-error for region size.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#ifdef NET_RT_IFLIST
|
||||
#include <sys/param.h>
|
||||
#include <net/route.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(AF_LINK)
|
||||
#define SA_LEN(sa) sizeof(struct sockaddr)
|
||||
#endif
|
||||
|
||||
#if !defined(SA_LEN)
|
||||
#define SA_LEN(sa) (sa)->sa_len
|
||||
#endif
|
||||
|
||||
#define SALIGN (sizeof(long) - 1)
|
||||
#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
|
||||
|
||||
#ifndef ALIGNBYTES
|
||||
/*
|
||||
* On systems with a routing socket, ALIGNBYTES should match the value
|
||||
* that the kernel uses when building the messages.
|
||||
*/
|
||||
#define ALIGNBYTES XXX
|
||||
#endif
|
||||
#ifndef ALIGN
|
||||
#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
||||
#endif
|
||||
|
||||
#if _BSDI_VERSION >= 199701
|
||||
#define HAVE_IFM_DATA
|
||||
#endif
|
||||
|
||||
#if _BSDI_VERSION >= 199802
|
||||
#define HAVE_IFAM_DATA
|
||||
#endif
|
||||
|
||||
int
|
||||
getifaddrs(struct ifaddrs **pif)
|
||||
{
|
||||
int icnt = 1;
|
||||
int dcnt = 0;
|
||||
int ncnt = 0;
|
||||
#ifdef NET_RT_IFLIST
|
||||
int mib[6];
|
||||
size_t needed;
|
||||
char *buf;
|
||||
char *next;
|
||||
struct ifaddrs *cif = 0;
|
||||
char *p, *p0;
|
||||
struct rt_msghdr *rtm;
|
||||
struct if_msghdr *ifm;
|
||||
struct ifa_msghdr *ifam;
|
||||
struct sockaddr_dl *dl;
|
||||
struct sockaddr *sa;
|
||||
struct ifaddrs *ifa, *ift;
|
||||
u_short index = 0;
|
||||
#else /* NET_RT_IFLIST */
|
||||
char buf[1024];
|
||||
int m, sock;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr;
|
||||
struct ifreq *lifr;
|
||||
#endif /* NET_RT_IFLIST */
|
||||
int i;
|
||||
size_t len, alen;
|
||||
char *data;
|
||||
char *names;
|
||||
|
||||
#ifdef NET_RT_IFLIST
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0; /* protocol */
|
||||
mib[3] = 0; /* wildcard address family */
|
||||
mib[4] = NET_RT_IFLIST;
|
||||
mib[5] = 0; /* no flags */
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
return (-1);
|
||||
if ((buf = malloc(needed)) == NULL)
|
||||
return (-1);
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
|
||||
free(buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
if (rtm->rtm_version != RTM_VERSION)
|
||||
continue;
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_IFINFO:
|
||||
ifm = (struct if_msghdr *)rtm;
|
||||
if (ifm->ifm_addrs & RTA_IFP) {
|
||||
index = ifm->ifm_index;
|
||||
++icnt;
|
||||
dl = (struct sockaddr_dl *)(ifm + 1);
|
||||
dcnt += SA_RLEN((struct sockaddr *)dl) +
|
||||
ALIGNBYTES;
|
||||
#ifdef HAVE_IFM_DATA
|
||||
dcnt += sizeof(ifm->ifm_data);
|
||||
#endif /* HAVE_IFM_DATA */
|
||||
ncnt += dl->sdl_nlen + 1;
|
||||
} else
|
||||
index = 0;
|
||||
break;
|
||||
|
||||
case RTM_NEWADDR:
|
||||
ifam = (struct ifa_msghdr *)rtm;
|
||||
if (index && ifam->ifam_index != index)
|
||||
abort(); /* this cannot happen */
|
||||
|
||||
#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
|
||||
if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
|
||||
break;
|
||||
p = (char *)(ifam + 1);
|
||||
++icnt;
|
||||
#ifdef HAVE_IFAM_DATA
|
||||
dcnt += sizeof(ifam->ifam_data) + ALIGNBYTES;
|
||||
#endif /* HAVE_IFAM_DATA */
|
||||
/* Scan to look for length of address */
|
||||
alen = 0;
|
||||
for (p0 = p, i = 0; i < RTAX_MAX; i++) {
|
||||
if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
|
||||
== 0)
|
||||
continue;
|
||||
sa = (struct sockaddr *)p;
|
||||
len = SA_RLEN(sa);
|
||||
if (i == RTAX_IFA) {
|
||||
alen = len;
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
for (p = p0, i = 0; i < RTAX_MAX; i++) {
|
||||
if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
|
||||
== 0)
|
||||
continue;
|
||||
sa = (struct sockaddr *)p;
|
||||
len = SA_RLEN(sa);
|
||||
if (i == RTAX_NETMASK && SA_LEN(sa) == 0)
|
||||
dcnt += alen;
|
||||
else
|
||||
dcnt += len;
|
||||
p += len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else /* NET_RT_IFLIST */
|
||||
ifc.ifc_buf = buf;
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
return (-1);
|
||||
i = ioctl(sock, SIOCGIFCONF, (char *)&ifc);
|
||||
close(sock);
|
||||
if (i < 0)
|
||||
return (-1);
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
|
||||
|
||||
while (ifr < lifr) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
sa = &ifr->ifr_addr;
|
||||
++icnt;
|
||||
dcnt += SA_RLEN(sa);
|
||||
ncnt += sizeof(ifr->ifr_name) + 1;
|
||||
|
||||
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
|
||||
}
|
||||
#endif /* NET_RT_IFLIST */
|
||||
|
||||
if (icnt + dcnt + ncnt == 1) {
|
||||
*pif = NULL;
|
||||
free(buf);
|
||||
return (0);
|
||||
}
|
||||
data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
|
||||
if (data == NULL) {
|
||||
free(buf);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
ifa = (struct ifaddrs *)data;
|
||||
data += sizeof(struct ifaddrs) * icnt;
|
||||
names = data + dcnt;
|
||||
|
||||
memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
|
||||
ift = ifa;
|
||||
|
||||
#ifdef NET_RT_IFLIST
|
||||
index = 0;
|
||||
for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
if (rtm->rtm_version != RTM_VERSION)
|
||||
continue;
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_IFINFO:
|
||||
ifm = (struct if_msghdr *)rtm;
|
||||
if (ifm->ifm_addrs & RTA_IFP) {
|
||||
index = ifm->ifm_index;
|
||||
dl = (struct sockaddr_dl *)(ifm + 1);
|
||||
|
||||
cif = ift;
|
||||
ift->ifa_name = names;
|
||||
ift->ifa_flags = (int)ifm->ifm_flags;
|
||||
memcpy(names, dl->sdl_data, dl->sdl_nlen);
|
||||
names[dl->sdl_nlen] = 0;
|
||||
names += dl->sdl_nlen + 1;
|
||||
|
||||
ift->ifa_addr = (struct sockaddr *)data;
|
||||
memcpy(data, dl, SA_LEN((struct sockaddr *)dl));
|
||||
data += SA_RLEN((struct sockaddr *)dl);
|
||||
|
||||
#ifdef HAVE_IFM_DATA
|
||||
/* ifm_data needs to be aligned */
|
||||
ift->ifa_data = data = (void *)ALIGN(data);
|
||||
memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
|
||||
data += sizeof(ifm->ifm_data);
|
||||
#else /* HAVE_IFM_DATA */
|
||||
ift->ifa_data = NULL;
|
||||
#endif /* HAVE_IFM_DATA */
|
||||
|
||||
ift = (ift->ifa_next = ift + 1);
|
||||
} else
|
||||
index = 0;
|
||||
break;
|
||||
|
||||
case RTM_NEWADDR:
|
||||
ifam = (struct ifa_msghdr *)rtm;
|
||||
if (index && ifam->ifam_index != index)
|
||||
abort(); /* this cannot happen */
|
||||
|
||||
if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
|
||||
break;
|
||||
ift->ifa_name = cif->ifa_name;
|
||||
ift->ifa_flags = cif->ifa_flags;
|
||||
ift->ifa_data = NULL;
|
||||
p = (char *)(ifam + 1);
|
||||
/* Scan to look for length of address */
|
||||
alen = 0;
|
||||
for (p0 = p, i = 0; i < RTAX_MAX; i++) {
|
||||
if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
|
||||
== 0)
|
||||
continue;
|
||||
sa = (struct sockaddr *)p;
|
||||
len = SA_RLEN(sa);
|
||||
if (i == RTAX_IFA) {
|
||||
alen = len;
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
for (p = p0, i = 0; i < RTAX_MAX; i++) {
|
||||
if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
|
||||
== 0)
|
||||
continue;
|
||||
sa = (struct sockaddr *)p;
|
||||
len = SA_RLEN(sa);
|
||||
switch (i) {
|
||||
case RTAX_IFA:
|
||||
ift->ifa_addr = (struct sockaddr *)data;
|
||||
memcpy(data, p, len);
|
||||
data += len;
|
||||
break;
|
||||
|
||||
case RTAX_NETMASK:
|
||||
ift->ifa_netmask =
|
||||
(struct sockaddr *)data;
|
||||
if (SA_LEN(sa) == 0) {
|
||||
memset(data, 0, alen);
|
||||
data += alen;
|
||||
break;
|
||||
}
|
||||
memcpy(data, p, len);
|
||||
data += len;
|
||||
break;
|
||||
|
||||
case RTAX_BRD:
|
||||
ift->ifa_broadaddr =
|
||||
(struct sockaddr *)data;
|
||||
memcpy(data, p, len);
|
||||
data += len;
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IFAM_DATA
|
||||
/* ifam_data needs to be aligned */
|
||||
ift->ifa_data = data = (void *)ALIGN(data);
|
||||
memcpy(data, &ifam->ifam_data, sizeof(ifam->ifam_data));
|
||||
data += sizeof(ifam->ifam_data);
|
||||
#endif /* HAVE_IFAM_DATA */
|
||||
|
||||
ift = (ift->ifa_next = ift + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
#else /* NET_RT_IFLIST */
|
||||
ifr = ifc.ifc_req;
|
||||
lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
|
||||
|
||||
while (ifr < lifr) {
|
||||
struct sockaddr *sa;
|
||||
|
||||
ift->ifa_name = names;
|
||||
names[sizeof(ifr->ifr_name)] = 0;
|
||||
strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
|
||||
while (*names++)
|
||||
;
|
||||
|
||||
ift->ifa_addr = (struct sockaddr *)data;
|
||||
sa = &ifr->ifr_addr;
|
||||
memcpy(data, sa, SA_LEN(sa));
|
||||
data += SA_RLEN(sa);
|
||||
|
||||
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
|
||||
ift = (ift->ifa_next = ift + 1);
|
||||
}
|
||||
#endif /* NET_RT_IFLIST */
|
||||
if (--ift >= ifa) {
|
||||
ift->ifa_next = NULL;
|
||||
*pif = ifa;
|
||||
} else {
|
||||
*pif = NULL;
|
||||
free(ifa);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
freeifaddrs(struct ifaddrs *ifp)
|
||||
{
|
||||
free(ifp);
|
||||
}
|
Loading…
Reference in New Issue
Block a user