summaryrefslogtreecommitdiff
path: root/usr.sbin/brconfig
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>1999-02-26 17:52:13 +0000
committerJason Wright <jason@cvs.openbsd.org>1999-02-26 17:52:13 +0000
commit69d576fc982d36bc64dc3f5db977001920165dc6 (patch)
treed017dec25d103ce3d856522e6a8a31e271473d28 /usr.sbin/brconfig
parent2acc654aba54712531d8185598afc25f1d2877f0 (diff)
bridge config utility
Diffstat (limited to 'usr.sbin/brconfig')
-rw-r--r--usr.sbin/brconfig/Makefile7
-rw-r--r--usr.sbin/brconfig/brconfig.8134
-rw-r--r--usr.sbin/brconfig/brconfig.c419
3 files changed, 560 insertions, 0 deletions
diff --git a/usr.sbin/brconfig/Makefile b/usr.sbin/brconfig/Makefile
new file mode 100644
index 00000000000..a6e5fa9e99e
--- /dev/null
+++ b/usr.sbin/brconfig/Makefile
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile,v 1.1 1999/02/26 17:52:12 jason Exp $
+
+PROG= brconfig
+MAN= brconfig.8
+COPTS+= -Wall
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/brconfig/brconfig.8 b/usr.sbin/brconfig/brconfig.8
new file mode 100644
index 00000000000..50c26bce0a0
--- /dev/null
+++ b/usr.sbin/brconfig/brconfig.8
@@ -0,0 +1,134 @@
+.\" $OpenBSD: brconfig.8,v 1.1 1999/02/26 17:52:12 jason Exp $
+.\"
+.\" Copyright (c) 1999 Jason L. Wright (jason@thought.net)
+.\" All rights reserved.
+.\"
+.\" 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 by Jason L. Wright
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+.\"
+.Dd Jan 13, 1999
+.Dt BRIDGECTL 8
+.Os
+.Sh NAME
+.Nm brconfig
+.Nd manipulate Ethernet bridges
+.Sh SYNOPSIS
+.Nm brconfig
+.Ar bridge-name
+.Op Ar up
+.Op Ar down
+.Op Ar list
+.Op Ar routes
+.Op Ar status
+.Op Ar add interface-name
+.Op Ar delete interface-name
+.Op Ar link0
+.Op Ar link1
+.Op Ar -link0
+.Op Ar -link1
+.Op Ar ...
+.Sh DESCRIPTION
+The
+.Nm brconfig
+utility retrieves kernel state of Ethernet bridges and allows
+user control of these bridges. Its command line consists
+of the name of a bridge and a set of operations to be
+performed on that bridge. The commands are executed in
+the order they were specified.
+.Pp
+The available commands are:
+.Bl -tag -width Ds
+.It Ar up
+Start the bridge forwarding packets.
+.It Ar down
+Stop the bridge from forwarding packets.
+.It Ar list
+Retrieve a list of interface members of the bridge.
+.It Ar routes
+Display the routes that have been learned by the bridge.
+.It Ar status
+Print the status of the bridge, including member interfaces and
+routes learned by the bridge.
+.It Ar add interface-name
+Add the interface named by
+.Ar interface-name
+as a member of the bridge.
+The interface must already be ready for packet
+reception, (ie. it must be in the
+.Cm up
+state, see
+.Xr ifconfig 8 )
+The interface is put into promiscuous mode so
+that it can receive every packet sent on the
+network.
+.It Ar delete interface-name
+Remove the interface named by
+.Ar interface-name
+from the bridge.
+Promiscuous mode is turned off for the interface when it is
+removed from the bridge.
+.It Ar link0
+Setting this flag stops all non-IP multicast packets from
+being forwarded by the bridge.
+.It Ar -link0
+Clear the
+.Ar link0
+flag on the bridge interface.
+.It Ar link1
+Setting this flags stops all IP multicast packets from
+being forwarded by the bridge.
+.It Ar -link0
+Clear the
+.Ar link1
+flag on the bridge interface.
+.El
+.Sh EXAMPLES
+.Bl -tag -width brconfig
+.It Cm brconfig bridge0 add pn0 add mx0 up
+Add the Ethernet interfaces pn0 and mx0 to the bridge bridge0, and
+start the bridge forwarding packets.
+.It Cm brconfig bridge0 list
+Retrieve a list of interfaces that are members of bridge0.
+.It Cm brconfig bridge0 down
+Stop bridge0 from forwarding packets.
+.It Cm brconfig bridge0 delete pn0
+Remove the interface pn0 from the bridge bridge0.
+.El
+.Sh SEE ALSO
+.Xr ifconfig 8 ,
+.Xr bridge 4
+.Sh AUTHOR
+The
+.Xr brconfig 8
+command and the
+.Xr bridge 4
+kernel interface were written by Jason L. Wright <jason@thought.net> as
+part of an undergraduate indenpendent study
+at the University of North Carolina at Greensboro.
+.Sh HISTORY
+.Nm brconfig
+first appeared in
+.Ox 2.5 .
diff --git a/usr.sbin/brconfig/brconfig.c b/usr.sbin/brconfig/brconfig.c
new file mode 100644
index 00000000000..947eb4eef1f
--- /dev/null
+++ b/usr.sbin/brconfig/brconfig.c
@@ -0,0 +1,419 @@
+/* $OpenBSD: brconfig.c,v 1.1 1999/02/26 17:52:12 jason Exp $ */
+
+/*
+ * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
+ * All rights reserved.
+ *
+ * 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 by Jason L. Wright
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <net/if_bridge.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <err.h>
+#include <sysexits.h>
+
+void usage(void);
+int main(int, char **);
+int bridge_setflag(int, char *, short);
+int bridge_clrflag(int, char *, short);
+int bridge_list(int, char *, char *);
+int bridge_routes(int, char *, char *);
+int bridge_add(int, char *, char *);
+int bridge_delete(int, char *, char *);
+int bridge_status(int, char *);
+int is_bridge(int, char *);
+void printb(char *, unsigned short, char *);
+
+/* if_flags bits: borrowed from ifconfig.c */
+#define IFFBITS \
+"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
+\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
+
+void
+usage() {
+ fprintf(stderr,
+ "brconfig bridge_name [up] [down] [add interface_name]\n");
+ fprintf(stderr, "\t[delete interface_name] ...\n");
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int error = 0, sock;
+ char *brdg;
+
+ if (argc < 2) {
+ usage();
+ return (EX_USAGE);
+ }
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+ err(1, "socket");
+
+ argc--; argv++;
+ brdg = argv[0];
+
+ if (!is_bridge(sock, brdg))
+ return (EX_USAGE);
+
+ if (argc == 1) {
+ error = bridge_status(sock, brdg);
+ return (error);
+ }
+
+ for (argc--, argv++; argc != 0; argc--, argv++) {
+ if (strcmp("add", argv[0]) == 0) {
+ argc--; argv++;
+ if (argc == 0) {
+ warnx("add requires an argument");
+ return (EX_USAGE);
+ }
+ error = bridge_add(sock, brdg, argv[0]);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("delete", argv[0]) == 0) {
+ argc--; argv++;
+ if (argc == 0) {
+ warnx("delete requires an argument");
+ return (EX_USAGE);
+ }
+ error = bridge_delete(sock, brdg, argv[0]);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("list", argv[0]) == 0) {
+ error = bridge_list(sock, brdg, "");
+ if (error)
+ return (error);
+ }
+ else if (strcmp("up", argv[0]) == 0) {
+ error = bridge_setflag(sock, brdg, IFF_UP);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("down", argv[0]) == 0) {
+ error = bridge_clrflag(sock, brdg, IFF_UP);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("link0", argv[0]) == 0) {
+ error = bridge_setflag(sock, brdg, IFF_LINK0);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("-link0", argv[0]) == 0) {
+ error = bridge_clrflag(sock, brdg, IFF_LINK0);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("link1", argv[0]) == 0) {
+ error = bridge_setflag(sock, brdg, IFF_LINK1);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("-link1", argv[0]) == 0) {
+ error = bridge_clrflag(sock, brdg, IFF_LINK1);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("routes", argv[0]) == 0) {
+ error = bridge_routes(sock, brdg, "");
+ if (error)
+ return (error);
+ }
+ else if (strcmp("status", argv[0]) == 0) {
+ error = bridge_status(sock, brdg);
+ if (error)
+ return (error);
+ }
+ else {
+ warnx("unrecognized option: %s", argv[0]);
+ return (EX_USAGE);
+ }
+ }
+
+ return (0);
+}
+
+int
+bridge_setflag(s, brdg, f)
+ int s;
+ char *brdg;
+ short f;
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, brdg, sizeof ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+ warn("ioctl(SIOCGIFFLAGS)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+
+ ifr.ifr_flags |= f;
+
+ if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
+ warn("ioctl(SIOCSIFFLAGS)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+
+ return (0);
+}
+
+int
+bridge_clrflag(s, brdg, f)
+ int s;
+ char *brdg;
+ short f;
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, brdg, sizeof ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+ warn("ioctl(SIOCGIFFLAGS)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+
+ ifr.ifr_flags &= ~(f);
+
+ if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
+ warn("ioctl(SIOCSIFFLAGS)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+
+ return (0);
+}
+
+int
+bridge_list(sock, brdg, delim)
+ int sock;
+ char *brdg, *delim;
+{
+ struct ifbreq req;
+ u_int32_t i = 0;
+ char buf[sizeof(req.ifsname) + 1];
+
+ while (1) {
+ strncpy(req.ifbname, brdg, sizeof(req.ifbname));
+ req.index = i;
+ if (ioctl(sock, SIOCBRDGIDX, &req) < 0) {
+ if (errno == ENOENT) /* end of list */
+ return (0);
+ warn("ioctl(SIOCBRDGIDX)");
+ return (EX_IOERR);
+ }
+
+ bzero(buf, sizeof(buf));
+ strncpy(buf, req.ifsname, sizeof(req.ifsname));
+ printf("%s%s\n", delim, buf);
+ i++;
+ }
+
+ return (0); /* NOTREACHED */
+}
+
+int
+bridge_add(s, brdg, ifn)
+ int s;
+ char *brdg, *ifn;
+{
+ struct ifbreq req;
+
+ strncpy(req.ifbname, brdg, sizeof(req.ifbname));
+ strncpy(req.ifsname, ifn, sizeof(req.ifsname));
+ if (ioctl(s, SIOCBRDGADD, &req) < 0) {
+ warn("ioctl(SIOCADDBRDG)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+ return (0);
+}
+
+int
+bridge_delete(s, brdg, ifn)
+ int s;
+ char *brdg, *ifn;
+{
+ struct ifbreq req;
+
+ strncpy(req.ifbname, brdg, sizeof(req.ifbname));
+ strncpy(req.ifsname, ifn, sizeof(req.ifsname));
+ if (ioctl(s, SIOCBRDGDEL, &req) < 0) {
+ warn("ioctl(SIOCDELBRDG)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+ return (0);
+}
+
+int
+bridge_routes(s, brdg, delim)
+ int s;
+ char *brdg, *delim;
+{
+ struct ifbrtreq req;
+ u_int32_t i = 0;
+ int r = 0;
+
+ while (r == 0) {
+ strncpy(req.ifbname, brdg, sizeof(req.ifbname));
+ req.index = i;
+
+ r = ioctl(s, SIOCBRDGRT, &req);
+ if (r != 0) {
+ if (errno == ENOENT || errno == ENETDOWN)
+ return (0);
+ warn("ioctl(SIOCBRDGRT)");
+ return (EX_IOERR);
+ }
+ printf("%s%s %u %s\n", delim, ether_ntoa(&req.dst),
+ req.age, req.ifsname);
+ i++;
+ }
+
+ return (0);
+}
+
+/*
+ * Check to make sure 'brdg' is really a bridge interface.
+ */
+int
+is_bridge(s, brdg)
+ int s;
+ char *brdg;
+{
+ struct ifreq ifr;
+ struct ifbrtreq req;
+
+ strncpy(ifr.ifr_name, brdg, sizeof ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+ warn("ioctl(SIOCGIFFLAGS)");
+ return (0);
+ }
+
+ strncpy(req.ifbname, brdg, sizeof(req.ifbname));
+ req.index = 0;
+ if (ioctl(s, SIOCBRDGRT, (caddr_t)&req) < 0) {
+ if (errno == ENOENT || errno == ENETDOWN)
+ return (1);
+ warn("ioctl(SIOCBRDGRT)");
+ return (0);
+ }
+ return (1);
+}
+
+int
+bridge_status(s, brdg)
+ int s;
+ char *brdg;
+{
+ struct ifreq ifr;
+ int err;
+
+ strncpy(ifr.ifr_name, brdg, sizeof ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+ warn("ioctl(SIOCGIFFLAGS)");
+ if (errno == EPERM)
+ return (EX_NOPERM);
+ return (EX_IOERR);
+ }
+
+ printf("%s: ", brdg);
+ printb("flags", ifr.ifr_flags, IFFBITS);
+ printf("\n");
+
+ printf("\tInterfaces:\n");
+ err = bridge_list(s, brdg, "\t\t");
+ if (err)
+ return (err);
+
+ printf("\tRoutes:\n");
+ err = bridge_routes(s, brdg, "\t\t");
+ return (err);
+}
+
+/*
+ * Print a value a la the %b format of the kernel's printf
+ * (borrowed from ifconfig.c)
+ */
+void
+printb(s, v, bits)
+ char *s;
+ char *bits;
+ unsigned short v;
+{
+ register int i, any = 0;
+ register char c;
+
+ if (bits && *bits == 8)
+ printf("%s=%o", s, v);
+ else
+ printf("%s=%x", s, v);
+ bits++;
+ if (bits) {
+ putchar('<');
+ while ((i = *bits++)) {
+ if (v & (1 << (i-1))) {
+ if (any)
+ putchar(',');
+ any = 1;
+ for (; (c = *bits) > 32; bits++)
+ putchar(c);
+ } else
+ for (; *bits > 32; bits++)
+ ;
+ }
+ putchar('>');
+ }
+}