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