Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ab47d47 authored by Antony Antony's avatar Antony Antony Committed by Steffen Klassert
Browse files

xfrm: extend MIGRATE with UDP encapsulation port



Add UDP encapsulation port to XFRM_MSG_MIGRATE using an optional
netlink attribute XFRMA_ENCAP.

The devices that support IKE MOBIKE extension (RFC-4555 Section 3.8)
could go to sleep for a few minutes and wake up. When it wake up the
NAT mapping could have expired, the device send a MOBIKE UPDATE_SA
message to migrate the IPsec SA. The change could be a change UDP
encapsulation port, IP address, or both.

Reported-by: default avatarPaul Wouters <pwouters@redhat.com>
Signed-off-by: default avatarAntony Antony <antony@phenome.org>
Reviewed-by: default avatarRichard Guy Briggs <rgb@tricolour.ca>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent d49c9dc1
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1688,10 +1688,12 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
	       const struct xfrm_kmaddress *k);
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
				      struct xfrm_migrate *m);
				      struct xfrm_migrate *m,
				      struct xfrm_encap_tmpl *encap);
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
		 struct xfrm_migrate *m, int num_bundles,
		 struct xfrm_kmaddress *k, struct net *net);
		 struct xfrm_kmaddress *k, struct net *net,
		 struct xfrm_encap_tmpl *encap);
#endif

int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
+1 −1
Original line number Diff line number Diff line
@@ -2602,7 +2602,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
	}

	return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
			    kma ? &k : NULL, net);
			    kma ? &k : NULL, net, NULL);

 out:
	return err;
+4 −7
Original line number Diff line number Diff line
@@ -3315,11 +3315,6 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
		return -EINVAL;

	for (i = 0; i < num_migrate; i++) {
		if (xfrm_addr_equal(&m[i].old_daddr, &m[i].new_daddr,
				    m[i].old_family) &&
		    xfrm_addr_equal(&m[i].old_saddr, &m[i].new_saddr,
				    m[i].old_family))
			return -EINVAL;
		if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) ||
		    xfrm_addr_any(&m[i].new_saddr, m[i].new_family))
			return -EINVAL;
@@ -3343,7 +3338,8 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)

int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
		 struct xfrm_migrate *m, int num_migrate,
		 struct xfrm_kmaddress *k, struct net *net)
		 struct xfrm_kmaddress *k, struct net *net,
		 struct xfrm_encap_tmpl *encap)
{
	int i, err, nx_cur = 0, nx_new = 0;
	struct xfrm_policy *pol = NULL;
@@ -3366,7 +3362,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
		if ((x = xfrm_migrate_state_find(mp, net))) {
			x_cur[nx_cur] = x;
			nx_cur++;
			if ((xc = xfrm_state_migrate(x, mp))) {
			xc = xfrm_state_migrate(x, mp, encap);
			if (xc) {
				x_new[nx_new] = xc;
				nx_new++;
			} else {
+13 −5
Original line number Diff line number Diff line
@@ -1309,7 +1309,8 @@ int xfrm_state_add(struct xfrm_state *x)
EXPORT_SYMBOL(xfrm_state_add);

#ifdef CONFIG_XFRM_MIGRATE
static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
					   struct xfrm_encap_tmpl *encap)
{
	struct net *net = xs_net(orig);
	struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1351,8 +1352,14 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
	}
	x->props.calgo = orig->props.calgo;

	if (orig->encap) {
		x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
	if (encap || orig->encap) {
		if (encap)
			x->encap = kmemdup(encap, sizeof(*x->encap),
					GFP_KERNEL);
		else
			x->encap = kmemdup(orig->encap, sizeof(*x->encap),
					GFP_KERNEL);

		if (!x->encap)
			goto error;
	}
@@ -1440,11 +1447,12 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
EXPORT_SYMBOL(xfrm_migrate_state_find);

struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
				      struct xfrm_migrate *m)
				      struct xfrm_migrate *m,
				      struct xfrm_encap_tmpl *encap)
{
	struct xfrm_state *xc;

	xc = xfrm_state_clone(x);
	xc = xfrm_state_clone(x, encap);
	if (!xc)
		return NULL;

+12 −2
Original line number Diff line number Diff line
@@ -2243,6 +2243,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
	int err;
	int n = 0;
	struct net *net = sock_net(skb->sk);
	struct xfrm_encap_tmpl  *encap = NULL;

	if (attrs[XFRMA_MIGRATE] == NULL)
		return -EINVAL;
@@ -2260,10 +2261,19 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (!n)
		return 0;

	xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net);

	if (attrs[XFRMA_ENCAP]) {
		encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
				sizeof(*encap), GFP_KERNEL);
		if (!encap)
			return 0;
	}

	err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap);

	kfree(encap);

	return err;
}
#else
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
			   struct nlattr **attrs)