diff options
| -rw-r--r-- | conf.c | 42 | ||||
| -rw-r--r-- | fwd.c | 61 | ||||
| -rw-r--r-- | fwd.h | 4 |
3 files changed, 49 insertions, 58 deletions
@@ -151,9 +151,26 @@ static void conf_ports_range_except(const struct ctx *c, char optname, const uint8_t *exclude, uint16_t to, uint8_t flags) { + struct fwd_rule rule = { + .addr = addr ? *addr : inany_any6, + .ifname = { 0 }, + .proto = proto, + .flags = flags, + }; unsigned delta = to - first; unsigned base, i; + if (!addr) + rule.flags |= FWD_DUAL_STACK_ANY; + if (ifname) { + int ret; + + ret = snprintf(rule.ifname, sizeof(rule.ifname), + "%s", ifname); + if (ret <= 0 || (size_t)ret >= sizeof(rule.ifname)) + die("Invalid interface name: %s", ifname); + } + assert(first != 0); for (base = first; base <= last; base++) { @@ -165,28 +182,37 @@ static void conf_ports_range_except(const struct ctx *c, char optname, break; } + rule.first = base; + rule.last = i - 1; + rule.to = base + delta; + if ((optname == 'T' || optname == 'U') && c->no_bindtodevice) { /* FIXME: Once the fwd bitmaps are removed, move this * workaround to the caller */ + struct fwd_rule rulev = { + .ifname = { 0 }, + .flags = flags, + .first = base, + .last = i - 1, + .to = base + delta, + }; + assert(!addr && ifname && !strcmp(ifname, "lo")); warn( "SO_BINDTODEVICE unavailable, forwarding only 127.0.0.1 and ::1 for '-%c %s'", optname, optarg); if (c->ifi4) { - fwd_rule_add(fwd, proto, flags, - &inany_loopback4, NULL, - base, i - 1, base + delta); + rulev.addr = inany_loopback4; + fwd_rule_add(fwd, &rulev); } if (c->ifi6) { - fwd_rule_add(fwd, proto, flags, - &inany_loopback6, NULL, - base, i - 1, base + delta); + rulev.addr = inany_loopback6; + fwd_rule_add(fwd, &rulev); } } else { - fwd_rule_add(fwd, proto, flags, addr, ifname, - base, i - 1, base + delta); + fwd_rule_add(fwd, &rule); } base = i - 1; } @@ -332,30 +332,22 @@ void fwd_rule_init(struct ctx *c) } /** - * fwd_rule_add() - Add a rule to a forwarding table + * fwd_rule_add() - Validate and add a rule to a forwarding table * @fwd: Table to add to - * @proto: Protocol to forward - * @flags: Flags for this entry - * @addr: Our address to forward (NULL for both 0.0.0.0 and ::) - * @ifname: Only forward from this interface name, if non-empty - * @first: First port number to forward - * @last: Last port number to forward - * @to: First port of target port range to map to + * @new: Rule to add */ -void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags, - const union inany_addr *addr, const char *ifname, - in_port_t first, in_port_t last, in_port_t to) +void fwd_rule_add(struct fwd_table *fwd, const struct fwd_rule *new) { /* Flags which can be set from the caller */ const uint8_t allowed_flags = FWD_WEAK | FWD_SCAN | FWD_DUAL_STACK_ANY; - unsigned num = (unsigned)last - first + 1; - struct fwd_rule *new; + unsigned num = (unsigned)new->last - new->first + 1; unsigned i, port; - assert(!(flags & ~allowed_flags)); + assert(!(new->flags & ~allowed_flags)); /* Passing a non-wildcard address with DUAL_STACK_ANY is a bug */ - assert(!(flags & FWD_DUAL_STACK_ANY) || !addr || - inany_equals(addr, &inany_any6)); + assert(!(new->flags & FWD_DUAL_STACK_ANY) || + inany_equals(&new->addr, &inany_any6)); + assert(new->first <= new->last); if (fwd->count >= ARRAY_SIZE(fwd->rules)) die("Too many port forwarding ranges"); @@ -367,55 +359,30 @@ void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags, char newstr[INANY_ADDRSTRLEN], rulestr[INANY_ADDRSTRLEN]; const struct fwd_rule *rule = &fwd->rules[i]; - if (proto != rule->proto) + if (new->proto != rule->proto) /* Non-conflicting protocols */ continue; - if (!inany_matches(addr, fwd_rule_addr(rule))) + if (!inany_matches(fwd_rule_addr(new), fwd_rule_addr(rule))) /* Non-conflicting addresses */ continue; - if (last < rule->first || rule->last < first) + if (new->last < rule->first || rule->last < new->first) /* Port ranges don't overlap */ continue; die("Forwarding configuration conflict: %s/%u-%u versus %s/%u-%u", - inany_ntop(addr, newstr, sizeof(newstr)), first, last, + inany_ntop(fwd_rule_addr(new), newstr, sizeof(newstr)), + new->first, new->last, inany_ntop(fwd_rule_addr(rule), rulestr, sizeof(rulestr)), rule->first, rule->last); } - new = &fwd->rules[fwd->count]; - new->proto = proto; - new->flags = flags; - - if (addr) { - new->addr = *addr; - } else { - new->addr = inany_any6; - new->flags |= FWD_DUAL_STACK_ANY; - } - - memset(new->ifname, 0, sizeof(new->ifname)); - if (ifname) { - int ret; - - ret = snprintf(new->ifname, sizeof(new->ifname), - "%s", ifname); - if (ret <= 0 || (size_t)ret >= sizeof(new->ifname)) - die("Invalid interface name: %s", ifname); - } - - assert(first <= last); - new->first = first; - new->last = last; - new->to = to; - fwd->rulesocks[fwd->count] = &fwd->socks[fwd->sock_count]; for (port = new->first; port <= new->last; port++) fwd->rulesocks[fwd->count][port - new->first] = -1; - fwd->count++; + fwd->rules[fwd->count++] = *new; fwd->sock_count += num; } @@ -85,9 +85,7 @@ struct fwd_scan { #define FWD_PORT_SCAN_INTERVAL 1000 /* ms */ void fwd_rule_init(struct ctx *c); -void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags, - const union inany_addr *addr, const char *ifname, - in_port_t first, in_port_t last, in_port_t to); +void fwd_rule_add(struct fwd_table *fwd, const struct fwd_rule *new); const struct fwd_rule *fwd_rule_search(const struct fwd_table *fwd, const struct flowside *ini, uint8_t proto, int hint); |
