summaryrefslogtreecommitdiffstats
path: root/sys/net/rtsock.c
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2003-11-14 18:48:15 +0000
committerbms <bms@FreeBSD.org>2003-11-14 18:48:15 +0000
commit0cfaf203b6dc7906d6cf6e6df3d4999dec616f45 (patch)
treee811cc6977ff46eeba858fd2be6f296f56f6432c /sys/net/rtsock.c
parent1e116ec1a8b7c481f5081d48ea2ede7817c2e24f (diff)
downloadFreeBSD-src-0cfaf203b6dc7906d6cf6e6df3d4999dec616f45.zip
FreeBSD-src-0cfaf203b6dc7906d6cf6e6df3d4999dec616f45.tar.gz
Add a sysctl MIB, NET_RT_IFMALIST, to retrieve multicast group memberships
in a protocol-independent way. Submitted by: harti
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r--sys/net/rtsock.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index ffde557..7a6c6e3 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -85,6 +85,7 @@ static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *);
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 *);
static void rt_dispatch(struct mbuf *, struct sockaddr *);
@@ -684,6 +685,10 @@ again:
len = sizeof(struct if_msghdr);
break;
+ case RTM_NEWMADDR:
+ len = sizeof(struct ifma_msghdr);
+ break;
+
default:
len = sizeof(struct rt_msghdr);
}
@@ -1014,6 +1019,61 @@ done:
return (error);
}
+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 = 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 != ifp->if_index)
+ continue;
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (af && af != ifma->ifma_addr->sa_family)
+ continue;
+ if (jailed(curproc->p_ucred) &&
+ prison_if(curproc->p_ucred, ifma->ifma_addr))
+ continue;
+ info.rti_addrs = RTA_IFA;
+ info.rti_info[RTAX_IFA] = ifma->ifma_addr;
+ if (TAILQ_FIRST(&ifp->if_addrhead)) {
+ info.rti_addrs |= RTA_IFP;
+ info.rti_info[RTAX_IFP] =
+ TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
+ } else
+ info.rti_info[RTAX_IFP] = NULL;
+
+ if (ifma->ifma_addr->sa_family != AF_LINK) {
+ info.rti_addrs |= RTA_GATEWAY;
+ info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr;
+ } else
+ info.rti_info[RTAX_GATEWAY] = NULL;
+
+ len = rt_msg2(RTM_NEWMADDR, &info, 0, w);
+ if (w->w_req && w->w_tmem) {
+ register struct ifma_msghdr *ifmam;
+
+ ifmam = (struct ifma_msghdr *)w->w_tmem;
+ ifmam->ifmam_index = ifma->ifma_ifp->if_index;
+ ifmam->ifmam_flags = 0;
+ ifmam->ifmam_addrs = info.rti_addrs;
+ error = 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)
{
@@ -1066,6 +1126,11 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
case NET_RT_IFLIST:
error = sysctl_iflist(af, &w);
+ break;
+
+ case NET_RT_IFMALIST:
+ error = sysctl_ifmalist(af, &w);
+ break;
}
splx(s);
if (w.w_tmem)
OpenPOWER on IntegriCloud