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 39 static const char rcsid[] = 40 "$FreeBSD$"; 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 static const char *stpstates[] = { STP_STATES }; 67 static const char *stpproto[] = { STP_PROTOS }; 68 static const char *stproles[] = { STP_ROLES }; 69 70 static int 71 get_val(const char *cp, u_long *valp) 72 { 73 char *endptr; 74 u_long val; 75 76 errno = 0; 77 val = strtoul(cp, &endptr, 0); 78 if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE) 79 return (-1); 80 81 *valp = val; 82 return (0); 83 } 84 85 static int 86 do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) 87 { 88 struct ifdrv ifd; 89 90 memset(&ifd, 0, sizeof(ifd)); 91 92 strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 93 ifd.ifd_cmd = op; 94 ifd.ifd_len = argsize; 95 ifd.ifd_data = arg; 96 97 return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); 98 } 99 100 static void 101 do_bridgeflag(int sock, const char *ifs, int flag, int set) 102 { 103 struct ifbreq req; 104 105 strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); 106 107 if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) 108 err(1, "unable to get bridge flags"); 109 110 if (set) 111 req.ifbr_ifsflags |= flag; 112 else 113 req.ifbr_ifsflags &= ~flag; 114 115 if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) 116 err(1, "unable to set bridge flags"); 117 } 118 119 static void 120 bridge_interfaces(int s, const char *prefix) 121 { 122 struct ifbifconf bifc; 123 struct ifbreq *req; 124 char *inbuf = NULL, *ninbuf; 125 char *p, *pad; 126 int i, len = 8192; 127 128 pad = strdup(prefix); 129 if (pad == NULL) 130 err(1, "strdup"); 131 /* replace the prefix with whitespace */ 132 for (p = pad; *p != '\0'; p++) { 133 if(isprint(*p)) 134 *p = ' '; 135 } 136 137 for (;;) { 138 ninbuf = realloc(inbuf, len); 139 if (ninbuf == NULL) 140 err(1, "unable to allocate interface buffer"); 141 bifc.ifbic_len = len; 142 bifc.ifbic_buf = inbuf = ninbuf; 143 if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0) 144 err(1, "unable to get interface list"); 145 if ((bifc.ifbic_len + sizeof(*req)) < len) 146 break; 147 len *= 2; 148 } 149 150 for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) { 151 req = bifc.ifbic_req + i; 152 printf("%s%s ", prefix, req->ifbr_ifsname); 153 printb("flags", req->ifbr_ifsflags, IFBIFBITS); 154 printf("\n"); 155 156 printf("%s", pad); 157 printf("ifmaxaddr %u", req->ifbr_addrmax); 158 printf(" port %u priority %u", req->ifbr_portno, 159 req->ifbr_priority); 160 printf(" path cost %u", req->ifbr_path_cost); 161 162 if (req->ifbr_ifsflags & IFBIF_STP) { 163 if (req->ifbr_proto < nitems(stpproto)) 164 printf(" proto %s", stpproto[req->ifbr_proto]); 165 else 166 printf(" <unknown proto %d>", 167 req->ifbr_proto); 168 169 printf("\n%s", pad); 170 if (req->ifbr_role < nitems(stproles)) 171 printf("role %s", stproles[req->ifbr_role]); 172 else 173 printf("<unknown role %d>", 174 req->ifbr_role); 175 if (req->ifbr_state < nitems(stpstates)) 176 printf(" state %s", stpstates[req->ifbr_state]); 177 else 178 printf(" <unknown state %d>", 179 req->ifbr_state); 180 } 181 printf("\n"); 182 } 183 free(pad); 184 free(inbuf); 185 } 186 187 static void 188 bridge_addresses(int s, const char *prefix) 189 { 190 struct ifbaconf ifbac; 191 struct ifbareq *ifba; 192 char *inbuf = NULL, *ninbuf; 193 int i, len = 8192; 194 struct ether_addr ea; 195 196 for (;;) { 197 ninbuf = realloc(inbuf, len); 198 if (ninbuf == NULL) 199 err(1, "unable to allocate address buffer"); 200 ifbac.ifbac_len = len; 201 ifbac.ifbac_buf = inbuf = ninbuf; 202 if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) 203 err(1, "unable to get address cache"); 204 if ((ifbac.ifbac_len + sizeof(*ifba)) < len) 205 break; 206 len *= 2; 207 } 208 209 for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { 210 ifba = ifbac.ifbac_req + i; 211 memcpy(ea.octet, ifba->ifba_dst, 212 sizeof(ea.octet)); 213 printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea), 214 ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire); 215 printb("flags", ifba->ifba_flags, IFBAFBITS); 216 printf("\n"); 217 } 218 219 free(inbuf); 220 } 221 222 static void 223 bridge_status(int s) 224 { 225 struct ifbropreq ifbp; 226 struct ifbrparam param; 227 u_int16_t pri; 228 u_int8_t ht, fd, ma, hc, pro; 229 u_int8_t lladdr[ETHER_ADDR_LEN]; 230 u_int16_t bprio; 231 u_int32_t csize, ctime; 232 233 if (do_cmd(s, BRDGGCACHE, ¶m, sizeof(param), 0) < 0) 234 return; 235 csize = param.ifbrp_csize; 236 if (do_cmd(s, BRDGGTO, ¶m, sizeof(param), 0) < 0) 237 return; 238 ctime = param.ifbrp_ctime; 239 if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0) 240 return; 241 pri = ifbp.ifbop_priority; 242 pro = ifbp.ifbop_protocol; 243 ht = ifbp.ifbop_hellotime; 244 fd = ifbp.ifbop_fwddelay; 245 hc = ifbp.ifbop_holdcount; 246 ma = ifbp.ifbop_maxage; 247 248 PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr); 249 printf("\tid %s priority %u hellotime %u fwddelay %u\n", 250 ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd); 251 printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n", 252 ma, hc, stpproto[pro], csize, ctime); 253 254 PV2ID(ifbp.ifbop_designated_root, bprio, lladdr); 255 printf("\troot id %s priority %d ifcost %u port %u\n", 256 ether_ntoa((struct ether_addr *)lladdr), bprio, 257 ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff); 258 259 bridge_interfaces(s, "\tmember: "); 260 261 return; 262 263 } 264 265 static void 266 setbridge_add(const char *val, int d, int s, const struct afswtch *afp) 267 { 268 struct ifbreq req; 269 270 memset(&req, 0, sizeof(req)); 271 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 272 if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) 273 err(1, "BRDGADD %s", val); 274 } 275 276 static void 277 setbridge_delete(const char *val, int d, int s, const struct afswtch *afp) 278 { 279 struct ifbreq req; 280 281 memset(&req, 0, sizeof(req)); 282 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 283 if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) 284 err(1, "BRDGDEL %s", val); 285 } 286 287 static void 288 setbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 289 { 290 291 do_bridgeflag(s, val, IFBIF_DISCOVER, 1); 292 } 293 294 static void 295 unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 296 { 297 298 do_bridgeflag(s, val, IFBIF_DISCOVER, 0); 299 } 300 301 static void 302 setbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 303 { 304 305 do_bridgeflag(s, val, IFBIF_LEARNING, 1); 306 } 307 308 static void 309 unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 310 { 311 312 do_bridgeflag(s, val, IFBIF_LEARNING, 0); 313 } 314 315 static void 316 setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 317 { 318 319 do_bridgeflag(s, val, IFBIF_STICKY, 1); 320 } 321 322 static void 323 unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 324 { 325 326 do_bridgeflag(s, val, IFBIF_STICKY, 0); 327 } 328 329 static void 330 setbridge_span(const char *val, int d, int s, const struct afswtch *afp) 331 { 332 struct ifbreq req; 333 334 memset(&req, 0, sizeof(req)); 335 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 336 if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) 337 err(1, "BRDGADDS %s", val); 338 } 339 340 static void 341 unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 342 { 343 struct ifbreq req; 344 345 memset(&req, 0, sizeof(req)); 346 strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 347 if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) 348 err(1, "BRDGDELS %s", val); 349 } 350 351 static void 352 setbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 353 { 354 355 do_bridgeflag(s, val, IFBIF_STP, 1); 356 } 357 358 static void 359 unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 360 { 361 362 do_bridgeflag(s, val, IFBIF_STP, 0); 363 } 364 365 static void 366 setbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 367 { 368 do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); 369 } 370 371 static void 372 unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 373 { 374 do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); 375 } 376 377 static void 378 setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 379 { 380 do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); 381 } 382 383 static void 384 unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 385 { 386 do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); 387 } 388 389 static void 390 setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 391 { 392 do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); 393 } 394 395 static void 396 unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 397 { 398 do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); 399 } 400 401 static void 402 setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 403 { 404 do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); 405 } 406 407 static void 408 unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 409 { 410 do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); 411 } 412 413 static void 414 setbridge_flush(const char *val, int d, int s, const struct afswtch *afp) 415 { 416 struct ifbreq req; 417 418 memset(&req, 0, sizeof(req)); 419 req.ifbr_ifsflags = IFBF_FLUSHDYN; 420 if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 421 err(1, "BRDGFLUSH"); 422 } 423 424 static void 425 setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) 426 { 427 struct ifbreq req; 428 429 memset(&req, 0, sizeof(req)); 430 req.ifbr_ifsflags = IFBF_FLUSHALL; 431 if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 432 err(1, "BRDGFLUSH"); 433 } 434 435 static void 436 setbridge_static(const char *val, const char *mac, int s, 437 const struct afswtch *afp) 438 { 439 struct ifbareq req; 440 struct ether_addr *ea; 441 442 memset(&req, 0, sizeof(req)); 443 strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); 444 445 ea = ether_aton(mac); 446 if (ea == NULL) 447 errx(1, "%s: invalid address: %s", val, mac); 448 449 memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 450 req.ifba_flags = IFBAF_STATIC; 451 req.ifba_vlan = 1; /* XXX allow user to specify */ 452 453 if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) 454 err(1, "BRDGSADDR %s", val); 455 } 456 457 static void 458 setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) 459 { 460 struct ifbareq req; 461 struct ether_addr *ea; 462 463 memset(&req, 0, sizeof(req)); 464 465 ea = ether_aton(val); 466 if (ea == NULL) 467 errx(1, "invalid address: %s", val); 468 469 memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 470 471 if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) 472 err(1, "BRDGDADDR %s", val); 473 } 474 475 static void 476 setbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 477 { 478 479 bridge_addresses(s, ""); 480 } 481 482 static void 483 setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) 484 { 485 struct ifbrparam param; 486 u_long val; 487 488 if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 489 errx(1, "invalid value: %s", arg); 490 491 param.ifbrp_csize = val & 0xffffffff; 492 493 if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 494 err(1, "BRDGSCACHE %s", arg); 495 } 496 497 static void 498 setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) 499 { 500 struct ifbrparam param; 501 u_long val; 502 503 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 504 errx(1, "invalid value: %s", arg); 505 506 param.ifbrp_hellotime = val & 0xff; 507 508 if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) 509 err(1, "BRDGSHT %s", arg); 510 } 511 512 static void 513 setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) 514 { 515 struct ifbrparam param; 516 u_long val; 517 518 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 519 errx(1, "invalid value: %s", arg); 520 521 param.ifbrp_fwddelay = val & 0xff; 522 523 if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) 524 err(1, "BRDGSFD %s", arg); 525 } 526 527 static void 528 setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) 529 { 530 struct ifbrparam param; 531 u_long val; 532 533 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 534 errx(1, "invalid value: %s", arg); 535 536 param.ifbrp_maxage = val & 0xff; 537 538 if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) 539 err(1, "BRDGSMA %s", arg); 540 } 541 542 static void 543 setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) 544 { 545 struct ifbrparam param; 546 u_long val; 547 548 if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) 549 errx(1, "invalid value: %s", arg); 550 551 param.ifbrp_prio = val & 0xffff; 552 553 if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 554 err(1, "BRDGSPRI %s", arg); 555 } 556 557 static void 558 setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) 559 { 560 struct ifbrparam param; 561 562 if (strcasecmp(arg, "stp") == 0) { 563 param.ifbrp_proto = 0; 564 } else if (strcasecmp(arg, "rstp") == 0) { 565 param.ifbrp_proto = 2; 566 } else { 567 errx(1, "unknown stp protocol"); 568 } 569 570 if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) 571 err(1, "BRDGSPROTO %s", arg); 572 } 573 574 static void 575 setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) 576 { 577 struct ifbrparam param; 578 u_long val; 579 580 if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 581 errx(1, "invalid value: %s", arg); 582 583 param.ifbrp_txhc = val & 0xff; 584 585 if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) 586 err(1, "BRDGSTXHC %s", arg); 587 } 588 589 static void 590 setbridge_ifpriority(const char *ifn, const char *pri, int s, 591 const struct afswtch *afp) 592 { 593 struct ifbreq req; 594 u_long val; 595 596 memset(&req, 0, sizeof(req)); 597 598 if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) 599 errx(1, "invalid value: %s", pri); 600 601 strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 602 req.ifbr_priority = val & 0xff; 603 604 if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) 605 err(1, "BRDGSIFPRIO %s", pri); 606 } 607 608 static void 609 setbridge_ifpathcost(const char *ifn, const char *cost, int s, 610 const struct afswtch *afp) 611 { 612 struct ifbreq req; 613 u_long val; 614 615 memset(&req, 0, sizeof(req)); 616 617 if (get_val(cost, &val) < 0) 618 errx(1, "invalid value: %s", cost); 619 620 strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 621 req.ifbr_path_cost = val; 622 623 if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) 624 err(1, "BRDGSIFCOST %s", cost); 625 } 626 627 static void 628 setbridge_ifmaxaddr(const char *ifn, const char *arg, int s, 629 const struct afswtch *afp) 630 { 631 struct ifbreq req; 632 u_long val; 633 634 memset(&req, 0, sizeof(req)); 635 636 if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 637 errx(1, "invalid value: %s", arg); 638 639 strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 640 req.ifbr_addrmax = val & 0xffffffff; 641 642 if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0) 643 err(1, "BRDGSIFAMAX %s", arg); 644 } 645 646 static void 647 setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) 648 { 649 struct ifbrparam param; 650 u_long val; 651 652 if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 653 errx(1, "invalid value: %s", arg); 654 655 param.ifbrp_ctime = val & 0xffffffff; 656 657 if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) 658 err(1, "BRDGSTO %s", arg); 659 } 660 661 static void 662 setbridge_private(const char *val, int d, int s, const struct afswtch *afp) 663 { 664 665 do_bridgeflag(s, val, IFBIF_PRIVATE, 1); 666 } 667 668 static void 669 unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 670 { 671 672 do_bridgeflag(s, val, IFBIF_PRIVATE, 0); 673 } 674 675 static struct cmd bridge_cmds[] = { 676 DEF_CMD_ARG("addm", setbridge_add), 677 DEF_CMD_ARG("deletem", setbridge_delete), 678 DEF_CMD_ARG("discover", setbridge_discover), 679 DEF_CMD_ARG("-discover", unsetbridge_discover), 680 DEF_CMD_ARG("learn", setbridge_learn), 681 DEF_CMD_ARG("-learn", unsetbridge_learn), 682 DEF_CMD_ARG("sticky", setbridge_sticky), 683 DEF_CMD_ARG("-sticky", unsetbridge_sticky), 684 DEF_CMD_ARG("span", setbridge_span), 685 DEF_CMD_ARG("-span", unsetbridge_span), 686 DEF_CMD_ARG("stp", setbridge_stp), 687 DEF_CMD_ARG("-stp", unsetbridge_stp), 688 DEF_CMD_ARG("edge", setbridge_edge), 689 DEF_CMD_ARG("-edge", unsetbridge_edge), 690 DEF_CMD_ARG("autoedge", setbridge_autoedge), 691 DEF_CMD_ARG("-autoedge", unsetbridge_autoedge), 692 DEF_CMD_ARG("ptp", setbridge_ptp), 693 DEF_CMD_ARG("-ptp", unsetbridge_ptp), 694 DEF_CMD_ARG("autoptp", setbridge_autoptp), 695 DEF_CMD_ARG("-autoptp", unsetbridge_autoptp), 696 DEF_CMD("flush", 0, setbridge_flush), 697 DEF_CMD("flushall", 0, setbridge_flushall), 698 DEF_CMD_ARG2("static", setbridge_static), 699 DEF_CMD_ARG("deladdr", setbridge_deladdr), 700 DEF_CMD("addr", 1, setbridge_addr), 701 DEF_CMD_ARG("maxaddr", setbridge_maxaddr), 702 DEF_CMD_ARG("hellotime", setbridge_hellotime), 703 DEF_CMD_ARG("fwddelay", setbridge_fwddelay), 704 DEF_CMD_ARG("maxage", setbridge_maxage), 705 DEF_CMD_ARG("priority", setbridge_priority), 706 DEF_CMD_ARG("proto", setbridge_protocol), 707 DEF_CMD_ARG("holdcnt", setbridge_holdcount), 708 DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), 709 DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), 710 DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr), 711 DEF_CMD_ARG("timeout", setbridge_timeout), 712 DEF_CMD_ARG("private", setbridge_private), 713 DEF_CMD_ARG("-private", unsetbridge_private), 714 }; 715 static struct afswtch af_bridge = { 716 .af_name = "af_bridge", 717 .af_af = AF_UNSPEC, 718 .af_other_status = bridge_status, 719 }; 720 721 static __constructor void 722 bridge_ctor(void) 723 { 724 int i; 725 726 for (i = 0; i < nitems(bridge_cmds); i++) 727 cmd_register(&bridge_cmds[i]); 728 af_register(&af_bridge); 729 } 730