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