diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 74 |
1 files changed, 59 insertions, 15 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0a2c71d0d8aa..54722e622e6d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -369,7 +369,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
| 369 | 369 | ||
| 370 | /* Use GFP_ATOMIC since BHs are disabled. */ | 370 | /* Use GFP_ATOMIC since BHs are disabled. */ |
| 371 | addr->v4.sin_port = ntohs(addr->v4.sin_port); | 371 | addr->v4.sin_port = ntohs(addr->v4.sin_port); |
| 372 | ret = sctp_add_bind_addr(bp, addr, GFP_ATOMIC); | 372 | ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC); |
| 373 | addr->v4.sin_port = htons(addr->v4.sin_port); | 373 | addr->v4.sin_port = htons(addr->v4.sin_port); |
| 374 | sctp_write_unlock(&ep->base.addr_lock); | 374 | sctp_write_unlock(&ep->base.addr_lock); |
| 375 | sctp_local_bh_enable(); | 375 | sctp_local_bh_enable(); |
| @@ -491,6 +491,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
| 491 | struct sctp_chunk *chunk; | 491 | struct sctp_chunk *chunk; |
| 492 | struct sctp_sockaddr_entry *laddr; | 492 | struct sctp_sockaddr_entry *laddr; |
| 493 | union sctp_addr *addr; | 493 | union sctp_addr *addr; |
| 494 | union sctp_addr saveaddr; | ||
| 494 | void *addr_buf; | 495 | void *addr_buf; |
| 495 | struct sctp_af *af; | 496 | struct sctp_af *af; |
| 496 | struct list_head *pos; | 497 | struct list_head *pos; |
| @@ -558,14 +559,26 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
| 558 | } | 559 | } |
| 559 | 560 | ||
| 560 | retval = sctp_send_asconf(asoc, chunk); | 561 | retval = sctp_send_asconf(asoc, chunk); |
| 562 | if (retval) | ||
| 563 | goto out; | ||
| 561 | 564 | ||
| 562 | /* FIXME: After sending the add address ASCONF chunk, we | 565 | /* Add the new addresses to the bind address list with |
| 563 | * cannot append the address to the association's binding | 566 | * use_as_src set to 0. |
| 564 | * address list, because the new address may be used as the | ||
| 565 | * source of a message sent to the peer before the ASCONF | ||
| 566 | * chunk is received by the peer. So we should wait until | ||
| 567 | * ASCONF_ACK is received. | ||
| 568 | */ | 567 | */ |
| 568 | sctp_local_bh_disable(); | ||
| 569 | sctp_write_lock(&asoc->base.addr_lock); | ||
| 570 | addr_buf = addrs; | ||
| 571 | for (i = 0; i < addrcnt; i++) { | ||
| 572 | addr = (union sctp_addr *)addr_buf; | ||
| 573 | af = sctp_get_af_specific(addr->v4.sin_family); | ||
| 574 | memcpy(&saveaddr, addr, af->sockaddr_len); | ||
| 575 | saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); | ||
| 576 | retval = sctp_add_bind_addr(bp, &saveaddr, 0, | ||
| 577 | GFP_ATOMIC); | ||
| 578 | addr_buf += af->sockaddr_len; | ||
| 579 | } | ||
| 580 | sctp_write_unlock(&asoc->base.addr_lock); | ||
| 581 | sctp_local_bh_enable(); | ||
| 569 | } | 582 | } |
| 570 | 583 | ||
| 571 | out: | 584 | out: |
| @@ -676,12 +689,15 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
| 676 | struct sctp_sock *sp; | 689 | struct sctp_sock *sp; |
| 677 | struct sctp_endpoint *ep; | 690 | struct sctp_endpoint *ep; |
| 678 | struct sctp_association *asoc; | 691 | struct sctp_association *asoc; |
| 692 | struct sctp_transport *transport; | ||
| 679 | struct sctp_bind_addr *bp; | 693 | struct sctp_bind_addr *bp; |
| 680 | struct sctp_chunk *chunk; | 694 | struct sctp_chunk *chunk; |
| 681 | union sctp_addr *laddr; | 695 | union sctp_addr *laddr; |
| 696 | union sctp_addr saveaddr; | ||
| 682 | void *addr_buf; | 697 | void *addr_buf; |
| 683 | struct sctp_af *af; | 698 | struct sctp_af *af; |
| 684 | struct list_head *pos; | 699 | struct list_head *pos, *pos1; |
| 700 | struct sctp_sockaddr_entry *saddr; | ||
| 685 | int i; | 701 | int i; |
| 686 | int retval = 0; | 702 | int retval = 0; |
| 687 | 703 | ||
| @@ -748,14 +764,42 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
| 748 | goto out; | 764 | goto out; |
| 749 | } | 765 | } |
| 750 | 766 | ||
| 751 | retval = sctp_send_asconf(asoc, chunk); | 767 | /* Reset use_as_src flag for the addresses in the bind address |
| 768 | * list that are to be deleted. | ||
| 769 | */ | ||
| 770 | sctp_local_bh_disable(); | ||
| 771 | sctp_write_lock(&asoc->base.addr_lock); | ||
| 772 | addr_buf = addrs; | ||
| 773 | for (i = 0; i < addrcnt; i++) { | ||
| 774 | laddr = (union sctp_addr *)addr_buf; | ||
| 775 | af = sctp_get_af_specific(laddr->v4.sin_family); | ||
| 776 | memcpy(&saveaddr, laddr, af->sockaddr_len); | ||
| 777 | saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); | ||
| 778 | list_for_each(pos1, &bp->address_list) { | ||
| 779 | saddr = list_entry(pos1, | ||
| 780 | struct sctp_sockaddr_entry, | ||
| 781 | list); | ||
| 782 | if (sctp_cmp_addr_exact(&saddr->a, &saveaddr)) | ||
| 783 | saddr->use_as_src = 0; | ||
| 784 | } | ||
| 785 | addr_buf += af->sockaddr_len; | ||
| 786 | } | ||
| 787 | sctp_write_unlock(&asoc->base.addr_lock); | ||
| 788 | sctp_local_bh_enable(); | ||
| 752 | 789 | ||
| 753 | /* FIXME: After sending the delete address ASCONF chunk, we | 790 | /* Update the route and saddr entries for all the transports |
| 754 | * cannot remove the addresses from the association's bind | 791 | * as some of the addresses in the bind address list are |
| 755 | * address list, because there maybe some packet send to | 792 | * about to be deleted and cannot be used as source addresses. |
| 756 | * the delete addresses, so we should wait until ASCONF_ACK | ||
| 757 | * packet is received. | ||
| 758 | */ | 793 | */ |
| 794 | list_for_each(pos1, &asoc->peer.transport_addr_list) { | ||
| 795 | transport = list_entry(pos1, struct sctp_transport, | ||
| 796 | transports); | ||
| 797 | dst_release(transport->dst); | ||
| 798 | sctp_transport_route(transport, NULL, | ||
| 799 | sctp_sk(asoc->base.sk)); | ||
| 800 | } | ||
| 801 | |||
| 802 | retval = sctp_send_asconf(asoc, chunk); | ||
| 759 | } | 803 | } |
| 760 | out: | 804 | out: |
| 761 | return retval; | 805 | return retval; |
| @@ -4977,7 +5021,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
| 4977 | /* Caller must hold hashbucket lock for this tb with local BH disabled */ | 5021 | /* Caller must hold hashbucket lock for this tb with local BH disabled */ |
| 4978 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) | 5022 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) |
| 4979 | { | 5023 | { |
| 4980 | if (hlist_empty(&pp->owner)) { | 5024 | if (pp && hlist_empty(&pp->owner)) { |
| 4981 | if (pp->next) | 5025 | if (pp->next) |
| 4982 | pp->next->pprev = pp->pprev; | 5026 | pp->next->pprev = pp->pprev; |
| 4983 | *(pp->pprev) = pp->next; | 5027 | *(pp->pprev) = pp->next; |
