aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/structs.h2
-rw-r--r--net/sctp/bind_addr.c26
-rw-r--r--net/sctp/sm_statefuns.c52
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 *,
1200int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); 1200int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
1201int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, 1201int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
1202 struct sctp_sock *); 1202 struct sctp_sock *);
1203int sctp_bind_addr_state(const struct sctp_bind_addr *bp,
1204 const union sctp_addr *addr);
1203union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, 1205union 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 */
357int 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
146static 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
2400static 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))