aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamal Hadi Salim <hadi@cyberus.ca>2010-02-22 19:20:22 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-22 19:20:22 -0500
commitbd55775c8dd656fc69b3a42a1c4ab32abb7e8af9 (patch)
tree766b30d5fc29d5d4849a10a290db51fe0f7c3ad7
parentbf825f81b454fae2ffe1b675f3a549656726440e (diff)
xfrm: SA lookups signature with mark
pass mark to all SA lookups to prepare them for when we add code to have them search. Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/xfrm.h23
-rw-r--r--net/core/pktgen.c3
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/esp4.c2
-rw-r--r--net/ipv4/ipcomp.c6
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/ipcomp6.c6
-rw-r--r--net/ipv6/xfrm6_input.c2
-rw-r--r--net/key/af_key.c14
-rw-r--r--net/xfrm/xfrm_input.c2
-rw-r--r--net/xfrm/xfrm_state.c58
-rw-r--r--net/xfrm/xfrm_user.c17
13 files changed, 84 insertions, 55 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 39f151c7f251..693523c870b9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1319,7 +1319,7 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t
1319 struct flowi *fl, struct xfrm_tmpl *tmpl, 1319 struct flowi *fl, struct xfrm_tmpl *tmpl,
1320 struct xfrm_policy *pol, int *err, 1320 struct xfrm_policy *pol, int *err,
1321 unsigned short family); 1321 unsigned short family);
1322extern struct xfrm_state * xfrm_stateonly_find(struct net *net, 1322extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
1323 xfrm_address_t *daddr, 1323 xfrm_address_t *daddr,
1324 xfrm_address_t *saddr, 1324 xfrm_address_t *saddr,
1325 unsigned short family, 1325 unsigned short family,
@@ -1328,8 +1328,14 @@ extern int xfrm_state_check_expire(struct xfrm_state *x);
1328extern void xfrm_state_insert(struct xfrm_state *x); 1328extern void xfrm_state_insert(struct xfrm_state *x);
1329extern int xfrm_state_add(struct xfrm_state *x); 1329extern int xfrm_state_add(struct xfrm_state *x);
1330extern int xfrm_state_update(struct xfrm_state *x); 1330extern int xfrm_state_update(struct xfrm_state *x);
1331extern struct xfrm_state *xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family); 1331extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
1332extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); 1332 xfrm_address_t *daddr, __be32 spi,
1333 u8 proto, unsigned short family);
1334extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1335 xfrm_address_t *daddr,
1336 xfrm_address_t *saddr,
1337 u8 proto,
1338 unsigned short family);
1333#ifdef CONFIG_XFRM_SUB_POLICY 1339#ifdef CONFIG_XFRM_SUB_POLICY
1334extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, 1340extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1335 int n, unsigned short family); 1341 int n, unsigned short family);
@@ -1366,7 +1372,8 @@ struct xfrmk_spdinfo {
1366 u32 spdhmcnt; 1372 u32 spdhmcnt;
1367}; 1373};
1368 1374
1369extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq); 1375extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
1376 u32 seq);
1370extern int xfrm_state_delete(struct xfrm_state *x); 1377extern int xfrm_state_delete(struct xfrm_state *x);
1371extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info); 1378extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
1372extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); 1379extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
@@ -1451,9 +1458,11 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int d
1451int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); 1458int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
1452u32 xfrm_get_acqseq(void); 1459u32 xfrm_get_acqseq(void);
1453extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); 1460extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
1454struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, 1461struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
1455 xfrm_address_t *daddr, xfrm_address_t *saddr, 1462 u8 mode, u32 reqid, u8 proto,
1456 int create, unsigned short family); 1463 xfrm_address_t *daddr,
1464 xfrm_address_t *saddr, int create,
1465 unsigned short family);
1457extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); 1466extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
1458extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, 1467extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
1459 struct flowi *fl, int family, int strict); 1468 struct flowi *fl, int family, int strict);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2e692afdc55d..43923811bd6a 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2188,12 +2188,13 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)
2188/* If there was already an IPSEC SA, we keep it as is, else 2188/* If there was already an IPSEC SA, we keep it as is, else
2189 * we go look for it ... 2189 * we go look for it ...
2190*/ 2190*/
2191#define DUMMY_MARK 0
2191static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow) 2192static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
2192{ 2193{
2193 struct xfrm_state *x = pkt_dev->flows[flow].x; 2194 struct xfrm_state *x = pkt_dev->flows[flow].x;
2194 if (!x) { 2195 if (!x) {
2195 /*slow path: we dont already have xfrm_state*/ 2196 /*slow path: we dont already have xfrm_state*/
2196 x = xfrm_stateonly_find(&init_net, 2197 x = xfrm_stateonly_find(&init_net, DUMMY_MARK,
2197 (xfrm_address_t *)&pkt_dev->cur_daddr, 2198 (xfrm_address_t *)&pkt_dev->cur_daddr,
2198 (xfrm_address_t *)&pkt_dev->cur_saddr, 2199 (xfrm_address_t *)&pkt_dev->cur_saddr,
2199 AF_INET, 2200 AF_INET,
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 7ed3e4ae93ae..987b47dc69ad 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -393,7 +393,7 @@ static void ah4_err(struct sk_buff *skb, u32 info)
393 icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) 393 icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
394 return; 394 return;
395 395
396 x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); 396 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET);
397 if (!x) 397 if (!x)
398 return; 398 return;
399 printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n", 399 printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n",
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 1948895beb6d..14ca1f1c3fb0 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -422,7 +422,7 @@ static void esp4_err(struct sk_buff *skb, u32 info)
422 icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) 422 icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
423 return; 423 return;
424 424
425 x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); 425 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
426 if (!x) 426 if (!x)
427 return; 427 return;
428 NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", 428 NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 83ed71500898..629067571f02 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -36,7 +36,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
36 return; 36 return;
37 37
38 spi = htonl(ntohs(ipch->cpi)); 38 spi = htonl(ntohs(ipch->cpi));
39 x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, 39 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr,
40 spi, IPPROTO_COMP, AF_INET); 40 spi, IPPROTO_COMP, AF_INET);
41 if (!x) 41 if (!x)
42 return; 42 return;
@@ -63,6 +63,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
63 t->props.mode = x->props.mode; 63 t->props.mode = x->props.mode;
64 t->props.saddr.a4 = x->props.saddr.a4; 64 t->props.saddr.a4 = x->props.saddr.a4;
65 t->props.flags = x->props.flags; 65 t->props.flags = x->props.flags;
66 memcpy(&t->mark, &x->mark, sizeof(t->mark));
66 67
67 if (xfrm_init_state(t)) 68 if (xfrm_init_state(t))
68 goto error; 69 goto error;
@@ -87,8 +88,9 @@ static int ipcomp_tunnel_attach(struct xfrm_state *x)
87 struct net *net = xs_net(x); 88 struct net *net = xs_net(x);
88 int err = 0; 89 int err = 0;
89 struct xfrm_state *t; 90 struct xfrm_state *t;
91 u32 mark = x->mark.v & x->mark.m;
90 92
91 t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr.a4, 93 t = xfrm_state_lookup(net, mark, (xfrm_address_t *)&x->id.daddr.a4,
92 x->props.saddr.a4, IPPROTO_IPIP, AF_INET); 94 x->props.saddr.a4, IPPROTO_IPIP, AF_INET);
93 if (!t) { 95 if (!t) {
94 t = ipcomp_tunnel_create(x); 96 t = ipcomp_tunnel_create(x);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c2f300c314be..5ac89025f9de 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -614,7 +614,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
614 type != ICMPV6_PKT_TOOBIG) 614 type != ICMPV6_PKT_TOOBIG)
615 return; 615 return;
616 616
617 x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); 617 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6);
618 if (!x) 618 if (!x)
619 return; 619 return;
620 620
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 668a46b655e6..ee9b93bdd6a2 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -365,7 +365,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
365 type != ICMPV6_PKT_TOOBIG) 365 type != ICMPV6_PKT_TOOBIG)
366 return; 366 return;
367 367
368 x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); 368 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
369 if (!x) 369 if (!x)
370 return; 370 return;
371 printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n", 371 printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n",
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index bb42f39c1db8..85cccd6ed0b7 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -64,7 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
64 return; 64 return;
65 65
66 spi = htonl(ntohs(ipcomph->cpi)); 66 spi = htonl(ntohs(ipcomph->cpi));
67 x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); 67 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6);
68 if (!x) 68 if (!x)
69 return; 69 return;
70 70
@@ -92,6 +92,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
92 t->props.family = AF_INET6; 92 t->props.family = AF_INET6;
93 t->props.mode = x->props.mode; 93 t->props.mode = x->props.mode;
94 memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); 94 memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
95 memcpy(&t->mark, &x->mark, sizeof(t->mark));
95 96
96 if (xfrm_init_state(t)) 97 if (xfrm_init_state(t))
97 goto error; 98 goto error;
@@ -114,10 +115,11 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x)
114 int err = 0; 115 int err = 0;
115 struct xfrm_state *t = NULL; 116 struct xfrm_state *t = NULL;
116 __be32 spi; 117 __be32 spi;
118 u32 mark = x->mark.m & x->mark.v;
117 119
118 spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&x->props.saddr); 120 spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&x->props.saddr);
119 if (spi) 121 if (spi)
120 t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr, 122 t = xfrm_state_lookup(net, mark, (xfrm_address_t *)&x->id.daddr,
121 spi, IPPROTO_IPV6, AF_INET6); 123 spi, IPPROTO_IPV6, AF_INET6);
122 if (!t) { 124 if (!t) {
123 t = ipcomp6_tunnel_create(x); 125 t = ipcomp6_tunnel_create(x);
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 9084582d236b..2bc98ede1235 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -101,7 +101,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
101 break; 101 break;
102 } 102 }
103 103
104 x = xfrm_state_lookup_byaddr(net, dst, src, proto, AF_INET6); 104 x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6);
105 if (!x) 105 if (!x)
106 continue; 106 continue;
107 107
diff --git a/net/key/af_key.c b/net/key/af_key.c
index da2fe5f57619..aae3cd86ccd7 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -43,6 +43,8 @@ struct netns_pfkey {
43}; 43};
44static DEFINE_MUTEX(pfkey_mutex); 44static DEFINE_MUTEX(pfkey_mutex);
45 45
46#define DUMMY_MARK 0
47static struct xfrm_mark dummy_mark = {0, 0};
46struct pfkey_sock { 48struct pfkey_sock {
47 /* struct sock must be the first member of struct pfkey_sock */ 49 /* struct sock must be the first member of struct pfkey_sock */
48 struct sock sk; 50 struct sock sk;
@@ -647,7 +649,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct net *net, struct sadb_
647 if (!xaddr) 649 if (!xaddr)
648 return NULL; 650 return NULL;
649 651
650 return xfrm_state_lookup(net, xaddr, sa->sadb_sa_spi, proto, family); 652 return xfrm_state_lookup(net, DUMMY_MARK, xaddr, sa->sadb_sa_spi, proto, family);
651} 653}
652 654
653#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) 655#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
@@ -1316,7 +1318,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
1316 } 1318 }
1317 1319
1318 if (hdr->sadb_msg_seq) { 1320 if (hdr->sadb_msg_seq) {
1319 x = xfrm_find_acq_byseq(net, hdr->sadb_msg_seq); 1321 x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
1320 if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) { 1322 if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) {
1321 xfrm_state_put(x); 1323 xfrm_state_put(x);
1322 x = NULL; 1324 x = NULL;
@@ -1324,7 +1326,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
1324 } 1326 }
1325 1327
1326 if (!x) 1328 if (!x)
1327 x = xfrm_find_acq(net, mode, reqid, proto, xdaddr, xsaddr, 1, family); 1329 x = xfrm_find_acq(net, &dummy_mark, mode, reqid, proto, xdaddr, xsaddr, 1, family);
1328 1330
1329 if (x == NULL) 1331 if (x == NULL)
1330 return -ENOENT; 1332 return -ENOENT;
@@ -1373,7 +1375,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
1373 if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0) 1375 if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0)
1374 return 0; 1376 return 0;
1375 1377
1376 x = xfrm_find_acq_byseq(net, hdr->sadb_msg_seq); 1378 x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
1377 if (x == NULL) 1379 if (x == NULL)
1378 return 0; 1380 return 0;
1379 1381
@@ -2572,8 +2574,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
2572 return -EINVAL; 2574 return -EINVAL;
2573 2575
2574 delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); 2576 delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
2575 xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN, dir, 2577 xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN,
2576 pol->sadb_x_policy_id, delete, &err); 2578 dir, pol->sadb_x_policy_id, delete, &err);
2577 if (xp == NULL) 2579 if (xp == NULL)
2578 return -ENOENT; 2580 return -ENOENT;
2579 2581
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index e0009c17d809..45f1c98d4fce 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -152,7 +152,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
152 goto drop; 152 goto drop;
153 } 153 }
154 154
155 x = xfrm_state_lookup(net, daddr, spi, nexthdr, family); 155 x = xfrm_state_lookup(net, skb->mark, daddr, spi, nexthdr, family);
156 if (x == NULL) { 156 if (x == NULL) {
157 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); 157 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
158 xfrm_audit_state_notfound(skb, family, spi, seq); 158 xfrm_audit_state_notfound(skb, family, spi, seq);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9fa3322b2a7d..9f8530356b86 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -669,7 +669,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
669 return 0; 669 return 0;
670} 670}
671 671
672static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) 672static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
673{ 673{
674 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); 674 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
675 struct xfrm_state *x; 675 struct xfrm_state *x;
@@ -689,7 +689,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
689 return NULL; 689 return NULL;
690} 690}
691 691
692static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) 692static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
693{ 693{
694 unsigned int h = xfrm_src_hash(net, daddr, saddr, family); 694 unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
695 struct xfrm_state *x; 695 struct xfrm_state *x;
@@ -713,12 +713,14 @@ static inline struct xfrm_state *
713__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) 713__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
714{ 714{
715 struct net *net = xs_net(x); 715 struct net *net = xs_net(x);
716 u32 mark = x->mark.v & x->mark.m;
716 717
717 if (use_spi) 718 if (use_spi)
718 return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, 719 return __xfrm_state_lookup(net, mark, &x->id.daddr,
719 x->id.proto, family); 720 x->id.spi, x->id.proto, family);
720 else 721 else
721 return __xfrm_state_lookup_byaddr(net, &x->id.daddr, 722 return __xfrm_state_lookup_byaddr(net, mark,
723 &x->id.daddr,
722 &x->props.saddr, 724 &x->props.saddr,
723 x->id.proto, family); 725 x->id.proto, family);
724} 726}
@@ -783,6 +785,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
783 int acquire_in_progress = 0; 785 int acquire_in_progress = 0;
784 int error = 0; 786 int error = 0;
785 struct xfrm_state *best = NULL; 787 struct xfrm_state *best = NULL;
788 u32 mark = pol->mark.v & pol->mark.m;
786 789
787 to_put = NULL; 790 to_put = NULL;
788 791
@@ -819,7 +822,7 @@ found:
819 x = best; 822 x = best;
820 if (!x && !error && !acquire_in_progress) { 823 if (!x && !error && !acquire_in_progress) {
821 if (tmpl->id.spi && 824 if (tmpl->id.spi &&
822 (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, 825 (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
823 tmpl->id.proto, family)) != NULL) { 826 tmpl->id.proto, family)) != NULL) {
824 to_put = x0; 827 to_put = x0;
825 error = -EEXIST; 828 error = -EEXIST;
@@ -833,6 +836,7 @@ found:
833 /* Initialize temporary selector matching only 836 /* Initialize temporary selector matching only
834 * to current session. */ 837 * to current session. */
835 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 838 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
839 memcpy(&x->mark, &pol->mark, sizeof(x->mark));
836 840
837 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); 841 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
838 if (error) { 842 if (error) {
@@ -875,7 +879,7 @@ out:
875} 879}
876 880
877struct xfrm_state * 881struct xfrm_state *
878xfrm_stateonly_find(struct net *net, 882xfrm_stateonly_find(struct net *net, u32 mark,
879 xfrm_address_t *daddr, xfrm_address_t *saddr, 883 xfrm_address_t *daddr, xfrm_address_t *saddr,
880 unsigned short family, u8 mode, u8 proto, u32 reqid) 884 unsigned short family, u8 mode, u8 proto, u32 reqid)
881{ 885{
@@ -971,7 +975,7 @@ void xfrm_state_insert(struct xfrm_state *x)
971EXPORT_SYMBOL(xfrm_state_insert); 975EXPORT_SYMBOL(xfrm_state_insert);
972 976
973/* xfrm_state_lock is held */ 977/* xfrm_state_lock is held */
974static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) 978static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
975{ 979{
976 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); 980 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
977 struct hlist_node *entry; 981 struct hlist_node *entry;
@@ -1026,6 +1030,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1026 x->props.family = family; 1030 x->props.family = family;
1027 x->props.mode = mode; 1031 x->props.mode = mode;
1028 x->props.reqid = reqid; 1032 x->props.reqid = reqid;
1033 x->mark.v = m->v;
1034 x->mark.m = m->m;
1029 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 1035 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
1030 xfrm_state_hold(x); 1036 xfrm_state_hold(x);
1031 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); 1037 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
@@ -1042,7 +1048,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1042 return x; 1048 return x;
1043} 1049}
1044 1050
1045static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); 1051static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
1046 1052
1047int xfrm_state_add(struct xfrm_state *x) 1053int xfrm_state_add(struct xfrm_state *x)
1048{ 1054{
@@ -1050,6 +1056,7 @@ int xfrm_state_add(struct xfrm_state *x)
1050 struct xfrm_state *x1, *to_put; 1056 struct xfrm_state *x1, *to_put;
1051 int family; 1057 int family;
1052 int err; 1058 int err;
1059 u32 mark = x->mark.v & x->mark.m;
1053 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); 1060 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1054 1061
1055 family = x->props.family; 1062 family = x->props.family;
@@ -1067,7 +1074,7 @@ int xfrm_state_add(struct xfrm_state *x)
1067 } 1074 }
1068 1075
1069 if (use_spi && x->km.seq) { 1076 if (use_spi && x->km.seq) {
1070 x1 = __xfrm_find_acq_byseq(net, x->km.seq); 1077 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
1071 if (x1 && ((x1->id.proto != x->id.proto) || 1078 if (x1 && ((x1->id.proto != x->id.proto) ||
1072 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1079 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
1073 to_put = x1; 1080 to_put = x1;
@@ -1076,8 +1083,8 @@ int xfrm_state_add(struct xfrm_state *x)
1076 } 1083 }
1077 1084
1078 if (use_spi && !x1) 1085 if (use_spi && !x1)
1079 x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, 1086 x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
1080 x->id.proto, 1087 x->props.reqid, x->id.proto,
1081 &x->id.daddr, &x->props.saddr, 0); 1088 &x->id.daddr, &x->props.saddr, 0);
1082 1089
1083 __xfrm_state_bump_genids(x); 1090 __xfrm_state_bump_genids(x);
@@ -1151,6 +1158,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1151 goto error; 1158 goto error;
1152 } 1159 }
1153 1160
1161 memcpy(&x->mark, &orig->mark, sizeof(x->mark));
1162
1154 err = xfrm_init_state(x); 1163 err = xfrm_init_state(x);
1155 if (err) 1164 if (err)
1156 goto error; 1165 goto error;
@@ -1342,41 +1351,41 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1342EXPORT_SYMBOL(xfrm_state_check_expire); 1351EXPORT_SYMBOL(xfrm_state_check_expire);
1343 1352
1344struct xfrm_state * 1353struct xfrm_state *
1345xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, 1354xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi,
1346 unsigned short family) 1355 u8 proto, unsigned short family)
1347{ 1356{
1348 struct xfrm_state *x; 1357 struct xfrm_state *x;
1349 1358
1350 spin_lock_bh(&xfrm_state_lock); 1359 spin_lock_bh(&xfrm_state_lock);
1351 x = __xfrm_state_lookup(net, daddr, spi, proto, family); 1360 x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
1352 spin_unlock_bh(&xfrm_state_lock); 1361 spin_unlock_bh(&xfrm_state_lock);
1353 return x; 1362 return x;
1354} 1363}
1355EXPORT_SYMBOL(xfrm_state_lookup); 1364EXPORT_SYMBOL(xfrm_state_lookup);
1356 1365
1357struct xfrm_state * 1366struct xfrm_state *
1358xfrm_state_lookup_byaddr(struct net *net, 1367xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1359 xfrm_address_t *daddr, xfrm_address_t *saddr, 1368 xfrm_address_t *daddr, xfrm_address_t *saddr,
1360 u8 proto, unsigned short family) 1369 u8 proto, unsigned short family)
1361{ 1370{
1362 struct xfrm_state *x; 1371 struct xfrm_state *x;
1363 1372
1364 spin_lock_bh(&xfrm_state_lock); 1373 spin_lock_bh(&xfrm_state_lock);
1365 x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); 1374 x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
1366 spin_unlock_bh(&xfrm_state_lock); 1375 spin_unlock_bh(&xfrm_state_lock);
1367 return x; 1376 return x;
1368} 1377}
1369EXPORT_SYMBOL(xfrm_state_lookup_byaddr); 1378EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
1370 1379
1371struct xfrm_state * 1380struct xfrm_state *
1372xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, 1381xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
1373 xfrm_address_t *daddr, xfrm_address_t *saddr, 1382 xfrm_address_t *daddr, xfrm_address_t *saddr,
1374 int create, unsigned short family) 1383 int create, unsigned short family)
1375{ 1384{
1376 struct xfrm_state *x; 1385 struct xfrm_state *x;
1377 1386
1378 spin_lock_bh(&xfrm_state_lock); 1387 spin_lock_bh(&xfrm_state_lock);
1379 x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); 1388 x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
1380 spin_unlock_bh(&xfrm_state_lock); 1389 spin_unlock_bh(&xfrm_state_lock);
1381 1390
1382 return x; 1391 return x;
@@ -1423,7 +1432,7 @@ EXPORT_SYMBOL(xfrm_state_sort);
1423 1432
1424/* Silly enough, but I'm lazy to build resolution list */ 1433/* Silly enough, but I'm lazy to build resolution list */
1425 1434
1426static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) 1435static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1427{ 1436{
1428 int i; 1437 int i;
1429 1438
@@ -1442,12 +1451,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1442 return NULL; 1451 return NULL;
1443} 1452}
1444 1453
1445struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) 1454struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1446{ 1455{
1447 struct xfrm_state *x; 1456 struct xfrm_state *x;
1448 1457
1449 spin_lock_bh(&xfrm_state_lock); 1458 spin_lock_bh(&xfrm_state_lock);
1450 x = __xfrm_find_acq_byseq(net, seq); 1459 x = __xfrm_find_acq_byseq(net, mark, seq);
1451 spin_unlock_bh(&xfrm_state_lock); 1460 spin_unlock_bh(&xfrm_state_lock);
1452 return x; 1461 return x;
1453} 1462}
@@ -1474,6 +1483,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1474 int err = -ENOENT; 1483 int err = -ENOENT;
1475 __be32 minspi = htonl(low); 1484 __be32 minspi = htonl(low);
1476 __be32 maxspi = htonl(high); 1485 __be32 maxspi = htonl(high);
1486 u32 mark = x->mark.v & x->mark.m;
1477 1487
1478 spin_lock_bh(&x->lock); 1488 spin_lock_bh(&x->lock);
1479 if (x->km.state == XFRM_STATE_DEAD) 1489 if (x->km.state == XFRM_STATE_DEAD)
@@ -1486,7 +1496,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1486 err = -ENOENT; 1496 err = -ENOENT;
1487 1497
1488 if (minspi == maxspi) { 1498 if (minspi == maxspi) {
1489 x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); 1499 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
1490 if (x0) { 1500 if (x0) {
1491 xfrm_state_put(x0); 1501 xfrm_state_put(x0);
1492 goto unlock; 1502 goto unlock;
@@ -1496,7 +1506,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1496 u32 spi = 0; 1506 u32 spi = 0;
1497 for (h=0; h<high-low+1; h++) { 1507 for (h=0; h<high-low+1; h++) {
1498 spi = low + net_random()%(high-low+1); 1508 spi = low + net_random()%(high-low+1);
1499 x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); 1509 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
1500 if (x0 == NULL) { 1510 if (x0 == NULL) {
1501 x->id.spi = htonl(spi); 1511 x->id.spi = htonl(spi);
1502 break; 1512 break;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ee04e6bf0e54..331ae731080a 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -31,6 +31,9 @@
31#include <linux/in6.h> 31#include <linux/in6.h>
32#endif 32#endif
33 33
34#define DUMMY_MARK 0
35static struct xfrm_mark dummy_mark = {0, 0};
36
34static inline int aead_len(struct xfrm_algo_aead *alg) 37static inline int aead_len(struct xfrm_algo_aead *alg)
35{ 38{
36 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); 39 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -530,7 +533,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
530 533
531 if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { 534 if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
532 err = -ESRCH; 535 err = -ESRCH;
533 x = xfrm_state_lookup(net, &p->daddr, p->spi, p->proto, p->family); 536 x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family);
534 } else { 537 } else {
535 xfrm_address_t *saddr = NULL; 538 xfrm_address_t *saddr = NULL;
536 539
@@ -541,7 +544,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
541 } 544 }
542 545
543 err = -ESRCH; 546 err = -ESRCH;
544 x = xfrm_state_lookup_byaddr(net, &p->daddr, saddr, 547 x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr,
545 p->proto, p->family); 548 p->proto, p->family);
546 } 549 }
547 550
@@ -958,7 +961,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
958 961
959 x = NULL; 962 x = NULL;
960 if (p->info.seq) { 963 if (p->info.seq) {
961 x = xfrm_find_acq_byseq(net, p->info.seq); 964 x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq);
962 if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { 965 if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
963 xfrm_state_put(x); 966 xfrm_state_put(x);
964 x = NULL; 967 x = NULL;
@@ -966,7 +969,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
966 } 969 }
967 970
968 if (!x) 971 if (!x)
969 x = xfrm_find_acq(net, p->info.mode, p->info.reqid, 972 x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid,
970 p->info.id.proto, daddr, 973 p->info.id.proto, daddr,
971 &p->info.saddr, 1, 974 &p->info.saddr, 1,
972 family); 975 family);
@@ -1598,7 +1601,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1598 if (r_skb == NULL) 1601 if (r_skb == NULL)
1599 return -ENOMEM; 1602 return -ENOMEM;
1600 1603
1601 x = xfrm_state_lookup(net, &id->daddr, id->spi, id->proto, id->family); 1604 x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family);
1602 if (x == NULL) { 1605 if (x == NULL) {
1603 kfree_skb(r_skb); 1606 kfree_skb(r_skb);
1604 return -ESRCH; 1607 return -ESRCH;
@@ -1640,7 +1643,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1640 if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) 1643 if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
1641 return err; 1644 return err;
1642 1645
1643 x = xfrm_state_lookup(net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); 1646 x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
1644 if (x == NULL) 1647 if (x == NULL)
1645 return -ESRCH; 1648 return -ESRCH;
1646 1649
@@ -1767,7 +1770,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1767 struct xfrm_user_expire *ue = nlmsg_data(nlh); 1770 struct xfrm_user_expire *ue = nlmsg_data(nlh);
1768 struct xfrm_usersa_info *p = &ue->state; 1771 struct xfrm_usersa_info *p = &ue->state;
1769 1772
1770 x = xfrm_state_lookup(net, &p->id.daddr, p->id.spi, p->id.proto, p->family); 1773 x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family);
1771 1774
1772 err = -ENOENT; 1775 err = -ENOENT;
1773 if (x == NULL) 1776 if (x == NULL)