~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/sctp/sm_make_chunk.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1075
1075
 
1076
1076
/* Make a HEARTBEAT chunk.  */
1077
1077
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
1078
 
                                  const struct sctp_transport *transport,
1079
 
                                  const void *payload, const size_t paylen)
 
1078
                                  const struct sctp_transport *transport)
1080
1079
{
1081
 
        struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT,
1082
 
                                                    0, paylen);
 
1080
        struct sctp_chunk *retval;
 
1081
        sctp_sender_hb_info_t hbinfo;
 
1082
 
 
1083
        retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo));
1083
1084
 
1084
1085
        if (!retval)
1085
1086
                goto nodata;
1086
1087
 
 
1088
        hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO;
 
1089
        hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t));
 
1090
        hbinfo.daddr = transport->ipaddr;
 
1091
        hbinfo.sent_at = jiffies;
 
1092
        hbinfo.hb_nonce = transport->hb_nonce;
 
1093
 
1087
1094
        /* Cast away the 'const', as this is just telling the chunk
1088
1095
         * what transport it belongs to.
1089
1096
         */
1090
1097
        retval->transport = (struct sctp_transport *) transport;
1091
 
        retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload);
 
1098
        retval->subh.hbs_hdr = sctp_addto_chunk(retval, sizeof(hbinfo),
 
1099
                                                &hbinfo);
1092
1100
 
1093
1101
nodata:
1094
1102
        return retval;
2242
2250
 * Returns 0 on failure, else success.
2243
2251
 * FIXME:  This is an association method.
2244
2252
 */
2245
 
int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
 
2253
int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
2246
2254
                      const union sctp_addr *peer_addr,
2247
2255
                      sctp_init_chunk_t *peer_init, gfp_t gfp)
2248
2256
{
2249
2257
        union sctp_params param;
2250
2258
        struct sctp_transport *transport;
2251
2259
        struct list_head *pos, *temp;
 
2260
        struct sctp_af *af;
 
2261
        union sctp_addr addr;
2252
2262
        char *cookie;
 
2263
        int src_match = 0;
2253
2264
 
2254
2265
        /* We must include the address that the INIT packet came from.
2255
2266
         * This is the only address that matters for an INIT packet.
2261
2272
         * added as the primary transport.  The source address seems to
2262
2273
         * be a a better choice than any of the embedded addresses.
2263
2274
         */
2264
 
        if (peer_addr) {
2265
 
                if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
2266
 
                        goto nomem;
2267
 
        }
 
2275
        if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
 
2276
                goto nomem;
 
2277
 
 
2278
        if (sctp_cmp_addr_exact(sctp_source(chunk), peer_addr))
 
2279
                src_match = 1;
2268
2280
 
2269
2281
        /* Process the initialization parameters.  */
2270
2282
        sctp_walk_params(param, peer_init, init_hdr.params) {
 
2283
                if (!src_match && (param.p->type == SCTP_PARAM_IPV4_ADDRESS ||
 
2284
                    param.p->type == SCTP_PARAM_IPV6_ADDRESS)) {
 
2285
                        af = sctp_get_af_specific(param_type2af(param.p->type));
 
2286
                        af->from_addr_param(&addr, param.addr,
 
2287
                                            chunk->sctp_hdr->source, 0);
 
2288
                        if (sctp_cmp_addr_exact(sctp_source(chunk), &addr))
 
2289
                                src_match = 1;
 
2290
                }
2271
2291
 
2272
2292
                if (!sctp_process_param(asoc, param, peer_addr, gfp))
2273
2293
                        goto clean_up;
2274
2294
        }
2275
2295
 
 
2296
        /* source address of chunk may not match any valid address */
 
2297
        if (!src_match)
 
2298
                goto clean_up;
 
2299
 
2276
2300
        /* AUTH: After processing the parameters, make sure that we
2277
2301
         * have all the required info to potentially do authentications.
2278
2302
         */
2923
2947
            asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY)
2924
2948
                return SCTP_ERROR_UNKNOWN_PARAM;
2925
2949
 
2926
 
        switch (addr_param->v4.param_hdr.type) {
 
2950
        switch (addr_param->p.type) {
2927
2951
        case SCTP_PARAM_IPV6_ADDRESS:
2928
2952
                if (!asoc->peer.ipv6_address)
2929
2953
                        return SCTP_ERROR_DNS_FAILED;
2936
2960
                return SCTP_ERROR_DNS_FAILED;
2937
2961
        }
2938
2962
 
2939
 
        af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
 
2963
        af = sctp_get_af_specific(param_type2af(addr_param->p.type));
2940
2964
        if (unlikely(!af))
2941
2965
                return SCTP_ERROR_DNS_FAILED;
2942
2966
 
3100
3124
        /* Skip the address parameter and store a pointer to the first
3101
3125
         * asconf parameter.
3102
3126
         */
3103
 
        length = ntohs(addr_param->v4.param_hdr.length);
 
3127
        length = ntohs(addr_param->p.length);
3104
3128
        asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
3105
3129
        chunk_len -= length;
3106
3130
 
3107
3131
        /* create an ASCONF_ACK chunk.
3108
3132
         * Based on the definitions of parameters, we know that the size of
3109
 
         * ASCONF_ACK parameters are less than or equal to the twice of ASCONF
 
3133
         * ASCONF_ACK parameters are less than or equal to the fourfold of ASCONF
3110
3134
         * parameters.
3111
3135
         */
3112
 
        asconf_ack = sctp_make_asconf_ack(asoc, serial, chunk_len * 2);
 
3136
        asconf_ack = sctp_make_asconf_ack(asoc, serial, chunk_len * 4);
3113
3137
        if (!asconf_ack)
3114
3138
                goto done;
3115
3139
 
3177
3201
                        ((void *)asconf_param + sizeof(sctp_addip_param_t));
3178
3202
 
3179
3203
        /* We have checked the packet before, so we do not check again. */
3180
 
        af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
 
3204
        af = sctp_get_af_specific(param_type2af(addr_param->p.type));
3181
3205
        af->from_addr_param(&addr, addr_param, htons(bp->port), 0);
3182
3206
 
3183
3207
        switch (asconf_param->param_hdr.type) {
3193
3217
                local_bh_enable();
3194
3218
                list_for_each_entry(transport, &asoc->peer.transport_addr_list,
3195
3219
                                transports) {
3196
 
                        if (transport->state == SCTP_ACTIVE)
3197
 
                                continue;
3198
3220
                        dst_release(transport->dst);
3199
 
                        sctp_transport_route(transport, NULL,
3200
 
                                             sctp_sk(asoc->base.sk));
 
3221
                        transport->dst = NULL;
3201
3222
                }
3202
3223
                break;
3203
3224
        case SCTP_PARAM_DEL_IP:
3207
3228
                list_for_each_entry(transport, &asoc->peer.transport_addr_list,
3208
3229
                                transports) {
3209
3230
                        dst_release(transport->dst);
3210
 
                        sctp_transport_route(transport, NULL,
3211
 
                                             sctp_sk(asoc->base.sk));
 
3231
                        transport->dst = NULL;
3212
3232
                }
3213
3233
                break;
3214
3234
        default:
3304
3324
        /* Skip the address parameter in the last asconf sent and store a
3305
3325
         * pointer to the first asconf parameter.
3306
3326
         */
3307
 
        length = ntohs(addr_param->v4.param_hdr.length);
 
3327
        length = ntohs(addr_param->p.length);
3308
3328
        asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
3309
3329
        asconf_len -= length;
3310
3330
 
3375
3395
                                    struct sctp_fwdtsn_skip *skiplist)
3376
3396
{
3377
3397
        struct sctp_chunk *retval = NULL;
3378
 
        struct sctp_fwdtsn_chunk *ftsn_chunk;
3379
3398
        struct sctp_fwdtsn_hdr ftsn_hdr;
3380
3399
        struct sctp_fwdtsn_skip skip;
3381
3400
        size_t hint;
3388
3407
        if (!retval)
3389
3408
                return NULL;
3390
3409
 
3391
 
        ftsn_chunk = (struct sctp_fwdtsn_chunk *)retval->subh.fwdtsn_hdr;
3392
 
 
3393
3410
        ftsn_hdr.new_cum_tsn = htonl(new_cum_tsn);
3394
3411
        retval->subh.fwdtsn_hdr =
3395
3412
                sctp_addto_chunk(retval, sizeof(ftsn_hdr), &ftsn_hdr);