diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-29 06:54:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-29 06:54:01 -0500 |
commit | 0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch) | |
tree | 62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/sctp/input.c | |
parent | 21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff) | |
parent | 85040bcb4643cba578839e953f25e2d1965d83d0 (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.c | 125 |
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. */ |
65 | static int sctp_rcv_ootb(struct sk_buff *); | 66 | static 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 | */ | ||
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 | |||
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 | */ |
949 | 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, |
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 | */ |
967 | 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, |
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 | } |