aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h17
-rw-r--r--net/xfrm/xfrm_policy.c49
2 files changed, 57 insertions, 9 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index c435620dbb37..bed7d43932f6 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1045,6 +1045,23 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
1045 return NULL; 1045 return NULL;
1046} 1046}
1047 1047
1048static __inline__
1049void xfrm_flowi_addr_get(struct flowi *fl,
1050 xfrm_address_t *saddr, xfrm_address_t *daddr,
1051 unsigned short family)
1052{
1053 switch(family) {
1054 case AF_INET:
1055 memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4));
1056 memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4));
1057 break;
1058 case AF_INET6:
1059 ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src);
1060 ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst);
1061 break;
1062 }
1063}
1064
1048static __inline__ int 1065static __inline__ int
1049__xfrm4_state_addr_check(struct xfrm_state *x, 1066__xfrm4_state_addr_check(struct xfrm_state *x,
1050 xfrm_address_t *daddr, xfrm_address_t *saddr) 1067 xfrm_address_t *daddr, xfrm_address_t *saddr)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index bae94a8031a2..8e588f20c60c 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -97,25 +97,52 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
97 return 0; 97 return 0;
98} 98}
99 99
100static inline struct dst_entry *__xfrm_dst_lookup(int tos,
101 xfrm_address_t *saddr,
102 xfrm_address_t *daddr,
103 int family)
104{
105 struct xfrm_policy_afinfo *afinfo;
106 struct dst_entry *dst;
107
108 afinfo = xfrm_policy_get_afinfo(family);
109 if (unlikely(afinfo == NULL))
110 return ERR_PTR(-EAFNOSUPPORT);
111
112 dst = afinfo->dst_lookup(tos, saddr, daddr);
113
114 xfrm_policy_put_afinfo(afinfo);
115
116 return dst;
117}
118
100static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, 119static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
120 xfrm_address_t *prev_saddr,
121 xfrm_address_t *prev_daddr,
101 int family) 122 int family)
102{ 123{
103 xfrm_address_t *saddr = &x->props.saddr; 124 xfrm_address_t *saddr = &x->props.saddr;
104 xfrm_address_t *daddr = &x->id.daddr; 125 xfrm_address_t *daddr = &x->id.daddr;
105 struct xfrm_policy_afinfo *afinfo;
106 struct dst_entry *dst; 126 struct dst_entry *dst;
107 127
108 if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) 128 if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) {
109 saddr = x->coaddr; 129 saddr = x->coaddr;
110 if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) 130 daddr = prev_daddr;
131 }
132 if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) {
133 saddr = prev_saddr;
111 daddr = x->coaddr; 134 daddr = x->coaddr;
135 }
112 136
113 afinfo = xfrm_policy_get_afinfo(family); 137 dst = __xfrm_dst_lookup(tos, saddr, daddr, family);
114 if (unlikely(afinfo == NULL)) 138
115 return ERR_PTR(-EAFNOSUPPORT); 139 if (!IS_ERR(dst)) {
140 if (prev_saddr != saddr)
141 memcpy(prev_saddr, saddr, sizeof(*prev_saddr));
142 if (prev_daddr != daddr)
143 memcpy(prev_daddr, daddr, sizeof(*prev_daddr));
144 }
116 145
117 dst = afinfo->dst_lookup(tos, saddr, daddr);
118 xfrm_policy_put_afinfo(afinfo);
119 return dst; 146 return dst;
120} 147}
121 148
@@ -1354,6 +1381,9 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1354 int trailer_len = 0; 1381 int trailer_len = 0;
1355 int tos; 1382 int tos;
1356 int family = policy->selector.family; 1383 int family = policy->selector.family;
1384 xfrm_address_t saddr, daddr;
1385
1386 xfrm_flowi_addr_get(fl, &saddr, &daddr, family);
1357 1387
1358 tos = xfrm_get_tos(fl, family); 1388 tos = xfrm_get_tos(fl, family);
1359 err = tos; 1389 err = tos;
@@ -1384,7 +1414,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1384 1414
1385 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { 1415 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
1386 family = xfrm[i]->props.family; 1416 family = xfrm[i]->props.family;
1387 dst = xfrm_dst_lookup(xfrm[i], tos, family); 1417 dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr,
1418 family);
1388 err = PTR_ERR(dst); 1419 err = PTR_ERR(dst);
1389 if (IS_ERR(dst)) 1420 if (IS_ERR(dst))
1390 goto put_states; 1421 goto put_states;