From: egc112 Date: Sun, 20 Apr 2025 11:05:11 +0000 (+0200) Subject: netifd: iprule add sport and dport X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=7901e66c5f273bceee8981bc8a0c8b0e60945f60;p=project%2Fnetifd.git 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 Link: https://github.com/openwrt/netifd/pull/47 Signed-off-by: Robert Marko --- 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); }