forked from mirrors/linux
		
	xfrm: remove output_finish indirection from xfrm_state_afinfo
There are only two implementaions, one for ipv4 and one for ipv6. Both are almost identical, they clear skb->cb[], set the TRANSFORMED flag in IP(6)CB and then call the common xfrm_output() function. By placing the IPCB handling into the common function, we avoid the need for the output_finish indirection as the output functions can simply use xfrm_output(). Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
		
							parent
							
								
									f3075f48dd
								
							
						
					
					
						commit
						2ab6096db2
					
				
					 6 changed files with 19 additions and 57 deletions
				
			
		|  | @ -361,7 +361,6 @@ struct xfrm_state_afinfo { | ||||||
| 	const struct xfrm_type		*type_dstopts; | 	const struct xfrm_type		*type_dstopts; | ||||||
| 
 | 
 | ||||||
| 	int			(*output)(struct net *net, struct sock *sk, struct sk_buff *skb); | 	int			(*output)(struct net *net, struct sock *sk, struct sk_buff *skb); | ||||||
| 	int			(*output_finish)(struct sock *sk, struct sk_buff *skb); |  | ||||||
| 	int			(*transport_finish)(struct sk_buff *skb, | 	int			(*transport_finish)(struct sk_buff *skb, | ||||||
| 						    int async); | 						    int async); | ||||||
| 	void			(*local_error)(struct sk_buff *skb, u32 mtu); | 	void			(*local_error)(struct sk_buff *skb, u32 mtu); | ||||||
|  |  | ||||||
|  | @ -14,22 +14,9 @@ | ||||||
| #include <net/xfrm.h> | #include <net/xfrm.h> | ||||||
| #include <net/icmp.h> | #include <net/icmp.h> | ||||||
| 
 | 
 | ||||||
| int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb) |  | ||||||
| { |  | ||||||
| 	memset(IPCB(skb), 0, sizeof(*IPCB(skb))); |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_NETFILTER |  | ||||||
| 	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	return xfrm_output(sk, skb); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) | static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
| { | { | ||||||
| 	struct xfrm_state *x = skb_dst(skb)->xfrm; | 	struct xfrm_state *x = skb_dst(skb)->xfrm; | ||||||
| 	const struct xfrm_state_afinfo *afinfo; |  | ||||||
| 	int ret = -EAFNOSUPPORT; |  | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_NETFILTER | #ifdef CONFIG_NETFILTER | ||||||
| 	if (!x) { | 	if (!x) { | ||||||
|  | @ -38,15 +25,7 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	rcu_read_lock(); | 	return xfrm_output(sk, skb); | ||||||
| 	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family); |  | ||||||
| 	if (likely(afinfo)) |  | ||||||
| 		ret = afinfo->output_finish(sk, skb); |  | ||||||
| 	else |  | ||||||
| 		kfree_skb(skb); |  | ||||||
| 	rcu_read_unlock(); |  | ||||||
| 
 |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) | int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
|  |  | ||||||
|  | @ -14,7 +14,6 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { | ||||||
| 	.family			= AF_INET, | 	.family			= AF_INET, | ||||||
| 	.proto			= IPPROTO_IPIP, | 	.proto			= IPPROTO_IPIP, | ||||||
| 	.output			= xfrm4_output, | 	.output			= xfrm4_output, | ||||||
| 	.output_finish		= xfrm4_output_finish, |  | ||||||
| 	.transport_finish	= xfrm4_transport_finish, | 	.transport_finish	= xfrm4_transport_finish, | ||||||
| 	.local_error		= xfrm4_local_error, | 	.local_error		= xfrm4_local_error, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -47,39 +47,9 @@ void xfrm6_local_error(struct sk_buff *skb, u32 mtu) | ||||||
| 	ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); | 	ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb) |  | ||||||
| { |  | ||||||
| 	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_NETFILTER |  | ||||||
| 	IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	return xfrm_output(sk, skb); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk, |  | ||||||
| 				       struct sk_buff *skb) |  | ||||||
| { |  | ||||||
| 	const struct xfrm_state_afinfo *afinfo; |  | ||||||
| 	int ret = -EAFNOSUPPORT; |  | ||||||
| 
 |  | ||||||
| 	rcu_read_lock(); |  | ||||||
| 	afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family); |  | ||||||
| 	if (likely(afinfo)) |  | ||||||
| 		ret = afinfo->output_finish(sk, skb); |  | ||||||
| 	else |  | ||||||
| 		kfree_skb(skb); |  | ||||||
| 	rcu_read_unlock(); |  | ||||||
| 
 |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
| { | { | ||||||
| 	struct xfrm_state *x = skb_dst(skb)->xfrm; | 	return xfrm_output(sk, skb); | ||||||
| 
 |  | ||||||
| 	return __xfrm6_output_state_finish(x, sk, skb); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
|  | @ -121,7 +91,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
| 				    __xfrm6_output_finish); | 				    __xfrm6_output_finish); | ||||||
| 
 | 
 | ||||||
| skip_frag: | skip_frag: | ||||||
| 	return __xfrm6_output_state_finish(x, sk, skb); | 	return xfrm_output(sk, skb); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | ||||||
|  |  | ||||||
|  | @ -18,7 +18,6 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { | ||||||
| 	.family			= AF_INET6, | 	.family			= AF_INET6, | ||||||
| 	.proto			= IPPROTO_IPV6, | 	.proto			= IPPROTO_IPV6, | ||||||
| 	.output			= xfrm6_output, | 	.output			= xfrm6_output, | ||||||
| 	.output_finish		= xfrm6_output_finish, |  | ||||||
| 	.transport_finish	= xfrm6_transport_finish, | 	.transport_finish	= xfrm6_transport_finish, | ||||||
| 	.local_error		= xfrm6_local_error, | 	.local_error		= xfrm6_local_error, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -571,6 +571,22 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) | ||||||
| 	struct xfrm_state *x = skb_dst(skb)->xfrm; | 	struct xfrm_state *x = skb_dst(skb)->xfrm; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
|  | 	switch (x->outer_mode.family) { | ||||||
|  | 	case AF_INET: | ||||||
|  | 		memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | ||||||
|  | #ifdef CONFIG_NETFILTER | ||||||
|  | 		IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; | ||||||
|  | #endif | ||||||
|  | 		break; | ||||||
|  | 	case AF_INET6: | ||||||
|  | 		memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_NETFILTER | ||||||
|  | 		IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | ||||||
|  | #endif | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	secpath_reset(skb); | 	secpath_reset(skb); | ||||||
| 
 | 
 | ||||||
| 	if (xfrm_dev_offload_ok(skb, x)) { | 	if (xfrm_dev_offload_ok(skb, x)) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Florian Westphal
						Florian Westphal