[XFRM] STATE: Add a hook to obtain local/remote outbound address.
Outbound transformation replaces both source and destination address with
state's end-point addresses at the same time when IPsec tunnel mode.
It is also required to change them for Mobile IPv6 route optimization, but we
should care about the following differences:
- changing result is not end-point but care-of address
- either source or destination is replaced for each state
This hook is a common platform to change outbound address.
Based on MIPL2 kernel patch.
Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0d735a5..aa3ac99 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -266,6 +266,8 @@
int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
+ xfrm_address_t *(*local_addr)(struct xfrm_state *, xfrm_address_t *);
+ xfrm_address_t *(*remote_addr)(struct xfrm_state *, xfrm_address_t *);
/* Estimate maximal size of result of transformation of a dgram */
u32 (*get_max_size)(struct xfrm_state *, int size);
};
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 81355bb..9328fc88 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -59,6 +59,22 @@
return dst;
}
+static inline struct in6_addr*
+__xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr)
+{
+ return (x->type->remote_addr) ?
+ (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) :
+ (struct in6_addr*)&x->id.daddr;
+}
+
+static inline struct in6_addr*
+__xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
+{
+ return (x->type->local_addr) ?
+ (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) :
+ (struct in6_addr*)&x->props.saddr;
+}
+
/* Allocate chain of dst_entry's, attach known xfrm's, calculate
* all the metrics... Shortly, bundle a bundle.
*/
@@ -115,8 +131,8 @@
dst1->next = dst_prev;
dst_prev = dst1;
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
- remote = (struct in6_addr*)&xfrm[i]->id.daddr;
- local = (struct in6_addr*)&xfrm[i]->props.saddr;
+ remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
+ local = __xfrm6_bundle_addr_local(xfrm[i], local);
tunnel = 1;
}
header_len += xfrm[i]->props.header_len;