]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/iprule.c
rdma: Properly mark RDMAtool license
[mirror_iproute2.git] / ip / iprule.c
index d89d808d89095d3e958bd02f14ceaec76d25d1ac..4e9437de343780df8c56c68a8d8792ec4ece5a7a 100644 (file)
@@ -71,6 +71,7 @@ static struct
        unsigned int tos, tosmask;
        unsigned int pref, prefmask;
        unsigned int fwmark, fwmask;
+       uint64_t tun_id;
        char iif[IFNAMSIZ];
        char oif[IFNAMSIZ];
        struct fib_rule_uid_range range;
@@ -78,6 +79,9 @@ static struct
        inet_prefix dst;
        int protocol;
        int protocolmask;
+       struct fib_rule_port_range sport;
+       struct fib_rule_port_range dport;
+       __u8 ipproto;
 } filter;
 
 static inline int frh_get_table(struct fib_rule_hdr *frh, struct rtattr **tb)
@@ -174,6 +178,51 @@ static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
                        return false;
        }
 
+       if (filter.ipproto) {
+               __u8 ipproto = 0;
+
+               if (tb[FRA_IP_PROTO])
+                       ipproto = rta_getattr_u8(tb[FRA_IP_PROTO]);
+               if (filter.ipproto != ipproto)
+                       return false;
+       }
+
+       if (filter.sport.start) {
+               const struct fib_rule_port_range *r;
+
+               if (!tb[FRA_SPORT_RANGE])
+                       return false;
+
+               r = RTA_DATA(tb[FRA_SPORT_RANGE]);
+               if (r->start != filter.sport.start ||
+                   r->end != filter.sport.end)
+                       return false;
+       }
+
+       if (filter.dport.start) {
+               const struct fib_rule_port_range *r;
+
+               if (!tb[FRA_DPORT_RANGE])
+                       return false;
+
+               r = RTA_DATA(tb[FRA_DPORT_RANGE]);
+               if (r->start != filter.dport.start ||
+                   r->end != filter.dport.end)
+                       return false;
+       }
+
+       if (filter.tun_id) {
+               __u64 tun_id = 0;
+
+               if (tb[FRA_TUN_ID]) {
+                       tun_id = ntohll(rta_getattr_u64(tb[FRA_TUN_ID]));
+                       if (filter.tun_id != tun_id)
+                               return false;
+               } else {
+                       return false;
+               }
+       }
+
        table = frh_get_table(frh, tb);
        if (filter.tb > 0 && filter.tb ^ table)
                return false;
@@ -263,10 +312,10 @@ int print_rule(struct nlmsghdr *n, void *arg)
 
                if (tb[FRA_FWMASK] &&
                    (mask = rta_getattr_u32(tb[FRA_FWMASK])) != 0xFFFFFFFF) {
-                       print_0xhex(PRINT_ANY, "fwmark", "fwmark 0x%x", mark);
-                       print_0xhex(PRINT_ANY, "fwmask", "/0x%x ", mask);
+                       print_0xhex(PRINT_ANY, "fwmark", "fwmark %#llx", mark);
+                       print_0xhex(PRINT_ANY, "fwmask", "/%#llx ", mask);
                } else {
-                       print_0xhex(PRINT_ANY, "fwmark", "fwmark 0x%x ", mark);
+                       print_0xhex(PRINT_ANY, "fwmark", "fwmark %#llx ", mark);
                }
        }
 
@@ -340,6 +389,12 @@ int print_rule(struct nlmsghdr *n, void *arg)
                }
        }
 
+       if (tb[FRA_TUN_ID]) {
+               __u64 tun_id = ntohll(rta_getattr_u64(tb[FRA_TUN_ID]));
+
+               print_u64(PRINT_ANY, "tun_id", "tun_id %llu ", tun_id);
+       }
+
        table = frh_get_table(frh, tb);
        if (table) {
                print_string(PRINT_ANY, "table",
@@ -404,7 +459,7 @@ int print_rule(struct nlmsghdr *n, void *arg)
        } else if (frh->action == FR_ACT_NOP) {
                print_null(PRINT_ANY, "nop", "nop", NULL);
        } else if (frh->action != FR_ACT_TO_TBL) {
-               print_string(PRINT_ANY, "to_tbl", "%s",
+               print_string(PRINT_ANY, "action", "%s",
                             rtnl_rtntype_n2a(frh->action, b1, sizeof(b1)));
        }
 
@@ -461,6 +516,7 @@ static int flush_rule(struct nlmsghdr *n, void *arg)
        struct fib_rule_hdr *frh = NLMSG_DATA(n);
        int len = n->nlmsg_len;
        struct rtattr *tb[FRA_MAX+1];
+       int host_len = -1;
 
        len -= NLMSG_LENGTH(sizeof(*frh));
        if (len < 0)
@@ -468,6 +524,10 @@ static int flush_rule(struct nlmsghdr *n, void *arg)
 
        parse_rtattr(tb, FRA_MAX, RTM_RTA(frh), len);
 
+       host_len = af_bit_len(frh->family);
+       if (!filter_nlmsg(n, tb, host_len))
+               return 0;
+
        if (tb[FRA_PROTOCOL]) {
                __u8 protocol = rta_getattr_u8(tb[FRA_PROTOCOL]);
 
@@ -578,6 +638,13 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action)
                                   &filter.range.end) != 2)
                                invarg("invalid UID range\n", *argv);
 
+               } else if (matches(*argv, "tun_id") == 0) {
+                       __u64 tun_id;
+
+                       NEXT_ARG();
+                       if (get_u64(&tun_id, *argv, 0))
+                               invarg("\"tun_id\" value is invalid\n", *argv);
+                       filter.tun_id = tun_id;
                } else if (matches(*argv, "lookup") == 0 ||
                           matches(*argv, "table") == 0) {
                        __u32 tid;
@@ -602,6 +669,36 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action)
                                filter.protocolmask = 0;
                        }
                        filter.protocol = prot;
+               } else if (strcmp(*argv, "ipproto") == 0) {
+                       int ipproto;
+
+                       NEXT_ARG();
+                       ipproto = inet_proto_a2n(*argv);
+                       if (ipproto < 0)
+                               invarg("Invalid \"ipproto\" value\n", *argv);
+                       filter.ipproto = ipproto;
+               } else if (strcmp(*argv, "sport") == 0) {
+                       struct fib_rule_port_range r;
+                       int ret;
+
+                       NEXT_ARG();
+                       ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end);
+                       if (ret == 1)
+                               r.end = r.start;
+                       else if (ret != 2)
+                               invarg("invalid port range\n", *argv);
+                       filter.sport = r;
+               } else if (strcmp(*argv, "dport") == 0) {
+                       struct fib_rule_port_range r;
+                       int ret;
+
+                       NEXT_ARG();
+                       ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end);
+                       if (ret == 1)
+                               r.end = r.start;
+                       else if (ret != 2)
+                               invarg("invalid dport range\n", *argv);
+                       filter.dport = r;
                } else{
                        if (matches(*argv, "dst") == 0 ||
                            matches(*argv, "to") == 0) {
@@ -691,6 +788,11 @@ static int iprule_modify(int cmd, int argc, char **argv)
        };
 
        if (cmd == RTM_NEWRULE) {
+               if (argc == 0) {
+                       fprintf(stderr,
+                               "\"ip rule add\" requires arguments.\n");
+                       return -1;
+               }
                req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
                req.frh.action = FR_ACT_TO_TBL;
        }
@@ -769,6 +871,13 @@ static int iprule_modify(int cmd, int argc, char **argv)
                        if (rtnl_rtprot_a2n(&proto, *argv))
                                invarg("\"protocol\" value is invalid\n", *argv);
                        addattr8(&req.n, sizeof(req), FRA_PROTOCOL, proto);
+               } else if (matches(*argv, "tun_id") == 0) {
+                       __u64 tun_id;
+
+                       NEXT_ARG();
+                       if (get_be64(&tun_id, *argv, 0))
+                               invarg("\"tun_id\" value is invalid\n", *argv);
+                       addattr64(&req.n, sizeof(req), FRA_TUN_ID, tun_id);
                } else if (matches(*argv, "table") == 0 ||
                           strcmp(*argv, "lookup") == 0) {
                        NEXT_ARG();