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>