diff options
-rw-r--r-- | include/net/sctp/command.h | 1 | ||||
-rw-r--r-- | include/net/sctp/sctp.h | 6 | ||||
-rw-r--r-- | net/sctp/input.c | 144 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 16 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 81 | ||||
-rw-r--r-- | net/sctp/socket.c | 29 |
6 files changed, 168 insertions, 109 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 34a1a09e5aef..807d6f1ef4b5 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h | |||
@@ -99,6 +99,7 @@ typedef enum { | |||
99 | SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */ | 99 | SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */ |
100 | SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */ | 100 | SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */ |
101 | SCTP_CMD_FORCE_PRIM_RETRAN, /* Forces retrans. over primary path. */ | 101 | SCTP_CMD_FORCE_PRIM_RETRAN, /* Forces retrans. over primary path. */ |
102 | SCTP_CMD_SET_SK_ERR, /* Set sk_err */ | ||
102 | SCTP_CMD_LAST | 103 | SCTP_CMD_LAST |
103 | } sctp_verb_t; | 104 | } sctp_verb_t; |
104 | 105 | ||
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index e673b2c984e9..aa6033ca7cd8 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -461,12 +461,12 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu) | |||
461 | * there is room for a param header too. | 461 | * there is room for a param header too. |
462 | */ | 462 | */ |
463 | #define sctp_walk_params(pos, chunk, member)\ | 463 | #define sctp_walk_params(pos, chunk, member)\ |
464 | _sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member) | 464 | _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) |
465 | 465 | ||
466 | #define _sctp_walk_params(pos, chunk, end, member)\ | 466 | #define _sctp_walk_params(pos, chunk, end, member)\ |
467 | for (pos.v = chunk->member;\ | 467 | for (pos.v = chunk->member;\ |
468 | pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\ | 468 | pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\ |
469 | pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\ | 469 | pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ |
470 | ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ | 470 | ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ |
471 | pos.v += WORD_ROUND(ntohs(pos.p->length))) | 471 | pos.v += WORD_ROUND(ntohs(pos.p->length))) |
472 | 472 | ||
@@ -477,7 +477,7 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) | |||
477 | for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ | 477 | for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ |
478 | sizeof(sctp_chunkhdr_t));\ | 478 | sizeof(sctp_chunkhdr_t));\ |
479 | (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ | 479 | (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ |
480 | (void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length)) &&\ | 480 | (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ |
481 | ntohs(err->length) >= sizeof(sctp_errhdr_t); \ | 481 | ntohs(err->length) >= sizeof(sctp_errhdr_t); \ |
482 | err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) | 482 | err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) |
483 | 483 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index d117ebc75cf8..1662f9cc869e 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -73,6 +73,8 @@ static struct sctp_association *__sctp_lookup_association( | |||
73 | const union sctp_addr *peer, | 73 | const union sctp_addr *peer, |
74 | struct sctp_transport **pt); | 74 | struct sctp_transport **pt); |
75 | 75 | ||
76 | static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); | ||
77 | |||
76 | 78 | ||
77 | /* Calculate the SCTP checksum of an SCTP packet. */ | 79 | /* Calculate the SCTP checksum of an SCTP packet. */ |
78 | static inline int sctp_rcv_checksum(struct sk_buff *skb) | 80 | static inline int sctp_rcv_checksum(struct sk_buff *skb) |
@@ -186,7 +188,6 @@ int sctp_rcv(struct sk_buff *skb) | |||
186 | */ | 188 | */ |
187 | if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) | 189 | if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) |
188 | { | 190 | { |
189 | sock_put(sk); | ||
190 | if (asoc) { | 191 | if (asoc) { |
191 | sctp_association_put(asoc); | 192 | sctp_association_put(asoc); |
192 | asoc = NULL; | 193 | asoc = NULL; |
@@ -197,7 +198,6 @@ int sctp_rcv(struct sk_buff *skb) | |||
197 | sk = sctp_get_ctl_sock(); | 198 | sk = sctp_get_ctl_sock(); |
198 | ep = sctp_sk(sk)->ep; | 199 | ep = sctp_sk(sk)->ep; |
199 | sctp_endpoint_hold(ep); | 200 | sctp_endpoint_hold(ep); |
200 | sock_hold(sk); | ||
201 | rcvr = &ep->base; | 201 | rcvr = &ep->base; |
202 | } | 202 | } |
203 | 203 | ||
@@ -253,25 +253,18 @@ int sctp_rcv(struct sk_buff *skb) | |||
253 | */ | 253 | */ |
254 | sctp_bh_lock_sock(sk); | 254 | sctp_bh_lock_sock(sk); |
255 | 255 | ||
256 | /* It is possible that the association could have moved to a different | ||
257 | * socket if it is peeled off. If so, update the sk. | ||
258 | */ | ||
259 | if (sk != rcvr->sk) { | ||
260 | sctp_bh_lock_sock(rcvr->sk); | ||
261 | sctp_bh_unlock_sock(sk); | ||
262 | sk = rcvr->sk; | ||
263 | } | ||
264 | |||
265 | if (sock_owned_by_user(sk)) | 256 | if (sock_owned_by_user(sk)) |
266 | sk_add_backlog(sk, skb); | 257 | sctp_add_backlog(sk, skb); |
267 | else | 258 | else |
268 | sctp_backlog_rcv(sk, skb); | 259 | sctp_inq_push(&chunk->rcvr->inqueue, chunk); |
269 | 260 | ||
270 | /* Release the sock and the sock ref we took in the lookup calls. | ||
271 | * The asoc/ep ref will be released in sctp_backlog_rcv. | ||
272 | */ | ||
273 | sctp_bh_unlock_sock(sk); | 261 | sctp_bh_unlock_sock(sk); |
274 | sock_put(sk); | 262 | |
263 | /* Release the asoc/ep ref we took in the lookup calls. */ | ||
264 | if (asoc) | ||
265 | sctp_association_put(asoc); | ||
266 | else | ||
267 | sctp_endpoint_put(ep); | ||
275 | 268 | ||
276 | return 0; | 269 | return 0; |
277 | 270 | ||
@@ -280,8 +273,7 @@ discard_it: | |||
280 | return 0; | 273 | return 0; |
281 | 274 | ||
282 | discard_release: | 275 | discard_release: |
283 | /* Release any structures we may be holding. */ | 276 | /* Release the asoc/ep ref we took in the lookup calls. */ |
284 | sock_put(sk); | ||
285 | if (asoc) | 277 | if (asoc) |
286 | sctp_association_put(asoc); | 278 | sctp_association_put(asoc); |
287 | else | 279 | else |
@@ -290,56 +282,87 @@ discard_release: | |||
290 | goto discard_it; | 282 | goto discard_it; |
291 | } | 283 | } |
292 | 284 | ||
293 | /* Handle second half of inbound skb processing. If the sock was busy, | 285 | /* Process the backlog queue of the socket. Every skb on |
294 | * we may have need to delay processing until later when the sock is | 286 | * the backlog holds a ref on an association or endpoint. |
295 | * released (on the backlog). If not busy, we call this routine | 287 | * We hold this ref throughout the state machine to make |
296 | * directly from the bottom half. | 288 | * sure that the structure we need is still around. |
297 | */ | 289 | */ |
298 | int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) | 290 | int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) |
299 | { | 291 | { |
300 | struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; | 292 | struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; |
301 | struct sctp_inq *inqueue = NULL; | 293 | struct sctp_inq *inqueue = &chunk->rcvr->inqueue; |
302 | struct sctp_ep_common *rcvr = NULL; | 294 | struct sctp_ep_common *rcvr = NULL; |
295 | int backloged = 0; | ||
303 | 296 | ||
304 | rcvr = chunk->rcvr; | 297 | rcvr = chunk->rcvr; |
305 | 298 | ||
306 | BUG_TRAP(rcvr->sk == sk); | 299 | /* If the rcvr is dead then the association or endpoint |
307 | 300 | * has been deleted and we can safely drop the chunk | |
308 | if (rcvr->dead) { | 301 | * and refs that we are holding. |
309 | sctp_chunk_free(chunk); | 302 | */ |
310 | } else { | 303 | if (rcvr->dead) { |
311 | inqueue = &chunk->rcvr->inqueue; | 304 | sctp_chunk_free(chunk); |
312 | sctp_inq_push(inqueue, chunk); | 305 | goto done; |
313 | } | 306 | } |
314 | 307 | ||
315 | /* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ | 308 | if (unlikely(rcvr->sk != sk)) { |
316 | if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) | 309 | /* In this case, the association moved from one socket to |
317 | sctp_association_put(sctp_assoc(rcvr)); | 310 | * another. We are currently sitting on the backlog of the |
318 | else | 311 | * old socket, so we need to move. |
319 | sctp_endpoint_put(sctp_ep(rcvr)); | 312 | * However, since we are here in the process context we |
320 | 313 | * need to take make sure that the user doesn't own | |
314 | * the new socket when we process the packet. | ||
315 | * If the new socket is user-owned, queue the chunk to the | ||
316 | * backlog of the new socket without dropping any refs. | ||
317 | * Otherwise, we can safely push the chunk on the inqueue. | ||
318 | */ | ||
319 | |||
320 | sk = rcvr->sk; | ||
321 | sctp_bh_lock_sock(sk); | ||
322 | |||
323 | if (sock_owned_by_user(sk)) { | ||
324 | sk_add_backlog(sk, skb); | ||
325 | backloged = 1; | ||
326 | } else | ||
327 | sctp_inq_push(inqueue, chunk); | ||
328 | |||
329 | sctp_bh_unlock_sock(sk); | ||
330 | |||
331 | /* If the chunk was backloged again, don't drop refs */ | ||
332 | if (backloged) | ||
333 | return 0; | ||
334 | } else { | ||
335 | sctp_inq_push(inqueue, chunk); | ||
336 | } | ||
337 | |||
338 | done: | ||
339 | /* Release the refs we took in sctp_add_backlog */ | ||
340 | if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) | ||
341 | sctp_association_put(sctp_assoc(rcvr)); | ||
342 | else if (SCTP_EP_TYPE_SOCKET == rcvr->type) | ||
343 | sctp_endpoint_put(sctp_ep(rcvr)); | ||
344 | else | ||
345 | BUG(); | ||
346 | |||
321 | return 0; | 347 | return 0; |
322 | } | 348 | } |
323 | 349 | ||
324 | void sctp_backlog_migrate(struct sctp_association *assoc, | 350 | static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) |
325 | struct sock *oldsk, struct sock *newsk) | ||
326 | { | 351 | { |
327 | struct sk_buff *skb; | 352 | struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; |
328 | struct sctp_chunk *chunk; | 353 | struct sctp_ep_common *rcvr = chunk->rcvr; |
329 | 354 | ||
330 | skb = oldsk->sk_backlog.head; | 355 | /* Hold the assoc/ep while hanging on the backlog queue. |
331 | oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL; | 356 | * This way, we know structures we need will not disappear from us |
332 | while (skb != NULL) { | 357 | */ |
333 | struct sk_buff *next = skb->next; | 358 | if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) |
334 | 359 | sctp_association_hold(sctp_assoc(rcvr)); | |
335 | chunk = SCTP_INPUT_CB(skb)->chunk; | 360 | else if (SCTP_EP_TYPE_SOCKET == rcvr->type) |
336 | skb->next = NULL; | 361 | sctp_endpoint_hold(sctp_ep(rcvr)); |
337 | if (&assoc->base == chunk->rcvr) | 362 | else |
338 | sk_add_backlog(newsk, skb); | 363 | BUG(); |
339 | else | 364 | |
340 | sk_add_backlog(oldsk, skb); | 365 | sk_add_backlog(sk, skb); |
341 | skb = next; | ||
342 | } | ||
343 | } | 366 | } |
344 | 367 | ||
345 | /* Handle icmp frag needed error. */ | 368 | /* Handle icmp frag needed error. */ |
@@ -412,7 +435,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
412 | union sctp_addr daddr; | 435 | union sctp_addr daddr; |
413 | struct sctp_af *af; | 436 | struct sctp_af *af; |
414 | struct sock *sk = NULL; | 437 | struct sock *sk = NULL; |
415 | struct sctp_association *asoc = NULL; | 438 | struct sctp_association *asoc; |
416 | struct sctp_transport *transport = NULL; | 439 | struct sctp_transport *transport = NULL; |
417 | 440 | ||
418 | *app = NULL; *tpp = NULL; | 441 | *app = NULL; *tpp = NULL; |
@@ -453,7 +476,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
453 | return sk; | 476 | return sk; |
454 | 477 | ||
455 | out: | 478 | out: |
456 | sock_put(sk); | ||
457 | if (asoc) | 479 | if (asoc) |
458 | sctp_association_put(asoc); | 480 | sctp_association_put(asoc); |
459 | return NULL; | 481 | return NULL; |
@@ -463,7 +485,6 @@ out: | |||
463 | void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) | 485 | void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) |
464 | { | 486 | { |
465 | sctp_bh_unlock_sock(sk); | 487 | sctp_bh_unlock_sock(sk); |
466 | sock_put(sk); | ||
467 | if (asoc) | 488 | if (asoc) |
468 | sctp_association_put(asoc); | 489 | sctp_association_put(asoc); |
469 | } | 490 | } |
@@ -490,7 +511,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
490 | int type = skb->h.icmph->type; | 511 | int type = skb->h.icmph->type; |
491 | int code = skb->h.icmph->code; | 512 | int code = skb->h.icmph->code; |
492 | struct sock *sk; | 513 | struct sock *sk; |
493 | struct sctp_association *asoc; | 514 | struct sctp_association *asoc = NULL; |
494 | struct sctp_transport *transport; | 515 | struct sctp_transport *transport; |
495 | struct inet_sock *inet; | 516 | struct inet_sock *inet; |
496 | char *saveip, *savesctp; | 517 | char *saveip, *savesctp; |
@@ -716,7 +737,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l | |||
716 | 737 | ||
717 | hit: | 738 | hit: |
718 | sctp_endpoint_hold(ep); | 739 | sctp_endpoint_hold(ep); |
719 | sock_hold(epb->sk); | ||
720 | read_unlock(&head->lock); | 740 | read_unlock(&head->lock); |
721 | return ep; | 741 | return ep; |
722 | } | 742 | } |
@@ -818,7 +838,6 @@ static struct sctp_association *__sctp_lookup_association( | |||
818 | hit: | 838 | hit: |
819 | *pt = transport; | 839 | *pt = transport; |
820 | sctp_association_hold(asoc); | 840 | sctp_association_hold(asoc); |
821 | sock_hold(epb->sk); | ||
822 | read_unlock(&head->lock); | 841 | read_unlock(&head->lock); |
823 | return asoc; | 842 | return asoc; |
824 | } | 843 | } |
@@ -846,7 +865,6 @@ int sctp_has_association(const union sctp_addr *laddr, | |||
846 | struct sctp_transport *transport; | 865 | struct sctp_transport *transport; |
847 | 866 | ||
848 | if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) { | 867 | if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) { |
849 | sock_put(asoc->base.sk); | ||
850 | sctp_association_put(asoc); | 868 | sctp_association_put(asoc); |
851 | return 1; | 869 | return 1; |
852 | } | 870 | } |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 8d1dc24bab4c..c5beb2ad7ef7 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -498,10 +498,6 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, | |||
498 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 498 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
499 | SCTP_STATE(SCTP_STATE_CLOSED)); | 499 | SCTP_STATE(SCTP_STATE_CLOSED)); |
500 | 500 | ||
501 | /* Set sk_err to ECONNRESET on a 1-1 style socket. */ | ||
502 | if (!sctp_style(asoc->base.sk, UDP)) | ||
503 | asoc->base.sk->sk_err = ECONNRESET; | ||
504 | |||
505 | /* SEND_FAILED sent later when cleaning up the association. */ | 501 | /* SEND_FAILED sent later when cleaning up the association. */ |
506 | asoc->outqueue.error = error; | 502 | asoc->outqueue.error = error; |
507 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 503 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
@@ -838,6 +834,15 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) | |||
838 | return; | 834 | return; |
839 | } | 835 | } |
840 | 836 | ||
837 | /* Helper function to set sk_err on a 1-1 style socket. */ | ||
838 | static void sctp_cmd_set_sk_err(struct sctp_association *asoc, int error) | ||
839 | { | ||
840 | struct sock *sk = asoc->base.sk; | ||
841 | |||
842 | if (!sctp_style(sk, UDP)) | ||
843 | sk->sk_err = error; | ||
844 | } | ||
845 | |||
841 | /* These three macros allow us to pull the debugging code out of the | 846 | /* These three macros allow us to pull the debugging code out of the |
842 | * main flow of sctp_do_sm() to keep attention focused on the real | 847 | * main flow of sctp_do_sm() to keep attention focused on the real |
843 | * functionality there. | 848 | * functionality there. |
@@ -1458,6 +1463,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1458 | local_cork = 0; | 1463 | local_cork = 0; |
1459 | asoc->peer.retran_path = t; | 1464 | asoc->peer.retran_path = t; |
1460 | break; | 1465 | break; |
1466 | case SCTP_CMD_SET_SK_ERR: | ||
1467 | sctp_cmd_set_sk_err(asoc, cmd->obj.error); | ||
1468 | break; | ||
1461 | default: | 1469 | default: |
1462 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1470 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1463 | cmd->verb, cmd->obj.ptr); | 1471 | cmd->verb, cmd->obj.ptr); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8cdba51ec076..8bc279219a72 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | |||
93 | static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); | 93 | static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); |
94 | 94 | ||
95 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | 95 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
96 | __u16 error, | 96 | __u16 error, int sk_err, |
97 | const struct sctp_association *asoc, | 97 | const struct sctp_association *asoc, |
98 | struct sctp_transport *transport); | 98 | struct sctp_transport *transport); |
99 | 99 | ||
@@ -448,7 +448,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
448 | __u32 init_tag; | 448 | __u32 init_tag; |
449 | struct sctp_chunk *err_chunk; | 449 | struct sctp_chunk *err_chunk; |
450 | struct sctp_packet *packet; | 450 | struct sctp_packet *packet; |
451 | sctp_disposition_t ret; | 451 | __u16 error; |
452 | 452 | ||
453 | if (!sctp_vtag_verify(chunk, asoc)) | 453 | if (!sctp_vtag_verify(chunk, asoc)) |
454 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 454 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
@@ -480,11 +480,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
480 | goto nomem; | 480 | goto nomem; |
481 | 481 | ||
482 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); | 482 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); |
483 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 483 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM, |
484 | SCTP_STATE(SCTP_STATE_CLOSED)); | 484 | ECONNREFUSED, asoc, |
485 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 485 | chunk->transport); |
486 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | ||
487 | return SCTP_DISPOSITION_DELETE_TCB; | ||
488 | } | 486 | } |
489 | 487 | ||
490 | /* Verify the INIT chunk before processing it. */ | 488 | /* Verify the INIT chunk before processing it. */ |
@@ -511,27 +509,16 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
511 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 509 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
512 | SCTP_PACKET(packet)); | 510 | SCTP_PACKET(packet)); |
513 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 511 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); |
514 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 512 | error = SCTP_ERROR_INV_PARAM; |
515 | SCTP_STATE(SCTP_STATE_CLOSED)); | ||
516 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, | ||
517 | SCTP_NULL()); | ||
518 | return SCTP_DISPOSITION_CONSUME; | ||
519 | } else { | 513 | } else { |
520 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 514 | error = SCTP_ERROR_NO_RESOURCE; |
521 | SCTP_STATE(SCTP_STATE_CLOSED)); | ||
522 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, | ||
523 | SCTP_NULL()); | ||
524 | return SCTP_DISPOSITION_NOMEM; | ||
525 | } | 515 | } |
526 | } else { | 516 | } else { |
527 | ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg, | 517 | sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
528 | commands); | 518 | error = SCTP_ERROR_INV_PARAM; |
529 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | ||
530 | SCTP_STATE(SCTP_STATE_CLOSED)); | ||
531 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, | ||
532 | SCTP_NULL()); | ||
533 | return ret; | ||
534 | } | 519 | } |
520 | return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, | ||
521 | asoc, chunk->transport); | ||
535 | } | 522 | } |
536 | 523 | ||
537 | /* Tag the variable length parameters. Note that we never | 524 | /* Tag the variable length parameters. Note that we never |
@@ -886,6 +873,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | |||
886 | struct sctp_transport *transport = (struct sctp_transport *) arg; | 873 | struct sctp_transport *transport = (struct sctp_transport *) arg; |
887 | 874 | ||
888 | if (asoc->overall_error_count >= asoc->max_retrans) { | 875 | if (asoc->overall_error_count >= asoc->max_retrans) { |
876 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
877 | SCTP_ERROR(ETIMEDOUT)); | ||
889 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 878 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
890 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 879 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
891 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 880 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
@@ -1030,6 +1019,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1030 | commands); | 1019 | commands); |
1031 | 1020 | ||
1032 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; | 1021 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; |
1022 | /* Make sure that the length of the parameter is what we expect */ | ||
1023 | if (ntohs(hbinfo->param_hdr.length) != | ||
1024 | sizeof(sctp_sender_hb_info_t)) { | ||
1025 | return SCTP_DISPOSITION_DISCARD; | ||
1026 | } | ||
1027 | |||
1033 | from_addr = hbinfo->daddr; | 1028 | from_addr = hbinfo->daddr; |
1034 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); | 1029 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); |
1035 | 1030 | ||
@@ -2126,6 +2121,8 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
2126 | int attempts = asoc->init_err_counter + 1; | 2121 | int attempts = asoc->init_err_counter + 1; |
2127 | 2122 | ||
2128 | if (attempts > asoc->max_init_attempts) { | 2123 | if (attempts > asoc->max_init_attempts) { |
2124 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
2125 | SCTP_ERROR(ETIMEDOUT)); | ||
2129 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2126 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
2130 | SCTP_U32(SCTP_ERROR_STALE_COOKIE)); | 2127 | SCTP_U32(SCTP_ERROR_STALE_COOKIE)); |
2131 | return SCTP_DISPOSITION_DELETE_TCB; | 2128 | return SCTP_DISPOSITION_DELETE_TCB; |
@@ -2262,6 +2259,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2262 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2259 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2263 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2260 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2264 | 2261 | ||
2262 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); | ||
2265 | /* ASSOC_FAILED will DELETE_TCB. */ | 2263 | /* ASSOC_FAILED will DELETE_TCB. */ |
2266 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); | 2264 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); |
2267 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2265 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -2306,7 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2306 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2304 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2307 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2305 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2308 | 2306 | ||
2309 | return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); | 2307 | return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc, |
2308 | chunk->transport); | ||
2310 | } | 2309 | } |
2311 | 2310 | ||
2312 | /* | 2311 | /* |
@@ -2318,7 +2317,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
2318 | void *arg, | 2317 | void *arg, |
2319 | sctp_cmd_seq_t *commands) | 2318 | sctp_cmd_seq_t *commands) |
2320 | { | 2319 | { |
2321 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, | 2320 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, |
2321 | ENOPROTOOPT, asoc, | ||
2322 | (struct sctp_transport *)arg); | 2322 | (struct sctp_transport *)arg); |
2323 | } | 2323 | } |
2324 | 2324 | ||
@@ -2343,7 +2343,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
2343 | * This is common code called by several sctp_sf_*_abort() functions above. | 2343 | * This is common code called by several sctp_sf_*_abort() functions above. |
2344 | */ | 2344 | */ |
2345 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | 2345 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
2346 | __u16 error, | 2346 | __u16 error, int sk_err, |
2347 | const struct sctp_association *asoc, | 2347 | const struct sctp_association *asoc, |
2348 | struct sctp_transport *transport) | 2348 | struct sctp_transport *transport) |
2349 | { | 2349 | { |
@@ -2353,6 +2353,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | |||
2353 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2353 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
2354 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2354 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2355 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 2355 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
2356 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); | ||
2356 | /* CMD_INIT_FAILED will DELETE_TCB. */ | 2357 | /* CMD_INIT_FAILED will DELETE_TCB. */ |
2357 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2358 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
2358 | SCTP_U32(error)); | 2359 | SCTP_U32(error)); |
@@ -3336,6 +3337,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3336 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 3337 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
3337 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 3338 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
3338 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); | 3339 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); |
3340 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3341 | SCTP_ERROR(ECONNABORTED)); | ||
3339 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3342 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3340 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); | 3343 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); |
3341 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 3344 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -3362,6 +3365,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3362 | * processing the rest of the chunks in the packet. | 3365 | * processing the rest of the chunks in the packet. |
3363 | */ | 3366 | */ |
3364 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); | 3367 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); |
3368 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3369 | SCTP_ERROR(ECONNABORTED)); | ||
3365 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3370 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3366 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); | 3371 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); |
3367 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 3372 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -3714,9 +3719,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
3714 | if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { | 3719 | if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { |
3715 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 3720 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
3716 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 3721 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
3722 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3723 | SCTP_ERROR(ECONNREFUSED)); | ||
3717 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 3724 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
3718 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); | 3725 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); |
3719 | } else { | 3726 | } else { |
3727 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3728 | SCTP_ERROR(ECONNABORTED)); | ||
3720 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3729 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3721 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); | 3730 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); |
3722 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 3731 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); |
@@ -4034,6 +4043,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
4034 | * TCB. This is a departure from our typical NOMEM handling. | 4043 | * TCB. This is a departure from our typical NOMEM handling. |
4035 | */ | 4044 | */ |
4036 | 4045 | ||
4046 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4047 | SCTP_ERROR(ECONNABORTED)); | ||
4037 | /* Delete the established association. */ | 4048 | /* Delete the established association. */ |
4038 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4049 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4039 | SCTP_U32(SCTP_ERROR_USER_ABORT)); | 4050 | SCTP_U32(SCTP_ERROR_USER_ABORT)); |
@@ -4175,6 +4186,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4175 | * TCB. This is a departure from our typical NOMEM handling. | 4186 | * TCB. This is a departure from our typical NOMEM handling. |
4176 | */ | 4187 | */ |
4177 | 4188 | ||
4189 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4190 | SCTP_ERROR(ECONNREFUSED)); | ||
4178 | /* Delete the established association. */ | 4191 | /* Delete the established association. */ |
4179 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4192 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4180 | SCTP_U32(SCTP_ERROR_USER_ABORT)); | 4193 | SCTP_U32(SCTP_ERROR_USER_ABORT)); |
@@ -4543,6 +4556,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
4543 | struct sctp_transport *transport = arg; | 4556 | struct sctp_transport *transport = arg; |
4544 | 4557 | ||
4545 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4558 | if (asoc->overall_error_count >= asoc->max_retrans) { |
4559 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4560 | SCTP_ERROR(ETIMEDOUT)); | ||
4546 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 4561 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
4547 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4562 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4548 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4563 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
@@ -4662,6 +4677,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | |||
4662 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" | 4677 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" |
4663 | " max_init_attempts: %d\n", | 4678 | " max_init_attempts: %d\n", |
4664 | attempts, asoc->max_init_attempts); | 4679 | attempts, asoc->max_init_attempts); |
4680 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4681 | SCTP_ERROR(ETIMEDOUT)); | ||
4665 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4682 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4666 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4683 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4667 | return SCTP_DISPOSITION_DELETE_TCB; | 4684 | return SCTP_DISPOSITION_DELETE_TCB; |
@@ -4711,6 +4728,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
4711 | 4728 | ||
4712 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 4729 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
4713 | } else { | 4730 | } else { |
4731 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4732 | SCTP_ERROR(ETIMEDOUT)); | ||
4714 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4733 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4715 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4734 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4716 | return SCTP_DISPOSITION_DELETE_TCB; | 4735 | return SCTP_DISPOSITION_DELETE_TCB; |
@@ -4742,6 +4761,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
4742 | 4761 | ||
4743 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); | 4762 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); |
4744 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4763 | if (asoc->overall_error_count >= asoc->max_retrans) { |
4764 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4765 | SCTP_ERROR(ETIMEDOUT)); | ||
4745 | /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 4766 | /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
4746 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4767 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4747 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4768 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
@@ -4817,6 +4838,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
4817 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4838 | if (asoc->overall_error_count >= asoc->max_retrans) { |
4818 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 4839 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4819 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 4840 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
4841 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4842 | SCTP_ERROR(ETIMEDOUT)); | ||
4820 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4843 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4821 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4844 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4822 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4845 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -4870,6 +4893,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | |||
4870 | goto nomem; | 4893 | goto nomem; |
4871 | 4894 | ||
4872 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); | 4895 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); |
4896 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4897 | SCTP_ERROR(ETIMEDOUT)); | ||
4873 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4898 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4874 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4899 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4875 | 4900 | ||
@@ -5309,6 +5334,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5309 | * processing the rest of the chunks in the packet. | 5334 | * processing the rest of the chunks in the packet. |
5310 | */ | 5335 | */ |
5311 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); | 5336 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); |
5337 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
5338 | SCTP_ERROR(ECONNABORTED)); | ||
5312 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5339 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5313 | SCTP_U32(SCTP_ERROR_NO_DATA)); | 5340 | SCTP_U32(SCTP_ERROR_NO_DATA)); |
5314 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5341 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b6e4b89539b3..174d4d35e951 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1057,6 +1057,7 @@ static int __sctp_connect(struct sock* sk, | |||
1057 | inet_sk(sk)->dport = htons(asoc->peer.port); | 1057 | inet_sk(sk)->dport = htons(asoc->peer.port); |
1058 | af = sctp_get_af_specific(to.sa.sa_family); | 1058 | af = sctp_get_af_specific(to.sa.sa_family); |
1059 | af->to_sk_daddr(&to, sk); | 1059 | af->to_sk_daddr(&to, sk); |
1060 | sk->sk_err = 0; | ||
1060 | 1061 | ||
1061 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | 1062 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); |
1062 | err = sctp_wait_for_connect(asoc, &timeo); | 1063 | err = sctp_wait_for_connect(asoc, &timeo); |
@@ -1228,7 +1229,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1228 | 1229 | ||
1229 | ep = sctp_sk(sk)->ep; | 1230 | ep = sctp_sk(sk)->ep; |
1230 | 1231 | ||
1231 | /* Walk all associations on a socket, not on an endpoint. */ | 1232 | /* Walk all associations on an endpoint. */ |
1232 | list_for_each_safe(pos, temp, &ep->asocs) { | 1233 | list_for_each_safe(pos, temp, &ep->asocs) { |
1233 | asoc = list_entry(pos, struct sctp_association, asocs); | 1234 | asoc = list_entry(pos, struct sctp_association, asocs); |
1234 | 1235 | ||
@@ -1241,13 +1242,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1241 | if (sctp_state(asoc, CLOSED)) { | 1242 | if (sctp_state(asoc, CLOSED)) { |
1242 | sctp_unhash_established(asoc); | 1243 | sctp_unhash_established(asoc); |
1243 | sctp_association_free(asoc); | 1244 | sctp_association_free(asoc); |
1245 | continue; | ||
1246 | } | ||
1247 | } | ||
1244 | 1248 | ||
1245 | } else if (sock_flag(sk, SOCK_LINGER) && | 1249 | if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) |
1246 | !sk->sk_lingertime) | 1250 | sctp_primitive_ABORT(asoc, NULL); |
1247 | sctp_primitive_ABORT(asoc, NULL); | 1251 | else |
1248 | else | ||
1249 | sctp_primitive_SHUTDOWN(asoc, NULL); | ||
1250 | } else | ||
1251 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1252 | sctp_primitive_SHUTDOWN(asoc, NULL); |
1252 | } | 1253 | } |
1253 | 1254 | ||
@@ -5317,6 +5318,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, | |||
5317 | */ | 5318 | */ |
5318 | sctp_release_sock(sk); | 5319 | sctp_release_sock(sk); |
5319 | current_timeo = schedule_timeout(current_timeo); | 5320 | current_timeo = schedule_timeout(current_timeo); |
5321 | BUG_ON(sk != asoc->base.sk); | ||
5320 | sctp_lock_sock(sk); | 5322 | sctp_lock_sock(sk); |
5321 | 5323 | ||
5322 | *timeo_p = current_timeo; | 5324 | *timeo_p = current_timeo; |
@@ -5604,12 +5606,14 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5604 | */ | 5606 | */ |
5605 | newsp->type = type; | 5607 | newsp->type = type; |
5606 | 5608 | ||
5607 | spin_lock_bh(&oldsk->sk_lock.slock); | 5609 | /* Mark the new socket "in-use" by the user so that any packets |
5608 | /* Migrate the backlog from oldsk to newsk. */ | 5610 | * that may arrive on the association after we've moved it are |
5609 | sctp_backlog_migrate(assoc, oldsk, newsk); | 5611 | * queued to the backlog. This prevents a potential race between |
5610 | /* Migrate the association to the new socket. */ | 5612 | * backlog processing on the old socket and new-packet processing |
5613 | * on the new socket. | ||
5614 | */ | ||
5615 | sctp_lock_sock(newsk); | ||
5611 | sctp_assoc_migrate(assoc, newsk); | 5616 | sctp_assoc_migrate(assoc, newsk); |
5612 | spin_unlock_bh(&oldsk->sk_lock.slock); | ||
5613 | 5617 | ||
5614 | /* If the association on the newsk is already closed before accept() | 5618 | /* If the association on the newsk is already closed before accept() |
5615 | * is called, set RCV_SHUTDOWN flag. | 5619 | * is called, set RCV_SHUTDOWN flag. |
@@ -5618,6 +5622,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5618 | newsk->sk_shutdown |= RCV_SHUTDOWN; | 5622 | newsk->sk_shutdown |= RCV_SHUTDOWN; |
5619 | 5623 | ||
5620 | newsk->sk_state = SCTP_SS_ESTABLISHED; | 5624 | newsk->sk_state = SCTP_SS_ESTABLISHED; |
5625 | sctp_release_sock(newsk); | ||
5621 | } | 5626 | } |
5622 | 5627 | ||
5623 | /* This proto struct describes the ULP interface for SCTP. */ | 5628 | /* This proto struct describes the ULP interface for SCTP. */ |