From b7a3df0f3c56c10587e926307daaa87fc3b854bf Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 9 Jul 2013 13:37:54 +0900 Subject: Support experimental UID range routing. This uses the FRA_UID_START and FRA_UID_END rule attribute types with values 18 and 19, and the RTA_UID route attribute type with value 18. Syntax uses the uidrange keyword for rules and the uid keyword for routes. Example: root@hammerhead:/ # ip -6 rule add prio 123 uidrange 100-200 lookup 100 root@hammerhead:/ # ip -6 rule | grep uidrange 123: from all uidrange 100-200 lookup 100 ooot@hammerhead:/ # t@hammerhead:/ # ip -4 route get uid 10045 8.8.4.4 8.8.4.4 via 192.168.159.254 dev wlan0 src 192.168.158.102 uid 10045 cache (cherry picked from commit 628e7252f75b2621d4b8c5f9314f55f3ec24b92b) Change-Id: I52d544f27ffef895ad5513a516e37cfba7da9b75 --- include/linux/fib_rules.h | 2 ++ include/linux/rtnetlink.h | 2 ++ ip/iproute.c | 10 +++++++++- ip/iprule.c | 24 ++++++++++++++++++++++-- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index 51da65b..106d35f 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h @@ -49,6 +49,8 @@ enum { FRA_TABLE, /* Extended table id */ FRA_FWMASK, /* mask for netfilter mark */ FRA_OIFNAME, + FRA_UID_START, + FRA_UID_END, __FRA_MAX }; diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index d5b7fdd..4ee1f37 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -283,6 +283,8 @@ enum rtattr_type_t { RTA_MP_ALGO, /* no longer used */ RTA_TABLE, RTA_MARK, + RTA_MFC_STATS, /* not used - backported from the future */ + RTA_UID, __RTA_MAX }; diff --git a/ip/iproute.c b/ip/iproute.c index 5cd313e..8dc0bc8 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -62,7 +62,7 @@ static void usage(void) fprintf(stderr, " ip route restore\n"); fprintf(stderr, " ip route get ADDRESS [ from ADDRESS iif STRING ]\n"); fprintf(stderr, " [ oif STRING ] [ tos TOS ]\n"); - fprintf(stderr, " [ mark NUMBER ]\n"); + fprintf(stderr, " [ mark NUMBER ] [ uid NUMBER ]\n"); fprintf(stderr, " ip route { add | del | change | append | replace } ROUTE\n"); fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n"); fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n"); @@ -423,6 +423,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) } } + if (tb[RTA_UID]) + fprintf(fp, " uid %u ", rta_getattr_u32(tb[RTA_UID])); + if (tb[RTA_FLOW] && filter.realmmask != ~0U) { __u32 to = rta_getattr_u32(tb[RTA_FLOW]); __u32 from = to>>16; @@ -1401,6 +1404,11 @@ int iproute_get(int argc, char **argv) strcmp(*argv, "dev") == 0) { NEXT_ARG(); odev = *argv; + } else if (matches(*argv, "uid") == 0) { + uid_t uid; + NEXT_ARG(); + get_unsigned(&uid, *argv, 0); + addattr32(&req.n, sizeof(req), RTA_UID, uid); } else if (matches(*argv, "notify") == 0) { req.r.rtm_flags |= RTM_F_NOTIFY; } else if (matches(*argv, "connected") == 0) { diff --git a/ip/iprule.c b/ip/iprule.c index a5fcd43..3ea0e81 100644 --- a/ip/iprule.c +++ b/ip/iprule.c @@ -34,7 +34,7 @@ static void usage(void) { fprintf(stderr, "Usage: ip rule [ list | add | del | flush ] SELECTOR ACTION\n"); fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n"); - fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n"); + fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ] [ uidrange UID1-UID2 ]\n"); fprintf(stderr, "ACTION := [ table TABLE_ID ]\n"); fprintf(stderr, " [ prohibit | reject | unreachable ]\n"); fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n"); @@ -49,7 +49,7 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; int host_len = -1; - __u32 table; + __u32 table, uid_start, uid_end; struct rtattr * tb[FRA_MAX+1]; char abuf[256]; SPRINT_BUF(b1); @@ -152,6 +152,19 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) fprintf(fp, "[detached] "); } + if (tb[FRA_UID_START] || tb[FRA_UID_END]) { + fprintf(fp, "uidrange "); + if (tb[FRA_UID_START]) + fprintf(fp, "%u", rta_getattr_u32(tb[FRA_UID_START])); + else + fprintf(fp, "???"); + + if (tb[FRA_UID_END]) + fprintf(fp, "-%u ", rta_getattr_u32(tb[FRA_UID_END])); + else + fprintf(fp, "-??? "); + } + table = rtm_get_table(r, tb); if (table) fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1))); @@ -323,6 +336,13 @@ static int iprule_modify(int cmd, int argc, char **argv) fprintf(stderr, "Warning: route NAT is deprecated\n"); addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv)); req.r.rtm_type = RTN_NAT; + } else if (strcmp(*argv, "uidrange") == 0) { + __u32 uid_start, uid_end; + NEXT_ARG(); + if (sscanf(*argv, "%u-%u", &uid_start, &uid_end) != 2) + invarg("UID range is invalid\n", *argv); + addattr32(&req.n, sizeof(req), FRA_UID_START, uid_start); + addattr32(&req.n, sizeof(req), FRA_UID_END, uid_end); } else { int type; -- cgit v1.2.3