[SCTP]: Tie ADD-IP and AUTH functionality as required by spec.
[powerpc.git] / net / sctp / sm_make_chunk.c
index 4c02875..f983a36 100644 (file)
@@ -1111,6 +1111,41 @@ nodata:
        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
  ********************************************************************/
@@ -1225,6 +1260,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
        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;
 
@@ -1812,7 +1851,8 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
                            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;
                }
@@ -2098,6 +2138,16 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
                                        !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);