diff options
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 40 |
1 files changed, 36 insertions, 4 deletions
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, struct sctp_transport *peer; struct sctp_af *af; union sctp_addr addr; - struct list_head *pos; union sctp_addr_param *addr_param; addr_param = (union sctp_addr_param *) @@ -2738,8 +2737,24 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, return SCTP_ERROR_INV_PARAM; af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); + + /* ADDIP 4.2.1 This parameter MUST NOT contain a broadcast + * or multicast address. + * (note: wildcard is permitted and requires special handling so + * make sure we check for that) + */ + if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb)) + return SCTP_ERROR_INV_PARAM; + switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: + /* Section 4.2.1: + * If the address 0.0.0.0 or ::0 is provided, the source + * address of the packet MUST be added. + */ + if (af->is_any(&addr)) + memcpy(&addr, &asconf->source, sizeof(addr)); + /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address * request and does not have the local resources to add this * new address to the association, it MUST return an Error @@ -2761,8 +2776,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * MUST send an Error Cause TLV with the error cause set to the * new error code 'Request to Delete Last Remaining IP Address'. */ - pos = asoc->peer.transport_addr_list.next; - if (pos->next == &asoc->peer.transport_addr_list) + if (asoc->peer.transport_count == 1) return SCTP_ERROR_DEL_LAST_IP; /* 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, if (sctp_cmp_addr_exact(sctp_source(asconf), &addr)) return SCTP_ERROR_DEL_SRC_IP; - sctp_assoc_del_peer(asoc, &addr); + /* Section 4.2.2 + * If the address 0.0.0.0 or ::0 is provided, all + * addresses of the peer except the source address of the + * packet MUST be deleted. + */ + if (af->is_any(&addr)) { + sctp_assoc_set_primary(asoc, asconf->transport); + sctp_assoc_del_nonprimary_peers(asoc, + asconf->transport); + } else + sctp_assoc_del_peer(asoc, &addr); break; case SCTP_PARAM_SET_PRIMARY: + /* ADDIP Section 4.2.4 + * If the address 0.0.0.0 or ::0 is provided, the receiver + * MAY mark the source address of the packet as its + * primary. + */ + if (af->is_any(&addr)) + memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); + peer = sctp_assoc_lookup_paddr(asoc, &addr); if (!peer) return SCTP_ERROR_INV_PARAM; |