aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-12-20 17:08:56 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:20 -0500
commit42e30bf3463cd37d73839376662cb79b4d5c416c (patch)
tree18489b96b4af4ec12ebafc8ea1cb9fd3e6756ce1
parent6afd2e83cd86b17b074e1854d063b8ec590d7f5b (diff)
[SCTP]: Handle the wildcard ADD-IP Address parameter
The Address Parameter in the parameter list of the ASCONF chunk may be a wildcard address. In this case special processing is required. For the 'add' case, the source IP of the packet is added. In the 'del' case, all addresses except the source IP of packet are removed. In the "mark primary" case, the source address is marked as primary. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/structs.h2
-rw-r--r--net/sctp/associola.c17
-rw-r--r--net/sctp/sm_make_chunk.c40
3 files changed, 55 insertions, 4 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index bb965742b64e..96621db22466 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1938,6 +1938,8 @@ void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned);
1938void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned); 1938void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned);
1939void sctp_assoc_set_primary(struct sctp_association *, 1939void sctp_assoc_set_primary(struct sctp_association *,
1940 struct sctp_transport *); 1940 struct sctp_transport *);
1941void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
1942 struct sctp_transport *);
1941int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, 1943int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *,
1942 gfp_t); 1944 gfp_t);
1943int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *, 1945int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 33ae9b01131e..61bebb9b96e6 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 3cc629d3c9ff..64790b53323b 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;