summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>1999-03-01 04:44:45 +0000
committerJason Wright <jason@cvs.openbsd.org>1999-03-01 04:44:45 +0000
commit1211d39b07c91e33d52e5bf82d3fcda41715f51b (patch)
tree4140b15b412266fa14868707cb59c732622c166b
parent4a6d5c512e998e2de70b33261943e87d2dcc3780 (diff)
completely (almost) revamped ioctl's:
o new ioctls for getting/setting cache size (default == 100) o changed SIOCBRDGRT -> SIOCBRDGRTS o changed SIOCBRDGIDX -> SIOCBRDGIFS
-rw-r--r--sys/net/if_bridge.c236
-rw-r--r--sys/net/if_bridge.h55
-rw-r--r--sys/sys/sockio.h8
-rw-r--r--usr.sbin/brconfig/brconfig.c144
4 files changed, 336 insertions, 107 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 72646e8a9de..e1eb0d47fee 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.2 1999/02/27 21:19:27 jason Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.3 1999/03/01 04:44:44 jason Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -67,6 +67,13 @@
#endif
#define BRIDGE_RTABLE_MASK (BRIDGE_RTABLE_SIZE - 1)
+/*
+ * Maximum number of addresses to cache
+ */
+#ifndef BRIDGE_RTABLE_MAX
+#define BRIDGE_RTABLE_MAX 100
+#endif
+
extern int ifqmaxlen;
/*
@@ -74,7 +81,7 @@ extern int ifqmaxlen;
*/
struct bridge_iflist {
LIST_ENTRY(bridge_iflist) next; /* next in list */
- struct ifnet *ifp; /* member interface */
+ struct ifnet *ifp; /* member interface */
u_int32_t bif_flags; /* member flags */
};
@@ -83,17 +90,19 @@ struct bridge_iflist {
*/
struct bridge_rtnode {
LIST_ENTRY(bridge_rtnode) brt_next; /* next in list */
- struct ifnet *brt_if; /* destination ifs */
+ struct ifnet *brt_if; /* destination ifs */
u_int32_t brt_age; /* age counter */
- struct ether_addr brt_addr; /* destination addr */
+ struct ether_addr brt_addr; /* dst addr */
};
/*
* Software state for each bridge
*/
struct bridge_softc {
- struct ifnet sc_if; /* the interface */
+ struct ifnet sc_if; /* the interface */
u_int32_t sc_brtageidx; /* route age index */
+ u_int32_t sc_brtmax; /* max # addresses */
+ u_int32_t sc_brtcnt; /* current # addrs */
LIST_HEAD(, bridge_iflist) sc_iflist; /* interface list */
LIST_HEAD(bridge_rthead, bridge_rtnode) *sc_rts;/* hash table */
};
@@ -107,9 +116,11 @@ struct mbuf * bridge_broadcast __P((struct bridge_softc *sc,
struct ifnet *, struct ether_header *, struct mbuf *));
void bridge_stop __P((struct bridge_softc *));
void bridge_init __P((struct bridge_softc *));
+int bridge_bifconf __P((struct bridge_softc *, struct ifbifconf *));
-int bridge_rtfind __P((struct bridge_softc *, struct ifbrtreq *));
+int bridge_rtfind __P((struct bridge_softc *, struct ifbaconf *));
void bridge_rtage __P((void *));
+void bridge_rttrim __P((struct bridge_softc *));
void bridge_rtdelete __P((struct bridge_softc *, struct ifnet *));
struct ifnet * bridge_rtupdate __P((struct bridge_softc *,
struct ether_addr *, struct ifnet *ifp));
@@ -137,12 +148,12 @@ void
bridgeattach(unused)
int unused;
{
- register int i;
+ int i;
struct ifnet *ifp;
for (i = 0; i < NBRIDGE; i++) {
+ bridgectl[i].sc_brtmax = BRIDGE_RTABLE_MAX;
LIST_INIT(&bridgectl[i].sc_iflist);
-
ifp = &bridgectl[i].sc_if;
sprintf(ifp->if_xname, "bridge%d", i);
ifp->if_softc = &bridgectl[i];
@@ -153,7 +164,6 @@ bridgeattach(unused)
ifp->if_type = IFT_PROPVIRTUAL;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_hdrlen = sizeof(struct ether_header);
-
if_attach(ifp);
}
}
@@ -168,8 +178,10 @@ bridge_ioctl(ifp, cmd, data)
struct ifnet *ifs;
struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
struct ifbreq *req = (struct ifbreq *)data;
- struct ifbrtreq *brtreq = (struct ifbrtreq *)data;
- int error = 0, s, i;
+ struct ifbaconf *baconf = (struct ifbaconf *)data;
+ struct ifbcachereq *bcachereq = (struct ifbcachereq *)data;
+ struct ifbifconf *bifconf = (struct ifbifconf *)data;
+ int error = 0, s;
struct bridge_iflist *p;
s = splimp();
@@ -184,7 +196,7 @@ bridge_ioctl(ifp, cmd, data)
/*
* Get pointer to ifnet structure for the named interface.
*/
- ifs = ifunit(req->ifsname);
+ ifs = ifunit(req->ifbr_ifsname);
if (ifs == NULL) { /* no such interface */
error = ENOENT;
break;
@@ -249,7 +261,7 @@ bridge_ioctl(ifp, cmd, data)
p = LIST_FIRST(&sc->sc_iflist);
while (p != NULL) {
- if (strncmp(p->ifp->if_xname, req->ifsname,
+ if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
sizeof(p->ifp->if_xname)) == 0) {
/*
* Remove the pointer back to us.
@@ -278,34 +290,22 @@ bridge_ioctl(ifp, cmd, data)
break;
}
break;
- case SIOCBRDGIDX:
- /*
- * Search through list looking for right element.
- */
- i = 0;
- p = LIST_FIRST(&sc->sc_iflist);
- while (p != NULL && i < req->index) {
- i++;
- p = LIST_NEXT(p, next);
- }
-
- /*
- * Make sure we didn't go off the end of the list.
- */
- if (p == NULL || req->index != i) {
- error = ENOENT;
- break;
- }
- /* found it */
- strncpy(req->ifsname, p->ifp->if_xname, sizeof(req->ifsname)-1);
- req->ifsname[sizeof(req->ifsname)-1] = '\0';
+ case SIOCBRDGIFS:
+ error = bridge_bifconf(sc, bifconf);
break;
- case SIOCBRDGRT:
+ case SIOCBRDGRTS:
if ((ifp->if_flags & IFF_RUNNING) == 0) {
error = ENETDOWN;
break;
}
- error = bridge_rtfind(sc, brtreq);
+ error = bridge_rtfind(sc, baconf);
+ break;
+ case SIOCBRDGGCACHE:
+ bcachereq->ifbc_size = sc->sc_brtmax;
+ break;
+ case SIOCBRDGSCACHE:
+ sc->sc_brtmax = bcachereq->ifbc_size;
+ bridge_rttrim(sc);
break;
case SIOCSIFFLAGS:
if ((ifp->if_flags & IFF_UP) == IFF_UP)
@@ -322,6 +322,51 @@ bridge_ioctl(ifp, cmd, data)
return (error);
}
+int
+bridge_bifconf(sc, bifc)
+ struct bridge_softc *sc;
+ struct ifbifconf *bifc;
+{
+ struct bridge_iflist *p;
+ u_int32_t total, i;
+ int error;
+ struct ifbreq breq;
+
+ p = LIST_FIRST(&sc->sc_iflist);
+ while (p != NULL) {
+ total++;
+ p = LIST_NEXT(p, next);
+ }
+
+ if (bifc->ifbic_len == 0) {
+ bifc->ifbic_len = total * sizeof(struct ifbreq);
+ return (0);
+ }
+
+ p = LIST_FIRST(&sc->sc_iflist);
+ i = 0;
+ while (p != NULL && bifc->ifbic_len > sizeof(breq)) {
+ strncpy(breq.ifbr_name, sc->sc_if.if_xname,
+ sizeof (breq.ifbr_name));
+ breq.ifbr_name[sizeof(breq.ifbr_name)-1] = '\0';
+ strncpy(breq.ifbr_ifsname, p->ifp->if_xname,
+ sizeof (breq.ifbr_ifsname));
+ breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname)-1] = '\0';
+ breq.ifbr_ifsflags = p->bif_flags;
+ error = copyout((caddr_t)&breq,
+ (caddr_t)(bifc->ifbic_req + i), sizeof(breq));
+ if (error) {
+ bifc->ifbic_len = i * sizeof(breq);
+ return (error);
+ }
+ p = LIST_NEXT(p, next);
+ i++;
+ bifc->ifbic_len -= sizeof(breq);
+ }
+ bifc->ifbic_len = i * sizeof(breq);
+ return (0);
+}
+
void
bridge_init(sc)
struct bridge_softc *sc;
@@ -385,6 +430,7 @@ bridge_stop(sc)
p = LIST_NEXT(n, brt_next);
LIST_REMOVE(n, brt_next);
free(n, M_DEVBUF);
+ sc->sc_brtcnt--;
n = p;
}
}
@@ -812,6 +858,10 @@ bridge_rtupdate(sc, ea, ifp)
h = bridge_hash(ea);
p = LIST_FIRST(&sc->sc_rts[h]);
if (p == NULL) {
+ if (sc->sc_brtcnt >= sc->sc_brtmax) {
+ splx(s);
+ return (NULL);
+ }
p = (struct bridge_rtnode *)
malloc(sizeof(struct bridge_rtnode),
M_DEVBUF, M_NOWAIT);
@@ -824,6 +874,7 @@ bridge_rtupdate(sc, ea, ifp)
p->brt_if = ifp;
p->brt_age = 1;
LIST_INSERT_HEAD(&sc->sc_rts[h], p, brt_next);
+ sc->sc_brtcnt++;
splx(s);
return (ifp);
}
@@ -841,6 +892,10 @@ bridge_rtupdate(sc, ea, ifp)
}
if (dir > 0) {
+ if (sc->sc_brtcnt >= sc->sc_brtmax) {
+ splx(s);
+ return (NULL);
+ }
p = (struct bridge_rtnode *)
malloc(sizeof(struct bridge_rtnode),
M_DEVBUF, M_NOWAIT);
@@ -853,11 +908,16 @@ bridge_rtupdate(sc, ea, ifp)
p->brt_if = ifp;
p->brt_age = 1;
LIST_INSERT_BEFORE(q, p, brt_next);
+ sc->sc_brtcnt++;
splx(s);
return (ifp);
}
if (p == NULL) {
+ if (sc->sc_brtcnt >= sc->sc_brtmax) {
+ splx(s);
+ return (NULL);
+ }
p = (struct bridge_rtnode *)
malloc(sizeof(struct bridge_rtnode),
M_DEVBUF, M_NOWAIT);
@@ -870,6 +930,7 @@ bridge_rtupdate(sc, ea, ifp)
p->brt_if = ifp;
p->brt_age = 1;
LIST_INSERT_AFTER(q, p, brt_next);
+ sc->sc_brtcnt++;
splx(s);
return (ifp);
}
@@ -954,6 +1015,60 @@ bridge_hash(addr)
return (c & BRIDGE_RTABLE_MASK);
}
+/*
+ * Trim the routing table so that we've got a number of routes
+ * less than or equal to the maximum.
+ */
+void
+bridge_rttrim(sc)
+ struct bridge_softc *sc;
+{
+ struct bridge_rtnode *n, *p;
+ int s, i;
+
+ s = splhigh();
+ if (sc->sc_rts == NULL) {
+ splx(s);
+ return;
+ }
+
+ /*
+ * Make sure we have to trim the address table
+ */
+ if (sc->sc_brtcnt <= sc->sc_brtmax) {
+ splx(s);
+ return;
+ }
+
+ /*
+ * Force an aging cycle, this might trim enough addresses.
+ */
+ splx(s);
+ bridge_rtage(sc);
+ s = splhigh();
+
+ if (sc->sc_brtcnt <= sc->sc_brtmax) {
+ splx(s);
+ return;
+ }
+
+ for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+ n = LIST_FIRST(&sc->sc_rts[i]);
+ while (n != NULL) {
+ p = LIST_NEXT(n, brt_next);
+ LIST_REMOVE(n, brt_next);
+ sc->sc_brtcnt--;
+ free(n, M_DEVBUF);
+ n = p;
+ if (sc->sc_brtcnt <= sc->sc_brtmax) {
+ splx(s);
+ return;
+ }
+ }
+ }
+ splx(s);
+}
+
void
bridge_rtage(vsc)
void *vsc;
@@ -987,6 +1102,7 @@ bridge_rtage(vsc)
n->brt_addr.ether_addr_octet[5]);
#endif
LIST_REMOVE(n, brt_next);
+ sc->sc_brtcnt--;
free(n, M_DEVBUF);
n = p;
}
@@ -1022,6 +1138,7 @@ bridge_rtdelete(sc, ifp)
if (n->brt_if == ifp) { /* found one */
p = LIST_NEXT(n, brt_next);
LIST_REMOVE(n, brt_next);
+ sc->sc_brtcnt--;
free(n, M_DEVBUF);
n = p;
}
@@ -1034,41 +1151,62 @@ bridge_rtdelete(sc, ifp)
}
/*
- * Find the route for a given index value in rq->index.
- * Returns 0 on success, otherwise an error value.
+ * Gather all of the routes for this interface.
*/
int
-bridge_rtfind(sc, rq)
+bridge_rtfind(sc, baconf)
struct bridge_softc *sc;
- struct ifbrtreq *rq;
+ struct ifbaconf *baconf;
{
- int i, s;
+ int i, s, error;
u_int32_t cnt;
struct bridge_rtnode *n;
+ struct ifbareq bareq;
s = splhigh();
+
if (sc->sc_rts == NULL) {
+ baconf->ifbac_len = 0;
+ splx(s);
+ return (0);
+ }
+
+ if (baconf->ifbac_len == 0) {
+ baconf->ifbac_len = sc->sc_brtcnt * sizeof(struct ifbareq);
splx(s);
- return (ENOENT);
+ return (0);
}
- for (cnt = 0, i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
+ for (i = 0, cnt = 0; i < BRIDGE_RTABLE_SIZE; i++) {
n = LIST_FIRST(&sc->sc_rts[i]);
while (n != NULL) {
- if (cnt == rq->index) {
- bcopy(&n->brt_addr, &rq->dst, sizeof(rq->dst));
- bcopy(n->brt_if->if_xname, rq->ifsname,
- IFNAMSIZ);
- rq->age = n->brt_age;
+ if (baconf->ifbac_len < sizeof(struct ifbareq)) {
+ baconf->ifbac_len = cnt *
+ sizeof(struct ifbareq);
splx(s);
return (0);
}
+ bcopy(n->brt_if->if_xname, bareq.ifba_name,
+ sizeof(bareq.ifba_name));
+ bcopy(&n->brt_addr, &bareq.ifba_dst,
+ sizeof(bareq.ifba_dst));
+ bareq.ifba_age = n->brt_age;
+ error = copyout((caddr_t)&bareq,
+ (caddr_t)(baconf->ifbac_req + cnt), sizeof(bareq));
+ if (error) {
+ baconf->ifbac_len = cnt *
+ sizeof(struct ifbareq);
+ splx(s);
+ return (error);
+ }
n = LIST_NEXT(n, brt_next);
cnt++;
}
}
+
+ baconf->ifbac_len = cnt * sizeof(struct ifbareq);
splx(s);
- return (ENOENT);
+ return (0);
}
#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
diff --git a/sys/net/if_bridge.h b/sys/net/if_bridge.h
index d127c091604..ec873697c1a 100644
--- a/sys/net/if_bridge.h
+++ b/sys/net/if_bridge.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.h,v 1.1 1999/02/26 17:01:32 jason Exp $ */
+/* $OpenBSD: if_bridge.h,v 1.2 1999/03/01 04:44:44 jason Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -32,23 +32,54 @@
*/
/*
- * Bridge control request: (add/delete/iterate) member interfaces.
+ * Bridge control request: add/delete member interfaces.
*/
struct ifbreq {
- char ifbname[IFNAMSIZ]; /* bridge ifs name */
- char ifsname[IFNAMSIZ]; /* member ifs name */
- u_int32_t index; /* iteration index */
+ char ifbr_name[IFNAMSIZ]; /* bridge ifs name */
+ char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */
+ u_int32_t ifbr_ifsflags; /* memver ifs flags */
};
/*
- * Bridge routing request: iterate known routes.
+ * Interface list structure
*/
-struct ifbrtreq {
- char ifbname[IFNAMSIZ]; /* bridge ifs name */
- u_int32_t index; /* iteration index */
- struct ether_addr dst; /* destination addr */
- char ifsname[IFNAMSIZ]; /* destination ifs */
- u_int16_t age; /* route age */
+struct ifbifconf {
+ char ifbic_name[IFNAMSIZ]; /* bridge ifs name */
+ u_int32_t ifbic_len; /* buffer size */
+ union {
+ caddr_t ifbicu_buf;
+ struct ifbreq *ifbicu_req;
+ } ifbic_ifbicu;
+#define ifbic_buf ifbic_ifbicu.ifbicu_buf
+#define ifbic_req ifbic_ifbicu.ifbicu_req
+};
+
+/*
+ * Bridge address request
+ */
+struct ifbareq {
+ char ifba_name[IFNAMSIZ]; /* destination ifs */
+ u_int32_t ifba_age; /* route age */
+ struct ether_addr ifba_dst; /* destination addr */
+};
+
+struct ifbaconf {
+ char ifbac_name[IFNAMSIZ]; /* bridge ifs name */
+ u_int32_t ifbac_len; /* buffer size */
+ union {
+ caddr_t ifbacu_buf; /* buffer */
+ struct ifbareq *ifbacu_req; /* request pointer */
+ } ifbac_ifbacu;
+#define ifbac_buf ifbac_ifbacu.ifbacu_buf
+#define ifbac_req ifbac_ifbacu.ifbacu_req
+};
+
+/*
+ * Bridge cache size get/set
+ */
+struct ifbcachereq {
+ char ifbc_name[IFNAMSIZ]; /* bridge ifs name */
+ u_int32_t ifbc_size; /* cache size */
};
#ifdef _KERNEL
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 7a3bb7c543a..4b593d3ce7b 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sockio.h,v 1.5 1999/02/26 17:01:33 jason Exp $ */
+/* $OpenBSD: sockio.h,v 1.6 1999/03/01 04:44:43 jason Exp $ */
/* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */
/*-
@@ -85,8 +85,10 @@
#define SIOCBRDGADD _IOWR('i', 60, struct ifbreq) /* add bridge ifs */
#define SIOCBRDGDEL _IOWR('i', 61, struct ifbreq) /* del bridge ifs */
-#define SIOCBRDGIDX _IOWR('i', 62, struct ifbreq) /* get ifs by index */
-#define SIOCBRDGRT _IOWR('i', 63, struct ifbrtreq) /* get rts by index */
+#define SIOCBRDGSCACHE _IOWR('i', 64, struct ifbcachereq) /* set cache size */
+#define SIOCBRDGGCACHE _IOWR('i', 65, struct ifbcachereq) /* get cache size */
+#define SIOCBRDGIFS _IOWR('i', 66, struct ifbreq) /* get member ifs */
+#define SIOCBRDGRTS _IOWR('i', 67, struct ifbaconf) /* get addresses */
#define SIOCSIFMTU _IOW('i', 127, struct ifreq) /* set ifnet mtu */
#define SIOCGIFMTU _IOWR('i', 126, struct ifreq) /* get ifnet mtu */
diff --git a/usr.sbin/brconfig/brconfig.c b/usr.sbin/brconfig/brconfig.c
index 3071d2541c4..6c561fa21f4 100644
--- a/usr.sbin/brconfig/brconfig.c
+++ b/usr.sbin/brconfig/brconfig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: brconfig.c,v 1.2 1999/02/27 18:29:54 jason Exp $ */
+/* $OpenBSD: brconfig.c,v 1.3 1999/03/01 04:44:44 jason Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -46,6 +46,8 @@
#include <string.h>
#include <err.h>
#include <sysexits.h>
+#include <stdlib.h>
+#include <limits.h>
void usage(void);
int main(int, char **);
@@ -53,6 +55,7 @@ int bridge_setflag(int, char *, short);
int bridge_clrflag(int, char *, short);
int bridge_list(int, char *, char *);
int bridge_addrs(int, char *, char *);
+int bridge_maxaddr(int, char *, char *);
int bridge_add(int, char *, char *);
int bridge_delete(int, char *, char *);
int bridge_status(int, char *);
@@ -162,6 +165,16 @@ main(argc, argv)
if (error)
return (error);
}
+ else if (strcmp("maxaddr", argv[0]) == 0) {
+ argc--; argv++;
+ if (argc == 0) {
+ warnx("maxaddr requires an argument");
+ return (EX_USAGE);
+ }
+ error = bridge_maxaddr(sock, brdg, argv[0]);
+ if (error)
+ return (error);
+ }
else {
warnx("unrecognized option: %s", argv[0]);
return (EX_USAGE);
@@ -266,30 +279,34 @@ bridge_clrflag(s, brdg, f)
}
int
-bridge_list(sock, brdg, delim)
- int sock;
+bridge_list(s, brdg, delim)
+ int s;
char *brdg, *delim;
{
- struct ifbreq req;
- u_int32_t i = 0;
- char buf[sizeof(req.ifsname) + 1];
+ struct ifbreq *reqp;
+ struct ifbifconf bifc;
+ int i, len = 8192;
+ char buf[sizeof(reqp->ifbr_ifsname) + 1], *inbuf = NULL;
while (1) {
- strncpy(req.ifbname, brdg, sizeof(req.ifbname));
- req.index = i;
- if (ioctl(sock, SIOCBRDGIDX, &req) < 0) {
- if (errno == ENOENT) /* end of list */
- return (0);
- warn("ioctl(SIOCBRDGIDX)");
- return (EX_IOERR);
- }
-
+ strncpy(bifc.ifbic_name, brdg, sizeof(bifc.ifbic_name));
+ bifc.ifbic_len = len;
+ bifc.ifbic_buf = inbuf = realloc(inbuf, len);
+ if (inbuf == NULL)
+ err(1, "malloc");
+ if (ioctl(s, SIOCBRDGIFS, &bifc) < 0)
+ err(1, "ioctl(SIOCBRDGIFS)");
+ if (bifc.ifbic_len + sizeof(*reqp) < len)
+ break;
+ len *= 2;
+ }
+ for (i = 0; i < bifc.ifbic_len / sizeof(*reqp); i++) {
+ reqp = bifc.ifbic_req + i;
bzero(buf, sizeof(buf));
- strncpy(buf, req.ifsname, sizeof(req.ifsname));
+ strncpy(buf, reqp->ifbr_ifsname, sizeof(reqp->ifbr_ifsname));
printf("%s%s\n", delim, buf);
- i++;
}
-
+ free(bifc.ifbic_buf);
return (0); /* NOTREACHED */
}
@@ -300,8 +317,8 @@ bridge_add(s, brdg, ifn)
{
struct ifbreq req;
- strncpy(req.ifbname, brdg, sizeof(req.ifbname));
- strncpy(req.ifsname, ifn, sizeof(req.ifsname));
+ strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+ strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
if (ioctl(s, SIOCBRDGADD, &req) < 0) {
warn("ioctl(SIOCADDBRDG)");
if (errno == EPERM)
@@ -318,8 +335,8 @@ bridge_delete(s, brdg, ifn)
{
struct ifbreq req;
- strncpy(req.ifbname, brdg, sizeof(req.ifbname));
- strncpy(req.ifsname, ifn, sizeof(req.ifsname));
+ strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+ strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
if (ioctl(s, SIOCBRDGDEL, &req) < 0) {
warn("ioctl(SIOCDELBRDG)");
if (errno == EPERM)
@@ -330,28 +347,61 @@ bridge_delete(s, brdg, ifn)
}
int
+bridge_maxaddr(s, brdg, arg)
+ int s;
+ char *brdg, *arg;
+{
+ struct ifbcachereq ifbc;
+ u_int32_t newsize;
+ char *endptr;
+
+ newsize = strtoul(arg, &endptr, 0);
+ if (arg[0] == '\0' || endptr[0] != '\0') {
+ printf("invalid arg for maxaddr: %s\n", arg);
+ return (EX_USAGE);
+ }
+
+ strncpy(ifbc.ifbc_name, brdg, sizeof ifbc.ifbc_name);
+ ifbc.ifbc_size = newsize;
+ if (ioctl(s, SIOCBRDGSCACHE, (caddr_t)&ifbc) < 0) {
+ warn("ioctl(SIOCBRDGGCACHE)");
+ return (EX_IOERR);
+ }
+ return (0);
+}
+
+int
bridge_addrs(s, brdg, delim)
int s;
char *brdg, *delim;
{
- struct ifbrtreq req;
- u_int32_t i = 0;
- int r = 0;
+ struct ifbaconf ifbac;
+ struct ifbareq *ifba;
+ char *inbuf = NULL, buf[sizeof(ifba->ifba_name) + 1];
+ int i, len = 8192;
- while (r == 0) {
- strncpy(req.ifbname, brdg, sizeof(req.ifbname));
- req.index = i;
-
- r = ioctl(s, SIOCBRDGRT, &req);
- if (r != 0) {
- if (errno == ENOENT || errno == ENETDOWN)
+ while (1) {
+ ifbac.ifbac_len = len;
+ ifbac.ifbac_buf = inbuf = realloc(inbuf, len);
+ strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name));
+ if (inbuf == NULL)
+ err(EX_IOERR, "malloc");
+ if (ioctl(s, SIOCBRDGRTS, &ifbac) < 0) {
+ if (errno == ENETDOWN)
return (0);
- warn("ioctl(SIOCBRDGRT)");
- return (EX_IOERR);
+ err(EX_IOERR, "ioctl(SIOCBRDGRTS)");
}
- printf("%s%s %u %s\n", delim, ether_ntoa(&req.dst),
- req.age, req.ifsname);
- i++;
+ if (ifbac.ifbac_len + sizeof(*ifba) < len)
+ break;
+ len *= 2;
+ }
+
+ for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
+ ifba = ifbac.ifbac_req + i;
+ bzero(buf, sizeof(buf));
+ strncpy(buf, ifba->ifba_name, sizeof(ifba->ifba_name));
+ printf("%s%s %s %u\n", delim, ether_ntoa(&ifba->ifba_dst),
+ buf, ifba->ifba_age);
}
return (0);
@@ -366,7 +416,7 @@ is_bridge(s, brdg)
char *brdg;
{
struct ifreq ifr;
- struct ifbrtreq req;
+ struct ifbaconf ifbac;
strncpy(ifr.ifr_name, brdg, sizeof ifr.ifr_name);
@@ -375,10 +425,10 @@ is_bridge(s, brdg)
return (0);
}
- strncpy(req.ifbname, brdg, sizeof(req.ifbname));
- req.index = 0;
- if (ioctl(s, SIOCBRDGRT, (caddr_t)&req) < 0) {
- if (errno == ENOENT || errno == ENETDOWN)
+ ifbac.ifbac_len = 0;
+ strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name));
+ if (ioctl(s, SIOCBRDGRTS, (caddr_t)&ifbac) < 0) {
+ if (errno == ENETDOWN)
return (1);
return (0);
}
@@ -391,6 +441,7 @@ bridge_status(s, brdg)
char *brdg;
{
struct ifreq ifr;
+ struct ifbcachereq ifbc;
int err;
strncpy(ifr.ifr_name, brdg, sizeof ifr.ifr_name);
@@ -411,7 +462,14 @@ bridge_status(s, brdg)
if (err)
return (err);
- printf("\tAddresses:\n");
+ strncpy(ifbc.ifbc_name, brdg, sizeof ifbc.ifbc_name);
+ if (ioctl(s, SIOCBRDGGCACHE, (caddr_t)&ifbc) < 0) {
+ warn("ioctl(SIOCBRDGGCACHE)");
+ return (EX_IOERR);
+ }
+
+ printf("\tAddresses (max cache: %u):\n", ifbc.ifbc_size);
+
err = bridge_addrs(s, brdg, "\t\t");
return (err);
}