1 /* $NetBSD: brconfig.c,v 1.2 2002/11/06 05:26:54 enami Exp $ */ 2 3 /* 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * brconfig(8) -- 40 * 41 * Configuration utility for the bridge(4) driver. 42 */ 43 44 #include <sys/param.h> 45 #include <sys/socket.h> 46 #include <sys/ioctl.h> 47 48 #include <net/if.h> 49 #include <net/if_ether.h> 50 #include <net/if_bridgevar.h> 51 52 #include <ctype.h> 53 #include <err.h> 54 #include <errno.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <unistd.h> 59 #include <ifaddrs.h> 60 61 struct command { 62 const char *cmd_keyword; 63 int cmd_argcnt; 64 int cmd_flags; 65 void (*cmd_func)(const struct command *, int, const char *, 66 char **); 67 }; 68 69 #define CMD_INVERT 0x01 /* "invert" the sense of the command */ 70 71 void cmd_add(const struct command *, int, const char *, char **); 72 void cmd_delete(const struct command *, int, const char *, char **); 73 void cmd_up(const struct command *, int, const char *, char **); 74 void cmd_down(const struct command *, int, const char *, char **); 75 void cmd_discover(const struct command *, int, const char *, char **); 76 void cmd_learn(const struct command *, int, const char *, char **); 77 void cmd_flush(const struct command *, int, const char *, char **); 78 void cmd_flushall(const struct command *, int, const char *, char **); 79 void cmd_static(const struct command *, int, const char *, char **); 80 void cmd_deladdr(const struct command *, int, const char *, char **); 81 void cmd_addr(const struct command *, int, const char *, char **); 82 void cmd_maxaddr(const struct command *, int, const char *, char **); 83 void cmd_hellotime(const struct command *, int, const char *, char **); 84 void cmd_fwddelay(const struct command *, int, const char *, char **); 85 void cmd_maxage(const struct command *, int, const char *, char **); 86 void cmd_priority(const struct command *, int, const char *, char **); 87 void cmd_ifpriority(const struct command *, int, const char *, char **); 88 void cmd_timeout(const struct command *, int, const char *, char **); 89 void cmd_stp(const struct command *, int, const char *, char **); 90 91 const struct command command_table[] = { 92 { "add", 1, 0, cmd_add }, 93 { "delete", 1, 0, cmd_delete }, 94 95 { "up", 0, 0, cmd_up }, 96 { "down", 0, 0, cmd_down }, 97 98 { "discover", 1, 0, cmd_discover }, 99 { "-discover", 1, CMD_INVERT, cmd_discover }, 100 101 { "learn", 1, 0, cmd_learn }, 102 { "-learn", 1, CMD_INVERT, cmd_learn }, 103 104 { "flush", 0, 0, cmd_flush }, 105 { "flushall", 0, 0, cmd_flushall }, 106 107 { "static", 2, 0, cmd_static }, 108 { "deladdr", 1, 0, cmd_deladdr }, 109 110 { "addr", 0, 0, cmd_addr }, 111 { "maxaddr", 1, 0, cmd_maxaddr }, 112 113 { "hellotime", 1, 0, cmd_hellotime }, 114 { "fwddelay", 1, 0, cmd_fwddelay }, 115 { "maxage", 1, 0, cmd_maxage }, 116 { "priority", 1, 0, cmd_priority }, 117 { "ifpriority", 2, 0, cmd_ifpriority }, 118 { "timeout", 1, 0, cmd_timeout }, 119 { "stp", 1, 0, cmd_stp }, 120 { "-stp", 1, CMD_INVERT, cmd_stp }, 121 122 { NULL, 0, 0, NULL }, 123 }; 124 125 void printall(int); 126 void status(int, const char *); 127 int is_bridge(const char *); 128 void show_config(int, const char *, const char *); 129 void show_interfaces(int, const char *, const char *); 130 void show_addresses(int, const char *, const char *); 131 int get_val(const char *, u_long *); 132 int do_cmd(int, const char *, u_long, void *, size_t, int); 133 void do_ifflag(int, const char *, int, int); 134 void do_bridgeflag(int, const char *, const char *, int, int); 135 136 void printb(const char *, u_int, const char *); 137 138 int main(int, char *[]); 139 void usage(void); 140 141 int aflag; 142 143 struct ifreq g_ifr; 144 int g_ifr_updated; 145 146 #define IFFBITS \ 147 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 148 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 149 150 int 151 main(int argc, char *argv[]) 152 { 153 const struct command *cmd; 154 char *bridge; 155 int sock, ch; 156 157 if (argc < 2) 158 usage(); 159 160 sock = socket(AF_INET, SOCK_DGRAM, 0); 161 if (sock < 0) 162 err(1, "socket"); 163 164 while ((ch = getopt(argc, argv, "a")) != -1) { 165 switch (ch) { 166 case 'a': 167 aflag = 1; 168 break; 169 170 default: 171 usage(); 172 } 173 } 174 175 argc -= optind; 176 argv += optind; 177 178 if (aflag) { 179 if (argc != 0) 180 usage(); 181 printall(sock); 182 exit(0); 183 } 184 185 if (argc == 0) 186 usage(); 187 188 bridge = argv[0]; 189 190 if (is_bridge(bridge) == 0) 191 errx(1, "%s is not a bridge", bridge); 192 193 /* Get a copy of the interface flags. */ 194 strlcpy(g_ifr.ifr_name, bridge, sizeof(g_ifr.ifr_name)); 195 if (ioctl(sock, SIOCGIFFLAGS, &g_ifr) < 0) 196 err(1, "unable to get interface flags"); 197 198 argc--; 199 argv++; 200 201 if (argc == 0) { 202 status(sock, bridge); 203 exit(0); 204 } 205 206 while (argc != 0) { 207 for (cmd = command_table; cmd->cmd_keyword != NULL; cmd++) { 208 if (strcmp(cmd->cmd_keyword, argv[0]) == 0) 209 break; 210 } 211 if (cmd->cmd_keyword == NULL) 212 errx(1, "unknown command: %s", argv[0]); 213 214 argc--; 215 argv++; 216 217 if (argc < cmd->cmd_argcnt) 218 errx(1, "command %s requires %d argument%s", 219 cmd->cmd_keyword, cmd->cmd_argcnt, 220 cmd->cmd_argcnt == 1 ? "" : "s"); 221 222 (*cmd->cmd_func)(cmd, sock, bridge, argv); 223 224 argc -= cmd->cmd_argcnt; 225 argv += cmd->cmd_argcnt; 226 } 227 228 /* If the flags changed, update them. */ 229 if (g_ifr_updated && ioctl(sock, SIOCSIFFLAGS, &g_ifr) < 0) 230 err(1, "unable to set interface flags"); 231 232 exit (0); 233 } 234 235 void 236 usage(void) 237 { 238 static const char *usage_strings[] = { 239 "-a", 240 "<bridge>", 241 "<bridge> up|down", 242 "<bridge> addr", 243 "<bridge> add <interface>", 244 "<bridge> delete <interface>", 245 "<bridge> maxaddr <size>", 246 "<bridge> timeout <time>", 247 "<bridge> static <interface> <address>", 248 "<bridge> deladdr <address>", 249 "<bridge> flush", 250 "<bridge> flushall", 251 "<bridge> discover|-discover <interface>", 252 "<bridge> learn|-learn <interface>", 253 "<bridge> stp|-stp <interface>", 254 "<bridge> maxage <time>", 255 "<bridge> fwddelay <time>", 256 "<bridge> hellotime <time>", 257 "<bridge> priority <value>", 258 "<bridge> ifpriority <interface> <value>", 259 NULL, 260 }; 261 extern const char *__progname; 262 int i; 263 264 for (i = 0; usage_strings[i] != NULL; i++) 265 fprintf(stderr, "%s %s %s\n", 266 i == 0 ? "usage:" : " ", 267 __progname, usage_strings[i]); 268 269 exit(1); 270 } 271 272 int 273 is_bridge(const char *bridge) 274 { 275 276 if (strncmp(bridge, "bridge", 6) != 0 || 277 isdigit(bridge[6]) == 0) 278 return (0); 279 280 return (1); 281 } 282 283 void 284 printb(const char *s, u_int v, const char *bits) 285 { 286 int i, any = 0; 287 char c; 288 289 if (bits && *bits == 8) 290 printf("%s=%o", s, v); 291 else 292 printf("%s=%x", s, v); 293 bits++; 294 if (bits) { 295 putchar('<'); 296 while ((i = *bits++) != 0) { 297 if (v & (1 << (i-1))) { 298 if (any) 299 putchar(','); 300 any = 1; 301 for (; (c = *bits) > 32; bits++) 302 putchar(c); 303 } else 304 for (; *bits > 32; bits++) 305 ; 306 } 307 putchar('>'); 308 } 309 } 310 311 void 312 printall(int sock) 313 { 314 struct ifaddrs *ifap, *ifa; 315 char *p; 316 317 if (getifaddrs(&ifap) != 0) 318 err(1, "getifaddrs"); 319 p = NULL; 320 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 321 if (is_bridge(ifa->ifa_name) == 0) 322 continue; 323 if (p != NULL && strcmp(p, ifa->ifa_name) == 0) 324 continue; 325 p = ifa->ifa_name; 326 status(sock, ifa->ifa_name); 327 } 328 329 freeifaddrs(ifap); 330 } 331 332 void 333 status(int sock, const char *bridge) 334 { 335 struct ifreq ifr; 336 struct ifbrparam bp1, bp2; 337 338 memset(&ifr, 0, sizeof(ifr)); 339 340 strlcpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name)); 341 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) 342 err(1, "unable to get flags"); 343 344 printf("%s: ", bridge); 345 printb("flags", ifr.ifr_flags, IFFBITS); 346 printf("\n"); 347 348 printf("\tConfiguration:\n"); 349 show_config(sock, bridge, "\t\t"); 350 351 printf("\tInterfaces:\n"); 352 show_interfaces(sock, bridge, "\t\t"); 353 354 if (do_cmd(sock, bridge, BRDGGCACHE, &bp1, sizeof(bp1), 0) < 0) 355 err(1, "unable to get address cache size"); 356 if (do_cmd(sock, bridge, BRDGGTO, &bp2, sizeof(bp2), 0) < 0) 357 err(1, "unable to get address timeout"); 358 359 printf("\tAddress cache (max cache: %u, timeout: %u):\n", 360 bp1.ifbrp_csize, bp2.ifbrp_ctime); 361 show_addresses(sock, bridge, "\t\t"); 362 } 363 364 void 365 show_config(int sock, const char *bridge, const char *prefix) 366 { 367 struct ifbrparam param; 368 u_int16_t pri; 369 u_int8_t ht, fd, ma; 370 371 if (do_cmd(sock, bridge, BRDGGPRI, ¶m, sizeof(param), 0) < 0) 372 err(1, "unable to get bridge priority"); 373 pri = param.ifbrp_prio; 374 375 if (do_cmd(sock, bridge, BRDGGHT, ¶m, sizeof(param), 0) < 0) 376 err(1, "unable to get hellotime"); 377 ht = param.ifbrp_hellotime; 378 379 if (do_cmd(sock, bridge, BRDGGFD, ¶m, sizeof(param), 0) < 0) 380 err(1, "unable to get forward delay"); 381 fd = param.ifbrp_fwddelay; 382 383 if (do_cmd(sock, bridge, BRDGGMA, ¶m, sizeof(param), 0) < 0) 384 err(1, "unable to get max age"); 385 ma = param.ifbrp_maxage; 386 387 printf("%spriority %u hellotime %u fwddelay %u maxage %u\n", 388 prefix, pri, ht, fd, ma); 389 } 390 391 void 392 show_interfaces(int sock, const char *bridge, const char *prefix) 393 { 394 static const char *stpstates[] = { 395 "disabled", 396 "listening", 397 "learning", 398 "forwarding", 399 "blocking", 400 }; 401 struct ifbifconf bifc; 402 struct ifbreq *req; 403 char *inbuf = NULL; 404 int i, len = 8192; 405 406 for (;;) { 407 bifc.ifbic_len = len; 408 bifc.ifbic_buf = inbuf = realloc(inbuf, len); 409 if (inbuf == NULL) 410 err(1, "unable to allocate interface buffer"); 411 if (do_cmd(sock, bridge, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0) 412 err(1, "unable to get interface list"); 413 if ((bifc.ifbic_len + sizeof(*req)) < len) 414 break; 415 len *= 2; 416 } 417 418 for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) { 419 req = bifc.ifbic_req + i; 420 printf("%s%s ", prefix, req->ifbr_ifsname); 421 printb("flags", req->ifbr_ifsflags, IFBIFBITS); 422 printf("\n"); 423 printf("%s\t", prefix); 424 printf("port %u priority %u", 425 req->ifbr_portno, req->ifbr_priority); 426 if (req->ifbr_ifsflags & IFBIF_STP) { 427 if (req->ifbr_state < 428 sizeof(stpstates) / sizeof(stpstates[0])) 429 printf(" %s", stpstates[req->ifbr_state]); 430 else 431 printf(" <unknown state %d>", 432 req->ifbr_state); 433 } 434 printf("\n"); 435 } 436 437 free(inbuf); 438 } 439 440 void 441 show_addresses(int sock, const char *bridge, const char *prefix) 442 { 443 struct ifbaconf ifbac; 444 struct ifbareq *ifba; 445 char *inbuf = NULL; 446 int i, len = 8192; 447 struct ether_addr ea; 448 449 for (;;) { 450 ifbac.ifbac_len = len; 451 ifbac.ifbac_buf = inbuf = realloc(inbuf, len); 452 if (inbuf == NULL) 453 err(1, "unable to allocate address buffer"); 454 if (do_cmd(sock, bridge, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) 455 err(1, "unable to get address cache"); 456 if ((ifbac.ifbac_len + sizeof(*ifba)) < len) 457 break; 458 len *= 2; 459 } 460 461 for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { 462 ifba = ifbac.ifbac_req + i; 463 memcpy(ea.ether_addr_octet, ifba->ifba_dst, 464 sizeof(ea.ether_addr_octet)); 465 printf("%s%s %s %lu ", prefix, ether_ntoa(&ea), 466 ifba->ifba_ifsname, ifba->ifba_expire); 467 printb("flags", ifba->ifba_flags, IFBAFBITS); 468 printf("\n"); 469 } 470 471 free(inbuf); 472 } 473 474 int 475 get_val(const char *cp, u_long *valp) 476 { 477 char *endptr; 478 u_long val; 479 480 errno = 0; 481 val = strtoul(cp, &endptr, 0); 482 if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE) 483 return (-1); 484 485 *valp = val; 486 return (0); 487 } 488 489 int 490 do_cmd(int sock, const char *bridge, u_long op, void *arg, size_t argsize, 491 int set) 492 { 493 struct ifdrv ifd; 494 495 memset(&ifd, 0, sizeof(ifd)); 496 497 strlcpy(ifd.ifd_name, bridge, sizeof(ifd.ifd_name)); 498 ifd.ifd_cmd = op; 499 ifd.ifd_len = argsize; 500 ifd.ifd_data = arg; 501 502 return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); 503 } 504 505 void 506 do_ifflag(int sock, const char *bridge, int flag, int set) 507 { 508 509 if (set) 510 g_ifr.ifr_flags |= flag; 511 else 512 g_ifr.ifr_flags &= ~flag; 513 514 g_ifr_updated = 1; 515 } 516 517 void 518 do_bridgeflag(int sock, const char *bridge, const char *ifs, int flag, 519 int set) 520 { 521 struct ifbreq req; 522 523 strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); 524 525 if (do_cmd(sock, bridge, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) 526 err(1, "unable to get bridge flags"); 527 528 if (set) 529 req.ifbr_ifsflags |= flag; 530 else 531 req.ifbr_ifsflags &= ~flag; 532 533 if (do_cmd(sock, bridge, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) 534 err(1, "unable to set bridge flags"); 535 } 536 537 void 538 cmd_add(const struct command *cmd, int sock, const char *bridge, 539 char **argv) 540 { 541 struct ifbreq req; 542 543 memset(&req, 0, sizeof(req)); 544 545 strlcpy(req.ifbr_ifsname, argv[0], sizeof(req.ifbr_ifsname)); 546 if (do_cmd(sock, bridge, BRDGADD, &req, sizeof(req), 1) < 0) 547 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 548 } 549 550 void 551 cmd_delete(const struct command *cmd, int sock, const char *bridge, 552 char **argv) 553 { 554 struct ifbreq req; 555 556 memset(&req, 0, sizeof(req)); 557 strlcpy(req.ifbr_ifsname, argv[0], sizeof(req.ifbr_ifsname)); 558 if (do_cmd(sock, bridge, BRDGDEL, &req, sizeof(req), 1) < 0) 559 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 560 } 561 562 void 563 cmd_up(const struct command *cmd, int sock, const char *bridge, 564 char **argv) 565 { 566 567 do_ifflag(sock, bridge, IFF_UP, 1); 568 } 569 570 void 571 cmd_down(const struct command *cmd, int sock, const char *bridge, 572 char **argv) 573 { 574 575 do_ifflag(sock, bridge, IFF_UP, 0); 576 } 577 578 void 579 cmd_discover(const struct command *cmd, int sock, const char *bridge, 580 char **argv) 581 { 582 583 do_bridgeflag(sock, bridge, argv[0], IFBIF_DISCOVER, 584 (cmd->cmd_flags & CMD_INVERT) ? 0 : 1); 585 } 586 587 void 588 cmd_learn(const struct command *cmd, int sock, const char *bridge, 589 char **argv) 590 { 591 592 do_bridgeflag(sock, bridge, argv[0], IFBIF_LEARNING, 593 (cmd->cmd_flags & CMD_INVERT) ? 0 : 1); 594 } 595 596 void 597 cmd_stp(const struct command *cmd, int sock, const char *bridge, 598 char **argv) 599 { 600 601 do_bridgeflag(sock, bridge, argv[0], IFBIF_STP, 602 (cmd->cmd_flags & CMD_INVERT) ? 0 : 1); 603 } 604 605 void 606 cmd_flush(const struct command *cmd, int sock, const char *bridge, 607 char **argv) 608 { 609 struct ifbreq req; 610 611 memset(&req, 0, sizeof(req)); 612 req.ifbr_ifsflags = IFBF_FLUSHDYN; 613 if (do_cmd(sock, bridge, BRDGFLUSH, &req, sizeof(req), 1) < 0) 614 err(1, "%s", cmd->cmd_keyword); 615 } 616 617 void 618 cmd_flushall(const struct command *cmd, int sock, const char *bridge, 619 char **argv) 620 { 621 struct ifbreq req; 622 623 memset(&req, 0, sizeof(req)); 624 req.ifbr_ifsflags = IFBF_FLUSHALL; 625 if (do_cmd(sock, bridge, BRDGFLUSH, &req, sizeof(req), 1) < 0) 626 err(1, "%s", cmd->cmd_keyword); 627 } 628 629 void 630 cmd_static(const struct command *cmd, int sock, const char *bridge, 631 char **argv) 632 { 633 struct ifbareq req; 634 struct ether_addr *ea; 635 636 memset(&req, 0, sizeof(req)); 637 strlcpy(req.ifba_ifsname, argv[0], sizeof(req.ifba_ifsname)); 638 639 ea = ether_aton(argv[1]); 640 if (ea == NULL) 641 errx(1, "%s: invalid address: %s", cmd->cmd_keyword, argv[1]); 642 643 memcpy(req.ifba_dst, ea->ether_addr_octet, sizeof(req.ifba_dst)); 644 req.ifba_flags = IFBAF_STATIC; 645 646 if (do_cmd(sock, bridge, BRDGSADDR, &req, sizeof(req), 1) < 0) 647 err(1, "%s %s %s", cmd->cmd_keyword, argv[0], argv[1]); 648 } 649 650 void 651 cmd_deladdr(const struct command *cmd, int sock, const char *bridge, 652 char **argv) 653 { 654 struct ifbareq req; 655 struct ether_addr *ea; 656 657 memset(&req, 0, sizeof(req)); 658 659 ea = ether_aton(argv[0]); 660 if (ea == NULL) 661 errx(1, "%s: invalid address: %s", cmd->cmd_keyword, argv[0]); 662 663 memcpy(req.ifba_dst, ea->ether_addr_octet, sizeof(req.ifba_dst)); 664 665 if (do_cmd(sock, bridge, BRDGDADDR, &req, sizeof(req), 1) < 0) 666 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 667 } 668 669 void 670 cmd_addr(const struct command *cmd, int sock, const char *bridge, 671 char **argv) 672 { 673 674 show_addresses(sock, bridge, "\t"); 675 } 676 677 void 678 cmd_maxaddr(const struct command *cmd, int sock, const char *bridge, 679 char **argv) 680 { 681 struct ifbrparam param; 682 u_long val; 683 684 if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0) 685 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]); 686 687 param.ifbrp_csize = val & 0xffffffff; 688 689 if (do_cmd(sock, bridge, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) 690 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 691 } 692 693 void 694 cmd_hellotime(const struct command *cmd, int sock, const char *bridge, 695 char **argv) 696 { 697 struct ifbrparam param; 698 u_long val; 699 700 if (get_val(argv[0], &val) < 0 || (val & ~0xff) != 0) 701 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]); 702 703 param.ifbrp_hellotime = val & 0xff; 704 705 if (do_cmd(sock, bridge, BRDGSHT, ¶m, sizeof(param), 1) < 0) 706 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 707 } 708 709 void 710 cmd_fwddelay(const struct command *cmd, int sock, const char *bridge, 711 char **argv) 712 { 713 struct ifbrparam param; 714 u_long val; 715 716 if (get_val(argv[0], &val) < 0 || (val & ~0xff) != 0) 717 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]); 718 719 param.ifbrp_fwddelay = val & 0xff; 720 721 if (do_cmd(sock, bridge, BRDGSFD, ¶m, sizeof(param), 1) < 0) 722 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 723 } 724 725 void 726 cmd_maxage(const struct command *cmd, int sock, const char *bridge, 727 char **argv) 728 { 729 struct ifbrparam param; 730 u_long val; 731 732 if (get_val(argv[0], &val) < 0 || (val & ~0xff) != 0) 733 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]); 734 735 param.ifbrp_maxage = val & 0xff; 736 737 if (do_cmd(sock, bridge, BRDGSMA, ¶m, sizeof(param), 1) < 0) 738 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 739 } 740 741 void 742 cmd_priority(const struct command *cmd, int sock, const char *bridge, 743 char **argv) 744 { 745 struct ifbrparam param; 746 u_long val; 747 748 if (get_val(argv[0], &val) < 0 || (val & ~0xffff) != 0) 749 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]); 750 751 param.ifbrp_prio = val & 0xffff; 752 753 if (do_cmd(sock, bridge, BRDGSPRI, ¶m, sizeof(param), 1) < 0) 754 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 755 } 756 757 void 758 cmd_ifpriority(const struct command *cmd, int sock, const char *bridge, 759 char **argv) 760 { 761 struct ifbreq req; 762 u_long val; 763 764 memset(&req, 0, sizeof(req)); 765 766 if (get_val(argv[1], &val) < 0 || (val & ~0xff) != 0) 767 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[1]); 768 769 strlcpy(req.ifbr_ifsname, argv[0], sizeof(req.ifbr_ifsname)); 770 req.ifbr_priority = val & 0xff; 771 772 if (do_cmd(sock, bridge, BRDGSPRI, &req, sizeof(req), 1) < 0) 773 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 774 } 775 776 void 777 cmd_timeout(const struct command *cmd, int sock, const char *bridge, 778 char **argv) 779 { 780 struct ifbrparam param; 781 u_long val; 782 783 if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0) 784 errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]); 785 786 param.ifbrp_ctime = val & 0xffffffff; 787 788 if (do_cmd(sock, bridge, BRDGSTO, ¶m, sizeof(param), 1) < 0) 789 err(1, "%s %s", cmd->cmd_keyword, argv[0]); 790 } 791