summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoregc1122025-04-20 11:05:11 +0000
committerRobert Marko2025-05-23 11:18:40 +0000
commit7901e66c5f273bceee8981bc8a0c8b0e60945f60 (patch)
treec3f8bd28f933b585511c50f1494e59edb181ca39
parentd476e18e8d430ddfe3ae1809ddeea035bbb9a998 (diff)
downloadnetifd-7901e66c5f273bceee8981bc8a0c8b0e60945f60.tar.gz
netifd: iprule add sport and dport
Maintainer: @nbd, @robimarko I was missing the ip rules for `sport` and `dport` in netifd and although I have a working C knowledge, I have little netlink knowledge and it is the first time I looked into netifd but after some research I could come up with a working patch to implement `option sport` and `option dport`. I hope you can have a look and implement these useful options. Run tested: Dynalink DL-WRX36 (ipq8074) running Main Snapshot r29276-963d320086 20-apr-2025 Example 1 sport: ``` config rule option src '192.168.9.23/32' option sport '1194' option lookup 'main' ``` Result: ``` root@DL-WRX36:~# ip ru 0: from all lookup local 1: from 192.168.9.23 sport 1194 lookup main ``` Example 2 sport range: ``` config rule option src '192.168.9.23/32' option sport '1194-1195' option lookup 'main' ``` Result: ``` root@DL-WRX36:~# ip ru 0: from all lookup local 1: from 192.168.9.23 sport 1194-1195 lookup main ``` Example 3 dport: ``` config rule option src '192.168.9.23/32' option dport '1294' option lookup 'main' ``` Result: ``` root@DL-WRX36:~# ip ru 0: from all lookup local 1: from 192.168.9.23 dport 1294 lookup main ``` Example 4 dport range: ``` config rule option src '192.168.9.23/32' option dport '1294-1295' option lookup 'main' ``` Result: ``` root@DL-WRX36:~# ip ru 0: from all lookup local 1: from 192.168.9.23 dport 1294-1295 lookup main ``` Example 5 sport dport: ``` config rule option src '192.168.9.23/32' option sport '1194-1195' option dport '1294-1295' option lookup 'main' ``` Result: ``` root@DL-WRX36:~# ip ru 0: from all lookup local 1: from 192.168.9.23 sport 1194-1195 dport 1294-1295 lookup main ``` Signed-off-by: Erik Conijn <egc112@msn.com> Link: https://github.com/openwrt/netifd/pull/47 Signed-off-by: Robert Marko <robimarko@gmail.com>
-rw-r--r--iprule.c28
-rw-r--r--iprule.h10
-rw-r--r--system-linux.c18
3 files changed, 56 insertions, 0 deletions
diff --git a/iprule.c b/iprule.c
index f6f9d4e..c2009c8 100644
--- a/iprule.c
+++ b/iprule.c
@@ -46,6 +46,8 @@ enum {
RULE_SUP_PREFIXLEN,
RULE_UIDRANGE,
RULE_IPPROTO,
+ RULE_SPORT,
+ RULE_DPORT,
RULE_DISABLED,
__RULE_MAX
};
@@ -65,6 +67,8 @@ static const struct blobmsg_policy rule_attr[__RULE_MAX] = {
[RULE_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_STRING },
[RULE_GOTO] = { .name = "goto", .type = BLOBMSG_TYPE_INT32 },
[RULE_IPPROTO] = { .name = "ipproto", .type = BLOBMSG_TYPE_STRING },
+ [RULE_SPORT] = { .name = "sport", .type = BLOBMSG_TYPE_STRING },
+ [RULE_DPORT] = { .name = "dport", .type = BLOBMSG_TYPE_STRING },
[RULE_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
};
@@ -319,6 +323,30 @@ iprule_add(struct blob_attr *attr, bool v6)
rule->flags |= IPRULE_IPPROTO;
}
+ if ((cur = tb[RULE_SPORT]) != NULL) {
+ int ret = sscanf(blobmsg_get_string(cur), "%u-%u", &rule->sport_start, &rule->sport_end);
+
+ if (ret == 1)
+ rule->sport_end = rule->sport_start;
+ else if (ret != 2) {
+ D(INTERFACE, "Failed to parse sport range: %s", (char *) blobmsg_data(cur));
+ goto error;
+ }
+ rule->flags |= IPRULE_SPORT;
+ }
+
+ if ((cur = tb[RULE_DPORT]) != NULL) {
+ int ret = sscanf(blobmsg_get_string(cur), "%u-%u", &rule->dport_start, &rule->dport_end);
+
+ if (ret == 1)
+ rule->dport_end = rule->dport_start;
+ else if (ret != 2) {
+ D(INTERFACE, "Failed to parse dport range: %s", (char *) blobmsg_data(cur));
+ goto error;
+ }
+ rule->flags |= IPRULE_DPORT;
+ }
+
vlist_add(&iprules, &rule->node, rule);
return;
diff --git a/iprule.h b/iprule.h
index 56b9998..19d24fb 100644
--- a/iprule.h
+++ b/iprule.h
@@ -69,6 +69,12 @@ enum iprule_flags {
/* rule specifies ipproto */
IPRULE_IPPROTO = (1 << 15),
+
+ /* rule specifies sport */
+ IPRULE_SPORT = (1 << 16),
+
+ /* rule specifies dport */
+ IPRULE_DPORT = (1 << 17),
};
struct iprule {
@@ -113,6 +119,10 @@ struct iprule {
unsigned int action;
unsigned int gotoid;
unsigned int ipproto;
+ unsigned int sport_start;
+ unsigned int sport_end;
+ unsigned int dport_start;
+ unsigned int dport_end;
};
extern struct vlist_tree iprules;
diff --git a/system-linux.c b/system-linux.c
index 5c525ce..29f9b4d 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -3690,6 +3690,24 @@ static int system_iprule(struct iprule *rule, int cmd)
if (rule->flags & IPRULE_IPPROTO)
nla_put_u8(msg, FRA_IP_PROTO, rule->ipproto);
+ if (rule->flags & IPRULE_SPORT) {
+ struct fib_rule_port_range sportrange = {
+ .start = rule->sport_start,
+ .end = rule->sport_end
+ };
+
+ nla_put(msg, FRA_SPORT_RANGE, sizeof(sportrange), &sportrange);
+ }
+
+ if (rule->flags & IPRULE_DPORT) {
+ struct fib_rule_port_range dportrange = {
+ .start = rule->dport_start,
+ .end = rule->dport_end
+ };
+
+ nla_put(msg, FRA_DPORT_RANGE, sizeof(dportrange), &dportrange);
+ }
+
return system_rtnl_call(msg);
}