ifbridge.c revision 153408
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 153408 2005-12-14 02:52:13Z 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 293153408Sthompsasetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 294153408Sthompsa{ 295153408Sthompsa struct ifbreq req; 296153408Sthompsa 297153408Sthompsa memset(&req, 0, sizeof(req)); 298153408Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 299153408Sthompsa if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) 300153408Sthompsa err(1, "BRDGADDS %s", val); 301153408Sthompsa} 302153408Sthompsa 303153408Sthompsastatic void 304153408Sthompsaunsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) 305153408Sthompsa{ 306153408Sthompsa struct ifbreq req; 307153408Sthompsa 308153408Sthompsa memset(&req, 0, sizeof(req)); 309153408Sthompsa strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); 310153408Sthompsa if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) 311153408Sthompsa err(1, "BRDGDELS %s", val); 312153408Sthompsa} 313153408Sthompsa 314153408Sthompsastatic void 315146985Sthompsasetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 316146985Sthompsa{ 317146985Sthompsa 318146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 1); 319146985Sthompsa} 320146985Sthompsa 321146985Sthompsastatic void 322146985Sthompsaunsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) 323146985Sthompsa{ 324146985Sthompsa 325146985Sthompsa do_bridgeflag(s, val, IFBIF_STP, 0); 326146985Sthompsa} 327146985Sthompsa 328146985Sthompsastatic void 329146985Sthompsasetbridge_flush(const char *val, int d, int s, const struct afswtch *afp) 330146985Sthompsa{ 331146985Sthompsa struct ifbreq req; 332146985Sthompsa 333146985Sthompsa memset(&req, 0, sizeof(req)); 334146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHDYN; 335146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 336146985Sthompsa err(1, "BRDGFLUSH"); 337146985Sthompsa} 338146985Sthompsa 339146985Sthompsastatic void 340146985Sthompsasetbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) 341146985Sthompsa{ 342146985Sthompsa struct ifbreq req; 343146985Sthompsa 344146985Sthompsa memset(&req, 0, sizeof(req)); 345146985Sthompsa req.ifbr_ifsflags = IFBF_FLUSHALL; 346146985Sthompsa if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) 347146985Sthompsa err(1, "BRDGFLUSH"); 348146985Sthompsa} 349146985Sthompsa 350146985Sthompsastatic void 351146985Sthompsasetbridge_static(const char *val, const char *mac, int s, 352146985Sthompsa const struct afswtch *afp) 353146985Sthompsa{ 354146985Sthompsa struct ifbareq req; 355146985Sthompsa struct ether_addr *ea; 356146985Sthompsa 357146985Sthompsa memset(&req, 0, sizeof(req)); 358146985Sthompsa strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname)); 359146985Sthompsa 360146985Sthompsa ea = ether_aton(mac); 361146985Sthompsa if (ea == NULL) 362146985Sthompsa errx(1, "%s: invalid address: %s", val, mac); 363146985Sthompsa 364146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 365146985Sthompsa req.ifba_flags = IFBAF_STATIC; 366146985Sthompsa 367146985Sthompsa if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) 368146985Sthompsa err(1, "BRDGSADDR %s", val); 369146985Sthompsa} 370146985Sthompsa 371146985Sthompsastatic void 372146985Sthompsasetbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) 373146985Sthompsa{ 374146985Sthompsa struct ifbareq req; 375146985Sthompsa struct ether_addr *ea; 376146985Sthompsa 377146985Sthompsa memset(&req, 0, sizeof(req)); 378146985Sthompsa 379146985Sthompsa ea = ether_aton(val); 380146985Sthompsa if (ea == NULL) 381146985Sthompsa errx(1, "invalid address: %s", val); 382146985Sthompsa 383146985Sthompsa memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); 384146985Sthompsa 385146985Sthompsa if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) 386146985Sthompsa err(1, "BRDGDADDR %s", val); 387146985Sthompsa} 388146985Sthompsa 389146985Sthompsastatic void 390146985Sthompsasetbridge_addr(const char *val, int d, int s, const struct afswtch *afp) 391146985Sthompsa{ 392146985Sthompsa 393146985Sthompsa bridge_addresses(s, ""); 394146985Sthompsa} 395146985Sthompsa 396146985Sthompsastatic void 397146985Sthompsasetbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) 398146985Sthompsa{ 399146985Sthompsa struct ifbrparam param; 400146985Sthompsa u_long val; 401146985Sthompsa 402146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 403146985Sthompsa errx(1, "invalid value: %s", arg); 404146985Sthompsa 405146985Sthompsa param.ifbrp_csize = val & 0xffffffff; 406146985Sthompsa 407146985Sthompsa if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 408146985Sthompsa err(1, "BRDGSCACHE %s", arg); 409146985Sthompsa} 410146985Sthompsa 411146985Sthompsastatic void 412146985Sthompsasetbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) 413146985Sthompsa{ 414146985Sthompsa struct ifbrparam param; 415146985Sthompsa u_long val; 416146985Sthompsa 417146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 418146985Sthompsa errx(1, "invalid value: %s", arg); 419146985Sthompsa 420146985Sthompsa param.ifbrp_hellotime = val & 0xff; 421146985Sthompsa 422146985Sthompsa if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) 423146985Sthompsa err(1, "BRDGSHT %s", arg); 424146985Sthompsa} 425146985Sthompsa 426146985Sthompsastatic void 427146985Sthompsasetbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) 428146985Sthompsa{ 429146985Sthompsa struct ifbrparam param; 430146985Sthompsa u_long val; 431146985Sthompsa 432146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 433146985Sthompsa errx(1, "invalid value: %s", arg); 434146985Sthompsa 435146985Sthompsa param.ifbrp_fwddelay = val & 0xff; 436146985Sthompsa 437146985Sthompsa if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) 438146985Sthompsa err(1, "BRDGSFD %s", arg); 439146985Sthompsa} 440146985Sthompsa 441146985Sthompsastatic void 442146985Sthompsasetbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) 443146985Sthompsa{ 444146985Sthompsa struct ifbrparam param; 445146985Sthompsa u_long val; 446146985Sthompsa 447146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) 448146985Sthompsa errx(1, "invalid value: %s", arg); 449146985Sthompsa 450146985Sthompsa param.ifbrp_maxage = val & 0xff; 451146985Sthompsa 452146985Sthompsa if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) 453146985Sthompsa err(1, "BRDGSMA %s", arg); 454146985Sthompsa} 455146985Sthompsa 456146985Sthompsastatic void 457146985Sthompsasetbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) 458146985Sthompsa{ 459146985Sthompsa struct ifbrparam param; 460146985Sthompsa u_long val; 461146985Sthompsa 462146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0) 463146985Sthompsa errx(1, "invalid value: %s", arg); 464146985Sthompsa 465146985Sthompsa param.ifbrp_prio = val & 0xffff; 466146985Sthompsa 467146985Sthompsa if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 468146985Sthompsa err(1, "BRDGSPRI %s", arg); 469146985Sthompsa} 470146985Sthompsa 471146985Sthompsastatic void 472146985Sthompsasetbridge_ifpriority(const char *ifn, const char *pri, int s, 473146985Sthompsa const struct afswtch *afp) 474146985Sthompsa{ 475146985Sthompsa struct ifbreq req; 476146985Sthompsa u_long val; 477146985Sthompsa 478146985Sthompsa memset(&req, 0, sizeof(req)); 479146985Sthompsa 480146985Sthompsa if (get_val(pri, &val) < 0 || (val & ~0xff) != 0) 481146985Sthompsa errx(1, "invalid value: %s", pri); 482146985Sthompsa 483146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 484146985Sthompsa req.ifbr_priority = val & 0xff; 485146985Sthompsa 486146985Sthompsa if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) 487146985Sthompsa err(1, "BRDGSIFPRIO %s", pri); 488146985Sthompsa} 489146985Sthompsa 490146985Sthompsastatic void 491146985Sthompsasetbridge_ifpathcost(const char *ifn, const char *cost, int s, 492146985Sthompsa const struct afswtch *afp) 493146985Sthompsa{ 494146985Sthompsa struct ifbreq req; 495146985Sthompsa u_long val; 496146985Sthompsa 497146985Sthompsa memset(&req, 0, sizeof(req)); 498146985Sthompsa 499146985Sthompsa if (get_val(cost, &val) < 0 || (val & ~0xff) != 0) 500146985Sthompsa errx(1, "invalid value: %s", cost); 501146985Sthompsa 502146985Sthompsa strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); 503146985Sthompsa req.ifbr_path_cost = val & 0xffff; 504146985Sthompsa 505146985Sthompsa if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) 506146985Sthompsa err(1, "BRDGSIFCOST %s", cost); 507146985Sthompsa} 508146985Sthompsa 509146985Sthompsastatic void 510146985Sthompsasetbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) 511146985Sthompsa{ 512146985Sthompsa struct ifbrparam param; 513146985Sthompsa u_long val; 514146985Sthompsa 515146985Sthompsa if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0) 516146985Sthompsa errx(1, "invalid value: %s", arg); 517146985Sthompsa 518146985Sthompsa param.ifbrp_ctime = val & 0xffffffff; 519146985Sthompsa 520146985Sthompsa if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) 521146985Sthompsa err(1, "BRDGSTO %s", arg); 522146985Sthompsa} 523146985Sthompsa 524146985Sthompsastatic struct cmd bridge_cmds[] = { 525146985Sthompsa DEF_CMD_ARG("addm", setbridge_add), 526146985Sthompsa DEF_CMD_ARG("deletem", setbridge_delete), 527146985Sthompsa DEF_CMD_ARG("discover", setbridge_discover), 528146985Sthompsa DEF_CMD_ARG("-discover", unsetbridge_discover), 529146985Sthompsa DEF_CMD_ARG("learn", setbridge_learn), 530146985Sthompsa DEF_CMD_ARG("-learn", unsetbridge_learn), 531153408Sthompsa DEF_CMD_ARG("span", setbridge_span), 532153408Sthompsa DEF_CMD_ARG("-span", unsetbridge_span), 533146985Sthompsa DEF_CMD_ARG("stp", setbridge_stp), 534146985Sthompsa DEF_CMD_ARG("-stp", unsetbridge_stp), 535146985Sthompsa DEF_CMD("flush", 0, setbridge_flush), 536146985Sthompsa DEF_CMD("flushall", 0, setbridge_flushall), 537146985Sthompsa DEF_CMD_ARG2("static", setbridge_static), 538146985Sthompsa DEF_CMD_ARG("deladdr", setbridge_deladdr), 539146985Sthompsa DEF_CMD("addr", 1, setbridge_addr), 540146985Sthompsa DEF_CMD_ARG("maxaddr", setbridge_maxaddr), 541146985Sthompsa DEF_CMD_ARG("hellotime", setbridge_hellotime), 542146985Sthompsa DEF_CMD_ARG("fwddelay", setbridge_fwddelay), 543146985Sthompsa DEF_CMD_ARG("maxage", setbridge_maxage), 544146985Sthompsa DEF_CMD_ARG("priority", setbridge_priority), 545146985Sthompsa DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), 546146985Sthompsa DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), 547146985Sthompsa DEF_CMD_ARG("timeout", setbridge_timeout), 548146985Sthompsa}; 549146985Sthompsastatic struct afswtch af_bridge = { 550146985Sthompsa .af_name = "af_bridge", 551146985Sthompsa .af_af = AF_UNSPEC, 552146985Sthompsa .af_other_status = bridge_status, 553146985Sthompsa}; 554146985Sthompsa 555146985Sthompsastatic __constructor void 556146985Sthompsabridge_ctor(void) 557146985Sthompsa{ 558146985Sthompsa#define N(a) (sizeof(a) / sizeof(a[0])) 559146985Sthompsa int i; 560146985Sthompsa 561146985Sthompsa for (i = 0; i < N(bridge_cmds); i++) 562146985Sthompsa cmd_register(&bridge_cmds[i]); 563146985Sthompsa af_register(&af_bridge); 564146985Sthompsa#undef N 565146985Sthompsa} 566