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