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