File Index
Files and directories
Sign in
FILE

pm_userspace.c

File preview with syntax highlighting.

linux-6.19.14/net/mptcp/pm_userspace.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Multipath TCP
  3 *
  4 * Copyright (c) 2022, Intel Corporation.
  5 */
  6
  7#include "protocol.h"
  8#include "mib.h"
  9#include "mptcp_pm_gen.h"
 10
 11#define mptcp_for_each_userspace_pm_addr(__msk, __entry)			\
 12	list_for_each_entry(__entry,						\
 13			    &((__msk)->pm.userspace_pm_local_addr_list), list)
 14
 15void mptcp_userspace_pm_free_local_addr_list(struct mptcp_sock *msk)
 16{
 17	struct mptcp_pm_addr_entry *entry, *tmp;
 18	struct sock *sk = (struct sock *)msk;
 19	LIST_HEAD(free_list);
 20
 21	spin_lock_bh(&msk->pm.lock);
 22	list_splice_init(&msk->pm.userspace_pm_local_addr_list, &free_list);
 23	spin_unlock_bh(&msk->pm.lock);
 24
 25	list_for_each_entry_safe(entry, tmp, &free_list, list) {
 26		sock_kfree_s(sk, entry, sizeof(*entry));
 27	}
 28}
 29
 30static struct mptcp_pm_addr_entry *
 31mptcp_userspace_pm_lookup_addr(struct mptcp_sock *msk,
 32			       const struct mptcp_addr_info *addr)
 33{
 34	struct mptcp_pm_addr_entry *entry;
 35
 36	mptcp_for_each_userspace_pm_addr(msk, entry) {
 37		if (mptcp_addresses_equal(&entry->addr, addr, false))
 38			return entry;
 39	}
 40	return NULL;
 41}
 42
 43static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 44						    struct mptcp_pm_addr_entry *entry,
 45						    bool needs_id)
 46{
 47	DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
 48	struct sock *sk = (struct sock *)msk;
 49	struct mptcp_pm_addr_entry *e;
 50	bool addr_match = false;
 51	bool id_match = false;
 52	int ret = -EINVAL;
 53
 54	bitmap_zero(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
 55
 56	spin_lock_bh(&msk->pm.lock);
 57	mptcp_for_each_userspace_pm_addr(msk, e) {
 58		addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true);
 59		if (addr_match && entry->addr.id == 0 && needs_id)
 60			entry->addr.id = e->addr.id;
 61		id_match = (e->addr.id == entry->addr.id);
 62		if (addr_match || id_match)
 63			break;
 64		__set_bit(e->addr.id, id_bitmap);
 65	}
 66
 67	if (!addr_match && !id_match) {
 68		/* Memory for the entry is allocated from the
 69		 * sock option buffer.
 70		 */
 71		e = sock_kmemdup(sk, entry, sizeof(*entry), GFP_ATOMIC);
 72		if (!e) {
 73			ret = -ENOMEM;
 74			goto append_err;
 75		}
 76
 77		if (!e->addr.id && needs_id)
 78			e->addr.id = find_next_zero_bit(id_bitmap,
 79							MPTCP_PM_MAX_ADDR_ID + 1,
 80							1);
 81		list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
 82		msk->pm.local_addr_used++;
 83		ret = e->addr.id;
 84	} else if (addr_match && id_match) {
 85		ret = entry->addr.id;
 86	}
 87
 88append_err:
 89	spin_unlock_bh(&msk->pm.lock);
 90	return ret;
 91}
 92
 93/* If the subflow is closed from the other peer (not via a
 94 * subflow destroy command then), we want to keep the entry
 95 * not to assign the same ID to another address and to be
 96 * able to send RM_ADDR after the removal of the subflow.
 97 */
 98static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
 99						struct mptcp_pm_addr_entry *addr)
100{
101	struct sock *sk = (struct sock *)msk;
102	struct mptcp_pm_addr_entry *entry;
103
104	entry = mptcp_userspace_pm_lookup_addr(msk, &addr->addr);
105	if (!entry)
106		return -EINVAL;
107
108	/* TODO: a refcount is needed because the entry can
109	 * be used multiple times (e.g. fullmesh mode).
110	 */
111	list_del_rcu(&entry->list);
112	sock_kfree_s(sk, entry, sizeof(*entry));
113	msk->pm.local_addr_used--;
114	return 0;
115}
116
117static struct mptcp_pm_addr_entry *
118mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
119{
120	struct mptcp_pm_addr_entry *entry;
121
122	mptcp_for_each_userspace_pm_addr(msk, entry) {
123		if (entry->addr.id == id)
124			return entry;
125	}
126	return NULL;
127}
128
129int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
130				    struct mptcp_pm_addr_entry *skc)
131{
132	__be16 msk_sport =  ((struct inet_sock *)
133			     inet_sk((struct sock *)msk))->inet_sport;
134	struct mptcp_pm_addr_entry *entry;
135
136	spin_lock_bh(&msk->pm.lock);
137	entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
138	spin_unlock_bh(&msk->pm.lock);
139	if (entry)
140		return entry->addr.id;
141
142	if (skc->addr.port == msk_sport)
143		skc->addr.port = 0;
144
145	return mptcp_userspace_pm_append_new_local_addr(msk, skc, true);
146}
147
148bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
149				  struct mptcp_addr_info *skc)
150{
151	struct mptcp_pm_addr_entry *entry;
152	bool backup;
153
154	spin_lock_bh(&msk->pm.lock);
155	entry = mptcp_userspace_pm_lookup_addr(msk, skc);
156	backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
157	spin_unlock_bh(&msk->pm.lock);
158
159	return backup;
160}
161
162static struct mptcp_sock *mptcp_userspace_pm_get_sock(const struct genl_info *info)
163{
164	struct mptcp_sock *msk;
165	struct nlattr *token;
166
167	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_TOKEN))
168		return NULL;
169
170	token = info->attrs[MPTCP_PM_ATTR_TOKEN];
171	msk = mptcp_token_get_sock(genl_info_net(info), nla_get_u32(token));
172	if (!msk) {
173		NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
174		return NULL;
175	}
176
177	if (!mptcp_pm_is_userspace(msk)) {
178		NL_SET_ERR_MSG_ATTR(info->extack, token,
179				    "userspace PM not selected");
180		sock_put((struct sock *)msk);
181		return NULL;
182	}
183
184	return msk;
185}
186
187int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
188{
189	struct mptcp_pm_addr_entry addr_val;
190	struct mptcp_sock *msk;
191	struct nlattr *addr;
192	int err = -EINVAL;
193	struct sock *sk;
194
195	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR))
196		return err;
197
198	msk = mptcp_userspace_pm_get_sock(info);
199	if (!msk)
200		return err;
201
202	sk = (struct sock *)msk;
203
204	addr = info->attrs[MPTCP_PM_ATTR_ADDR];
205	err = mptcp_pm_parse_entry(addr, info, true, &addr_val);
206	if (err < 0)
207		goto announce_err;
208
209	if (addr_val.addr.id == 0) {
210		NL_SET_ERR_MSG_ATTR(info->extack, addr, "invalid addr id");
211		err = -EINVAL;
212		goto announce_err;
213	}
214
215	if (!(addr_val.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
216		NL_SET_ERR_MSG_ATTR(info->extack, addr, "invalid addr flags");
217		err = -EINVAL;
218		goto announce_err;
219	}
220
221	err = mptcp_userspace_pm_append_new_local_addr(msk, &addr_val, false);
222	if (err < 0) {
223		NL_SET_ERR_MSG_ATTR(info->extack, addr,
224				    "did not match address and id");
225		goto announce_err;
226	}
227
228	lock_sock(sk);
229	spin_lock_bh(&msk->pm.lock);
230
231	if (mptcp_pm_alloc_anno_list(msk, &addr_val.addr)) {
232		msk->pm.add_addr_signaled++;
233		mptcp_pm_announce_addr(msk, &addr_val.addr, false);
234		mptcp_pm_addr_send_ack(msk);
235	}
236
237	spin_unlock_bh(&msk->pm.lock);
238	release_sock(sk);
239
240	err = 0;
241 announce_err:
242	sock_put(sk);
243	return err;
244}
245
246static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)
247{
248	struct mptcp_rm_list list = { .nr = 0 };
249	struct mptcp_subflow_context *subflow;
250	struct sock *sk = (struct sock *)msk;
251	bool has_id_0 = false;
252	int err = -EINVAL;
253
254	lock_sock(sk);
255	mptcp_for_each_subflow(msk, subflow) {
256		if (READ_ONCE(subflow->local_id) == 0) {
257			has_id_0 = true;
258			break;
259		}
260	}
261	if (!has_id_0)
262		goto remove_err;
263
264	list.ids[list.nr++] = 0;
265
266	spin_lock_bh(&msk->pm.lock);
267	mptcp_pm_remove_addr(msk, &list);
268	spin_unlock_bh(&msk->pm.lock);
269
270	err = 0;
271
272remove_err:
273	release_sock(sk);
274	return err;
275}
276
277void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
278				struct mptcp_pm_addr_entry *entry)
279{
280	struct mptcp_rm_list alist = { .nr = 0 };
281	int anno_nr = 0;
282
283	/* only delete if either announced or matching a subflow */
284	if (mptcp_remove_anno_list_by_saddr(msk, &entry->addr))
285		anno_nr++;
286	else if (!mptcp_lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
287		return;
288
289	alist.ids[alist.nr++] = entry->addr.id;
290
291	spin_lock_bh(&msk->pm.lock);
292	msk->pm.add_addr_signaled -= anno_nr;
293	mptcp_pm_remove_addr(msk, &alist);
294	spin_unlock_bh(&msk->pm.lock);
295}
296
297int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
298{
299	struct mptcp_pm_addr_entry *match;
300	struct mptcp_sock *msk;
301	struct nlattr *id;
302	int err = -EINVAL;
303	struct sock *sk;
304	u8 id_val;
305
306	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_LOC_ID))
307		return err;
308
309	id = info->attrs[MPTCP_PM_ATTR_LOC_ID];
310	id_val = nla_get_u8(id);
311
312	msk = mptcp_userspace_pm_get_sock(info);
313	if (!msk)
314		return err;
315
316	sk = (struct sock *)msk;
317
318	if (id_val == 0) {
319		err = mptcp_userspace_pm_remove_id_zero_address(msk);
320		goto out;
321	}
322
323	lock_sock(sk);
324
325	spin_lock_bh(&msk->pm.lock);
326	match = mptcp_userspace_pm_lookup_addr_by_id(msk, id_val);
327	if (!match) {
328		spin_unlock_bh(&msk->pm.lock);
329		release_sock(sk);
330		goto out;
331	}
332
333	list_del_rcu(&match->list);
334	spin_unlock_bh(&msk->pm.lock);
335
336	mptcp_pm_remove_addr_entry(msk, match);
337
338	release_sock(sk);
339
340	kfree_rcu_mightsleep(match);
341	/* Adjust sk_omem_alloc like sock_kfree_s() does, to match
342	 * with allocation of this memory by sock_kmemdup()
343	 */
344	atomic_sub(sizeof(*match), &sk->sk_omem_alloc);
345
346	err = 0;
347out:
348	if (err)
349		NL_SET_ERR_MSG_ATTR_FMT(info->extack, id,
350					"address with id %u not found",
351					id_val);
352
353	sock_put(sk);
354	return err;
355}
356
357int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
358{
359	struct mptcp_pm_addr_entry entry = { 0 };
360	struct mptcp_addr_info addr_r;
361	struct nlattr *raddr, *laddr;
362	struct mptcp_pm_local local;
363	struct mptcp_sock *msk;
364	int err = -EINVAL;
365	struct sock *sk;
366
367	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR) ||
368	    GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR_REMOTE))
369		return err;
370
371	msk = mptcp_userspace_pm_get_sock(info);
372	if (!msk)
373		return err;
374
375	sk = (struct sock *)msk;
376
377	laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
378	err = mptcp_pm_parse_entry(laddr, info, true, &entry);
379	if (err < 0)
380		goto create_err;
381
382	if (entry.flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
383		NL_SET_ERR_MSG_ATTR(info->extack, laddr, "invalid addr flags");
384		err = -EINVAL;
385		goto create_err;
386	}
387	entry.flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
388
389	raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
390	err = mptcp_pm_parse_addr(raddr, info, &addr_r);
391	if (err < 0)
392		goto create_err;
393
394	if (!mptcp_pm_addr_families_match(sk, &entry.addr, &addr_r)) {
395		GENL_SET_ERR_MSG(info, "families mismatch");
396		err = -EINVAL;
397		goto create_err;
398	}
399
400	err = mptcp_userspace_pm_append_new_local_addr(msk, &entry, false);
401	if (err < 0) {
402		NL_SET_ERR_MSG_ATTR(info->extack, laddr,
403				    "did not match address and id");
404		goto create_err;
405	}
406
407	local.addr = entry.addr;
408	local.flags = entry.flags;
409	local.ifindex = entry.ifindex;
410
411	lock_sock(sk);
412	err = __mptcp_subflow_connect(sk, &local, &addr_r);
413	release_sock(sk);
414
415	if (err)
416		GENL_SET_ERR_MSG_FMT(info, "connect error: %d", err);
417
418	spin_lock_bh(&msk->pm.lock);
419	if (err)
420		mptcp_userspace_pm_delete_local_addr(msk, &entry);
421	else
422		msk->pm.extra_subflows++;
423	spin_unlock_bh(&msk->pm.lock);
424
425 create_err:
426	sock_put(sk);
427	return err;
428}
429
430static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
431				      const struct mptcp_addr_info *local,
432				      const struct mptcp_addr_info *remote)
433{
434	struct mptcp_subflow_context *subflow;
435
436	if (local->family != remote->family)
437		return NULL;
438
439	mptcp_for_each_subflow(msk, subflow) {
440		const struct inet_sock *issk;
441		struct sock *ssk;
442
443		ssk = mptcp_subflow_tcp_sock(subflow);
444
445		if (local->family != ssk->sk_family)
446			continue;
447
448		issk = inet_sk(ssk);
449
450		switch (ssk->sk_family) {
451		case AF_INET:
452			if (issk->inet_saddr != local->addr.s_addr ||
453			    issk->inet_daddr != remote->addr.s_addr)
454				continue;
455			break;
456#if IS_ENABLED(CONFIG_MPTCP_IPV6)
457		case AF_INET6: {
458			if (!ipv6_addr_equal(&local->addr6, &issk->pinet6->saddr) ||
459			    !ipv6_addr_equal(&remote->addr6, &ssk->sk_v6_daddr))
460				continue;
461			break;
462		}
463#endif
464		default:
465			continue;
466		}
467
468		if (issk->inet_sport == local->port &&
469		    issk->inet_dport == remote->port)
470			return ssk;
471	}
472
473	return NULL;
474}
475
476int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info *info)
477{
478	struct mptcp_pm_addr_entry addr_l;
479	struct mptcp_addr_info addr_r;
480	struct nlattr *raddr, *laddr;
481	struct mptcp_sock *msk;
482	struct sock *sk, *ssk;
483	int err = -EINVAL;
484
485	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR) ||
486	    GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR_REMOTE))
487		return err;
488
489	msk = mptcp_userspace_pm_get_sock(info);
490	if (!msk)
491		return err;
492
493	sk = (struct sock *)msk;
494
495	laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
496	err = mptcp_pm_parse_entry(laddr, info, true, &addr_l);
497	if (err < 0)
498		goto destroy_err;
499
500	raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
501	err = mptcp_pm_parse_addr(raddr, info, &addr_r);
502	if (err < 0)
503		goto destroy_err;
504
505#if IS_ENABLED(CONFIG_MPTCP_IPV6)
506	if (addr_l.addr.family == AF_INET && ipv6_addr_v4mapped(&addr_r.addr6)) {
507		ipv6_addr_set_v4mapped(addr_l.addr.addr.s_addr, &addr_l.addr.addr6);
508		addr_l.addr.family = AF_INET6;
509	}
510	if (addr_r.family == AF_INET && ipv6_addr_v4mapped(&addr_l.addr.addr6)) {
511		ipv6_addr_set_v4mapped(addr_r.addr.s_addr, &addr_r.addr6);
512		addr_r.family = AF_INET6;
513	}
514#endif
515	if (addr_l.addr.family != addr_r.family) {
516		GENL_SET_ERR_MSG(info, "address families do not match");
517		err = -EINVAL;
518		goto destroy_err;
519	}
520
521	if (!addr_l.addr.port) {
522		NL_SET_ERR_MSG_ATTR(info->extack, laddr, "missing local port");
523		err = -EINVAL;
524		goto destroy_err;
525	}
526
527	if (!addr_r.port) {
528		NL_SET_ERR_MSG_ATTR(info->extack, raddr, "missing remote port");
529		err = -EINVAL;
530		goto destroy_err;
531	}
532
533	lock_sock(sk);
534	ssk = mptcp_nl_find_ssk(msk, &addr_l.addr, &addr_r);
535	if (!ssk) {
536		GENL_SET_ERR_MSG(info, "subflow not found");
537		err = -ESRCH;
538		goto release_sock;
539	}
540
541	spin_lock_bh(&msk->pm.lock);
542	mptcp_userspace_pm_delete_local_addr(msk, &addr_l);
543	spin_unlock_bh(&msk->pm.lock);
544	mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
545	mptcp_close_ssk(sk, ssk, mptcp_subflow_ctx(ssk));
546	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
547release_sock:
548	release_sock(sk);
549
550destroy_err:
551	sock_put(sk);
552	return err;
553}
554
555int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_entry *local,
556				 struct genl_info *info)
557{
558	struct mptcp_addr_info rem = { .family = AF_UNSPEC, };
559	struct mptcp_pm_addr_entry *entry;
560	struct nlattr *attr, *attr_rem;
561	struct mptcp_sock *msk;
562	int ret = -EINVAL;
563	struct sock *sk;
564	u8 bkup = 0;
565
566	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR_REMOTE))
567		return ret;
568
569	msk = mptcp_userspace_pm_get_sock(info);
570	if (!msk)
571		return ret;
572
573	sk = (struct sock *)msk;
574
575	attr = info->attrs[MPTCP_PM_ATTR_ADDR];
576	if (local->addr.family == AF_UNSPEC) {
577		NL_SET_ERR_MSG_ATTR(info->extack, attr,
578				    "invalid local address family");
579		ret = -EINVAL;
580		goto set_flags_err;
581	}
582
583	attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
584	ret = mptcp_pm_parse_addr(attr_rem, info, &rem);
585	if (ret < 0)
586		goto set_flags_err;
587
588	if (rem.family == AF_UNSPEC) {
589		NL_SET_ERR_MSG_ATTR(info->extack, attr_rem,
590				    "invalid remote address family");
591		ret = -EINVAL;
592		goto set_flags_err;
593	}
594
595	if (local->flags & MPTCP_PM_ADDR_FLAG_BACKUP)
596		bkup = 1;
597
598	spin_lock_bh(&msk->pm.lock);
599	entry = mptcp_userspace_pm_lookup_addr(msk, &local->addr);
600	if (entry) {
601		if (bkup)
602			entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
603		else
604			entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
605	}
606	spin_unlock_bh(&msk->pm.lock);
607
608	lock_sock(sk);
609	ret = mptcp_pm_mp_prio_send_ack(msk, &local->addr, &rem, bkup);
610	release_sock(sk);
611
612	/* mptcp_pm_mp_prio_send_ack() only fails in one case */
613	if (ret < 0)
614		GENL_SET_ERR_MSG(info, "subflow not found");
615
616set_flags_err:
617	sock_put(sk);
618	return ret;
619}
620
621int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
622				 struct netlink_callback *cb)
623{
624	struct id_bitmap {
625		DECLARE_BITMAP(map, MPTCP_PM_MAX_ADDR_ID + 1);
626	} *bitmap;
627	const struct genl_info *info = genl_info_dump(cb);
628	struct mptcp_pm_addr_entry *entry;
629	struct mptcp_sock *msk;
630	int ret = -EINVAL;
631	struct sock *sk;
632
633	BUILD_BUG_ON(sizeof(struct id_bitmap) > sizeof(cb->ctx));
634
635	bitmap = (struct id_bitmap *)cb->ctx;
636
637	msk = mptcp_userspace_pm_get_sock(info);
638	if (!msk)
639		return ret;
640
641	sk = (struct sock *)msk;
642
643	lock_sock(sk);
644	spin_lock_bh(&msk->pm.lock);
645	mptcp_for_each_userspace_pm_addr(msk, entry) {
646		if (test_bit(entry->addr.id, bitmap->map))
647			continue;
648
649		if (mptcp_pm_genl_fill_addr(msg, cb, entry) < 0)
650			break;
651
652		__set_bit(entry->addr.id, bitmap->map);
653	}
654	spin_unlock_bh(&msk->pm.lock);
655	release_sock(sk);
656	ret = msg->len;
657
658	sock_put(sk);
659	return ret;
660}
661
662int mptcp_userspace_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
663				struct genl_info *info)
664{
665	struct mptcp_pm_addr_entry *entry;
666	struct mptcp_sock *msk;
667	int ret = -EINVAL;
668	struct sock *sk;
669
670	msk = mptcp_userspace_pm_get_sock(info);
671	if (!msk)
672		return ret;
673
674	sk = (struct sock *)msk;
675
676	lock_sock(sk);
677	spin_lock_bh(&msk->pm.lock);
678	entry = mptcp_userspace_pm_lookup_addr_by_id(msk, id);
679	if (entry) {
680		*addr = *entry;
681		ret = 0;
682	}
683	spin_unlock_bh(&msk->pm.lock);
684	release_sock(sk);
685
686	sock_put(sk);
687	return ret;
688}
689
690static struct mptcp_pm_ops mptcp_pm_userspace = {
691	.name			= "userspace",
692	.owner			= THIS_MODULE,
693};
694
695void __init mptcp_pm_userspace_register(void)
696{
697	mptcp_pm_register(&mptcp_pm_userspace);
698}
~/ Read-only file preview.