diff options
-rw-r--r-- | net/sctp/input.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index ca6b022b1df2..d354a23972d4 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -430,6 +430,9 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
430 | struct sock *sk = NULL; | 430 | struct sock *sk = NULL; |
431 | struct sctp_association *asoc; | 431 | struct sctp_association *asoc; |
432 | struct sctp_transport *transport = NULL; | 432 | struct sctp_transport *transport = NULL; |
433 | struct sctp_init_chunk *chunkhdr; | ||
434 | __u32 vtag = ntohl(sctphdr->vtag); | ||
435 | int len = skb->len - ((void *)sctphdr - (void *)skb->data); | ||
433 | 436 | ||
434 | *app = NULL; *tpp = NULL; | 437 | *app = NULL; *tpp = NULL; |
435 | 438 | ||
@@ -451,8 +454,28 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
451 | 454 | ||
452 | sk = asoc->base.sk; | 455 | sk = asoc->base.sk; |
453 | 456 | ||
454 | if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { | 457 | /* RFC 4960, Appendix C. ICMP Handling |
455 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 458 | * |
459 | * ICMP6) An implementation MUST validate that the Verification Tag | ||
460 | * contained in the ICMP message matches the Verification Tag of | ||
461 | * the peer. If the Verification Tag is not 0 and does NOT | ||
462 | * match, discard the ICMP message. If it is 0 and the ICMP | ||
463 | * message contains enough bytes to verify that the chunk type is | ||
464 | * an INIT chunk and that the Initiate Tag matches the tag of the | ||
465 | * peer, continue with ICMP7. If the ICMP message is too short | ||
466 | * or the chunk type or the Initiate Tag does not match, silently | ||
467 | * discard the packet. | ||
468 | */ | ||
469 | if (vtag == 0) { | ||
470 | chunkhdr = (struct sctp_init_chunk *)((void *)sctphdr | ||
471 | + sizeof(struct sctphdr)); | ||
472 | if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t) | ||
473 | + sizeof(__be32) || | ||
474 | chunkhdr->chunk_hdr.type != SCTP_CID_INIT || | ||
475 | ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) { | ||
476 | goto out; | ||
477 | } | ||
478 | } else if (vtag != asoc->c.peer_vtag) { | ||
456 | goto out; | 479 | goto out; |
457 | } | 480 | } |
458 | 481 | ||