aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/input.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-12-20 17:10:38 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:59:22 -0500
commitdf21857714398acb8b24a8bb5a6d2286dd9c59ef (patch)
treec0c2d5fbfb4a9b4b1a122a5957dd2c7e6cfe27e0 /net/sctp/input.c
parentd6de3097592b7ae7f8e233a4dafb088e2aa8170f (diff)
[SCTP]: Update association lookup to look at ASCONF chunks as well
ADD-IP draft section 5.2 specifies that if an association can not be found using the source and destination of the IP packet, then, if the packet contains ASCONF chunks, the Address Parameter TLV should be used to lookup an association. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/input.c')
-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}