Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Nov 2003 12:20:55 +0000
From:      Bruce M Simpson <bms@spc.org>
To:        harti@freebsd.org
Cc:        Robert Watson <rwatson@freebsd.org>
Subject:   Re: Viewing multicast group membership?
Message-ID:  <20031112122055.GD22320@saboteur.dek.spc.org>
In-Reply-To: <20031111092650.P7611@beagle.fokus.fraunhofer.de>
References:  <20031110073822.GA20611@saboteur.dek.spc.org> <Pine.NEB.3.96L.1031110131422.59199A-100000@fledge.watson.org> <20031110191454.GC662@saboteur.dek.spc.org> <20031110204652.A84670@beagle.fokus.fraunhofer.de> <20031110221139.GB2441@saboteur.dek.spc.org> <20031111092650.P7611@beagle.fokus.fraunhofer.de>

next in thread | previous in thread | raw e-mail | index | archive | help

--NDin8bjvE/0mNLFQ
Content-Type: multipart/mixed; boundary="4Ckj6UjgE2iN1+kY"
Content-Disposition: inline


--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Tue, Nov 11, 2003 at 09:29:49AM +0100, Harti Brandt wrote:
> Here you are. This was even once (about a year ago) reviewed by someone,
> but did make it into the tree, because I did not insist.

Ok. The NET_RT_IFMALIST sysctl is not completely identical to the existing
NET_RT_IFLIST interface. I've made a few changes to your diff, and
rolled a userland interface; please review.

BMS

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="rtsock.diff"
Content-Transfer-Encoding: quoted-printable

Index: rtsock.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/rtsock.c,v
retrieving revision 1.89
diff -u -r1.89 rtsock.c
--- rtsock.c	5 Mar 2003 19:24:22 -0000	1.89
+++ rtsock.c	12 Nov 2003 11:28:43 -0000
@@ -73,6 +73,7 @@
 static int	rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
 static int	sysctl_dumpentry(struct radix_node *rn, void *vw);
 static int	sysctl_iflist(int af, struct walkarg *w);
+static int	sysctl_ifmalist(int af, struct walkarg *w);
 static int	 route_output(struct mbuf *, struct socket *);
 static void	 rt_setmetrics(u_long, struct rt_metrics *, struct rt_metrics =
*);
=20
@@ -658,6 +659,10 @@
 		len =3D sizeof(struct if_msghdr);
 		break;
=20
+	case RTM_NEWMADDR:
+		len =3D sizeof(struct ifma_msghdr);
+		break;
+
 	default:
 		len =3D sizeof(struct rt_msghdr);
 	}
@@ -994,6 +999,61 @@
 	return (error);
 }
=20
+int
+sysctl_ifmalist(af, w)
+	int	af;
+	register struct	walkarg *w;
+{
+	register struct ifnet *ifp;
+	struct ifmultiaddr *ifma;
+	struct	rt_addrinfo info;
+	int	len, error =3D 0;
+
+	bzero((caddr_t)&info, sizeof(info));
+	/* IFNET_RLOCK(); */		/* could sleep XXX */
+	TAILQ_FOREACH(ifp, &ifnet, if_link) {
+		if (w->w_arg && w->w_arg !=3D ifp->if_index)
+			continue;
+		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+			if (af && af !=3D ifma->ifma_addr->sa_family)
+				continue;
+			if (jailed(curproc->p_ucred) &&
+			    prison_if(curproc->p_ucred, ifma->ifma_addr))
+				continue;
+			info.rti_addrs =3D RTA_IFA;
+			info.rti_info[RTAX_IFA] =3D ifma->ifma_addr;
+			if (TAILQ_FIRST(&ifp->if_addrhead)) {
+				info.rti_addrs |=3D RTA_IFP;
+				info.rti_info[RTAX_IFP] =3D
+				    TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
+			} else
+				info.rti_info[RTAX_IFP] =3D NULL;
+
+			if (ifma->ifma_addr->sa_family !=3D AF_LINK) {
+				info.rti_addrs |=3D RTA_GATEWAY;
+				info.rti_info[RTAX_GATEWAY] =3D ifma->ifma_lladdr;
+			} else
+				info.rti_info[RTAX_GATEWAY] =3D NULL;
+
+			len =3D rt_msg2(RTM_NEWMADDR, &info, 0, w);
+			if (w->w_req && w->w_tmem) {
+				register struct ifma_msghdr *ifmam;
+
+				ifmam =3D (struct ifma_msghdr *)w->w_tmem;
+				ifmam->ifmam_index =3D ifma->ifma_ifp->if_index;
+				ifmam->ifmam_flags =3D 0;
+				ifmam->ifmam_addrs =3D info.rti_addrs;
+				error =3D SYSCTL_OUT(w->w_req, w->w_tmem, len);
+				if (error)
+					goto done;
+			}
+		}
+	}
+done:
+	/* IFNET_RUNLOCK(); */ /* XXX */
+	return (error);
+}
+
 static int
 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
 {
@@ -1046,6 +1106,11 @@
=20
 	case NET_RT_IFLIST:
 		error =3D sysctl_iflist(af, &w);
+		break;
+
+	case NET_RT_IFMALIST:
+		error =3D sysctl_ifmalist(af, &w);
+		break;
 	}
 	splx(s);
 	if (w.w_tmem)

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ifmaddrs.h"


struct ifmaddrs {
	struct ifmaddrs	*ifma_next;
	struct sockaddr	*ifma_name;
	struct sockaddr	*ifma_addr;
	struct sockaddr	*ifma_gateway;
	void		*ifma_data;
};

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="getifmaddrs.c"
Content-Transfer-Encoding: quoted-printable


#include <sys/cdefs.h>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/param.h>
#include <net/route.h>
#include <sys/sysctl.h>
#include <net/if_dl.h>

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "ifmaddrs.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

#define MAX_SYSCTL_TRY 5

int
getifmaddrs(struct ifmaddrs **pif)
{
	int icnt =3D 1;
	int dcnt =3D 0;
	int ncnt =3D 0;
	int ntry =3D 0;
	int mib[6];
	size_t needed;
	char *buf;
	char *next;
	char *p, *p0;
	struct rt_msghdr *rtm;
	struct ifma_msghdr *ifmam;
	struct sockaddr *sa;
	struct ifmaddrs *ifa, *ift;
	u_short idx =3D 0;
	int i;
	size_t len, alen;
	char *data;
	char *names;

	mib[0] =3D CTL_NET;
	mib[1] =3D PF_ROUTE;
	mib[2] =3D 0;             /* protocol */
	mib[3] =3D 0;             /* wildcard address family */
	mib[4] =3D NET_RT_IFMALIST;
	mib[5] =3D 0;             /* no flags */
	do {
		if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
			return (-1);
		if ((buf =3D malloc(needed)) =3D=3D NULL)
			return (-1);
		if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
			if (errno !=3D ENOMEM || ++ntry >=3D MAX_SYSCTL_TRY) {
				free(buf);
				return (-1);
			}
			free(buf);
			buf =3D NULL;
		}=20
	} while (buf =3D=3D NULL);

	for (next =3D buf; next < buf + needed; next +=3D rtm->rtm_msglen) {
		rtm =3D (struct rt_msghdr *)(void *)next;
		if (rtm->rtm_version !=3D RTM_VERSION)
			continue;
		switch (rtm->rtm_type) {
		case RTM_NEWMADDR:
			ifmam =3D (struct ifma_msghdr *)(void *)rtm;
#define	RTA_MASKS	(RTA_GATEWAY | RTA_IFP | RTA_IFA)
			if ((ifmam->ifmam_addrs & RTA_IFA) =3D=3D 0)
				break;
			p =3D (char *)(void *)(ifmam + 1);
			++icnt;
#ifdef	HAVE_IFAM_DATA
			dcnt +=3D sizeof(ifmam->ifmam_data) + ALIGNBYTES;
#endif	/* HAVE_IFAM_DATA */
			/* Scan to look for length of address */
			alen =3D 0;
			for (p0 =3D p, i =3D 0; i < RTAX_MAX; i++) {
				if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i))
				    =3D=3D 0)
					continue;
				sa =3D (struct sockaddr *)(void *)p;
				len =3D SA_RLEN(sa);
				if (i =3D=3D RTAX_IFA) {
					alen =3D len;
					break;
				}
				p +=3D len;
			}
			for (p =3D p0, i =3D 0; i < RTAX_MAX; i++) {
				if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i))
				    =3D=3D 0)
					continue;
				sa =3D (struct sockaddr *)(void *)p;
				len =3D SA_RLEN(sa);
				dcnt +=3D len;
				p +=3D len;
			}
			break;
		}
	}

	if (icnt + dcnt + ncnt =3D=3D 1) {
		*pif =3D NULL;
		free(buf);
		return (0);
	}
	data =3D malloc(sizeof(struct ifmaddrs) * icnt + dcnt + ncnt);
	if (data =3D=3D NULL) {
		free(buf);
		return(-1);
	}

	ifa =3D (struct ifmaddrs *)(void *)data;
	data +=3D sizeof(struct ifmaddrs) * icnt;
	names =3D data + dcnt;

	memset(ifa, 0, sizeof(struct ifmaddrs) * icnt);
	ift =3D ifa;

	idx =3D 0;
	for (next =3D buf; next < buf + needed; next +=3D rtm->rtm_msglen) {
		rtm =3D (struct rt_msghdr *)(void *)next;
		if (rtm->rtm_version !=3D RTM_VERSION)
			continue;
		switch (rtm->rtm_type) {
		case RTM_NEWMADDR:
			ifmam =3D (struct ifma_msghdr *)(void *)rtm;
			if ((ifmam->ifmam_addrs & RTA_IFA) =3D=3D 0)
				break;
			ift->ifma_data =3D NULL;
			p =3D (char *)(void *)(ifmam + 1);
			/* Scan to look for length of address */
			alen =3D 0;
			for (p0 =3D p, i =3D 0; i < RTAX_MAX; i++) {
				if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i))
				    =3D=3D 0)
					continue;
				sa =3D (struct sockaddr *)(void *)p;
				len =3D SA_RLEN(sa);
				if (i =3D=3D RTAX_IFA) {
					alen =3D len;
					break;
				}
				p +=3D len;
			}
			for (p =3D p0, i =3D 0; i < RTAX_MAX; i++) {
				if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i))
				    =3D=3D 0)
					continue;
				sa =3D (struct sockaddr *)(void *)p;
				len =3D SA_RLEN(sa);
				switch (i) {
				case RTAX_GATEWAY:
					ift->ifma_gateway =3D
					    (struct sockaddr *)(void *)data;
					memcpy(data, p, len);
					data +=3D len;
					break;

				case RTAX_IFP:
					ift->ifma_name =3D
					    (struct sockaddr *)(void *)data;
					memcpy(data, p, len);
					data +=3D len;
					break;

				case RTAX_IFA:
					ift->ifma_addr =3D
					    (struct sockaddr *)(void *)data;
					memcpy(data, p, len);
					data +=3D len;
					break;

				default:
					data +=3D len;
					break;
				}
				p +=3D len;
			}
			ift =3D (ift->ifma_next =3D ift + 1);
			break;
		}
	}

	free(buf);

	if (--ift >=3D ifa) {
		ift->ifma_next =3D NULL;
		*pif =3D ifa;
	} else {
		*pif =3D NULL;
		free(ifa);
	}
	return (0);
}

void
freeifmaddrs(struct ifmaddrs *ifp)
{

	free(ifp);
}

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=Makefile

# $Id$

PROG= matest
SRCS= getifmaddrs.c matest.c

CFLAGS= -g3 -Wall

NOMAN=	defined

.include <bsd.prog.mk>

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="matest.c"

#include <sys/types.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/if_var.h>
#include <net/if_mib.h>
#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <ctype.h>
#include <err.h>
#include <ifaddrs.h>
#include <sysexits.h>

#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

#include "ifmaddrs.h"

extern int getifmaddrs(struct ifmaddrs **ifap);
extern void freeifmaddrs(struct ifmaddrs *ifp);
void ifmalist_dump(void);

int
main(int argc, char *argv[])
{
	ifmalist_dump();
	exit(EXIT_SUCCESS);
}

union sockunion {
        struct sockaddr_storage ss;
        struct sockaddr sa;
        struct sockaddr_dl sdl;
        struct sockaddr_in sin;
	struct sockaddr_in6 sin6;
};
typedef union sockunion sockunion_t;

void
ifmalist_dump(void)
{
	struct ifmaddrs *ifmap, *ifma;
	sockunion_t *psa;

	if (getifmaddrs(&ifmap))
		err(EX_OSERR, "getifmaddrs");

	for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
		fprintf(stderr, "%p: ", ifma);

		psa = (sockunion_t *)ifma->ifma_name;
		if (psa != NULL) {
			fprintf(stderr, "name AF(%d) ", psa->sa.sa_family);
			switch (psa->sa.sa_family) {
			case AF_INET:
				fprintf(stderr, "%s ",
				    inet_ntoa(psa->sin.sin_addr));
				break;

			case AF_LINK:
				fprintf(stderr, "%s ", link_ntoa(&psa->sdl));
				break;
			}
		} else
			fprintf(stderr, "name NULL ");

		psa = (sockunion_t *)ifma->ifma_addr;
		if (psa != NULL) {
			fprintf(stderr, "addr AF(%d) ", psa->sa.sa_family);
			switch (psa->sa.sa_family) {
			case AF_INET:
				fprintf(stderr, "%s ",
				    inet_ntoa(psa->sin.sin_addr));
				break;

			case AF_INET6: {
				void *addr;
				static char addrbuf[INET6_ADDRSTRLEN];

				addr = &psa->sin6.sin6_addr;
				inet_ntop(psa->sa.sa_family, addr, addrbuf, sizeof(addrbuf));
				fprintf(stderr, "%s ", addrbuf);
			}
			break;

			case AF_LINK:
				fprintf(stderr, "%s ", link_ntoa(&psa->sdl));
				break;
			}
		} else
			fprintf(stderr, "addr NULL ");

		psa = (sockunion_t *)ifma->ifma_gateway;
		if (psa != NULL) {
			fprintf(stderr, "gw AF(%d) ", psa->sa.sa_family);
			switch (psa->sa.sa_family) {
			case AF_INET:
				fprintf(stderr, "%s ",
				    inet_ntoa(psa->sin.sin_addr));
				break;

			case AF_LINK:
				fprintf(stderr, "%s ", link_ntoa(&psa->sdl));
				break;
			}
		} else
			fprintf(stderr, "gw NULL ");

		fputc('\n', stderr);
	}

	freeifmaddrs(ifmap);
}

--4Ckj6UjgE2iN1+kY--

--NDin8bjvE/0mNLFQ
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Comment: ''

iD8DBQE/siWnueUpAYYNtTsRAnoaAJ99BxIJDPfHuDq1NCUCqw8/EeRTcwCghufB
POj3BPpMCws/wpUgfMEk5VI=
=kYkF
-----END PGP SIGNATURE-----

--NDin8bjvE/0mNLFQ--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031112122055.GD22320>