diff options
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b3434cc7d0cf..58eb27fed4b4 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1075,20 +1075,28 @@ nodata: | |||
1075 | 1075 | ||
1076 | /* Make a HEARTBEAT chunk. */ | 1076 | /* Make a HEARTBEAT chunk. */ |
1077 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1077 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1078 | const struct sctp_transport *transport, | 1078 | const struct sctp_transport *transport) |
1079 | const void *payload, const size_t paylen) | ||
1080 | { | 1079 | { |
1081 | struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, | 1080 | struct sctp_chunk *retval; |
1082 | 0, paylen); | 1081 | sctp_sender_hb_info_t hbinfo; |
1082 | |||
1083 | retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo)); | ||
1083 | 1084 | ||
1084 | if (!retval) | 1085 | if (!retval) |
1085 | goto nodata; | 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 | /* Cast away the 'const', as this is just telling the chunk | 1094 | /* Cast away the 'const', as this is just telling the chunk |
1088 | * what transport it belongs to. | 1095 | * what transport it belongs to. |
1089 | */ | 1096 | */ |
1090 | retval->transport = (struct sctp_transport *) transport; | 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 | nodata: | 1101 | nodata: |
1094 | return retval; | 1102 | return retval; |
@@ -2242,14 +2250,17 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2242 | * Returns 0 on failure, else success. | 2250 | * Returns 0 on failure, else success. |
2243 | * FIXME: This is an association method. | 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 | const union sctp_addr *peer_addr, | 2254 | const union sctp_addr *peer_addr, |
2247 | sctp_init_chunk_t *peer_init, gfp_t gfp) | 2255 | sctp_init_chunk_t *peer_init, gfp_t gfp) |
2248 | { | 2256 | { |
2249 | union sctp_params param; | 2257 | union sctp_params param; |
2250 | struct sctp_transport *transport; | 2258 | struct sctp_transport *transport; |
2251 | struct list_head *pos, *temp; | 2259 | struct list_head *pos, *temp; |
2260 | struct sctp_af *af; | ||
2261 | union sctp_addr addr; | ||
2252 | char *cookie; | 2262 | char *cookie; |
2263 | int src_match = 0; | ||
2253 | 2264 | ||
2254 | /* We must include the address that the INIT packet came from. | 2265 | /* We must include the address that the INIT packet came from. |
2255 | * This is the only address that matters for an INIT packet. | 2266 | * This is the only address that matters for an INIT packet. |
@@ -2261,18 +2272,31 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
2261 | * added as the primary transport. The source address seems to | 2272 | * added as the primary transport. The source address seems to |
2262 | * be a a better choice than any of the embedded addresses. | 2273 | * be a a better choice than any of the embedded addresses. |
2263 | */ | 2274 | */ |
2264 | if (peer_addr) { | 2275 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
2265 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) | 2276 | goto nomem; |
2266 | goto nomem; | 2277 | |
2267 | } | 2278 | if (sctp_cmp_addr_exact(sctp_source(chunk), peer_addr)) |
2279 | src_match = 1; | ||
2268 | 2280 | ||
2269 | /* Process the initialization parameters. */ | 2281 | /* Process the initialization parameters. */ |
2270 | sctp_walk_params(param, peer_init, init_hdr.params) { | 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 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) | 2292 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) |
2273 | goto clean_up; | 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 | /* AUTH: After processing the parameters, make sure that we | 2300 | /* AUTH: After processing the parameters, make sure that we |
2277 | * have all the required info to potentially do authentications. | 2301 | * have all the required info to potentially do authentications. |
2278 | */ | 2302 | */ |
@@ -2923,7 +2947,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2923 | asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY) | 2947 | asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY) |
2924 | return SCTP_ERROR_UNKNOWN_PARAM; | 2948 | return SCTP_ERROR_UNKNOWN_PARAM; |
2925 | 2949 | ||
2926 | switch (addr_param->v4.param_hdr.type) { | 2950 | switch (addr_param->p.type) { |
2927 | case SCTP_PARAM_IPV6_ADDRESS: | 2951 | case SCTP_PARAM_IPV6_ADDRESS: |
2928 | if (!asoc->peer.ipv6_address) | 2952 | if (!asoc->peer.ipv6_address) |
2929 | return SCTP_ERROR_DNS_FAILED; | 2953 | return SCTP_ERROR_DNS_FAILED; |
@@ -2936,7 +2960,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2936 | return SCTP_ERROR_DNS_FAILED; | 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 | if (unlikely(!af)) | 2964 | if (unlikely(!af)) |
2941 | return SCTP_ERROR_DNS_FAILED; | 2965 | return SCTP_ERROR_DNS_FAILED; |
2942 | 2966 | ||
@@ -3100,7 +3124,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, | |||
3100 | /* Skip the address parameter and store a pointer to the first | 3124 | /* Skip the address parameter and store a pointer to the first |
3101 | * asconf parameter. | 3125 | * asconf parameter. |
3102 | */ | 3126 | */ |
3103 | length = ntohs(addr_param->v4.param_hdr.length); | 3127 | length = ntohs(addr_param->p.length); |
3104 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); | 3128 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); |
3105 | chunk_len -= length; | 3129 | chunk_len -= length; |
3106 | 3130 | ||
@@ -3177,7 +3201,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, | |||
3177 | ((void *)asconf_param + sizeof(sctp_addip_param_t)); | 3201 | ((void *)asconf_param + sizeof(sctp_addip_param_t)); |
3178 | 3202 | ||
3179 | /* We have checked the packet before, so we do not check again. */ | 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 | af->from_addr_param(&addr, addr_param, htons(bp->port), 0); | 3205 | af->from_addr_param(&addr, addr_param, htons(bp->port), 0); |
3182 | 3206 | ||
3183 | switch (asconf_param->param_hdr.type) { | 3207 | switch (asconf_param->param_hdr.type) { |
@@ -3193,11 +3217,8 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, | |||
3193 | local_bh_enable(); | 3217 | local_bh_enable(); |
3194 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, | 3218 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, |
3195 | transports) { | 3219 | transports) { |
3196 | if (transport->state == SCTP_ACTIVE) | ||
3197 | continue; | ||
3198 | dst_release(transport->dst); | 3220 | dst_release(transport->dst); |
3199 | sctp_transport_route(transport, NULL, | 3221 | transport->dst = NULL; |
3200 | sctp_sk(asoc->base.sk)); | ||
3201 | } | 3222 | } |
3202 | break; | 3223 | break; |
3203 | case SCTP_PARAM_DEL_IP: | 3224 | case SCTP_PARAM_DEL_IP: |
@@ -3207,8 +3228,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, | |||
3207 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, | 3228 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, |
3208 | transports) { | 3229 | transports) { |
3209 | dst_release(transport->dst); | 3230 | dst_release(transport->dst); |
3210 | sctp_transport_route(transport, NULL, | 3231 | transport->dst = NULL; |
3211 | sctp_sk(asoc->base.sk)); | ||
3212 | } | 3232 | } |
3213 | break; | 3233 | break; |
3214 | default: | 3234 | default: |
@@ -3304,7 +3324,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
3304 | /* Skip the address parameter in the last asconf sent and store a | 3324 | /* Skip the address parameter in the last asconf sent and store a |
3305 | * pointer to the first asconf parameter. | 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 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); | 3328 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); |
3309 | asconf_len -= length; | 3329 | asconf_len -= length; |
3310 | 3330 | ||