1/*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#ifndef lint 39static const char rcsid[] = 40 "$FreeBSD: stable/11/sbin/ifconfig/ifbridge.c 330469 2018-03-05 08:33:29Z eadler $"; 41#endif /* not lint */ 42 43#include <sys/param.h> 44#include <sys/ioctl.h> 45#include <sys/socket.h> 46#include <sys/sockio.h> 47 48#include <stdlib.h> 49#include <unistd.h> 50 51#include <net/ethernet.h> 52#include <net/if.h> 53#include <net/if_bridgevar.h> 54#include <net/route.h> 55 56#include <ctype.h> 57#include <stdio.h> 58#include <string.h> 59#include <stdlib.h> 60#include <unistd.h> 61#include <err.h> 62#include <errno.h> 63 64#include "ifconfig.h" 65 66#define PV2ID(pv, epri, eaddr) do { \ 67 epri = pv >> 48; \ 68 eaddr[0] = pv >> 40; \ 69 eaddr[1] = pv >> 32; \ 70 eaddr[2] = pv >> 24; \ 71 eaddr[3] = pv >> 16; \ 72 eaddr[4] = pv >> 8; \ 73 eaddr[5] = pv >> 0; \ 74} while (0) 75 76static const char *stpstates[] = { 77 "disabled", 78 "listening", 79 "learning", 80 "forwarding", 81 "blocking", 82 "discarding" 83}; 84static const char *stpproto[] = { 85 "stp", 86 "-", 87 "rstp" 88}; 89static const char *stproles[] = { 90 "disabled", 91 "root", 92 "designated", 93 "alternate", 94 "backup" 95}; 96 97static int 98get_val(const char *cp, u_long *valp) 99{ 100 char *endptr; 101 u_long val; 102 103 errno = 0; 104 val = strtoul(cp, &endptr, 0); 105 if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE) 106 return (-1); 107 108 *valp = val; 109 return (0); 110} 111 112static int 113do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) 114{ 115 struct ifdrv ifd; 116 117 memset(&ifd, 0, sizeof(ifd)); 118 119 strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 120 ifd.ifd_cmd = op; 121 ifd.ifd_len = argsize; 122 ifd.ifd_data = arg; 123 124 return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); 125} 126 127static void 128do_bridgeflag(int sock, const char *ifs, int flag, int set) 129{ 130 struct ifbreq req; 131 132 strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); 133 134 if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) 135 err(1, "unable to get bridge flags"); 136 137 if (set) 138 req.ifbr_ifsflags |= flag; 139 else 140 req.ifbr_ifsflags &= ~flag; 141 142 if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) 143 err(1, "unable to set bridge flags"); 144} 145 146static void 147bridge_interfaces(int s, const char *prefix) 148{ 149 struct ifbifconf bifc; 150 struct ifbreq *req; 151 char *inbuf = NULL, *ninbuf; 152 char *p, *pad; 153 int i, len = 8192; 154 155 pad = strdup(prefix); 156 if (pad == NULL) 157 err(1, "strdup"); 158 /* replace the prefix with whitespace */ 159 for (p = pad; *p != '\0'; p++) { 160 if(isprint(*p)) 161 *p = ' '; 162 } 163 164 for (;;) { 165 ninbuf = realloc(inbuf, len); 166 if (ninbuf == NULL) 167 err(1, "unable to allocate interface buffer"); 168 bifc.ifbic_len = len; 169 bifc.ifbic_buf = inbuf = ninbuf; 170 if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0) 171 err(1, "unable to get interface list"); 172 if ((bifc.ifbic_len + sizeof(*req)) < len) 173 break; 174 len *= 2; 175 } 176 177 for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) { 178 req = bifc.ifbic_req + i; 179 printf("%s%s ", prefix, req->ifbr_ifsname); 180 printb("flags", req->ifbr_ifsflags, IFBIFBITS); 181 printf("\n"); 182 183 printf("%s", pad); 184 printf("ifmaxaddr %u", req->ifbr_addrmax); 185 printf(" port %u priority %u", req->ifbr_portno, 186 req->ifbr_priority); 187 printf(" path cost %u", req->ifbr_path_cost); 188 189 if (req->ifbr_ifsflags & IFBIF_STP) { 190 if (req->ifbr_proto < nitems(stpproto)) 191 printf(" proto %s", stpproto[req->ifbr_proto]); 192 else 193 printf(" <unknown proto %d>", 194 req->ifbr_proto); 195 196 printf("\n%s", pad); 197 if (req->ifbr_role < nitems(stproles)) 198 printf("role %s", stproles[req->ifbr_role]); 199 else 200 printf("<unknown role %d>", 201 req->ifbr_role); 202 if (req->ifbr_state < nitems(stpstates)) 203 printf(" state %s", stpstates[req->ifbr_state]); 204 else 205 printf(" <unknown state %d>", 206 req->ifbr_state); 207 } 208 printf("\n"); 209 } 210 free(pad); 211 free(inbuf); 212} 213 214static void 215bridge_addresses(int s, const char *prefix) 216{ 217 struct ifbaconf ifbac; 218 struct ifbareq *ifba; 219 char *inbuf = NULL, *ninbuf; 220 int i, len = 8192; 221 struct ether_addr ea; 222 223 for (;;) { 224 ninbuf = realloc(inbuf, len); 225 if (ninbuf == NULL) 226 err(1, "unable to allocate address buffer"); 227 ifbac.ifbac_len = len; 228 ifbac.ifbac_buf = inbuf = ninbuf; 229 if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) 230 err(1, "unable to get address cache"); 231 if ((ifbac.ifbac_len + sizeof(*ifba)) < len) 232 break; 233 len *= 2; 234 } 235 236 for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { 237 ifba = ifbac.ifbac_req + i; 238 memcpy(ea.octet, ifba->ifba_dst, 239 sizeof(ea.octet)); 240 printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea), 241 ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire); 242 printb("flags", ifba->ifba_flags, IFBAFBITS); 243 printf("\n"); 244 } 245 246 free(inbuf); 247} 248 249static void 250bridge_status(int s) 251{ 252 struct ifbropreq ifbp; 253 struct ifbrparam param; 254 u_int16_t pri; 255 u_int8_t ht, fd, ma, hc, pro; 256 u_int8_t lladdr[ETHER_ADDR_LEN]; 257 u_int16_t bprio; 258 u_int32_t csize, ctime; 259 260 if (do_cmd(s, BRDGGCACHE, ¶m, sizeof(param), 0) < 0) 261 return; 262 csize = param.ifbrp_csize; 263 if (do_cmd(s, BRDGGTO, ¶m, sizeof(param), 0) < 0) 264 return; 265 ctime = param.ifbrp_ctime; 266 if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0) 267 return; 268 pri = ifbp.ifbop_priority; 269 pro = ifbp.ifbop_protocol; 270 ht = ifbp.ifbop_hellotime; 271 fd = ifbp.ifbop_fwddelay; 272 hc = ifbp.ifbop_holdcount; 273 ma = ifbp.ifbop_maxage; 274 275 PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr); 276 printf("\tid %s priority %u hellotime %u fwddelay %u\n", 277 ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd); 278 printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n", 279 ma, hc, stpproto[pro], csize, ctime); 280 281 PV2ID(ifbp.ifbop_designated_root, bprio, lladdr); 282 printf("\troot id %s priority %d ifcost %u port %u\n", 283 ether_ntoa((struct ether_addr *)lladdr), bprio, 284 ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff); 285 286 bridge_interfaces(s, "\tmember: "); 287 288 return; 289 290} 291 292static void 293setbridge_add(const char *val, int d, int s, const struct afswtch *afp) 294{ 295 struct ifbreq req; 296 297 memset(&req, 0, sizeof(req)); 298 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 299 if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) 300 err(1, "BRDGADD %s", val); 301} 302 303static void 304setbridge_delete(const char *val, int d, int s, const struct afswtch *afp) 305{ 306 struct ifbreq req; 307 308 memset(&req, 0, sizeof(req)); 309 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 310 if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) 311 err(1, "BRDGDEL %s", val); 312} 313 314static void 315setbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 316{ 317 318 do_bridgeflag(s, val, IFBIF_DISCOVER, 1); 319} 320 321static void 322unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 323{ 324 325 do_bridgeflag(s, val, IFBIF_DISCOVER, 0); 326} 327 328static void 329setbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 330{ 331 332 do_bridgeflag(s, val, IFBIF_LEARNING, 1); 333} 334 335static void 336unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 337{ 338 339 do_bridgeflag(s, val, IFBIF_LEARNING, 0); 340} 341 342static void 343setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 344{ 345 346 do_bridgeflag(s, val, IFBIF_STICKY, 1); 347} 348 349static void 350unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 351{ 352 353 do_bridgeflag(s, val, IFBIF_STICKY, 0); 354} 355 356static void 357setbridge_span(const char *val, int d, int s, const struct afswtch *afp) 358{ 359 struct ifbreq req; 360 361 memset(&req, 0, sizeof(req)); 362 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 363 if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) 364 err(1, "BRDGADDS %s", val); 365} 366 367static void 368unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 369{ 370 struct ifbreq req; 371 372 memset(&req, 0, sizeof(req)); 373 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 374 if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) 375 err(1, "BRDGDELS %s", val); 376} 377 378static void 379setbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 380{ 381 382 do_bridgeflag(s, val, IFBIF_STP, 1); 383} 384 385static void 386unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 387{ 388 389 do_bridgeflag(s, val, IFBIF_STP, 0); 390} 391 392static void 393setbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 394{ 395 do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); 396} 397 398static void 399unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 400{ 401 do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); 402} 403 404static void 405setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 406{ 407 do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); 408} 409 410static void 411unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 412{ 413 do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); 414} 415 416static void 417setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 418{ 419 do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); 420} 421 422static void 423unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 424{ 425 do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); 426} 427 428static void 429setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 430{ 431 do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); 432} 433 434static void 435unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 436{ 437 do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); 438} 439 440static void 441setbridge_flush(const char *val, int d, int s, const struct afswtch *afp) 442{ 443 struct ifbreq req; 444 445 memset(&req, 0, sizeof(req)); 446 req.ifbr_ifsflags = IFBF_FLUSHDYN; 447 if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 448 err(1, "BRDGFLUSH"); 449} 450 451static void 452setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) 453{ 454 struct ifbreq req; 455 456 memset(&req, 0, sizeof(req)); 457 req.ifbr_ifsflags = IFBF_FLUSHALL; 458 if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 459 err(1, "BRDGFLUSH"); 460} 461 462static void 463setbridge_static(const char *val, const char *mac, int s, 464 const struct afswtch *afp) 465{ 466 struct ifbareq req; 467 struct ether_addr *ea; 468 469 memset(&req, 0, sizeof(req)); 470 strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); 471 472 ea = ether_aton(mac); 473 if (ea == NULL) 474 errx(1, "%s: invalid address: %s", val, mac); 475 476 memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 477 req.ifba_flags = IFBAF_STATIC; 478 req.ifba_vlan = 1; /* XXX allow user to specify */ 479 480 if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) 481 err(1, "BRDGSADDR %s", val); 482} 483 484static void 485setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) 486{ 487 struct ifbareq req; 488 struct ether_addr *ea; 489 490 memset(&req, 0, sizeof(req)); 491 492 ea = ether_aton(val); 493 if (ea == NULL) 494 errx(1, "invalid address: %s", val); 495 496 memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 497 498 if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) 499 err(1, "BRDGDADDR %s", val); 500} 501 502static void 503setbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 504{ 505 506 bridge_addresses(s, ""); 507} 508 509static void 510setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) 511{ 512 struct ifbrparam param; 513 u_long val; 514 515 if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 516 errx(1, "invalid value: %s", arg); 517 518 param.ifbrp_csize = val & 0xffffffff; 519 520 if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 521 err(1, "BRDGSCACHE %s", arg); 522} 523 524static void 525setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) 526{ 527 struct ifbrparam param; 528 u_long val; 529 530 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 531 errx(1, "invalid value: %s", arg); 532 533 param.ifbrp_hellotime = val & 0xff; 534 535 if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) 536 err(1, "BRDGSHT %s", arg); 537} 538 539static void 540setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) 541{ 542 struct ifbrparam param; 543 u_long val; 544 545 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 546 errx(1, "invalid value: %s", arg); 547 548 param.ifbrp_fwddelay = val & 0xff; 549 550 if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) 551 err(1, "BRDGSFD %s", arg); 552} 553 554static void 555setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) 556{ 557 struct ifbrparam param; 558 u_long val; 559 560 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 561 errx(1, "invalid value: %s", arg); 562 563 param.ifbrp_maxage = val & 0xff; 564 565 if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) 566 err(1, "BRDGSMA %s", arg); 567} 568 569static void 570setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) 571{ 572 struct ifbrparam param; 573 u_long val; 574 575 if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) 576 errx(1, "invalid value: %s", arg); 577 578 param.ifbrp_prio = val & 0xffff; 579 580 if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 581 err(1, "BRDGSPRI %s", arg); 582} 583 584static void 585setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) 586{ 587 struct ifbrparam param; 588 589 if (strcasecmp(arg, "stp") == 0) { 590 param.ifbrp_proto = 0; 591 } else if (strcasecmp(arg, "rstp") == 0) { 592 param.ifbrp_proto = 2; 593 } else { 594 errx(1, "unknown stp protocol"); 595 } 596 597 if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) 598 err(1, "BRDGSPROTO %s", arg); 599} 600 601static void 602setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) 603{ 604 struct ifbrparam param; 605 u_long val; 606 607 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 608 errx(1, "invalid value: %s", arg); 609 610 param.ifbrp_txhc = val & 0xff; 611 612 if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) 613 err(1, "BRDGSTXHC %s", arg); 614} 615 616static void 617setbridge_ifpriority(const char *ifn, const char *pri, int s, 618 const struct afswtch *afp) 619{ 620 struct ifbreq req; 621 u_long val; 622 623 memset(&req, 0, sizeof(req)); 624 625 if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) 626 errx(1, "invalid value: %s", pri); 627 628 strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 629 req.ifbr_priority = val & 0xff; 630 631 if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) 632 err(1, "BRDGSIFPRIO %s", pri); 633} 634 635static void 636setbridge_ifpathcost(const char *ifn, const char *cost, int s, 637 const struct afswtch *afp) 638{ 639 struct ifbreq req; 640 u_long val; 641 642 memset(&req, 0, sizeof(req)); 643 644 if (get_val(cost, &val) < 0) 645 errx(1, "invalid value: %s", cost); 646 647 strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 648 req.ifbr_path_cost = val; 649 650 if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) 651 err(1, "BRDGSIFCOST %s", cost); 652} 653 654static void 655setbridge_ifmaxaddr(const char *ifn, const char *arg, int s, 656 const struct afswtch *afp) 657{ 658 struct ifbreq req; 659 u_long val; 660 661 memset(&req, 0, sizeof(req)); 662 663 if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 664 errx(1, "invalid value: %s", arg); 665 666 strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 667 req.ifbr_addrmax = val & 0xffffffff; 668 669 if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0) 670 err(1, "BRDGSIFAMAX %s", arg); 671} 672 673static void 674setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) 675{ 676 struct ifbrparam param; 677 u_long val; 678 679 if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 680 errx(1, "invalid value: %s", arg); 681 682 param.ifbrp_ctime = val & 0xffffffff; 683 684 if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) 685 err(1, "BRDGSTO %s", arg); 686} 687 688static void 689setbridge_private(const char *val, int d, int s, const struct afswtch *afp) 690{ 691 692 do_bridgeflag(s, val, IFBIF_PRIVATE, 1); 693} 694 695static void 696unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 697{ 698 699 do_bridgeflag(s, val, IFBIF_PRIVATE, 0); 700} 701 702static struct cmd bridge_cmds[] = { 703 DEF_CMD_ARG("addm", setbridge_add), 704 DEF_CMD_ARG("deletem", setbridge_delete), 705 DEF_CMD_ARG("discover", setbridge_discover), 706 DEF_CMD_ARG("-discover", unsetbridge_discover), 707 DEF_CMD_ARG("learn", setbridge_learn), 708 DEF_CMD_ARG("-learn", unsetbridge_learn), 709 DEF_CMD_ARG("sticky", setbridge_sticky), 710 DEF_CMD_ARG("-sticky", unsetbridge_sticky), 711 DEF_CMD_ARG("span", setbridge_span), 712 DEF_CMD_ARG("-span", unsetbridge_span), 713 DEF_CMD_ARG("stp", setbridge_stp), 714 DEF_CMD_ARG("-stp", unsetbridge_stp), 715 DEF_CMD_ARG("edge", setbridge_edge), 716 DEF_CMD_ARG("-edge", unsetbridge_edge), 717 DEF_CMD_ARG("autoedge", setbridge_autoedge), 718 DEF_CMD_ARG("-autoedge", unsetbridge_autoedge), 719 DEF_CMD_ARG("ptp", setbridge_ptp), 720 DEF_CMD_ARG("-ptp", unsetbridge_ptp), 721 DEF_CMD_ARG("autoptp", setbridge_autoptp), 722 DEF_CMD_ARG("-autoptp", unsetbridge_autoptp), 723 DEF_CMD("flush", 0, setbridge_flush), 724 DEF_CMD("flushall", 0, setbridge_flushall), 725 DEF_CMD_ARG2("static", setbridge_static), 726 DEF_CMD_ARG("deladdr", setbridge_deladdr), 727 DEF_CMD("addr", 1, setbridge_addr), 728 DEF_CMD_ARG("maxaddr", setbridge_maxaddr), 729 DEF_CMD_ARG("hellotime", setbridge_hellotime), 730 DEF_CMD_ARG("fwddelay", setbridge_fwddelay), 731 DEF_CMD_ARG("maxage", setbridge_maxage), 732 DEF_CMD_ARG("priority", setbridge_priority), 733 DEF_CMD_ARG("proto", setbridge_protocol), 734 DEF_CMD_ARG("holdcnt", setbridge_holdcount), 735 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), 736 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), 737 DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr), 738 DEF_CMD_ARG("timeout", setbridge_timeout), 739 DEF_CMD_ARG("private", setbridge_private), 740 DEF_CMD_ARG("-private", unsetbridge_private), 741}; 742static struct afswtch af_bridge = { 743 .af_name = "af_bridge", 744 .af_af = AF_UNSPEC, 745 .af_other_status = bridge_status, 746}; 747 748static __constructor void 749bridge_ctor(void) 750{ 751 int i; 752 753 for (i = 0; i < nitems(bridge_cmds); i++) 754 cmd_register(&bridge_cmds[i]); 755 af_register(&af_bridge); 756} 757