| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* SCTP kernel implementation |
|---|
| 2 | 3 | * (C) Copyright IBM Corp. 2001, 2003 |
|---|
| 3 | 4 | * Copyright (c) Cisco 1999,2000 |
|---|
| .. | .. |
|---|
| 7 | 8 | * This file is part of the SCTP kernel implementation. |
|---|
| 8 | 9 | * |
|---|
| 9 | 10 | * A collection class to handle the storage of transport addresses. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This SCTP implementation is free software; |
|---|
| 12 | | - * you can redistribute it and/or modify it under the terms of |
|---|
| 13 | | - * the GNU General Public License as published by |
|---|
| 14 | | - * the Free Software Foundation; either version 2, or (at your option) |
|---|
| 15 | | - * any later version. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This SCTP implementation is distributed in the hope that it |
|---|
| 18 | | - * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
|---|
| 19 | | - * ************************ |
|---|
| 20 | | - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|---|
| 21 | | - * See the GNU General Public License for more details. |
|---|
| 22 | | - * |
|---|
| 23 | | - * You should have received a copy of the GNU General Public License |
|---|
| 24 | | - * along with GNU CC; see the file COPYING. If not, see |
|---|
| 25 | | - * <http://www.gnu.org/licenses/>. |
|---|
| 26 | 11 | * |
|---|
| 27 | 12 | * Please send any bug reports or fixes you make to the |
|---|
| 28 | 13 | * email address(es): |
|---|
| .. | .. |
|---|
| 87 | 72 | goto out; |
|---|
| 88 | 73 | } |
|---|
| 89 | 74 | } |
|---|
| 75 | + |
|---|
| 76 | + /* If somehow no addresses were found that can be used with this |
|---|
| 77 | + * scope, it's an error. |
|---|
| 78 | + */ |
|---|
| 79 | + if (list_empty(&dest->address_list)) |
|---|
| 80 | + error = -ENETUNREACH; |
|---|
| 90 | 81 | |
|---|
| 91 | 82 | out: |
|---|
| 92 | 83 | if (error) |
|---|
| .. | .. |
|---|
| 340 | 331 | return match; |
|---|
| 341 | 332 | } |
|---|
| 342 | 333 | |
|---|
| 334 | +int sctp_bind_addrs_check(struct sctp_sock *sp, |
|---|
| 335 | + struct sctp_sock *sp2, int cnt2) |
|---|
| 336 | +{ |
|---|
| 337 | + struct sctp_bind_addr *bp2 = &sp2->ep->base.bind_addr; |
|---|
| 338 | + struct sctp_bind_addr *bp = &sp->ep->base.bind_addr; |
|---|
| 339 | + struct sctp_sockaddr_entry *laddr, *laddr2; |
|---|
| 340 | + bool exist = false; |
|---|
| 341 | + int cnt = 0; |
|---|
| 342 | + |
|---|
| 343 | + rcu_read_lock(); |
|---|
| 344 | + list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
|---|
| 345 | + list_for_each_entry_rcu(laddr2, &bp2->address_list, list) { |
|---|
| 346 | + if (sp->pf->af->cmp_addr(&laddr->a, &laddr2->a) && |
|---|
| 347 | + laddr->valid && laddr2->valid) { |
|---|
| 348 | + exist = true; |
|---|
| 349 | + goto next; |
|---|
| 350 | + } |
|---|
| 351 | + } |
|---|
| 352 | + cnt = 0; |
|---|
| 353 | + break; |
|---|
| 354 | +next: |
|---|
| 355 | + cnt++; |
|---|
| 356 | + } |
|---|
| 357 | + rcu_read_unlock(); |
|---|
| 358 | + |
|---|
| 359 | + return (cnt == cnt2) ? 0 : (exist ? -EEXIST : 1); |
|---|
| 360 | +} |
|---|
| 361 | + |
|---|
| 343 | 362 | /* Does the address 'addr' conflict with any addresses in |
|---|
| 344 | 363 | * the bp. |
|---|
| 345 | 364 | */ |
|---|
| .. | .. |
|---|
| 383 | 402 | { |
|---|
| 384 | 403 | struct sctp_sockaddr_entry *laddr; |
|---|
| 385 | 404 | struct sctp_af *af; |
|---|
| 386 | | - int state = -1; |
|---|
| 387 | 405 | |
|---|
| 388 | 406 | af = sctp_get_af_specific(addr->sa.sa_family); |
|---|
| 389 | 407 | if (unlikely(!af)) |
|---|
| 390 | | - return state; |
|---|
| 408 | + return -1; |
|---|
| 391 | 409 | |
|---|
| 392 | | - rcu_read_lock(); |
|---|
| 393 | 410 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
|---|
| 394 | 411 | if (!laddr->valid) |
|---|
| 395 | 412 | continue; |
|---|
| 396 | | - if (af->cmp_addr(&laddr->a, addr)) { |
|---|
| 397 | | - state = laddr->state; |
|---|
| 398 | | - break; |
|---|
| 399 | | - } |
|---|
| 413 | + if (af->cmp_addr(&laddr->a, addr)) |
|---|
| 414 | + return laddr->state; |
|---|
| 400 | 415 | } |
|---|
| 401 | | - rcu_read_unlock(); |
|---|
| 402 | 416 | |
|---|
| 403 | | - return state; |
|---|
| 417 | + return -1; |
|---|
| 404 | 418 | } |
|---|
| 405 | 419 | |
|---|
| 406 | 420 | /* Find the first address in the bind address list that is not present in |
|---|
| .. | .. |
|---|
| 500 | 514 | return 0; |
|---|
| 501 | 515 | /* |
|---|
| 502 | 516 | * For INIT and INIT-ACK address list, let L be the level of |
|---|
| 503 | | - * of requested destination address, sender and receiver |
|---|
| 517 | + * requested destination address, sender and receiver |
|---|
| 504 | 518 | * SHOULD include all of its addresses with level greater |
|---|
| 505 | 519 | * than or equal to L. |
|---|
| 506 | 520 | * |
|---|