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 #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 76 static const char *stpstates[] = { 77 "disabled", 78 "listening", 79 "learning", 80 "forwarding", 81 "blocking", 82 "discarding" 83 }; 84 static const char *stpproto[] = { 85 "stp", 86 "-", 87 "rstp" 88 }; 89 static const char *stproles[] = { 90 "disabled", 91 "root", 92 "designated", 93 "alternate", 94 "backup" 95 }; 96 97 static int 98 get_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 112 static int 113 do_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 127 static void 128 do_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 146 static void 147 bridge_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 214 static void 215 bridge_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 249 static void 250 bridge_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 292 static void 293 setbridge_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 303 static void 304 setbridge_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 314 static void 315 setbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 316 { 317 318 do_bridgeflag(s, val, IFBIF_DISCOVER, 1); 319 } 320 321 static void 322 unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 323 { 324 325 do_bridgeflag(s, val, IFBIF_DISCOVER, 0); 326 } 327 328 static void 329 setbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 330 { 331 332 do_bridgeflag(s, val, IFBIF_LEARNING, 1); 333 } 334 335 static void 336 unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 337 { 338 339 do_bridgeflag(s, val, IFBIF_LEARNING, 0); 340 } 341 342 static void 343 setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 344 { 345 346 do_bridgeflag(s, val, IFBIF_STICKY, 1); 347 } 348 349 static void 350 unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) 351 { 352 353 do_bridgeflag(s, val, IFBIF_STICKY, 0); 354 } 355 356 static void 357 setbridge_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 367 static void 368 unsetbridge_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 378 static void 379 setbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 380 { 381 382 do_bridgeflag(s, val, IFBIF_STP, 1); 383 } 384 385 static void 386 unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 387 { 388 389 do_bridgeflag(s, val, IFBIF_STP, 0); 390 } 391 392 static void 393 setbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 394 { 395 do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); 396 } 397 398 static void 399 unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) 400 { 401 do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); 402 } 403 404 static void 405 setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 406 { 407 do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); 408 } 409 410 static void 411 unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) 412 { 413 do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); 414 } 415 416 static void 417 setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 418 { 419 do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); 420 } 421 422 static void 423 unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) 424 { 425 do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); 426 } 427 428 static void 429 setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 430 { 431 do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); 432 } 433 434 static void 435 unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) 436 { 437 do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); 438 } 439 440 static void 441 setbridge_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 451 static void 452 setbridge_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 462 static void 463 setbridge_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 484 static void 485 setbridge_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 502 static void 503 setbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 504 { 505 506 bridge_addresses(s, ""); 507 } 508 509 static void 510 setbridge_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 524 static void 525 setbridge_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 539 static void 540 setbridge_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 554 static void 555 setbridge_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 569 static void 570 setbridge_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 584 static void 585 setbridge_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 601 static void 602 setbridge_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 616 static void 617 setbridge_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 635 static void 636 setbridge_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 654 static void 655 setbridge_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 673 static void 674 setbridge_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 688 static void 689 setbridge_private(const char *val, int d, int s, const struct afswtch *afp) 690 { 691 692 do_bridgeflag(s, val, IFBIF_PRIVATE, 1); 693 } 694 695 static void 696 unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) 697 { 698 699 do_bridgeflag(s, val, IFBIF_PRIVATE, 0); 700 } 701 702 static 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 }; 742 static struct afswtch af_bridge = { 743 .af_name = "af_bridge", 744 .af_af = AF_UNSPEC, 745 .af_other_status = bridge_status, 746 }; 747 748 static __constructor void 749 bridge_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