aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/input.c124
1 files changed, 103 insertions, 21 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c
index b08c7cb5c9d6..d695f710fc77 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -891,14 +891,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
891 891
892 ch = (sctp_chunkhdr_t *) skb->data; 892 ch = (sctp_chunkhdr_t *) skb->data;
893 893
894 /* The code below will attempt to walk the chunk and extract
895 * parameter information. Before we do that, we need to verify
896 * that the chunk length doesn't cause overflow. Otherwise, we'll
897 * walk off the end.
898 */
899 if (WORD_ROUND(ntohs(ch->length)) > skb->len)
900 return NULL;
901
902 /* 894 /*
903 * This code will NOT touch anything inside the chunk--it is 895 * This code will NOT touch anything inside the chunk--it is
904 * strictly READ-ONLY. 896 * strictly READ-ONLY.
@@ -935,6 +927,44 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
935 return NULL; 927 return NULL;
936} 928}
937 929
930/* ADD-IP, Section 5.2
931 * When an endpoint receives an ASCONF Chunk from the remote peer
932 * special procedures may be needed to identify the association the
933 * ASCONF Chunk is associated with. To properly find the association
934 * the following procedures SHOULD be followed:
935 *
936 * D2) If the association is not found, use the address found in the
937 * Address Parameter TLV combined with the port number found in the
938 * SCTP common header. If found proceed to rule D4.
939 *
940 * D2-ext) If more than one ASCONF Chunks are packed together, use the
941 * address found in the ASCONF Address Parameter TLV of each of the
942 * subsequent ASCONF Chunks. If found, proceed to rule D4.
943 */
944static struct sctp_association *__sctp_rcv_asconf_lookup(
945 sctp_chunkhdr_t *ch,
946 const union sctp_addr *laddr,
947 __be32 peer_port,
948 struct sctp_transport **transportp)
949{
950 sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch;
951 struct sctp_af *af;
952 union sctp_addr_param *param;
953 union sctp_addr paddr;
954
955 /* Skip over the ADDIP header and find the Address parameter */
956 param = (union sctp_addr_param *)(asconf + 1);
957
958 af = sctp_get_af_specific(param_type2af(param->v4.param_hdr.type));
959 if (unlikely(!af))
960 return NULL;
961
962 af->from_addr_param(&paddr, param, peer_port, 0);
963
964 return __sctp_lookup_association(laddr, &paddr, transportp);
965}
966
967
938/* SCTP-AUTH, Section 6.3: 968/* SCTP-AUTH, Section 6.3:
939* If the receiver does not find a STCB for a packet containing an AUTH 969* If the receiver does not find a STCB for a packet containing an AUTH
940* chunk as the first chunk and not a COOKIE-ECHO chunk as the second 970* chunk as the first chunk and not a COOKIE-ECHO chunk as the second
@@ -943,20 +973,64 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
943* 973*
944* This means that any chunks that can help us identify the association need 974* This means that any chunks that can help us identify the association need
945* to be looked at to find this assocation. 975* to be looked at to find this assocation.
946*
947* TODO: The only chunk currently defined that can do that is ASCONF, but we
948* don't support that functionality yet.
949*/ 976*/
950static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb, 977static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
951 const union sctp_addr *paddr,
952 const union sctp_addr *laddr, 978 const union sctp_addr *laddr,
953 struct sctp_transport **transportp) 979 struct sctp_transport **transportp)
954{ 980{
955 /* XXX - walk through the chunks looking for something that can 981 struct sctp_association *asoc = NULL;
956 * help us find the association. INIT, and INIT-ACK are not permitted. 982 sctp_chunkhdr_t *ch;
957 * That leaves ASCONF, but we don't support that yet. 983 int have_auth = 0;
984 unsigned int chunk_num = 1;
985 __u8 *ch_end;
986
987 /* Walk through the chunks looking for AUTH or ASCONF chunks
988 * to help us find the association.
958 */ 989 */
959 return NULL; 990 ch = (sctp_chunkhdr_t *) skb->data;
991 do {
992 /* Break out if chunk length is less then minimal. */
993 if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
994 break;
995
996 ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
997 if (ch_end > skb_tail_pointer(skb))
998 break;
999
1000 switch(ch->type) {
1001 case SCTP_CID_AUTH:
1002 have_auth = chunk_num;
1003 break;
1004
1005 case SCTP_CID_COOKIE_ECHO:
1006 /* If a packet arrives containing an AUTH chunk as
1007 * a first chunk, a COOKIE-ECHO chunk as the second
1008 * chunk, and possibly more chunks after them, and
1009 * the receiver does not have an STCB for that
1010 * packet, then authentication is based on
1011 * the contents of the COOKIE- ECHO chunk.
1012 */
1013 if (have_auth == 1 && chunk_num == 2)
1014 return NULL;
1015 break;
1016
1017 case SCTP_CID_ASCONF:
1018 if (have_auth || sctp_addip_noauth)
1019 asoc = __sctp_rcv_asconf_lookup(ch, laddr,
1020 sctp_hdr(skb)->source,
1021 transportp);
1022 default:
1023 break;
1024 }
1025
1026 if (asoc)
1027 break;
1028
1029 ch = (sctp_chunkhdr_t *) ch_end;
1030 chunk_num++;
1031 } while (ch_end < skb_tail_pointer(skb));
1032
1033 return asoc;
960} 1034}
961 1035
962/* 1036/*
@@ -966,7 +1040,6 @@ static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb,
966 * chunks. 1040 * chunks.
967 */ 1041 */
968static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, 1042static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
969 const union sctp_addr *paddr,
970 const union sctp_addr *laddr, 1043 const union sctp_addr *laddr,
971 struct sctp_transport **transportp) 1044 struct sctp_transport **transportp)
972{ 1045{
@@ -974,6 +1047,14 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
974 1047
975 ch = (sctp_chunkhdr_t *) skb->data; 1048 ch = (sctp_chunkhdr_t *) skb->data;
976 1049
1050 /* The code below will attempt to walk the chunk and extract
1051 * parameter information. Before we do that, we need to verify
1052 * that the chunk length doesn't cause overflow. Otherwise, we'll
1053 * walk off the end.
1054 */
1055 if (WORD_ROUND(ntohs(ch->length)) > skb->len)
1056 return NULL;
1057
977 /* If this is INIT/INIT-ACK look inside the chunk too. */ 1058 /* If this is INIT/INIT-ACK look inside the chunk too. */
978 switch (ch->type) { 1059 switch (ch->type) {
979 case SCTP_CID_INIT: 1060 case SCTP_CID_INIT:
@@ -981,11 +1062,12 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
981 return __sctp_rcv_init_lookup(skb, laddr, transportp); 1062 return __sctp_rcv_init_lookup(skb, laddr, transportp);
982 break; 1063 break;
983 1064
984 case SCTP_CID_AUTH: 1065 default:
985 return __sctp_rcv_auth_lookup(skb, paddr, laddr, transportp); 1066 return __sctp_rcv_walk_lookup(skb, laddr, transportp);
986 break; 1067 break;
987 } 1068 }
988 1069
1070
989 return NULL; 1071 return NULL;
990} 1072}
991 1073
@@ -1004,7 +1086,7 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
1004 * parameters within the INIT or INIT-ACK. 1086 * parameters within the INIT or INIT-ACK.
1005 */ 1087 */
1006 if (!asoc) 1088 if (!asoc)
1007 asoc = __sctp_rcv_lookup_harder(skb, paddr, laddr, transportp); 1089 asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp);
1008 1090
1009 return asoc; 1091 return asoc;
1010} 1092}