diff --git a/lib/libifconfig/Makefile b/lib/libifconfig/Makefile index 02ef80f26591..8d510c537f82 100644 --- a/lib/libifconfig/Makefile +++ b/lib/libifconfig/Makefile @@ -1,22 +1,27 @@ # $FreeBSD$ PACKAGE= lib${LIB} LIB= ifconfig INTERNALLIB= true SHLIBDIR?= /lib SHLIB_MAJOR= 1 -SRCS= libifconfig.c libifconfig_carp.c libifconfig_inet.c -SRCS+= libifconfig_inet6.c libifconfig_internal.c libifconfig_lagg.c -SRCS+= libifconfig_media.c +SRCS= libifconfig.c \ + libifconfig_bridge.c \ + libifconfig_carp.c \ + libifconfig_inet.c \ + libifconfig_inet6.c \ + libifconfig_internal.c \ + libifconfig_lagg.c \ + libifconfig_media.c # If libifconfig become public uncomment those two lines #INCSDIR= ${INCLUDEDIR} #INCS= libifconfig.h #MAN= libifconfig.3 CFLAGS+= -I${.CURDIR} NO_WCAST_ALIGN= yes .include diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h index dd4e91eac07b..cd2929f315b4 100644 --- a/lib/libifconfig/libifconfig.h +++ b/lib/libifconfig/libifconfig.h @@ -1,256 +1,277 @@ /* * Copyright (c) 2016-2017, Marie Helene Kvello-Aune * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * thislist of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #pragma once #include #include #define ND6_IFF_DEFAULTIF 0x8000 typedef enum { OK = 0, OTHER, IOCTL, SOCKET } ifconfig_errtype; /* * Opaque definition so calling application can just pass a * pointer to it for library use. */ struct ifconfig_handle; typedef struct ifconfig_handle ifconfig_handle_t; struct carpreq; struct ifaddrs; +struct ifbropreq; +struct ifbreq; struct in6_ndireq; struct lagg_reqall; struct lagg_reqflags; struct lagg_reqopts; struct lagg_reqport; +/** Stores extra info associated with a bridge(4) interface */ +struct ifconfig_bridge_status { + struct ifbropreq *params; /**< current operational parameters */ + struct ifbreq *members; /**< list of bridge members */ + size_t members_count; /**< how many member interfaces */ + uint32_t cache_size; /**< size of address cache */ + uint32_t cache_lifetime; /**< address cache entry lifetime */ +}; + struct ifconfig_capabilities { /** Current capabilities (ifconfig prints this as 'options')*/ int curcap; /** Requested capabilities (ifconfig prints this as 'capabilities')*/ int reqcap; }; /** Stores extra info associated with an inet address */ struct ifconfig_inet_addr { const struct sockaddr_in *sin; const struct sockaddr_in *netmask; const struct sockaddr_in *dst; const struct sockaddr_in *broadcast; int prefixlen; uint8_t vhid; }; /** Stores extra info associated with an inet6 address */ struct ifconfig_inet6_addr { struct sockaddr_in6 *sin6; struct sockaddr_in6 *dstin6; struct in6_addrlifetime lifetime; int prefixlen; uint32_t flags; uint8_t vhid; }; /** Stores extra info associated with a lagg(4) interface */ struct ifconfig_lagg_status { struct lagg_reqall *ra; struct lagg_reqopts *ro; struct lagg_reqflags *rf; }; /** Retrieves a new state object for use in other API calls. * Example usage: *{@code * // Create state object * ifconfig_handle_t *lifh; * lifh = ifconfig_open(); * if (lifh == NULL) { * // Handle error * } * * // Do stuff with the handle * * // Dispose of the state object * ifconfig_close(lifh); * lifh = NULL; *} */ ifconfig_handle_t *ifconfig_open(void); /** Frees resources held in the provided state object. * @param h The state object to close. * @see #ifconfig_open(void) */ void ifconfig_close(ifconfig_handle_t *h); /** Identifies what kind of error occured. */ ifconfig_errtype ifconfig_err_errtype(ifconfig_handle_t *h); /** Retrieves the errno associated with the error, if any. */ int ifconfig_err_errno(ifconfig_handle_t *h); typedef void (*ifconfig_foreach_func_t)(ifconfig_handle_t *h, struct ifaddrs *ifa, void *udata); /** Iterate over every network interface * @param h An open ifconfig state object * @param cb A callback function to call with a pointer to each interface * @param udata An opaque value that will be passed to the callback. * @return 0 on success, nonzero if the list could not be iterated */ int ifconfig_foreach_iface(ifconfig_handle_t *h, ifconfig_foreach_func_t cb, void *udata); /** Iterate over every address on a single network interface * @param h An open ifconfig state object * @param ifa A pointer that was supplied by a previous call to * ifconfig_foreach_iface * @param udata An opaque value that will be passed to the callback. * @param cb A callback function to call with a pointer to each ifaddr */ void ifconfig_foreach_ifaddr(ifconfig_handle_t *h, struct ifaddrs *ifa, ifconfig_foreach_func_t cb, void *udata); /** If error type was IOCTL, this identifies which request failed. */ unsigned long ifconfig_err_ioctlreq(ifconfig_handle_t *h); int ifconfig_get_description(ifconfig_handle_t *h, const char *name, char **description); int ifconfig_set_description(ifconfig_handle_t *h, const char *name, const char *newdescription); int ifconfig_unset_description(ifconfig_handle_t *h, const char *name); int ifconfig_set_name(ifconfig_handle_t *h, const char *name, const char *newname); int ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname, char **orig_name); int ifconfig_set_fib(ifconfig_handle_t *h, const char *name, int fib); int ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib); int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu); int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu); int ifconfig_get_nd6(ifconfig_handle_t *h, const char *name, struct in6_ndireq *nd); int ifconfig_set_metric(ifconfig_handle_t *h, const char *name, const int metric); int ifconfig_get_metric(ifconfig_handle_t *h, const char *name, int *metric); int ifconfig_set_capability(ifconfig_handle_t *h, const char *name, const int capability); int ifconfig_get_capability(ifconfig_handle_t *h, const char *name, struct ifconfig_capabilities *capability); /** Retrieve the list of groups to which this interface belongs * @param h An open ifconfig state object * @param name The interface name * @param ifgr return argument. The caller is responsible for freeing * ifgr->ifgr_groups * @return 0 on success, nonzero on failure */ int ifconfig_get_groups(ifconfig_handle_t *h, const char *name, struct ifgroupreq *ifgr); int ifconfig_get_ifstatus(ifconfig_handle_t *h, const char *name, struct ifstat *stat); /** Retrieve the interface media information * @param h An open ifconfig state object * @param name The interface name * @param ifmr Return argument. The caller is responsible for freeing it * @return 0 on success, nonzero on failure */ int ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name, struct ifmediareq **ifmr); const char *ifconfig_media_get_type(int ifmw); const char *ifconfig_media_get_subtype(int ifmw); const char *ifconfig_media_get_status(const struct ifmediareq *ifmr); void ifconfig_media_get_options_string(int ifmw, char *buf, size_t buflen); int ifconfig_carp_get_info(ifconfig_handle_t *h, const char *name, struct carpreq *carpr, int ncarpr); /** Retrieve additional information about an inet address * @param h An open ifconfig state object * @param name The interface name * @param ifa Pointer to the the address structure of interest * @param addr Return argument. It will be filled with additional information * about the address. * @return 0 on success, nonzero on failure. */ int ifconfig_inet_get_addrinfo(ifconfig_handle_t *h, const char *name, struct ifaddrs *ifa, struct ifconfig_inet_addr *addr); /** Retrieve additional information about an inet6 address * @param h An open ifconfig state object * @param name The interface name * @param ifa Pointer to the the address structure of interest * @param addr Return argument. It will be filled with additional information * about the address. * @return 0 on success, nonzero on failure. */ int ifconfig_inet6_get_addrinfo(ifconfig_handle_t *h, const char *name, struct ifaddrs *ifa, struct ifconfig_inet6_addr *addr); +/** Retrieve additional information about a bridge(4) interface */ +int ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h, + const char *name, struct ifconfig_bridge_status **bridge); + +/** Frees the structure returned by ifconfig_bridge_get_bridge_status. Does + * nothing if the argument is NULL + * @param bridge Pointer to the structure to free + */ +void ifconfig_bridge_free_bridge_status(struct ifconfig_bridge_status *bridge); + /** Retrieve additional information about a lagg(4) interface */ int ifconfig_lagg_get_lagg_status(ifconfig_handle_t *h, const char *name, struct ifconfig_lagg_status **lagg_status); /** Retrieve additional information about a member of a lagg(4) interface */ int ifconfig_lagg_get_laggport_status(ifconfig_handle_t *h, const char *name, struct lagg_reqport *rp); -/** Frees the structure returned by ifconfig_lagg_get_status. Does nothing if - * the argument is NULL +/** Frees the structure returned by ifconfig_lagg_get_lagg_status. Does + * nothing if the argument is NULL * @param laggstat Pointer to the structure to free */ void ifconfig_lagg_free_lagg_status(struct ifconfig_lagg_status *laggstat); /** Destroy a virtual interface * @param name Interface to destroy */ int ifconfig_destroy_interface(ifconfig_handle_t *h, const char *name); /** Creates a (virtual) interface * @param name Name of interface to create. Example: bridge or bridge42 * @param name ifname Is set to actual name of created interface */ int ifconfig_create_interface(ifconfig_handle_t *h, const char *name, char **ifname); /** Creates a (virtual) interface * @param name Name of interface to create. Example: vlan0 or ix0.50 * @param name ifname Is set to actual name of created interface * @param vlandev Name of interface to attach to * @param vlanid VLAN ID/Tag. Must not be 0. */ int ifconfig_create_interface_vlan(ifconfig_handle_t *h, const char *name, char **ifname, const char *vlandev, const unsigned short vlantag); int ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name, const char *vlandev, const unsigned short vlantag); diff --git a/lib/libifconfig/libifconfig_bridge.c b/lib/libifconfig/libifconfig_bridge.c new file mode 100644 index 000000000000..95c4d93223ff --- /dev/null +++ b/lib/libifconfig/libifconfig_bridge.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2020, Ryan Moeller + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "libifconfig.h" +#include "libifconfig_internal.h" + +/* Internal structure used for allocations and frees */ +struct _ifconfig_bridge_status { + struct ifconfig_bridge_status inner; /* wrapped bridge status */ + struct ifbropreq params; /* operational parameters */ +}; + +static int +ifconfig_bridge_ioctlwrap(ifconfig_handle_t *h, const char *name, + unsigned long cmd, void *arg, size_t arglen, bool set) +{ + struct ifdrv ifd = { 0 }; + unsigned long req = set ? SIOCSDRVSPEC : SIOCGDRVSPEC; + + strlcpy(ifd.ifd_name, name, sizeof(ifd.ifd_name)); + ifd.ifd_cmd = cmd; + ifd.ifd_data = arg; + ifd.ifd_len = arglen; + + return (ifconfig_ioctlwrap(h, AF_LOCAL, req, &ifd)); +} + +int +ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h, + const char *name, struct ifconfig_bridge_status **bridgep) +{ + struct ifbifconf members; + struct ifbrparam cache_param; + struct _ifconfig_bridge_status *bridge; + char *buf; + + *bridgep = NULL; + + bridge = calloc(1, sizeof(struct _ifconfig_bridge_status)); + if (bridge == NULL) { + h->error.errtype = OTHER; + h->error.errcode = ENOMEM; + return (-1); + } + bridge->inner.params = &bridge->params; + + if (ifconfig_bridge_ioctlwrap(h, name, BRDGGCACHE, + &cache_param, sizeof(cache_param), false) != 0) { + free(bridge); + return (-1); + } + bridge->inner.cache_size = cache_param.ifbrp_csize; + + if (ifconfig_bridge_ioctlwrap(h, name, BRDGGTO, + &cache_param, sizeof(cache_param), false) != 0) { + free(bridge); + return (-1); + } + bridge->inner.cache_lifetime = cache_param.ifbrp_ctime; + + if (ifconfig_bridge_ioctlwrap(h, name, BRDGPARAM, + &bridge->params, sizeof(bridge->params), false) != 0) { + free(bridge); + return (-1); + } + + members.ifbic_buf = NULL; + for (size_t len = 8192; + (buf = realloc(members.ifbic_buf, len)) != NULL; + len *= 2) { + members.ifbic_buf = buf; + members.ifbic_len = len; + if (ifconfig_bridge_ioctlwrap(h, name, BRDGGIFS, + &members, sizeof(members), false) != 0) { + free(buf); + free(bridge); + return (-1); + } + if (members.ifbic_len <= len) + break; + } + if (buf == NULL) { + free(members.ifbic_buf); + free(bridge); + h->error.errtype = OTHER; + h->error.errcode = ENOMEM; + return (-1); + } + bridge->inner.members = members.ifbic_req; + bridge->inner.members_count = + members.ifbic_len / sizeof(*members.ifbic_req); + + *bridgep = &bridge->inner; + + return (0); +} + +void +ifconfig_bridge_free_bridge_status(struct ifconfig_bridge_status *bridge) +{ + if (bridge != NULL) { + free(bridge->members); + free(bridge); + } +} diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index 8ccbd622dff4..f4c51632bc98 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -1,756 +1,729 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ifconfig.h" -#define PV2ID(pv, epri, eaddr) do { \ - epri = pv >> 48; \ - eaddr[0] = pv >> 40; \ - eaddr[1] = pv >> 32; \ - eaddr[2] = pv >> 24; \ - eaddr[3] = pv >> 16; \ - eaddr[4] = pv >> 8; \ - eaddr[5] = pv >> 0; \ -} while (0) - -static const char *stpstates[] = { - "disabled", - "listening", - "learning", - "forwarding", - "blocking", - "discarding" -}; -static const char *stpproto[] = { - "stp", - "-", - "rstp" -}; -static const char *stproles[] = { - "disabled", - "root", - "designated", - "alternate", - "backup" -}; +static const char *stpstates[] = { STP_STATES }; +static const char *stpproto[] = { STP_PROTOS }; +static const char *stproles[] = { STP_ROLES }; static int get_val(const char *cp, u_long *valp) { char *endptr; u_long val; errno = 0; val = strtoul(cp, &endptr, 0); if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE) return (-1); *valp = val; return (0); } static int do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) { struct ifdrv ifd; memset(&ifd, 0, sizeof(ifd)); strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); ifd.ifd_cmd = op; ifd.ifd_len = argsize; ifd.ifd_data = arg; return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); } static void do_bridgeflag(int sock, const char *ifs, int flag, int set) { struct ifbreq req; strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) err(1, "unable to get bridge flags"); if (set) req.ifbr_ifsflags |= flag; else req.ifbr_ifsflags &= ~flag; if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) err(1, "unable to set bridge flags"); } static void bridge_interfaces(int s, const char *prefix) { struct ifbifconf bifc; struct ifbreq *req; char *inbuf = NULL, *ninbuf; char *p, *pad; int i, len = 8192; pad = strdup(prefix); if (pad == NULL) err(1, "strdup"); /* replace the prefix with whitespace */ for (p = pad; *p != '\0'; p++) { if(isprint(*p)) *p = ' '; } for (;;) { ninbuf = realloc(inbuf, len); if (ninbuf == NULL) err(1, "unable to allocate interface buffer"); bifc.ifbic_len = len; bifc.ifbic_buf = inbuf = ninbuf; if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0) err(1, "unable to get interface list"); if ((bifc.ifbic_len + sizeof(*req)) < len) break; len *= 2; } for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) { req = bifc.ifbic_req + i; printf("%s%s ", prefix, req->ifbr_ifsname); printb("flags", req->ifbr_ifsflags, IFBIFBITS); printf("\n"); printf("%s", pad); printf("ifmaxaddr %u", req->ifbr_addrmax); printf(" port %u priority %u", req->ifbr_portno, req->ifbr_priority); printf(" path cost %u", req->ifbr_path_cost); if (req->ifbr_ifsflags & IFBIF_STP) { if (req->ifbr_proto < nitems(stpproto)) printf(" proto %s", stpproto[req->ifbr_proto]); else printf(" ", req->ifbr_proto); printf("\n%s", pad); if (req->ifbr_role < nitems(stproles)) printf("role %s", stproles[req->ifbr_role]); else printf("", req->ifbr_role); if (req->ifbr_state < nitems(stpstates)) printf(" state %s", stpstates[req->ifbr_state]); else printf(" ", req->ifbr_state); } printf("\n"); } free(pad); free(inbuf); } static void bridge_addresses(int s, const char *prefix) { struct ifbaconf ifbac; struct ifbareq *ifba; char *inbuf = NULL, *ninbuf; int i, len = 8192; struct ether_addr ea; for (;;) { ninbuf = realloc(inbuf, len); if (ninbuf == NULL) err(1, "unable to allocate address buffer"); ifbac.ifbac_len = len; ifbac.ifbac_buf = inbuf = ninbuf; if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) err(1, "unable to get address cache"); 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; memcpy(ea.octet, ifba->ifba_dst, sizeof(ea.octet)); printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea), ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire); printb("flags", ifba->ifba_flags, IFBAFBITS); printf("\n"); } free(inbuf); } static void bridge_status(int s) { struct ifbropreq ifbp; struct ifbrparam param; u_int16_t pri; u_int8_t ht, fd, ma, hc, pro; u_int8_t lladdr[ETHER_ADDR_LEN]; u_int16_t bprio; u_int32_t csize, ctime; if (do_cmd(s, BRDGGCACHE, ¶m, sizeof(param), 0) < 0) return; csize = param.ifbrp_csize; if (do_cmd(s, BRDGGTO, ¶m, sizeof(param), 0) < 0) return; ctime = param.ifbrp_ctime; if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0) return; pri = ifbp.ifbop_priority; pro = ifbp.ifbop_protocol; ht = ifbp.ifbop_hellotime; fd = ifbp.ifbop_fwddelay; hc = ifbp.ifbop_holdcount; ma = ifbp.ifbop_maxage; PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr); printf("\tid %s priority %u hellotime %u fwddelay %u\n", ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd); printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n", ma, hc, stpproto[pro], csize, ctime); PV2ID(ifbp.ifbop_designated_root, bprio, lladdr); printf("\troot id %s priority %d ifcost %u port %u\n", ether_ntoa((struct ether_addr *)lladdr), bprio, ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff); bridge_interfaces(s, "\tmember: "); return; } static void setbridge_add(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) err(1, "BRDGADD %s", val); } static void setbridge_delete(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) err(1, "BRDGDEL %s", val); } static void setbridge_discover(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_DISCOVER, 1); } static void unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_DISCOVER, 0); } static void setbridge_learn(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_LEARNING, 1); } static void unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_LEARNING, 0); } static void setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_STICKY, 1); } static void unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_STICKY, 0); } static void setbridge_span(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) err(1, "BRDGADDS %s", val); } static void unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) err(1, "BRDGDELS %s", val); } static void setbridge_stp(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_STP, 1); } static void unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_STP, 0); } static void setbridge_edge(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); } static void unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); } static void setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); } static void unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); } static void setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); } static void unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); } static void setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); } static void unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); } static void setbridge_flush(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; memset(&req, 0, sizeof(req)); req.ifbr_ifsflags = IFBF_FLUSHDYN; if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) err(1, "BRDGFLUSH"); } static void setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; memset(&req, 0, sizeof(req)); req.ifbr_ifsflags = IFBF_FLUSHALL; if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) err(1, "BRDGFLUSH"); } static void setbridge_static(const char *val, const char *mac, int s, const struct afswtch *afp) { struct ifbareq req; struct ether_addr *ea; memset(&req, 0, sizeof(req)); strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); ea = ether_aton(mac); if (ea == NULL) errx(1, "%s: invalid address: %s", val, mac); memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); req.ifba_flags = IFBAF_STATIC; req.ifba_vlan = 1; /* XXX allow user to specify */ if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) err(1, "BRDGSADDR %s", val); } static void setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) { struct ifbareq req; struct ether_addr *ea; memset(&req, 0, sizeof(req)); ea = ether_aton(val); if (ea == NULL) errx(1, "invalid address: %s", val); memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) err(1, "BRDGDADDR %s", val); } static void setbridge_addr(const char *val, int d, int s, const struct afswtch *afp) { bridge_addresses(s, ""); } static void setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_csize = val & 0xffffffff; if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSCACHE %s", arg); } static void setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_hellotime = val & 0xff; if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSHT %s", arg); } static void setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_fwddelay = val & 0xff; if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSFD %s", arg); } static void setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_maxage = val & 0xff; if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSMA %s", arg); } static void setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_prio = val & 0xffff; if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSPRI %s", arg); } static void setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; if (strcasecmp(arg, "stp") == 0) { param.ifbrp_proto = 0; } else if (strcasecmp(arg, "rstp") == 0) { param.ifbrp_proto = 2; } else { errx(1, "unknown stp protocol"); } if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSPROTO %s", arg); } static void setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_txhc = val & 0xff; if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSTXHC %s", arg); } static void setbridge_ifpriority(const char *ifn, const char *pri, int s, const struct afswtch *afp) { struct ifbreq req; u_long val; memset(&req, 0, sizeof(req)); if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) errx(1, "invalid value: %s", pri); strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); req.ifbr_priority = val & 0xff; if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFPRIO %s", pri); } static void setbridge_ifpathcost(const char *ifn, const char *cost, int s, const struct afswtch *afp) { struct ifbreq req; u_long val; memset(&req, 0, sizeof(req)); if (get_val(cost, &val) < 0) errx(1, "invalid value: %s", cost); strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); req.ifbr_path_cost = val; if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFCOST %s", cost); } static void setbridge_ifmaxaddr(const char *ifn, const char *arg, int s, const struct afswtch *afp) { struct ifbreq req; u_long val; memset(&req, 0, sizeof(req)); if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) errx(1, "invalid value: %s", arg); strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); req.ifbr_addrmax = val & 0xffffffff; if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFAMAX %s", arg); } static void setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) { struct ifbrparam param; u_long val; if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) errx(1, "invalid value: %s", arg); param.ifbrp_ctime = val & 0xffffffff; if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSTO %s", arg); } static void setbridge_private(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_PRIVATE, 1); } static void unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) { do_bridgeflag(s, val, IFBIF_PRIVATE, 0); } static struct cmd bridge_cmds[] = { DEF_CMD_ARG("addm", setbridge_add), DEF_CMD_ARG("deletem", setbridge_delete), DEF_CMD_ARG("discover", setbridge_discover), DEF_CMD_ARG("-discover", unsetbridge_discover), DEF_CMD_ARG("learn", setbridge_learn), DEF_CMD_ARG("-learn", unsetbridge_learn), DEF_CMD_ARG("sticky", setbridge_sticky), DEF_CMD_ARG("-sticky", unsetbridge_sticky), DEF_CMD_ARG("span", setbridge_span), DEF_CMD_ARG("-span", unsetbridge_span), DEF_CMD_ARG("stp", setbridge_stp), DEF_CMD_ARG("-stp", unsetbridge_stp), DEF_CMD_ARG("edge", setbridge_edge), DEF_CMD_ARG("-edge", unsetbridge_edge), DEF_CMD_ARG("autoedge", setbridge_autoedge), DEF_CMD_ARG("-autoedge", unsetbridge_autoedge), DEF_CMD_ARG("ptp", setbridge_ptp), DEF_CMD_ARG("-ptp", unsetbridge_ptp), DEF_CMD_ARG("autoptp", setbridge_autoptp), DEF_CMD_ARG("-autoptp", unsetbridge_autoptp), DEF_CMD("flush", 0, setbridge_flush), DEF_CMD("flushall", 0, setbridge_flushall), DEF_CMD_ARG2("static", setbridge_static), DEF_CMD_ARG("deladdr", setbridge_deladdr), DEF_CMD("addr", 1, setbridge_addr), DEF_CMD_ARG("maxaddr", setbridge_maxaddr), DEF_CMD_ARG("hellotime", setbridge_hellotime), DEF_CMD_ARG("fwddelay", setbridge_fwddelay), DEF_CMD_ARG("maxage", setbridge_maxage), DEF_CMD_ARG("priority", setbridge_priority), DEF_CMD_ARG("proto", setbridge_protocol), DEF_CMD_ARG("holdcnt", setbridge_holdcount), DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr), DEF_CMD_ARG("timeout", setbridge_timeout), DEF_CMD_ARG("private", setbridge_private), DEF_CMD_ARG("-private", unsetbridge_private), }; static struct afswtch af_bridge = { .af_name = "af_bridge", .af_af = AF_UNSPEC, .af_other_status = bridge_status, }; static __constructor void bridge_ctor(void) { int i; for (i = 0; i < nitems(bridge_cmds); i++) cmd_register(&bridge_cmds[i]); af_register(&af_bridge); } diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 483f9b007e74..fef252821be7 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -1,290 +1,320 @@ /* $NetBSD: if_bridgevar.h,v 1.4 2003/07/08 07:13:50 itojun Exp $ */ /* * SPDX-License-Identifier: BSD-4-Clause * * Copyright 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Jason L. Wright * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * OpenBSD: if_bridge.h,v 1.14 2001/03/22 03:48:29 jason Exp * * $FreeBSD$ */ /* * Data structure and control definitions for bridge interfaces. */ #include #include #include /* * Commands used in the SIOCSDRVSPEC ioctl. Note the lookup of the * bridge interface itself is keyed off the ifdrv structure. */ #define BRDGADD 0 /* add bridge member (ifbreq) */ #define BRDGDEL 1 /* delete bridge member (ifbreq) */ #define BRDGGIFFLGS 2 /* get member if flags (ifbreq) */ #define BRDGSIFFLGS 3 /* set member if flags (ifbreq) */ #define BRDGSCACHE 4 /* set cache size (ifbrparam) */ #define BRDGGCACHE 5 /* get cache size (ifbrparam) */ #define BRDGGIFS 6 /* get member list (ifbifconf) */ #define BRDGRTS 7 /* get address list (ifbaconf) */ #define BRDGSADDR 8 /* set static address (ifbareq) */ #define BRDGSTO 9 /* set cache timeout (ifbrparam) */ #define BRDGGTO 10 /* get cache timeout (ifbrparam) */ #define BRDGDADDR 11 /* delete address (ifbareq) */ #define BRDGFLUSH 12 /* flush address cache (ifbreq) */ #define BRDGGPRI 13 /* get priority (ifbrparam) */ #define BRDGSPRI 14 /* set priority (ifbrparam) */ #define BRDGGHT 15 /* get hello time (ifbrparam) */ #define BRDGSHT 16 /* set hello time (ifbrparam) */ #define BRDGGFD 17 /* get forward delay (ifbrparam) */ #define BRDGSFD 18 /* set forward delay (ifbrparam) */ #define BRDGGMA 19 /* get max age (ifbrparam) */ #define BRDGSMA 20 /* set max age (ifbrparam) */ #define BRDGSIFPRIO 21 /* set if priority (ifbreq) */ #define BRDGSIFCOST 22 /* set if path cost (ifbreq) */ #define BRDGADDS 23 /* add bridge span member (ifbreq) */ #define BRDGDELS 24 /* delete bridge span member (ifbreq) */ #define BRDGPARAM 25 /* get bridge STP params (ifbropreq) */ #define BRDGGRTE 26 /* get cache drops (ifbrparam) */ #define BRDGGIFSSTP 27 /* get member STP params list * (ifbpstpconf) */ #define BRDGSPROTO 28 /* set protocol (ifbrparam) */ #define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */ #define BRDGSIFAMAX 30 /* set max interface addrs (ifbreq) */ /* * Generic bridge control request. */ struct ifbreq { char ifbr_ifsname[IFNAMSIZ]; /* member if name */ uint32_t ifbr_ifsflags; /* member if flags */ uint32_t ifbr_stpflags; /* member if STP flags */ uint32_t ifbr_path_cost; /* member if STP cost */ uint8_t ifbr_portno; /* member if port number */ uint8_t ifbr_priority; /* member if STP priority */ uint8_t ifbr_proto; /* member if STP protocol */ uint8_t ifbr_role; /* member if STP role */ uint8_t ifbr_state; /* member if STP state */ uint32_t ifbr_addrcnt; /* member if addr number */ uint32_t ifbr_addrmax; /* member if addr max */ uint32_t ifbr_addrexceeded; /* member if addr violations */ uint8_t pad[32]; }; /* BRDGGIFFLAGS, BRDGSIFFLAGS */ #define IFBIF_LEARNING 0x0001 /* if can learn */ #define IFBIF_DISCOVER 0x0002 /* if sends packets w/ unknown dest. */ #define IFBIF_STP 0x0004 /* if participates in spanning tree */ #define IFBIF_SPAN 0x0008 /* if is a span port */ #define IFBIF_STICKY 0x0010 /* if learned addresses stick */ #define IFBIF_BSTP_EDGE 0x0020 /* member stp edge port */ #define IFBIF_BSTP_AUTOEDGE 0x0040 /* member stp autoedge enabled */ #define IFBIF_BSTP_PTP 0x0080 /* member stp point to point */ #define IFBIF_BSTP_AUTOPTP 0x0100 /* member stp autoptp enabled */ #define IFBIF_BSTP_ADMEDGE 0x0200 /* member stp admin edge enabled */ #define IFBIF_BSTP_ADMCOST 0x0400 /* member stp admin path cost */ #define IFBIF_PRIVATE 0x0800 /* if is a private segment */ #define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \ "\005STICKY\014PRIVATE\006EDGE\007AUTOEDGE\010PTP" \ "\011AUTOPTP" #define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_PTP| \ IFBIF_BSTP_AUTOPTP|IFBIF_BSTP_ADMEDGE| \ IFBIF_BSTP_ADMCOST) /* not saved */ /* BRDGFLUSH */ #define IFBF_FLUSHDYN 0x00 /* flush learned addresses only */ #define IFBF_FLUSHALL 0x01 /* flush all addresses */ /* * Interface list structure. */ struct ifbifconf { uint32_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_ifsname[IFNAMSIZ]; /* member if name */ unsigned long ifba_expire; /* address expire time */ uint8_t ifba_flags; /* address flags */ uint8_t ifba_dst[ETHER_ADDR_LEN];/* destination address */ uint16_t ifba_vlan; /* vlan id */ }; #define IFBAF_TYPEMASK 0x03 /* address type mask */ #define IFBAF_DYNAMIC 0x00 /* dynamically learned address */ #define IFBAF_STATIC 0x01 /* static address */ #define IFBAF_STICKY 0x02 /* sticky address */ #define IFBAFBITS "\020\1STATIC\2STICKY" /* * Address list structure. */ struct ifbaconf { uint32_t ifbac_len; /* buffer size */ union { caddr_t ifbacu_buf; struct ifbareq *ifbacu_req; } ifbac_ifbacu; #define ifbac_buf ifbac_ifbacu.ifbacu_buf #define ifbac_req ifbac_ifbacu.ifbacu_req }; /* * Bridge parameter structure. */ struct ifbrparam { union { uint32_t ifbrpu_int32; uint16_t ifbrpu_int16; uint8_t ifbrpu_int8; } ifbrp_ifbrpu; }; #define ifbrp_csize ifbrp_ifbrpu.ifbrpu_int32 /* cache size */ #define ifbrp_ctime ifbrp_ifbrpu.ifbrpu_int32 /* cache time (sec) */ #define ifbrp_prio ifbrp_ifbrpu.ifbrpu_int16 /* bridge priority */ #define ifbrp_proto ifbrp_ifbrpu.ifbrpu_int8 /* bridge protocol */ #define ifbrp_txhc ifbrp_ifbrpu.ifbrpu_int8 /* bpdu tx holdcount */ #define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_int8 /* hello time (sec) */ #define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_int8 /* fwd time (sec) */ #define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_int8 /* max age (sec) */ #define ifbrp_cexceeded ifbrp_ifbrpu.ifbrpu_int32 /* # of cache dropped * adresses */ /* * Bridge current operational parameters structure. */ struct ifbropreq { uint8_t ifbop_holdcount; uint8_t ifbop_maxage; uint8_t ifbop_hellotime; uint8_t ifbop_fwddelay; uint8_t ifbop_protocol; uint16_t ifbop_priority; uint16_t ifbop_root_port; uint32_t ifbop_root_path_cost; uint64_t ifbop_bridgeid; uint64_t ifbop_designated_root; uint64_t ifbop_designated_bridge; struct timeval ifbop_last_tc_time; }; /* * Bridge member operational STP params structure. */ struct ifbpstpreq { uint8_t ifbp_portno; /* bp STP port number */ uint32_t ifbp_fwd_trans; /* bp STP fwd transitions */ uint32_t ifbp_design_cost; /* bp STP designated cost */ uint32_t ifbp_design_port; /* bp STP designated port */ uint64_t ifbp_design_bridge; /* bp STP designated bridge */ uint64_t ifbp_design_root; /* bp STP designated root */ }; /* * Bridge STP ports list structure. */ struct ifbpstpconf { uint32_t ifbpstp_len; /* buffer size */ union { caddr_t ifbpstpu_buf; struct ifbpstpreq *ifbpstpu_req; } ifbpstp_ifbpstpu; #define ifbpstp_buf ifbpstp_ifbpstpu.ifbpstpu_buf #define ifbpstp_req ifbpstp_ifbpstpu.ifbpstpu_req }; +#define STP_STATES \ + "disabled", \ + "listening", \ + "learning", \ + "forwarding", \ + "blocking", \ + "discarding" + +#define STP_PROTOS \ + "stp" \ + "-" \ + "rstp" + +#define STP_ROLES \ + "disabled" \ + "root" \ + "designated" \ + "alternate" \ + "backup" + +#define PV2ID(pv, epri, eaddr) do { \ + epri = pv >> 48; \ + eaddr[0] = pv >> 40; \ + eaddr[1] = pv >> 32; \ + eaddr[2] = pv >> 24; \ + eaddr[3] = pv >> 16; \ + eaddr[4] = pv >> 8; \ + eaddr[5] = pv >> 0; \ +} while (0) + #ifdef _KERNEL #define BRIDGE_INPUT(_ifp, _m) do { \ KASSERT((_ifp)->if_bridge_input != NULL, \ ("%s: if_bridge not loaded!", __func__)); \ _m = (*(_ifp)->if_bridge_input)(_ifp, _m); \ if (_m != NULL) \ _ifp = _m->m_pkthdr.rcvif; \ } while (0) #define BRIDGE_OUTPUT(_ifp, _m, _err) do { \ KASSERT((_ifp)->if_bridge_output != NULL, \ ("%s: if_bridge not loaded!", __func__)); \ _err = (*(_ifp)->if_bridge_output)(_ifp, _m, NULL, NULL); \ } while (0) extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); #endif /* _KERNEL */