Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
8d0df569
Commit
8d0df569
authored
Apr 07, 2003
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.5.67
into us.ibm.com:/home/sridhar/BK/lksctp-2.5.67
parents
f01d7733
d77fdda9
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
381 additions
and
316 deletions
+381
-316
include/net/sctp/constants.h
include/net/sctp/constants.h
+29
-25
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+0
-6
include/net/sctp/structs.h
include/net/sctp/structs.h
+26
-27
net/sctp/Kconfig
net/sctp/Kconfig
+37
-10
net/sctp/Makefile
net/sctp/Makefile
+1
-2
net/sctp/associola.c
net/sctp/associola.c
+6
-5
net/sctp/endpointola.c
net/sctp/endpointola.c
+43
-46
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+139
-109
net/sctp/socket.c
net/sctp/socket.c
+100
-86
No files found.
include/net/sctp/constants.h
View file @
8d0df569
...
...
@@ -6,46 +6,42 @@
*
* This file is part of the SCTP kernel reference Implementation
*
* This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation.
*
* The SCTP reference implementation is free software;
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
*
the SCTP reference implementation
is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty
*
The SCTP reference implementation
is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
*
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
See the
GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to one of the following email
* addresses:
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@motorola.com>
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@motorola.com>
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*
* There are still LOTS of bugs in this code... I always run on the motto
* "it is a wonder any code ever works :)"
*
*
*/
#ifndef __sctp_constants_h__
...
...
@@ -336,10 +332,18 @@ typedef enum {
#define SCTP_SIGNATURE_SIZE 20
/* size of a SLA-1 signature */
#define SCTP_COOKIE_MULTIPLE
64
/* Pad out our cookie to make our hash
#define SCTP_COOKIE_MULTIPLE
32
/* Pad out our cookie to make our hash
* functions simpler to write.
*/
#if defined (CONFIG_SCTP_HMAC_MD5)
#define SCTP_COOKIE_HMAC_ALG "md5"
#elif defined (CONFIG_SCTP_HMAC_SHA1)
#define SCTP_COOKIE_HMAC_ALG "sha1"
#else
#define SCTP_COOKIE_HMAC_ALG NULL
#endif
/* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue.
*/
...
...
include/net/sctp/sctp.h
View file @
8d0df569
...
...
@@ -178,12 +178,6 @@ extern void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct
sctp_association
*
);
extern
void
sctp_icmp_frag_needed
(
struct
sock
*
,
struct
sctp_association
*
,
struct
sctp_transport
*
t
,
__u32
pmtu
);
/*
* sctp/hashdriver.c
*/
extern
void
sctp_hash_digest
(
const
char
*
secret
,
const
int
secret_len
,
const
char
*
text
,
const
int
text_len
,
__u8
*
digest
);
/*
* Section: Macros, externs, and inlines
...
...
include/net/sctp/structs.h
View file @
8d0df569
...
...
@@ -283,8 +283,11 @@ struct sctp_opt {
/* PF_ family specific functions. */
struct
sctp_pf
*
pf
;
/* Access to HMAC transform. */
struct
crypto_tfm
*
hmac
;
/* What is our base endpointer? */
s
ctp_endpoint_
t
*
ep
;
s
truct
sctp_endpoin
t
*
ep
;
/* Various Socket Options. */
__u16
default_stream
;
...
...
@@ -1054,11 +1057,6 @@ struct sctp_endpoint {
/* Common substructure for endpoint and association. */
sctp_endpoint_common_t
base
;
/* These are the system-wide defaults and other stuff which is
* endpoint-independent.
*/
struct
sctp_protocol
*
proto
;
/* Associations: A list of current associations and mappings
* to the data consumers for each association. This
* may be in the form of a hash table or other
...
...
@@ -1092,28 +1090,29 @@ struct sctp_endpoint {
};
/* Recover the outter endpoint structure. */
static
inline
s
ctp_endpoint_
t
*
sctp_ep
(
sctp_endpoint_common_t
*
base
)
static
inline
s
truct
sctp_endpoin
t
*
sctp_ep
(
sctp_endpoint_common_t
*
base
)
{
s
ctp_endpoint_
t
*
ep
;
s
truct
sctp_endpoin
t
*
ep
;
ep
=
container_of
(
base
,
s
ctp_endpoint_
t
,
base
);
ep
=
container_of
(
base
,
s
truct
sctp_endpoin
t
,
base
);
return
ep
;
}
/* These are function signatures for manipulating endpoints. */
sctp_endpoint_t
*
sctp_endpoint_new
(
struct
sctp_protocol
*
,
struct
sock
*
,
int
);
sctp_endpoint_t
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
,
struct
sctp_protocol
*
,
struct
sock
*
,
int
gfp
);
void
sctp_endpoint_free
(
sctp_endpoint_t
*
);
void
sctp_endpoint_put
(
sctp_endpoint_t
*
);
void
sctp_endpoint_hold
(
sctp_endpoint_t
*
);
void
sctp_endpoint_add_asoc
(
sctp_endpoint_t
*
,
struct
sctp_association
*
asoc
);
struct
sctp_association
*
sctp_endpoint_lookup_assoc
(
const
sctp_endpoint_t
*
ep
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
);
int
sctp_endpoint_is_peeled_off
(
sctp_endpoint_t
*
,
const
union
sctp_addr
*
);
sctp_endpoint_t
*
sctp_endpoint_is_match
(
sctp_endpoint_t
*
,
struct
sctp_endpoint
*
sctp_endpoint_new
(
struct
sock
*
,
int
);
struct
sctp_endpoint
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
,
struct
sock
*
,
int
gfp
);
void
sctp_endpoint_free
(
struct
sctp_endpoint
*
);
void
sctp_endpoint_put
(
struct
sctp_endpoint
*
);
void
sctp_endpoint_hold
(
struct
sctp_endpoint
*
);
void
sctp_endpoint_add_asoc
(
struct
sctp_endpoint
*
,
struct
sctp_association
*
);
struct
sctp_association
*
sctp_endpoint_lookup_assoc
(
const
struct
sctp_endpoint
*
ep
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
);
int
sctp_endpoint_is_peeled_off
(
struct
sctp_endpoint
*
,
const
union
sctp_addr
*
);
struct
sctp_endpoint
*
sctp_endpoint_is_match
(
struct
sctp_endpoint
*
,
const
union
sctp_addr
*
);
int
sctp_has_association
(
const
union
sctp_addr
*
laddr
,
const
union
sctp_addr
*
paddr
);
...
...
@@ -1126,8 +1125,8 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
sctp_init_chunk_t
*
init
,
int
gfp
);
int
sctp_process_param
(
struct
sctp_association
*
,
union
sctp_params
param
,
const
union
sctp_addr
*
from
,
int
gfp
);
__u32
sctp_generate_tag
(
const
s
ctp_endpoint_
t
*
);
__u32
sctp_generate_tsn
(
const
s
ctp_endpoint_
t
*
);
__u32
sctp_generate_tag
(
const
s
truct
sctp_endpoin
t
*
);
__u32
sctp_generate_tsn
(
const
s
truct
sctp_endpoin
t
*
);
/* RFC2960
...
...
@@ -1162,7 +1161,7 @@ struct sctp_association {
__u32
eyecatcher
;
/* This is our parent endpoint. */
s
ctp_endpoint_
t
*
ep
;
s
truct
sctp_endpoin
t
*
ep
;
/* These are those association elements needed in the cookie. */
sctp_cookie_t
c
;
...
...
@@ -1571,10 +1570,10 @@ static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base)
struct
sctp_association
*
sctp_association_new
(
const
s
ctp_endpoint_
t
*
,
const
struct
sock
*
,
sctp_association_new
(
const
s
truct
sctp_endpoin
t
*
,
const
struct
sock
*
,
sctp_scope_t
scope
,
int
gfp
);
struct
sctp_association
*
sctp_association_init
(
struct
sctp_association
*
,
const
s
ctp_endpoint_
t
*
,
sctp_association_init
(
struct
sctp_association
*
,
const
s
truct
sctp_endpoin
t
*
,
const
struct
sock
*
,
sctp_scope_t
scope
,
int
gfp
);
void
sctp_association_free
(
struct
sctp_association
*
);
...
...
net/sctp/Kconfig
View file @
8d0df569
...
...
@@ -43,12 +43,12 @@ config SCTP_ADLER32
bool "SCTP: Use old checksum (Adler-32)"
depends on IP_SCTP
help
RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
This has been deprecated and replaced by an algorithm now referred
to as crc32c.
If you say Y, this will use the Adler-32 algorithm, this might be
useful
for interoperation with downlevel peers.
If you say Y, this will use the Adler-32 algorithm, this might be
useful
for interoperation with downlevel peers.
If unsure, say N.
...
...
@@ -58,19 +58,46 @@ config SCTP_DBG_MSG
help
If you say Y, this will enable verbose debugging messages.
If unsure, say N. However, if you are running into problems, use
this
option to gather detailed trace information
If unsure, say N. However, if you are running into problems, use
this
option to gather detailed trace information
config SCTP_DBG_OBJCNT
bool "SCTP: Debug object counts"
depends on IP_SCTP
help
If you say Y, this will enable debugging support for counting the types
of objects that are currently allocated. This is useful for identifying
memory leaks. If the /proc filesystem is enabled this debug information
can be viewed by 'cat /proc/net/sctp/sctp_dbg_objcnt'
If you say Y, this will enable debugging support for counting the
type of objects that are currently allocated. This is useful for
identifying memory leaks. If the /proc filesystem is enabled this
debug information can be viewed by
'cat /proc/net/sctp/sctp_dbg_objcnt'
If unsure, say N
endmenu
choice
prompt "SCTP: Cookie HMAC Algorithm"
help
HMAC algorithm to be used during association initialization. It
is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See
configuration for Cryptographic API and enable those algorithms
to make usable by SCTP.
config SCTP_HMAC_NONE
bool "None"
help
Choosing this disables the use of an HMAC during association
establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_SHA1
bool "HMAC-SHA1" if CRYPTO_HMAC=y && CRYPTO_SHA1=y || CRYPTO_SHA1=m
help
Enable the use of HMAC-SHA1 during association establishment. It
is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_MD5
bool "HMAC-MD5" if CRYPTO_HMAC=y && CRYPTO_MD5=y || CRYPTO_MD5=m
help
Enable the use of HMAC-MD5 during association establishment. It is
advised to use either HMAC-MD5 or HMAC-SHA1.
endchoice
endmenu
net/sctp/Makefile
View file @
8d0df569
...
...
@@ -9,8 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
transport.o sm_make_chunk.o ulpevent.o
\
inqueue.o outqueue.o ulpqueue.o command.o
\
tsnmap.o bind_addr.o socket.o primitive.o
\
output.o input.o hashdriver.o sla1.o
\
debug.o ssnmap.o proc.o
output.o input.o debug.o ssnmap.o proc.o
ifeq
($(CONFIG_SCTP_ADLER32), y)
sctp-y
+=
adler32.o
...
...
net/sctp/associola.c
View file @
8d0df569
...
...
@@ -96,6 +96,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
int
priority
)
{
struct
sctp_opt
*
sp
;
struct
sctp_protocol
*
proto
=
sctp_get_protocol
();
int
i
;
/* Retrieve the SCTP per socket area. */
...
...
@@ -136,10 +137,10 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc
->
frag_point
=
0
;
/* Initialize the default association max_retrans and RTO values. */
asoc
->
max_retrans
=
ep
->
proto
->
max_retrans_association
;
asoc
->
rto_initial
=
ep
->
proto
->
rto_initial
;
asoc
->
rto_max
=
ep
->
proto
->
rto_max
;
asoc
->
rto_min
=
ep
->
proto
->
rto_min
;
asoc
->
max_retrans
=
proto
->
max_retrans_association
;
asoc
->
rto_initial
=
proto
->
rto_initial
;
asoc
->
rto_max
=
proto
->
rto_max
;
asoc
->
rto_min
=
proto
->
rto_min
;
asoc
->
overall_error_threshold
=
0
;
asoc
->
overall_error_count
=
0
;
...
...
@@ -147,7 +148,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
/* Initialize the maximum mumber of new data packets that can be sent
* in a burst.
*/
asoc
->
max_burst
=
ep
->
proto
->
max_burst
;
asoc
->
max_burst
=
proto
->
max_burst
;
/* Copy things from the endpoint. */
for
(
i
=
SCTP_EVENT_TIMEOUT_NONE
;
i
<
SCTP_NUM_TIMEOUT_TYPES
;
++
i
)
{
...
...
net/sctp/endpointola.c
View file @
8d0df569
...
...
@@ -54,27 +54,27 @@
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/random.h>
/* get_random_bytes() */
#include <linux/crypto.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */
static
void
sctp_endpoint_bh_rcv
(
s
ctp_endpoint_
t
*
ep
);
static
void
sctp_endpoint_bh_rcv
(
s
truct
sctp_endpoin
t
*
ep
);
/* Create a sctp_endpoint
_t
with all that boring stuff initialized.
/* Create a sctp_endpoint with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
sctp_endpoint_t
*
sctp_endpoint_new
(
struct
sctp_protocol
*
proto
,
struct
sock
*
sk
,
int
priority
)
struct
sctp_endpoint
*
sctp_endpoint_new
(
struct
sock
*
sk
,
int
gfp
)
{
s
ctp_endpoint_
t
*
ep
;
s
truct
sctp_endpoin
t
*
ep
;
/* Build a local endpoint. */
ep
=
t_new
(
s
ctp_endpoint_t
,
priority
);
ep
=
t_new
(
s
truct
sctp_endpoint
,
gfp
);
if
(
!
ep
)
goto
fail
;
if
(
!
sctp_endpoint_init
(
ep
,
proto
,
sk
,
priority
))
if
(
!
sctp_endpoint_init
(
ep
,
sk
,
gfp
))
goto
fail_init
;
ep
->
base
.
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
ep
);
...
...
@@ -89,12 +89,11 @@ sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
/*
* Initialize the base fields of the endpoint structure.
*/
sctp_endpoint_t
*
sctp_endpoint_init
(
sctp_endpoint_t
*
ep
,
struct
sctp_protocol
*
proto
,
struct
sock
*
sk
,
int
priority
)
struct
sctp_endpoint
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
ep
,
struct
sock
*
sk
,
int
gfp
)
{
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
memset
(
ep
,
0
,
sizeof
(
s
ctp_endpoint_
t
));
memset
(
ep
,
0
,
sizeof
(
s
truct
sctp_endpoin
t
));
/* Initialize the base structure. */
/* What type of endpoint are we? */
...
...
@@ -110,8 +109,7 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
/* Set its top-half handler */
sctp_inq_set_th_handler
(
&
ep
->
base
.
inqueue
,
(
void
(
*
)(
void
*
))
sctp_endpoint_bh_rcv
,
ep
);
(
void
(
*
)(
void
*
))
sctp_endpoint_bh_rcv
,
ep
);
/* Initialize the bind addr area */
sctp_bind_addr_init
(
&
ep
->
base
.
bind_addr
,
0
);
...
...
@@ -121,21 +119,16 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep
->
base
.
sk
=
sk
;
sock_hold
(
ep
->
base
.
sk
);
/* This pointer is useful to access the default protocol parameter
* values.
*/
ep
->
proto
=
proto
;
/* Create the lists of associations. */
INIT_LIST_HEAD
(
&
ep
->
asocs
);
/* Set up the base timeout information. */
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_NONE
]
=
0
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]
=
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]
=
SCTP_DEFAULT_TIMEOUT_T1_COOKIE
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]
=
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]
=
SCTP_DEFAULT_TIMEOUT_T1_INIT
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN
]
=
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN
]
=
sp
->
rtoinfo
.
srto_initial
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T3_RTX
]
=
0
;
...
...
@@ -146,11 +139,11 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD
]
=
5
*
sp
->
rtoinfo
.
srto_max
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_HEARTBEAT
]
=
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_HEARTBEAT
]
=
SCTP_DEFAULT_TIMEOUT_HEARTBEAT
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_SACK
]
=
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_SACK
]
=
SCTP_DEFAULT_TIMEOUT_SACK
;
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_AUTOCLOSE
]
=
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_AUTOCLOSE
]
=
sp
->
autoclose
*
HZ
;
/* Set up the default send/receive buffer space. */
...
...
@@ -175,7 +168,8 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
}
/* Add an association to an endpoint. */
void
sctp_endpoint_add_asoc
(
sctp_endpoint_t
*
ep
,
sctp_association_t
*
asoc
)
void
sctp_endpoint_add_asoc
(
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
)
{
struct
sock
*
sk
=
ep
->
base
.
sk
;
...
...
@@ -191,14 +185,14 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
/* Free the endpoint structure. Delay cleanup until
* all users have released their reference count on this structure.
*/
void
sctp_endpoint_free
(
s
ctp_endpoint_
t
*
ep
)
void
sctp_endpoint_free
(
s
truct
sctp_endpoin
t
*
ep
)
{
ep
->
base
.
dead
=
1
;
sctp_endpoint_put
(
ep
);
}
/* Final destructor for endpoint. */
void
sctp_endpoint_destroy
(
s
ctp_endpoint_
t
*
ep
)
void
sctp_endpoint_destroy
(
s
truct
sctp_endpoin
t
*
ep
)
{
SCTP_ASSERT
(
ep
->
base
.
dead
,
"Endpoint is not dead"
,
return
);
...
...
@@ -207,9 +201,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
/* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint
(
ep
);
/* Cleanup the inqueue. */
sctp_inq_free
(
&
ep
->
base
.
inqueue
);
/* Free up the HMAC transform. */
if
(
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
)
crypto_free_tfm
(
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
);
/* Cleanup. */
sctp_inq_free
(
&
ep
->
base
.
inqueue
);
sctp_bind_addr_free
(
&
ep
->
base
.
bind_addr
);
/* Remove and free the port */
...
...
@@ -228,7 +225,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
}
/* Hold a reference to an endpoint. */
void
sctp_endpoint_hold
(
s
ctp_endpoint_
t
*
ep
)
void
sctp_endpoint_hold
(
s
truct
sctp_endpoin
t
*
ep
)
{
atomic_inc
(
&
ep
->
base
.
refcnt
);
}
...
...
@@ -236,17 +233,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep)
/* Release a reference to an endpoint and clean up if there are
* no more references.
*/
void
sctp_endpoint_put
(
s
ctp_endpoint_
t
*
ep
)
void
sctp_endpoint_put
(
s
truct
sctp_endpoin
t
*
ep
)
{
if
(
atomic_dec_and_test
(
&
ep
->
base
.
refcnt
))
sctp_endpoint_destroy
(
ep
);
}
/* Is this the endpoint we are looking for? */
s
ctp_endpoint_t
*
sctp_endpoint_is_match
(
sctp_endpoint_
t
*
ep
,
const
union
sctp_addr
*
laddr
)
s
truct
sctp_endpoint
*
sctp_endpoint_is_match
(
struct
sctp_endpoin
t
*
ep
,
const
union
sctp_addr
*
laddr
)
{
s
ctp_endpoint_
t
*
retval
;
s
truct
sctp_endpoin
t
*
retval
;
sctp_read_lock
(
&
ep
->
base
.
addr_lock
);
if
(
ep
->
base
.
bind_addr
.
port
==
laddr
->
v4
.
sin_port
)
{
...
...
@@ -268,19 +265,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
s
ctp_association_t
*
__sctp_endpoint_lookup_assoc
(
const
s
ctp_endpoint_t
*
endpoint
,
s
truct
sctp_association
*
__sctp_endpoint_lookup_assoc
(
const
s
truct
sctp_endpoint
*
ep
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
transport
)
{
int
rport
;
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
rport
=
paddr
->
v4
.
sin_port
;
list_for_each
(
pos
,
&
e
ndpoint
->
asocs
)
{
asoc
=
list_entry
(
pos
,
s
ctp_association_t
,
asocs
);
list_for_each
(
pos
,
&
e
p
->
asocs
)
{
asoc
=
list_entry
(
pos
,
s
truct
sctp_association
,
asocs
);
if
(
rport
==
asoc
->
peer
.
port
)
{
sctp_read_lock
(
&
asoc
->
base
.
addr_lock
);
*
transport
=
sctp_assoc_lookup_paddr
(
asoc
,
paddr
);
...
...
@@ -296,12 +293,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc(
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
s
ctp_association_t
*
sctp_endpoint_lookup_assoc
(
const
s
ctp_endpoint_
t
*
ep
,
s
truct
sctp_association
*
sctp_endpoint_lookup_assoc
(
const
s
truct
sctp_endpoin
t
*
ep
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
transport
)
{
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
sctp_local_bh_disable
();
asoc
=
__sctp_endpoint_lookup_assoc
(
ep
,
paddr
,
transport
);
...
...
@@ -313,7 +310,7 @@ sctp_association_t *sctp_endpoint_lookup_assoc(
/* Look for any peeled off association from the endpoint that matches the
* given peer address.
*/
int
sctp_endpoint_is_peeled_off
(
s
ctp_endpoint_
t
*
ep
,
int
sctp_endpoint_is_peeled_off
(
s
truct
sctp_endpoin
t
*
ep
,
const
union
sctp_addr
*
paddr
)
{
struct
list_head
*
pos
;
...
...
@@ -337,9 +334,9 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
/* Do delayed input processing. This is scheduled by sctp_rcv().
* This may be called on BH or task time.
*/
static
void
sctp_endpoint_bh_rcv
(
s
ctp_endpoint_
t
*
ep
)
static
void
sctp_endpoint_bh_rcv
(
s
truct
sctp_endpoin
t
*
ep
)
{
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
struct
sock
*
sk
;
struct
sctp_transport
*
transport
;
sctp_chunk_t
*
chunk
;
...
...
@@ -355,7 +352,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
inqueue
=
&
ep
->
base
.
inqueue
;
sk
=
ep
->
base
.
sk
;
while
(
NULL
!=
(
chunk
=
sctp_inq_pop
(
inqueue
)))
{
while
(
NULL
!=
(
chunk
=
sctp_inq_pop
(
inqueue
)))
{
subtype
.
chunk
=
chunk
->
chunk_hdr
->
type
;
/* We might have grown an association since last we
...
...
net/sctp/sm_make_chunk.c
View file @
8d0df569
...
...
@@ -59,6 +59,8 @@
#include <linux/ipv6.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <net/sock.h>
#include <linux/skbuff.h>
...
...
@@ -156,7 +158,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
* Host Name Address (Note 3) Optional 11
* Supported Address Types (Note 4) Optional 12
*/
sctp_chunk_t
*
sctp_make_init
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_init
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_bind_addr_t
*
bp
,
int
gfp
,
int
vparam_len
)
{
...
...
@@ -236,7 +238,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
return
retval
;
}
sctp_chunk_t
*
sctp_make_init_ack
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_init_ack
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
int
gfp
,
int
unkparam_len
)
{
...
...
@@ -294,7 +296,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
sctp_addto_chunk
(
retval
,
sizeof
(
ecap_param
),
&
ecap_param
);
/* We need to remove the const qualifier at this point. */
retval
->
asoc
=
(
s
ctp_association_t
*
)
asoc
;
retval
->
asoc
=
(
s
truct
sctp_association
*
)
asoc
;
/* RFC 2960 6.4 Multi-homed SCTP Endpoints
*
...
...
@@ -350,7 +352,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
* An implementation SHOULD make the cookie as small as possible
* to insure interoperability.
*/
sctp_chunk_t
*
sctp_make_cookie_echo
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_cookie_echo
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -401,7 +403,7 @@ sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *asoc,
*
* Set to zero on transmit and ignored on receipt.
*/
sctp_chunk_t
*
sctp_make_cookie_ack
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_cookie_ack
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -446,7 +448,7 @@ sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *asoc,
*
* Note: The CWR is considered a Control chunk.
*/
sctp_chunk_t
*
sctp_make_cwr
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_cwr
(
const
s
truct
sctp_association
*
asoc
,
const
__u32
lowest_tsn
,
const
sctp_chunk_t
*
chunk
)
{
...
...
@@ -481,7 +483,7 @@ sctp_chunk_t *sctp_make_cwr(const sctp_association_t *asoc,
}
/* Make an ECNE chunk. This is a congestion experienced report. */
sctp_chunk_t
*
sctp_make_ecne
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_ecne
(
const
s
truct
sctp_association
*
asoc
,
const
__u32
lowest_tsn
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -502,7 +504,7 @@ sctp_chunk_t *sctp_make_ecne(const sctp_association_t *asoc,
/* Make a DATA chunk for the given association from the provided
* parameters. However, do not populate the data payload.
*/
sctp_chunk_t
*
sctp_make_datafrag_empty
(
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_datafrag_empty
(
s
truct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
,
__u8
flags
,
__u16
ssn
)
{
...
...
@@ -537,7 +539,7 @@ sctp_chunk_t *sctp_make_datafrag_empty(sctp_association_t *asoc,
/* Make a DATA chunk for the given association. Populate the data
* payload.
*/
sctp_chunk_t
*
sctp_make_datafrag
(
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_datafrag
(
s
truct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
,
const
__u8
*
data
,
__u8
flags
,
__u16
ssn
)
...
...
@@ -554,7 +556,7 @@ sctp_chunk_t *sctp_make_datafrag(sctp_association_t *asoc,
/* Make a DATA chunk for the given association to ride on stream id
* 'stream', with a payload id of 'payload', and a body of 'data'.
*/
sctp_chunk_t
*
sctp_make_data
(
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_data
(
s
truct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
,
const
__u8
*
data
)
{
...
...
@@ -571,7 +573,7 @@ sctp_chunk_t *sctp_make_data(sctp_association_t *asoc,
* hold 'data_len' octets of data. We use this version when we need
* to build the message AFTER allocating memory.
*/
sctp_chunk_t
*
sctp_make_data_empty
(
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_data_empty
(
s
truct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
)
{
...
...
@@ -584,7 +586,7 @@ sctp_chunk_t *sctp_make_data_empty(sctp_association_t *asoc,
* association. This reports on which TSN's we've seen to date,
* including duplicates and gaps.
*/
sctp_chunk_t
*
sctp_make_sack
(
const
s
ctp_association_t
*
asoc
)
sctp_chunk_t
*
sctp_make_sack
(
const
s
truct
sctp_association
*
asoc
)
{
sctp_chunk_t
*
retval
;
sctp_sackhdr_t
sack
;
...
...
@@ -599,11 +601,13 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
SCTP_DEBUG_PRINTK
(
"sackCTSNAck sent is 0x%x.
\n
"
,
ctsn
);
/* Count the number of Gap Ack Blocks. */
sctp_tsnmap_iter_init
(
map
,
&
iter
);
for
(
num_gabs
=
0
;
sctp_tsnmap_next_gap_ack
(
map
,
&
iter
,
&
gab
.
start
,
&
gab
.
end
);
num_gabs
++
)
{
/* Do nothing. */
num_gabs
=
0
;
if
(
sctp_tsnmap_has_gap
(
map
))
{
sctp_tsnmap_iter_init
(
map
,
&
iter
);
while
(
sctp_tsnmap_next_gap_ack
(
map
,
&
iter
,
&
gab
.
start
,
&
gab
.
end
))
num_gabs
++
;
}
num_dup_tsns
=
sctp_tsnmap_num_dups
(
map
);
...
...
@@ -659,11 +663,15 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
sctp_addto_chunk
(
retval
,
sizeof
(
sack
),
&
sack
);
/* Put the Gap Ack Blocks into the chunk. */
sctp_tsnmap_iter_init
(
map
,
&
iter
);
while
(
sctp_tsnmap_next_gap_ack
(
map
,
&
iter
,
&
gab
.
start
,
&
gab
.
end
))
{
gab
.
start
=
htons
(
gab
.
start
);
gab
.
end
=
htons
(
gab
.
end
);
sctp_addto_chunk
(
retval
,
sizeof
(
sctp_gap_ack_block_t
),
&
gab
);
if
(
num_gabs
)
{
sctp_tsnmap_iter_init
(
map
,
&
iter
);
while
(
sctp_tsnmap_next_gap_ack
(
map
,
&
iter
,
&
gab
.
start
,
&
gab
.
end
))
{
gab
.
start
=
htons
(
gab
.
start
);
gab
.
end
=
htons
(
gab
.
end
);
sctp_addto_chunk
(
retval
,
sizeof
(
sctp_gap_ack_block_t
),
&
gab
);
}
}
/* Register the duplicates. */
...
...
@@ -675,7 +683,7 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
}
/* Make a SHUTDOWN chunk. */
sctp_chunk_t
*
sctp_make_shutdown
(
const
s
ctp_association_t
*
asoc
)
sctp_chunk_t
*
sctp_make_shutdown
(
const
s
truct
sctp_association
*
asoc
)
{
sctp_chunk_t
*
retval
;
sctp_shutdownhdr_t
shut
;
...
...
@@ -695,7 +703,7 @@ sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc)
return
retval
;
}
sctp_chunk_t
*
sctp_make_shutdown_ack
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_shutdown_ack
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -717,7 +725,7 @@ sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc,
return
retval
;
}
sctp_chunk_t
*
sctp_make_shutdown_complete
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_shutdown_complete
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -747,7 +755,7 @@ sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *asoc,
/* Create an ABORT. Note that we set the T bit if we have no
* association.
*/
sctp_chunk_t
*
sctp_make_abort
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_abort
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
const
size_t
hint
)
{
...
...
@@ -775,7 +783,7 @@ sctp_chunk_t *sctp_make_abort(const sctp_association_t *asoc,
}
/* Helper to create ABORT with a NO_USER_DATA error. */
sctp_chunk_t
*
sctp_make_abort_no_data
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_abort_no_data
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
__u32
tsn
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -809,7 +817,7 @@ sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *asoc,
}
/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */
sctp_chunk_t
*
sctp_make_abort_user
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_abort_user
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
const
struct
msghdr
*
msg
)
{
...
...
@@ -856,7 +864,7 @@ sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *asoc,
}
/* Make a HEARTBEAT chunk. */
sctp_chunk_t
*
sctp_make_heartbeat
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_heartbeat
(
const
s
truct
sctp_association
*
asoc
,
const
struct
sctp_transport
*
transport
,
const
void
*
payload
,
const
size_t
paylen
)
{
...
...
@@ -876,7 +884,7 @@ sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *asoc,
return
retval
;
}
sctp_chunk_t
*
sctp_make_heartbeat_ack
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_heartbeat_ack
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
const
void
*
payload
,
const
size_t
paylen
)
{
...
...
@@ -906,7 +914,7 @@ sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *asoc,
/* Create an Operation Error chunk with the specified space reserved.
* This routine can be used for containing multiple causes in the chunk.
*/
sctp_chunk_t
*
sctp_make_op_error_space
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_op_error_space
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
size_t
size
)
{
...
...
@@ -933,7 +941,7 @@ sctp_chunk_t *sctp_make_op_error_space(const sctp_association_t *asoc,
}
/* Create an Operation Error chunk. */
sctp_chunk_t
*
sctp_make_op_error
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_op_error
(
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
chunk
,
__u16
cause_code
,
const
void
*
payload
,
size_t
paylen
)
...
...
@@ -956,7 +964,8 @@ sctp_chunk_t *sctp_make_op_error(const sctp_association_t *asoc,
/* Turn an skb into a chunk.
* FIXME: Eventually move the structure directly inside the skb->cb[].
*/
sctp_chunk_t
*
sctp_chunkify
(
struct
sk_buff
*
skb
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_chunkify
(
struct
sk_buff
*
skb
,
const
struct
sctp_association
*
asoc
,
struct
sock
*
sk
)
{
sctp_chunk_t
*
retval
=
t_new
(
sctp_chunk_t
,
GFP_ATOMIC
);
...
...
@@ -970,7 +979,7 @@ sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc,
}
retval
->
skb
=
skb
;
retval
->
asoc
=
(
s
ctp_association_t
*
)
asoc
;
retval
->
asoc
=
(
s
truct
sctp_association
*
)
asoc
;
retval
->
num_times_sent
=
0
;
retval
->
has_tsn
=
0
;
retval
->
has_ssn
=
0
;
...
...
@@ -1023,7 +1032,7 @@ const union sctp_addr *sctp_source(const sctp_chunk_t *chunk)
/* Create a new chunk, setting the type and flags headers from the
* arguments, reserving enough space for a 'paylen' byte payload.
*/
sctp_chunk_t
*
sctp_make_chunk
(
const
s
ctp_association_t
*
asoc
,
sctp_chunk_t
*
sctp_make_chunk
(
const
s
truct
sctp_association
*
asoc
,
__u8
type
,
__u8
flags
,
int
paylen
)
{
sctp_chunk_t
*
retval
;
...
...
@@ -1032,7 +1041,7 @@ sctp_chunk_t *sctp_make_chunk(const sctp_association_t *asoc,
struct
sock
*
sk
;
/* No need to allocate LL here, as this is only a chunk. */
skb
=
alloc_skb
(
WORD_ROUND
(
sizeof
(
sctp_chunkhdr_t
)
+
paylen
),
skb
=
alloc_skb
(
WORD_ROUND
(
sizeof
(
sctp_chunkhdr_t
)
+
paylen
),
GFP_ATOMIC
);
if
(
!
skb
)
goto
nodata
;
...
...
@@ -1135,7 +1144,7 @@ static int sctp_user_addto_chunk(sctp_chunk_t *chunk, int off, int len,
*/
int
sctp_datachunks_from_user
(
s
ctp_association_t
*
asoc
,
int
sctp_datachunks_from_user
(
s
truct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
struct
msghdr
*
msg
,
int
msg_len
,
struct
sk_buff_head
*
chunks
)
...
...
@@ -1291,10 +1300,10 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
}
/* Create a CLOSED association to use with an incoming packet. */
s
ctp_association_t
*
sctp_make_temp_asoc
(
const
struct
sctp_endpoint
*
ep
,
s
truct
sctp_association
*
sctp_make_temp_asoc
(
const
struct
sctp_endpoint
*
ep
,
struct
sctp_chunk
*
chunk
,
int
gfp
)
{
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
struct
sk_buff
*
skb
;
sctp_scope_t
scope
;
...
...
@@ -1339,15 +1348,18 @@ sctp_association_t *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
/* Build a cookie representing asoc.
* This INCLUDES the param header needed to put the cookie in the INIT ACK.
*/
sctp_cookie_param_t
*
sctp_pack_cookie
(
const
s
ctp_endpoint_
t
*
ep
,
const
s
ctp_association_t
*
asoc
,
sctp_cookie_param_t
*
sctp_pack_cookie
(
const
s
truct
sctp_endpoin
t
*
ep
,
const
s
truct
sctp_association
*
asoc
,
const
sctp_chunk_t
*
init_chunk
,
int
*
cookie_len
,
const
__u8
*
raw_addrs
,
int
addrs_len
)
{
sctp_cookie_param_t
*
retval
;
sctp_signed_cookie_t
*
cookie
;
struct
scatterlist
sg
;
int
headersize
,
bodysize
;
unsigned
int
keylen
=
SCTP_SECRET_SIZE
;
char
*
key
;
headersize
=
sizeof
(
sctp_paramhdr_t
)
+
SCTP_SECRET_SIZE
;
bodysize
=
sizeof
(
sctp_cookie_t
)
...
...
@@ -1361,8 +1373,8 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
-
(
bodysize
%
SCTP_COOKIE_MULTIPLE
);
*
cookie_len
=
headersize
+
bodysize
;
retval
=
(
sctp_cookie_param_t
*
)
kmalloc
(
*
cookie_len
,
GFP_ATOMIC
);
retval
=
(
sctp_cookie_param_t
*
)
kmalloc
(
*
cookie_len
,
GFP_ATOMIC
);
if
(
!
retval
)
{
*
cookie_len
=
0
;
goto
nodata
;
...
...
@@ -1392,31 +1404,39 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
ntohs
(
init_chunk
->
chunk_hdr
->
length
));
/* Copy the raw local address list of the association. */
memcpy
((
__u8
*
)
&
cookie
->
c
.
peer_init
[
0
]
+
ntohs
(
init_chunk
->
chunk_hdr
->
length
),
raw_addrs
,
addrs_len
);
/* Sign the message. */
sctp_hash_digest
(
ep
->
secret_key
[
ep
->
current_key
],
SCTP_SECRET_SIZE
,
(
__u8
*
)
&
cookie
->
c
,
bodysize
,
cookie
->
signature
);
memcpy
((
__u8
*
)
&
cookie
->
c
.
peer_init
[
0
]
+
ntohs
(
init_chunk
->
chunk_hdr
->
length
),
raw_addrs
,
addrs_len
);
if
(
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
)
{
/* Sign the message. */
sg
.
page
=
virt_to_page
(
&
cookie
->
c
);
sg
.
offset
=
(
unsigned
long
)(
&
cookie
->
c
)
%
PAGE_SIZE
;
sg
.
length
=
bodysize
;
key
=
(
char
*
)
ep
->
secret_key
[
ep
->
current_key
];
crypto_hmac
(
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
,
key
,
&
keylen
,
&
sg
,
1
,
cookie
->
signature
);
}
nodata:
return
retval
;
}
/* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */
sctp_association_t
*
sctp_unpack_cookie
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
int
gfp
,
int
*
error
,
sctp_chunk_t
**
err_chk_p
)
struct
sctp_association
*
sctp_unpack_cookie
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
sctp_chunk_t
*
chunk
,
int
gfp
,
int
*
error
,
sctp_chunk_t
**
errp
)
{
s
ctp_association_t
*
retval
=
NULL
;
s
truct
sctp_association
*
retval
=
NULL
;
sctp_signed_cookie_t
*
cookie
;
sctp_cookie_t
*
bear_cookie
;
int
headersize
,
bodysize
;
int
fixed_size
;
__u8
digest_buf
[
SCTP_SIGNATURE_SIZE
];
int
secret
;
int
headersize
,
bodysize
,
fixed_size
;
__u8
digest
[
SCTP_SIGNATURE_SIZE
];
struct
scatterlist
sg
;
unsigned
int
keylen
;
char
*
key
;
sctp_scope_t
scope
;
struct
sk_buff
*
skb
=
chunk
->
skb
;
...
...
@@ -1440,23 +1460,34 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
cookie
=
chunk
->
subh
.
cookie_hdr
;
bear_cookie
=
&
cookie
->
c
;
if
(
!
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
)
goto
no_hmac
;
/* Check the signature. */
secret
=
ep
->
current_key
;
sctp_hash_digest
(
ep
->
secret_key
[
secret
],
SCTP_SECRET_SIZE
,
(
__u8
*
)
bear_cookie
,
bodysize
,
digest_buf
);
if
(
memcmp
(
digest_buf
,
cookie
->
signature
,
SCTP_SIGNATURE_SIZE
))
{
/* Try the previous key. */
secret
=
ep
->
last_key
;
sctp_hash_digest
(
ep
->
secret_key
[
secret
],
SCTP_SECRET_SIZE
,
(
__u8
*
)
bear_cookie
,
bodysize
,
digest_buf
);
if
(
memcmp
(
digest_buf
,
cookie
->
signature
,
SCTP_SIGNATURE_SIZE
))
{
keylen
=
SCTP_SECRET_SIZE
;
sg
.
page
=
virt_to_page
(
bear_cookie
);
sg
.
offset
=
(
unsigned
long
)(
bear_cookie
)
%
PAGE_SIZE
;
sg
.
length
=
bodysize
;
key
=
(
char
*
)
ep
->
secret_key
[
ep
->
current_key
];
memset
(
digest
,
0x00
,
sizeof
(
digest
));
crypto_hmac
(
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
,
key
,
&
keylen
,
&
sg
,
1
,
digest
);
if
(
memcmp
(
digest
,
cookie
->
signature
,
SCTP_SIGNATURE_SIZE
))
{
/* Try the previous key. */
key
=
(
char
*
)
ep
->
secret_key
[
ep
->
last_key
];
memset
(
digest
,
0x00
,
sizeof
(
digest
));
crypto_hmac
(
sctp_sk
(
ep
->
base
.
sk
)
->
hmac
,
key
,
&
keylen
,
&
sg
,
1
,
digest
);
if
(
memcmp
(
digest
,
cookie
->
signature
,
SCTP_SIGNATURE_SIZE
))
{
/* Yikes! Still bad signature! */
*
error
=
-
SCTP_IERROR_BAD_SIG
;
goto
fail
;
}
}
no_hmac:
/* Check to see if the cookie is stale. If there is already
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
...
...
@@ -1472,15 +1503,15 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* Cookie that has expired.
*/
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
*
err
_chk_
p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
*
err
_chk_
p
)
{
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
*
errp
)
{
suseconds_t
usecs
=
(
skb
->
stamp
.
tv_sec
-
bear_cookie
->
expiration
.
tv_sec
)
*
1000000L
+
skb
->
stamp
.
tv_usec
-
bear_cookie
->
expiration
.
tv_usec
;
usecs
=
htonl
(
usecs
);
sctp_init_cause
(
*
err
_chk_
p
,
SCTP_ERROR_STALE_COOKIE
,
sctp_init_cause
(
*
errp
,
SCTP_ERROR_STALE_COOKIE
,
&
usecs
,
sizeof
(
usecs
));
*
error
=
-
SCTP_IERROR_STALE_COOKIE
;
}
else
...
...
@@ -1541,10 +1572,10 @@ struct __sctp_missing {
/*
* Report a missing mandatory parameter.
*/
static
int
sctp_process_missing_param
(
const
s
ctp_association_t
*
asoc
,
static
int
sctp_process_missing_param
(
const
s
truct
sctp_association
*
asoc
,
sctp_param_t
paramtype
,
sctp_chunk_t
*
chunk
,
sctp_chunk_t
**
err
_chk_
p
)
sctp_chunk_t
**
errp
)
{
struct
__sctp_missing
report
;
__u16
len
;
...
...
@@ -1554,13 +1585,13 @@ static int sctp_process_missing_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
if
(
!*
err
_chk_
p
)
*
err
_chk_
p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
!*
errp
)
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
*
err
_chk_
p
)
{
if
(
*
errp
)
{
report
.
num_missing
=
htonl
(
1
);
report
.
type
=
paramtype
;
sctp_init_cause
(
*
err
_chk_
p
,
SCTP_ERROR_INV_PARAM
,
sctp_init_cause
(
*
errp
,
SCTP_ERROR_INV_PARAM
,
&
report
,
sizeof
(
report
));
}
...
...
@@ -1569,17 +1600,17 @@ static int sctp_process_missing_param(const sctp_association_t *asoc,
}
/* Report an Invalid Mandatory Parameter. */
static
int
sctp_process_inv_mandatory
(
const
s
ctp_association_t
*
asoc
,
static
int
sctp_process_inv_mandatory
(
const
s
truct
sctp_association
*
asoc
,
sctp_chunk_t
*
chunk
,
sctp_chunk_t
**
err
_chk_
p
)
sctp_chunk_t
**
errp
)
{
/* Invalid Mandatory Parameter Error has no payload. */
if
(
!*
err
_chk_
p
)
*
err
_chk_
p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
0
);
if
(
!*
errp
)
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
0
);
if
(
*
err
_chk_
p
)
sctp_init_cause
(
*
err
_chk_
p
,
SCTP_ERROR_INV_PARAM
,
NULL
,
0
);
if
(
*
errp
)
sctp_init_cause
(
*
errp
,
SCTP_ERROR_INV_PARAM
,
NULL
,
0
);
/* Stop processing this chunk. */
return
0
;
...
...
@@ -1588,19 +1619,19 @@ static int sctp_process_inv_mandatory(const sctp_association_t *asoc,
/* Do not attempt to handle the HOST_NAME parm. However, do
* send back an indicator to the peer.
*/
static
int
sctp_process_hn_param
(
const
s
ctp_association_t
*
asoc
,
static
int
sctp_process_hn_param
(
const
s
truct
sctp_association
*
asoc
,
union
sctp_params
param
,
sctp_chunk_t
*
chunk
,
sctp_chunk_t
**
err
_chk_
p
)
sctp_chunk_t
**
errp
)
{
__u16
len
=
ntohs
(
param
.
p
->
length
);
/* Make an ERROR chunk. */
if
(
!*
err
_chk_
p
)
*
err
_chk_
p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
!*
errp
)
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
*
err
_chk_
p
)
sctp_init_cause
(
*
err
_chk_
p
,
SCTP_ERROR_DNS_FAILED
,
if
(
*
errp
)
sctp_init_cause
(
*
errp
,
SCTP_ERROR_DNS_FAILED
,
param
.
v
,
len
);
/* Stop processing this chunk. */
...
...
@@ -1633,10 +1664,10 @@ static int sctp_process_hn_param(const sctp_association_t *asoc,
* 0 - discard the chunk
* 1 - continue with the chunk
*/
static
int
sctp_process_unk_param
(
const
s
ctp_association_t
*
asoc
,
static
int
sctp_process_unk_param
(
const
s
truct
sctp_association
*
asoc
,
union
sctp_params
param
,
sctp_chunk_t
*
chunk
,
sctp_chunk_t
**
err
_chk_
p
)
sctp_chunk_t
**
errp
)
{
int
retval
=
1
;
...
...
@@ -1649,12 +1680,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
if
(
NULL
==
*
err
_chk_
p
)
*
err
_chk_
p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
if
(
NULL
==
*
errp
)
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
ntohs
(
chunk
->
chunk_hdr
->
length
));
if
(
*
err
_chk_
p
)
sctp_init_cause
(
*
err
_chk_
p
,
SCTP_ERROR_UNKNOWN_PARAM
,
if
(
*
errp
)
sctp_init_cause
(
*
errp
,
SCTP_ERROR_UNKNOWN_PARAM
,
param
.
v
,
WORD_ROUND
(
ntohs
(
param
.
p
->
length
)));
...
...
@@ -1665,12 +1696,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
if
(
NULL
==
*
err
_chk_
p
)
*
err
_chk_
p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
if
(
NULL
==
*
errp
)
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
ntohs
(
chunk
->
chunk_hdr
->
length
));
if
(
*
err
_chk_
p
)
{
sctp_init_cause
(
*
err
_chk_
p
,
SCTP_ERROR_UNKNOWN_PARAM
,
if
(
*
errp
)
{
sctp_init_cause
(
*
errp
,
SCTP_ERROR_UNKNOWN_PARAM
,
param
.
v
,
WORD_ROUND
(
ntohs
(
param
.
p
->
length
)));
}
else
{
...
...
@@ -1695,7 +1726,7 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
* 0 - discard the chunk
* 1 - continue with the chunk
*/
static
int
sctp_verify_param
(
const
s
ctp_association_t
*
asoc
,
static
int
sctp_verify_param
(
const
s
truct
sctp_association
*
asoc
,
union
sctp_params
param
,
sctp_cid_t
cid
,
sctp_chunk_t
*
chunk
,
...
...
@@ -1733,11 +1764,11 @@ static int sctp_verify_param(const sctp_association_t *asoc,
}
/* Verify the INIT packet before we process it. */
int
sctp_verify_init
(
const
s
ctp_association_t
*
asoc
,
int
sctp_verify_init
(
const
s
truct
sctp_association
*
asoc
,
sctp_cid_t
cid
,
sctp_init_chunk_t
*
peer_init
,
sctp_chunk_t
*
chunk
,
sctp_chunk_t
**
err
_chk_
p
)
sctp_chunk_t
**
errp
)
{
union
sctp_params
param
;
int
has_cookie
=
0
;
...
...
@@ -1746,7 +1777,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
if
((
0
==
peer_init
->
init_hdr
.
num_outbound_streams
)
||
(
0
==
peer_init
->
init_hdr
.
num_inbound_streams
))
{
sctp_process_inv_mandatory
(
asoc
,
chunk
,
err
_chk_
p
);
sctp_process_inv_mandatory
(
asoc
,
chunk
,
errp
);
return
0
;
}
...
...
@@ -1762,9 +1793,8 @@ int sctp_verify_init(const sctp_association_t *asoc,
* the state cookie for an INIT-ACK chunk.
*/
if
((
SCTP_CID_INIT_ACK
==
cid
)
&&
!
has_cookie
)
{
sctp_process_missing_param
(
asoc
,
SCTP_PARAM_STATE_COOKIE
,
chunk
,
err
_chk_
p
);
chunk
,
errp
);
return
0
;
}
...
...
@@ -1772,7 +1802,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
sctp_walk_params
(
param
,
peer_init
,
init_hdr
.
params
)
{
if
(
!
sctp_verify_param
(
asoc
,
param
,
cid
,
chunk
,
err
_chk_
p
))
if
(
!
sctp_verify_param
(
asoc
,
param
,
cid
,
chunk
,
errp
))
return
0
;
}
/* for (loop through all parameters) */
...
...
@@ -1784,7 +1814,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
* Returns 0 on failure, else success.
* FIXME: This is an association method.
*/
int
sctp_process_init
(
s
ctp_association_t
*
asoc
,
sctp_cid_t
cid
,
int
sctp_process_init
(
s
truct
sctp_association
*
asoc
,
sctp_cid_t
cid
,
const
union
sctp_addr
*
peer_addr
,
sctp_init_chunk_t
*
peer_init
,
int
gfp
)
{
...
...
@@ -1923,7 +1953,7 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* work we do. In particular, we should not build transport
* structures for the addresses.
*/
int
sctp_process_param
(
s
ctp_association_t
*
asoc
,
union
sctp_params
param
,
int
sctp_process_param
(
s
truct
sctp_association
*
asoc
,
union
sctp_params
param
,
const
union
sctp_addr
*
peer_addr
,
int
gfp
)
{
union
sctp_addr
addr
;
...
...
net/sctp/socket.c
View file @
8d0df569
...
...
@@ -55,7 +55,6 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/time.h>
...
...
@@ -63,6 +62,7 @@
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <net/ip.h>
#include <net/icmp.h>
...
...
@@ -96,15 +96,16 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
static
int
sctp_autobind
(
struct
sock
*
sk
);
static
void
sctp_sock_migrate
(
struct
sock
*
,
struct
sock
*
,
struct
sctp_association
*
,
sctp_socket_type_t
);
static
char
*
sctp_hmac_alg
=
SCTP_COOKIE_HMAC_ALG
;
/* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored.
*/
s
ctp_association_t
*
sctp_id2assoc
(
struct
sock
*
sk
,
sctp_assoc_t
id
)
s
truct
sctp_association
*
sctp_id2assoc
(
struct
sock
*
sk
,
sctp_assoc_t
id
)
{
s
ctp_association_t
*
asoc
=
NULL
;
s
truct
sctp_association
*
asoc
=
NULL
;
/* If this is not a UDP-style socket, assoc id should be
/* If this is not a UDP-style socket, assoc id should be
* ignored.
*/
if
(
SCTP_SOCKET_UDP
!=
sctp_sk
(
sk
)
->
type
)
{
...
...
@@ -116,9 +117,9 @@ sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
/* First, verify that this is a kernel address. */
if
(
sctp_is_valid_kaddr
((
unsigned
long
)
id
))
{
s
ctp_association_t
*
temp
=
(
sctp_association_t
*
)
id
;
s
truct
sctp_association
*
temp
=
(
sctp_association_t
*
)
id
;
/* Verify that this _is_ an sctp_association
_t
/* Verify that this _is_ an sctp_association
* data structure and if so, that the socket matches.
*/
if
((
SCTP_ASSOC_EYECATCHER
==
temp
->
eyecatcher
)
&&
...
...
@@ -188,7 +189,6 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt,
return
af
;
}
/* Bind a local address either to an endpoint or to an association. */
SCTP_STATIC
int
sctp_do_bind
(
struct
sock
*
sk
,
union
sctp_addr
*
addr
,
int
len
)
{
...
...
@@ -637,7 +637,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
/* Alloc space for the address array in kernel memory. */
kaddrs
=
(
struct
sockaddr_storage
*
)
kmalloc
(
addrssize
,
GFP_KERNEL
);
if
(
unlikely
(
NULL
==
kaddrs
))
if
(
unlikely
(
!
kaddrs
))
return
-
ENOMEM
;
if
(
copy_from_user
(
kaddrs
,
addrs
,
addrssize
))
{
...
...
@@ -1134,8 +1134,9 @@ static int sctp_skb_pull(struct sk_buff *skb, int len)
*/
static
struct
sk_buff
*
sctp_skb_recv_datagram
(
struct
sock
*
,
int
,
int
,
int
*
);
SCTP_STATIC
int
sctp_recvmsg
(
struct
kiocb
*
iocb
,
struct
sock
*
sk
,
struct
msghdr
*
msg
,
int
len
,
int
noblock
,
int
flags
,
int
*
addr_len
)
SCTP_STATIC
int
sctp_recvmsg
(
struct
kiocb
*
iocb
,
struct
sock
*
sk
,
struct
msghdr
*
msg
,
int
len
,
int
noblock
,
int
flags
,
int
*
addr_len
)
{
struct
sctp_ulpevent
*
event
=
NULL
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
...
...
@@ -1156,7 +1157,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
err
=
-
ENOTCONN
;
goto
out
;
}
skb
=
sctp_skb_recv_datagram
(
sk
,
flags
,
noblock
,
&
err
);
if
(
!
skb
)
goto
out
;
...
...
@@ -1271,7 +1272,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
}
static
int
sctp_setsockopt_peer_addr_params
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
char
*
optval
,
int
optlen
)
{
struct
sctp_paddrparams
params
;
sctp_association_t
*
asoc
;
...
...
@@ -1329,8 +1330,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
return
0
;
}
static
int
sctp_setsockopt_initmsg
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
static
int
sctp_setsockopt_initmsg
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
if
(
optlen
!=
sizeof
(
struct
sctp_initmsg
))
return
-
EINVAL
;
...
...
@@ -1340,7 +1340,6 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval,
}
/*
*
* 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM)
*
* Applications that wish to use the sendto() system call may wish to
...
...
@@ -1428,12 +1427,10 @@ static int sctp_setsockopt_nodelay(struct sock *sk, char *optval,
if
(
optlen
<
sizeof
(
__u8
))
return
-
EINVAL
;
if
(
get_user
(
val
,
(
__u8
*
)
optval
))
return
-
EFAULT
;
sctp_sk
(
sk
)
->
nodelay
=
(
val
==
0
)
?
0
:
1
;
return
0
;
}
...
...
@@ -1590,7 +1587,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
/* connect() cannot be done on a socket that is already in ESTABLISHED
* state - UDP-style peeled off socket or a TCP-style socket that
* is already connected.
* is already connected.
* It cannot be done even on a TCP-style listening socket.
*/
if
((
SCTP_SS_ESTABLISHED
==
sk
->
state
)
||
...
...
@@ -1690,10 +1687,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
struct
sctp_opt
*
sp
;
struct
sctp_endpoint
*
ep
;
struct
sock
*
newsk
=
NULL
;
struct
sctp_association
*
as
s
oc
;
struct
sctp_association
*
asoc
;
long
timeo
;
int
error
=
0
;
sctp_lock_sock
(
sk
);
sp
=
sctp_sk
(
sk
);
...
...
@@ -1715,21 +1712,21 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
if
(
error
)
goto
out
;
/* We treat the list of associations on the endpoint as the accept
* queue and pick the first association on the list.
/* We treat the list of associations on the endpoint as the accept
* queue and pick the first association on the list.
*/
as
s
oc
=
list_entry
(
ep
->
asocs
.
next
,
struct
sctp_association
,
asocs
);
asoc
=
list_entry
(
ep
->
asocs
.
next
,
struct
sctp_association
,
asocs
);
newsk
=
sp
->
pf
->
create_accept_sk
(
sk
,
as
soc
);
newsk
=
sp
->
pf
->
create_accept_sk
(
sk
,
as
oc
);
if
(
!
newsk
)
{
error
=
-
ENOMEM
;
goto
out
;
}
/* Populate the fields of the newsk from the oldsk and migrate the
* as
s
oc to the newsk.
*/
sctp_sock_migrate
(
sk
,
newsk
,
as
s
oc
,
SCTP_SOCKET_TCP
);
* asoc to the newsk.
*/
sctp_sock_migrate
(
sk
,
newsk
,
asoc
,
SCTP_SOCKET_TCP
);
out:
sctp_release_sock
(
sk
);
...
...
@@ -1737,10 +1734,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
return
newsk
;
}
/*
FIXME: Write Comments
. */
/*
The SCTP ioctl handler
. */
SCTP_STATIC
int
sctp_ioctl
(
struct
sock
*
sk
,
int
cmd
,
unsigned
long
arg
)
{
return
-
E
OPNOTSUPP
;
/* STUB */
return
-
E
NOIOCTLCMD
;
}
/* This is the function which gets called during socket creation to
...
...
@@ -1835,11 +1832,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
* change the data structure relationships, this may still
* be useful for storing pre-connect address information.
*/
ep
=
sctp_endpoint_new
(
proto
,
sk
,
GFP_KERNEL
);
if
(
NULL
==
ep
)
ep
=
sctp_endpoint_new
(
sk
,
GFP_KERNEL
);
if
(
!
ep
)
return
-
ENOMEM
;
sp
->
ep
=
ep
;
sp
->
hmac
=
NULL
;
SCTP_DBG_OBJCNT_INC
(
sock
);
return
0
;
...
...
@@ -1848,7 +1846,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Cleanup any SCTP per socket resources. */
SCTP_STATIC
int
sctp_destroy_sock
(
struct
sock
*
sk
)
{
s
ctp_endpoint_
t
*
ep
;
s
truct
sctp_endpoin
t
*
ep
;
SCTP_DEBUG_PRINTK
(
"sctp_destroy_sock(sk: %p)
\n
"
,
sk
);
...
...
@@ -1877,7 +1875,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
int
*
optlen
)
{
struct
sctp_status
status
;
s
ctp_association_t
*
as
soc
=
NULL
;
s
truct
sctp_association
*
a
soc
=
NULL
;
struct
sctp_transport
*
transport
;
sctp_assoc_t
associd
;
int
retval
=
0
;
...
...
@@ -1893,22 +1891,22 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
}
associd
=
status
.
sstat_assoc_id
;
as
s
oc
=
sctp_id2assoc
(
sk
,
associd
);
if
(
!
as
s
oc
)
{
asoc
=
sctp_id2assoc
(
sk
,
associd
);
if
(
!
asoc
)
{
retval
=
-
EINVAL
;
goto
out
;
}
transport
=
as
s
oc
->
peer
.
primary_path
;
transport
=
asoc
->
peer
.
primary_path
;
status
.
sstat_assoc_id
=
sctp_assoc2id
(
as
s
oc
);
status
.
sstat_state
=
as
s
oc
->
state
;
status
.
sstat_rwnd
=
as
s
oc
->
peer
.
rwnd
;
status
.
sstat_unackdata
=
as
s
oc
->
unack_data
;
status
.
sstat_penddata
=
as
s
oc
->
peer
.
tsn_map
.
pending_data
;
status
.
sstat_instrms
=
as
s
oc
->
c
.
sinit_max_instreams
;
status
.
sstat_outstrms
=
as
s
oc
->
c
.
sinit_num_ostreams
;
status
.
sstat_fragmentation_point
=
as
s
oc
->
frag_point
;
status
.
sstat_assoc_id
=
sctp_assoc2id
(
asoc
);
status
.
sstat_state
=
asoc
->
state
;
status
.
sstat_rwnd
=
asoc
->
peer
.
rwnd
;
status
.
sstat_unackdata
=
asoc
->
unack_data
;
status
.
sstat_penddata
=
asoc
->
peer
.
tsn_map
.
pending_data
;
status
.
sstat_instrms
=
asoc
->
c
.
sinit_max_instreams
;
status
.
sstat_outstrms
=
asoc
->
c
.
sinit_num_ostreams
;
status
.
sstat_fragmentation_point
=
asoc
->
frag_point
;
status
.
sstat_primary
.
spinfo_assoc_id
=
sctp_assoc2id
(
transport
->
asoc
);
memcpy
(
&
status
.
sstat_primary
.
spinfo_address
,
&
(
transport
->
ipaddr
),
sizeof
(
union
sctp_addr
));
...
...
@@ -1975,33 +1973,29 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int
}
/* Helper routine to branch off an association to a new socket. */
SCTP_STATIC
int
sctp_do_peeloff
(
sctp_association_t
*
assoc
,
struct
socket
**
newsock
)
SCTP_STATIC
int
sctp_do_peeloff
(
struct
sctp_association
*
asoc
,
struct
socket
**
sockp
)
{
struct
sock
*
oldsk
=
assoc
->
base
.
sk
;
struct
sock
*
newsk
;
struct
socket
*
tmpsock
;
struct
sock
*
sk
=
asoc
->
base
.
sk
;
struct
socket
*
sock
;
int
err
=
0
;
/* An association cannot be branched off from an already peeled-off
* socket, nor is this supported for tcp style sockets.
*/
if
(
SCTP_SOCKET_UDP
!=
sctp_sk
(
old
sk
)
->
type
)
return
-
E
OPNOTSUPP
;
if
(
SCTP_SOCKET_UDP
!=
sctp_sk
(
sk
)
->
type
)
return
-
E
INVAL
;
/* Create a new socket. */
err
=
sock_create
(
oldsk
->
family
,
SOCK_SEQPACKET
,
IPPROTO_SCTP
,
&
tmpsock
);
err
=
sock_create
(
sk
->
family
,
SOCK_SEQPACKET
,
IPPROTO_SCTP
,
&
sock
);
if
(
err
<
0
)
return
err
;
newsk
=
tmpsock
->
sk
;
/* Populate the fields of the newsk from the oldsk and migrate the
* assoc to the newsk.
*/
sctp_sock_migrate
(
oldsk
,
newsk
,
assoc
,
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
);
*
newsock
=
tmpsock
;
*/
sctp_sock_migrate
(
sk
,
sock
->
sk
,
asoc
,
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
);
*
sockp
=
sock
;
return
err
;
}
...
...
@@ -2019,7 +2013,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
return
-
EFAULT
;
assoc
=
sctp_id2assoc
(
sk
,
peeloff
.
associd
);
if
(
NULL
==
assoc
)
{
if
(
!
assoc
)
{
retval
=
-
EINVAL
;
goto
out
;
}
...
...
@@ -2049,7 +2043,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
return
retval
;
}
static
int
sctp_getsockopt_peer_addr_params
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_peer_addr_params
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_paddrparams
params
;
...
...
@@ -2102,7 +2096,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *
return
0
;
}
static
int
sctp_getsockopt_peer_addrs_num
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_peer_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_assoc_t
id
;
...
...
@@ -2350,7 +2344,7 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
* integer boolean flag.
*/
static
int
sctp_getsockopt_nodelay
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_nodelay
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
__u8
val
;
...
...
@@ -2418,7 +2412,7 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_getsockopt_initmsg
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDRS_NUM
:
retval
=
sctp_getsockopt_peer_addrs_num
(
sk
,
len
,
optval
,
retval
=
sctp_getsockopt_peer_addrs_num
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_LOCAL_ADDRS_NUM
:
...
...
@@ -2553,7 +2547,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
}
if
(
pp
!=
NULL
&&
pp
->
sk
!=
NULL
)
{
if
(
pp
&&
pp
->
sk
)
{
/* We had a port hash table hit - there is an
* available port (pp != NULL) and it is being
* used by other socket (pp->sk != NULL); that other
...
...
@@ -2601,18 +2595,17 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
/* If there was a hash table miss, create a new port. */
ret
=
1
;
if
(
pp
==
NULL
&&
(
pp
=
sctp_bucket_create
(
head
,
snum
))
==
NULL
)
if
(
!
pp
&&
!
(
pp
=
sctp_bucket_create
(
head
,
snum
))
)
goto
fail_unlock
;
/* In either case (hit or miss), make sure fastreuse is 1 only
* if sk->reuse is too (that is, if the caller requested
* SO_REUSEADDR on this socket -sk-).
*/
if
(
pp
->
sk
==
NULL
)
{
if
(
!
pp
->
sk
)
pp
->
fastreuse
=
sk
->
reuse
?
1
:
0
;
}
else
if
(
pp
->
fastreuse
&&
sk
->
reuse
==
0
)
{
else
if
(
pp
->
fastreuse
&&
sk
->
reuse
==
0
)
pp
->
fastreuse
=
0
;
}
/* We are set, so fill up all the data in the hash table
* entry, tie the socket list information with the rest of the
...
...
@@ -2702,7 +2695,7 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
/*
* 4.1.3 listen() - TCP Style Syntax
*
* Applications uses listen() to ready the SCTP endpoint for accepting
* Applications uses listen() to ready the SCTP endpoint for accepting
* inbound associations.
*/
SCTP_STATIC
int
sctp_stream_listen
(
struct
sock
*
sk
,
int
backlog
)
...
...
@@ -2739,15 +2732,25 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
int
sctp_inet_listen
(
struct
socket
*
sock
,
int
backlog
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
err
;
struct
crypto_tfm
*
tfm
=
NULL
;
int
err
=
-
EINVAL
;
if
(
unlikely
(
backlog
<
0
))
goto
out
;
sctp_lock_sock
(
sk
);
err
=
-
EINVAL
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
goto
out
;
if
(
unlikely
(
backlog
<
0
))
goto
out
;
/* Allocate HMAC for generating cookie. */
if
(
sctp_hmac_alg
)
{
tfm
=
crypto_alloc_tfm
(
sctp_hmac_alg
,
0
);
if
(
!
tfm
)
{
err
=
-
ENOSYS
;
goto
out
;
}
}
switch
(
sock
->
type
)
{
case
SOCK_SEQPACKET
:
...
...
@@ -2756,14 +2759,21 @@ int sctp_inet_listen(struct socket *sock, int backlog)
case
SOCK_STREAM
:
err
=
sctp_stream_listen
(
sk
,
backlog
);
break
;
default:
goto
out
;
break
;
};
if
(
err
)
goto
cleanup
;
/* Store away the transform reference. */
sctp_sk
(
sk
)
->
hmac
=
tfm
;
out:
sctp_release_sock
(
sk
);
return
err
;
cleanup:
if
(
tfm
)
crypto_free_tfm
(
tfm
);
goto
out
;
}
/*
...
...
@@ -2967,7 +2977,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
/* Strictly check lengths following example in SCM code. */
switch
(
cmsg
->
cmsg_type
)
{
case
SCTP_INIT
:
/* SCTP Socket API Extension
(draft 1)
/* SCTP Socket API Extension
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
*
* This cmsghdr structure provides information for
...
...
@@ -2987,7 +2997,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
break
;
case
SCTP_SNDRCV
:
/* SCTP Socket API Extension
(draft 1)
/* SCTP Socket API Extension
* 5.2.2 SCTP Header Information Structure(SCTP_SNDRCV)
*
* This cmsghdr structure specifies SCTP options for
...
...
@@ -3002,7 +3012,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
CMSG_LEN
(
sizeof
(
struct
sctp_sndrcvinfo
)))
return
-
EINVAL
;
cmsgs
->
info
=
(
struct
sctp_sndrcvinfo
*
)
CMSG_DATA
(
cmsg
);
cmsgs
->
info
=
(
struct
sctp_sndrcvinfo
*
)
CMSG_DATA
(
cmsg
);
/* Minimally, validate the sinfo_flags. */
if
(
cmsgs
->
info
->
sinfo_flags
&
...
...
@@ -3085,13 +3096,14 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p)
* Note: This is pretty much the same routine as in core/datagram.c
* with a few changes to make lksctp work.
*/
static
struct
sk_buff
*
sctp_skb_recv_datagram
(
struct
sock
*
sk
,
int
flags
,
int
noblock
,
int
*
err
)
static
struct
sk_buff
*
sctp_skb_recv_datagram
(
struct
sock
*
sk
,
int
flags
,
int
noblock
,
int
*
err
)
{
int
error
;
struct
sk_buff
*
skb
;
long
timeo
;
/* Caller is allowed not to check sk->err before
skb_recv_datagram()
*/
/* Caller is allowed not to check sk->err before
calling.
*/
error
=
sock_error
(
sk
);
if
(
error
)
goto
no_packet
;
...
...
@@ -3140,7 +3152,7 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
}
/* Verify that this is a valid address. */
static
inline
int
sctp_verify_addr
(
struct
sock
*
sk
,
union
sctp_addr
*
addr
,
static
inline
int
sctp_verify_addr
(
struct
sock
*
sk
,
union
sctp_addr
*
addr
,
int
len
)
{
struct
sctp_af
*
af
;
...
...
@@ -3443,11 +3455,12 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo)
return
err
;
}
/* Populate the fields of the newsk from the oldsk and migrate the assoc
/* Populate the fields of the newsk from the oldsk and migrate the assoc
* and its messages to the newsk.
*/
void
sctp_sock_migrate
(
struct
sock
*
oldsk
,
struct
sock
*
newsk
,
struct
sctp_association
*
assoc
,
sctp_socket_type_t
type
)
*/
static
void
sctp_sock_migrate
(
struct
sock
*
oldsk
,
struct
sock
*
newsk
,
struct
sctp_association
*
assoc
,
sctp_socket_type_t
type
)
{
struct
sctp_opt
*
oldsp
=
sctp_sk
(
oldsk
);
struct
sctp_opt
*
newsp
=
sctp_sk
(
newsk
);
...
...
@@ -3466,6 +3479,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
* copy.
*/
newsp
->
ep
=
newep
;
newsp
->
hmac
=
NULL
;
/* Move any messages in the old socket's receive queue that are for the
* peeled off association to the new socket's receive queue.
...
...
@@ -3526,7 +3540,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsk
->
state
=
SCTP_SS_ESTABLISHED
;
}
/* This proto struct describes the ULP interface for SCTP. */
struct
proto
sctp_prot
=
{
.
name
=
"SCTP"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment