ifbridge.c revision 171678
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: head/sbin/ifconfig/ifbridge.c 171678 2007-08-01 00:33:52Z thompsa $"; 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"); 180146985Sthompsa 181146985Sthompsa if (req->ifbr_ifsflags & IFBIF_STP) { 182151040Sthompsa printf("%s", pad); 183151040Sthompsa printf("port %u priority %u", 184151040Sthompsa req->ifbr_portno, req->ifbr_priority); 185146985Sthompsa printf(" path cost %u", req->ifbr_path_cost); 186163863Sthompsa if (req->ifbr_proto < 187163863Sthompsa sizeof(stpproto) / sizeof(stpproto[0])) 188163863Sthompsa printf(" proto %s", stpproto[req->ifbr_proto]); 189163863Sthompsa else 190163863Sthompsa printf(" <unknown proto %d>", 191163863Sthompsa req->ifbr_proto); 192163863Sthompsa 193163863Sthompsa printf("\n%s", pad); 194163863Sthompsa if (req->ifbr_role < 195163863Sthompsa sizeof(stproles) / sizeof(stproles[0])) 196163863Sthompsa printf("role %s", stproles[req->ifbr_role]); 197163863Sthompsa else 198163863Sthompsa printf("<unknown role %d>", 199163863Sthompsa req->ifbr_role); 200146985Sthompsa if (req->ifbr_state < 201146985Sthompsa sizeof(stpstates) / sizeof(stpstates[0])) 202163863Sthompsa printf(" state %s", stpstates[req->ifbr_state]); 203146985Sthompsa else 204146985Sthompsa printf(" <unknown state %d>", 205146985Sthompsa req->ifbr_state); 206151040Sthompsa printf("\n"); 207146985Sthompsa } 208146985Sthompsa } 209146985Sthompsa 210146985Sthompsa free(inbuf); 211146985Sthompsa} 212146985Sthompsa 213146985Sthompsastatic void 214146985Sthompsabridge_addresses(int s, const char *prefix) 215146985Sthompsa{ 216146985Sthompsa struct ifbaconf ifbac; 217146985Sthompsa struct ifbareq *ifba; 218146985Sthompsa char *inbuf = NULL, *ninbuf; 219146985Sthompsa int i, len = 8192; 220146985Sthompsa struct ether_addr ea; 221146985Sthompsa 222146985Sthompsa for (;;) { 223146985Sthompsa ninbuf = realloc(inbuf, len); 224146985Sthompsa if (ninbuf == NULL) 225146985Sthompsa err(1, "unable to allocate address buffer"); 226146985Sthompsa ifbac.ifbac_len = len; 227146985Sthompsa ifbac.ifbac_buf = inbuf = ninbuf; 228146985Sthompsa if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) 229146985Sthompsa err(1, "unable to get address cache"); 230146985Sthompsa if ((ifbac.ifbac_len + sizeof(*ifba)) < len) 231146985Sthompsa break; 232146985Sthompsa len *= 2; 233146985Sthompsa } 234146985Sthompsa 235146985Sthompsa for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { 236146985Sthompsa ifba = ifbac.ifbac_req + i; 237146985Sthompsa memcpy(ea.octet, ifba->ifba_dst, 238146985Sthompsa sizeof(ea.octet)); 239170681Sthompsa printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea), 240170681Sthompsa ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire); 241146985Sthompsa printb("flags", ifba->ifba_flags, IFBAFBITS); 242146985Sthompsa printf("\n"); 243146985Sthompsa } 244146985Sthompsa 245146985Sthompsa free(inbuf); 246146985Sthompsa} 247146985Sthompsa 248146985Sthompsastatic void 249146985Sthompsabridge_status(int s) 250146985Sthompsa{ 251164691Sthompsa struct ifbropreq ifbp; 252164691Sthompsa struct ifbrparam param; 253146985Sthompsa u_int16_t pri; 254163863Sthompsa u_int8_t ht, fd, ma, hc, pro; 255164653Sthompsa u_int8_t lladdr[ETHER_ADDR_LEN]; 256164653Sthompsa u_int16_t bprio; 257164691Sthompsa u_int32_t csize, ctime; 258146985Sthompsa 259164691Sthompsa if (do_cmd(s, BRDGGCACHE, ¶m, sizeof(param), 0) < 0) 260146985Sthompsa return; 261164691Sthompsa csize = param.ifbrp_csize; 262164691Sthompsa if (do_cmd(s, BRDGGTO, ¶m, sizeof(param), 0) < 0) 263164691Sthompsa return; 264164691Sthompsa ctime = param.ifbrp_ctime; 265164691Sthompsa if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0) 266164691Sthompsa return; 267164691Sthompsa pri = ifbp.ifbop_priority; 268164691Sthompsa pro = ifbp.ifbop_protocol; 269164691Sthompsa ht = ifbp.ifbop_hellotime; 270164691Sthompsa fd = ifbp.ifbop_fwddelay; 271164691Sthompsa hc = ifbp.ifbop_holdcount; 272164691Sthompsa ma = ifbp.ifbop_maxage; 273146985Sthompsa 274164691Sthompsa PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr); 275164653Sthompsa printf("\tid %s priority %u hellotime %u fwddelay %u\n", 276164653Sthompsa ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd); 277164691Sthompsa printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n", 278164691Sthompsa ma, hc, stpproto[pro], csize, ctime); 279146985Sthompsa 280164691Sthompsa PV2ID(ifbp.ifbop_designated_root, bprio, lladdr); 281164653Sthompsa printf("\troot id %s priority %d ifcost %u port %u\n", 282164653Sthompsa ether_ntoa((struct ether_addr *)lladdr), bprio, 283164691Sthompsa ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff); 284164653Sthompsa 285151040Sthompsa bridge_interfaces(s, "\tmember: "); 286146985Sthompsa 287146985Sthompsa return; 288146985Sthompsa 289146985Sthompsa} 290146985Sthompsa 291146985Sthompsastatic void 292146985Sthompsasetbridge_add(const char *val, int d, int s, const struct afswtch *afp) 293146985Sthompsa{ 294146985Sthompsa struct ifbreq req; 295146985Sthompsa 296146985Sthompsa memset(&req, 0, sizeof(req)); 297146985Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 298146985Sthompsa if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) 299146985Sthompsa err(1, "BRDGADD %s", val); 300146985Sthompsa} 301146985Sthompsa 302146985Sthompsastatic void 303146985Sthompsasetbridge_delete(const char *val, int d, int s, const struct afswtch *afp) 304146985Sthompsa{ 305146985Sthompsa struct ifbreq req; 306146985Sthompsa 307146985Sthompsa memset(&req, 0, sizeof(req)); 308146985Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 309146985Sthompsa if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) 310146985Sthompsa err(1, "BRDGDEL %s", val); 311146985Sthompsa} 312146985Sthompsa 313146985Sthompsastatic void 314146985Sthompsasetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 315146985Sthompsa{ 316146985Sthompsa 317146985Sthompsa do_bridgeflag(s, val, IFBIF_DISCOVER, 1); 318146985Sthompsa} 319146985Sthompsa 320146985Sthompsastatic void 321146985Sthompsaunsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 322146985Sthompsa{ 323146985Sthompsa 324146985Sthompsa do_bridgeflag(s, val, IFBIF_DISCOVER, 0); 325146985Sthompsa} 326146985Sthompsa 327146985Sthompsastatic void 328146985Sthompsasetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 329146985Sthompsa{ 330146985Sthompsa 331146985Sthompsa do_bridgeflag(s, val, IFBIF_LEARNING, 1); 332146985Sthompsa} 333146985Sthompsa 334146985Sthompsastatic void 335146985Sthompsaunsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 336146985Sthompsa{ 337146985Sthompsa 338146985Sthompsa do_bridgeflag(s, val, IFBIF_LEARNING, 0); 339146985Sthompsa} 340146985Sthompsa 341146985Sthompsastatic void 342164112Sthompsasetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 343164112Sthompsa{ 344164112Sthompsa 345164112Sthompsa do_bridgeflag(s, val, IFBIF_STICKY, 1); 346164112Sthompsa} 347164112Sthompsa 348164112Sthompsastatic void 349164112Sthompsaunsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 350164112Sthompsa{ 351164112Sthompsa 352164112Sthompsa do_bridgeflag(s, val, IFBIF_STICKY, 0); 353164112Sthompsa} 354164112Sthompsa 355164112Sthompsastatic void 356153408Sthompsasetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 357153408Sthompsa{ 358153408Sthompsa struct ifbreq req; 359153408Sthompsa 360153408Sthompsa memset(&req, 0, sizeof(req)); 361153408Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 362153408Sthompsa if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) 363153408Sthompsa err(1, "BRDGADDS %s", val); 364153408Sthompsa} 365153408Sthompsa 366153408Sthompsastatic void 367153408Sthompsaunsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 368153408Sthompsa{ 369153408Sthompsa struct ifbreq req; 370153408Sthompsa 371153408Sthompsa memset(&req, 0, sizeof(req)); 372153408Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 373153408Sthompsa if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) 374153408Sthompsa err(1, "BRDGDELS %s", val); 375153408Sthompsa} 376153408Sthompsa 377153408Sthompsastatic void 378146985Sthompsasetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 379146985Sthompsa{ 380146985Sthompsa 381146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 1); 382146985Sthompsa} 383146985Sthompsa 384146985Sthompsastatic void 385146985Sthompsaunsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 386146985Sthompsa{ 387146985Sthompsa 388146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 0); 389146985Sthompsa} 390146985Sthompsa 391146985Sthompsastatic void 392163863Sthompsasetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 393163863Sthompsa{ 394164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); 395163863Sthompsa} 396163863Sthompsa 397163863Sthompsastatic void 398163863Sthompsaunsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 399163863Sthompsa{ 400164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); 401163863Sthompsa} 402163863Sthompsa 403163863Sthompsastatic void 404163863Sthompsasetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 405163863Sthompsa{ 406164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); 407163863Sthompsa} 408163863Sthompsa 409163863Sthompsastatic void 410163863Sthompsaunsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 411163863Sthompsa{ 412164653Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); 413164653Sthompsa} 414163863Sthompsa 415164653Sthompsastatic void 416165105Sthompsasetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 417164653Sthompsa{ 418165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); 419163863Sthompsa} 420163863Sthompsa 421163863Sthompsastatic void 422165105Sthompsaunsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 423164653Sthompsa{ 424165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); 425164653Sthompsa} 426164653Sthompsa 427164653Sthompsastatic void 428165105Sthompsasetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 429164653Sthompsa{ 430165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); 431164653Sthompsa} 432164653Sthompsa 433164653Sthompsastatic void 434165105Sthompsaunsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 435164653Sthompsa{ 436165105Sthompsa do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); 437164653Sthompsa} 438164653Sthompsa 439164653Sthompsastatic void 440146985Sthompsasetbridge_flush(const char *val, int d, int s, const struct afswtch *afp) 441146985Sthompsa{ 442146985Sthompsa struct ifbreq req; 443146985Sthompsa 444146985Sthompsa memset(&req, 0, sizeof(req)); 445146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHDYN; 446146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 447146985Sthompsa err(1, "BRDGFLUSH"); 448146985Sthompsa} 449146985Sthompsa 450146985Sthompsastatic void 451146985Sthompsasetbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) 452146985Sthompsa{ 453146985Sthompsa struct ifbreq req; 454146985Sthompsa 455146985Sthompsa memset(&req, 0, sizeof(req)); 456146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHALL; 457146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 458146985Sthompsa err(1, "BRDGFLUSH"); 459146985Sthompsa} 460146985Sthompsa 461146985Sthompsastatic void 462146985Sthompsasetbridge_static(const char *val, const char *mac, int s, 463146985Sthompsa const struct afswtch *afp) 464146985Sthompsa{ 465146985Sthompsa struct ifbareq req; 466146985Sthompsa struct ether_addr *ea; 467146985Sthompsa 468146985Sthompsa memset(&req, 0, sizeof(req)); 469146985Sthompsa strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); 470146985Sthompsa 471146985Sthompsa ea = ether_aton(mac); 472146985Sthompsa if (ea == NULL) 473146985Sthompsa errx(1, "%s: invalid address: %s", val, mac); 474146985Sthompsa 475146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 476146985Sthompsa req.ifba_flags = IFBAF_STATIC; 477170681Sthompsa req.ifba_vlan = 1; /* XXX allow user to specify */ 478146985Sthompsa 479146985Sthompsa if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) 480146985Sthompsa err(1, "BRDGSADDR %s", val); 481146985Sthompsa} 482146985Sthompsa 483146985Sthompsastatic void 484146985Sthompsasetbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) 485146985Sthompsa{ 486146985Sthompsa struct ifbareq req; 487146985Sthompsa struct ether_addr *ea; 488146985Sthompsa 489146985Sthompsa memset(&req, 0, sizeof(req)); 490146985Sthompsa 491146985Sthompsa ea = ether_aton(val); 492146985Sthompsa if (ea == NULL) 493146985Sthompsa errx(1, "invalid address: %s", val); 494146985Sthompsa 495146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 496146985Sthompsa 497146985Sthompsa if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) 498146985Sthompsa err(1, "BRDGDADDR %s", val); 499146985Sthompsa} 500146985Sthompsa 501146985Sthompsastatic void 502146985Sthompsasetbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 503146985Sthompsa{ 504146985Sthompsa 505146985Sthompsa bridge_addresses(s, ""); 506146985Sthompsa} 507146985Sthompsa 508146985Sthompsastatic void 509146985Sthompsasetbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) 510146985Sthompsa{ 511146985Sthompsa struct ifbrparam param; 512146985Sthompsa u_long val; 513146985Sthompsa 514146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 515146985Sthompsa errx(1, "invalid value: %s", arg); 516146985Sthompsa 517146985Sthompsa param.ifbrp_csize = val & 0xffffffff; 518146985Sthompsa 519146985Sthompsa if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 520146985Sthompsa err(1, "BRDGSCACHE %s", arg); 521146985Sthompsa} 522146985Sthompsa 523146985Sthompsastatic void 524146985Sthompsasetbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) 525146985Sthompsa{ 526146985Sthompsa struct ifbrparam param; 527146985Sthompsa u_long val; 528146985Sthompsa 529146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 530146985Sthompsa errx(1, "invalid value: %s", arg); 531146985Sthompsa 532146985Sthompsa param.ifbrp_hellotime = val & 0xff; 533146985Sthompsa 534146985Sthompsa if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) 535146985Sthompsa err(1, "BRDGSHT %s", arg); 536146985Sthompsa} 537146985Sthompsa 538146985Sthompsastatic void 539146985Sthompsasetbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) 540146985Sthompsa{ 541146985Sthompsa struct ifbrparam param; 542146985Sthompsa u_long val; 543146985Sthompsa 544146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 545146985Sthompsa errx(1, "invalid value: %s", arg); 546146985Sthompsa 547146985Sthompsa param.ifbrp_fwddelay = val & 0xff; 548146985Sthompsa 549146985Sthompsa if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) 550146985Sthompsa err(1, "BRDGSFD %s", arg); 551146985Sthompsa} 552146985Sthompsa 553146985Sthompsastatic void 554146985Sthompsasetbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) 555146985Sthompsa{ 556146985Sthompsa struct ifbrparam param; 557146985Sthompsa u_long val; 558146985Sthompsa 559146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 560146985Sthompsa errx(1, "invalid value: %s", arg); 561146985Sthompsa 562146985Sthompsa param.ifbrp_maxage = val & 0xff; 563146985Sthompsa 564146985Sthompsa if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) 565146985Sthompsa err(1, "BRDGSMA %s", arg); 566146985Sthompsa} 567146985Sthompsa 568146985Sthompsastatic void 569146985Sthompsasetbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) 570146985Sthompsa{ 571146985Sthompsa struct ifbrparam param; 572146985Sthompsa u_long val; 573146985Sthompsa 574146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) 575146985Sthompsa errx(1, "invalid value: %s", arg); 576146985Sthompsa 577146985Sthompsa param.ifbrp_prio = val & 0xffff; 578146985Sthompsa 579146985Sthompsa if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 580146985Sthompsa err(1, "BRDGSPRI %s", arg); 581146985Sthompsa} 582146985Sthompsa 583146985Sthompsastatic void 584163863Sthompsasetbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) 585163863Sthompsa{ 586163863Sthompsa struct ifbrparam param; 587163863Sthompsa 588163863Sthompsa if (strcasecmp(arg, "stp") == 0) { 589163863Sthompsa param.ifbrp_proto = 0; 590163863Sthompsa } else if (strcasecmp(arg, "rstp") == 0) { 591163863Sthompsa param.ifbrp_proto = 2; 592163863Sthompsa } else { 593163863Sthompsa errx(1, "unknown stp protocol"); 594163863Sthompsa } 595163863Sthompsa 596163863Sthompsa if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) 597163863Sthompsa err(1, "BRDGSPROTO %s", arg); 598163863Sthompsa} 599163863Sthompsa 600163863Sthompsastatic void 601163863Sthompsasetbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) 602163863Sthompsa{ 603163863Sthompsa struct ifbrparam param; 604163863Sthompsa u_long val; 605163863Sthompsa 606163863Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 607163863Sthompsa errx(1, "invalid value: %s", arg); 608163863Sthompsa 609163863Sthompsa param.ifbrp_txhc = val & 0xff; 610163863Sthompsa 611163863Sthompsa if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) 612163863Sthompsa err(1, "BRDGSTXHC %s", arg); 613163863Sthompsa} 614163863Sthompsa 615163863Sthompsastatic void 616146985Sthompsasetbridge_ifpriority(const char *ifn, const char *pri, int s, 617146985Sthompsa const struct afswtch *afp) 618146985Sthompsa{ 619146985Sthompsa struct ifbreq req; 620146985Sthompsa u_long val; 621146985Sthompsa 622146985Sthompsa memset(&req, 0, sizeof(req)); 623146985Sthompsa 624146985Sthompsa if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) 625146985Sthompsa errx(1, "invalid value: %s", pri); 626146985Sthompsa 627146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 628146985Sthompsa req.ifbr_priority = val & 0xff; 629146985Sthompsa 630146985Sthompsa if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) 631146985Sthompsa err(1, "BRDGSIFPRIO %s", pri); 632146985Sthompsa} 633146985Sthompsa 634146985Sthompsastatic void 635146985Sthompsasetbridge_ifpathcost(const char *ifn, const char *cost, int s, 636146985Sthompsa const struct afswtch *afp) 637146985Sthompsa{ 638146985Sthompsa struct ifbreq req; 639146985Sthompsa u_long val; 640146985Sthompsa 641146985Sthompsa memset(&req, 0, sizeof(req)); 642146985Sthompsa 643163863Sthompsa if (get_val(cost, &val) < 0) 644146985Sthompsa errx(1, "invalid value: %s", cost); 645146985Sthompsa 646146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 647163863Sthompsa req.ifbr_path_cost = val; 648146985Sthompsa 649146985Sthompsa if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) 650146985Sthompsa err(1, "BRDGSIFCOST %s", cost); 651146985Sthompsa} 652146985Sthompsa 653146985Sthompsastatic void 654146985Sthompsasetbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) 655146985Sthompsa{ 656146985Sthompsa struct ifbrparam param; 657146985Sthompsa u_long val; 658146985Sthompsa 659146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 660146985Sthompsa errx(1, "invalid value: %s", arg); 661146985Sthompsa 662146985Sthompsa param.ifbrp_ctime = val & 0xffffffff; 663146985Sthompsa 664146985Sthompsa if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) 665146985Sthompsa err(1, "BRDGSTO %s", arg); 666146985Sthompsa} 667146985Sthompsa 668171678Sthompsastatic void 669171678Sthompsasetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 670171678Sthompsa{ 671171678Sthompsa 672171678Sthompsa do_bridgeflag(s, val, IFBIF_PRIVATE, 1); 673171678Sthompsa} 674171678Sthompsa 675171678Sthompsastatic void 676171678Sthompsaunsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 677171678Sthompsa{ 678171678Sthompsa 679171678Sthompsa do_bridgeflag(s, val, IFBIF_PRIVATE, 0); 680171678Sthompsa} 681171678Sthompsa 682146985Sthompsastatic struct cmd bridge_cmds[] = { 683146985Sthompsa DEF_CMD_ARG("addm", setbridge_add), 684146985Sthompsa DEF_CMD_ARG("deletem", setbridge_delete), 685146985Sthompsa DEF_CMD_ARG("discover", setbridge_discover), 686146985Sthompsa DEF_CMD_ARG("-discover", unsetbridge_discover), 687146985Sthompsa DEF_CMD_ARG("learn", setbridge_learn), 688146985Sthompsa DEF_CMD_ARG("-learn", unsetbridge_learn), 689164112Sthompsa DEF_CMD_ARG("sticky", setbridge_sticky), 690164112Sthompsa DEF_CMD_ARG("-sticky", unsetbridge_sticky), 691153408Sthompsa DEF_CMD_ARG("span", setbridge_span), 692153408Sthompsa DEF_CMD_ARG("-span", unsetbridge_span), 693146985Sthompsa DEF_CMD_ARG("stp", setbridge_stp), 694146985Sthompsa DEF_CMD_ARG("-stp", unsetbridge_stp), 695163863Sthompsa DEF_CMD_ARG("edge", setbridge_edge), 696163863Sthompsa DEF_CMD_ARG("-edge", unsetbridge_edge), 697163863Sthompsa DEF_CMD_ARG("autoedge", setbridge_autoedge), 698163863Sthompsa DEF_CMD_ARG("-autoedge", unsetbridge_autoedge), 699165105Sthompsa DEF_CMD_ARG("ptp", setbridge_ptp), 700165105Sthompsa DEF_CMD_ARG("-ptp", unsetbridge_ptp), 701165105Sthompsa DEF_CMD_ARG("autoptp", setbridge_autoptp), 702165105Sthompsa DEF_CMD_ARG("-autoptp", unsetbridge_autoptp), 703146985Sthompsa DEF_CMD("flush", 0, setbridge_flush), 704146985Sthompsa DEF_CMD("flushall", 0, setbridge_flushall), 705146985Sthompsa DEF_CMD_ARG2("static", setbridge_static), 706146985Sthompsa DEF_CMD_ARG("deladdr", setbridge_deladdr), 707146985Sthompsa DEF_CMD("addr", 1, setbridge_addr), 708146985Sthompsa DEF_CMD_ARG("maxaddr", setbridge_maxaddr), 709146985Sthompsa DEF_CMD_ARG("hellotime", setbridge_hellotime), 710146985Sthompsa DEF_CMD_ARG("fwddelay", setbridge_fwddelay), 711146985Sthompsa DEF_CMD_ARG("maxage", setbridge_maxage), 712146985Sthompsa DEF_CMD_ARG("priority", setbridge_priority), 713163863Sthompsa DEF_CMD_ARG("proto", setbridge_protocol), 714164688Sthompsa DEF_CMD_ARG("holdcnt", setbridge_holdcount), 715146985Sthompsa DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), 716146985Sthompsa DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), 717146985Sthompsa DEF_CMD_ARG("timeout", setbridge_timeout), 718171678Sthompsa DEF_CMD_ARG("private", setbridge_private), 719171678Sthompsa DEF_CMD_ARG("-private", unsetbridge_private), 720146985Sthompsa}; 721146985Sthompsastatic struct afswtch af_bridge = { 722146985Sthompsa .af_name = "af_bridge", 723146985Sthompsa .af_af = AF_UNSPEC, 724146985Sthompsa .af_other_status = bridge_status, 725146985Sthompsa}; 726146985Sthompsa 727146985Sthompsastatic __constructor void 728146985Sthompsabridge_ctor(void) 729146985Sthompsa{ 730146985Sthompsa#define N(a) (sizeof(a) / sizeof(a[0])) 731146985Sthompsa int i; 732146985Sthompsa 733146985Sthompsa for (i = 0; i < N(bridge_cmds); i++) 734146985Sthompsa cmd_register(&bridge_cmds[i]); 735146985Sthompsa af_register(&af_bridge); 736146985Sthompsa#undef N 737146985Sthompsa} 738