aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/associola.c17
-rw-r--r--net/sctp/sm_make_chunk.c40
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 */
734void 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;