net: fib_rules: add extack support
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									f9d4b0c1e9
								
							
						
					
					
						commit
						b16fb418b1
					
				| @ -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 *, | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user