/* * 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; short sec; if (argc == 0) { printf("%% Invalid rule\n"); return (EX_USAGE); } rule.ifbr_tagname[0] = 0; rule.ifbr_flags = 0; rule.ifbr_action = 0; strlcpy(rule.ifbr_name, brdg, sizeof(rule.ifbr_name)); sec = 1; 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++; sec++; /* 2 */ if (argc == 0) { bridge_badrule(targc, targv, ln, sec); 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++; sec++; /* 3 */ if (argc == 0 || strcmp(argv[0], "on")) goto bad_rule; argc--; argv++; sec++; /* 4 */ if (argc == 0 || !is_valid_ifname(argv[0])) goto bad_rule; strlcpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname)); argc--; argv++; sec++; /* 5 */ 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 if (strcmp(argv[0], "tag") == 0) { if (argc < 2) { printf("%% missing tag name\n"); goto bad_rule; } if (rule.ifbr_tagname[0]) { printf("%% tag already defined\n"); goto bad_rule; } if (strlcpy(rule.ifbr_tagname, argv[1], PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) { printf("%% tag name too long\n"); goto bad_rule; } dea = NULL; } else goto bad_rule; argc--; argv++; sec++; if (argc == 0) goto bad_rule; if (dea != NULL) { ea = ether_aton(argv[0]); if (ea == NULL) { printf("%% Invalid address: %s\n", argv[0]); return (0); } bcopy(ea, dea, sizeof(*dea)); } argc--; argv++; sec++; } if (ioctl(s, SIOCBRDGARL, &rule) < 0) { printf("%% unable to add rule: SIOCBRDGARL: %s\n", strerror(errno)); return (EX_IOERR); } return (0); bad_rule: bridge_badrule(targc, targv, ln, sec); return (EX_USAGE); }
/* * 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 targc, char **targv, int ln) { char **argv = targv; int argc = targc; struct ifbrlreq rule; struct ether_addr *ea, *dea; if (argc == 0) { warnx("invalid rule"); return (1); } rule.ifbr_tagname[0] = 0; rule.ifbr_flags = 0; rule.ifbr_action = 0; strlcpy(rule.ifbr_name, name, 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 (1); } 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 if (strcmp(argv[0], "on") == 0) { rule.ifbr_flags |= BRL_FLAG_IN | BRL_FLAG_OUT; argc++; argv--; } 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 if (strcmp(argv[0], "tag") == 0) { if (argc < 2) { warnx("missing tag name"); goto bad_rule; } if (rule.ifbr_tagname[0]) { warnx("tag already defined"); goto bad_rule; } if (strlcpy(rule.ifbr_tagname, argv[1], PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) { warnx("tag name '%s' too long", argv[1]); goto bad_rule; } dea = NULL; } else goto bad_rule; argc--; argv++; if (argc == 0) goto bad_rule; if (dea != NULL) { ea = ether_aton(argv[0]); if (ea == NULL) { warnx("invalid address: %s", argv[0]); return (1); } bcopy(ea, dea, sizeof(*dea)); } argc--; argv++; } if (ioctl(s, SIOCBRDGARL, &rule) < 0) { warn("%s", name); return (1); } return (0); bad_rule: bridge_badrule(targc, targv, ln); return (1); }