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