summaryrefslogtreecommitdiff
path: root/sbin/brconfig/brconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/brconfig/brconfig.c')
-rw-r--r--sbin/brconfig/brconfig.c284
1 files changed, 281 insertions, 3 deletions
diff --git a/sbin/brconfig/brconfig.c b/sbin/brconfig/brconfig.c
index ff65659d922..82a14d9b6a9 100644
--- a/sbin/brconfig/brconfig.c
+++ b/sbin/brconfig/brconfig.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: brconfig.c,v 1.4 2000/01/10 22:14:25 angelos Exp $ */
+/* $OpenBSD: brconfig.c,v 1.5 2000/01/25 22:06:27 jason Exp $ */
/*
- * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
+ * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,12 @@ int bridge_status __P((int, char *));
int is_bridge __P((int, char *));
int bridge_show_all __P((int));
void printb __P((char *, unsigned short, char *));
+int bridge_rule __P((int, char *, int, char **, int));
+int bridge_rules __P((int, char *, char *));
+int bridge_flushrule __P((int, char *, char *));
+void bridge_badrule __P((int, char **, int));
+void bridge_showrule __P((struct ifbrlreq *));
+int bridge_rulefile __P((int, char *, char *));
/* if_flags bits: borrowed from ifconfig.c */
#define IFFBITS \
@@ -294,6 +300,40 @@ main(argc, argv)
if (error)
return (error);
}
+ else if (strcmp("rules", argv[0]) == 0) {
+ argc--; argv++;
+ if (argc == 0) {
+ warnx("rules requires an argument");
+ return (EX_USAGE);
+ }
+ error = bridge_rules(sock, brdg, argv[0]);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("rule", argv[0]) == 0) {
+ argc--; argv++;
+ return (bridge_rule(sock, brdg, argc, argv, -1));
+ }
+ else if (strcmp("rulefile", argv[0]) == 0) {
+ argc--; argv++;
+ if (argc == 0) {
+ warnx("rulefile requires an argument");
+ return (EX_USAGE);
+ }
+ error = bridge_rulefile(sock, brdg, argv[0]);
+ if (error)
+ return (error);
+ }
+ else if (strcmp("flushrule", argv[0]) == 0) {
+ argc--; argv++;
+ if (argc == 0) {
+ warnx("flushrule requires an argument");
+ return (EX_USAGE);
+ }
+ error = bridge_flushrule(sock, brdg, argv[0]);
+ if (error)
+ return (error);
+ }
else if (strcmp("timeout", argv[0]) == 0) {
argc--; argv++;
if (argc == 0) {
@@ -766,8 +806,246 @@ bridge_status(s, brdg)
return (err);
}
+int
+bridge_flushrule(s, brdg, ifname)
+ int s;
+ char *brdg, *ifname;
+{
+ struct ifbrlreq req;
+
+ strlcpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
+ strlcpy(req.ifbr_ifsname, ifname, sizeof(req.ifbr_ifsname));
+ if (ioctl(s, SIOCBRDGFRL, &req) < 0) {
+ warn("%s: %s", brdg, ifname);
+ return (EX_USAGE);
+ }
+ return (0);
+}
+
+int
+bridge_rules(s, brdg, ifname)
+ int s;
+ char *brdg, *ifname;
+{
+ char *inbuf = NULL;
+ struct ifbrlconf ifc;
+ struct ifbrlreq *ifrp, ifreq;
+ int len = 8192, i;
+
+ while (1) {
+ ifc.ifbrl_len = len;
+ ifc.ifbrl_buf = inbuf = realloc(inbuf, len);
+ strlcpy(ifc.ifbrl_name, brdg, sizeof(ifc.ifbrl_name));
+ strlcpy(ifc.ifbrl_ifsname, ifname, sizeof(ifc.ifbrl_ifsname));
+ if (inbuf == NULL)
+ err(1, "malloc");
+ if (ioctl(s, SIOCBRDGGRL, &ifc) < 0)
+ err(1, "ioctl(SIOCBRDGGRL)");
+ if (ifc.ifbrl_len + sizeof(ifreq) < len)
+ break;
+ len *= 2;
+ }
+ ifrp = ifc.ifbrl_req;
+ for (i = 0; i < ifc.ifbrl_len; i += sizeof(ifreq)) {
+ ifrp = (struct ifbrlreq *)((caddr_t)ifc.ifbrl_req + i);
+ bridge_showrule(ifrp);
+ }
+ return (0);
+}
+
+void
+bridge_showrule(r)
+ struct ifbrlreq *r;
+{
+ printf("%s: ", r->ifbr_name);
+
+ if (r->ifbr_action == BRL_ACTION_BLOCK)
+ printf("block ");
+ else if (r->ifbr_action == BRL_ACTION_PASS)
+ printf("pass ");
+ else
+ printf("[neither block nor pass?]\n");
+
+ if ((r->ifbr_flags & (BRL_FLAG_IN | BRL_FLAG_OUT)) ==
+ (BRL_FLAG_IN | BRL_FLAG_OUT))
+ printf("in/out ");
+ else if (r->ifbr_flags & BRL_FLAG_IN)
+ printf("in ");
+ else if (r->ifbr_flags & BRL_FLAG_OUT)
+ printf("out ");
+ else
+ printf("[neither in nor out?]\n");
+
+ printf("on %s", r->ifbr_ifsname);
+
+ if (r->ifbr_flags & BRL_FLAG_SRCVALID)
+ printf(" src %s", ether_ntoa(&r->ifbr_src));
+ if (r->ifbr_flags & BRL_FLAG_DSTVALID)
+ printf(" dst %s", ether_ntoa(&r->ifbr_dst));
+
+ printf("\n");
+}
+
+/*
+ * Parse a rule definition and send it upwards.
+ *
+ * Syntax:
+ * {block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}]
+ */
+int
+bridge_rule(int s, char *brdg, int targc, char **targv, int ln)
+{
+ char **argv = targv;
+ int argc = targc;
+ struct ifbrlreq rule;
+ struct ether_addr *ea, *dea;
+
+ if (argc == 0) {
+ fprintf(stderr, "invalid rule\n");
+ return (EX_USAGE);
+ }
+ rule.ifbr_flags = 0;
+ rule.ifbr_action = 0;
+ strlcpy(rule.ifbr_name, brdg, sizeof(rule.ifbr_name));
+
+ if (strcmp(argv[0], "block") == 0)
+ rule.ifbr_action = BRL_ACTION_BLOCK;
+ else if (strcmp(argv[0], "pass") == 0)
+ rule.ifbr_action = BRL_ACTION_PASS;
+ else
+ goto bad_rule;
+ argc--; argv++;
+
+ if (argc == 0) {
+ bridge_badrule(targc, targv, ln);
+ return (EX_USAGE);
+ }
+ if (strcmp(argv[0], "in") == 0)
+ rule.ifbr_flags |= BRL_FLAG_IN;
+ else if (strcmp(argv[0], "out") == 0)
+ rule.ifbr_flags |= BRL_FLAG_OUT;
+ else if (strcmp(argv[0], "in/out") == 0)
+ rule.ifbr_flags |= BRL_FLAG_IN | BRL_FLAG_OUT;
+ else
+ goto bad_rule;
+ argc--; argv++;
+
+ if (argc == 0 || strcmp(argv[0], "on"))
+ goto bad_rule;
+ argc--; argv++;
+
+ if (argc == 0)
+ goto bad_rule;
+ strlcpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname));
+ argc--; argv++;
+
+ while (argc) {
+ if (strcmp(argv[0], "dst") == 0) {
+ if (rule.ifbr_flags & BRL_FLAG_DSTVALID)
+ goto bad_rule;
+ rule.ifbr_flags |= BRL_FLAG_DSTVALID;
+ dea = &rule.ifbr_dst;
+ }
+ else if (strcmp(argv[0], "src") == 0) {
+ if (rule.ifbr_flags & BRL_FLAG_SRCVALID)
+ goto bad_rule;
+ rule.ifbr_flags |= BRL_FLAG_SRCVALID;
+ dea = &rule.ifbr_src;
+ }
+ else
+ goto bad_rule;
+
+ argc--; argv++;
+
+ if (argc == 0)
+ goto bad_rule;
+ ea = ether_aton(argv[0]);
+ if (ea == NULL) {
+ warnx("Invalid address: %s", argv[0]);
+ return (EX_USAGE);
+ }
+ bcopy(ea, dea, sizeof(*dea));
+ argc--; argv++;
+ }
+
+ if (ioctl(s, SIOCBRDGARL, &rule) < 0) {
+ warn("%s", brdg);
+ return (EX_IOERR);
+ }
+ return (0);
+
+bad_rule:
+ bridge_badrule(targc, targv, ln);
+ return (EX_USAGE);
+}
+
+#define MAXRULEWORDS 8
+
+int
+bridge_rulefile(s, brdg, fname)
+ int s;
+ char *brdg, *fname;
+{
+ FILE *f;
+ char *str, *argv[MAXRULEWORDS], buf[1024], xbuf[1024];
+ int ln = 1, argc = 0, err = 0, xerr;
+
+ f = fopen(fname, "r");
+ if (f == NULL) {
+ warn("%s", fname);
+ return (EX_IOERR);
+ }
+
+ while (1) {
+ fgets(buf, sizeof(buf), f);
+ if (feof(f))
+ break;
+ ln++;
+ if (buf[0] == '#')
+ continue;
+
+ argc = 0;
+ str = strtok(buf, "\n\t\r ");
+ strlcpy(xbuf, buf, sizeof(xbuf));
+ while (str != NULL) {
+ argv[argc++] = str;
+ if (argc > MAXRULEWORDS) {
+ fprintf(stderr, "invalid rule: %d: %s\n",
+ ln, xbuf);
+ break;
+ }
+ str = strtok(NULL, "\n\t\r ");
+ }
+
+ if (argc > MAXRULEWORDS)
+ continue;
+
+ xerr = bridge_rule(s, brdg, argc, argv, ln);
+ if (xerr)
+ err = xerr;
+ }
+ fclose(f);
+ return (err);
+}
+
+void
+bridge_badrule(argc, argv, ln)
+ int argc, ln;
+ char **argv;
+{
+ int i;
+
+ fprintf(stderr, "invalid rule: ");
+ if (ln != -1)
+ fprintf(stderr, "%d: ", ln);
+ for (i = 0; i < argc; i++) {
+ fprintf(stderr, "%s ", argv[i]);
+ }
+ fprintf(stderr, "\n");
+}
+
/*
- * Print a value a la the %b format of the kernel's printf
+ * Print a value ala the %b format of the kernel's printf
* (borrowed from ifconfig.c)
*/
void