diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/input.c | 124 |
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 | */ | ||
944 | static 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 | */ |
950 | static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb, | 977 | static 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 | */ |
968 | static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, | 1042 | static 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 | } |