return retval;
}
+struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc)
+{
+ struct sctp_chunk *retval;
+ struct sctp_hmac *hmac_desc;
+ struct sctp_authhdr auth_hdr;
+ __u8 *hmac;
+
+ /* Get the first hmac that the peer told us to use */
+ hmac_desc = sctp_auth_asoc_get_hmac(asoc);
+ if (unlikely(!hmac_desc))
+ return NULL;
+
+ retval = sctp_make_chunk(asoc, SCTP_CID_AUTH, 0,
+ hmac_desc->hmac_len + sizeof(sctp_authhdr_t));
+ if (!retval)
+ return NULL;
+
+ auth_hdr.hmac_id = htons(hmac_desc->hmac_id);
+ auth_hdr.shkey_id = htons(asoc->active_key_id);
+
+ retval->subh.auth_hdr = sctp_addto_chunk(retval, sizeof(sctp_authhdr_t),
+ &auth_hdr);
+
+ hmac = skb_put(retval->skb, hmac_desc->hmac_len);
+ memset(hmac, 0, hmac_desc->hmac_len);
+
+ /* Adjust the chunk header to include the empty MAC */
+ retval->chunk_hdr->length =
+ htons(ntohs(retval->chunk_hdr->length) + hmac_desc->hmac_len);
+ retval->chunk_end = skb_tail_pointer(retval->skb);
+
+ return retval;
+}
+
+
/********************************************************************
* 2nd Level Abstractions
********************************************************************/
retval->chunk_hdr = chunk_hdr;
retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);
+ /* Determine if the chunk needs to be authenticated */
+ if (sctp_auth_send_cid(type, asoc))
+ retval->auth = 1;
+
/* Set the skb to the belonging sock for accounting. */
skb->sk = sk;
break;
case SCTP_CID_ASCONF:
case SCTP_CID_ASCONF_ACK:
- /* don't need to do anything for ASCONF */
+ asoc->peer.addip_capable = 1;
+ break;
default:
break;
}
!asoc->peer.peer_hmacs))
asoc->peer.auth_capable = 0;
+
+ /* If the peer claims support for ADD-IP without support
+ * for AUTH, disable support for ADD-IP.
+ */
+ if (asoc->peer.addip_capable && !asoc->peer.auth_capable) {
+ asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP |
+ SCTP_PARAM_DEL_IP |
+ SCTP_PARAM_SET_PRIMARY);
+ }
+
/* Walk list of transports, removing transports in the UNKNOWN state. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports);