ifbridge.c revision 151040
1146985Sthompsa/*- 2146985Sthompsa * Copyright 2001 Wasabi Systems, Inc. 3146985Sthompsa * All rights reserved. 4146985Sthompsa * 5146985Sthompsa * Written by Jason R. Thorpe for Wasabi Systems, Inc. 6146985Sthompsa * 7146985Sthompsa * Redistribution and use in source and binary forms, with or without 8146985Sthompsa * modification, are permitted provided that the following conditions 9146985Sthompsa * are met: 10146985Sthompsa * 1. Redistributions of source code must retain the above copyright 11146985Sthompsa * notice, this list of conditions and the following disclaimer. 12146985Sthompsa * 2. Redistributions in binary form must reproduce the above copyright 13146985Sthompsa * notice, this list of conditions and the following disclaimer in the 14146985Sthompsa * documentation and/or other materials provided with the distribution. 15146985Sthompsa * 3. All advertising materials mentioning features or use of this software 16146985Sthompsa * must display the following acknowledgement: 17146985Sthompsa * This product includes software developed for the NetBSD Project by 18146985Sthompsa * Wasabi Systems, Inc. 19146985Sthompsa * 4. The name of Wasabi Systems, Inc. may not be used to endorse 20146985Sthompsa * or promote products derived from this software without specific prior 21146985Sthompsa * written permission. 22146985Sthompsa * 23146985Sthompsa * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 24146985Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25146985Sthompsa * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26146985Sthompsa * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 27146985Sthompsa * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28146985Sthompsa * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29146985Sthompsa * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30146985Sthompsa * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31146985Sthompsa * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32146985Sthompsa * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33146985Sthompsa * POSSIBILITY OF SUCH DAMAGE. 34146985Sthompsa */ 35146985Sthompsa 36146985Sthompsa#ifndef lint 37146985Sthompsastatic const char rcsid[] = 38146985Sthompsa "$FreeBSD: head/sbin/ifconfig/ifbridge.c 151040 2005-10-07 00:32:16Z thompsa $"; 39146985Sthompsa#endif /* not lint */ 40146985Sthompsa 41146985Sthompsa#include <sys/param.h> 42146985Sthompsa#include <sys/ioctl.h> 43146985Sthompsa#include <sys/socket.h> 44146985Sthompsa#include <sys/sockio.h> 45146985Sthompsa 46146985Sthompsa#include <stdlib.h> 47146985Sthompsa#include <unistd.h> 48146985Sthompsa 49146985Sthompsa#include <net/ethernet.h> 50146985Sthompsa#include <net/if.h> 51146985Sthompsa#include <net/if_bridgevar.h> 52146985Sthompsa#include <net/route.h> 53146985Sthompsa 54146985Sthompsa#include <ctype.h> 55146985Sthompsa#include <stdio.h> 56146985Sthompsa#include <string.h> 57146985Sthompsa#include <stdlib.h> 58146985Sthompsa#include <unistd.h> 59146985Sthompsa#include <err.h> 60146985Sthompsa#include <errno.h> 61146985Sthompsa 62146985Sthompsa#include "ifconfig.h" 63146985Sthompsa 64146985Sthompsastatic int 65146985Sthompsaget_val(const char *cp, u_long *valp) 66146985Sthompsa{ 67146985Sthompsa char *endptr; 68146985Sthompsa u_long val; 69146985Sthompsa 70146985Sthompsa errno = 0; 71146985Sthompsa val = strtoul(cp, &endptr, 0); 72146985Sthompsa if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE) 73146985Sthompsa return (-1); 74146985Sthompsa 75146985Sthompsa *valp = val; 76146985Sthompsa return (0); 77146985Sthompsa} 78146985Sthompsa 79146985Sthompsastatic int 80146985Sthompsado_cmd(int sock, u_long op, void *arg, size_t argsize, int set) 81146985Sthompsa{ 82146985Sthompsa struct ifdrv ifd; 83146985Sthompsa 84146985Sthompsa memset(&ifd, 0, sizeof(ifd)); 85146985Sthompsa 86146985Sthompsa strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 87146985Sthompsa ifd.ifd_cmd = op; 88146985Sthompsa ifd.ifd_len = argsize; 89146985Sthompsa ifd.ifd_data = arg; 90146985Sthompsa 91146985Sthompsa return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); 92146985Sthompsa} 93146985Sthompsa 94146985Sthompsastatic void 95146985Sthompsado_bridgeflag(int sock, const char *ifs, int flag, int set) 96146985Sthompsa{ 97146985Sthompsa struct ifbreq req; 98146985Sthompsa 99146985Sthompsa strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); 100146985Sthompsa 101146985Sthompsa if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) 102146985Sthompsa err(1, "unable to get bridge flags"); 103146985Sthompsa 104146985Sthompsa if (set) 105146985Sthompsa req.ifbr_ifsflags |= flag; 106146985Sthompsa else 107146985Sthompsa req.ifbr_ifsflags &= ~flag; 108146985Sthompsa 109146985Sthompsa if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) 110146985Sthompsa err(1, "unable to set bridge flags"); 111146985Sthompsa} 112146985Sthompsa 113146985Sthompsastatic void 114151040Sthompsabridge_interfaces(int s, const char *prefix) 115146985Sthompsa{ 116146985Sthompsa static const char *stpstates[] = { 117146985Sthompsa "disabled", 118146985Sthompsa "listening", 119146985Sthompsa "learning", 120146985Sthompsa "forwarding", 121146985Sthompsa "blocking", 122146985Sthompsa }; 123146985Sthompsa struct ifbifconf bifc; 124146985Sthompsa struct ifbreq *req; 125146985Sthompsa char *inbuf = NULL, *ninbuf; 126151040Sthompsa char *p, *pad; 127146985Sthompsa int i, len = 8192; 128146985Sthompsa 129151040Sthompsa pad = strdup(prefix); 130151040Sthompsa if (pad == NULL) 131151040Sthompsa err(1, "strdup"); 132151040Sthompsa /* replace the prefix with whitespace */ 133151040Sthompsa for (p = pad; *p != '\0'; p++) { 134151040Sthompsa if(isprint(*p)) 135151040Sthompsa *p = ' '; 136151040Sthompsa } 137151040Sthompsa 138146985Sthompsa for (;;) { 139146985Sthompsa ninbuf = realloc(inbuf, len); 140146985Sthompsa if (ninbuf == NULL) 141146985Sthompsa err(1, "unable to allocate interface buffer"); 142146985Sthompsa bifc.ifbic_len = len; 143146985Sthompsa bifc.ifbic_buf = inbuf = ninbuf; 144146985Sthompsa if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0) 145146985Sthompsa err(1, "unable to get interface list"); 146146985Sthompsa if ((bifc.ifbic_len + sizeof(*req)) < len) 147146985Sthompsa break; 148146985Sthompsa len *= 2; 149146985Sthompsa } 150146985Sthompsa 151146985Sthompsa for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) { 152146985Sthompsa req = bifc.ifbic_req + i; 153146985Sthompsa printf("%s%s ", prefix, req->ifbr_ifsname); 154146985Sthompsa printb("flags", req->ifbr_ifsflags, IFBIFBITS); 155146985Sthompsa printf("\n"); 156146985Sthompsa 157146985Sthompsa if (req->ifbr_ifsflags & IFBIF_STP) { 158151040Sthompsa printf("%s", pad); 159151040Sthompsa printf("port %u priority %u", 160151040Sthompsa req->ifbr_portno, req->ifbr_priority); 161146985Sthompsa printf(" path cost %u", req->ifbr_path_cost); 162146985Sthompsa if (req->ifbr_state < 163146985Sthompsa sizeof(stpstates) / sizeof(stpstates[0])) 164146985Sthompsa printf(" %s", stpstates[req->ifbr_state]); 165146985Sthompsa else 166146985Sthompsa printf(" <unknown state %d>", 167146985Sthompsa req->ifbr_state); 168151040Sthompsa printf("\n"); 169146985Sthompsa } 170146985Sthompsa } 171146985Sthompsa 172146985Sthompsa free(inbuf); 173146985Sthompsa} 174146985Sthompsa 175146985Sthompsastatic void 176146985Sthompsabridge_addresses(int s, const char *prefix) 177146985Sthompsa{ 178146985Sthompsa struct ifbaconf ifbac; 179146985Sthompsa struct ifbareq *ifba; 180146985Sthompsa char *inbuf = NULL, *ninbuf; 181146985Sthompsa int i, len = 8192; 182146985Sthompsa struct ether_addr ea; 183146985Sthompsa 184146985Sthompsa for (;;) { 185146985Sthompsa ninbuf = realloc(inbuf, len); 186146985Sthompsa if (ninbuf == NULL) 187146985Sthompsa err(1, "unable to allocate address buffer"); 188146985Sthompsa ifbac.ifbac_len = len; 189146985Sthompsa ifbac.ifbac_buf = inbuf = ninbuf; 190146985Sthompsa if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) 191146985Sthompsa err(1, "unable to get address cache"); 192146985Sthompsa if ((ifbac.ifbac_len + sizeof(*ifba)) < len) 193146985Sthompsa break; 194146985Sthompsa len *= 2; 195146985Sthompsa } 196146985Sthompsa 197146985Sthompsa for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { 198146985Sthompsa ifba = ifbac.ifbac_req + i; 199146985Sthompsa memcpy(ea.octet, ifba->ifba_dst, 200146985Sthompsa sizeof(ea.octet)); 201146985Sthompsa printf("%s%s %s %lu ", prefix, ether_ntoa(&ea), 202146985Sthompsa ifba->ifba_ifsname, ifba->ifba_expire); 203146985Sthompsa printb("flags", ifba->ifba_flags, IFBAFBITS); 204146985Sthompsa printf("\n"); 205146985Sthompsa } 206146985Sthompsa 207146985Sthompsa free(inbuf); 208146985Sthompsa} 209146985Sthompsa 210146985Sthompsastatic void 211146985Sthompsabridge_status(int s) 212146985Sthompsa{ 213146985Sthompsa struct ifbrparam param; 214146985Sthompsa u_int16_t pri; 215146985Sthompsa u_int8_t ht, fd, ma; 216146985Sthompsa 217146985Sthompsa if (do_cmd(s, BRDGGPRI, ¶m, sizeof(param), 0) < 0) 218146985Sthompsa return; 219146985Sthompsa pri = param.ifbrp_prio; 220146985Sthompsa 221146985Sthompsa if (do_cmd(s, BRDGGHT, ¶m, sizeof(param), 0) < 0) 222146985Sthompsa return; 223146985Sthompsa ht = param.ifbrp_hellotime; 224146985Sthompsa 225146985Sthompsa if (do_cmd(s, BRDGGFD, ¶m, sizeof(param), 0) < 0) 226146985Sthompsa return; 227146985Sthompsa fd = param.ifbrp_fwddelay; 228146985Sthompsa 229146985Sthompsa if (do_cmd(s, BRDGGMA, ¶m, sizeof(param), 0) < 0) 230146985Sthompsa return; 231146985Sthompsa ma = param.ifbrp_maxage; 232146985Sthompsa 233146985Sthompsa printf("\tpriority %u hellotime %u fwddelay %u maxage %u\n", 234146985Sthompsa pri, ht, fd, ma); 235146985Sthompsa 236151040Sthompsa bridge_interfaces(s, "\tmember: "); 237146985Sthompsa 238146985Sthompsa return; 239146985Sthompsa 240146985Sthompsa} 241146985Sthompsa 242146985Sthompsastatic void 243146985Sthompsasetbridge_add(const char *val, int d, int s, const struct afswtch *afp) 244146985Sthompsa{ 245146985Sthompsa struct ifbreq req; 246146985Sthompsa 247146985Sthompsa memset(&req, 0, sizeof(req)); 248146985Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 249146985Sthompsa if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) 250146985Sthompsa err(1, "BRDGADD %s", val); 251146985Sthompsa} 252146985Sthompsa 253146985Sthompsastatic void 254146985Sthompsasetbridge_delete(const char *val, int d, int s, const struct afswtch *afp) 255146985Sthompsa{ 256146985Sthompsa struct ifbreq req; 257146985Sthompsa 258146985Sthompsa memset(&req, 0, sizeof(req)); 259146985Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 260146985Sthompsa if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) 261146985Sthompsa err(1, "BRDGDEL %s", val); 262146985Sthompsa} 263146985Sthompsa 264146985Sthompsastatic void 265146985Sthompsasetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 266146985Sthompsa{ 267146985Sthompsa 268146985Sthompsa do_bridgeflag(s, val, IFBIF_DISCOVER, 1); 269146985Sthompsa} 270146985Sthompsa 271146985Sthompsastatic void 272146985Sthompsaunsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) 273146985Sthompsa{ 274146985Sthompsa 275146985Sthompsa do_bridgeflag(s, val, IFBIF_DISCOVER, 0); 276146985Sthompsa} 277146985Sthompsa 278146985Sthompsastatic void 279146985Sthompsasetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 280146985Sthompsa{ 281146985Sthompsa 282146985Sthompsa do_bridgeflag(s, val, IFBIF_LEARNING, 1); 283146985Sthompsa} 284146985Sthompsa 285146985Sthompsastatic void 286146985Sthompsaunsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) 287146985Sthompsa{ 288146985Sthompsa 289146985Sthompsa do_bridgeflag(s, val, IFBIF_LEARNING, 0); 290146985Sthompsa} 291146985Sthompsa 292146985Sthompsastatic void 293146985Sthompsasetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 294146985Sthompsa{ 295146985Sthompsa 296146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 1); 297146985Sthompsa} 298146985Sthompsa 299146985Sthompsastatic void 300146985Sthompsaunsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 301146985Sthompsa{ 302146985Sthompsa 303146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 0); 304146985Sthompsa} 305146985Sthompsa 306146985Sthompsastatic void 307146985Sthompsasetbridge_flush(const char *val, int d, int s, const struct afswtch *afp) 308146985Sthompsa{ 309146985Sthompsa struct ifbreq req; 310146985Sthompsa 311146985Sthompsa memset(&req, 0, sizeof(req)); 312146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHDYN; 313146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 314146985Sthompsa err(1, "BRDGFLUSH"); 315146985Sthompsa} 316146985Sthompsa 317146985Sthompsastatic void 318146985Sthompsasetbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) 319146985Sthompsa{ 320146985Sthompsa struct ifbreq req; 321146985Sthompsa 322146985Sthompsa memset(&req, 0, sizeof(req)); 323146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHALL; 324146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 325146985Sthompsa err(1, "BRDGFLUSH"); 326146985Sthompsa} 327146985Sthompsa 328146985Sthompsastatic void 329146985Sthompsasetbridge_static(const char *val, const char *mac, int s, 330146985Sthompsa const struct afswtch *afp) 331146985Sthompsa{ 332146985Sthompsa struct ifbareq req; 333146985Sthompsa struct ether_addr *ea; 334146985Sthompsa 335146985Sthompsa memset(&req, 0, sizeof(req)); 336146985Sthompsa strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); 337146985Sthompsa 338146985Sthompsa ea = ether_aton(mac); 339146985Sthompsa if (ea == NULL) 340146985Sthompsa errx(1, "%s: invalid address: %s", val, mac); 341146985Sthompsa 342146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 343146985Sthompsa req.ifba_flags = IFBAF_STATIC; 344146985Sthompsa 345146985Sthompsa if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) 346146985Sthompsa err(1, "BRDGSADDR %s", val); 347146985Sthompsa} 348146985Sthompsa 349146985Sthompsastatic void 350146985Sthompsasetbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) 351146985Sthompsa{ 352146985Sthompsa struct ifbareq req; 353146985Sthompsa struct ether_addr *ea; 354146985Sthompsa 355146985Sthompsa memset(&req, 0, sizeof(req)); 356146985Sthompsa 357146985Sthompsa ea = ether_aton(val); 358146985Sthompsa if (ea == NULL) 359146985Sthompsa errx(1, "invalid address: %s", val); 360146985Sthompsa 361146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 362146985Sthompsa 363146985Sthompsa if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) 364146985Sthompsa err(1, "BRDGDADDR %s", val); 365146985Sthompsa} 366146985Sthompsa 367146985Sthompsastatic void 368146985Sthompsasetbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 369146985Sthompsa{ 370146985Sthompsa 371146985Sthompsa bridge_addresses(s, ""); 372146985Sthompsa} 373146985Sthompsa 374146985Sthompsastatic void 375146985Sthompsasetbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) 376146985Sthompsa{ 377146985Sthompsa struct ifbrparam param; 378146985Sthompsa u_long val; 379146985Sthompsa 380146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 381146985Sthompsa errx(1, "invalid value: %s", arg); 382146985Sthompsa 383146985Sthompsa param.ifbrp_csize = val & 0xffffffff; 384146985Sthompsa 385146985Sthompsa if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 386146985Sthompsa err(1, "BRDGSCACHE %s", arg); 387146985Sthompsa} 388146985Sthompsa 389146985Sthompsastatic void 390146985Sthompsasetbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) 391146985Sthompsa{ 392146985Sthompsa struct ifbrparam param; 393146985Sthompsa u_long val; 394146985Sthompsa 395146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 396146985Sthompsa errx(1, "invalid value: %s", arg); 397146985Sthompsa 398146985Sthompsa param.ifbrp_hellotime = val & 0xff; 399146985Sthompsa 400146985Sthompsa if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) 401146985Sthompsa err(1, "BRDGSHT %s", arg); 402146985Sthompsa} 403146985Sthompsa 404146985Sthompsastatic void 405146985Sthompsasetbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) 406146985Sthompsa{ 407146985Sthompsa struct ifbrparam param; 408146985Sthompsa u_long val; 409146985Sthompsa 410146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 411146985Sthompsa errx(1, "invalid value: %s", arg); 412146985Sthompsa 413146985Sthompsa param.ifbrp_fwddelay = val & 0xff; 414146985Sthompsa 415146985Sthompsa if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) 416146985Sthompsa err(1, "BRDGSFD %s", arg); 417146985Sthompsa} 418146985Sthompsa 419146985Sthompsastatic void 420146985Sthompsasetbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) 421146985Sthompsa{ 422146985Sthompsa struct ifbrparam param; 423146985Sthompsa u_long val; 424146985Sthompsa 425146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 426146985Sthompsa errx(1, "invalid value: %s", arg); 427146985Sthompsa 428146985Sthompsa param.ifbrp_maxage = val & 0xff; 429146985Sthompsa 430146985Sthompsa if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) 431146985Sthompsa err(1, "BRDGSMA %s", arg); 432146985Sthompsa} 433146985Sthompsa 434146985Sthompsastatic void 435146985Sthompsasetbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) 436146985Sthompsa{ 437146985Sthompsa struct ifbrparam param; 438146985Sthompsa u_long val; 439146985Sthompsa 440146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) 441146985Sthompsa errx(1, "invalid value: %s", arg); 442146985Sthompsa 443146985Sthompsa param.ifbrp_prio = val & 0xffff; 444146985Sthompsa 445146985Sthompsa if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 446146985Sthompsa err(1, "BRDGSPRI %s", arg); 447146985Sthompsa} 448146985Sthompsa 449146985Sthompsastatic void 450146985Sthompsasetbridge_ifpriority(const char *ifn, const char *pri, int s, 451146985Sthompsa const struct afswtch *afp) 452146985Sthompsa{ 453146985Sthompsa struct ifbreq req; 454146985Sthompsa u_long val; 455146985Sthompsa 456146985Sthompsa memset(&req, 0, sizeof(req)); 457146985Sthompsa 458146985Sthompsa if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) 459146985Sthompsa errx(1, "invalid value: %s", pri); 460146985Sthompsa 461146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 462146985Sthompsa req.ifbr_priority = val & 0xff; 463146985Sthompsa 464146985Sthompsa if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) 465146985Sthompsa err(1, "BRDGSIFPRIO %s", pri); 466146985Sthompsa} 467146985Sthompsa 468146985Sthompsastatic void 469146985Sthompsasetbridge_ifpathcost(const char *ifn, const char *cost, int s, 470146985Sthompsa const struct afswtch *afp) 471146985Sthompsa{ 472146985Sthompsa struct ifbreq req; 473146985Sthompsa u_long val; 474146985Sthompsa 475146985Sthompsa memset(&req, 0, sizeof(req)); 476146985Sthompsa 477146985Sthompsa if (get_val(cost, &val) < 0 || (val & ~0xff) != 0) 478146985Sthompsa errx(1, "invalid value: %s", cost); 479146985Sthompsa 480146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 481146985Sthompsa req.ifbr_path_cost = val & 0xffff; 482146985Sthompsa 483146985Sthompsa if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) 484146985Sthompsa err(1, "BRDGSIFCOST %s", cost); 485146985Sthompsa} 486146985Sthompsa 487146985Sthompsastatic void 488146985Sthompsasetbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) 489146985Sthompsa{ 490146985Sthompsa struct ifbrparam param; 491146985Sthompsa u_long val; 492146985Sthompsa 493146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 494146985Sthompsa errx(1, "invalid value: %s", arg); 495146985Sthompsa 496146985Sthompsa param.ifbrp_ctime = val & 0xffffffff; 497146985Sthompsa 498146985Sthompsa if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) 499146985Sthompsa err(1, "BRDGSTO %s", arg); 500146985Sthompsa} 501146985Sthompsa 502146985Sthompsastatic struct cmd bridge_cmds[] = { 503146985Sthompsa DEF_CMD_ARG("addm", setbridge_add), 504146985Sthompsa DEF_CMD_ARG("deletem", setbridge_delete), 505146985Sthompsa DEF_CMD_ARG("discover", setbridge_discover), 506146985Sthompsa DEF_CMD_ARG("-discover", unsetbridge_discover), 507146985Sthompsa DEF_CMD_ARG("learn", setbridge_learn), 508146985Sthompsa DEF_CMD_ARG("-learn", unsetbridge_learn), 509146985Sthompsa DEF_CMD_ARG("stp", setbridge_stp), 510146985Sthompsa DEF_CMD_ARG("-stp", unsetbridge_stp), 511146985Sthompsa DEF_CMD("flush", 0, setbridge_flush), 512146985Sthompsa DEF_CMD("flushall", 0, setbridge_flushall), 513146985Sthompsa DEF_CMD_ARG2("static", setbridge_static), 514146985Sthompsa DEF_CMD_ARG("deladdr", setbridge_deladdr), 515146985Sthompsa DEF_CMD("addr", 1, setbridge_addr), 516146985Sthompsa DEF_CMD_ARG("maxaddr", setbridge_maxaddr), 517146985Sthompsa DEF_CMD_ARG("hellotime", setbridge_hellotime), 518146985Sthompsa DEF_CMD_ARG("fwddelay", setbridge_fwddelay), 519146985Sthompsa DEF_CMD_ARG("maxage", setbridge_maxage), 520146985Sthompsa DEF_CMD_ARG("priority", setbridge_priority), 521146985Sthompsa DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), 522146985Sthompsa DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), 523146985Sthompsa DEF_CMD_ARG("timeout", setbridge_timeout), 524146985Sthompsa}; 525146985Sthompsastatic struct afswtch af_bridge = { 526146985Sthompsa .af_name = "af_bridge", 527146985Sthompsa .af_af = AF_UNSPEC, 528146985Sthompsa .af_other_status = bridge_status, 529146985Sthompsa}; 530146985Sthompsa 531146985Sthompsastatic __constructor void 532146985Sthompsabridge_ctor(void) 533146985Sthompsa{ 534146985Sthompsa#define N(a) (sizeof(a) / sizeof(a[0])) 535146985Sthompsa int i; 536146985Sthompsa 537146985Sthompsa for (i = 0; i < N(bridge_cmds); i++) 538146985Sthompsa cmd_register(&bridge_cmds[i]); 539146985Sthompsa af_register(&af_bridge); 540146985Sthompsa#undef N 541146985Sthompsa} 542