1146985Sthompsa/*- 2330449Seadler * SPDX-License-Identifier: BSD-4-Clause 3330449Seadler * 4146985Sthompsa * Copyright 2001 Wasabi Systems, Inc. 5146985Sthompsa * All rights reserved. 6146985Sthompsa * 7146985Sthompsa * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8146985Sthompsa * 9146985Sthompsa * Redistribution and use in source and binary forms, with or without 10146985Sthompsa * modification, are permitted provided that the following conditions 11146985Sthompsa * are met: 12146985Sthompsa * 1. Redistributions of source code must retain the above copyright 13146985Sthompsa * notice, this list of conditions and the following disclaimer. 14146985Sthompsa * 2. Redistributions in binary form must reproduce the above copyright 15146985Sthompsa * notice, this list of conditions and the following disclaimer in the 16146985Sthompsa * documentation and/or other materials provided with the distribution. 17146985Sthompsa * 3. All advertising materials mentioning features or use of this software 18146985Sthompsa * must display the following acknowledgement: 19146985Sthompsa * This product includes software developed for the NetBSD Project by 20146985Sthompsa * Wasabi Systems, Inc. 21146985Sthompsa * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22146985Sthompsa * or promote products derived from this software without specific prior 23146985Sthompsa * written permission. 24146985Sthompsa * 25146985Sthompsa * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26146985Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27146985Sthompsa * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28146985Sthompsa * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29146985Sthompsa * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30146985Sthompsa * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31146985Sthompsa * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32146985Sthompsa * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33146985Sthompsa * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34146985Sthompsa * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35146985Sthompsa * POSSIBILITY OF SUCH DAMAGE. 36146985Sthompsa */ 37146985Sthompsa 38146985Sthompsa#ifndef lint 39146985Sthompsastatic const char rcsid[] = 40146985Sthompsa "$FreeBSD: stable/11/sbin/ifconfig/ifbridge.c 330469 2018-03-05 08:33:29Z eadler $"; 41146985Sthompsa#endif /* not lint */ 42146985Sthompsa 43146985Sthompsa#include <sys/param.h> 44146985Sthompsa#include <sys/ioctl.h> 45146985Sthompsa#include <sys/socket.h> 46146985Sthompsa#include <sys/sockio.h> 47146985Sthompsa 48146985Sthompsa#include <stdlib.h> 49146985Sthompsa#include <unistd.h> 50146985Sthompsa 51146985Sthompsa#include <net/ethernet.h> 52146985Sthompsa#include <net/if.h> 53146985Sthompsa#include <net/if_bridgevar.h> 54146985Sthompsa#include <net/route.h> 55146985Sthompsa 56146985Sthompsa#include <ctype.h> 57146985Sthompsa#include <stdio.h> 58146985Sthompsa#include <string.h> 59146985Sthompsa#include <stdlib.h> 60146985Sthompsa#include <unistd.h> 61146985Sthompsa#include <err.h> 62146985Sthompsa#include <errno.h> 63146985Sthompsa 64146985Sthompsa#include "ifconfig.h" 65146985Sthompsa 66164653Sthompsa#define PV2ID(pv, epri, eaddr) do { \ 67164653Sthompsa epri = pv >> 48; \ 68164653Sthompsa eaddr[0] = pv >> 40; \ 69164653Sthompsa eaddr[1] = pv >> 32; \ 70164653Sthompsa eaddr[2] = pv >> 24; \ 71164653Sthompsa eaddr[3] = pv >> 16; \ 72164653Sthompsa eaddr[4] = pv >> 8; \ 73164653Sthompsa eaddr[5] = pv >> 0; \ 74164653Sthompsa} while (0) 75164653Sthompsa 76163863Sthompsastatic const char *stpstates[] = { 77163863Sthompsa "disabled", 78163863Sthompsa "listening", 79163863Sthompsa "learning", 80163863Sthompsa "forwarding", 81163863Sthompsa "blocking", 82163863Sthompsa "discarding" 83163863Sthompsa}; 84163863Sthompsastatic const char *stpproto[] = { 85163863Sthompsa "stp", 86163863Sthompsa "-", 87163863Sthompsa "rstp" 88163863Sthompsa}; 89163863Sthompsastatic const char *stproles[] = { 90163863Sthompsa "disabled", 91163863Sthompsa "root", 92163863Sthompsa "designated", 93163863Sthompsa "alternate", 94163863Sthompsa "backup" 95163863Sthompsa}; 96163863Sthompsa 97146985Sthompsastatic int 98146985Sthompsaget_val(const char *cp, u_long *valp) 99146985Sthompsa{ 100146985Sthompsa char *endptr; 101146985Sthompsa u_long val; 102146985Sthompsa 103146985Sthompsa errno = 0; 104146985Sthompsa val = strtoul(cp, &endptr, 0); 105146985Sthompsa if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE) 106146985Sthompsa return (-1); 107146985Sthompsa 108146985Sthompsa *valp = val; 109146985Sthompsa return (0); 110146985Sthompsa} 111146985Sthompsa 112146985Sthompsastatic int 113146985Sthompsado_cmd(int sock, u_long op, void *arg, size_t argsize, int set) 114146985Sthompsa{ 115146985Sthompsa struct ifdrv ifd; 116146985Sthompsa 117146985Sthompsa memset(&ifd, 0, sizeof(ifd)); 118146985Sthompsa 119146985Sthompsa strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 120146985Sthompsa ifd.ifd_cmd = op; 121146985Sthompsa ifd.ifd_len = argsize; 122146985Sthompsa ifd.ifd_data = arg; 123146985Sthompsa 124146985Sthompsa return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); 125146985Sthompsa} 126146985Sthompsa 127146985Sthompsastatic void 128146985Sthompsado_bridgeflag(int sock, const char *ifs, int flag, int set) 129146985Sthompsa{ 130146985Sthompsa struct ifbreq req; 131146985Sthompsa 132146985Sthompsa strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); 133146985Sthompsa 134146985Sthompsa if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) 135146985Sthompsa err(1, "unable to get bridge flags"); 136146985Sthompsa 137146985Sthompsa if (set) 138146985Sthompsa req.ifbr_ifsflags |= flag; 139146985Sthompsa else 140146985Sthompsa req.ifbr_ifsflags &= ~flag; 141146985Sthompsa 142146985Sthompsa if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) 143146985Sthompsa err(1, "unable to set bridge flags"); 144146985Sthompsa} 145146985Sthompsa 146146985Sthompsastatic void 147151040Sthompsabridge_interfaces(int s, const char *prefix) 148146985Sthompsa{ 149146985Sthompsa struct ifbifconf bifc; 150146985Sthompsa struct ifbreq *req; 151146985Sthompsa char *inbuf = NULL, *ninbuf; 152151040Sthompsa char *p, *pad; 153146985Sthompsa int i, len = 8192; 154146985Sthompsa 155151040Sthompsa pad = strdup(prefix); 156151040Sthompsa if (pad == NULL) 157151040Sthompsa err(1, "strdup"); 158151040Sthompsa /* replace the prefix with whitespace */ 159151040Sthompsa for (p = pad; *p != '\0'; p++) { 160151040Sthompsa if(isprint(*p)) 161151040Sthompsa *p = ' '; 162151040Sthompsa } 163151040Sthompsa 164146985Sthompsa for (;;) { 165146985Sthompsa ninbuf = realloc(inbuf, len); 166146985Sthompsa if (ninbuf == NULL) 167146985Sthompsa err(1, "unable to allocate interface buffer"); 168146985Sthompsa bifc.ifbic_len = len; 169146985Sthompsa bifc.ifbic_buf = inbuf = ninbuf; 170146985Sthompsa if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0) 171146985Sthompsa err(1, "unable to get interface list"); 172146985Sthompsa if ((bifc.ifbic_len + sizeof(*req)) < len) 173146985Sthompsa break; 174146985Sthompsa len *= 2; 175146985Sthompsa } 176146985Sthompsa 177146985Sthompsa for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) { 178146985Sthompsa req = bifc.ifbic_req + i; 179146985Sthompsa printf("%s%s ", prefix, req->ifbr_ifsname); 180146985Sthompsa printb("flags", req->ifbr_ifsflags, IFBIFBITS); 181146985Sthompsa printf("\n"); 182173320Sthompsa 183173320Sthompsa printf("%s", pad); 184173320Sthompsa printf("ifmaxaddr %u", req->ifbr_addrmax); 185173320Sthompsa printf(" port %u priority %u", req->ifbr_portno, 186173320Sthompsa req->ifbr_priority); 187173320Sthompsa printf(" path cost %u", req->ifbr_path_cost); 188173320Sthompsa 189146985Sthompsa if (req->ifbr_ifsflags & IFBIF_STP) { 190298246Saraujo if (req->ifbr_proto < nitems(stpproto)) 191163863Sthompsa printf(" proto %s", stpproto[req->ifbr_proto]); 192163863Sthompsa else 193163863Sthompsa printf(" <unknown proto %d>", 194163863Sthompsa req->ifbr_proto); 195163863Sthompsa 196163863Sthompsa printf("\n%s", pad); 197298246Saraujo if (req->ifbr_role < nitems(stproles)) 198163863Sthompsa printf("role %s", stproles[req->ifbr_role]); 199163863Sthompsa else 200163863Sthompsa printf("<unknown role %d>", 201163863Sthompsa req->ifbr_role); 202298246Saraujo if (req->ifbr_state < nitems(stpstates)) 203163863Sthompsa printf(" state %s", stpstates[req->ifbr_state]); 204146985Sthompsa else 205146985Sthompsa printf(" <unknown state %d>", 206146985Sthompsa req->ifbr_state); 207146985Sthompsa } 208173320Sthompsa printf("\n"); 209146985Sthompsa } 210330469Seadler free(pad); 211146985Sthompsa free(inbuf); 212146985Sthompsa} 213146985Sthompsa 214146985Sthompsastatic void 215146985Sthompsabridge_addresses(int s, const char *prefix) 216146985Sthompsa{ 217146985Sthompsa struct ifbaconf ifbac; 218146985Sthompsa struct ifbareq *ifba; 219146985Sthompsa char *inbuf = NULL, *ninbuf; 220146985Sthompsa int i, len = 8192; 221146985Sthompsa struct ether_addr ea; 222146985Sthompsa 223146985Sthompsa for (;;) { 224146985Sthompsa ninbuf = realloc(inbuf, len); 225146985Sthompsa if (ninbuf == NULL) 226146985Sthompsa err(1, "unable to allocate address buffer"); 227146985Sthompsa ifbac.ifbac_len = len; 228146985Sthompsa ifbac.ifbac_buf = inbuf = ninbuf; 229146985Sthompsa if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) 230146985Sthompsa err(1, "unable to get address cache"); 231146985Sthompsa if ((ifbac.ifbac_len + sizeof(*ifba)) < len) 232146985Sthompsa break; 233146985Sthompsa len *= 2; 234146985Sthompsa } 235146985Sthompsa 236146985Sthompsa for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { 237146985Sthompsa ifba = ifbac.ifbac_req + i; 238146985Sthompsa memcpy(ea.octet, ifba->ifba_dst, 239146985Sthompsa sizeof(ea.octet)); 240170681Sthompsa printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea), 241170681Sthompsa ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire); 242146985Sthompsa printb("flags", ifba->ifba_flags, IFBAFBITS); 243146985Sthompsa printf("\n"); 244146985Sthompsa } 245146985Sthompsa 246146985Sthompsa free(inbuf); 247146985Sthompsa} 248146985Sthompsa 249146985Sthompsastatic void 250146985Sthompsabridge_status(int s) 251146985Sthompsa{ 252164691Sthompsa struct ifbropreq ifbp; 253164691Sthompsa struct ifbrparam param; 254146985Sthompsa u_int16_t pri; 255163863Sthompsa u_int8_t ht, fd, ma, hc, pro; 256164653Sthompsa u_int8_t lladdr[ETHER_ADDR_LEN]; 257164653Sthompsa u_int16_t bprio; 258164691Sthompsa u_int32_t csize, ctime; 259146985Sthompsa 260164691Sthompsa if (do_cmd(s, BRDGGCACHE, ¶m, sizeof(param), 0) < 0) 261146985Sthompsa return; 262164691Sthompsa csize = param.ifbrp_csize; 263164691Sthompsa if (do_cmd(s, BRDGGTO, ¶m, sizeof(param), 0) < 0) 264164691Sthompsa return; 265164691Sthompsa ctime = param.ifbrp_ctime; 266164691Sthompsa if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0) 267164691Sthompsa return; 268164691Sthompsa pri = ifbp.ifbop_priority; 269164691Sthompsa pro = ifbp.ifbop_protocol; 270164691Sthompsa ht = ifbp.ifbop_hellotime; 271164691Sthompsa fd = ifbp.ifbop_fwddelay; 272164691Sthompsa hc = ifbp.ifbop_holdcount; 273164691Sthompsa ma = ifbp.ifbop_maxage; 274146985Sthompsa 275164691Sthompsa PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr); 276164653Sthompsa printf("\tid %s priority %u hellotime %u fwddelay %u\n", 277164653Sthompsa ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd); 278164691Sthompsa printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n", 279164691Sthompsa ma, hc, stpproto[pro], csize, ctime); 280146985Sthompsa 281164691Sthompsa PV2ID(ifbp.ifbop_designated_root, bprio, lladdr); 282164653Sthompsa printf("\troot id %s priority %d ifcost %u port %u\n", 283164653Sthompsa ether_ntoa((struct ether_addr *)lladdr), bprio, 284164691Sthompsa ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff); 285164653Sthompsa 286151040Sthompsa bridge_interfaces(s, "\tmember: "); 287146985Sthompsa 288146985Sthompsa return; 289146985Sthompsa 290146985Sthompsa} 291146985Sthompsa 292146985Sthompsastatic void 293146985Sthompsasetbridge_add(const char *val, int d, int s, const struct afswtch *afp) 294146985Sthompsa{ 295146985Sthompsa struct ifbreq req; 296146985Sthompsa 297146985Sthompsa memset(&req, 0, sizeof(req)); 298146985Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 299146985Sthompsa if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) 300146985Sthompsa err(1, "BRDGADD %s", val); 301146985Sthompsa} 302146985Sthompsa 303146985Sthompsastatic void 304146985Sthompsasetbridge_delete(const char *val, int d, int s, const struct afswtch *afp) 305146985Sthompsa{ 306146985Sthompsa struct ifbreq req; 307146985Sthompsa 308146985Sthompsa memset(&req, 0, sizeof(req)); 309146985Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 310146985Sthompsa if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) 311146985Sthompsa err(1, "BRDGDEL %s", val); 312146985Sthompsa} 313146985Sthompsa 314146985Sthompsastatic void 315146985Sthompsasetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 316146985Sthompsa{ 317146985Sthompsa 318146985Sthompsa do_bridgeflag(s, val, IFBIF_DISCOVER, 1); 319146985Sthompsa} 320146985Sthompsa 321146985Sthompsastatic void 322146985Sthompsaunsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 323146985Sthompsa{ 324146985Sthompsa 325146985Sthompsa do_bridgeflag(s, val, IFBIF_DISCOVER, 0); 326146985Sthompsa} 327146985Sthompsa 328146985Sthompsastatic void 329146985Sthompsasetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 330146985Sthompsa{ 331146985Sthompsa 332146985Sthompsa do_bridgeflag(s, val, IFBIF_LEARNING, 1); 333146985Sthompsa} 334146985Sthompsa 335146985Sthompsastatic void 336146985Sthompsaunsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 337146985Sthompsa{ 338146985Sthompsa 339146985Sthompsa do_bridgeflag(s, val, IFBIF_LEARNING, 0); 340146985Sthompsa} 341146985Sthompsa 342146985Sthompsastatic void 343164112Sthompsasetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 344164112Sthompsa{ 345164112Sthompsa 346164112Sthompsa do_bridgeflag(s, val, IFBIF_STICKY, 1); 347164112Sthompsa} 348164112Sthompsa 349164112Sthompsastatic void 350164112Sthompsaunsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 351164112Sthompsa{ 352164112Sthompsa 353164112Sthompsa do_bridgeflag(s, val, IFBIF_STICKY, 0); 354164112Sthompsa} 355164112Sthompsa 356164112Sthompsastatic void 357153408Sthompsasetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 358153408Sthompsa{ 359153408Sthompsa struct ifbreq req; 360153408Sthompsa 361153408Sthompsa memset(&req, 0, sizeof(req)); 362153408Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 363153408Sthompsa if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) 364153408Sthompsa err(1, "BRDGADDS %s", val); 365153408Sthompsa} 366153408Sthompsa 367153408Sthompsastatic void 368153408Sthompsaunsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 369153408Sthompsa{ 370153408Sthompsa struct ifbreq req; 371153408Sthompsa 372153408Sthompsa memset(&req, 0, sizeof(req)); 373153408Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 374153408Sthompsa if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) 375153408Sthompsa err(1, "BRDGDELS %s", val); 376153408Sthompsa} 377153408Sthompsa 378153408Sthompsastatic void 379146985Sthompsasetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 380146985Sthompsa{ 381146985Sthompsa 382146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 1); 383146985Sthompsa} 384146985Sthompsa 385146985Sthompsastatic void 386146985Sthompsaunsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 387146985Sthompsa{ 388146985Sthompsa 389146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 0); 390146985Sthompsa} 391146985Sthompsa 392146985Sthompsastatic void 393163863Sthompsasetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 394163863Sthompsa{ 395164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); 396163863Sthompsa} 397163863Sthompsa 398163863Sthompsastatic void 399163863Sthompsaunsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 400163863Sthompsa{ 401164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); 402163863Sthompsa} 403163863Sthompsa 404163863Sthompsastatic void 405163863Sthompsasetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 406163863Sthompsa{ 407164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); 408163863Sthompsa} 409163863Sthompsa 410163863Sthompsastatic void 411163863Sthompsaunsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 412163863Sthompsa{ 413164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); 414164653Sthompsa} 415163863Sthompsa 416164653Sthompsastatic void 417165105Sthompsasetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 418164653Sthompsa{ 419165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); 420163863Sthompsa} 421163863Sthompsa 422163863Sthompsastatic void 423165105Sthompsaunsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 424164653Sthompsa{ 425165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); 426164653Sthompsa} 427164653Sthompsa 428164653Sthompsastatic void 429165105Sthompsasetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 430164653Sthompsa{ 431165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); 432164653Sthompsa} 433164653Sthompsa 434164653Sthompsastatic void 435165105Sthompsaunsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 436164653Sthompsa{ 437165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); 438164653Sthompsa} 439164653Sthompsa 440164653Sthompsastatic void 441146985Sthompsasetbridge_flush(const char *val, int d, int s, const struct afswtch *afp) 442146985Sthompsa{ 443146985Sthompsa struct ifbreq req; 444146985Sthompsa 445146985Sthompsa memset(&req, 0, sizeof(req)); 446146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHDYN; 447146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 448146985Sthompsa err(1, "BRDGFLUSH"); 449146985Sthompsa} 450146985Sthompsa 451146985Sthompsastatic void 452146985Sthompsasetbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) 453146985Sthompsa{ 454146985Sthompsa struct ifbreq req; 455146985Sthompsa 456146985Sthompsa memset(&req, 0, sizeof(req)); 457146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHALL; 458146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 459146985Sthompsa err(1, "BRDGFLUSH"); 460146985Sthompsa} 461146985Sthompsa 462146985Sthompsastatic void 463146985Sthompsasetbridge_static(const char *val, const char *mac, int s, 464146985Sthompsa const struct afswtch *afp) 465146985Sthompsa{ 466146985Sthompsa struct ifbareq req; 467146985Sthompsa struct ether_addr *ea; 468146985Sthompsa 469146985Sthompsa memset(&req, 0, sizeof(req)); 470146985Sthompsa strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); 471146985Sthompsa 472146985Sthompsa ea = ether_aton(mac); 473146985Sthompsa if (ea == NULL) 474146985Sthompsa errx(1, "%s: invalid address: %s", val, mac); 475146985Sthompsa 476146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 477146985Sthompsa req.ifba_flags = IFBAF_STATIC; 478170681Sthompsa req.ifba_vlan = 1; /* XXX allow user to specify */ 479146985Sthompsa 480146985Sthompsa if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) 481146985Sthompsa err(1, "BRDGSADDR %s", val); 482146985Sthompsa} 483146985Sthompsa 484146985Sthompsastatic void 485146985Sthompsasetbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) 486146985Sthompsa{ 487146985Sthompsa struct ifbareq req; 488146985Sthompsa struct ether_addr *ea; 489146985Sthompsa 490146985Sthompsa memset(&req, 0, sizeof(req)); 491146985Sthompsa 492146985Sthompsa ea = ether_aton(val); 493146985Sthompsa if (ea == NULL) 494146985Sthompsa errx(1, "invalid address: %s", val); 495146985Sthompsa 496146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 497146985Sthompsa 498146985Sthompsa if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) 499146985Sthompsa err(1, "BRDGDADDR %s", val); 500146985Sthompsa} 501146985Sthompsa 502146985Sthompsastatic void 503146985Sthompsasetbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 504146985Sthompsa{ 505146985Sthompsa 506146985Sthompsa bridge_addresses(s, ""); 507146985Sthompsa} 508146985Sthompsa 509146985Sthompsastatic void 510146985Sthompsasetbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) 511146985Sthompsa{ 512146985Sthompsa struct ifbrparam param; 513146985Sthompsa u_long val; 514146985Sthompsa 515146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 516146985Sthompsa errx(1, "invalid value: %s", arg); 517146985Sthompsa 518146985Sthompsa param.ifbrp_csize = val & 0xffffffff; 519146985Sthompsa 520146985Sthompsa if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 521146985Sthompsa err(1, "BRDGSCACHE %s", arg); 522146985Sthompsa} 523146985Sthompsa 524146985Sthompsastatic void 525146985Sthompsasetbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) 526146985Sthompsa{ 527146985Sthompsa struct ifbrparam param; 528146985Sthompsa u_long val; 529146985Sthompsa 530146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 531146985Sthompsa errx(1, "invalid value: %s", arg); 532146985Sthompsa 533146985Sthompsa param.ifbrp_hellotime = val & 0xff; 534146985Sthompsa 535146985Sthompsa if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) 536146985Sthompsa err(1, "BRDGSHT %s", arg); 537146985Sthompsa} 538146985Sthompsa 539146985Sthompsastatic void 540146985Sthompsasetbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) 541146985Sthompsa{ 542146985Sthompsa struct ifbrparam param; 543146985Sthompsa u_long val; 544146985Sthompsa 545146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 546146985Sthompsa errx(1, "invalid value: %s", arg); 547146985Sthompsa 548146985Sthompsa param.ifbrp_fwddelay = val & 0xff; 549146985Sthompsa 550146985Sthompsa if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) 551146985Sthompsa err(1, "BRDGSFD %s", arg); 552146985Sthompsa} 553146985Sthompsa 554146985Sthompsastatic void 555146985Sthompsasetbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) 556146985Sthompsa{ 557146985Sthompsa struct ifbrparam param; 558146985Sthompsa u_long val; 559146985Sthompsa 560146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 561146985Sthompsa errx(1, "invalid value: %s", arg); 562146985Sthompsa 563146985Sthompsa param.ifbrp_maxage = val & 0xff; 564146985Sthompsa 565146985Sthompsa if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) 566146985Sthompsa err(1, "BRDGSMA %s", arg); 567146985Sthompsa} 568146985Sthompsa 569146985Sthompsastatic void 570146985Sthompsasetbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) 571146985Sthompsa{ 572146985Sthompsa struct ifbrparam param; 573146985Sthompsa u_long val; 574146985Sthompsa 575146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) 576146985Sthompsa errx(1, "invalid value: %s", arg); 577146985Sthompsa 578146985Sthompsa param.ifbrp_prio = val & 0xffff; 579146985Sthompsa 580146985Sthompsa if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 581146985Sthompsa err(1, "BRDGSPRI %s", arg); 582146985Sthompsa} 583146985Sthompsa 584146985Sthompsastatic void 585163863Sthompsasetbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) 586163863Sthompsa{ 587163863Sthompsa struct ifbrparam param; 588163863Sthompsa 589163863Sthompsa if (strcasecmp(arg, "stp") == 0) { 590163863Sthompsa param.ifbrp_proto = 0; 591163863Sthompsa } else if (strcasecmp(arg, "rstp") == 0) { 592163863Sthompsa param.ifbrp_proto = 2; 593163863Sthompsa } else { 594163863Sthompsa errx(1, "unknown stp protocol"); 595163863Sthompsa } 596163863Sthompsa 597163863Sthompsa if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) 598163863Sthompsa err(1, "BRDGSPROTO %s", arg); 599163863Sthompsa} 600163863Sthompsa 601163863Sthompsastatic void 602163863Sthompsasetbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) 603163863Sthompsa{ 604163863Sthompsa struct ifbrparam param; 605163863Sthompsa u_long val; 606163863Sthompsa 607163863Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 608163863Sthompsa errx(1, "invalid value: %s", arg); 609163863Sthompsa 610163863Sthompsa param.ifbrp_txhc = val & 0xff; 611163863Sthompsa 612163863Sthompsa if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) 613163863Sthompsa err(1, "BRDGSTXHC %s", arg); 614163863Sthompsa} 615163863Sthompsa 616163863Sthompsastatic void 617146985Sthompsasetbridge_ifpriority(const char *ifn, const char *pri, int s, 618146985Sthompsa const struct afswtch *afp) 619146985Sthompsa{ 620146985Sthompsa struct ifbreq req; 621146985Sthompsa u_long val; 622146985Sthompsa 623146985Sthompsa memset(&req, 0, sizeof(req)); 624146985Sthompsa 625146985Sthompsa if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) 626146985Sthompsa errx(1, "invalid value: %s", pri); 627146985Sthompsa 628146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 629146985Sthompsa req.ifbr_priority = val & 0xff; 630146985Sthompsa 631146985Sthompsa if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) 632146985Sthompsa err(1, "BRDGSIFPRIO %s", pri); 633146985Sthompsa} 634146985Sthompsa 635146985Sthompsastatic void 636146985Sthompsasetbridge_ifpathcost(const char *ifn, const char *cost, int s, 637146985Sthompsa const struct afswtch *afp) 638146985Sthompsa{ 639146985Sthompsa struct ifbreq req; 640146985Sthompsa u_long val; 641146985Sthompsa 642146985Sthompsa memset(&req, 0, sizeof(req)); 643146985Sthompsa 644163863Sthompsa if (get_val(cost, &val) < 0) 645146985Sthompsa errx(1, "invalid value: %s", cost); 646146985Sthompsa 647146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 648163863Sthompsa req.ifbr_path_cost = val; 649146985Sthompsa 650146985Sthompsa if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) 651146985Sthompsa err(1, "BRDGSIFCOST %s", cost); 652146985Sthompsa} 653146985Sthompsa 654146985Sthompsastatic void 655173320Sthompsasetbridge_ifmaxaddr(const char *ifn, const char *arg, int s, 656173320Sthompsa const struct afswtch *afp) 657173320Sthompsa{ 658173320Sthompsa struct ifbreq req; 659173320Sthompsa u_long val; 660173320Sthompsa 661173320Sthompsa memset(&req, 0, sizeof(req)); 662173320Sthompsa 663173320Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 664173320Sthompsa errx(1, "invalid value: %s", arg); 665173320Sthompsa 666173320Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 667173320Sthompsa req.ifbr_addrmax = val & 0xffffffff; 668173320Sthompsa 669173320Sthompsa if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0) 670173320Sthompsa err(1, "BRDGSIFAMAX %s", arg); 671173320Sthompsa} 672173320Sthompsa 673173320Sthompsastatic void 674146985Sthompsasetbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) 675146985Sthompsa{ 676146985Sthompsa struct ifbrparam param; 677146985Sthompsa u_long val; 678146985Sthompsa 679146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 680146985Sthompsa errx(1, "invalid value: %s", arg); 681146985Sthompsa 682146985Sthompsa param.ifbrp_ctime = val & 0xffffffff; 683146985Sthompsa 684146985Sthompsa if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) 685146985Sthompsa err(1, "BRDGSTO %s", arg); 686146985Sthompsa} 687146985Sthompsa 688171678Sthompsastatic void 689171678Sthompsasetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 690171678Sthompsa{ 691171678Sthompsa 692171678Sthompsa do_bridgeflag(s, val, IFBIF_PRIVATE, 1); 693171678Sthompsa} 694171678Sthompsa 695171678Sthompsastatic void 696171678Sthompsaunsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 697171678Sthompsa{ 698171678Sthompsa 699171678Sthompsa do_bridgeflag(s, val, IFBIF_PRIVATE, 0); 700171678Sthompsa} 701171678Sthompsa 702146985Sthompsastatic struct cmd bridge_cmds[] = { 703146985Sthompsa DEF_CMD_ARG("addm", setbridge_add), 704146985Sthompsa DEF_CMD_ARG("deletem", setbridge_delete), 705146985Sthompsa DEF_CMD_ARG("discover", setbridge_discover), 706146985Sthompsa DEF_CMD_ARG("-discover", unsetbridge_discover), 707146985Sthompsa DEF_CMD_ARG("learn", setbridge_learn), 708146985Sthompsa DEF_CMD_ARG("-learn", unsetbridge_learn), 709164112Sthompsa DEF_CMD_ARG("sticky", setbridge_sticky), 710164112Sthompsa DEF_CMD_ARG("-sticky", unsetbridge_sticky), 711153408Sthompsa DEF_CMD_ARG("span", setbridge_span), 712153408Sthompsa DEF_CMD_ARG("-span", unsetbridge_span), 713146985Sthompsa DEF_CMD_ARG("stp", setbridge_stp), 714146985Sthompsa DEF_CMD_ARG("-stp", unsetbridge_stp), 715163863Sthompsa DEF_CMD_ARG("edge", setbridge_edge), 716163863Sthompsa DEF_CMD_ARG("-edge", unsetbridge_edge), 717163863Sthompsa DEF_CMD_ARG("autoedge", setbridge_autoedge), 718163863Sthompsa DEF_CMD_ARG("-autoedge", unsetbridge_autoedge), 719165105Sthompsa DEF_CMD_ARG("ptp", setbridge_ptp), 720165105Sthompsa DEF_CMD_ARG("-ptp", unsetbridge_ptp), 721165105Sthompsa DEF_CMD_ARG("autoptp", setbridge_autoptp), 722165105Sthompsa DEF_CMD_ARG("-autoptp", unsetbridge_autoptp), 723146985Sthompsa DEF_CMD("flush", 0, setbridge_flush), 724146985Sthompsa DEF_CMD("flushall", 0, setbridge_flushall), 725146985Sthompsa DEF_CMD_ARG2("static", setbridge_static), 726146985Sthompsa DEF_CMD_ARG("deladdr", setbridge_deladdr), 727146985Sthompsa DEF_CMD("addr", 1, setbridge_addr), 728146985Sthompsa DEF_CMD_ARG("maxaddr", setbridge_maxaddr), 729146985Sthompsa DEF_CMD_ARG("hellotime", setbridge_hellotime), 730146985Sthompsa DEF_CMD_ARG("fwddelay", setbridge_fwddelay), 731146985Sthompsa DEF_CMD_ARG("maxage", setbridge_maxage), 732146985Sthompsa DEF_CMD_ARG("priority", setbridge_priority), 733163863Sthompsa DEF_CMD_ARG("proto", setbridge_protocol), 734164688Sthompsa DEF_CMD_ARG("holdcnt", setbridge_holdcount), 735146985Sthompsa DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), 736146985Sthompsa DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), 737173320Sthompsa DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr), 738146985Sthompsa DEF_CMD_ARG("timeout", setbridge_timeout), 739171678Sthompsa DEF_CMD_ARG("private", setbridge_private), 740171678Sthompsa DEF_CMD_ARG("-private", unsetbridge_private), 741146985Sthompsa}; 742146985Sthompsastatic struct afswtch af_bridge = { 743146985Sthompsa .af_name = "af_bridge", 744146985Sthompsa .af_af = AF_UNSPEC, 745146985Sthompsa .af_other_status = bridge_status, 746146985Sthompsa}; 747146985Sthompsa 748146985Sthompsastatic __constructor void 749146985Sthompsabridge_ctor(void) 750146985Sthompsa{ 751146985Sthompsa int i; 752146985Sthompsa 753288305Sngie for (i = 0; i < nitems(bridge_cmds); i++) 754146985Sthompsa cmd_register(&bridge_cmds[i]); 755146985Sthompsa af_register(&af_bridge); 756146985Sthompsa} 757