diff options
-rw-r--r-- | include/net/sctp/structs.h | 2 | ||||
-rw-r--r-- | net/sctp/bind_addr.c | 26 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 52 |
3 files changed, 76 insertions, 4 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 2528f8a837d9..4d591bfce452 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -1200,6 +1200,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, | |||
1200 | int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); | 1200 | int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); |
1201 | int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, | 1201 | int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, |
1202 | struct sctp_sock *); | 1202 | struct sctp_sock *); |
1203 | int sctp_bind_addr_state(const struct sctp_bind_addr *bp, | ||
1204 | const union sctp_addr *addr); | ||
1203 | union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, | 1205 | union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, |
1204 | const union sctp_addr *addrs, | 1206 | const union sctp_addr *addrs, |
1205 | int addrcnt, | 1207 | int addrcnt, |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 432661174789..13fbfb449a55 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -353,6 +353,32 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, | |||
353 | return match; | 353 | return match; |
354 | } | 354 | } |
355 | 355 | ||
356 | /* Get the state of the entry in the bind_addr_list */ | ||
357 | int sctp_bind_addr_state(const struct sctp_bind_addr *bp, | ||
358 | const union sctp_addr *addr) | ||
359 | { | ||
360 | struct sctp_sockaddr_entry *laddr; | ||
361 | struct sctp_af *af; | ||
362 | int state = -1; | ||
363 | |||
364 | af = sctp_get_af_specific(addr->sa.sa_family); | ||
365 | if (unlikely(!af)) | ||
366 | return state; | ||
367 | |||
368 | rcu_read_lock(); | ||
369 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
370 | if (!laddr->valid) | ||
371 | continue; | ||
372 | if (af->cmp_addr(&laddr->a, addr)) { | ||
373 | state = laddr->state; | ||
374 | break; | ||
375 | } | ||
376 | } | ||
377 | rcu_read_unlock(); | ||
378 | |||
379 | return state; | ||
380 | } | ||
381 | |||
356 | /* Find the first address in the bind address list that is not present in | 382 | /* Find the first address in the bind address list that is not present in |
357 | * the addrs packed array. | 383 | * the addrs packed array. |
358 | */ | 384 | */ |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index a1be9d93f1a8..0c9f37eb7d8d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -143,6 +143,12 @@ static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep, | |||
143 | const sctp_subtype_t type, | 143 | const sctp_subtype_t type, |
144 | struct sctp_chunk *chunk); | 144 | struct sctp_chunk *chunk); |
145 | 145 | ||
146 | static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | ||
147 | const struct sctp_association *asoc, | ||
148 | const sctp_subtype_t type, | ||
149 | void *arg, | ||
150 | sctp_cmd_seq_t *commands); | ||
151 | |||
146 | /* Small helper function that checks if the chunk length | 152 | /* Small helper function that checks if the chunk length |
147 | * is of the appropriate length. The 'required_length' argument | 153 | * is of the appropriate length. The 'required_length' argument |
148 | * is set to be the size of a specific chunk we are testing. | 154 | * is set to be the size of a specific chunk we are testing. |
@@ -2073,11 +2079,20 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2073 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2079 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2074 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2080 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
2075 | 2081 | ||
2082 | /* ADD-IP: Special case for ABORT chunks | ||
2083 | * F4) One special consideration is that ABORT Chunks arriving | ||
2084 | * destined to the IP address being deleted MUST be | ||
2085 | * ignored (see Section 5.3.1 for further details). | ||
2086 | */ | ||
2087 | if (SCTP_ADDR_DEL == | ||
2088 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | ||
2089 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | ||
2090 | |||
2076 | /* Stop the T5-shutdown guard timer. */ | 2091 | /* Stop the T5-shutdown guard timer. */ |
2077 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2092 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2078 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 2093 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
2079 | 2094 | ||
2080 | return sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2095 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); |
2081 | } | 2096 | } |
2082 | 2097 | ||
2083 | /* | 2098 | /* |
@@ -2109,6 +2124,15 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2109 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2124 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2110 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2125 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
2111 | 2126 | ||
2127 | /* ADD-IP: Special case for ABORT chunks | ||
2128 | * F4) One special consideration is that ABORT Chunks arriving | ||
2129 | * destined to the IP address being deleted MUST be | ||
2130 | * ignored (see Section 5.3.1 for further details). | ||
2131 | */ | ||
2132 | if (SCTP_ADDR_DEL == | ||
2133 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | ||
2134 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | ||
2135 | |||
2112 | /* Stop the T2-shutdown timer. */ | 2136 | /* Stop the T2-shutdown timer. */ |
2113 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2137 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2114 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 2138 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
@@ -2117,7 +2141,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2117 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2141 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2118 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 2142 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
2119 | 2143 | ||
2120 | return sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2144 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); |
2121 | } | 2145 | } |
2122 | 2146 | ||
2123 | /* | 2147 | /* |
@@ -2344,8 +2368,6 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2344 | sctp_cmd_seq_t *commands) | 2368 | sctp_cmd_seq_t *commands) |
2345 | { | 2369 | { |
2346 | struct sctp_chunk *chunk = arg; | 2370 | struct sctp_chunk *chunk = arg; |
2347 | unsigned len; | ||
2348 | __be16 error = SCTP_ERROR_NO_ERROR; | ||
2349 | 2371 | ||
2350 | if (!sctp_vtag_verify_either(chunk, asoc)) | 2372 | if (!sctp_vtag_verify_either(chunk, asoc)) |
2351 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2373 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
@@ -2363,6 +2385,28 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2363 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2385 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2364 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2386 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
2365 | 2387 | ||
2388 | /* ADD-IP: Special case for ABORT chunks | ||
2389 | * F4) One special consideration is that ABORT Chunks arriving | ||
2390 | * destined to the IP address being deleted MUST be | ||
2391 | * ignored (see Section 5.3.1 for further details). | ||
2392 | */ | ||
2393 | if (SCTP_ADDR_DEL == | ||
2394 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | ||
2395 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | ||
2396 | |||
2397 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | ||
2398 | } | ||
2399 | |||
2400 | static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | ||
2401 | const struct sctp_association *asoc, | ||
2402 | const sctp_subtype_t type, | ||
2403 | void *arg, | ||
2404 | sctp_cmd_seq_t *commands) | ||
2405 | { | ||
2406 | struct sctp_chunk *chunk = arg; | ||
2407 | unsigned len; | ||
2408 | __be16 error = SCTP_ERROR_NO_ERROR; | ||
2409 | |||
2366 | /* See if we have an error cause code in the chunk. */ | 2410 | /* See if we have an error cause code in the chunk. */ |
2367 | len = ntohs(chunk->chunk_hdr->length); | 2411 | len = ntohs(chunk->chunk_hdr->length); |
2368 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2412 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |