aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--fwd.c10
-rw-r--r--fwd.h17
2 files changed, 24 insertions, 3 deletions
diff --git a/fwd.c b/fwd.c
index da4c313..30b8a25 100644
--- a/fwd.c
+++ b/fwd.c
@@ -346,6 +346,7 @@ void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
{
/* Flags which can be set from the caller */
const uint8_t allowed_flags = FWD_WEAK | FWD_SCAN;
+ unsigned num = (unsigned)last - first + 1;
struct fwd_rule *new;
unsigned port;
@@ -353,6 +354,8 @@ void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
if (fwd->count >= ARRAY_SIZE(fwd->rules))
die("Too many port forwarding ranges");
+ if ((fwd->sock_count + num) > ARRAY_SIZE(fwd->socks))
+ die("Too many listening sockets");
new = &fwd->rules[fwd->count++];
new->flags = flags;
@@ -379,8 +382,13 @@ void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
new->to = to;
+ new->socks = &fwd->socks[fwd->sock_count];
+ fwd->sock_count += num;
+
for (port = new->first; port <= new->last; port++) {
- /* Fill in the legacy data structures to match the table */
+ new->socks[port - new->first] = -1;
+
+ /* Fill in the legacy forwarding data structures to match the table */
if (!(new->flags & FWD_SCAN))
bitmap_set(fwd->map, port);
fwd->delta[port] = new->to - new->first;
diff --git a/fwd.h b/fwd.h
index cc7e0ac..f971fff 100644
--- a/fwd.h
+++ b/fwd.h
@@ -23,6 +23,7 @@ bool fwd_port_is_ephemeral(in_port_t port);
* @first: First port number to forward
* @last: Last port number to forward
* @to: Target port for @first, port n goes to @to + (n - @first)
+ * @socks: Array of listening sockets for this entry
* @flags: Flag mask
* FWD_DUAL_STACK_ANY - match any IPv4 or IPv6 address (@addr should be ::)
* FWD_WEAK - Don't give an error if binds fail for some forwards
@@ -36,6 +37,7 @@ struct fwd_rule {
in_port_t first;
in_port_t last;
in_port_t to;
+ int *socks;
#define FWD_DUAL_STACK_ANY BIT(0)
#define FWD_WEAK BIT(1)
#define FWD_SCAN BIT(2)
@@ -68,15 +70,24 @@ enum fwd_ports_mode {
#define PORT_BITMAP_SIZE DIV_ROUND_UP(NUM_PORTS, 8)
+/* Maximum number of listening sockets (per pif & protocol)
+ *
+ * Rationale: This lets us listen on every port for two addresses (which we need
+ * for -T auto without SO_BINDTODEVICE), plus a comfortable number of extras.
+ */
+#define MAX_LISTEN_SOCKS (NUM_PORTS * 3)
+
/**
* fwd_ports() - Describes port forwarding for one protocol and direction
- * @mode: Overall forwarding mode (all, none, auto, specific ports)
+ * @mode: Overall mode (all, none, auto, specific ports)
* @scan4: /proc/net fd to scan for IPv4 ports when in AUTO mode
* @scan6: /proc/net fd to scan for IPv6 ports when in AUTO mode
* @count: Number of forwarding rules
* @rules: Array of forwarding rules
* @map: Bitmap describing which ports are forwarded
- * @delta: Offset between the original destination and mapped port number
+ * @delta: Offset between the original mapped port number
+ * @sock_count: Number of entries used in @socks
+ * @socks: Listening sockets for forwarding
*/
struct fwd_ports {
enum fwd_ports_mode mode;
@@ -86,6 +97,8 @@ struct fwd_ports {
struct fwd_rule rules[MAX_FWD_RULES];
uint8_t map[PORT_BITMAP_SIZE];
in_port_t delta[NUM_PORTS];
+ unsigned sock_count;
+ int socks[MAX_LISTEN_SOCKS];
};
#define FWD_PORT_SCAN_INTERVAL 1000 /* ms */