diff options
author | Jason Wright <jason@cvs.openbsd.org> | 1999-03-01 04:44:45 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 1999-03-01 04:44:45 +0000 |
commit | 1211d39b07c91e33d52e5bf82d3fcda41715f51b (patch) | |
tree | 4140b15b412266fa14868707cb59c732622c166b | |
parent | 4a6d5c512e998e2de70b33261943e87d2dcc3780 (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.c | 236 | ||||
-rw-r--r-- | sys/net/if_bridge.h | 55 | ||||
-rw-r--r-- | sys/sys/sockio.h | 8 | ||||
-rw-r--r-- | usr.sbin/brconfig/brconfig.c | 144 |
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); } |