Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  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
 10void mptcp_free_local_addr_list(struct mptcp_sock *msk)
 11{
 12	struct mptcp_pm_addr_entry *entry, *tmp;
 13	struct sock *sk = (struct sock *)msk;
 14	LIST_HEAD(free_list);
 15
 16	if (!mptcp_pm_is_userspace(msk))
 17		return;
 18
 19	spin_lock_bh(&msk->pm.lock);
 20	list_splice_init(&msk->pm.userspace_pm_local_addr_list, &free_list);
 21	spin_unlock_bh(&msk->pm.lock);
 22
 23	list_for_each_entry_safe(entry, tmp, &free_list, list) {
 24		sock_kfree_s(sk, entry, sizeof(*entry));
 25	}
 26}
 27
 28int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 29					     struct mptcp_pm_addr_entry *entry)
 30{
 31	DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
 32	struct mptcp_pm_addr_entry *match = NULL;
 33	struct sock *sk = (struct sock *)msk;
 34	struct mptcp_pm_addr_entry *e;
 35	bool addr_match = false;
 36	bool id_match = false;
 37	int ret = -EINVAL;
 38
 39	bitmap_zero(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
 40
 41	spin_lock_bh(&msk->pm.lock);
 42	list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
 43		addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true);
 44		if (addr_match && entry->addr.id == 0)
 45			entry->addr.id = e->addr.id;
 46		id_match = (e->addr.id == entry->addr.id);
 47		if (addr_match && id_match) {
 48			match = e;
 49			break;
 50		} else if (addr_match || id_match) {
 51			break;
 52		}
 53		__set_bit(e->addr.id, id_bitmap);
 54	}
 55
 56	if (!match && !addr_match && !id_match) {
 57		/* Memory for the entry is allocated from the
 58		 * sock option buffer.
 59		 */
 60		e = sock_kmalloc(sk, sizeof(*e), GFP_ATOMIC);
 61		if (!e) {
 62			spin_unlock_bh(&msk->pm.lock);
 63			return -ENOMEM;
 64		}
 65
 66		*e = *entry;
 67		if (!e->addr.id)
 68			e->addr.id = find_next_zero_bit(id_bitmap,
 69							MPTCP_PM_MAX_ADDR_ID + 1,
 70							1);
 71		list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
 72		ret = e->addr.id;
 73	} else if (match) {
 74		ret = entry->addr.id;
 75	}
 76
 77	spin_unlock_bh(&msk->pm.lock);
 78	return ret;
 79}
 80
 81int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
 82						   unsigned int id,
 83						   u8 *flags, int *ifindex)
 84{
 85	struct mptcp_pm_addr_entry *entry, *match = NULL;
 86
 87	*flags = 0;
 88	*ifindex = 0;
 89
 90	spin_lock_bh(&msk->pm.lock);
 91	list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
 92		if (id == entry->addr.id) {
 93			match = entry;
 94			break;
 95		}
 96	}
 97	spin_unlock_bh(&msk->pm.lock);
 98	if (match) {
 99		*flags = match->flags;
100		*ifindex = match->ifindex;
101	}
102
103	return 0;
104}
105
106int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
107				    struct mptcp_addr_info *skc)
108{
109	struct mptcp_pm_addr_entry new_entry;
110	__be16 msk_sport =  ((struct inet_sock *)
111			     inet_sk((struct sock *)msk))->inet_sport;
112
113	memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
114	new_entry.addr = *skc;
115	new_entry.addr.id = 0;
116	new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
117
118	if (new_entry.addr.port == msk_sport)
119		new_entry.addr.port = 0;
120
121	return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry);
122}
123
124int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info)
125{
126	struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
127	struct nlattr *addr = info->attrs[MPTCP_PM_ATTR_ADDR];
128	struct mptcp_pm_addr_entry addr_val;
129	struct mptcp_sock *msk;
130	int err = -EINVAL;
131	u32 token_val;
132
133	if (!addr || !token) {
134		GENL_SET_ERR_MSG(info, "missing required inputs");
135		return err;
136	}
137
138	token_val = nla_get_u32(token);
139
140	msk = mptcp_token_get_sock(sock_net(skb->sk), token_val);
141	if (!msk) {
142		NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
143		return err;
144	}
145
146	if (!mptcp_pm_is_userspace(msk)) {
147		GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
148		goto announce_err;
149	}
150
151	err = mptcp_pm_parse_entry(addr, info, true, &addr_val);
152	if (err < 0) {
153		GENL_SET_ERR_MSG(info, "error parsing local address");
154		goto announce_err;
155	}
156
157	if (addr_val.addr.id == 0 || !(addr_val.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
158		GENL_SET_ERR_MSG(info, "invalid addr id or flags");
159		err = -EINVAL;
160		goto announce_err;
161	}
162
163	err = mptcp_userspace_pm_append_new_local_addr(msk, &addr_val);
164	if (err < 0) {
165		GENL_SET_ERR_MSG(info, "did not match address and id");
166		goto announce_err;
167	}
168
169	lock_sock((struct sock *)msk);
170	spin_lock_bh(&msk->pm.lock);
171
172	if (mptcp_pm_alloc_anno_list(msk, &addr_val)) {
173		mptcp_pm_announce_addr(msk, &addr_val.addr, false);
174		mptcp_pm_nl_addr_send_ack(msk);
175	}
176
177	spin_unlock_bh(&msk->pm.lock);
178	release_sock((struct sock *)msk);
179
180	err = 0;
181 announce_err:
182	sock_put((struct sock *)msk);
183	return err;
184}
185
186int mptcp_nl_cmd_remove(struct sk_buff *skb, struct genl_info *info)
187{
188	struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
189	struct nlattr *id = info->attrs[MPTCP_PM_ATTR_LOC_ID];
190	struct mptcp_pm_addr_entry *match = NULL;
191	struct mptcp_pm_addr_entry *entry;
192	struct mptcp_sock *msk;
193	LIST_HEAD(free_list);
194	int err = -EINVAL;
195	u32 token_val;
196	u8 id_val;
197
198	if (!id || !token) {
199		GENL_SET_ERR_MSG(info, "missing required inputs");
200		return err;
201	}
202
203	id_val = nla_get_u8(id);
204	token_val = nla_get_u32(token);
205
206	msk = mptcp_token_get_sock(sock_net(skb->sk), token_val);
207	if (!msk) {
208		NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
209		return err;
210	}
211
212	if (!mptcp_pm_is_userspace(msk)) {
213		GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
214		goto remove_err;
215	}
216
217	lock_sock((struct sock *)msk);
218
219	list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
220		if (entry->addr.id == id_val) {
221			match = entry;
222			break;
223		}
224	}
225
226	if (!match) {
227		GENL_SET_ERR_MSG(info, "address with specified id not found");
228		release_sock((struct sock *)msk);
229		goto remove_err;
230	}
231
232	list_move(&match->list, &free_list);
233
234	mptcp_pm_remove_addrs_and_subflows(msk, &free_list);
235
236	release_sock((struct sock *)msk);
237
238	list_for_each_entry_safe(match, entry, &free_list, list) {
239		sock_kfree_s((struct sock *)msk, match, sizeof(*match));
240	}
241
242	err = 0;
243 remove_err:
244	sock_put((struct sock *)msk);
245	return err;
246}
247
248int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
249{
250	struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
251	struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
252	struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
253	struct mptcp_addr_info addr_r;
254	struct mptcp_addr_info addr_l;
255	struct mptcp_sock *msk;
256	int err = -EINVAL;
257	struct sock *sk;
258	u32 token_val;
259
260	if (!laddr || !raddr || !token) {
261		GENL_SET_ERR_MSG(info, "missing required inputs");
262		return err;
263	}
264
265	token_val = nla_get_u32(token);
266
267	msk = mptcp_token_get_sock(genl_info_net(info), token_val);
268	if (!msk) {
269		NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
270		return err;
271	}
272
273	if (!mptcp_pm_is_userspace(msk)) {
274		GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
275		goto create_err;
276	}
277
278	err = mptcp_pm_parse_addr(laddr, info, &addr_l);
279	if (err < 0) {
280		NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr");
281		goto create_err;
282	}
283
284	if (addr_l.id == 0) {
285		NL_SET_ERR_MSG_ATTR(info->extack, laddr, "missing local addr id");
286		err = -EINVAL;
287		goto create_err;
288	}
289
290	err = mptcp_pm_parse_addr(raddr, info, &addr_r);
291	if (err < 0) {
292		NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr");
293		goto create_err;
294	}
295
296	sk = (struct sock *)msk;
297
298	if (!mptcp_pm_addr_families_match(sk, &addr_l, &addr_r)) {
299		GENL_SET_ERR_MSG(info, "families mismatch");
300		err = -EINVAL;
301		goto create_err;
302	}
303
304	lock_sock(sk);
305
306	err = __mptcp_subflow_connect(sk, &addr_l, &addr_r);
307
308	release_sock(sk);
309
310 create_err:
311	sock_put((struct sock *)msk);
312	return err;
313}
314
315static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
316				      const struct mptcp_addr_info *local,
317				      const struct mptcp_addr_info *remote)
318{
319	struct mptcp_subflow_context *subflow;
320
321	if (local->family != remote->family)
322		return NULL;
323
324	mptcp_for_each_subflow(msk, subflow) {
325		const struct inet_sock *issk;
326		struct sock *ssk;
327
328		ssk = mptcp_subflow_tcp_sock(subflow);
329
330		if (local->family != ssk->sk_family)
331			continue;
332
333		issk = inet_sk(ssk);
334
335		switch (ssk->sk_family) {
336		case AF_INET:
337			if (issk->inet_saddr != local->addr.s_addr ||
338			    issk->inet_daddr != remote->addr.s_addr)
339				continue;
340			break;
341#if IS_ENABLED(CONFIG_MPTCP_IPV6)
342		case AF_INET6: {
343			const struct ipv6_pinfo *pinfo = inet6_sk(ssk);
344
345			if (!ipv6_addr_equal(&local->addr6, &pinfo->saddr) ||
346			    !ipv6_addr_equal(&remote->addr6, &ssk->sk_v6_daddr))
347				continue;
348			break;
349		}
350#endif
351		default:
352			continue;
353		}
354
355		if (issk->inet_sport == local->port &&
356		    issk->inet_dport == remote->port)
357			return ssk;
358	}
359
360	return NULL;
361}
362
363int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
364{
365	struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
366	struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
367	struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
368	struct mptcp_addr_info addr_l;
369	struct mptcp_addr_info addr_r;
370	struct mptcp_sock *msk;
371	struct sock *sk, *ssk;
372	int err = -EINVAL;
373	u32 token_val;
374
375	if (!laddr || !raddr || !token) {
376		GENL_SET_ERR_MSG(info, "missing required inputs");
377		return err;
378	}
379
380	token_val = nla_get_u32(token);
381
382	msk = mptcp_token_get_sock(genl_info_net(info), token_val);
383	if (!msk) {
384		NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
385		return err;
386	}
387
388	if (!mptcp_pm_is_userspace(msk)) {
389		GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
390		goto destroy_err;
391	}
392
393	err = mptcp_pm_parse_addr(laddr, info, &addr_l);
394	if (err < 0) {
395		NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr");
396		goto destroy_err;
397	}
398
399	err = mptcp_pm_parse_addr(raddr, info, &addr_r);
400	if (err < 0) {
401		NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr");
402		goto destroy_err;
403	}
404
405	if (addr_l.family != addr_r.family) {
406		GENL_SET_ERR_MSG(info, "address families do not match");
407		err = -EINVAL;
408		goto destroy_err;
409	}
410
411	if (!addr_l.port || !addr_r.port) {
412		GENL_SET_ERR_MSG(info, "missing local or remote port");
413		err = -EINVAL;
414		goto destroy_err;
415	}
416
417	sk = (struct sock *)msk;
418	lock_sock(sk);
419	ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r);
420	if (ssk) {
421		struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
422
423		mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
424		mptcp_close_ssk(sk, ssk, subflow);
425		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
426		err = 0;
427	} else {
428		err = -ESRCH;
429	}
430	release_sock(sk);
431
432destroy_err:
433	sock_put((struct sock *)msk);
434	return err;
435}
436
437int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
438				 struct mptcp_pm_addr_entry *loc,
439				 struct mptcp_pm_addr_entry *rem, u8 bkup)
440{
441	struct mptcp_sock *msk;
442	int ret = -EINVAL;
443	u32 token_val;
444
445	token_val = nla_get_u32(token);
446
447	msk = mptcp_token_get_sock(net, token_val);
448	if (!msk)
449		return ret;
450
451	if (!mptcp_pm_is_userspace(msk))
452		goto set_flags_err;
453
454	if (loc->addr.family == AF_UNSPEC ||
455	    rem->addr.family == AF_UNSPEC)
456		goto set_flags_err;
457
458	lock_sock((struct sock *)msk);
459	ret = mptcp_pm_nl_mp_prio_send_ack(msk, &loc->addr, &rem->addr, bkup);
460	release_sock((struct sock *)msk);
461
462set_flags_err:
463	sock_put((struct sock *)msk);
464	return ret;
465}