aboutgitcodebugslistschat
path: root/fwd_rule.c
diff options
context:
space:
mode:
Diffstat (limited to 'fwd_rule.c')
-rw-r--r--fwd_rule.c77
1 files changed, 63 insertions, 14 deletions
diff --git a/fwd_rule.c b/fwd_rule.c
index ef35e1b..42ec68e 100644
--- a/fwd_rule.c
+++ b/fwd_rule.c
@@ -378,14 +378,17 @@ int fwd_rule_add(struct fwd_table *fwd, const struct fwd_rule *new)
* @first: First port to forward
* @last: Last port to forward
* @exclude: Bitmap of ports to exclude (may be NULL)
- * @to: Port to translate @first to when forwarding
+ * @tgt_addr: Destination address on the target side
+ * @tgt_first: Destination port to use for @first on the target side
* @flags: Flags for forwarding entries
*/
static void fwd_rule_range_except(struct fwd_table *fwd, bool del,
uint8_t proto, const union inany_addr *addr,
const char *ifname,
uint16_t first, uint16_t last,
- const uint8_t *exclude, uint16_t to,
+ const uint8_t *exclude,
+ const union inany_addr *tgt_addr,
+ uint16_t tgt_first,
uint8_t flags)
{
struct fwd_rule rule = {
@@ -394,10 +397,18 @@ static void fwd_rule_range_except(struct fwd_table *fwd, bool del,
.proto = proto,
.flags = flags,
};
+ unsigned delta = tgt_first - first;
char rulestr[FWD_RULE_STRLEN];
- unsigned delta = to - first;
unsigned base, i;
+ if (tgt_addr && !inany_is_unspecified(tgt_addr)) {
+ char astr[INANY_ADDRSTRLEN];
+
+ info("Target address: %s",
+ inany_ntop(tgt_addr, astr, sizeof(astr)));
+ die("Target address remapping not yet implemented");
+ }
+
if (!addr)
rule.flags |= FWD_DUAL_STACK_ANY;
if (ifname) {
@@ -458,19 +469,31 @@ enum fwd_port_chunk_kind {
* @cursor: Parsing point (see parse.c)
* @kindp: Updated with kind of chunk we parsed
* @lrange: Updated with listening port range (for INCLUDE & EXCLUDE)
+ * @taddr: Updated with target address (for INCLUDE & ALL)
* @trange: Updated with target port range (for INCLUDE)
*/
static bool parse_port_chunk(const char **cursor,
enum fwd_port_chunk_kind *kindp,
struct port_range *lrange,
+ union inany_addr *taddr,
struct port_range *trange)
{
struct port_range lr = { 0 }, tr = { 0 };
+ union inany_addr taddr_tmp = inany_any6;
enum fwd_port_chunk_kind kind;
const char *p = *cursor;
if (parse_literal(&p, "all")) {
+ const char *tgtspec = p;
+
kind = CHUNK_ALL;
+ if (p = tgtspec,
+ parse_literal(&p, ":") &&
+ parse_inany(&p, &taddr_tmp)) {
+ /* Target address */
+ } else {
+ p = tgtspec;
+ }
} else if (parse_literal(&p, "auto")) {
kind = CHUNK_AUTO;
} else if (parse_literal(&p, "~")) {
@@ -478,12 +501,29 @@ static bool parse_port_chunk(const char **cursor,
if (!parse_port_range(&p, &lr))
return false;
} else if (parse_port_range(&p, &lr)) {
- kind = CHUNK_INCLUDE;
+ const char *tgtspec = p;
- if (parse_literal(&p, ":")) {
- if (!parse_port_range(&p, &tr))
- return false;
+ kind = CHUNK_INCLUDE;
+ if (p = tgtspec,
+ parse_literal(&p, ":") &&
+ parse_inany(&p, &taddr_tmp) &&
+ parse_literal(&p, "/") &&
+ parse_port_range(&p, &tr)) {
+ /* Target address & range */
+ } else if (p = tgtspec,
+ parse_literal(&p, ":") &&
+ parse_inany(&p, &taddr_tmp)) {
+ /* Target address only */
+ tr = lr;
+ } else if (p = tgtspec,
+ parse_literal(&p, ":") &&
+ parse_port_range(&p, &tr)) {
+ /* Target range only */
+ taddr_tmp = inany_any6;
} else {
+ p = tgtspec;
+ /* No target specification */
+ taddr_tmp = inany_any6;
tr = lr;
}
} else {
@@ -492,6 +532,8 @@ static bool parse_port_chunk(const char **cursor,
*kindp = kind;
*lrange = lr;
+ if (taddr)
+ *taddr = taddr_tmp;
if (trange)
*trange = tr;
*cursor = p;
@@ -551,6 +593,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
const char *spec)
{
uint8_t exclude[PORT_BITMAP_SIZE] = { 0 };
+ union inany_addr all_taddr = inany_any6;
enum fwd_port_chunk_kind kind;
struct port_range lrange;
bool exclude_only = true;
@@ -561,7 +604,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
/* Consider excluded ranges and "auto" in the first pass */
p = spec;
do {
- if (!parse_port_chunk(&p, &kind, &lrange, NULL))
+ if (!parse_port_chunk(&p, &kind, &lrange, NULL, NULL))
goto bad;
switch (kind) {
@@ -586,14 +629,19 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
p = spec;
do {
struct port_range trange;
+ union inany_addr taddr;
- if (!parse_port_chunk(&p, &kind, &lrange, &trange))
+ if (!parse_port_chunk(&p, &kind, &lrange, &taddr, &trange))
goto bad;
switch (kind) {
- case CHUNK_AUTO: /* already handled */
- case CHUNK_EXCLUDE: /* already handled */
- case CHUNK_ALL: /* handled later */
+ case CHUNK_AUTO:
+ case CHUNK_EXCLUDE:
+ continue; /* already handled */
+
+ case CHUNK_ALL:
+ /* Save the address to use later */
+ all_taddr = taddr;
continue;
case CHUNK_INCLUDE:
@@ -604,7 +652,8 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
fwd_rule_range_except(fwd, del, proto, addr, ifname,
lrange.first, lrange.last,
- exclude, trange.first, flags);
+ exclude, &taddr, trange.first,
+ flags);
break;
default:
goto bad;
@@ -620,7 +669,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto,
fwd_rule_range_except(fwd, del, proto, addr, ifname,
1, NUM_PORTS - 1, exclude,
- 1, flags | FWD_WEAK);
+ &all_taddr, 1, flags | FWD_WEAK);
}
return;
bad: