aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/input.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 06:54:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 06:54:01 -0500
commit0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch)
tree62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/sctp/input.c
parent21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff)
parent85040bcb4643cba578839e953f25e2d1965d83d0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
Diffstat (limited to 'net/sctp/input.c')
-rw-r--r--net/sctp/input.c125
1 files changed, 104 insertions, 21 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 91ae463b079b..d695f710fc77 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -60,6 +60,7 @@
60#include <net/xfrm.h> 60#include <net/xfrm.h>
61#include <net/sctp/sctp.h> 61#include <net/sctp/sctp.h>
62#include <net/sctp/sm.h> 62#include <net/sctp/sm.h>
63#include <net/sctp/checksum.h>
63 64
64/* Forward declarations for internal helpers. */ 65/* Forward declarations for internal helpers. */
65static int sctp_rcv_ootb(struct sk_buff *); 66static int sctp_rcv_ootb(struct sk_buff *);
@@ -890,14 +891,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
890 891
891 ch = (sctp_chunkhdr_t *) skb->data; 892 ch = (sctp_chunkhdr_t *) skb->data;
892 893
893 /* The code below will attempt to walk the chunk and extract
894 * parameter information. Before we do that, we need to verify
895 * that the chunk length doesn't cause overflow. Otherwise, we'll
896 * walk off the end.
897 */
898 if (WORD_ROUND(ntohs(ch->length)) > skb->len)
899 return NULL;
900
901 /* 894 /*
902 * This code will NOT touch anything inside the chunk--it is 895 * This code will NOT touch anything inside the chunk--it is
903 * strictly READ-ONLY. 896 * strictly READ-ONLY.
@@ -934,6 +927,44 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
934 return NULL; 927 return NULL;
935} 928}
936 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
937/* SCTP-AUTH, Section 6.3: 968/* SCTP-AUTH, Section 6.3:
938* 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
939* 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
@@ -942,20 +973,64 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
942* 973*
943* 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
944* to be looked at to find this assocation. 975* to be looked at to find this assocation.
945*
946* TODO: The only chunk currently defined that can do that is ASCONF, but we
947* don't support that functionality yet.
948*/ 976*/
949static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb, 977static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
950 const union sctp_addr *paddr,
951 const union sctp_addr *laddr, 978 const union sctp_addr *laddr,
952 struct sctp_transport **transportp) 979 struct sctp_transport **transportp)
953{ 980{
954 /* XXX - walk through the chunks looking for something that can 981 struct sctp_association *asoc = NULL;
955 * help us find the association. INIT, and INIT-ACK are not permitted. 982 sctp_chunkhdr_t *ch;
956 * 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.
957 */ 989 */
958 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;
959} 1034}
960 1035
961/* 1036/*
@@ -965,7 +1040,6 @@ static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb,
965 * chunks. 1040 * chunks.
966 */ 1041 */
967static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, 1042static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
968 const union sctp_addr *paddr,
969 const union sctp_addr *laddr, 1043 const union sctp_addr *laddr,
970 struct sctp_transport **transportp) 1044 struct sctp_transport **transportp)
971{ 1045{
@@ -973,6 +1047,14 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
973 1047
974 ch = (sctp_chunkhdr_t *) skb->data; 1048 ch = (sctp_chunkhdr_t *) skb->data;
975 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
976 /* If this is INIT/INIT-ACK look inside the chunk too. */ 1058 /* If this is INIT/INIT-ACK look inside the chunk too. */
977 switch (ch->type) { 1059 switch (ch->type) {
978 case SCTP_CID_INIT: 1060 case SCTP_CID_INIT:
@@ -980,11 +1062,12 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
980 return __sctp_rcv_init_lookup(skb, laddr, transportp); 1062 return __sctp_rcv_init_lookup(skb, laddr, transportp);
981 break; 1063 break;
982 1064
983 case SCTP_CID_AUTH: 1065 default:
984 return __sctp_rcv_auth_lookup(skb, paddr, laddr, transportp); 1066 return __sctp_rcv_walk_lookup(skb, laddr, transportp);
985 break; 1067 break;
986 } 1068 }
987 1069
1070
988 return NULL; 1071 return NULL;
989} 1072}
990 1073
@@ -1003,7 +1086,7 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
1003 * parameters within the INIT or INIT-ACK. 1086 * parameters within the INIT or INIT-ACK.
1004 */ 1087 */
1005 if (!asoc) 1088 if (!asoc)
1006 asoc = __sctp_rcv_lookup_harder(skb, paddr, laddr, transportp); 1089 asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp);
1007 1090
1008 return asoc; 1091 return asoc;
1009} 1092}