diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 17 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 40 |
2 files changed, 53 insertions, 4 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 33ae9b01131..61bebb9b96e 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -730,6 +730,23 @@ struct sctp_transport *sctp_assoc_lookup_paddr( | |||
730 | return NULL; | 730 | return NULL; |
731 | } | 731 | } |
732 | 732 | ||
733 | /* Remove all transports except a give one */ | ||
734 | void sctp_assoc_del_nonprimary_peers(struct sctp_association *asoc, | ||
735 | struct sctp_transport *primary) | ||
736 | { | ||
737 | struct sctp_transport *temp; | ||
738 | struct sctp_transport *t; | ||
739 | |||
740 | list_for_each_entry_safe(t, temp, &asoc->peer.transport_addr_list, | ||
741 | transports) { | ||
742 | /* if the current transport is not the primary one, delete it */ | ||
743 | if (t != primary) | ||
744 | sctp_assoc_rm_peer(asoc, t); | ||
745 | } | ||
746 | |||
747 | return; | ||
748 | } | ||
749 | |||
733 | /* Engage in transport control operations. | 750 | /* Engage in transport control operations. |
734 | * Mark the transport up or down and send a notification to the user. | 751 | * Mark the transport up or down and send a notification to the user. |
735 | * Select and update the new active and retran paths. | 752 | * Select and update the new active and retran paths. |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 3cc629d3c9f..64790b53323 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -2727,7 +2727,6 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2727 | struct sctp_transport *peer; | 2727 | struct sctp_transport *peer; |
2728 | struct sctp_af *af; | 2728 | struct sctp_af *af; |
2729 | union sctp_addr addr; | 2729 | union sctp_addr addr; |
2730 | struct list_head *pos; | ||
2731 | union sctp_addr_param *addr_param; | 2730 | union sctp_addr_param *addr_param; |
2732 | 2731 | ||
2733 | addr_param = (union sctp_addr_param *) | 2732 | addr_param = (union sctp_addr_param *) |
@@ -2738,8 +2737,24 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2738 | return SCTP_ERROR_INV_PARAM; | 2737 | return SCTP_ERROR_INV_PARAM; |
2739 | 2738 | ||
2740 | af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); | 2739 | af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); |
2740 | |||
2741 | /* ADDIP 4.2.1 This parameter MUST NOT contain a broadcast | ||
2742 | * or multicast address. | ||
2743 | * (note: wildcard is permitted and requires special handling so | ||
2744 | * make sure we check for that) | ||
2745 | */ | ||
2746 | if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb)) | ||
2747 | return SCTP_ERROR_INV_PARAM; | ||
2748 | |||
2741 | switch (asconf_param->param_hdr.type) { | 2749 | switch (asconf_param->param_hdr.type) { |
2742 | case SCTP_PARAM_ADD_IP: | 2750 | case SCTP_PARAM_ADD_IP: |
2751 | /* Section 4.2.1: | ||
2752 | * If the address 0.0.0.0 or ::0 is provided, the source | ||
2753 | * address of the packet MUST be added. | ||
2754 | */ | ||
2755 | if (af->is_any(&addr)) | ||
2756 | memcpy(&addr, &asconf->source, sizeof(addr)); | ||
2757 | |||
2743 | /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address | 2758 | /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address |
2744 | * request and does not have the local resources to add this | 2759 | * request and does not have the local resources to add this |
2745 | * new address to the association, it MUST return an Error | 2760 | * new address to the association, it MUST return an Error |
@@ -2761,8 +2776,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2761 | * MUST send an Error Cause TLV with the error cause set to the | 2776 | * MUST send an Error Cause TLV with the error cause set to the |
2762 | * new error code 'Request to Delete Last Remaining IP Address'. | 2777 | * new error code 'Request to Delete Last Remaining IP Address'. |
2763 | */ | 2778 | */ |
2764 | pos = asoc->peer.transport_addr_list.next; | 2779 | if (asoc->peer.transport_count == 1) |
2765 | if (pos->next == &asoc->peer.transport_addr_list) | ||
2766 | return SCTP_ERROR_DEL_LAST_IP; | 2780 | return SCTP_ERROR_DEL_LAST_IP; |
2767 | 2781 | ||
2768 | /* ADDIP 4.3 D8) If a request is received to delete an IP | 2782 | /* ADDIP 4.3 D8) If a request is received to delete an IP |
@@ -2775,9 +2789,27 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2775 | if (sctp_cmp_addr_exact(sctp_source(asconf), &addr)) | 2789 | if (sctp_cmp_addr_exact(sctp_source(asconf), &addr)) |
2776 | return SCTP_ERROR_DEL_SRC_IP; | 2790 | return SCTP_ERROR_DEL_SRC_IP; |
2777 | 2791 | ||
2778 | sctp_assoc_del_peer(asoc, &addr); | 2792 | /* Section 4.2.2 |
2793 | * If the address 0.0.0.0 or ::0 is provided, all | ||
2794 | * addresses of the peer except the source address of the | ||
2795 | * packet MUST be deleted. | ||
2796 | */ | ||
2797 | if (af->is_any(&addr)) { | ||
2798 | sctp_assoc_set_primary(asoc, asconf->transport); | ||
2799 | sctp_assoc_del_nonprimary_peers(asoc, | ||
2800 | asconf->transport); | ||
2801 | } else | ||
2802 | sctp_assoc_del_peer(asoc, &addr); | ||
2779 | break; | 2803 | break; |
2780 | case SCTP_PARAM_SET_PRIMARY: | 2804 | case SCTP_PARAM_SET_PRIMARY: |
2805 | /* ADDIP Section 4.2.4 | ||
2806 | * If the address 0.0.0.0 or ::0 is provided, the receiver | ||
2807 | * MAY mark the source address of the packet as its | ||
2808 | * primary. | ||
2809 | */ | ||
2810 | if (af->is_any(&addr)) | ||
2811 | memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); | ||
2812 | |||
2781 | peer = sctp_assoc_lookup_paddr(asoc, &addr); | 2813 | peer = sctp_assoc_lookup_paddr(asoc, &addr); |
2782 | if (!peer) | 2814 | if (!peer) |
2783 | return SCTP_ERROR_INV_PARAM; | 2815 | return SCTP_ERROR_INV_PARAM; |