Skip to content

Commit 7e65264

Browse files
committed
xfrm: Add a new lookup key to match xfrm interfaces.
This patch adds the xfrm interface id as a lookup key for xfrm states and policies. With this we can assign states and policies to virtual xfrm interfaces. Signed-off-by: Steffen Klassert <[email protected]> Acked-by: Shannon Nelson <[email protected]> Acked-by: Benedict Wong <[email protected]> Tested-by: Benedict Wong <[email protected]> Tested-by: Antony Antony <[email protected]> Reviewed-by: Eyal Birger <[email protected]>
1 parent d159ce7 commit 7e65264

File tree

7 files changed

+96
-25
lines changed

7 files changed

+96
-25
lines changed

include/net/xfrm.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct xfrm_state {
147147
struct xfrm_id id;
148148
struct xfrm_selector sel;
149149
struct xfrm_mark mark;
150+
u32 if_id;
150151
u32 tfcpad;
151152

152153
u32 genid;
@@ -574,6 +575,7 @@ struct xfrm_policy {
574575
atomic_t genid;
575576
u32 priority;
576577
u32 index;
578+
u32 if_id;
577579
struct xfrm_mark mark;
578580
struct xfrm_selector selector;
579581
struct xfrm_lifetime_cfg lft;
@@ -1533,7 +1535,7 @@ struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
15331535
struct xfrm_tmpl *tmpl,
15341536
struct xfrm_policy *pol, int *err,
15351537
unsigned short family);
1536-
struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
1538+
struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark, u32 if_id,
15371539
xfrm_address_t *daddr,
15381540
xfrm_address_t *saddr,
15391541
unsigned short family,
@@ -1690,20 +1692,20 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
16901692
void *);
16911693
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
16921694
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
1693-
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
1695+
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
16941696
u8 type, int dir,
16951697
struct xfrm_selector *sel,
16961698
struct xfrm_sec_ctx *ctx, int delete,
16971699
int *err);
1698-
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
1699-
u32 id, int delete, int *err);
1700+
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id, u8,
1701+
int dir, u32 id, int delete, int *err);
17001702
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
17011703
void xfrm_policy_hash_rebuild(struct net *net);
17021704
u32 xfrm_get_acqseq(void);
17031705
int verify_spi_info(u8 proto, u32 min, u32 max);
17041706
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
17051707
struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
1706-
u8 mode, u32 reqid, u8 proto,
1708+
u8 mode, u32 reqid, u32 if_id, u8 proto,
17071709
const xfrm_address_t *daddr,
17081710
const xfrm_address_t *saddr, int create,
17091711
unsigned short family);
@@ -2019,6 +2021,15 @@ static inline __u32 xfrm_smark_get(__u32 mark, struct xfrm_state *x)
20192021
return (m->v & m->m) | (mark & ~m->m);
20202022
}
20212023

2024+
static inline int xfrm_if_id_put(struct sk_buff *skb, __u32 if_id)
2025+
{
2026+
int ret = 0;
2027+
2028+
if (if_id)
2029+
ret = nla_put_u32(skb, XFRMA_IF_ID, if_id);
2030+
return ret;
2031+
}
2032+
20222033
static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
20232034
unsigned int family)
20242035
{

include/uapi/linux/xfrm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ enum xfrm_attr_type_t {
307307
XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
308308
XFRMA_SET_MARK, /* __u32 */
309309
XFRMA_SET_MARK_MASK, /* __u32 */
310+
XFRMA_IF_ID, /* __u32 */
310311
__XFRMA_MAX
311312

312313
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */

net/core/pktgen.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2255,7 +2255,7 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
22552255
x = xfrm_state_lookup_byspi(pn->net, htonl(pkt_dev->spi), AF_INET);
22562256
} else {
22572257
/* slow path: we dont already have xfrm_state */
2258-
x = xfrm_stateonly_find(pn->net, DUMMY_MARK,
2258+
x = xfrm_stateonly_find(pn->net, DUMMY_MARK, 0,
22592259
(xfrm_address_t *)&pkt_dev->cur_daddr,
22602260
(xfrm_address_t *)&pkt_dev->cur_saddr,
22612261
AF_INET,

net/key/af_key.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
13831383
}
13841384

13851385
if (!x)
1386-
x = xfrm_find_acq(net, &dummy_mark, mode, reqid, proto, xdaddr, xsaddr, 1, family);
1386+
x = xfrm_find_acq(net, &dummy_mark, mode, reqid, 0, proto, xdaddr, xsaddr, 1, family);
13871387

13881388
if (x == NULL)
13891389
return -ENOENT;
@@ -2414,7 +2414,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
24142414
return err;
24152415
}
24162416

2417-
xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN,
2417+
xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
24182418
pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
24192419
1, &err);
24202420
security_xfrm_policy_free(pol_ctx);
@@ -2663,7 +2663,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_
26632663
return -EINVAL;
26642664

26652665
delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
2666-
xp = xfrm_policy_byid(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN,
2666+
xp = xfrm_policy_byid(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
26672667
dir, pol->sadb_x_policy_id, delete, &err);
26682668
if (xp == NULL)
26692669
return -ENOENT;

net/xfrm/xfrm_policy.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
747747
newpos = NULL;
748748
hlist_for_each_entry(pol, chain, bydst) {
749749
if (pol->type == policy->type &&
750+
pol->if_id == policy->if_id &&
750751
!selector_cmp(&pol->selector, &policy->selector) &&
751752
xfrm_policy_mark_match(policy, pol) &&
752753
xfrm_sec_ctx_match(pol->security, policy->security) &&
@@ -798,8 +799,9 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
798799
}
799800
EXPORT_SYMBOL(xfrm_policy_insert);
800801

801-
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
802-
int dir, struct xfrm_selector *sel,
802+
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
803+
u8 type, int dir,
804+
struct xfrm_selector *sel,
803805
struct xfrm_sec_ctx *ctx, int delete,
804806
int *err)
805807
{
@@ -812,6 +814,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
812814
ret = NULL;
813815
hlist_for_each_entry(pol, chain, bydst) {
814816
if (pol->type == type &&
817+
pol->if_id == if_id &&
815818
(mark & pol->mark.m) == pol->mark.v &&
816819
!selector_cmp(sel, &pol->selector) &&
817820
xfrm_sec_ctx_match(ctx, pol->security)) {
@@ -837,8 +840,9 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
837840
}
838841
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
839842

840-
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
841-
int dir, u32 id, int delete, int *err)
843+
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
844+
u8 type, int dir, u32 id, int delete,
845+
int *err)
842846
{
843847
struct xfrm_policy *pol, *ret;
844848
struct hlist_head *chain;
@@ -853,6 +857,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
853857
ret = NULL;
854858
hlist_for_each_entry(pol, chain, byidx) {
855859
if (pol->type == type && pol->index == id &&
860+
pol->if_id == if_id &&
856861
(mark & pol->mark.m) == pol->mark.v) {
857862
xfrm_pol_hold(pol);
858863
if (delete) {
@@ -1063,6 +1068,7 @@ static int xfrm_policy_match(const struct xfrm_policy *pol,
10631068
bool match;
10641069

10651070
if (pol->family != family ||
1071+
pol->if_id != fl->flowi_xfrm.if_id ||
10661072
(fl->flowi_mark & pol->mark.m) != pol->mark.v ||
10671073
pol->type != type)
10681074
return ret;
@@ -1177,7 +1183,8 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
11771183

11781184
match = xfrm_selector_match(&pol->selector, fl, family);
11791185
if (match) {
1180-
if ((sk->sk_mark & pol->mark.m) != pol->mark.v) {
1186+
if ((sk->sk_mark & pol->mark.m) != pol->mark.v ||
1187+
pol->if_id != fl->flowi_xfrm.if_id) {
11811188
pol = NULL;
11821189
goto out;
11831190
}
@@ -1305,6 +1312,7 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
13051312
newp->lft = old->lft;
13061313
newp->curlft = old->curlft;
13071314
newp->mark = old->mark;
1315+
newp->if_id = old->if_id;
13081316
newp->action = old->action;
13091317
newp->flags = old->flags;
13101318
newp->xfrm_nr = old->xfrm_nr;

net/xfrm/xfrm_state.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
941941
int error = 0;
942942
struct xfrm_state *best = NULL;
943943
u32 mark = pol->mark.v & pol->mark.m;
944+
u32 if_id = fl->flowi_xfrm.if_id;
944945
unsigned short encap_family = tmpl->encap_family;
945946
unsigned int sequence;
946947
struct km_event c;
@@ -955,6 +956,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
955956
if (x->props.family == encap_family &&
956957
x->props.reqid == tmpl->reqid &&
957958
(mark & x->mark.m) == x->mark.v &&
959+
x->if_id == if_id &&
958960
!(x->props.flags & XFRM_STATE_WILDRECV) &&
959961
xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
960962
tmpl->mode == x->props.mode &&
@@ -971,6 +973,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
971973
if (x->props.family == encap_family &&
972974
x->props.reqid == tmpl->reqid &&
973975
(mark & x->mark.m) == x->mark.v &&
976+
x->if_id == if_id &&
974977
!(x->props.flags & XFRM_STATE_WILDRECV) &&
975978
xfrm_addr_equal(&x->id.daddr, daddr, encap_family) &&
976979
tmpl->mode == x->props.mode &&
@@ -1010,6 +1013,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
10101013
* to current session. */
10111014
xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);
10121015
memcpy(&x->mark, &pol->mark, sizeof(x->mark));
1016+
x->if_id = if_id;
10131017

10141018
error = security_xfrm_state_alloc_acquire(x, pol->security, fl->flowi_secid);
10151019
if (error) {
@@ -1067,7 +1071,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
10671071
}
10681072

10691073
struct xfrm_state *
1070-
xfrm_stateonly_find(struct net *net, u32 mark,
1074+
xfrm_stateonly_find(struct net *net, u32 mark, u32 if_id,
10711075
xfrm_address_t *daddr, xfrm_address_t *saddr,
10721076
unsigned short family, u8 mode, u8 proto, u32 reqid)
10731077
{
@@ -1080,6 +1084,7 @@ xfrm_stateonly_find(struct net *net, u32 mark,
10801084
if (x->props.family == family &&
10811085
x->props.reqid == reqid &&
10821086
(mark & x->mark.m) == x->mark.v &&
1087+
x->if_id == if_id &&
10831088
!(x->props.flags & XFRM_STATE_WILDRECV) &&
10841089
xfrm_state_addr_check(x, daddr, saddr, family) &&
10851090
mode == x->props.mode &&
@@ -1160,11 +1165,13 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
11601165
struct xfrm_state *x;
11611166
unsigned int h;
11621167
u32 mark = xnew->mark.v & xnew->mark.m;
1168+
u32 if_id = xnew->if_id;
11631169

11641170
h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family);
11651171
hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
11661172
if (x->props.family == family &&
11671173
x->props.reqid == reqid &&
1174+
x->if_id == if_id &&
11681175
(mark & x->mark.m) == x->mark.v &&
11691176
xfrm_addr_equal(&x->id.daddr, &xnew->id.daddr, family) &&
11701177
xfrm_addr_equal(&x->props.saddr, &xnew->props.saddr, family))
@@ -1187,7 +1194,7 @@ EXPORT_SYMBOL(xfrm_state_insert);
11871194
static struct xfrm_state *__find_acq_core(struct net *net,
11881195
const struct xfrm_mark *m,
11891196
unsigned short family, u8 mode,
1190-
u32 reqid, u8 proto,
1197+
u32 reqid, u32 if_id, u8 proto,
11911198
const xfrm_address_t *daddr,
11921199
const xfrm_address_t *saddr,
11931200
int create)
@@ -1242,6 +1249,7 @@ static struct xfrm_state *__find_acq_core(struct net *net,
12421249
x->props.family = family;
12431250
x->props.mode = mode;
12441251
x->props.reqid = reqid;
1252+
x->if_id = if_id;
12451253
x->mark.v = m->v;
12461254
x->mark.m = m->m;
12471255
x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
@@ -1296,7 +1304,7 @@ int xfrm_state_add(struct xfrm_state *x)
12961304

12971305
if (use_spi && !x1)
12981306
x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
1299-
x->props.reqid, x->id.proto,
1307+
x->props.reqid, x->if_id, x->id.proto,
13001308
&x->id.daddr, &x->props.saddr, 0);
13011309

13021310
__xfrm_state_bump_genids(x);
@@ -1395,6 +1403,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
13951403
x->props.flags = orig->props.flags;
13961404
x->props.extra_flags = orig->props.extra_flags;
13971405

1406+
x->if_id = orig->if_id;
13981407
x->tfcpad = orig->tfcpad;
13991408
x->replay_maxdiff = orig->replay_maxdiff;
14001409
x->replay_maxage = orig->replay_maxage;
@@ -1619,13 +1628,13 @@ EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
16191628

16201629
struct xfrm_state *
16211630
xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid,
1622-
u8 proto, const xfrm_address_t *daddr,
1631+
u32 if_id, u8 proto, const xfrm_address_t *daddr,
16231632
const xfrm_address_t *saddr, int create, unsigned short family)
16241633
{
16251634
struct xfrm_state *x;
16261635

16271636
spin_lock_bh(&net->xfrm.xfrm_state_lock);
1628-
x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
1637+
x = __find_acq_core(net, mark, family, mode, reqid, if_id, proto, daddr, saddr, create);
16291638
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
16301639

16311640
return x;

0 commit comments

Comments
 (0)