Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Introduce new sysctls for obtaining interface-specific addre...



details:   https://anonhg.NetBSD.org/src/rev/608a54301520
branches:  trunk
changeset: 796561:608a54301520
user:      joerg <joerg%NetBSD.org@localhost>
date:      Tue Jun 10 09:38:30 2014 +0000

description:
Introduce new sysctls for obtaining interface-specific addresses:
- net.sdl for the active link-layer adddress (the MAC)
- net.ether.multicast for the Ethernet multicast addresses
- net.inet6.multicast for the IPv6 multicast groups
- net.inet6.multicast_kludge for temporarily removed multicast groups

Use this sysctls for replacing the kmem grovelling in ifmcstat(8).

diffstat:

 sys/net/if.c                 |   45 ++++++-
 sys/net/if_ether.h           |    8 +-
 sys/net/if_ethersubr.c       |   72 ++++++++++-
 sys/netinet6/mld6.c          |  147 ++++++++++++++++++++-
 usr.sbin/ifmcstat/Makefile   |    6 +-
 usr.sbin/ifmcstat/ifmcstat.c |  301 ++++++++++++++++++++++--------------------
 6 files changed, 423 insertions(+), 156 deletions(-)

diffs (truncated from 739 to 300 lines):

diff -r 8d5136b1f058 -r 608a54301520 sys/net/if.c
--- a/sys/net/if.c      Tue Jun 10 07:26:19 2014 +0000
+++ b/sys/net/if.c      Tue Jun 10 09:38:30 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.279 2014/06/09 12:57:04 rmind Exp $   */
+/*     $NetBSD: if.c,v 1.280 2014/06/10 09:38:30 joerg Exp $   */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.279 2014/06/09 12:57:04 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.280 2014/06/10 09:38:30 joerg Exp $");
 
 #include "opt_inet.h"
 
@@ -2457,3 +2457,44 @@
                       CTL_NET, pf, ipn, qid, IFQCTL_DROPS, CTL_EOL);
 }
 #endif /* INET || INET6 */
+
+static int
+if_sdl_sysctl(SYSCTLFN_ARGS)
+{
+       struct ifnet *ifp;
+       const struct sockaddr_dl *sdl;
+
+       if (namelen != 1)
+               return EINVAL;
+
+       ifp = if_byindex(name[0]);
+       if (ifp == NULL)
+               return ENODEV;
+
+       sdl = ifp->if_sadl;
+       if (sdl == NULL) {
+               *oldlenp = 0;
+               return 0;
+       }
+
+       if (oldp == NULL) {
+               *oldlenp = sdl->sdl_alen;
+               return 0;
+       }
+
+       if (*oldlenp >= sdl->sdl_alen)
+               *oldlenp = sdl->sdl_alen;
+       return sysctl_copyout(l, &sdl->sdl_data[sdl->sdl_nlen], oldp, *oldlenp);
+}
+
+SYSCTL_SETUP(sysctl_net_sdl_setup, "sysctl net.sdl subtree setup")
+{
+       const struct sysctlnode *rnode = NULL;
+
+       sysctl_createv(clog, 0, NULL, &rnode,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "sdl",
+                      SYSCTL_DESCR("Get active link-layer address"),
+                      if_sdl_sysctl, 0, NULL, 0,
+                      CTL_NET, CTL_CREATE, CTL_EOL);
+}
diff -r 8d5136b1f058 -r 608a54301520 sys/net/if_ether.h
--- a/sys/net/if_ether.h        Tue Jun 10 07:26:19 2014 +0000
+++ b/sys/net/if_ether.h        Tue Jun 10 09:38:30 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ether.h,v 1.62 2014/04/23 23:17:22 pooka Exp $      */
+/*     $NetBSD: if_ether.h,v 1.63 2014/06/10 09:38:30 joerg Exp $      */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -228,6 +228,12 @@
        LIST_ENTRY(ether_multi) enm_list;
 };
 
+struct ether_multi_sysctl {
+       u_int   enm_refcount;
+       uint8_t enm_addrlo[ETHER_ADDR_LEN];
+       uint8_t enm_addrhi[ETHER_ADDR_LEN];
+};
+
 /*
  * Structure used by macros below to remember position when stepping through
  * all of the ether_multi records.
diff -r 8d5136b1f058 -r 608a54301520 sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c    Tue Jun 10 07:26:19 2014 +0000
+++ b/sys/net/if_ethersubr.c    Tue Jun 10 09:38:30 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ethersubr.c,v 1.199 2014/06/05 23:48:16 rmind Exp $ */
+/*     $NetBSD: if_ethersubr.c,v 1.200 2014/06/10 09:38:30 joerg Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.199 2014/06/05 23:48:16 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.200 2014/06/10 09:38:30 joerg Exp $");
 
 #include "opt_inet.h"
 #include "opt_atalk.h"
@@ -78,6 +78,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/sysctl.h>
 #include <sys/kernel.h>
 #include <sys/callout.h>
 #include <sys/malloc.h>
@@ -1489,3 +1490,70 @@
        }
        return 0;
 }
+
+static int
+ether_multicast_sysctl(SYSCTLFN_ARGS)
+{
+       struct ether_multi *enm;
+       struct ether_multi_sysctl addr;
+       struct ifnet *ifp;
+       struct ethercom *ec;
+       int error;
+       size_t written;
+
+       if (namelen != 1)
+               return EINVAL;
+
+       ifp = if_byindex(name[0]);
+       if (ifp == NULL)
+               return ENODEV;
+       if (ifp->if_type != IFT_ETHER) {
+               *oldlenp = 0;
+               return 0;
+       }
+       ec = (struct ethercom *)ifp;
+
+       if (oldp == NULL) {
+               *oldlenp = ec->ec_multicnt * sizeof(addr);
+               return 0;
+       }
+
+       memset(&addr, 0, sizeof(addr));
+       error = 0;
+       written = 0;
+
+       LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) {
+               if (written + sizeof(addr) > *oldlenp)
+                       break;
+               addr.enm_refcount = enm->enm_refcount;
+               memcpy(addr.enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
+               memcpy(addr.enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
+               error = sysctl_copyout(l, &addr, oldp, sizeof(addr));
+               if (error)
+                       break;
+               written += sizeof(addr);
+               oldp = (char *)oldp + sizeof(addr);
+       }
+
+       *oldlenp = written;
+       return error;
+}
+
+SYSCTL_SETUP(sysctl_net_ether_setup, "sysctl net.ether subtree setup")
+{
+       const struct sysctlnode *rnode = NULL;
+
+       sysctl_createv(clog, 0, NULL, &rnode,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "ether",
+                      SYSCTL_DESCR("Ethernet-specific information"),
+                      NULL, 0, NULL, 0,
+                      CTL_NET, CTL_CREATE, CTL_EOL);
+
+       sysctl_createv(clog, 0, &rnode, NULL,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "multicast",
+                      SYSCTL_DESCR("multicast addresses"),
+                      ether_multicast_sysctl, 0, NULL, 0,
+                      CTL_CREATE, CTL_EOL);
+}
diff -r 8d5136b1f058 -r 608a54301520 sys/netinet6/mld6.c
--- a/sys/netinet6/mld6.c       Tue Jun 10 07:26:19 2014 +0000
+++ b/sys/netinet6/mld6.c       Tue Jun 10 09:38:30 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mld6.c,v 1.56 2014/06/02 11:02:20 joerg Exp $  */
+/*     $NetBSD: mld6.c,v 1.57 2014/06/10 09:38:30 joerg Exp $  */
 /*     $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $   */
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.56 2014/06/02 11:02:20 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.57 2014/06/10 09:38:30 joerg Exp $");
 
 #include "opt_inet.h"
 
@@ -897,3 +897,146 @@
        LIST_REMOVE(mk, mk_entry);
        free(mk, M_IPMADDR);
 }
+
+static int
+in6_mkludge_sysctl(SYSCTLFN_ARGS)
+{
+       struct multi6_kludge *mk;
+       struct in6_multi *in6m;
+       int error;
+       uint32_t tmp;
+       size_t written;
+
+       if (namelen != 1)
+               return EINVAL;
+
+       if (oldp == NULL) {
+               *oldlenp = 0;
+               LIST_FOREACH(mk, &in6_mk, mk_entry) {
+                       if (mk->mk_ifp->if_index == name[0])
+                               continue;
+                       LIST_FOREACH(in6m, &mk->mk_head, in6m_entry) {
+                               *oldlenp += sizeof(struct in6_addr) +
+                                   sizeof(uint32_t);
+                       }
+               }
+               return 0;
+       }
+
+       error = 0;
+       written = 0;
+       LIST_FOREACH(mk, &in6_mk, mk_entry) {
+               if (mk->mk_ifp->if_index == name[0])
+                       continue;
+               LIST_FOREACH(in6m, &mk->mk_head, in6m_entry) {
+                       if (written + sizeof(struct in6_addr) +
+                           sizeof(uint32_t) > *oldlenp)
+                               goto done;
+                       error = sysctl_copyout(l, &in6m->in6m_addr,
+                           oldp, sizeof(struct in6_addr));
+                       if (error)
+                               goto done;
+                       oldp = (char *)oldp + sizeof(struct in6_addr);
+                       written += sizeof(struct in6_addr);
+                       tmp = in6m->in6m_refcount;
+                       error = sysctl_copyout(l, &tmp, oldp, sizeof(tmp));
+                       if (error)
+                               goto done;
+                       oldp = (char *)oldp + sizeof(tmp);
+                       written += sizeof(tmp);
+               }
+       }
+
+done:
+       *oldlenp = written;
+       return error;
+}
+
+static int
+in6_multicast_sysctl(SYSCTLFN_ARGS)
+{
+       struct ifnet *ifp;
+       struct ifaddr *ifa;
+       struct in6_ifaddr *ifa6;
+       struct in6_multi *in6m;
+       uint32_t tmp;
+       int error;
+       size_t written;
+
+       if (namelen != 1)
+               return EINVAL;
+
+       ifp = if_byindex(name[0]);
+       if (ifp == NULL)
+               return ENODEV;
+
+       if (oldp == NULL) {
+               *oldlenp = 0;
+               TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+                       if (ifa->ifa_addr == NULL)
+                               continue;
+                       if (ifa->ifa_addr->sa_family != AF_INET6)
+                               continue;
+                       ifa6 = (struct in6_ifaddr *)ifa;
+                       LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) {
+                               *oldlenp += 2 * sizeof(struct in6_addr) +
+                                   sizeof(uint32_t);
+                       }
+               }
+               return 0;
+       }
+
+       error = 0;
+       written = 0;
+       TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+               if (ifa->ifa_addr == NULL)
+                       continue;
+               if (ifa->ifa_addr->sa_family != AF_INET6)
+                       continue;



Home | Main Index | Thread Index | Old Index