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