iprule: add support for uidrange
authorMatthew Hagan <mnhagan88@gmail.com>
Sun, 16 Jan 2022 00:21:17 +0000 (00:21 +0000)
committerHans Dedecker <dedeckeh@gmail.com>
Sat, 22 Jan 2022 20:24:16 +0000 (21:24 +0100)
Allow for per-user routing policies via the uidrange iprule option.
Option allows for a single UID or range of UIDs.

Signed-off-by: Matthew Hagan <mnhagan88@gmail.com>
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
iprule.c
iprule.h
system-linux.c

index b9e16a5f082c4451f6bac85273c9e83cb423a4ee..095607373f417a7036441d17ab3c650a7d6a143a 100644 (file)
--- a/iprule.c
+++ b/iprule.c
@@ -44,6 +44,7 @@ enum {
        RULE_ACTION,
        RULE_GOTO,
        RULE_SUP_PREFIXLEN,
+       RULE_UIDRANGE,
        RULE_DISABLED,
        __RULE_MAX
 };
@@ -59,6 +60,7 @@ static const struct blobmsg_policy rule_attr[__RULE_MAX] = {
        [RULE_FWMARK] = { .name = "mark", .type = BLOBMSG_TYPE_STRING },
        [RULE_LOOKUP] = { .name = "lookup", .type = BLOBMSG_TYPE_STRING },
        [RULE_SUP_PREFIXLEN] = { .name = "suppress_prefixlength", .type = BLOBMSG_TYPE_INT32 },
+       [RULE_UIDRANGE] = { .name = "uidrange", .type = BLOBMSG_TYPE_STRING },
        [RULE_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_STRING },
        [RULE_GOTO]   = { .name = "goto", .type = BLOBMSG_TYPE_INT32 },
        [RULE_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
@@ -282,6 +284,18 @@ iprule_add(struct blob_attr *attr, bool v6)
                rule->flags |= IPRULE_SUP_PREFIXLEN;
        }
 
+       if ((cur = tb[RULE_UIDRANGE]) != NULL) {
+               int ret = sscanf(blobmsg_get_string(cur), "%u-%u", &rule->uidrange_start, &rule->uidrange_end);
+
+               if (ret == 1)
+                       rule->uidrange_end = rule->uidrange_start;
+               else if (ret != 2) {
+                       DPRINTF("Failed to parse UID range: %s\n", (char *) blobmsg_data(cur));
+                       goto error;
+               }
+               rule->flags |= IPRULE_UIDRANGE;
+       }
+
        if ((cur = tb[RULE_ACTION]) != NULL) {
                if (!system_resolve_iprule_action(blobmsg_data(cur), &rule->action)) {
                        DPRINTF("Failed to parse rule action: %s\n", (char *) blobmsg_data(cur));
index 89b94b459a49ec1cd9fa87809342185297e3b9a4..6d91d061e04109d28ba052c4fb0f75fb4b7c1903 100644 (file)
--- a/iprule.h
+++ b/iprule.h
@@ -63,6 +63,9 @@ enum iprule_flags {
 
        /* rule suppresses results by prefix length */
        IPRULE_SUP_PREFIXLEN    = (1 << 13),
+
+       /* rule specifies uidrange */
+       IPRULE_UIDRANGE         = (1 << 14),
 };
 
 struct iprule {
@@ -102,6 +105,8 @@ struct iprule {
 
        unsigned int lookup;
        unsigned int sup_prefixlen;
+       unsigned int uidrange_start;
+       unsigned int uidrange_end;
        unsigned int action;
        unsigned int gotoid;
 };
index 654f2acdc00cdbb01552b1ad17630c0baae9a40c..9846e98882362079e0ff8fda25591221cc10755c 100644 (file)
@@ -2954,6 +2954,15 @@ static int system_iprule(struct iprule *rule, int cmd)
        if (rule->flags & IPRULE_SUP_PREFIXLEN)
                nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
 
+       if (rule->flags & IPRULE_UIDRANGE) {
+               struct fib_rule_uid_range uidrange = {
+                       .start = rule->uidrange_start,
+                       .end = rule->uidrange_end
+               };
+
+               nla_put(msg, FRA_UID_RANGE, sizeof(uidrange), &uidrange);
+       }
+
        if (rule->flags & IPRULE_GOTO)
                nla_put_u32(msg, FRA_GOTO, rule->gotoid);