aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-12-20 17:12:59 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:24 -0500
commit75205f478331cc64ce729ea72d3c8c1837fb59cb (patch)
tree6267006b32ff0756c142e5d4c74755d11696f6c6
parentf57d96b2e92d209ab3991bba9a44e0d6ef7614a8 (diff)
[SCTP]: Implement ADD-IP special case processing for ABORT chunk
ADD-IP spec has a special case for processing ABORTs: F4) ... One special consideration is that ABORT Chunks arriving destined to the IP address being deleted MUST be ignored (see Section 5.3.1 for further details). Check if the address we received on is in the DEL state, and if so, ignore the ABORT. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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))