fedora core 2.6.10-1.12-FC2
[linux-2.6.git] / net / sctp / sm_make_chunk.c
index c2ca732..1f0676d 100644 (file)
@@ -171,6 +171,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
        struct sctp_opt *sp;
        sctp_supported_addrs_param_t sat;
        __u16 types[2];
+       sctp_adaption_ind_param_t aiparam;
 
        /* RFC 2960 3.3.2 Initiation (INIT) (1)
         *
@@ -196,6 +197,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
        chunksize += sizeof(ecap_param);
        if (sctp_prsctp_enable)
                chunksize += sizeof(prsctp_param);
+       chunksize += sizeof(aiparam);
        chunksize += vparam_len;
 
        /* RFC 2960 3.3.2 Initiation (INIT) (1)
@@ -234,6 +236,10 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
        sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
        if (sctp_prsctp_enable)
                sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
+       aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+       aiparam.param_hdr.length = htons(sizeof(aiparam));
+       aiparam.adaption_ind = htonl(sp->adaption_ind);
+       sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
 nodata:
        if (addrs.v)
                kfree(addrs.v);
@@ -251,6 +257,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
        sctp_cookie_param_t *cookie;
        int cookie_len;
        size_t chunksize;
+       sctp_adaption_ind_param_t aiparam;
 
        retval = NULL;
 
@@ -284,6 +291,8 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
        if (asoc->peer.prsctp_capable)
                chunksize += sizeof(prsctp_param);
 
+       chunksize += sizeof(aiparam);
+
        /* Now allocate and fill out the chunk.  */
        retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
        if (!retval)
@@ -302,6 +311,11 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
        if (asoc->peer.prsctp_capable)
                sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
 
+       aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+       aiparam.param_hdr.length = htons(sizeof(aiparam));
+       aiparam.adaption_ind = htonl(sctp_sk(asoc->base.sk)->adaption_ind);
+       sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
+
        /* We need to remove the const qualifier at this point.  */
        retval->asoc = (struct sctp_association *) asoc;
 
@@ -1297,6 +1311,9 @@ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
        /* Remember PR-SCTP capability. */
        cookie->c.prsctp_capable = asoc->peer.prsctp_capable;
 
+       /* Save adaption indication in the cookie. */
+       cookie->c.adaption_ind = asoc->peer.adaption_ind;
+
        /* Set an expiration time for the cookie.  */
        do_gettimeofday(&cookie->c.expiration);
        TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration);
@@ -1455,6 +1472,7 @@ no_hmac:
        retval->addip_serial = retval->c.initial_tsn;
        retval->adv_peer_ack_point = retval->ctsn_ack_point;
        retval->peer.prsctp_capable = retval->c.prsctp_capable;
+       retval->peer.adaption_ind = retval->c.adaption_ind;
 
        /* The INIT stuff will be done by the side effects.  */
        return retval;
@@ -1661,6 +1679,7 @@ static int sctp_verify_param(const struct sctp_association *asoc,
        case SCTP_PARAM_HEARTBEAT_INFO:
        case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
        case SCTP_PARAM_ECN_CAPABLE:
+       case SCTP_PARAM_ADAPTION_LAYER_IND:
                break;
 
        case SCTP_PARAM_HOST_NAME_ADDRESS:
@@ -1989,6 +2008,10 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
                asoc->peer.ecn_capable = 1;
                break;
 
+       case SCTP_PARAM_ADAPTION_LAYER_IND:
+               asoc->peer.adaption_ind = param.aind->adaption_ind;
+               break;
+
        case SCTP_PARAM_FWD_TSN_SUPPORT:
                if (sctp_prsctp_enable) {
                        asoc->peer.prsctp_capable = 1;
@@ -2459,6 +2482,8 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
        union sctp_addr addr;
        struct sctp_bind_addr *bp = &asoc->base.bind_addr;
        union sctp_addr_param *addr_param;
+       struct list_head *pos;
+       struct sctp_transport *transport;
        int retval = 0;
 
        addr_param = (union sctp_addr_param *)
@@ -2482,6 +2507,12 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
                retval = sctp_del_bind_addr(bp, &addr);
                sctp_write_unlock(&asoc->base.addr_lock);
                sctp_local_bh_enable();
+               list_for_each(pos, &asoc->peer.transport_addr_list) {
+                       transport = list_entry(pos, struct sctp_transport,
+                                                transports);
+                       sctp_transport_route(transport, NULL,
+                                            sctp_sk(asoc->base.sk));
+               }
                break;
        default:
                break;