diff options
author | bms <bms@FreeBSD.org> | 2003-11-14 18:53:22 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2003-11-14 18:53:22 +0000 |
commit | 47c129ab4445e4c2476772fd12576c58374dc7f0 (patch) | |
tree | d7da58d9004bc41430474427213f067467a3eb59 /lib/libc | |
parent | 690de3f7ac39802c0fe04563dacd6ab0f2a4d79f (diff) | |
download | FreeBSD-src-47c129ab4445e4c2476772fd12576c58374dc7f0.zip FreeBSD-src-47c129ab4445e4c2476772fd12576c58374dc7f0.tar.gz |
Add the userland part of the NET_RT_IFMALIST sysctl MIB. A new function,
getifmaddrs(), is added to retrieve current multicast group memberships.
Reviewed by: harti
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/net/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libc/net/getifmaddrs.3 | 112 | ||||
-rw-r--r-- | lib/libc/net/getifmaddrs.c | 207 |
3 files changed, 322 insertions, 2 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index a00269e..6062550 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -6,7 +6,7 @@ SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c getaddrinfo.c \ gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \ - getifaddrs.c getnameinfo.c \ + getifaddrs.c getifmaddrs.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 hesiod.c inet_addr.c \ @@ -40,7 +40,7 @@ nslexer.c: nslexer.l nsparser.h .endif MAN+= addr2ascii.3 byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 \ - getifaddrs.3 getipnodebyname.3 \ + getifaddrs.3 getifmaddrs.3 getipnodebyname.3 \ getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 hesiod.3 \ if_indextoname.3 \ inet.3 inet_net.3 \ @@ -59,6 +59,7 @@ MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \ gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \ gethostbyname.3 sethostent.3 MLINKS+=getifaddrs.3 freeifaddrs.3 +MLINKS+=getifmaddrs.3 freeifmaddrs.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 diff --git a/lib/libc/net/getifmaddrs.3 b/lib/libc/net/getifmaddrs.3 new file mode 100644 index 0000000..8594f6b --- /dev/null +++ b/lib/libc/net/getifmaddrs.3 @@ -0,0 +1,112 @@ +.\" $FreeBSD$ +.\" +.\" Copyright (c) 2003 Bruce M. Simpson. 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 Bruce M. Simpson ``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 Bruce M. Simpson 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 GETIFMADDRS 3 +.Os +.Sh NAME +.Nm getifmaddrs +.Nd get multicast group memberships +.Sh SYNOPSIS +.In sys/types.h +.In sys/socket.h +.In ifaddrs.h +.Ft int +.Fn getifmaddrs "struct ifmaddrs **ifmap" +.Ft void +.Fn freeifmaddrs "struct ifmaddrs *ifmp" +.Sh DESCRIPTION +The +.Fn getifmaddrs +function stores a reference to a linked list of the multicast memberships +on the local machine in the memory referenced by +.Fa ifmap . +The list consists of +.Nm ifmaddrs +structures, as defined in the include file +.Aq Pa ifaddrs.h . +The +.Nm ifmaddrs +structure contains at least the following entries: +.Bd -literal + struct ifmaddrs *ifma_next; /* Pointer to next struct */ + struct sockaddr *ifma_name; /* Interface name (AF_LINK) */ + struct sockaddr *ifma_addr; /* Multicast address */ + struct sockaddr *ifma_lladdr; /* Link-layer translation, if any */ +.Ed +.Pp +The +.Li ifma_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 ifma_name +field references an AF_LINK address structure, containing the name of the +interface where the membership exists. +.Pp +The +.Li ifma_addr +references the address that this membership is for. +.Pp +The +.Li ifma_lladdr +field references a link-layer translation for the protocol-level address in +.Li ifma_addr , +if one is set, otherwise it is NULL. +.Pp +The data returned by +.Fn getifmaddrs +is dynamically allocated and should be freed using +.Fn freeifmaddrs +when no longer needed. +.Sh RETURN VALUES +.Rv -std getifmaddrs +.Sh ERRORS +The +.Fn getifmaddrs +may fail and set +.Va errno +for any of the errors specified for the library routines +.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 sysctl 3 , +.Xr networking 4 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +implementation first appeared in +.Fx 5.2 . diff --git a/lib/libc/net/getifmaddrs.c b/lib/libc/net/getifmaddrs.c new file mode 100644 index 0000000..40475ae --- /dev/null +++ b/lib/libc/net/getifmaddrs.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2003 Bruce M. Simpson. + * 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bruce M. Simpson. + * 4. Neither the name of Bruce M. Simpson nor the names of other + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRUCE M. SIMPSON AND AFFILIATES + * ``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 BRUCE M. SIMPSON OR CONTRIBUTORS + * 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include <sys/param.h> +#include <sys/sysctl.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <net/route.h> + +#include <errno.h> +#include <ifaddrs.h> +#include <stdlib.h> +#include <string.h> +#include "un-namespace.h" + +#define SALIGN (sizeof(long) - 1) +#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ + (SALIGN + 1)) +#define MAX_SYSCTL_TRY 5 +#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) + +int +getifmaddrs(struct ifmaddrs **pif) +{ + int icnt = 1; + int dcnt = 0; + int ntry = 0; + u_short idx = 0; + size_t len; + size_t needed; + int mib[6]; + int i; + char *buf; + char *data; + char *names; + char *next; + char *p; + struct ifma_msghdr *ifmam; + struct ifmaddrs *ifa, *ift; + struct rt_msghdr *rtm; + struct sockaddr *sa; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; /* protocol */ + mib[3] = 0; /* wildcard address family */ + mib[4] = NET_RT_IFMALIST; + mib[5] = 0; /* no flags */ + do { + 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) { + if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { + free(buf); + return (-1); + } + free(buf); + buf = NULL; + } + } while (buf == NULL); + + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + switch (rtm->rtm_type) { + case RTM_NEWMADDR: + ifmam = (struct ifma_msghdr *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + icnt++; + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + dcnt += len; + p += len; + } + break; + } + } + + data = malloc(sizeof(struct ifmaddrs) * icnt + dcnt); + if (data == NULL) { + free(buf); + return (-1); + } + + ifa = (struct ifmaddrs *)(void *)data; + data += sizeof(struct ifmaddrs) * icnt; + names = data + dcnt; + + memset(ifa, 0, sizeof(struct ifmaddrs) * icnt); + ift = ifa; + + idx = 0; + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + + switch (rtm->rtm_type) { + case RTM_NEWMADDR: + ifmam = (struct ifma_msghdr *)(void *)rtm; + if ((ifmam->ifmam_addrs & RTA_IFA) == 0) + break; + + p = (char *)(ifmam + 1); + for (i = 0; i < RTAX_MAX; i++) { + if ((RTA_MASKS & ifmam->ifmam_addrs & + (1 << i)) == 0) + continue; + sa = (struct sockaddr *)(void *)p; + len = SA_RLEN(sa); + switch (i) { + case RTAX_GATEWAY: + ift->ifma_lladdr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFP: + ift->ifma_name = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + case RTAX_IFA: + ift->ifma_addr = + (struct sockaddr *)(void *)data; + memcpy(data, p, len); + data += len; + break; + + default: + data += len; + break; + } + p += len; + } + ift->ifma_next = ift + 1; + ift = ift->ifma_next; + break; + } + } + + free(buf); + + if (ift > ifa) { + ift--; + ift->ifma_next = NULL; + *pif = ifa; + } else { + *pif = NULL; + free(ifa); + } + return (0); +} + +void +freeifmaddrs(struct ifmaddrs *ifmp) +{ + + free(ifmp); +} |