aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--conf.c5
-rw-r--r--fwd.c21
-rw-r--r--inany.c19
-rw-r--r--inany.h1
4 files changed, 40 insertions, 6 deletions
diff --git a/conf.c b/conf.c
index ce6c012..2f22a7f 100644
--- a/conf.c
+++ b/conf.c
@@ -172,11 +172,6 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
for (i = base; i <= last; i++) {
if (exclude && bitmap_isset(exclude, i))
break;
-
- if (bitmap_isset(fwd->map, i)) {
- warn(
-"Altering mapping of already mapped port number: %s", optarg);
- }
}
if ((optname == 'T' || optname == 'U') && c->no_bindtodevice) {
diff --git a/fwd.c b/fwd.c
index 50df3d5..bc2698f 100644
--- a/fwd.c
+++ b/fwd.c
@@ -349,7 +349,7 @@ void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
const uint8_t allowed_flags = FWD_WEAK | FWD_SCAN;
unsigned num = (unsigned)last - first + 1;
struct fwd_rule *new;
- unsigned port;
+ unsigned i, port;
ASSERT(!(flags & ~allowed_flags));
@@ -358,6 +358,25 @@ void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
if ((fwd->sock_count + num) > ARRAY_SIZE(fwd->socks))
die("Too many listening sockets");
+ /* Check for any conflicting entries */
+ for (i = 0; i < fwd->count; i++) {
+ char newstr[INANY_ADDRSTRLEN], rulestr[INANY_ADDRSTRLEN];
+ struct fwd_rule *rule = &fwd->rules[i];
+
+ if (!inany_matches(addr, fwd_rule_addr(rule)))
+ /* Non-conflicting addresses */
+ continue;
+
+ if (last < rule->first || rule->last < 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(rule), rulestr, sizeof(rulestr)),
+ rule->first, rule->last);
+ }
+
new = &fwd->rules[fwd->count++];
new->flags = flags;
diff --git a/inany.c b/inany.c
index 87a4d8b..543b60d 100644
--- a/inany.c
+++ b/inany.c
@@ -21,6 +21,25 @@
const union inany_addr inany_loopback4 = INANY_INIT4(IN4ADDR_LOOPBACK_INIT);
const union inany_addr inany_any4 = INANY_INIT4(IN4ADDR_ANY_INIT);
+/** inany_matches - Do two addresses match?
+ * @a, @b: IPv[46] addresses (NULL for 0.0.0.0 & ::)
+ *
+ * Return: true if they match, false otherwise
+ *
+ * Addresses match themselves, but also unspecified addresses of the same
+ * family.
+ */
+bool inany_matches(const union inany_addr *a, const union inany_addr *b)
+{
+ if (!a || !b)
+ return true;
+
+ if (inany_is_unspecified(a) || inany_is_unspecified(b))
+ return !!inany_v4(a) == !!inany_v4(b);
+
+ return inany_equals(a, b);
+}
+
/** inany_ntop - Convert an IPv[46] address to text format
* @src: IPv[46] address (NULL for unspecified)
* @dst: output buffer, minimum INANY_ADDRSTRLEN bytes
diff --git a/inany.h b/inany.h
index 61b36fb..b02c289 100644
--- a/inany.h
+++ b/inany.h
@@ -293,6 +293,7 @@ static inline void inany_siphash_feed(struct siphash_state *state,
#define INANY_ADDRSTRLEN MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)
+bool inany_matches(const union inany_addr *a, const union inany_addr *b);
const char *inany_ntop(const union inany_addr *src, char *dst, socklen_t size);
int inany_pton(const char *src, union inany_addr *dst);