summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsa@cumulusnetworks.com>2015-08-10 18:58:11 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2015-08-11 06:41:35 -0400
commit42a7b32b73d6bf22e4bdd7bf68746e2d71f4cd8d (patch)
tree750adee8068e2e45dfa3aa39b10a6e3ea2162cf1
parentdf367561ffe5a66cd0b2970fdb8897d5487d38e6 (diff)
xfrm: Add oif to dst lookups
Rules can be installed that direct route lookups to specific tables based on oif. Plumb the oif through the xfrm lookups so it gets set in the flow struct and passed to the resolver routines. Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
-rw-r--r--include/net/xfrm.h7
-rw-r--r--net/ipv4/xfrm4_policy.c11
-rw-r--r--net/ipv6/xfrm6_policy.c7
-rw-r--r--net/xfrm/xfrm_policy.c24
4 files changed, 29 insertions, 20 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f0ee97eec24d..312e3fee9ccf 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -285,10 +285,13 @@ struct xfrm_policy_afinfo {
285 unsigned short family; 285 unsigned short family;
286 struct dst_ops *dst_ops; 286 struct dst_ops *dst_ops;
287 void (*garbage_collect)(struct net *net); 287 void (*garbage_collect)(struct net *net);
288 struct dst_entry *(*dst_lookup)(struct net *net, int tos, 288 struct dst_entry *(*dst_lookup)(struct net *net,
289 int tos, int oif,
289 const xfrm_address_t *saddr, 290 const xfrm_address_t *saddr,
290 const xfrm_address_t *daddr); 291 const xfrm_address_t *daddr);
291 int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr); 292 int (*get_saddr)(struct net *net, int oif,
293 xfrm_address_t *saddr,
294 xfrm_address_t *daddr);
292 void (*decode_session)(struct sk_buff *skb, 295 void (*decode_session)(struct sk_buff *skb,
293 struct flowi *fl, 296 struct flowi *fl,
294 int reverse); 297 int reverse);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index bff69746e05f..55b3c0f4dde5 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -19,7 +19,7 @@
19static struct xfrm_policy_afinfo xfrm4_policy_afinfo; 19static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
20 20
21static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, 21static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
22 int tos, 22 int tos, int oif,
23 const xfrm_address_t *saddr, 23 const xfrm_address_t *saddr,
24 const xfrm_address_t *daddr) 24 const xfrm_address_t *daddr)
25{ 25{
@@ -28,6 +28,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
28 memset(fl4, 0, sizeof(*fl4)); 28 memset(fl4, 0, sizeof(*fl4));
29 fl4->daddr = daddr->a4; 29 fl4->daddr = daddr->a4;
30 fl4->flowi4_tos = tos; 30 fl4->flowi4_tos = tos;
31 fl4->flowi4_oif = oif;
31 if (saddr) 32 if (saddr)
32 fl4->saddr = saddr->a4; 33 fl4->saddr = saddr->a4;
33 34
@@ -38,22 +39,22 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
38 return ERR_CAST(rt); 39 return ERR_CAST(rt);
39} 40}
40 41
41static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, 42static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
42 const xfrm_address_t *saddr, 43 const xfrm_address_t *saddr,
43 const xfrm_address_t *daddr) 44 const xfrm_address_t *daddr)
44{ 45{
45 struct flowi4 fl4; 46 struct flowi4 fl4;
46 47
47 return __xfrm4_dst_lookup(net, &fl4, tos, saddr, daddr); 48 return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr);
48} 49}
49 50
50static int xfrm4_get_saddr(struct net *net, 51static int xfrm4_get_saddr(struct net *net, int oif,
51 xfrm_address_t *saddr, xfrm_address_t *daddr) 52 xfrm_address_t *saddr, xfrm_address_t *daddr)
52{ 53{
53 struct dst_entry *dst; 54 struct dst_entry *dst;
54 struct flowi4 fl4; 55 struct flowi4 fl4;
55 56
56 dst = __xfrm4_dst_lookup(net, &fl4, 0, NULL, daddr); 57 dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr);
57 if (IS_ERR(dst)) 58 if (IS_ERR(dst))
58 return -EHOSTUNREACH; 59 return -EHOSTUNREACH;
59 60
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index ed0583c1b9fc..a74013d3eceb 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -26,7 +26,7 @@
26 26
27static struct xfrm_policy_afinfo xfrm6_policy_afinfo; 27static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
28 28
29static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, 29static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
30 const xfrm_address_t *saddr, 30 const xfrm_address_t *saddr,
31 const xfrm_address_t *daddr) 31 const xfrm_address_t *daddr)
32{ 32{
@@ -35,6 +35,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
35 int err; 35 int err;
36 36
37 memset(&fl6, 0, sizeof(fl6)); 37 memset(&fl6, 0, sizeof(fl6));
38 fl6.flowi6_oif = oif;
38 memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr)); 39 memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
39 if (saddr) 40 if (saddr)
40 memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr)); 41 memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
@@ -50,13 +51,13 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
50 return dst; 51 return dst;
51} 52}
52 53
53static int xfrm6_get_saddr(struct net *net, 54static int xfrm6_get_saddr(struct net *net, int oif,
54 xfrm_address_t *saddr, xfrm_address_t *daddr) 55 xfrm_address_t *saddr, xfrm_address_t *daddr)
55{ 56{
56 struct dst_entry *dst; 57 struct dst_entry *dst;
57 struct net_device *dev; 58 struct net_device *dev;
58 59
59 dst = xfrm6_dst_lookup(net, 0, NULL, daddr); 60 dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr);
60 if (IS_ERR(dst)) 61 if (IS_ERR(dst))
61 return -EHOSTUNREACH; 62 return -EHOSTUNREACH;
62 63
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 18cead7645be..94af3d065785 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -115,7 +115,8 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
115 rcu_read_unlock(); 115 rcu_read_unlock();
116} 116}
117 117
118static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, 118static inline struct dst_entry *__xfrm_dst_lookup(struct net *net,
119 int tos, int oif,
119 const xfrm_address_t *saddr, 120 const xfrm_address_t *saddr,
120 const xfrm_address_t *daddr, 121 const xfrm_address_t *daddr,
121 int family) 122 int family)
@@ -127,14 +128,15 @@ static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos,
127 if (unlikely(afinfo == NULL)) 128 if (unlikely(afinfo == NULL))
128 return ERR_PTR(-EAFNOSUPPORT); 129 return ERR_PTR(-EAFNOSUPPORT);
129 130
130 dst = afinfo->dst_lookup(net, tos, saddr, daddr); 131 dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr);
131 132
132 xfrm_policy_put_afinfo(afinfo); 133 xfrm_policy_put_afinfo(afinfo);
133 134
134 return dst; 135 return dst;
135} 136}
136 137
137static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, 138static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
139 int tos, int oif,
138 xfrm_address_t *prev_saddr, 140 xfrm_address_t *prev_saddr,
139 xfrm_address_t *prev_daddr, 141 xfrm_address_t *prev_daddr,
140 int family) 142 int family)
@@ -153,7 +155,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
153 daddr = x->coaddr; 155 daddr = x->coaddr;
154 } 156 }
155 157
156 dst = __xfrm_dst_lookup(net, tos, saddr, daddr, family); 158 dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family);
157 159
158 if (!IS_ERR(dst)) { 160 if (!IS_ERR(dst)) {
159 if (prev_saddr != saddr) 161 if (prev_saddr != saddr)
@@ -1373,15 +1375,15 @@ int __xfrm_sk_clone_policy(struct sock *sk)
1373} 1375}
1374 1376
1375static int 1377static int
1376xfrm_get_saddr(struct net *net, xfrm_address_t *local, xfrm_address_t *remote, 1378xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
1377 unsigned short family) 1379 xfrm_address_t *remote, unsigned short family)
1378{ 1380{
1379 int err; 1381 int err;
1380 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); 1382 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
1381 1383
1382 if (unlikely(afinfo == NULL)) 1384 if (unlikely(afinfo == NULL))
1383 return -EINVAL; 1385 return -EINVAL;
1384 err = afinfo->get_saddr(net, local, remote); 1386 err = afinfo->get_saddr(net, oif, local, remote);
1385 xfrm_policy_put_afinfo(afinfo); 1387 xfrm_policy_put_afinfo(afinfo);
1386 return err; 1388 return err;
1387} 1389}
@@ -1410,7 +1412,9 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
1410 remote = &tmpl->id.daddr; 1412 remote = &tmpl->id.daddr;
1411 local = &tmpl->saddr; 1413 local = &tmpl->saddr;
1412 if (xfrm_addr_any(local, tmpl->encap_family)) { 1414 if (xfrm_addr_any(local, tmpl->encap_family)) {
1413 error = xfrm_get_saddr(net, &tmp, remote, tmpl->encap_family); 1415 error = xfrm_get_saddr(net, fl->flowi_oif,
1416 &tmp, remote,
1417 tmpl->encap_family);
1414 if (error) 1418 if (error)
1415 goto fail; 1419 goto fail;
1416 local = &tmp; 1420 local = &tmp;
@@ -1690,8 +1694,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1690 1694
1691 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { 1695 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
1692 family = xfrm[i]->props.family; 1696 family = xfrm[i]->props.family;
1693 dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr, 1697 dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
1694 family); 1698 &saddr, &daddr, family);
1695 err = PTR_ERR(dst); 1699 err = PTR_ERR(dst);
1696 if (IS_ERR(dst)) 1700 if (IS_ERR(dst))
1697 goto put_states; 1701 goto put_states;