/* $NetBSD: brconfig.c,v 1.17.26.1 2024/09/05 09:27:12 martin Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * brconfig(8) -- * * Configuration utility for the bridge(4) driver. */ #include #ifndef lint __RCSID("$NetBSD: brconfig.c,v 1.17.26.1 2024/09/05 09:27:12 martin Exp $"); #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct command { const char *cmd_keyword; int cmd_argcnt; int cmd_flags; void (*cmd_func)(const struct command *, int, const char *, char **); }; #define CMD_INVERT 0x01 /* "invert" the sense of the command */ static void cmd_add(const struct command *, int, const char *, char **); static void cmd_delete(const struct command *, int, const char *, char **); static void cmd_up(const struct command *, int, const char *, char **); static void cmd_down(const struct command *, int, const char *, char **); static void cmd_discover(const struct command *, int, const char *, char **); static void cmd_learn(const struct command *, int, const char *, char **); static void cmd_flush(const struct command *, int, const char *, char **); static void cmd_flushall(const struct command *, int, const char *, char **); static void cmd_static(const struct command *, int, const char *, char **); static void cmd_deladdr(const struct command *, int, const char *, char **); static void cmd_addr(const struct command *, int, const char *, char **); static void cmd_maxaddr(const struct command *, int, const char *, char **); static void cmd_hellotime(const struct command *, int, const char *, char **); static void cmd_fwddelay(const struct command *, int, const char *, char **); static void cmd_maxage(const struct command *, int, const char *, char **); static void cmd_priority(const struct command *, int, const char *, char **); static void cmd_ifpriority(const struct command *, int, const char *, char **); static void cmd_ifpathcost(const struct command *, int, const char *, char **); static void cmd_timeout(const struct command *, int, const char *, char **); static void cmd_stp(const struct command *, int, const char *, char **); static void cmd_ipf(const struct command *, int, const char *, char **); static void cmd_protect(const struct command *, int, const char *, char **); static const struct command command_table[] = { { "add", 1, 0, cmd_add }, { "delete", 1, 0, cmd_delete }, { "up", 0, 0, cmd_up }, { "down", 0, 0, cmd_down }, { "discover", 1, 0, cmd_discover }, { "-discover", 1, CMD_INVERT, cmd_discover }, { "learn", 1, 0, cmd_learn }, { "-learn", 1, CMD_INVERT, cmd_learn }, { "flush", 0, 0, cmd_flush }, { "flushall", 0, 0, cmd_flushall }, { "static", 2, 0, cmd_static }, { "deladdr", 1, 0, cmd_deladdr }, { "addr", 0, 0, cmd_addr }, { "maxaddr", 1, 0, cmd_maxaddr }, { "hellotime", 1, 0, cmd_hellotime }, { "fwddelay", 1, 0, cmd_fwddelay }, { "maxage", 1, 0, cmd_maxage }, { "priority", 1, 0, cmd_priority }, { "ifpriority", 2, 0, cmd_ifpriority }, { "ifpathcost", 2, 0, cmd_ifpathcost }, { "timeout", 1, 0, cmd_timeout }, { "stp", 1, 0, cmd_stp }, { "-stp", 1, CMD_INVERT, cmd_stp }, { "ipf", 0, 0, cmd_ipf }, { "-ipf", 0, CMD_INVERT, cmd_ipf }, { "protect", 1, 0, cmd_protect }, { "-protect", 1, CMD_INVERT, cmd_protect }, { NULL, 0, 0, NULL }, }; static void printall(int); static void status(int, const char *); static int is_bridge(const char *); static void show_config(int, const char *, const char *); static void show_interfaces(int, const char *, const char *); static void show_addresses(int, const char *, const char *); static int get_val(const char *, u_long *); #define do_cmd(a,b,c,d,e,f) do_cmd2((a),(b),(c),(d),(e),NULL,(f)) static int do_cmd2(int, const char *, u_long, void *, size_t, size_t *, int); static void do_ifflag(int, const char *, int, int); static void do_bridgeflag(int, const char *, const char *, int, int); static void printb(const char *, u_int, const char *); __dead static void usage(void); static int aflag; static struct ifreq g_ifr; static int g_ifr_updated; int main(int argc, char *argv[]) { const struct command *cmd; char *bridge; int sock, ch; if (argc < 2) usage(); sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) err(1, "socket"); while ((ch = getopt(argc, argv, "a")) != -1) { switch (ch) { case 'a': aflag = 1; break; default: usage(); } } argc -= optind; argv += optind; if (aflag) { if (argc != 0) usage(); printall(sock); exit(0); } if (argc == 0) usage(); bridge = argv[0]; if (is_bridge(bridge) == 0) errx(1, "%s is not a bridge", bridge); /* Get a copy of the interface flags. */ strlcpy(g_ifr.ifr_name, bridge, sizeof(g_ifr.ifr_name)); if (ioctl(sock, SIOCGIFFLAGS, &g_ifr) < 0) err(1, "unable to get interface flags"); argc--; argv++; if (argc == 0) { status(sock, bridge); exit(0); } while (argc != 0) { for (cmd = command_table; cmd->cmd_keyword != NULL; cmd++) { if (strcmp(cmd->cmd_keyword, argv[0]) == 0) break; } if (cmd->cmd_keyword == NULL) errx(1, "unknown command: %s", argv[0]); argc--; argv++; if (argc < cmd->cmd_argcnt) errx(1, "command %s requires %d argument%s", cmd->cmd_keyword, cmd->cmd_argcnt, cmd->cmd_argcnt == 1 ? "" : "s"); (*cmd->cmd_func)(cmd, sock, bridge, argv); argc -= cmd->cmd_argcnt; argv += cmd->cmd_argcnt; } /* If the flags changed, update them. */ if (g_ifr_updated && ioctl(sock, SIOCSIFFLAGS, &g_ifr) < 0) err(1, "unable to set interface flags"); exit (0); } static void usage(void) { static const char *usage_strings[] = { "-a", "", " up|down", " addr", " add ", " delete ", " maxaddr ", " timeout