From patchwork Mon Apr 16 20:41:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 898929 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="P6otEZD5"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40Q0fk4HWBz9s0R for ; Tue, 17 Apr 2018 06:41:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751398AbeDPUlq (ORCPT ); Mon, 16 Apr 2018 16:41:46 -0400 Received: from mail-pl0-f66.google.com ([209.85.160.66]:37104 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750989AbeDPUlo (ORCPT ); Mon, 16 Apr 2018 16:41:44 -0400 Received: by mail-pl0-f66.google.com with SMTP id f7-v6so3639966plr.4 for ; Mon, 16 Apr 2018 13:41:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=PuowzuRn/bnoL+19UfI/h7WsBar7rpR8TvYCnUsdOfU=; b=P6otEZD5rls/aK2qirCMPDys/GFvGEdrGuXNFn/VgXpe0RLBCyGN1HU8dpIavKPCpm kJ/iHJ2EJr6Qn6YIoeDW5uo7tf3GnoEMtZUjfpSXXvysLX9q1pKT+7G2VkzPjPNOFbDh PmffQy61Cr4wpJsqTP/A8cvkPb5kJJ5ltaN3g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=PuowzuRn/bnoL+19UfI/h7WsBar7rpR8TvYCnUsdOfU=; b=ggNN1YlTwyKvCc+E1tIwRN97e+Y7aNhUPcBiGvIX1tnm8v4jWWwbYhoyd0h434e/AS Epmon81zmXtXTqWptX0PE/spFOxhJwJjxyoA45r1Em09L7k/AGuEchWohyV1OOuiwvMW b37hQa4R3c/nUtb3ZQgOA9Y2iBGFcF+5hwN+hYzRrXWFj40IhzJpLzEpDcRUxgFLSvkA opzf+41Mo9T1Y0ScsJaY7P8eVM39QidFzLL1RIwpeZX6948w4KE2wWYCV1XdThyak2GQ 4oB4L7/LQYFJzbR8xKkglyEORd3zNSzrEPiWBBupevKQvpHYkrdnmrSgnhtL80wfm6tL 1PeA== X-Gm-Message-State: ALQs6tCOMIHJKpCyX1GNWeJxJhAbGXH8e9mnUqEuTrd+FzeYgnb65MUj 3OXxHerSQ1W+Mdx8ZIdV/uH/cw== X-Google-Smtp-Source: AIpwx4/fXhCb4o4J543nnH4nps/wmjA4xwuLruAF+HkCETSwWAuIwh8NTysTWRzbOGr3oq5VGYQopA== X-Received: by 2002:a17:902:780d:: with SMTP id p13-v6mr16792330pll.281.1523911304160; Mon, 16 Apr 2018 13:41:44 -0700 (PDT) Received: from monster-08.mvlab.cumulusnetworks.com. (fw.cumulusnetworks.com. [216.129.126.126]) by smtp.googlemail.com with ESMTPSA id v186sm24030774pfb.182.2018.04.16.13.41.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Apr 2018 13:41:43 -0700 (PDT) From: Roopa Prabhu X-Google-Original-From: Roopa Prabhu To: davem@davemloft.net Cc: netdev@vger.kernel.org, dsa@cumulusnetworks.com Subject: [PATCH net-next 1/5] fib_rules: move common handling of newrule delrule msgs into fib_nl2rule Date: Mon, 16 Apr 2018 13:41:34 -0700 Message-Id: <1523911298-8965-2-git-send-email-roopa@cumulusnetworks.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> References: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu This reduces code duplication in the fib rule add and del paths. Get rid of validate_rulemsg. This became obvious when adding duplicate extack support in fib newrule/delrule error paths. Signed-off-by: Roopa Prabhu --- net/core/fib_rules.c | 436 +++++++++++++++++++++++---------------------------- 1 file changed, 192 insertions(+), 244 deletions(-) diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 33958f8..6780110 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -387,206 +387,185 @@ unsigned int fib_rules_seq_read(struct net *net, int family) } EXPORT_SYMBOL_GPL(fib_rules_seq_read); -static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, - struct fib_rules_ops *ops) -{ - int err = -EINVAL; - - if (frh->src_len) - if (tb[FRA_SRC] == NULL || - frh->src_len > (ops->addr_size * 8) || - nla_len(tb[FRA_SRC]) != ops->addr_size) - goto errout; - - if (frh->dst_len) - if (tb[FRA_DST] == NULL || - frh->dst_len > (ops->addr_size * 8) || - nla_len(tb[FRA_DST]) != ops->addr_size) - goto errout; - - err = 0; -errout: - return err; -} - -static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh, - struct nlattr **tb, struct fib_rule *rule) +static struct fib_rule *rule_find(struct fib_rules_ops *ops, + struct fib_rule_hdr *frh, + struct nlattr **tb, + struct fib_rule *rule, + bool user_priority) { struct fib_rule *r; list_for_each_entry(r, &ops->rules_list, list) { - if (r->action != rule->action) + if (rule->action && r->action != rule->action) continue; - if (r->table != rule->table) + if (rule->table && r->table != rule->table) continue; - if (r->pref != rule->pref) + if (user_priority && r->pref != rule->pref) continue; - if (memcmp(r->iifname, rule->iifname, IFNAMSIZ)) + if (rule->iifname[0] && + memcmp(r->iifname, rule->iifname, IFNAMSIZ)) continue; - if (memcmp(r->oifname, rule->oifname, IFNAMSIZ)) + if (rule->oifname[0] && + memcmp(r->oifname, rule->oifname, IFNAMSIZ)) continue; - if (r->mark != rule->mark) + if (rule->mark && r->mark != rule->mark) continue; - if (r->mark_mask != rule->mark_mask) + if (rule->mark_mask && r->mark_mask != rule->mark_mask) continue; - if (r->tun_id != rule->tun_id) + if (rule->tun_id && r->tun_id != rule->tun_id) continue; if (r->fr_net != rule->fr_net) continue; - if (r->l3mdev != rule->l3mdev) + if (rule->l3mdev && r->l3mdev != rule->l3mdev) continue; - if (!uid_eq(r->uid_range.start, rule->uid_range.start) || - !uid_eq(r->uid_range.end, rule->uid_range.end)) + if (uid_range_set(&rule->uid_range) && + (!uid_eq(r->uid_range.start, rule->uid_range.start) || + !uid_eq(r->uid_range.end, rule->uid_range.end))) continue; - if (r->ip_proto != rule->ip_proto) + if (rule->ip_proto && r->ip_proto != rule->ip_proto) continue; - if (!fib_rule_port_range_compare(&r->sport_range, + if (fib_rule_port_range_set(&rule->sport_range) && + !fib_rule_port_range_compare(&r->sport_range, &rule->sport_range)) continue; - if (!fib_rule_port_range_compare(&r->dport_range, + if (fib_rule_port_range_set(&rule->dport_range) && + !fib_rule_port_range_compare(&r->dport_range, &rule->dport_range)) continue; if (!ops->compare(r, frh, tb)) continue; - return 1; + return r; } - return 0; + + return NULL; } -int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, - struct netlink_ext_ack *extack) +static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, + struct netlink_ext_ack *extack, + struct fib_rules_ops *ops, + struct nlattr *tb[], + struct fib_rule **rule, + bool *user_priority) { struct net *net = sock_net(skb->sk); struct fib_rule_hdr *frh = nlmsg_data(nlh); - struct fib_rules_ops *ops = NULL; - struct fib_rule *rule, *r, *last = NULL; - struct nlattr *tb[FRA_MAX+1]; - int err = -EINVAL, unresolved = 0; - - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) - goto errout; - - ops = lookup_rules_ops(net, frh->family); - if (ops == NULL) { - err = -EAFNOSUPPORT; - goto errout; - } + struct fib_rule *nlrule = NULL; + int err = -EINVAL; - err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); - if (err < 0) - goto errout; + if (frh->src_len) + if (!tb[FRA_SRC] || + frh->src_len > (ops->addr_size * 8) || + nla_len(tb[FRA_SRC]) != ops->addr_size) + goto errout; - err = validate_rulemsg(frh, tb, ops); - if (err < 0) - goto errout; + if (frh->dst_len) + if (!tb[FRA_DST] || + frh->dst_len > (ops->addr_size * 8) || + nla_len(tb[FRA_DST]) != ops->addr_size) + goto errout; - rule = kzalloc(ops->rule_size, GFP_KERNEL); - if (rule == NULL) { + nlrule = kzalloc(ops->rule_size, GFP_KERNEL); + if (!nlrule) { err = -ENOMEM; goto errout; } - refcount_set(&rule->refcnt, 1); - rule->fr_net = net; + refcount_set(&nlrule->refcnt, 1); + nlrule->fr_net = net; - rule->pref = tb[FRA_PRIORITY] ? nla_get_u32(tb[FRA_PRIORITY]) - : fib_default_rule_pref(ops); + if (tb[FRA_PRIORITY]) { + nlrule->pref = nla_get_u32(tb[FRA_PRIORITY]); + *user_priority = true; + } else { + nlrule->pref = fib_default_rule_pref(ops); + } - rule->proto = tb[FRA_PROTOCOL] ? + nlrule->proto = tb[FRA_PROTOCOL] ? nla_get_u8(tb[FRA_PROTOCOL]) : RTPROT_UNSPEC; if (tb[FRA_IIFNAME]) { struct net_device *dev; - rule->iifindex = -1; - nla_strlcpy(rule->iifname, tb[FRA_IIFNAME], IFNAMSIZ); - dev = __dev_get_by_name(net, rule->iifname); + nlrule->iifindex = -1; + nla_strlcpy(nlrule->iifname, tb[FRA_IIFNAME], IFNAMSIZ); + dev = __dev_get_by_name(net, nlrule->iifname); if (dev) - rule->iifindex = dev->ifindex; + nlrule->iifindex = dev->ifindex; } if (tb[FRA_OIFNAME]) { struct net_device *dev; - rule->oifindex = -1; - nla_strlcpy(rule->oifname, tb[FRA_OIFNAME], IFNAMSIZ); - dev = __dev_get_by_name(net, rule->oifname); + nlrule->oifindex = -1; + nla_strlcpy(nlrule->oifname, tb[FRA_OIFNAME], IFNAMSIZ); + dev = __dev_get_by_name(net, nlrule->oifname); if (dev) - rule->oifindex = dev->ifindex; + nlrule->oifindex = dev->ifindex; } if (tb[FRA_FWMARK]) { - rule->mark = nla_get_u32(tb[FRA_FWMARK]); - if (rule->mark) + nlrule->mark = nla_get_u32(tb[FRA_FWMARK]); + if (nlrule->mark) /* compatibility: if the mark value is non-zero all bits * are compared unless a mask is explicitly specified. */ - rule->mark_mask = 0xFFFFFFFF; + nlrule->mark_mask = 0xFFFFFFFF; } if (tb[FRA_FWMASK]) - rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]); + nlrule->mark_mask = nla_get_u32(tb[FRA_FWMASK]); if (tb[FRA_TUN_ID]) - rule->tun_id = nla_get_be64(tb[FRA_TUN_ID]); + nlrule->tun_id = nla_get_be64(tb[FRA_TUN_ID]); err = -EINVAL; if (tb[FRA_L3MDEV]) { #ifdef CONFIG_NET_L3_MASTER_DEV - rule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); - if (rule->l3mdev != 1) + nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); + if (nlrule->l3mdev != 1) #endif goto errout_free; } - rule->action = frh->action; - rule->flags = frh->flags; - rule->table = frh_get_table(frh, tb); + nlrule->action = frh->action; + nlrule->flags = frh->flags; + nlrule->table = frh_get_table(frh, tb); if (tb[FRA_SUPPRESS_PREFIXLEN]) - rule->suppress_prefixlen = nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]); + nlrule->suppress_prefixlen = nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]); else - rule->suppress_prefixlen = -1; + nlrule->suppress_prefixlen = -1; if (tb[FRA_SUPPRESS_IFGROUP]) - rule->suppress_ifgroup = nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]); + nlrule->suppress_ifgroup = nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]); else - rule->suppress_ifgroup = -1; + nlrule->suppress_ifgroup = -1; if (tb[FRA_GOTO]) { - if (rule->action != FR_ACT_GOTO) + if (nlrule->action != FR_ACT_GOTO) goto errout_free; - rule->target = nla_get_u32(tb[FRA_GOTO]); + nlrule->target = nla_get_u32(tb[FRA_GOTO]); /* Backward jumps are prohibited to avoid endless loops */ - if (rule->target <= rule->pref) + if (nlrule->target <= nlrule->pref) goto errout_free; - - list_for_each_entry(r, &ops->rules_list, list) { - if (r->pref == rule->target) { - RCU_INIT_POINTER(rule->ctarget, r); - break; - } - } - - if (rcu_dereference_protected(rule->ctarget, 1) == NULL) - unresolved = 1; - } else if (rule->action == FR_ACT_GOTO) + } else if (nlrule->action == FR_ACT_GOTO) { goto errout_free; + } - if (rule->l3mdev && rule->table) + if (nlrule->l3mdev && nlrule->table) goto errout_free; if (tb[FRA_UID_RANGE]) { @@ -595,34 +574,72 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout_free; } - rule->uid_range = nla_get_kuid_range(tb); + nlrule->uid_range = nla_get_kuid_range(tb); - if (!uid_range_set(&rule->uid_range) || - !uid_lte(rule->uid_range.start, rule->uid_range.end)) + if (!uid_range_set(&nlrule->uid_range) || + !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) goto errout_free; } else { - rule->uid_range = fib_kuid_range_unset; + nlrule->uid_range = fib_kuid_range_unset; } if (tb[FRA_IP_PROTO]) - rule->ip_proto = nla_get_u8(tb[FRA_IP_PROTO]); + nlrule->ip_proto = nla_get_u8(tb[FRA_IP_PROTO]); if (tb[FRA_SPORT_RANGE]) { err = nla_get_port_range(tb[FRA_SPORT_RANGE], - &rule->sport_range); + &nlrule->sport_range); if (err) goto errout_free; } if (tb[FRA_DPORT_RANGE]) { err = nla_get_port_range(tb[FRA_DPORT_RANGE], - &rule->dport_range); + &nlrule->dport_range); if (err) goto errout_free; } + *rule = nlrule; + + return 0; + +errout_free: + kfree(nlrule); +errout: + return err; +} + +int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, + struct netlink_ext_ack *extack) +{ + struct net *net = sock_net(skb->sk); + struct fib_rule_hdr *frh = nlmsg_data(nlh); + struct fib_rules_ops *ops = NULL; + struct fib_rule *rule = NULL, *r, *last = NULL; + struct nlattr *tb[FRA_MAX + 1]; + int err = -EINVAL, unresolved = 0; + bool user_priority = false; + + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) + goto errout; + + ops = lookup_rules_ops(net, frh->family); + if (!ops) { + err = -EAFNOSUPPORT; + goto errout; + } + + err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); + if (err < 0) + goto errout; + + err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority); + if (err) + goto errout; + if ((nlh->nlmsg_flags & NLM_F_EXCL) && - rule_exists(ops, frh, tb, rule)) { + rule_find(ops, frh, tb, rule, user_priority)) { err = -EEXIST; goto errout_free; } @@ -637,6 +654,16 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout_free; list_for_each_entry(r, &ops->rules_list, list) { + if (r->pref == rule->target) { + RCU_INIT_POINTER(rule->ctarget, r); + break; + } + } + + if (rcu_dereference_protected(rule->ctarget, 1) == NULL) + unresolved = 1; + + list_for_each_entry(r, &ops->rules_list, list) { if (r->pref > rule->pref) break; last = r; @@ -690,13 +717,11 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct fib_rule_hdr *frh = nlmsg_data(nlh); - struct fib_rule_port_range sprange = {0, 0}; - struct fib_rule_port_range dprange = {0, 0}; struct fib_rules_ops *ops = NULL; - struct fib_rule *rule, *r; + struct fib_rule *rule = NULL, *r, *nlrule = NULL; struct nlattr *tb[FRA_MAX+1]; - struct fib_kuid_range range; int err = -EINVAL; + bool user_priority = false; if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) goto errout; @@ -711,150 +736,73 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, if (err < 0) goto errout; - err = validate_rulemsg(frh, tb, ops); - if (err < 0) + err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority); + if (err) goto errout; - if (tb[FRA_UID_RANGE]) { - range = nla_get_kuid_range(tb); - if (!uid_range_set(&range)) { - err = -EINVAL; - goto errout; - } - } else { - range = fib_kuid_range_unset; + rule = rule_find(ops, frh, tb, nlrule, user_priority); + if (!rule) { + err = -ENOENT; + goto errout; } - if (tb[FRA_SPORT_RANGE]) { - err = nla_get_port_range(tb[FRA_SPORT_RANGE], - &sprange); - if (err) - goto errout; + if (rule->flags & FIB_RULE_PERMANENT) { + err = -EPERM; + goto errout; } - if (tb[FRA_DPORT_RANGE]) { - err = nla_get_port_range(tb[FRA_DPORT_RANGE], - &dprange); + if (ops->delete) { + err = ops->delete(rule); if (err) goto errout; } - list_for_each_entry(rule, &ops->rules_list, list) { - if (tb[FRA_PROTOCOL] && - (rule->proto != nla_get_u8(tb[FRA_PROTOCOL]))) - continue; - - if (frh->action && (frh->action != rule->action)) - continue; - - if (frh_get_table(frh, tb) && - (frh_get_table(frh, tb) != rule->table)) - continue; - - if (tb[FRA_PRIORITY] && - (rule->pref != nla_get_u32(tb[FRA_PRIORITY]))) - continue; - - if (tb[FRA_IIFNAME] && - nla_strcmp(tb[FRA_IIFNAME], rule->iifname)) - continue; - - if (tb[FRA_OIFNAME] && - nla_strcmp(tb[FRA_OIFNAME], rule->oifname)) - continue; - - if (tb[FRA_FWMARK] && - (rule->mark != nla_get_u32(tb[FRA_FWMARK]))) - continue; - - if (tb[FRA_FWMASK] && - (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK]))) - continue; - - if (tb[FRA_TUN_ID] && - (rule->tun_id != nla_get_be64(tb[FRA_TUN_ID]))) - continue; - - if (tb[FRA_L3MDEV] && - (rule->l3mdev != nla_get_u8(tb[FRA_L3MDEV]))) - continue; - - if (uid_range_set(&range) && - (!uid_eq(rule->uid_range.start, range.start) || - !uid_eq(rule->uid_range.end, range.end))) - continue; - - if (tb[FRA_IP_PROTO] && - (rule->ip_proto != nla_get_u8(tb[FRA_IP_PROTO]))) - continue; - - if (fib_rule_port_range_set(&sprange) && - !fib_rule_port_range_compare(&rule->sport_range, &sprange)) - continue; - - if (fib_rule_port_range_set(&dprange) && - !fib_rule_port_range_compare(&rule->dport_range, &dprange)) - continue; - - if (!ops->compare(rule, frh, tb)) - continue; - - if (rule->flags & FIB_RULE_PERMANENT) { - err = -EPERM; - goto errout; - } - - if (ops->delete) { - err = ops->delete(rule); - if (err) - goto errout; - } - - if (rule->tun_id) - ip_tunnel_unneed_metadata(); + if (rule->tun_id) + ip_tunnel_unneed_metadata(); - list_del_rcu(&rule->list); + list_del_rcu(&rule->list); - if (rule->action == FR_ACT_GOTO) { - ops->nr_goto_rules--; - if (rtnl_dereference(rule->ctarget) == NULL) - ops->unresolved_rules--; - } + if (rule->action == FR_ACT_GOTO) { + ops->nr_goto_rules--; + if (rtnl_dereference(rule->ctarget) == NULL) + ops->unresolved_rules--; + } - /* - * Check if this rule is a target to any of them. If so, - * adjust to the next one with the same preference or - * disable them. As this operation is eventually very - * expensive, it is only performed if goto rules, except - * current if it is goto rule, have actually been added. - */ - if (ops->nr_goto_rules > 0) { - struct fib_rule *n; - - n = list_next_entry(rule, list); - if (&n->list == &ops->rules_list || n->pref != rule->pref) - n = NULL; - list_for_each_entry(r, &ops->rules_list, list) { - if (rtnl_dereference(r->ctarget) != rule) - continue; - rcu_assign_pointer(r->ctarget, n); - if (!n) - ops->unresolved_rules++; - } + /* + * Check if this rule is a target to any of them. If so, + * adjust to the next one with the same preference or + * disable them. As this operation is eventually very + * expensive, it is only performed if goto rules, except + * current if it is goto rule, have actually been added. + */ + if (ops->nr_goto_rules > 0) { + struct fib_rule *n; + + n = list_next_entry(rule, list); + if (&n->list == &ops->rules_list || n->pref != rule->pref) + n = NULL; + list_for_each_entry(r, &ops->rules_list, list) { + if (rtnl_dereference(r->ctarget) != rule) + continue; + rcu_assign_pointer(r->ctarget, n); + if (!n) + ops->unresolved_rules++; } - - call_fib_rule_notifiers(net, FIB_EVENT_RULE_DEL, rule, ops, - NULL); - notify_rule_change(RTM_DELRULE, rule, ops, nlh, - NETLINK_CB(skb).portid); - fib_rule_put(rule); - flush_route_cache(ops); - rules_ops_put(ops); - return 0; } - err = -ENOENT; + call_fib_rule_notifiers(net, FIB_EVENT_RULE_DEL, rule, ops, + NULL); + notify_rule_change(RTM_DELRULE, rule, ops, nlh, + NETLINK_CB(skb).portid); + fib_rule_put(rule); + flush_route_cache(ops); + rules_ops_put(ops); + kfree(nlrule); + return 0; + errout: + if (nlrule) + kfree(nlrule); rules_ops_put(ops); return err; } From patchwork Mon Apr 16 20:41:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 898934 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="b47871Ae"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40Q0g42gtvz9s0R for ; Tue, 17 Apr 2018 06:42:08 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752096AbeDPUmG (ORCPT ); Mon, 16 Apr 2018 16:42:06 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:45437 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751169AbeDPUlq (ORCPT ); Mon, 16 Apr 2018 16:41:46 -0400 Received: by mail-pl0-f68.google.com with SMTP id k9-v6so5908141pll.12 for ; Mon, 16 Apr 2018 13:41:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=n1Zv5t9FE/++D6xFhmPpjnoltTgkgc1W+9nmwj+giCg=; b=b47871AeTUL17k66JJTbJNuEX+8fv6bZpXWvAKK3SlG/m0gHTahBBceG/bWhB64C9Y 8YNQEnLmQtputST5QSxZlcCk6SGG4wtIfOuw9j4oiWiO2QxSwMpfNVHegdYUEkCxHkmA suisGR8svGiLCCwgj8MGEWp5l4YjK4k8JjHdc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=n1Zv5t9FE/++D6xFhmPpjnoltTgkgc1W+9nmwj+giCg=; b=j2r9NjtDTWRvak82DOcANPO+o/0WJHgyUa7KcMboZgwgc9JBtg0KdUQXWx9G80sJlQ d4HrvYmdl1yEWYxEyL72U3Wfaa2pVAEgTljbNkKCuVfaJsnFoR7ebBCMZnAjfA9v0vRH TjVr1fhHeezbQoHtBLPiPKxhFMpiewkBSSI0Vsf0gza6WhRdZA7vhFljy6ARgQ0ozwCz CE7guN/iH9AN9YK9ATPMZ6kpEgzy/OB8jHP4UVEOD1RGIdZQfEYGDJmuStixv5LN/LVW ujRXgdkE2+9BH5mFsROJa9BNfStGiya9CdA7X2b+zzQRsRciXsibjNlNKLSNa1eWHyZM LJoA== X-Gm-Message-State: ALQs6tCTtkq/qYCUsi9XMlqyEWZBvYyao09yUnlge9sGkvNAI1CAFTRH E6ljG5/Dvq1zFWdST3Hobw+gGQ== X-Google-Smtp-Source: AIpwx4/IVPZzV6XfAtuiOvrjp16FJyH6Y5fLuoBGo6ldP7dzd8Qx7trw/QBtQNz5DOrFD+kfp9Bwtg== X-Received: by 2002:a17:902:6887:: with SMTP id i7-v6mr8064217plk.269.1523911305233; Mon, 16 Apr 2018 13:41:45 -0700 (PDT) Received: from monster-08.mvlab.cumulusnetworks.com. (fw.cumulusnetworks.com. [216.129.126.126]) by smtp.googlemail.com with ESMTPSA id v186sm24030774pfb.182.2018.04.16.13.41.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Apr 2018 13:41:44 -0700 (PDT) From: Roopa Prabhu X-Google-Original-From: Roopa Prabhu To: davem@davemloft.net Cc: netdev@vger.kernel.org, dsa@cumulusnetworks.com Subject: [PATCH net-next 2/5] net: fib_rules: add extack support Date: Mon, 16 Apr 2018 13:41:35 -0700 Message-Id: <1523911298-8965-3-git-send-email-roopa@cumulusnetworks.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> References: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu Signed-off-by: Roopa Prabhu --- include/net/fib_rules.h | 3 ++- net/core/fib_rules.c | 55 +++++++++++++++++++++++++++++++++++++------------ net/decnet/dn_rules.c | 7 +++++-- net/ipv4/fib_rules.c | 7 +++++-- net/ipv4/ipmr.c | 3 ++- net/ipv6/fib6_rules.c | 7 +++++-- net/ipv6/ip6mr.c | 3 ++- 7 files changed, 63 insertions(+), 22 deletions(-) diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index e5cfcfc..b473df5 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -75,7 +75,8 @@ struct fib_rules_ops { int (*configure)(struct fib_rule *, struct sk_buff *, struct fib_rule_hdr *, - struct nlattr **); + struct nlattr **, + struct netlink_ext_ack *); int (*delete)(struct fib_rule *); int (*compare)(struct fib_rule *, struct fib_rule_hdr *, diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 6780110..ebd9351 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -469,14 +469,18 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, if (frh->src_len) if (!tb[FRA_SRC] || frh->src_len > (ops->addr_size * 8) || - nla_len(tb[FRA_SRC]) != ops->addr_size) + nla_len(tb[FRA_SRC]) != ops->addr_size) { + NL_SET_ERR_MSG(extack, "Invalid source address"); goto errout; + } if (frh->dst_len) if (!tb[FRA_DST] || frh->dst_len > (ops->addr_size * 8) || - nla_len(tb[FRA_DST]) != ops->addr_size) + nla_len(tb[FRA_DST]) != ops->addr_size) { + NL_SET_ERR_MSG(extack, "Invalid dst address"); goto errout; + } nlrule = kzalloc(ops->rule_size, GFP_KERNEL); if (!nlrule) { @@ -537,6 +541,7 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); if (nlrule->l3mdev != 1) #endif + NL_SET_ERR_MSG(extack, "Invalid l3mdev"); goto errout_free; } @@ -554,31 +559,41 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, nlrule->suppress_ifgroup = -1; if (tb[FRA_GOTO]) { - if (nlrule->action != FR_ACT_GOTO) + if (nlrule->action != FR_ACT_GOTO) { + NL_SET_ERR_MSG(extack, "Unexpected goto"); goto errout_free; + } nlrule->target = nla_get_u32(tb[FRA_GOTO]); /* Backward jumps are prohibited to avoid endless loops */ - if (nlrule->target <= nlrule->pref) + if (nlrule->target <= nlrule->pref) { + NL_SET_ERR_MSG(extack, "Backward goto not supported"); goto errout_free; + } } else if (nlrule->action == FR_ACT_GOTO) { + NL_SET_ERR_MSG(extack, "Missing goto target for action goto"); goto errout_free; } - if (nlrule->l3mdev && nlrule->table) + if (nlrule->l3mdev && nlrule->table) { + NL_SET_ERR_MSG(extack, "l3mdev and table are mutually exclusive"); goto errout_free; + } if (tb[FRA_UID_RANGE]) { if (current_user_ns() != net->user_ns) { err = -EPERM; + NL_SET_ERR_MSG(extack, "No permission to set uid"); goto errout_free; } nlrule->uid_range = nla_get_kuid_range(tb); if (!uid_range_set(&nlrule->uid_range) || - !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) + !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) { + NL_SET_ERR_MSG(extack, "Invalid uid range"); goto errout_free; + } } else { nlrule->uid_range = fib_kuid_range_unset; } @@ -589,15 +604,19 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, if (tb[FRA_SPORT_RANGE]) { err = nla_get_port_range(tb[FRA_SPORT_RANGE], &nlrule->sport_range); - if (err) + if (err) { + NL_SET_ERR_MSG(extack, "Invalid sport range"); goto errout_free; + } } if (tb[FRA_DPORT_RANGE]) { err = nla_get_port_range(tb[FRA_DPORT_RANGE], &nlrule->dport_range); - if (err) + if (err) { + NL_SET_ERR_MSG(extack, "Invalid dport range"); goto errout_free; + } } *rule = nlrule; @@ -621,18 +640,23 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, int err = -EINVAL, unresolved = 0; bool user_priority = false; - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { + NL_SET_ERR_MSG(extack, "Invalid msg length"); goto errout; + } ops = lookup_rules_ops(net, frh->family); if (!ops) { err = -EAFNOSUPPORT; + NL_SET_ERR_MSG(extack, "Rule family not supported"); goto errout; } err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); - if (err < 0) + if (err < 0) { + NL_SET_ERR_MSG(extack, "Error parsing msg"); goto errout; + } err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority); if (err) @@ -644,7 +668,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout_free; } - err = ops->configure(rule, skb, frh, tb); + err = ops->configure(rule, skb, frh, tb, extack); if (err < 0) goto errout_free; @@ -723,18 +747,23 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, int err = -EINVAL; bool user_priority = false; - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { + NL_SET_ERR_MSG(extack, "Invalid msg length"); goto errout; + } ops = lookup_rules_ops(net, frh->family); if (ops == NULL) { err = -EAFNOSUPPORT; + NL_SET_ERR_MSG(extack, "Rule family not supported"); goto errout; } err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); - if (err < 0) + if (err < 0) { + NL_SET_ERR_MSG(extack, "Error parsing msg"); goto errout; + } err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority); if (err) diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index c795c3f..7223669 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -121,13 +121,16 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, struct fib_rule_hdr *frh, - struct nlattr **tb) + struct nlattr **tb, + struct netlink_ext_ack *extack) { int err = -EINVAL; struct dn_fib_rule *r = (struct dn_fib_rule *)rule; - if (frh->tos) + if (frh->tos) { + NL_SET_ERR_MSG(extack, "Invalid tos value"); goto errout; + } if (rule->table == RT_TABLE_UNSPEC) { if (rule->action == FR_ACT_TO_TBL) { diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 737d11b..f8eb78d 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -213,14 +213,17 @@ static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = { static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, struct fib_rule_hdr *frh, - struct nlattr **tb) + struct nlattr **tb, + struct netlink_ext_ack *extack) { struct net *net = sock_net(skb->sk); int err = -EINVAL; struct fib4_rule *rule4 = (struct fib4_rule *) rule; - if (frh->tos & ~IPTOS_TOS_MASK) + if (frh->tos & ~IPTOS_TOS_MASK) { + NL_SET_ERR_MSG(extack, "Invalid tos"); goto errout; + } /* split local/main if they are not already split */ err = fib_unmerge(net); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 2fb4de3..38e092e 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -201,7 +201,8 @@ static const struct nla_policy ipmr_rule_policy[FRA_MAX + 1] = { }; static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct fib_rule_hdr *frh, struct nlattr **tb) + struct fib_rule_hdr *frh, struct nlattr **tb, + struct netlink_ext_ack *extack) { return 0; } diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index df113c7..6547fc6 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -245,15 +245,18 @@ static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = { static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, struct fib_rule_hdr *frh, - struct nlattr **tb) + struct nlattr **tb, + struct netlink_ext_ack *extack) { int err = -EINVAL; struct net *net = sock_net(skb->sk); struct fib6_rule *rule6 = (struct fib6_rule *) rule; if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) { - if (rule->table == RT6_TABLE_UNSPEC) + if (rule->table == RT6_TABLE_UNSPEC) { + NL_SET_ERR_MSG(extack, "Invalid table"); goto errout; + } if (fib6_new_table(net, rule->table) == NULL) { err = -ENOBUFS; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 298fd8b..20a419e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -180,7 +180,8 @@ static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = { }; static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct fib_rule_hdr *frh, struct nlattr **tb) + struct fib_rule_hdr *frh, struct nlattr **tb, + struct netlink_ext_ack *extack) { return 0; } From patchwork Mon Apr 16 20:41:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 898930 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="WhJ19tbq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40Q0fm1hl2z9s0R for ; Tue, 17 Apr 2018 06:41:52 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751857AbeDPUlt (ORCPT ); Mon, 16 Apr 2018 16:41:49 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:35559 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751210AbeDPUlq (ORCPT ); Mon, 16 Apr 2018 16:41:46 -0400 Received: by mail-pl0-f68.google.com with SMTP id 61-v6so10691764plb.2 for ; Mon, 16 Apr 2018 13:41:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QE9GVmoOeirJowFgkEYqoj60nLGcqtF+tL0lr7FPx7g=; b=WhJ19tbqc3E1cXmo2p1ymCNvWfzVxCt32kLMapeXf90RUCpc2RuoQeZiQrZvVkA3O5 giS9BGE9lPbGr3RXLWgHSMlCA03tWaHIVeF6T8/wUYUZ5ZONysHjnWTl0eGFvYcH+A1G 33nlCafriNuFIX6lcxIeHYMqtX1U051cL3/EQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QE9GVmoOeirJowFgkEYqoj60nLGcqtF+tL0lr7FPx7g=; b=AbmTWhSFcH+P7GhSHh4CB8DD0zpC9C8aZcjLsnpXpIXr6oLuRh33DUSQ8xqvoI5zk6 bcNv+p1+ZHlNnO6ENGX37bMQZCmzzBjPTgvynCi8K66drvRe/EwF/g91lXYXQgvxVITi w2MG5cIaOGoMNYLXJ5Vut4ec0HRObY9XcK77eQ1eaCeCdHPRU9WnS6M8W5FyMbjARn/I 2aLSVbCM4jpReawdBPfiAFMtM+G3do9jA94cyBv/DGh4EOBZkz7C7kocH+h9/0BftbaM JL5M9i8zpPbDdz/+iAbweaM+ufAlreKsHESn0+WqcY4zlY2eFqW47G3yOD3nUUi59Q+8 /GMQ== X-Gm-Message-State: ALQs6tAzav7WcI/QgudbSCwwm9VPgtIuQ5xOVSeWUSn9DDaBbpON0dDj ZDjf6FhcTJ4rpT6XXhEH1DCJEw== X-Google-Smtp-Source: AIpwx48aa06SW8vdmlLu+Jc56HKFYbxCGIpS4fsJ4FpeK1ak/19bv3mzZQHADE/gguLvKL2hD4UUnA== X-Received: by 2002:a17:902:6709:: with SMTP id f9-v6mr16599621plk.159.1523911306188; Mon, 16 Apr 2018 13:41:46 -0700 (PDT) Received: from monster-08.mvlab.cumulusnetworks.com. (fw.cumulusnetworks.com. [216.129.126.126]) by smtp.googlemail.com with ESMTPSA id v186sm24030774pfb.182.2018.04.16.13.41.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Apr 2018 13:41:45 -0700 (PDT) From: Roopa Prabhu X-Google-Original-From: Roopa Prabhu To: davem@davemloft.net Cc: netdev@vger.kernel.org, dsa@cumulusnetworks.com Subject: [PATCH net-next 3/5] ipv4: support sport, dport and ip protocol in RTM_GETROUTE Date: Mon, 16 Apr 2018 13:41:36 -0700 Message-Id: <1523911298-8965-4-git-send-email-roopa@cumulusnetworks.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> References: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu This is a followup to fib rules sport, dport and ip proto match support. Having them supported in getroute makes it easier to test fib rule lookups. Used by fib rule self tests. Signed-off-by: Roopa Prabhu --- include/uapi/linux/rtnetlink.h | 3 ++ net/ipv4/route.c | 75 +++++++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 9b15005..7947252 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -327,6 +327,9 @@ enum rtattr_type_t { RTA_PAD, RTA_UID, RTA_TTL_PROPAGATE, + RTA_SPORT, + RTA_DPORT, + RTA_IP_PROTO, __RTA_MAX }; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ccb25d8..ae55711 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2663,6 +2663,18 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, from_kuid_munged(current_user_ns(), fl4->flowi4_uid))) goto nla_put_failure; + if (fl4->fl4_sport && + nla_put_u16(skb, RTA_SPORT, ntohs(fl4->fl4_sport))) + goto nla_put_failure; + + if (fl4->fl4_dport && + nla_put_u16(skb, RTA_DPORT, ntohs(fl4->fl4_dport))) + goto nla_put_failure; + + if (fl4->flowi4_proto && + nla_put_u8(skb, RTA_IP_PROTO, fl4->flowi4_proto)) + goto nla_put_failure; + error = rt->dst.error; if (rt_is_input_route(rt)) { @@ -2695,35 +2707,48 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, return -EMSGSIZE; } +static int nla_get_port(struct nlattr *attr, __be16 *port) +{ + int p = nla_get_u16(attr); + + if (p <= 0 || p >= 0xffff) + return -EINVAL; + + *port = htons(p); + return 0; +} + static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) { struct net *net = sock_net(in_skb->sk); - struct rtmsg *rtm; struct nlattr *tb[RTA_MAX+1]; + u32 table_id = RT_TABLE_MAIN; + __be16 sport = 0, dport = 0; struct fib_result res = {}; struct rtable *rt = NULL; + struct sk_buff *skb; + struct rtmsg *rtm; struct flowi4 fl4; + u8 ip_proto = 0; __be32 dst = 0; __be32 src = 0; + kuid_t uid; u32 iif; int err; int mark; - struct sk_buff *skb; - u32 table_id = RT_TABLE_MAIN; - kuid_t uid; err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy, extack); if (err < 0) - goto errout; + return err; rtm = nlmsg_data(nlh); skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) { err = -ENOBUFS; - goto errout; + return err; } /* Reserve room for dummy headers, this skb can pass @@ -2740,6 +2765,20 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID])); else uid = (iif ? INVALID_UID : current_uid()); + if (tb[RTA_SPORT]) { + err = nla_get_port(tb[RTA_SPORT], &sport); + if (err) + goto errout_free; + } + + if (tb[RTA_DPORT]) { + err = nla_get_port(tb[RTA_DPORT], &dport); + if (err) + goto errout_free; + } + + if (tb[RTA_IP_PROTO]) + ip_proto = nla_get_u8(tb[RTA_IP_PROTO]); /* Bugfix: need to give ip_route_input enough of an IP header to * not gag. @@ -2757,6 +2796,12 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0; fl4.flowi4_mark = mark; fl4.flowi4_uid = uid; + if (sport) + fl4.fl4_sport = sport; + if (dport) + fl4.fl4_dport = dport; + if (ip_proto) + fl4.flowi4_proto = ip_proto; rcu_read_lock(); @@ -2766,7 +2811,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, dev = dev_get_by_index_rcu(net, iif); if (!dev) { err = -ENODEV; - goto errout_free; + goto errout_rcu; } skb->protocol = htons(ETH_P_IP); @@ -2789,7 +2834,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, } if (err) - goto errout_free; + goto errout_rcu; if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; @@ -2802,7 +2847,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, err = fib_props[res.type].error; if (!err) err = -EHOSTUNREACH; - goto errout_free; + goto errout_rcu; } err = fib_dump_info(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, RTM_NEWROUTE, table_id, @@ -2813,18 +2858,18 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq); } if (err < 0) - goto errout_free; + goto errout_rcu; rcu_read_unlock(); - err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); -errout: - return err; + return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); errout_free: - rcu_read_unlock(); kfree_skb(skb); - goto errout; + return err; +errout_rcu: + rcu_read_unlock(); + goto errout_free; } void ip_rt_multicast_event(struct in_device *in_dev) From patchwork Mon Apr 16 20:41:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 898932 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="bzWDl4v6"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40Q0fx0nQQz9s1B for ; Tue, 17 Apr 2018 06:42:01 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752040AbeDPUl7 (ORCPT ); Mon, 16 Apr 2018 16:41:59 -0400 Received: from mail-pl0-f66.google.com ([209.85.160.66]:45437 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750989AbeDPUls (ORCPT ); Mon, 16 Apr 2018 16:41:48 -0400 Received: by mail-pl0-f66.google.com with SMTP id k9-v6so5908173pll.12 for ; Mon, 16 Apr 2018 13:41:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6Rdq86er6Y/iYYCeMknNtD1QPDvT1418D91/Sd78/Eg=; b=bzWDl4v6khTxNs2fpjuNfyzaUhBbN0WVovSQTzqc4rbayiz+Nw0u78P54KsSPQotcW 05cQdbbGOgwS71vnSvE6csCkLUrdzKo1kNZ2RFSPqwKaj+7ASUN4//WPv9uLoesiGSdg VdhP4b8cBTwiLzGMACvR91fEfMIKwZKPW4Q8Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6Rdq86er6Y/iYYCeMknNtD1QPDvT1418D91/Sd78/Eg=; b=RxSrlM0ISyJOm6gA6MSxEAlaHyenjCEwHvOMOK4vvpO0zbU1/rT7YkXzW5sQ4c4JTe yf+FVXV39lE/tVZZRVSr+v3q/itcHj0Vt2KwnA/mGEVI7j1a3GR8qvyG4sEQy0C+k9hK X7wU3PhxiAQdxr68Vgb2AkuaY+eY8rSSqMCxzzNB5hPhUClNxO73hlPNvVyR3YTz6Qv1 kKk90fpOVVhu92DMvM6xqoQK5EZWxqLZexTnpjRtfhv6pQH29vecGRLI4fYRd8rOlaGE l7ffqVHfjPWxYCHMQ9zGBev0YEx/pKgXD7IPsyUmpYGo06mqC1nH2fJN9A6iobXvMR9l wfSA== X-Gm-Message-State: ALQs6tAuAhiC9l26MhcbxaRjWtWfvBx5FwS8LCtlT0/H9VQ5gxGNhMar mUWhcO9FbBo5ORSzkEg5OAfupQ== X-Google-Smtp-Source: AIpwx4+hRHoJzi09ir17KgDQuLtaLVsb1g40jc3HMI+e/ssHIAwXEglKT9V08zu4TFIVrEkVTXyo4g== X-Received: by 2002:a17:902:694a:: with SMTP id k10-v6mr16312060plt.161.1523911307070; Mon, 16 Apr 2018 13:41:47 -0700 (PDT) Received: from monster-08.mvlab.cumulusnetworks.com. (fw.cumulusnetworks.com. [216.129.126.126]) by smtp.googlemail.com with ESMTPSA id v186sm24030774pfb.182.2018.04.16.13.41.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Apr 2018 13:41:46 -0700 (PDT) From: Roopa Prabhu X-Google-Original-From: Roopa Prabhu To: davem@davemloft.net Cc: netdev@vger.kernel.org, dsa@cumulusnetworks.com Subject: [PATCH net-next 4/5] ipv6: support sport, dport and ip protocol in RTM_GETROUTE Date: Mon, 16 Apr 2018 13:41:37 -0700 Message-Id: <1523911298-8965-5-git-send-email-roopa@cumulusnetworks.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> References: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu This is a followup to fib6 rules sport, dport and ip proto match support. Having them supported in getroute makes it easier to test fib6 rule lookups. Used by fib6 rule self tests. Signed-off-by: Roopa Prabhu --- net/ipv6/route.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 49b954d..5086a80 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3986,6 +3986,9 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { [RTA_EXPIRES] = { .type = NLA_U32 }, [RTA_UID] = { .type = NLA_U32 }, [RTA_MARK] = { .type = NLA_U32 }, + [RTA_IP_PROTO] = { .type = NLA_U8 }, + [RTA_SPORT] = { .type = NLA_U16 }, + [RTA_DPORT] = { .type = NLA_U16 }, }; static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -4658,6 +4661,17 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) NLM_F_MULTI); } +static int nla_get_port(struct nlattr *attr, __be16 *port) +{ + int p = nla_get_u16(attr); + + if (p <= 0 || p >= 0xffff) + return -EINVAL; + + *port = htons(p); + return 0; +} + static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) { @@ -4711,6 +4725,21 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, else fl6.flowi6_uid = iif ? INVALID_UID : current_uid(); + if (tb[RTA_SPORT]) { + err = nla_get_port(tb[RTA_SPORT], &fl6.fl6_sport); + if (err) + goto errout; + } + + if (tb[RTA_DPORT]) { + err = nla_get_port(tb[RTA_DPORT], &fl6.fl6_dport); + if (err) + goto errout; + } + + if (tb[RTA_IP_PROTO]) + fl6.flowi6_proto = nla_get_u8(tb[RTA_IP_PROTO]); + if (iif) { struct net_device *dev; int flags = 0; From patchwork Mon Apr 16 20:41:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 898931 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="f7cBd3/O"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40Q0fp6G2Tz9s0R for ; Tue, 17 Apr 2018 06:41:54 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751893AbeDPUlx (ORCPT ); Mon, 16 Apr 2018 16:41:53 -0400 Received: from mail-pg0-f53.google.com ([74.125.83.53]:35457 "EHLO mail-pg0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751210AbeDPUlu (ORCPT ); Mon, 16 Apr 2018 16:41:50 -0400 Received: by mail-pg0-f53.google.com with SMTP id j3so4356001pgf.2 for ; Mon, 16 Apr 2018 13:41:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+lC/rF2D3I/ax+/biFdfe5o+tszzwAdpobuaCLQTPMY=; b=f7cBd3/Oq3y0djYG0ltfQrM+me5sXtl0mzln2TUm6OBoCdF3MHCh7+x0+ZgWSvHG4D qWoIgYrL1gg32JFv6PA90QuknHecwyJiRxH+4M/aVM+bIikJX37K11dIHIjFPvhY/5SN kL1AEC2d6vj/gTUAc7dAf+B3KmsoIIepAKaBs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+lC/rF2D3I/ax+/biFdfe5o+tszzwAdpobuaCLQTPMY=; b=C5TKykgqda3GpjPml+pAAdlj5Bp9hD+hQGinpxGSP18kdQvP+m4kbFvSAg4B9t6jH5 jcsLgXpeJkNTmDEd/Glu6huIUUZtSpqUGWf7/XPgH1Mlsa0lLSR6Gr+Cw20Y9+glLhvb ibGchw272teOQjc0ALB3qp6feXkZTmu8w5KR9Y5naixAsN3Gjr5Elw7Ukhs9zE9bzD9z rLm1J6iGXrcHGpyY3bNKttjg4kAEnnyyQOJ4wX6FRvMqbKhNU2tKnPXlfQekyu92JBsv Jv0ZlDdHayMhWMYBHYv0SZzpt6iKgxoir2buA6i5IuewW+SayUeY9OKRIGb2BKZD3tG9 KuDg== X-Gm-Message-State: ALQs6tAZyA+Q6ThebGtTHf/TNKC7O9aVA5ar2QEik6l+OhUyyyrBo8Ny GgfqkLyrI1LjbIpb1XHJTUgybQ== X-Google-Smtp-Source: AIpwx48QSKgVn2LDD4C9H/IXmAwYH2Vp46z/NgfiX0k7tBtuUbDNQA5QavArqkzd1FXuScTz6HZEZg== X-Received: by 10.101.102.12 with SMTP id w12mr14485706pgv.419.1523911307987; Mon, 16 Apr 2018 13:41:47 -0700 (PDT) Received: from monster-08.mvlab.cumulusnetworks.com. (fw.cumulusnetworks.com. [216.129.126.126]) by smtp.googlemail.com with ESMTPSA id v186sm24030774pfb.182.2018.04.16.13.41.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 16 Apr 2018 13:41:47 -0700 (PDT) From: Roopa Prabhu X-Google-Original-From: Roopa Prabhu To: davem@davemloft.net Cc: netdev@vger.kernel.org, dsa@cumulusnetworks.com Subject: [PATCH net-next 5/5] selftests: net: initial fib rule tests Date: Mon, 16 Apr 2018 13:41:38 -0700 Message-Id: <1523911298-8965-6-git-send-email-roopa@cumulusnetworks.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> References: <1523911298-8965-1-git-send-email-roopa@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu This adds a first set of tests for fib rule match/action for ipv4 and ipv6. Initial tests only cover action table. can be extended to cover other actions in the future. Uses ip route get to validate the rule lookup. Signed-off-by: Roopa Prabhu --- tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/fib_rule_tests.sh | 208 ++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/net/fib_rule_tests.sh diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 785fc18..f02ab70 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -5,7 +5,7 @@ CFLAGS = -Wall -Wl,--no-as-needed -O2 -g CFLAGS += -I../../../../usr/include/ TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh -TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh +TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh fib_rule_tests.sh TEST_GEN_FILES = socket TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa diff --git a/tools/testing/selftests/net/fib_rule_tests.sh b/tools/testing/selftests/net/fib_rule_tests.sh new file mode 100755 index 0000000..b28fbc1 --- /dev/null +++ b/tools/testing/selftests/net/fib_rule_tests.sh @@ -0,0 +1,208 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# This test is for checking IPv4 and IPv6 FIB rules API + +ret=0 + +PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} + +RTABLE=100 +GW_IP4=192.51.100.2 +SRC_IP=192.51.100.3 +GW_IP6=2001:db8:1::2 +SRC_IP6=2001:db8:1::3 + +DEV_ADDR=192.51.100.1 +DEV=dummy0 + +log_test() +{ + local rc=$1 + local expected=$2 + local msg="$3" + + if [ ${rc} -eq ${expected} ]; then + printf " %-60s [ OK ]\n" "${msg}" + else + ret=1 + printf " %-60s [FAIL]\n" "${msg}" + if [ "${PAUSE_ON_FAIL}" = "yes" ]; then + echo + echo "hit enter to continue, 'q' to quit" + read a + [ "$a" = "q" ] && exit 1 + fi + fi +} + +setup() +{ + set -e + ip netns add testns + ip -netns testns link set dev lo up + + ip -netns testns link add dummy0 type dummy + ip -netns testns link set dev dummy0 up + ip -netns testns address add 198.51.100.1/24 dev dummy0 + ip -netns testns -6 address add 2001:db8:1::1/64 dev dummy0 + + set +e +} + +cleanup() +{ + ip -netns testns link del dev dummy0 &> /dev/null + ip netns del testns +} + +fib_check_iproute_support() +{ + ip rule help 2>&1 | grep -q $1 + if [ $? -ne 0 ]; then + echo "SKIP: iproute2 get too old, missing $1 match" + return 1 + fi + + ip route get help 2>&1 | grep -q $2 + if [ $? -ne 0 ]; then + echo "SKIP: iproute2 get too old, missing $2 match" + return 1 + fi + + return 0 +} + +fib_rule6_del() +{ + ip -netns testns -6 rule del $1 + log_test $? 0 "rule6 del $1" +} + +fib_rule6_del_by_pref() +{ + pref=$(ip -netns testns -6 rule show | grep "$1 lookup $TABLE" | cut -d ":" -f 1) + ip -netns testns -6 rule del pref $pref +} + +fib_rule6_test_match_n_redirect() +{ + match="$1" + getmatch="$2" + + ip -netns testns -6 rule add $match table $RTABLE + ip -netns testns -6 route get $GW_IP6 $getmatch | grep -q "table $RTABLE" + log_test $? 0 "rule6 check: $1" + + fib_rule6_del_by_pref "$match" + log_test $? 0 "rule6 del by pref: $match" +} + +fib_rule6_test() +{ + # setup the pbr redirect route + ip -netns testns -6 route add table $RTABLE default via $GW_IP6 dev $DEV onlink + # test oif match + match="oif $DEV" + fib_rule6_test_match_n_redirect "$match" "$match" "oif redirect to table" + + match="from $SRC_IP6 iif $DEV" + fib_rule6_test_match_n_redirect "$match" "$match" "iif redirect to table" + + match="tos 0x10" + fib_rule6_test_match_n_redirect "$match" "$match" "tos redirect to table" + + match="fwmark 0x64" + getmatch="mark 0x64" + fib_rule6_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table" + + fib_check_iproute_support "uidrange" "uid" + if [ $? -eq 0 ]; then + match="uidrange 100-100" + getmatch="uid 100" + fib_rule6_test_match_n_redirect "$match" "$getmatch" "uid redirect to table" + fi + + fib_check_iproute_support "sport" "sport" + if [ $? -eq 0 ]; then + match="sport 666 dport 777" + fib_rule6_test_match_n_redirect "$match" "$match" "sport and dport redirect to table" + fi +} + +fib_rule4_del() +{ + ip -netns testns rule del $1 + log_test $? 0 "del $1" +} + +fib_rule4_del_by_pref() +{ + pref=$(ip -netns testns rule show | grep "$1 lookup $TABLE" | cut -d ":" -f 1) + ip -netns testns rule del pref $pref +} + +fib_rule4_test_match_n_redirect() +{ + match="$1" + getmatch="$2" + + ip -netns testns rule add $match table $RTABLE + ip -netns testns route get $GW_IP4 $getmatch | grep -q "table $RTABLE" + log_test $? 0 "rule4 check: $1" + + fib_rule4_del_by_pref "$match" + log_test $? 0 "rule4 del by pref: $match" +} + +fib_rule4_test() +{ + # setup the pbr redirect route + ip -netns testns route add table $RTABLE default via $GW_IP4 dev $DEV onlink + + # test oif match + match="oif $DEV" + fib_rule4_test_match_n_redirect "$match" "$match" "oif redirect to table" + + match="from $SRC_IP iif $DEV" + fib_rule4_test_match_n_redirect "$match" "$match" "iif redirect to table" + + match="tos 0x10" + fib_rule4_test_match_n_redirect "$match" "$match" "tos redirect to table" + + match="fwmark 0x64" + getmatch="mark 0x64" + fib_rule4_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table" + + fib_check_iproute_support "uidrange" "uid" + if [ $? -eq 0 ]; then + match="uidrange 100-100" + getmatch="uid 100" + fib_rule4_test_match_n_redirect "$match" "$getmatch" "uid redirect to table" + fi + + fib_check_iproute_support "sport" "sport" + if [ $? -eq 0 ]; then + match="sport 666 dport 777" + fib_rule4_test_match_n_redirect "$match" "$match" "sport and dport redirect to table" + fi +} + +if [ "$(id -u)" -ne 0 ];then + echo "SKIP: Need root privileges" + exit 0 +fi + +if [ ! -x "$(command -v ip)" ]; then + echo "SKIP: Could not run test without ip tool" + exit 0 +fi + +# start clean +cleanup &> /dev/null +setup +fib_rule4_test +fib_rule6_test +cleanup + +exit $ret