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
Kirill Smelkov
linux
Commits
e5e956d0
Commit
e5e956d0
authored
Mar 05, 2003
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.5.64
into us.ibm.com:/home/sridhar/BK/lksctp-2.5.64
parents
236b5445
56d10bed
Changes
21
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1057 additions
and
529 deletions
+1057
-529
include/net/sctp/command.h
include/net/sctp/command.h
+8
-8
include/net/sctp/constants.h
include/net/sctp/constants.h
+14
-8
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+13
-36
include/net/sctp/sm.h
include/net/sctp/sm.h
+23
-23
include/net/sctp/structs.h
include/net/sctp/structs.h
+27
-29
include/net/sctp/user.h
include/net/sctp/user.h
+2
-0
net/sctp/associola.c
net/sctp/associola.c
+48
-23
net/sctp/bind_addr.c
net/sctp/bind_addr.c
+1
-1
net/sctp/endpointola.c
net/sctp/endpointola.c
+5
-2
net/sctp/ipv6.c
net/sctp/ipv6.c
+87
-4
net/sctp/output.c
net/sctp/output.c
+60
-43
net/sctp/outqueue.c
net/sctp/outqueue.c
+80
-55
net/sctp/protocol.c
net/sctp/protocol.c
+107
-24
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+24
-30
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+30
-10
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+16
-18
net/sctp/socket.c
net/sctp/socket.c
+485
-185
net/sctp/sysctl.c
net/sctp/sysctl.c
+1
-1
net/sctp/transport.c
net/sctp/transport.c
+2
-2
net/sctp/tsnmap.c
net/sctp/tsnmap.c
+2
-2
net/sctp/ulpqueue.c
net/sctp/ulpqueue.c
+22
-25
No files found.
include/net/sctp/command.h
View file @
e5e956d0
...
...
@@ -110,13 +110,13 @@ typedef union {
sctp_event_timeout_t
to
;
sctp_counter_t
counter
;
void
*
ptr
;
s
ctp_chunk_t
*
chunk
;
s
ctp_association_t
*
asoc
;
s
truct
sctp_chunk
*
chunk
;
s
truct
sctp_association
*
asoc
;
struct
sctp_transport
*
transport
;
s
ctp_bind_addr_t
*
bp
;
s
truct
sctp_bind_addr
*
bp
;
sctp_init_chunk_t
*
init
;
struct
sctp_ulpevent
*
ulpevent
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_sackhdr_t
*
sackh
;
}
sctp_arg_t
;
...
...
@@ -158,13 +158,13 @@ SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR
(
COUNTER
,
sctp_counter_t
,
counter
)
SCTP_ARG_CONSTRUCTOR
(
TO
,
sctp_event_timeout_t
,
to
)
SCTP_ARG_CONSTRUCTOR
(
PTR
,
void
*
,
ptr
)
SCTP_ARG_CONSTRUCTOR
(
CHUNK
,
s
ctp_chunk_t
*
,
chunk
)
SCTP_ARG_CONSTRUCTOR
(
ASOC
,
s
ctp_association_t
*
,
asoc
)
SCTP_ARG_CONSTRUCTOR
(
CHUNK
,
s
truct
sctp_chunk
*
,
chunk
)
SCTP_ARG_CONSTRUCTOR
(
ASOC
,
s
truct
sctp_association
*
,
asoc
)
SCTP_ARG_CONSTRUCTOR
(
TRANSPORT
,
struct
sctp_transport
*
,
transport
)
SCTP_ARG_CONSTRUCTOR
(
BA
,
s
ctp_bind_addr_t
*
,
bp
)
SCTP_ARG_CONSTRUCTOR
(
BA
,
s
truct
sctp_bind_addr
*
,
bp
)
SCTP_ARG_CONSTRUCTOR
(
PEER_INIT
,
sctp_init_chunk_t
*
,
init
)
SCTP_ARG_CONSTRUCTOR
(
ULPEVENT
,
struct
sctp_ulpevent
*
,
ulpevent
)
SCTP_ARG_CONSTRUCTOR
(
PACKET
,
s
ctp_packet_
t
*
,
packet
)
SCTP_ARG_CONSTRUCTOR
(
PACKET
,
s
truct
sctp_packe
t
*
,
packet
)
SCTP_ARG_CONSTRUCTOR
(
SACKH
,
sctp_sackhdr_t
*
,
sackh
)
typedef
struct
{
...
...
include/net/sctp/constants.h
View file @
e5e956d0
...
...
@@ -210,14 +210,19 @@ typedef enum {
/* These are values for sk->state.
* For a UDP-style SCTP socket, the states are defined as follows
* (at this point of time, may change later after more discussions: FIXME)
* A socket in SCTP_SS_UNCONNECTED state indicates that it is not willing
* to accept new associations, but it can initiate the creation of new
* ones.
* A socket in SCTP_SS_LISTENING state indicates that it is willing to
* - A socket in SCTP_SS_CLOSED state indicates that it is not willing to
* accept new associations, but it can initiate the creation of new ones.
* - A socket in SCTP_SS_LISTENING state indicates that it is willing to
* accept new associations and can initiate the creation of new ones.
* A socket in SCTP_SS_ESTABLISHED state indicates that it is a peeled off
*
-
A socket in SCTP_SS_ESTABLISHED state indicates that it is a peeled off
* socket with one association.
* For a TCP-style SCTP socket, the states are defined as follows
* - A socket in SCTP_SS_CLOSED state indicates that it is not willing to
* accept new associations, but it can initiate the creation of new ones.
* - A socket in SCTP_SS_LISTENING state indicates that it is willing to
* accept new associations, but cannot initiate the creation of new ones.
* - A socket in SCTP_SS_ESTABLISHED state indicates that it has a single
* association in ESTABLISHED state.
*/
typedef
enum
{
SCTP_SS_CLOSED
=
TCP_CLOSE
,
...
...
@@ -345,6 +350,7 @@ typedef enum {
SCTP_XMIT_PMTU_FULL
,
SCTP_XMIT_RWND_FULL
,
SCTP_XMIT_MUST_FRAG
,
SCTP_XMIT_NAGLE_DELAY
,
}
sctp_xmit_t
;
/* These are the commands for manipulating transports. */
...
...
include/net/sctp/sctp.h
View file @
e5e956d0
...
...
@@ -121,9 +121,10 @@
/*
* sctp_protocol.c
*/
extern
s
ctp_protocol_t
sctp_proto
;
extern
s
truct
sctp_protocol
sctp_proto
;
extern
struct
sock
*
sctp_get_ctl_sock
(
void
);
extern
int
sctp_copy_local_addr_list
(
sctp_protocol_t
*
,
sctp_bind_addr_t
*
,
extern
int
sctp_copy_local_addr_list
(
struct
sctp_protocol
*
,
struct
sctp_bind_addr
*
,
sctp_scope_t
,
int
priority
,
int
flags
);
extern
struct
sctp_pf
*
sctp_get_pf_specific
(
sa_family_t
family
);
extern
int
sctp_register_pf
(
struct
sctp_pf
*
,
sa_family_t
);
...
...
@@ -312,30 +313,21 @@ static inline void sctp_sysctl_unregister(void) { return; }
#endif
/* Size of Supported Address Parameter for 'x' address types. */
#define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16))
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
extern
int
sctp_v6_init
(
void
);
extern
void
sctp_v6_exit
(
void
);
static
inline
int
sctp_ipv6_addr_type
(
const
struct
in6_addr
*
addr
)
{
return
ipv6_addr_type
((
struct
in6_addr
*
)
addr
);
}
#define SCTP_SAT_LEN (sizeof(sctp_paramhdr_t) + 2 * sizeof(__u16))
/* Note: These V6 macros are obsolescent. */
/* Use this macro to enclose code fragments which are V6-dependent. */
#define SCTP_V6(m...) m
#define SCTP_V6_SUPPORT 1
#else
/* #ifdef defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
#define sctp_ipv6_addr_type(a) 0
#define SCTP_SAT_LEN (sizeof(sctp_paramhdr_t) + 1 * sizeof(__u16))
#define SCTP_V6(m...)
/* Do nothing. */
#undef SCTP_V6_SUPPORT
static
inline
int
sctp_v6_init
(
void
)
{
return
0
;
}
static
inline
void
sctp_v6_exit
(
void
)
{
return
;
}
...
...
@@ -348,25 +340,10 @@ static inline sctp_assoc_t sctp_assoc2id(const sctp_association_t *asoc)
return
(
sctp_assoc_t
)
asoc
;
}
/* Look up the association by its id. */
static
inline
sctp_association_t
*
sctp_id2assoc
(
const
struct
sock
*
sk
,
sctp_assoc_t
id
)
{
sctp_association_t
*
asoc
=
NULL
;
/* First, verify that this is a kernel address. */
if
(
sctp_is_valid_kaddr
((
unsigned
long
)
id
))
{
sctp_association_t
*
temp
=
(
sctp_association_t
*
)
id
;
/* Verify that this _is_ an sctp_association_t
* data structure and if so, that the socket matches.
*/
if
((
SCTP_ASSOC_EYECATCHER
==
temp
->
eyecatcher
)
&&
(
temp
->
base
.
sk
==
sk
))
asoc
=
temp
;
}
/* Look up the association by its id. */
sctp_association_t
*
sctp_id2assoc
(
struct
sock
*
sk
,
sctp_assoc_t
id
);
return
asoc
;
}
/* A macro to walk a list of skbs. */
#define sctp_skb_for_each(pos, head, tmp) \
...
...
@@ -494,7 +471,7 @@ extern void sctp_put_port(struct sock *sk);
/* Static inline functions. */
/* Return the SCTP protocol structure. */
static
inline
s
ctp_protocol_t
*
sctp_get_protocol
(
void
)
static
inline
s
truct
sctp_protocol
*
sctp_get_protocol
(
void
)
{
return
&
sctp_proto
;
}
...
...
@@ -523,21 +500,21 @@ static inline int ipver2af(__u8 ipver)
/* This is the hash function for the SCTP port hash table. */
static
inline
int
sctp_phashfn
(
__u16
lport
)
{
s
ctp_protocol_t
*
sctp_proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
sctp_proto
=
sctp_get_protocol
();
return
(
lport
&
(
sctp_proto
->
port_hashsize
-
1
));
}
/* This is the hash function for the endpoint hash table. */
static
inline
int
sctp_ep_hashfn
(
__u16
lport
)
{
s
ctp_protocol_t
*
sctp_proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
sctp_proto
=
sctp_get_protocol
();
return
(
lport
&
(
sctp_proto
->
ep_hashsize
-
1
));
}
/* This is the hash function for the association hash table. */
static
inline
int
sctp_assoc_hashfn
(
__u16
lport
,
__u16
rport
)
{
s
ctp_protocol_t
*
sctp_proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
sctp_proto
=
sctp_get_protocol
();
int
h
=
(
lport
<<
16
)
+
rport
;
h
^=
h
>>
8
;
return
(
h
&
(
sctp_proto
->
assoc_hashsize
-
1
));
...
...
@@ -549,7 +526,7 @@ static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
*/
static
inline
int
sctp_vtag_hashfn
(
__u16
lport
,
__u16
rport
,
__u32
vtag
)
{
s
ctp_protocol_t
*
sctp_proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
sctp_proto
=
sctp_get_protocol
();
int
h
=
(
lport
<<
16
)
+
rport
;
h
^=
vtag
;
return
(
h
&
(
sctp_proto
->
assoc_hashsize
-
1
));
...
...
include/net/sctp/sm.h
View file @
e5e956d0
...
...
@@ -313,18 +313,18 @@ void sctp_generate_t3_rtx_event(unsigned long peer);
void
sctp_generate_heartbeat_event
(
unsigned
long
peer
);
sctp_sackhdr_t
*
sctp_sm_pull_sack
(
sctp_chunk_t
*
);
s
ctp_packet_t
*
sctp_abort_pkt_new
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
s
truct
sctp_packet
*
sctp_abort_pkt_new
(
const
struct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
struct
sctp_chunk
*
chunk
,
const
void
*
payload
,
size_t
paylen
);
s
ctp_packet_t
*
sctp_ootb_pkt_new
(
const
sctp_association_t
*
asoc
,
const
sctp_chunk_t
*
chunk
);
void
sctp_ootb_pkt_free
(
s
ctp_packet_t
*
packet
);
s
truct
sctp_packet
*
sctp_ootb_pkt_new
(
const
struct
sctp_association
*
,
const
struct
sctp_chunk
*
);
void
sctp_ootb_pkt_free
(
s
truct
sctp_packet
*
);
sctp_cookie_param_t
*
sctp_pack_cookie
(
const
s
ctp_endpoint_t
*
,
const
sctp_association_t
*
,
const
s
ctp_chunk_t
*
,
int
*
cookie_len
,
sctp_pack_cookie
(
const
s
truct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
const
s
truct
sctp_chunk
*
,
int
*
cookie_len
,
const
__u8
*
,
int
addrs_len
);
sctp_association_t
*
sctp_unpack_cookie
(
const
sctp_endpoint_t
*
,
const
sctp_association_t
*
,
...
...
include/net/sctp/structs.h
View file @
e5e956d0
...
...
@@ -86,10 +86,8 @@ struct sctp_opt;
struct
sctp_endpoint_common
;
struct
sctp_ssnmap
;
typedef
struct
sctp_protocol
sctp_protocol_t
;
typedef
struct
sctp_endpoint
sctp_endpoint_t
;
typedef
struct
sctp_association
sctp_association_t
;
typedef
struct
sctp_packet
sctp_packet_t
;
typedef
struct
sctp_chunk
sctp_chunk_t
;
typedef
struct
sctp_bind_addr
sctp_bind_addr_t
;
typedef
struct
sctp_endpoint_common
sctp_endpoint_common_t
;
...
...
@@ -262,6 +260,9 @@ struct sctp_pf {
const
union
sctp_addr
*
,
struct
sctp_opt
*
);
int
(
*
bind_verify
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
int
(
*
supported_addrs
)(
const
struct
sctp_opt
*
,
__u16
*
);
struct
sock
*
(
*
create_accept_sk
)
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
);
struct
sctp_af
*
af
;
};
...
...
@@ -366,8 +367,6 @@ typedef struct sctp_signed_cookie {
sctp_cookie_t
c
;
}
sctp_signed_cookie_t
;
/* This is another convenience type to allocate memory for address
* params for the maximum size and pass such structures around
* internally.
...
...
@@ -604,26 +603,26 @@ struct sctp_packet {
typedef
int
(
sctp_outq_thandler_t
)(
struct
sctp_outq
*
,
void
*
);
typedef
int
(
sctp_outq_ehandler_t
)(
struct
sctp_outq
*
);
typedef
s
ctp_packet_
t
*
(
sctp_outq_ohandler_init_t
)
(
s
ctp_packet_
t
*
,
typedef
s
truct
sctp_packe
t
*
(
sctp_outq_ohandler_init_t
)
(
s
truct
sctp_packe
t
*
,
struct
sctp_transport
*
,
__u16
sport
,
__u16
dport
);
typedef
s
ctp_packet_
t
*
(
sctp_outq_ohandler_config_t
)
(
s
ctp_packet_
t
*
,
typedef
s
truct
sctp_packe
t
*
(
sctp_outq_ohandler_config_t
)
(
s
truct
sctp_packe
t
*
,
__u32
vtag
,
int
ecn_capable
,
sctp_packet_phandler_t
*
get_prepend_chunk
);
typedef
sctp_xmit_t
(
sctp_outq_ohandler_t
)(
s
ctp_packet_
t
*
,
typedef
sctp_xmit_t
(
sctp_outq_ohandler_t
)(
s
truct
sctp_packe
t
*
,
sctp_chunk_t
*
);
typedef
int
(
sctp_outq_ohandler_force_t
)(
s
ctp_packet_
t
*
);
typedef
int
(
sctp_outq_ohandler_force_t
)(
s
truct
sctp_packe
t
*
);
sctp_outq_ohandler_init_t
sctp_packet_init
;
sctp_outq_ohandler_config_t
sctp_packet_config
;
sctp_outq_ohandler_t
sctp_packet_append_chunk
;
sctp_outq_ohandler_t
sctp_packet_transmit_chunk
;
sctp_outq_ohandler_force_t
sctp_packet_transmit
;
void
sctp_packet_free
(
s
ctp_packet_
t
*
);
void
sctp_packet_free
(
s
truct
sctp_packe
t
*
);
/* This represents a remote transport address.
...
...
@@ -789,7 +788,7 @@ struct sctp_transport {
struct
list_head
transmitted
;
/* We build bundle-able packets for this transport here. */
s
ctp_packet_
t
packet
;
s
truct
sctp_packe
t
packet
;
/* This is the list of transports that have chunks to send. */
struct
list_head
send_ready
;
...
...
@@ -865,12 +864,11 @@ void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
struct
sctp_outq
{
sctp_association_t
*
asoc
;
/* BUG: This really should be an array of streams.
* This really holds a list of chunks (one stream).
* FIXME: If true, why so?
*/
/* Data pending that has never been transmitted. */
struct
sk_buff_head
out
;
unsigned
out_qlen
;
/* Total length of queued data chunks. */
/* These are control chunks we want to send. */
struct
sk_buff_head
control
;
...
...
@@ -885,7 +883,7 @@ struct sctp_outq {
struct
list_head
retransmit
;
/* Call these functions to send chunks down to the next lower
* layer. This is always
SCTP
_packet, but we separate the two
* layer. This is always
sctp
_packet, but we separate the two
* structures to make testing simpler.
*/
sctp_outq_ohandler_init_t
*
init_output
;
...
...
@@ -1098,8 +1096,9 @@ static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
}
/* These are function signatures for manipulating endpoints. */
sctp_endpoint_t
*
sctp_endpoint_new
(
sctp_protocol_t
*
,
struct
sock
*
,
int
);
sctp_endpoint_t
*
sctp_endpoint_init
(
sctp_endpoint_t
*
,
sctp_protocol_t
*
,
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
priority
);
void
sctp_endpoint_free
(
sctp_endpoint_t
*
);
void
sctp_endpoint_put
(
sctp_endpoint_t
*
);
...
...
@@ -1111,7 +1110,6 @@ sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
int
sctp_endpoint_is_peeled_off
(
sctp_endpoint_t
*
,
const
union
sctp_addr
*
);
sctp_endpoint_t
*
sctp_endpoint_is_match
(
sctp_endpoint_t
*
,
const
union
sctp_addr
*
);
int
sctp_has_association
(
const
union
sctp_addr
*
laddr
,
const
union
sctp_addr
*
paddr
);
...
...
@@ -1587,7 +1585,7 @@ struct sctp_transport *sctp_assoc_lookup_paddr(const sctp_association_t *,
struct
sctp_transport
*
sctp_assoc_add_peer
(
sctp_association_t
*
,
const
union
sctp_addr
*
address
,
const
int
priority
);
void
sctp_assoc_control_transport
(
s
ctp_association_t
*
,
void
sctp_assoc_control_transport
(
s
truct
sctp_association
*
,
struct
sctp_transport
*
,
sctp_transport_cmd_t
,
sctp_sn_error_t
);
struct
sctp_transport
*
sctp_assoc_lookup_tsn
(
sctp_association_t
*
,
__u32
);
...
...
@@ -1597,14 +1595,14 @@ struct sctp_transport *sctp_assoc_is_match(sctp_association_t *,
void
sctp_assoc_migrate
(
sctp_association_t
*
,
struct
sock
*
);
void
sctp_assoc_update
(
sctp_association_t
*
dst
,
sctp_association_t
*
src
);
__u32
__sctp_association_get_next_tsn
(
sctp_association_t
*
);
__u32
__sctp_association_get_tsn_block
(
sctp_association_t
*
,
int
);
__u16
__sctp_association_get_next_ssn
(
sctp_association_t
*
,
__u16
sid
);
void
sctp_assoc_sync_pmtu
(
sctp_association_t
*
);
void
sctp_assoc_rwnd_increase
(
sctp_association_t
*
,
int
);
void
sctp_assoc_rwnd_decrease
(
sctp_association_t
*
,
int
);
__u32
sctp_association_get_next_tsn
(
struct
sctp_association
*
);
__u32
sctp_association_get_tsn_block
(
struct
sctp_association
*
,
int
);
void
sctp_assoc_sync_pmtu
(
struct
sctp_association
*
);
void
sctp_assoc_rwnd_increase
(
struct
sctp_association
*
,
int
);
void
sctp_assoc_rwnd_decrease
(
struct
sctp_association
*
,
int
);
void
sctp_assoc_set_primary
(
struct
sctp_association
*
,
struct
sctp_transport
*
);
int
sctp_assoc_set_bind_addr_from_ep
(
sctp_association_t
*
,
int
);
int
sctp_assoc_set_bind_addr_from_cookie
(
sctp_association_t
*
,
sctp_cookie_t
*
,
int
);
...
...
include/net/sctp/user.h
View file @
e5e956d0
...
...
@@ -108,6 +108,8 @@ enum sctp_optname {
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS
,
/* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
SCTP_NODELAY
,
/* Get/set nodelay option. */
#define SCTP_NODELAY SCTP_NODELAY
};
...
...
net/sctp/associola.c
View file @
e5e956d0
...
...
@@ -181,7 +181,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
else
asoc
->
rwnd
=
sk
->
rcvbuf
;
asoc
->
a_rwnd
=
0
;
asoc
->
a_rwnd
=
asoc
->
rwnd
;
asoc
->
rwnd_over
=
0
;
...
...
@@ -360,9 +360,25 @@ static void sctp_association_destroy(sctp_association_t *asoc)
}
}
/* Change the primary destination address for the peer. */
void
sctp_assoc_set_primary
(
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
transport
)
{
asoc
->
peer
.
primary_path
=
transport
;
/* Set a default msg_name for events. */
memcpy
(
&
asoc
->
peer
.
primary_addr
,
&
transport
->
ipaddr
,
sizeof
(
union
sctp_addr
));
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
if
(
transport
->
active
)
asoc
->
peer
.
active_path
=
transport
;
}
/* Add a transport address to an association. */
struct
sctp_transport
*
sctp_assoc_add_peer
(
s
ctp_association_t
*
asoc
,
struct
sctp_transport
*
sctp_assoc_add_peer
(
s
truct
sctp_association
*
asoc
,
const
union
sctp_addr
*
addr
,
int
priority
)
{
...
...
@@ -397,17 +413,16 @@ struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *asoc,
* If not and the current association PMTU is higher than the new
* peer's PMTU, reset the association PMTU to the new peer's PMTU.
*/
if
(
asoc
->
pmtu
)
{
if
(
asoc
->
pmtu
)
asoc
->
pmtu
=
min_t
(
int
,
peer
->
pmtu
,
asoc
->
pmtu
);
}
else
{
else
asoc
->
pmtu
=
peer
->
pmtu
;
}
SCTP_DEBUG_PRINTK
(
"sctp_assoc_add_peer:association %p PMTU set to "
"%d
\n
"
,
asoc
,
asoc
->
pmtu
);
asoc
->
frag_point
=
asoc
->
pmtu
-
(
SCTP_IP_OVERHEAD
+
sizeof
(
sctp_data_chunk_t
)
);
asoc
->
frag_point
=
asoc
->
pmtu
;
asoc
->
frag_point
-=
SCTP_IP_OVERHEAD
+
sizeof
(
struct
sctp_data_chunk
);
/* The asoc->peer.port might not be meaningful yet, but
* initialize the packet structure anyway.
...
...
@@ -460,11 +475,7 @@ struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *asoc,
/* If we do not yet have a primary path, set one. */
if
(
NULL
==
asoc
->
peer
.
primary_path
)
{
asoc
->
peer
.
primary_path
=
peer
;
/* Set a default msg_name for events. */
memcpy
(
&
asoc
->
peer
.
primary_addr
,
&
peer
->
ipaddr
,
sizeof
(
union
sctp_addr
));
asoc
->
peer
.
active_path
=
peer
;
sctp_assoc_set_primary
(
asoc
,
peer
);
asoc
->
peer
.
retran_path
=
peer
;
}
...
...
@@ -603,7 +614,7 @@ void sctp_association_put(sctp_association_t *asoc)
/* Allocate the next TSN, Transmission Sequence Number, for the given
* association.
*/
__u32
__
sctp_association_get_next_tsn
(
sctp_association_t
*
asoc
)
__u32
sctp_association_get_next_tsn
(
sctp_association_t
*
asoc
)
{
/* From Section 1.6 Serial Number Arithmetic:
* Transmission Sequence Numbers wrap around when they reach
...
...
@@ -618,7 +629,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc)
}
/* Allocate 'num' TSNs by incrementing the association's TSN by num. */
__u32
__
sctp_association_get_tsn_block
(
sctp_association_t
*
asoc
,
int
num
)
__u32
sctp_association_get_tsn_block
(
sctp_association_t
*
asoc
,
int
num
)
{
__u32
retval
=
asoc
->
next_tsn
;
...
...
@@ -983,6 +994,24 @@ void sctp_assoc_sync_pmtu(sctp_association_t *asoc)
__FUNCTION__
,
asoc
,
asoc
->
pmtu
,
asoc
->
frag_point
);
}
/* Should we send a SACK to update our peer? */
static
inline
int
sctp_peer_needs_update
(
struct
sctp_association
*
asoc
)
{
switch
(
asoc
->
state
)
{
case
SCTP_STATE_ESTABLISHED
:
case
SCTP_STATE_SHUTDOWN_PENDING
:
case
SCTP_STATE_SHUTDOWN_RECEIVED
:
if
((
asoc
->
rwnd
>
asoc
->
a_rwnd
)
&&
((
asoc
->
rwnd
-
asoc
->
a_rwnd
)
>=
min_t
(
__u32
,
(
asoc
->
base
.
sk
->
rcvbuf
>>
1
),
asoc
->
pmtu
)))
return
1
;
break
;
default:
break
;
}
return
0
;
}
/* Increase asoc's rwnd by len and send any window update SACK if needed. */
void
sctp_assoc_rwnd_increase
(
sctp_association_t
*
asoc
,
int
len
)
{
...
...
@@ -1009,10 +1038,8 @@ void sctp_assoc_rwnd_increase(sctp_association_t *asoc, int len)
* The algorithm used is similar to the one described in
* Section 4.2.3.3 of RFC 1122.
*/
if
((
asoc
->
state
==
SCTP_STATE_ESTABLISHED
)
&&
(
asoc
->
rwnd
>
asoc
->
a_rwnd
)
&&
((
asoc
->
rwnd
-
asoc
->
a_rwnd
)
>=
min_t
(
__u32
,
(
asoc
->
base
.
sk
->
rcvbuf
>>
1
),
asoc
->
pmtu
)))
{
if
(
sctp_peer_needs_update
(
asoc
))
{
asoc
->
a_rwnd
=
asoc
->
rwnd
;
SCTP_DEBUG_PRINTK
(
"%s: Sending window update SACK- asoc: %p "
"rwnd: %u a_rwnd: %u
\n
"
,
__FUNCTION__
,
asoc
,
asoc
->
rwnd
,
asoc
->
a_rwnd
);
...
...
@@ -1020,9 +1047,6 @@ void sctp_assoc_rwnd_increase(sctp_association_t *asoc, int len)
if
(
!
sack
)
return
;
/* Update the last advertised rwnd value. */
asoc
->
a_rwnd
=
asoc
->
rwnd
;
asoc
->
peer
.
sack_needed
=
0
;
sctp_outq_tail
(
&
asoc
->
outqueue
,
sack
);
...
...
@@ -1046,7 +1070,8 @@ void sctp_assoc_rwnd_decrease(sctp_association_t *asoc, int len)
asoc
->
rwnd
=
0
;
}
SCTP_DEBUG_PRINTK
(
"%s: asoc %p rwnd decreased by %d to (%u, %u)
\n
"
,
__FUNCTION__
,
asoc
,
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
);
__FUNCTION__
,
asoc
,
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
);
}
/* Build the bind address list for the association based on info from the
...
...
net/sctp/bind_addr.c
View file @
e5e956d0
...
...
@@ -302,7 +302,7 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
static
int
sctp_copy_one_addr
(
sctp_bind_addr_t
*
dest
,
union
sctp_addr
*
addr
,
sctp_scope_t
scope
,
int
priority
,
int
flags
)
{
s
ctp_protocol_t
*
proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
proto
=
sctp_get_protocol
();
int
error
=
0
;
if
(
sctp_is_any
(
addr
))
{
...
...
net/sctp/endpointola.c
View file @
e5e956d0
...
...
@@ -65,7 +65,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep);
/* Create a sctp_endpoint_t with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
sctp_endpoint_t
*
sctp_endpoint_new
(
s
ctp_protocol_t
*
proto
,
sctp_endpoint_t
*
sctp_endpoint_new
(
s
truct
sctp_protocol
*
proto
,
struct
sock
*
sk
,
int
priority
)
{
sctp_endpoint_t
*
ep
;
...
...
@@ -89,7 +89,8 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto,
/*
* Initialize the base fields of the endpoint structure.
*/
sctp_endpoint_t
*
sctp_endpoint_init
(
sctp_endpoint_t
*
ep
,
sctp_protocol_t
*
proto
,
sctp_endpoint_t
*
sctp_endpoint_init
(
sctp_endpoint_t
*
ep
,
struct
sctp_protocol
*
proto
,
struct
sock
*
sk
,
int
priority
)
{
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
...
...
@@ -194,6 +195,8 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
{
SCTP_ASSERT
(
ep
->
base
.
dead
,
"Endpoint is not dead"
,
return
);
ep
->
base
.
sk
->
state
=
SCTP_SS_CLOSED
;
/* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint
(
ep
);
...
...
net/sctp/ipv6.c
View file @
e5e956d0
...
...
@@ -432,6 +432,62 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
return
retval
;
}
/* Create and initialize a new sk for the socket to be returned by accept(). */
struct
sock
*
sctp_v6_create_accept_sk
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
)
{
struct
inet_opt
*
inet
=
inet_sk
(
sk
);
struct
sock
*
newsk
;
struct
inet_opt
*
newinet
;
struct
ipv6_pinfo
*
newnp
,
*
np
=
inet6_sk
(
sk
);
struct
sctp6_sock
*
newsctp6sk
;
newsk
=
sk_alloc
(
PF_INET6
,
GFP_KERNEL
,
sizeof
(
struct
sctp6_sock
),
sk
->
slab
);
if
(
!
newsk
)
goto
out
;
sock_init_data
(
NULL
,
newsk
);
newsk
->
type
=
SOCK_STREAM
;
newsk
->
prot
=
sk
->
prot
;
newsk
->
no_check
=
sk
->
no_check
;
newsk
->
reuse
=
sk
->
reuse
;
newsk
->
destruct
=
inet_sock_destruct
;
newsk
->
zapped
=
0
;
newsk
->
family
=
PF_INET6
;
newsk
->
protocol
=
IPPROTO_SCTP
;
newsk
->
backlog_rcv
=
sk
->
prot
->
backlog_rcv
;
newsctp6sk
=
(
struct
sctp6_sock
*
)
newsk
;
newsctp6sk
->
pinet6
=
&
newsctp6sk
->
inet6
;
newinet
=
inet_sk
(
newsk
);
newnp
=
inet6_sk
(
newsk
);
memcpy
(
newnp
,
np
,
sizeof
(
struct
ipv6_pinfo
));
ipv6_addr_copy
(
&
newnp
->
daddr
,
&
asoc
->
peer
.
primary_addr
.
v6
.
sin6_addr
);
newinet
->
sport
=
inet
->
sport
;
newinet
->
dport
=
asoc
->
peer
.
port
;
#ifdef INET_REFCNT_DEBUG
atomic_inc
(
&
inet6_sock_nr
);
atomic_inc
(
&
inet_sock_nr
);
#endif
if
(
0
!=
newsk
->
prot
->
init
(
newsk
))
{
inet_sock_release
(
newsk
);
newsk
=
NULL
;
}
out:
return
newsk
;
}
/* Initialize a PF_INET6 socket msg_name. */
static
void
sctp_inet6_msgname
(
char
*
msgname
,
int
*
addr_len
)
{
...
...
@@ -564,6 +620,20 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
return
af
->
available
(
addr
);
}
/* Fill in Supported Address Type information for INIT and INIT-ACK
* chunks. Note: In the future, we may want to look at sock options
* to determine whether a PF_INET6 socket really wants to have IPV4
* addresses.
* Returns number of addresses supported.
*/
static
int
sctp_inet6_supported_addrs
(
const
struct
sctp_opt
*
opt
,
__u16
*
types
)
{
types
[
0
]
=
SCTP_PARAM_IPV4_ADDRESS
;
types
[
1
]
=
SCTP_PARAM_IPV6_ADDRESS
;
return
2
;
}
static
struct
proto_ops
inet6_seqpacket_ops
=
{
.
family
=
PF_INET6
,
.
release
=
inet6_release
,
...
...
@@ -583,7 +653,7 @@ static struct proto_ops inet6_seqpacket_ops = {
.
mmap
=
sock_no_mmap
,
};
static
struct
inet_protosw
sctpv6_protosw
=
{
static
struct
inet_protosw
sctpv6_
seqpacket_
protosw
=
{
.
type
=
SOCK_SEQPACKET
,
.
protocol
=
IPPROTO_SCTP
,
.
prot
=
&
sctp_prot
,
...
...
@@ -592,6 +662,15 @@ static struct inet_protosw sctpv6_protosw = {
.
no_check
=
0
,
.
flags
=
SCTP_PROTOSW_FLAG
};
static
struct
inet_protosw
sctpv6_stream_protosw
=
{
.
type
=
SOCK_STREAM
,
.
protocol
=
IPPROTO_SCTP
,
.
prot
=
&
sctp_prot
,
.
ops
=
&
inet6_seqpacket_ops
,
.
capability
=
-
1
,
.
no_check
=
0
,
.
flags
=
SCTP_PROTOSW_FLAG
};
static
struct
inet6_protocol
sctpv6_protocol
=
{
.
handler
=
sctp_rcv
,
...
...
@@ -626,6 +705,8 @@ static struct sctp_pf sctp_pf_inet6_specific = {
.
af_supported
=
sctp_inet6_af_supported
,
.
cmp_addr
=
sctp_inet6_cmp_addr
,
.
bind_verify
=
sctp_inet6_bind_verify
,
.
supported_addrs
=
sctp_inet6_supported_addrs
,
.
create_accept_sk
=
sctp_v6_create_accept_sk
,
.
af
=
&
sctp_ipv6_specific
,
};
...
...
@@ -636,8 +717,9 @@ int sctp_v6_init(void)
if
(
inet6_add_protocol
(
&
sctpv6_protocol
,
IPPROTO_SCTP
)
<
0
)
return
-
EAGAIN
;
/* Add SCTPv6 to inetsw6 linked list. */
inet6_register_protosw
(
&
sctpv6_protosw
);
/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
inet6_register_protosw
(
&
sctpv6_seqpacket_protosw
);
inet6_register_protosw
(
&
sctpv6_stream_protosw
);
/* Register the SCTP specfic PF_INET6 functions. */
sctp_register_pf
(
&
sctp_pf_inet6_specific
,
PF_INET6
);
...
...
@@ -656,6 +738,7 @@ void sctp_v6_exit(void)
{
list_del
(
&
sctp_ipv6_specific
.
list
);
inet6_del_protocol
(
&
sctpv6_protocol
,
IPPROTO_SCTP
);
inet6_unregister_protosw
(
&
sctpv6_protosw
);
inet6_unregister_protosw
(
&
sctpv6_seqpacket_protosw
);
inet6_unregister_protosw
(
&
sctpv6_stream_protosw
);
unregister_inet6addr_notifier
(
&
sctp_inetaddr_notifier
);
}
net/sctp/output.c
View file @
e5e956d0
...
...
@@ -62,16 +62,15 @@
#include <net/sctp/sm.h>
/* Forward declarations for private helpers. */
static
void
sctp_packet_reset
(
s
ctp_packet_
t
*
packet
);
static
sctp_xmit_t
sctp_packet_append_data
(
s
ctp_packet_
t
*
packet
,
s
ctp_chunk_t
*
chunk
);
static
void
sctp_packet_reset
(
s
truct
sctp_packe
t
*
packet
);
static
sctp_xmit_t
sctp_packet_append_data
(
s
truct
sctp_packe
t
*
packet
,
s
truct
sctp_chunk
*
chunk
);
/* Config a packet.
* This appears to be a followup set of initializations.)
*/
sctp_packet_t
*
sctp_packet_config
(
sctp_packet_t
*
packet
,
__u32
vtag
,
int
ecn_capable
,
struct
sctp_packet
*
sctp_packet_config
(
struct
sctp_packet
*
packet
,
__u32
vtag
,
int
ecn_capable
,
sctp_packet_phandler_t
*
prepend_handler
)
{
int
packet_empty
=
(
packet
->
size
==
SCTP_IP_OVERHEAD
);
...
...
@@ -89,10 +88,9 @@ sctp_packet_t *sctp_packet_config(sctp_packet_t *packet,
}
/* Initialize the packet structure. */
s
ctp_packet_t
*
sctp_packet_init
(
sctp_packet_
t
*
packet
,
s
truct
sctp_packet
*
sctp_packet_init
(
struct
sctp_packe
t
*
packet
,
struct
sctp_transport
*
transport
,
__u16
sport
,
__u16
dport
)
__u16
sport
,
__u16
dport
)
{
packet
->
transport
=
transport
;
packet
->
source_port
=
sport
;
...
...
@@ -109,14 +107,12 @@ sctp_packet_t *sctp_packet_init(sctp_packet_t *packet,
}
/* Free a packet. */
void
sctp_packet_free
(
s
ctp_packet_
t
*
packet
)
void
sctp_packet_free
(
s
truct
sctp_packe
t
*
packet
)
{
s
ctp_chunk_t
*
chunk
;
s
truct
sctp_chunk
*
chunk
;
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
packet
->
chunks
)))
{
while
((
chunk
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
packet
->
chunks
)))
sctp_free_chunk
(
chunk
);
}
if
(
packet
->
malloced
)
kfree
(
packet
);
...
...
@@ -129,8 +125,8 @@ void sctp_packet_free(sctp_packet_t *packet)
* as it can fit in the packet, but any more data that does not fit in this
* packet can be sent only after receiving the COOKIE_ACK.
*/
sctp_xmit_t
sctp_packet_transmit_chunk
(
s
ctp_packet_
t
*
packet
,
s
ctp_chunk_t
*
chunk
)
sctp_xmit_t
sctp_packet_transmit_chunk
(
s
truct
sctp_packe
t
*
packet
,
s
truct
sctp_chunk
*
chunk
)
{
sctp_xmit_t
retval
;
int
error
=
0
;
...
...
@@ -152,6 +148,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet,
case
SCTP_XMIT_MUST_FRAG
:
case
SCTP_XMIT_RWND_FULL
:
case
SCTP_XMIT_OK
:
case
SCTP_XMIT_NAGLE_DELAY
:
break
;
};
...
...
@@ -161,7 +158,8 @@ sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet,
/* Append a chunk to the offered packet reporting back any inability to do
* so.
*/
sctp_xmit_t
sctp_packet_append_chunk
(
sctp_packet_t
*
packet
,
sctp_chunk_t
*
chunk
)
sctp_xmit_t
sctp_packet_append_chunk
(
struct
sctp_packet
*
packet
,
struct
sctp_chunk
*
chunk
)
{
sctp_xmit_t
retval
=
SCTP_XMIT_OK
;
__u16
chunk_len
=
WORD_ROUND
(
ntohs
(
chunk
->
chunk_hdr
->
length
));
...
...
@@ -223,7 +221,7 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
}
/* It is OK to send this chunk. */
skb_queue_tail
(
&
packet
->
chunks
,
(
struct
sk_buff
*
)
chunk
);
__
skb_queue_tail
(
&
packet
->
chunks
,
(
struct
sk_buff
*
)
chunk
);
packet
->
size
+=
chunk_len
;
finish:
return
retval
;
...
...
@@ -234,18 +232,18 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
*
* The return value is a normal kernel error return value.
*/
int
sctp_packet_transmit
(
s
ctp_packet_
t
*
packet
)
int
sctp_packet_transmit
(
s
truct
sctp_packe
t
*
packet
)
{
struct
sctp_transport
*
transport
=
packet
->
transport
;
s
ctp_association_t
*
asoc
=
transport
->
asoc
;
s
truct
sctp_association
*
asoc
=
transport
->
asoc
;
struct
sctphdr
*
sh
;
__u32
crc32
;
struct
sk_buff
*
nskb
;
s
ctp_chunk_t
*
chunk
;
s
truct
sctp_chunk
*
chunk
;
struct
sock
*
sk
;
int
err
=
0
;
int
padding
;
/* How much padding do we need? */
__u8
packet_
has_data
=
0
;
__u8
has_data
=
0
;
struct
dst_entry
*
dst
;
/* Do NOT generate a chunkless packet... */
...
...
@@ -253,7 +251,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
return
err
;
/* Set up convenience variables... */
chunk
=
(
s
ctp_chunk_t
*
)
(
packet
->
chunks
.
next
);
chunk
=
(
s
truct
sctp_chunk
*
)
(
packet
->
chunks
.
next
);
sk
=
chunk
->
skb
->
sk
;
/* Allocate the new skb. */
...
...
@@ -291,8 +289,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* [This whole comment explains WORD_ROUND() below.]
*/
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet***
\n
"
);
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
packet
->
chunks
)))
{
while
((
chunk
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
packet
->
chunks
)))
{
chunk
->
num_times_sent
++
;
chunk
->
sent_at
=
jiffies
;
if
(
sctp_chunk_is_data
(
chunk
))
{
...
...
@@ -309,7 +306,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
chunk
->
rtt_in_progress
=
1
;
transport
->
rto_pending
=
1
;
}
packet_
has_data
=
1
;
has_data
=
1
;
}
memcpy
(
skb_put
(
nskb
,
chunk
->
skb
->
len
),
chunk
->
skb
->
data
,
chunk
->
skb
->
len
);
...
...
@@ -399,7 +396,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
asoc
->
peer
.
last_sent_to
=
transport
;
}
if
(
packet_
has_data
)
{
if
(
has_data
)
{
struct
timer_list
*
timer
;
unsigned
long
timeout
;
...
...
@@ -456,9 +453,9 @@ int sctp_packet_transmit(sctp_packet_t *packet)
/*
* This private function resets the packet to a fresh state.
*/
static
void
sctp_packet_reset
(
s
ctp_packet_
t
*
packet
)
static
void
sctp_packet_reset
(
s
truct
sctp_packe
t
*
packet
)
{
s
ctp_chunk_t
*
chunk
=
NULL
;
s
truct
sctp_chunk
*
chunk
=
NULL
;
packet
->
size
=
SCTP_IP_OVERHEAD
;
...
...
@@ -473,13 +470,16 @@ static void sctp_packet_reset(sctp_packet_t *packet)
}
/* This private function handles the specifics of appending DATA chunks. */
static
sctp_xmit_t
sctp_packet_append_data
(
s
ctp_packet_t
*
packet
,
s
ctp_chunk_t
*
chunk
)
static
sctp_xmit_t
sctp_packet_append_data
(
s
truct
sctp_packet
*
packet
,
s
truct
sctp_chunk
*
chunk
)
{
sctp_xmit_t
retval
=
SCTP_XMIT_OK
;
size_t
datasize
,
rwnd
,
inflight
;
struct
sctp_transport
*
transport
=
packet
->
transport
;
__u32
max_burst_bytes
;
struct
sctp_association
*
asoc
=
transport
->
asoc
;
struct
sctp_opt
*
sp
=
sctp_sk
(
asoc
->
base
.
sk
);
struct
sctp_outq
*
q
=
&
asoc
->
outqueue
;
/* RFC 2960 6.1 Transmission of DATA Chunks
*
...
...
@@ -494,8 +494,8 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
* receiver to the data sender.
*/
rwnd
=
transport
->
asoc
->
peer
.
rwnd
;
inflight
=
transport
->
asoc
->
outqueue
.
outstanding_bytes
;
rwnd
=
asoc
->
peer
.
rwnd
;
inflight
=
asoc
->
outqueue
.
outstanding_bytes
;
datasize
=
sctp_data_size
(
chunk
);
...
...
@@ -517,7 +517,7 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
* if ((flightsize + Max.Burst * MTU) < cwnd)
* cwnd = flightsize + Max.Burst * MTU
*/
max_burst_bytes
=
transport
->
asoc
->
max_burst
*
transport
->
asoc
->
pmtu
;
max_burst_bytes
=
asoc
->
max_burst
*
asoc
->
pmtu
;
if
((
transport
->
flight_size
+
max_burst_bytes
)
<
transport
->
cwnd
)
{
transport
->
cwnd
=
transport
->
flight_size
+
max_burst_bytes
;
SCTP_DEBUG_PRINTK
(
"%s: cwnd limited by max_burst: "
...
...
@@ -543,27 +543,44 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
* When a Fast Retransmit is being performed the sender SHOULD
* ignore the value of cwnd and SHOULD NOT delay retransmission.
*/
if
(
!
chunk
->
fast_retransmit
)
{
if
(
!
chunk
->
fast_retransmit
)
if
(
transport
->
flight_size
>=
transport
->
cwnd
)
{
retval
=
SCTP_XMIT_RWND_FULL
;
goto
finish
;
}
/* Nagle's algorithm to solve small-packet problem:
* Inhibit the sending of new chunks when new outgoing data arrives
* if any previously transmitted data on the connection remains
* unacknowledged.
*/
if
(
!
sp
->
nodelay
&&
SCTP_IP_OVERHEAD
==
packet
->
size
&&
q
->
outstanding_bytes
&&
SCTP_STATE_ESTABLISHED
==
asoc
->
state
)
{
unsigned
len
=
datasize
+
q
->
out_qlen
;
/* Check whether this chunk and all the rest of pending
* data will fit or delay in hopes of bundling a full
* sized packet.
*/
if
(
len
<
asoc
->
pmtu
-
SCTP_IP_OVERHEAD
)
{
retval
=
SCTP_XMIT_NAGLE_DELAY
;
goto
finish
;
}
}
/* Keep track of how many bytes are in flight over this transport. */
transport
->
flight_size
+=
datasize
;
/* Keep track of how many bytes are in flight to the receiver. */
transport
->
asoc
->
outqueue
.
outstanding_bytes
+=
datasize
;
asoc
->
outqueue
.
outstanding_bytes
+=
datasize
;
/* Update our view of the receiver's rwnd. */
if
(
datasize
<
rwnd
)
{
if
(
datasize
<
rwnd
)
rwnd
-=
datasize
;
}
else
{
else
rwnd
=
0
;
}
transport
->
asoc
->
peer
.
rwnd
=
rwnd
;
asoc
->
peer
.
rwnd
=
rwnd
;
finish:
return
retval
;
...
...
net/sctp/outqueue.c
View file @
e5e956d0
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001
-2003
Intel Corp.
* Copyright (c) 2001-2003 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
...
...
@@ -62,6 +62,43 @@ static void sctp_check_transmitted(struct sctp_outq *q,
sctp_sackhdr_t
*
sack
,
__u32
highest_new_tsn
);
/* Add data to the front of the queue. */
static
inline
void
sctp_outq_head_data
(
struct
sctp_outq
*
q
,
struct
sctp_chunk
*
ch
)
{
__skb_queue_head
(
&
q
->
out
,
(
struct
sk_buff
*
)
ch
);
q
->
out_qlen
+=
ch
->
skb
->
len
;
return
;
}
/* Take data from the front of the queue. */
static
inline
struct
sctp_chunk
*
sctp_outq_dequeue_data
(
struct
sctp_outq
*
q
)
{
struct
sctp_chunk
*
ch
;
ch
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
q
->
out
);
if
(
ch
)
q
->
out_qlen
-=
ch
->
skb
->
len
;
return
ch
;
}
/* Add data chunk to the end of the queue. */
static
inline
void
sctp_outq_tail_data
(
struct
sctp_outq
*
q
,
struct
sctp_chunk
*
ch
)
{
__skb_queue_tail
(
&
q
->
out
,
(
struct
sk_buff
*
)
ch
);
q
->
out_qlen
+=
ch
->
skb
->
len
;
return
;
}
/* Insert a chunk behind chunk 'pos'. */
static
inline
void
sctp_outq_insert_data
(
struct
sctp_outq
*
q
,
struct
sctp_chunk
*
ch
,
struct
sctp_chunk
*
pos
)
{
__skb_insert
((
struct
sk_buff
*
)
ch
,
(
struct
sk_buff
*
)
pos
->
prev
,
(
struct
sk_buff
*
)
pos
,
pos
->
list
);
q
->
out_qlen
+=
ch
->
skb
->
len
;
}
/* Generate a new outqueue. */
struct
sctp_outq
*
sctp_outq_new
(
sctp_association_t
*
asoc
)
{
...
...
@@ -97,6 +134,7 @@ void sctp_outq_init(sctp_association_t *asoc, struct sctp_outq *q)
q
->
empty
=
1
;
q
->
malloced
=
0
;
q
->
out_qlen
=
0
;
}
/* Free the outqueue structure and any related pending chunks.
...
...
@@ -133,7 +171,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
}
/* Throw away any leftover data chunks. */
while
((
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
&
q
->
out
)))
while
((
chunk
=
sctp_outq_dequeue_data
(
q
)))
sctp_free_chunk
(
chunk
);
/* Throw away any leftover control chunks. */
...
...
@@ -192,7 +230,7 @@ int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk)
sctp_cname
(
SCTP_ST_CHUNK
(
chunk
->
chunk_hdr
->
type
))
:
"Illegal Chunk"
);
s
kb_queue_tail
(
&
q
->
out
,
(
struct
sk_buff
*
)
chunk
);
s
ctp_outq_tail_data
(
q
,
chunk
);
if
(
chunk
->
chunk_hdr
->
flags
&
SCTP_DATA_UNORDERED
)
SCTP_INC_STATS
(
SctpOutUnorderChunks
);
else
...
...
@@ -201,7 +239,7 @@ int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk)
break
;
};
}
else
{
skb_queue_tail
(
&
q
->
control
,
(
struct
sk_buff
*
)
chunk
);
__
skb_queue_tail
(
&
q
->
control
,
(
struct
sk_buff
*
)
chunk
);
SCTP_INC_STATS
(
SctpOutCtrlChunks
);
}
...
...
@@ -351,7 +389,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
*
* The return value is a normal kernel error return value.
*/
static
int
sctp_outq_flush_rtx
(
struct
sctp_outq
*
q
,
s
ctp_packet_
t
*
pkt
,
static
int
sctp_outq_flush_rtx
(
struct
sctp_outq
*
q
,
s
truct
sctp_packe
t
*
pkt
,
int
rtx_timeout
,
int
*
start_timer
)
{
struct
list_head
*
lqueue
;
...
...
@@ -385,17 +423,6 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, sctp_packet_t *pkt,
while
(
lchunk
)
{
chunk
=
list_entry
(
lchunk
,
sctp_chunk_t
,
transmitted_list
);
#if 0
/* If a chunk has been tried for more than SCTP_DEF_MAX_SEND
* times, discard it, and check the empty flag of the outqueue.
*
* --xguo
*/
if (chunk->snd_count > SCTP_DEF_MAX_SEND) {
sctp_free_chunk(chunk);
continue;
}
#endif
/* Make sure that Gap Acked TSNs are not retransmitted. A
* simple approach is just to move such TSNs out of the
...
...
@@ -461,8 +488,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, sctp_packet_t *pkt,
* queue. 'pos' points to the next chunk in the output queue after the
* chunk that is currently in the process of fragmentation.
*/
void
sctp_xmit_frag
(
struct
sctp_outq
*
q
,
struct
s
k_buff
*
pos
,
sctp_packet_t
*
packet
,
sctp_chunk_t
*
frag
,
__u32
tsn
)
void
sctp_xmit_frag
(
struct
sctp_outq
*
q
,
struct
s
ctp_chunk
*
pos
,
struct
sctp_packet
*
packet
,
struct
sctp_chunk
*
frag
,
__u32
tsn
)
{
struct
sctp_transport
*
transport
=
packet
->
transport
;
struct
sk_buff_head
*
queue
=
&
q
->
out
;
...
...
@@ -480,11 +507,10 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: q not empty. "
"adding 0x%x to outqueue
\n
"
,
ntohl
(
frag
->
subh
.
data_hdr
->
tsn
));
if
(
pos
)
{
skb_insert
(
pos
,
(
struct
sk_buff
*
)
frag
);
}
else
{
skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
}
if
(
pos
)
sctp_outq_insert_data
(
q
,
frag
,
pos
);
else
sctp_outq_tail_data
(
q
,
frag
);
return
;
}
...
...
@@ -496,11 +522,10 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: rwnd full. "
"adding 0x%x to outqueue
\n
"
,
ntohl
(
frag
->
subh
.
data_hdr
->
tsn
));
if
(
pos
)
{
skb_insert
(
pos
,
(
struct
sk_buff
*
)
frag
);
}
else
{
skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
}
if
(
pos
)
sctp_outq_insert_data
(
q
,
frag
,
pos
);
else
sctp_outq_tail_data
(
q
,
frag
);
break
;
case
SCTP_XMIT_OK
:
...
...
@@ -512,11 +537,10 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: force output "
"failed. adding 0x%x to outqueue
\n
"
,
ntohl
(
frag
->
subh
.
data_hdr
->
tsn
));
if
(
pos
)
{
skb_insert
(
pos
,
(
struct
sk_buff
*
)
frag
);
}
else
{
skb_queue_tail
(
queue
,
(
struct
sk_buff
*
)
frag
);
}
if
(
pos
)
sctp_outq_insert_data
(
q
,
frag
,
pos
);
else
sctp_outq_tail_data
(
q
,
frag
);
}
else
{
SCTP_DEBUG_PRINTK
(
"sctp_xmit_frag: force output "
"success. 0x%x sent
\n
"
,
...
...
@@ -537,14 +561,14 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sk_buff *pos,
* The argument 'frag' point to the first fragment and it holds the list
* of all the other fragments in the 'frag_list' field.
*/
void
sctp_xmit_fragmented_chunks
(
struct
sctp_outq
*
q
,
s
ctp_packet_t
*
packe
t
,
void
sctp_xmit_fragmented_chunks
(
struct
sctp_outq
*
q
,
s
truct
sctp_packet
*
pk
t
,
sctp_chunk_t
*
frag
)
{
sctp_association_t
*
asoc
=
frag
->
asoc
;
struct
list_head
*
lfrag
,
*
frag_list
;
__u32
tsn
;
int
nfrags
=
1
;
struct
s
k_buff
*
pos
;
struct
s
ctp_chunk
*
pos
;
/* Count the number of fragments. */
frag_list
=
&
frag
->
frag_list
;
...
...
@@ -553,17 +577,17 @@ void sctp_xmit_fragmented_chunks(struct sctp_outq *q, sctp_packet_t *packet,
}
/* Get a TSN block of nfrags TSNs. */
tsn
=
__
sctp_association_get_tsn_block
(
asoc
,
nfrags
);
tsn
=
sctp_association_get_tsn_block
(
asoc
,
nfrags
);
pos
=
skb_peek
(
&
q
->
out
);
pos
=
(
struct
sctp_chunk
*
)
skb_peek
(
&
q
->
out
);
/* Transmit the first fragment. */
sctp_xmit_frag
(
q
,
pos
,
p
acke
t
,
frag
,
tsn
++
);
sctp_xmit_frag
(
q
,
pos
,
p
k
t
,
frag
,
tsn
++
);
/* Transmit the rest of fragments. */
frag_list
=
&
frag
->
frag_list
;
list_for_each
(
lfrag
,
frag_list
)
{
frag
=
list_entry
(
lfrag
,
sctp_chunk_t
,
frag_list
);
sctp_xmit_frag
(
q
,
pos
,
p
acke
t
,
frag
,
tsn
++
);
sctp_xmit_frag
(
q
,
pos
,
p
k
t
,
frag
,
tsn
++
);
}
}
...
...
@@ -672,15 +696,14 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk,
*
* Description: Send everything in q which we legally can, subject to
* congestion limitations.
*
* Note: This function can be called from multiple contexts so appropriate
* * Note: This function can be called from multiple contexts so appropriate
* locking concerns must be made. Today we use the sock lock to protect
* this function.
*/
int
sctp_outq_flush
(
struct
sctp_outq
*
q
,
int
rtx_timeout
)
{
s
ctp_packet_
t
*
packet
;
s
ctp_packet_
t
singleton
;
s
truct
sctp_packe
t
*
packet
;
s
truct
sctp_packe
t
singleton
;
sctp_association_t
*
asoc
=
q
->
asoc
;
int
ecn_capable
=
asoc
->
peer
.
ecn_capable
;
__u16
sport
=
asoc
->
base
.
bind_addr
.
port
;
...
...
@@ -719,7 +742,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
}
queue
=
&
q
->
control
;
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
queue
)))
{
while
((
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
queue
)))
{
/* Pick the right transport to use. */
new_transport
=
chunk
->
transport
;
...
...
@@ -852,7 +875,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
/* Finally, transmit new packets. */
start_timer
=
0
;
queue
=
&
q
->
out
;
while
(
NULL
!=
(
chunk
=
(
sctp_chunk_t
*
)
skb_dequeue
(
queue
)))
{
while
(
NULL
!=
(
chunk
=
sctp_outq_dequeue_data
(
q
)))
{
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
* stream identifier.
*/
...
...
@@ -925,6 +949,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
switch
(
status
)
{
case
SCTP_XMIT_PMTU_FULL
:
case
SCTP_XMIT_RWND_FULL
:
case
SCTP_XMIT_NAGLE_DELAY
:
/* We could not append this chunk, so put
* the chunk back on the output queue.
*/
...
...
@@ -932,7 +957,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
"not transmit TSN: 0x%x, status: %d
\n
"
,
ntohl
(
chunk
->
subh
.
data_hdr
->
tsn
),
status
);
s
kb_queue_head
(
queue
,
(
struct
sk_buff
*
)
chunk
);
s
ctp_outq_head_data
(
q
,
chunk
);
goto
sctp_flush_out
;
break
;
...
...
@@ -994,6 +1019,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
}
sctp_flush_out:
/* Before returning, examine all the transports touched in
* this call. Right now, we bluntly force clear all the
* transports. Things might change after we implement Nagle.
...
...
@@ -1163,11 +1189,10 @@ int sctp_outq_sack(struct sctp_outq *q, sctp_sackhdr_t *sack)
sack_a_rwnd
=
ntohl
(
sack
->
a_rwnd
);
outstanding
=
q
->
outstanding_bytes
;
if
(
outstanding
<
sack_a_rwnd
)
{
if
(
outstanding
<
sack_a_rwnd
)
sack_a_rwnd
-=
outstanding
;
}
else
{
else
sack_a_rwnd
=
0
;
}
asoc
->
peer
.
rwnd
=
sack_a_rwnd
;
...
...
net/sctp/protocol.c
View file @
e5e956d0
...
...
@@ -58,7 +58,7 @@
#include <net/inet_common.h>
/* Global data structures. */
s
ctp_protocol_t
sctp_proto
;
s
truct
sctp_protocol
sctp_proto
;
struct
proc_dir_entry
*
proc_net_sctp
;
DEFINE_SNMP_STAT
(
struct
sctp_mib
,
sctp_statistics
);
...
...
@@ -152,7 +152,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
/* Extract our IP addresses from the system and stash them in the
* protocol structure.
*/
static
void
__sctp_get_local_addr_list
(
s
ctp_protocol_t
*
proto
)
static
void
__sctp_get_local_addr_list
(
s
truct
sctp_protocol
*
proto
)
{
struct
net_device
*
dev
;
struct
list_head
*
pos
;
...
...
@@ -168,7 +168,7 @@ static void __sctp_get_local_addr_list(sctp_protocol_t *proto)
read_unlock
(
&
dev_base_lock
);
}
static
void
sctp_get_local_addr_list
(
s
ctp_protocol_t
*
proto
)
static
void
sctp_get_local_addr_list
(
s
truct
sctp_protocol
*
proto
)
{
long
flags
__attribute__
((
unused
));
...
...
@@ -178,7 +178,7 @@ static void sctp_get_local_addr_list(sctp_protocol_t *proto)
}
/* Free the existing local addresses. */
static
void
__sctp_free_local_addr_list
(
s
ctp_protocol_t
*
proto
)
static
void
__sctp_free_local_addr_list
(
s
truct
sctp_protocol
*
proto
)
{
struct
sockaddr_storage_list
*
addr
;
struct
list_head
*
pos
,
*
temp
;
...
...
@@ -191,7 +191,7 @@ static void __sctp_free_local_addr_list(sctp_protocol_t *proto)
}
/* Free the existing local addresses. */
static
void
sctp_free_local_addr_list
(
s
ctp_protocol_t
*
proto
)
static
void
sctp_free_local_addr_list
(
s
truct
sctp_protocol
*
proto
)
{
long
flags
__attribute__
((
unused
));
...
...
@@ -201,8 +201,9 @@ static void sctp_free_local_addr_list(sctp_protocol_t *proto)
}
/* Copy the local addresses which are valid for 'scope' into 'bp'. */
int
sctp_copy_local_addr_list
(
sctp_protocol_t
*
proto
,
sctp_bind_addr_t
*
bp
,
sctp_scope_t
scope
,
int
priority
,
int
copy_flags
)
int
sctp_copy_local_addr_list
(
struct
sctp_protocol
*
proto
,
struct
sctp_bind_addr
*
bp
,
sctp_scope_t
scope
,
int
priority
,
int
copy_flags
)
{
struct
sockaddr_storage_list
*
addr
;
int
error
=
0
;
...
...
@@ -479,6 +480,61 @@ void sctp_v4_get_saddr(sctp_association_t *asoc,
}
/* Create and initialize a new sk for the socket returned by accept(). */
struct
sock
*
sctp_v4_create_accept_sk
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
)
{
struct
sock
*
newsk
;
struct
inet_opt
*
inet
=
inet_sk
(
sk
);
struct
inet_opt
*
newinet
;
newsk
=
sk_alloc
(
PF_INET
,
GFP_KERNEL
,
sizeof
(
struct
sctp_sock
),
sk
->
slab
);
if
(
!
newsk
)
goto
out
;
sock_init_data
(
NULL
,
newsk
);
newsk
->
type
=
SOCK_STREAM
;
newsk
->
prot
=
sk
->
prot
;
newsk
->
no_check
=
sk
->
no_check
;
newsk
->
reuse
=
sk
->
reuse
;
newsk
->
destruct
=
inet_sock_destruct
;
newsk
->
zapped
=
0
;
newsk
->
family
=
PF_INET
;
newsk
->
protocol
=
IPPROTO_SCTP
;
newsk
->
backlog_rcv
=
sk
->
prot
->
backlog_rcv
;
newinet
=
inet_sk
(
newsk
);
newinet
->
sport
=
inet
->
sport
;
newinet
->
saddr
=
inet
->
saddr
;
newinet
->
rcv_saddr
=
inet
->
saddr
;
newinet
->
dport
=
asoc
->
peer
.
port
;
newinet
->
daddr
=
asoc
->
peer
.
primary_addr
.
v4
.
sin_addr
.
s_addr
;
newinet
->
pmtudisc
=
inet
->
pmtudisc
;
newinet
->
id
=
0
;
newinet
->
ttl
=
sysctl_ip_default_ttl
;
newinet
->
mc_loop
=
1
;
newinet
->
mc_ttl
=
1
;
newinet
->
mc_index
=
0
;
newinet
->
mc_list
=
NULL
;
#ifdef INET_REFCNT_DEBUG
atomic_inc
(
&
inet_sock_nr
);
#endif
if
(
0
!=
newsk
->
prot
->
init
(
newsk
))
{
inet_sock_release
(
newsk
);
newsk
=
NULL
;
}
out:
return
newsk
;
}
/* Event handler for inet address addition/deletion events.
* Basically, whenever there is an event, we re-build our local address list.
*/
...
...
@@ -501,10 +557,13 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long event,
*/
int
sctp_ctl_sock_init
(
void
)
{
int
err
=
0
;
int
family
=
PF_INET
;
int
err
;
sa_family_t
family
;
SCTP_V6
(
family
=
PF_INET6
;)
if
(
sctp_get_pf_specific
(
PF_INET6
))
family
=
PF_INET6
;
else
family
=
PF_INET
;
err
=
sock_create
(
family
,
SOCK_SEQPACKET
,
IPPROTO_SCTP
,
&
sctp_ctl_socket
);
...
...
@@ -630,6 +689,16 @@ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
return
sctp_v4_available
(
addr
);
}
/* Fill in Supported Address Type information for INIT and INIT-ACK
* chunks. Returns number of addresses supported.
*/
static
int
sctp_inet_supported_addrs
(
const
struct
sctp_opt
*
opt
,
__u16
*
types
)
{
types
[
0
]
=
SCTP_PARAM_IPV4_ADDRESS
;
return
1
;
}
/* Wrapper routine that calls the ip transmit routine. */
static
inline
int
sctp_v4_xmit
(
struct
sk_buff
*
skb
,
struct
sctp_transport
*
transport
,
int
ipfragok
)
...
...
@@ -652,6 +721,8 @@ static struct sctp_pf sctp_pf_inet = {
.
af_supported
=
sctp_inet_af_supported
,
.
cmp_addr
=
sctp_inet_cmp_addr
,
.
bind_verify
=
sctp_inet_bind_verify
,
.
supported_addrs
=
sctp_inet_supported_addrs
,
.
create_accept_sk
=
sctp_v4_create_accept_sk
,
.
af
=
&
sctp_ipv4_specific
,
};
...
...
@@ -682,7 +753,7 @@ struct proto_ops inet_seqpacket_ops = {
};
/* Registration with AF_INET family. */
st
ruct
inet_protosw
sctp
_protosw
=
{
st
atic
struct
inet_protosw
sctp_seqpacket
_protosw
=
{
.
type
=
SOCK_SEQPACKET
,
.
protocol
=
IPPROTO_SCTP
,
.
prot
=
&
sctp_prot
,
...
...
@@ -691,6 +762,15 @@ struct inet_protosw sctp_protosw = {
.
no_check
=
0
,
.
flags
=
SCTP_PROTOSW_FLAG
};
static
struct
inet_protosw
sctp_stream_protosw
=
{
.
type
=
SOCK_STREAM
,
.
protocol
=
IPPROTO_SCTP
,
.
prot
=
&
sctp_prot
,
.
ops
=
&
inet_seqpacket_ops
,
.
capability
=
-
1
,
.
no_check
=
0
,
.
flags
=
SCTP_PROTOSW_FLAG
};
/* Register with IP layer. */
static
struct
inet_protocol
sctp_protocol
=
{
...
...
@@ -797,8 +877,9 @@ __init int sctp_init(void)
if
(
inet_add_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
)
<
0
)
return
-
EAGAIN
;
/* Add SCTP to inetsw linked list. */
inet_register_protosw
(
&
sctp_protosw
);
/* Add SCTP(TCP and UDP style) to inetsw linked list. */
inet_register_protosw
(
&
sctp_seqpacket_protosw
);
inet_register_protosw
(
&
sctp_stream_protosw
);
/* Allocate and initialise sctp mibs. */
status
=
init_sctp_mibs
();
...
...
@@ -944,7 +1025,8 @@ __init int sctp_init(void)
cleanup_sctp_mibs
();
err_init_mibs:
inet_del_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
);
inet_unregister_protosw
(
&
sctp_protosw
);
inet_unregister_protosw
(
&
sctp_seqpacket_protosw
);
inet_unregister_protosw
(
&
sctp_stream_protosw
);
return
status
;
}
...
...
@@ -977,7 +1059,8 @@ __exit void sctp_exit(void)
cleanup_sctp_mibs
();
inet_del_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
);
inet_unregister_protosw
(
&
sctp_protosw
);
inet_unregister_protosw
(
&
sctp_seqpacket_protosw
);
inet_unregister_protosw
(
&
sctp_stream_protosw
);
}
module_init
(
sctp_init
);
...
...
net/sctp/sm_make_chunk.c
View file @
e5e956d0
...
...
@@ -66,29 +66,6 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
* Note 4: This parameter, when present, specifies all the
* address types the sending endpoint can support. The absence
* of this parameter indicates that the sending endpoint can
* support any address type.
*/
static
const
sctp_supported_addrs_param_t
sat_param
=
{
{
SCTP_PARAM_SUPPORTED_ADDRESS_TYPES
,
__constant_htons
(
SCTP_SAT_LEN
),
}
};
/* gcc 3.2 doesn't allow initialization of zero-length arrays. So the above
* structure is split and the address types array is initialized using a
* fixed length array.
*/
static
const
__u16
sat_addr_types
[
2
]
=
{
SCTP_PARAM_IPV4_ADDRESS
,
SCTP_V6
(
SCTP_PARAM_IPV6_ADDRESS
,)
};
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
* Note 2: The ECN capable field is reserved for future use of
...
...
@@ -174,7 +151,10 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
union
sctp_params
addrs
;
size_t
chunksize
;
sctp_chunk_t
*
retval
=
NULL
;
int
addrs_len
=
0
;
int
num_types
,
addrs_len
=
0
;
struct
sctp_opt
*
sp
;
sctp_supported_addrs_param_t
sat
;
__u16
types
[
2
];
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
...
...
@@ -195,7 +175,11 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
init
.
num_inbound_streams
=
htons
(
asoc
->
c
.
sinit_max_instreams
);
init
.
initial_tsn
=
htonl
(
asoc
->
c
.
initial_tsn
);
chunksize
=
sizeof
(
init
)
+
addrs_len
+
SCTP_SAT_LEN
;
/* How many address types are needed? */
sp
=
sctp_sk
(
asoc
->
base
.
sk
);
num_types
=
sp
->
pf
->
supported_addrs
(
sp
,
types
);
chunksize
=
sizeof
(
init
)
+
addrs_len
+
SCTP_SAT_LEN
(
num_types
);
chunksize
+=
sizeof
(
ecap_param
);
chunksize
+=
vparam_len
;
...
...
@@ -220,8 +204,18 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
retval
->
param_hdr
.
v
=
sctp_addto_chunk
(
retval
,
addrs_len
,
addrs
.
v
);
sctp_addto_chunk
(
retval
,
sizeof
(
sctp_paramhdr_t
),
&
sat_param
);
sctp_addto_chunk
(
retval
,
sizeof
(
sat_addr_types
),
sat_addr_types
);
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
* Note 4: This parameter, when present, specifies all the
* address types the sending endpoint can support. The absence
* of this parameter indicates that the sending endpoint can
* support any address type.
*/
sat
.
param_hdr
.
type
=
SCTP_PARAM_SUPPORTED_ADDRESS_TYPES
;
sat
.
param_hdr
.
length
=
htons
(
SCTP_SAT_LEN
(
num_types
));
sctp_addto_chunk
(
retval
,
sizeof
(
sat
),
&
sat
);
sctp_addto_chunk
(
retval
,
num_types
*
sizeof
(
__u16
),
&
types
);
sctp_addto_chunk
(
retval
,
sizeof
(
ecap_param
),
&
ecap_param
);
nodata:
if
(
addrs
.
v
)
...
...
@@ -604,7 +598,7 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
/* Initialize the SACK header. */
sack
.
cum_tsn_ack
=
htonl
(
ctsn
);
sack
.
a_rwnd
=
htonl
(
asoc
->
rwnd
);
sack
.
a_rwnd
=
htonl
(
asoc
->
a_
rwnd
);
sack
.
num_gap_ack_blocks
=
htons
(
num_gabs
);
sack
.
num_dup_tsns
=
htons
(
num_dup_tsns
);
...
...
@@ -1159,7 +1153,7 @@ int sctp_datachunks_from_user(sctp_association_t *asoc,
first_len
=
max
;
/* Encourage Cookie-ECHO bundling. */
if
(
asoc
->
state
<
SCTP_STATE_
ESTABLISH
ED
)
{
if
(
asoc
->
state
<
SCTP_STATE_
COOKIE_ECHO
ED
)
{
whole
=
msg_len
/
(
max
-
SCTP_ARBITRARY_COOKIE_ECHO_LEN
);
/* Account for the DATA to be bundled with the COOKIE-ECHO. */
...
...
@@ -1282,7 +1276,7 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
* assign a TSN.
*/
chunk
->
subh
.
data_hdr
->
tsn
=
htonl
(
__
sctp_association_get_next_tsn
(
chunk
->
asoc
));
htonl
(
sctp_association_get_next_tsn
(
chunk
->
asoc
));
chunk
->
has_tsn
=
1
;
}
}
...
...
net/sctp/sm_sideeffect.c
View file @
e5e956d0
...
...
@@ -105,8 +105,7 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *, sctp_association_t *,
#define DEBUG_POST_SFX \
SCTP_DEBUG_PRINTK("sctp_do_sm post sfx: error %d, asoc %p[%s]\n", \
error, asoc, \
sctp_state_tbl[sctp_id2assoc(ep->base.sk, \
sctp_assoc2id(asoc))?asoc->state:SCTP_STATE_CLOSED])
sctp_state_tbl[asoc?asoc->state:SCTP_STATE_CLOSED])
/*
* This is the master state machine processing function.
...
...
@@ -256,7 +255,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_cmd_t
*
cmd
;
sctp_chunk_t
*
new_obj
;
sctp_chunk_t
*
chunk
=
NULL
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
struct
list_head
*
pos
;
struct
timer_list
*
timer
;
unsigned
long
timeout
;
...
...
@@ -716,13 +715,12 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands)
asoc
->
peer
.
sack_needed
=
1
;
goto
out
;
}
else
{
if
(
asoc
->
a_rwnd
>
asoc
->
rwnd
)
asoc
->
a_rwnd
=
asoc
->
rwnd
;
sack
=
sctp_make_sack
(
asoc
);
if
(
!
sack
)
goto
nomem
;
/* Update the last advertised rwnd value. */
asoc
->
a_rwnd
=
asoc
->
rwnd
;
asoc
->
peer
.
sack_needed
=
0
;
error
=
sctp_outq_tail
(
&
asoc
->
outqueue
,
sack
);
...
...
@@ -1223,13 +1221,35 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, sctp_association_t *asoc,
static
void
sctp_cmd_new_state
(
sctp_cmd_seq_t
*
cmds
,
sctp_association_t
*
asoc
,
sctp_state_t
state
)
{
struct
sock
*
sk
=
asoc
->
base
.
sk
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
asoc
->
state
=
state
;
asoc
->
state_timestamp
=
jiffies
;
/* Wake up any process waiting for the association to
* get established.
if
((
SCTP_STATE_ESTABLISHED
==
asoc
->
state
)
||
(
SCTP_STATE_CLOSED
==
asoc
->
state
))
{
/* Wake up any processes waiting in the asoc's wait queue in
* sctp_wait_for_connect() or sctp_wait_for_sndbuf().
*/
if
((
SCTP_STATE_ESTABLISHED
==
asoc
->
state
)
&&
(
waitqueue_active
(
&
asoc
->
wait
)))
if
(
waitqueue_active
(
&
asoc
->
wait
))
wake_up_interruptible
(
&
asoc
->
wait
);
/* Wake up any processes waiting in the sk's sleep queue of
* a TCP-style or UDP-style peeled-off socket in
* sctp_wait_for_accept() or sctp_wait_for_packet().
* For a UDP-style socket, the waiters are woken up by the
* notifications.
*/
if
(
SCTP_SOCKET_UDP
!=
sp
->
type
)
sk
->
state_change
(
sk
);
}
/* Change the sk->state of a TCP-style socket that has sucessfully
* completed a connect() call.
*/
if
((
SCTP_STATE_ESTABLISHED
==
asoc
->
state
)
&&
(
SCTP_SOCKET_TCP
==
sp
->
type
)
&&
(
SCTP_SS_CLOSED
==
sk
->
state
))
sk
->
state
=
SCTP_SS_ESTABLISHED
;
}
net/sctp/sm_statefuns.c
View file @
e5e956d0
...
...
@@ -189,7 +189,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep,
sctp_chunk_t
*
repl
;
sctp_association_t
*
new_asoc
;
sctp_chunk_t
*
err_chunk
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_unrecognized_param_t
*
unk_param
;
int
len
;
...
...
@@ -354,10 +354,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep,
sctp_init_chunk_t
*
initchunk
;
__u32
init_tag
;
sctp_chunk_t
*
err_chunk
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_disposition_t
ret
;
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
...
...
@@ -912,14 +911,14 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
sctp_cmd_seq_t
*
commands
)
{
int
len
;
s
ctp_packet_
t
*
pkt
;
s
truct
sctp_packe
t
*
pkt
;
sctp_addr_param_t
*
addrparm
;
sctp_errhdr_t
*
errhdr
;
sctp_endpoint_t
*
ep
;
char
buffer
[
sizeof
(
sctp_errhdr_t
)
+
sizeof
(
sctp_addr_param_t
)];
/* Build the error on the stack. We are way to malloc
*
malloc crazy
throughout the code today.
/* Build the error on the stack. We are way to malloc
crazy
* throughout the code today.
*/
errhdr
=
(
sctp_errhdr_t
*
)
buffer
;
addrparm
=
(
sctp_addr_param_t
*
)
errhdr
->
variable
;
...
...
@@ -1105,11 +1104,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
sctp_chunk_t
*
repl
;
sctp_association_t
*
new_asoc
;
sctp_chunk_t
*
err_chunk
;
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_unrecognized_param_t
*
unk_param
;
int
len
;
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
...
...
@@ -2751,7 +2749,7 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(const sctp_endpoint_t *ep,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
s
ctp_packet_
t
*
packet
=
NULL
;
s
truct
sctp_packe
t
*
packet
=
NULL
;
sctp_chunk_t
*
chunk
=
arg
;
sctp_chunk_t
*
abort
;
...
...
@@ -2953,7 +2951,7 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const sctp_endpoint_t *ep,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
s
ctp_packet_
t
*
packet
=
NULL
;
s
truct
sctp_packe
t
*
packet
=
NULL
;
sctp_chunk_t
*
chunk
=
arg
;
sctp_chunk_t
*
shut
;
...
...
@@ -4377,13 +4375,13 @@ sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *chunk)
/* Create an ABORT packet to be sent as a response, with the specified
* error causes.
*/
s
ctp_packet_
t
*
sctp_abort_pkt_new
(
const
sctp_endpoint_t
*
ep
,
s
truct
sctp_packe
t
*
sctp_abort_pkt_new
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
const
void
*
payload
,
size_t
paylen
)
{
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
sctp_chunk_t
*
abort
;
packet
=
sctp_ootb_pkt_new
(
asoc
,
chunk
);
...
...
@@ -4413,10 +4411,10 @@ sctp_packet_t *sctp_abort_pkt_new(const sctp_endpoint_t *ep,
}
/* Allocate a packet for responding in the OOTB conditions. */
s
ctp_packet_
t
*
sctp_ootb_pkt_new
(
const
sctp_association_t
*
asoc
,
s
truct
sctp_packe
t
*
sctp_ootb_pkt_new
(
const
sctp_association_t
*
asoc
,
const
sctp_chunk_t
*
chunk
)
{
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
struct
sctp_transport
*
transport
;
__u16
sport
;
__u16
dport
;
...
...
@@ -4449,7 +4447,7 @@ sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
goto
nomem
;
/* Allocate a new packet for sending the response. */
packet
=
t_new
(
s
ctp_packet_
t
,
GFP_ATOMIC
);
packet
=
t_new
(
s
truct
sctp_packe
t
,
GFP_ATOMIC
);
if
(
!
packet
)
goto
nomem_packet
;
...
...
@@ -4471,7 +4469,7 @@ sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
}
/* Free the packet allocated earlier for responding in the OOTB condition. */
void
sctp_ootb_pkt_free
(
s
ctp_packet_
t
*
packet
)
void
sctp_ootb_pkt_free
(
s
truct
sctp_packe
t
*
packet
)
{
sctp_transport_free
(
packet
->
transport
);
sctp_packet_free
(
packet
);
...
...
@@ -4484,7 +4482,7 @@ void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
sctp_cmd_seq_t
*
commands
,
sctp_chunk_t
*
err_chunk
)
{
s
ctp_packet_
t
*
packet
;
s
truct
sctp_packe
t
*
packet
;
if
(
err_chunk
)
{
packet
=
sctp_ootb_pkt_new
(
asoc
,
chunk
);
...
...
net/sctp/socket.c
View file @
e5e956d0
This diff is collapsed.
Click to expand it.
net/sctp/sysctl.c
View file @
e5e956d0
...
...
@@ -42,7 +42,7 @@
#include <net/sctp/structs.h>
#include <linux/sysctl.h>
extern
s
ctp_protocol_t
sctp_proto
;
extern
s
truct
sctp_protocol
sctp_proto
;
static
ctl_table
sctp_table
[]
=
{
{
...
...
net/sctp/transport.c
View file @
e5e956d0
...
...
@@ -83,7 +83,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
const
union
sctp_addr
*
addr
,
int
priority
)
{
s
ctp_protocol_t
*
proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
proto
=
sctp_get_protocol
();
/* Copy in the address. */
peer
->
ipaddr
=
*
addr
;
...
...
@@ -262,7 +262,7 @@ void sctp_transport_put(struct sctp_transport *transport)
/* Update transport's RTO based on the newly calculated RTT. */
void
sctp_transport_update_rto
(
struct
sctp_transport
*
tp
,
__u32
rtt
)
{
s
ctp_protocol_t
*
proto
=
sctp_get_protocol
();
s
truct
sctp_protocol
*
proto
=
sctp_get_protocol
();
/* Check for valid transport. */
SCTP_ASSERT
(
tp
,
"NULL transport"
,
return
);
...
...
net/sctp/tsnmap.c
View file @
e5e956d0
...
...
@@ -250,7 +250,7 @@ int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
/* The Gap Ack Block happens to end at the end of the
* overflow map.
*/
if
(
started
&
!
ended
)
{
if
(
started
&
&
!
ended
)
{
ended
++
;
_end
=
map
->
len
+
map
->
len
-
1
;
}
...
...
net/sctp/ulpqueue.c
View file @
e5e956d0
...
...
@@ -220,7 +220,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
if
(
sctp_event2skb
(
event
)
->
list
)
sctp_skb_list_tail
(
sctp_event2skb
(
event
)
->
list
,
queue
);
else
skb_queue_tail
(
queue
,
sctp_event2skb
(
event
));
__
skb_queue_tail
(
queue
,
sctp_event2skb
(
event
));
/* Did we just complete partial delivery and need to get
* rolling again? Move pending data to the receive
...
...
@@ -230,7 +230,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
sctp_ulpq_clear_pd
(
ulpq
);
if
(
queue
==
&
sk
->
receive_queue
)
wake_up_interruptible
(
sk
->
sleep
);
sk
->
data_ready
(
sk
,
0
);
return
1
;
out_free:
...
...
@@ -247,14 +247,14 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
static
inline
void
sctp_ulpq_store_reasm
(
struct
sctp_ulpq
*
ulpq
,
struct
sctp_ulpevent
*
event
)
{
struct
sk_buff
*
pos
,
*
tmp
;
struct
sk_buff
*
pos
;
struct
sctp_ulpevent
*
cevent
;
__u32
tsn
,
ctsn
;
tsn
=
event
->
sndrcvinfo
.
sinfo_tsn
;
/* Find the right place in this list. We store them by TSN. */
s
ctp_skb_for_each
(
pos
,
&
ulpq
->
reasm
,
tmp
)
{
s
kb_queue_walk
(
&
ulpq
->
reasm
,
pos
)
{
cevent
=
sctp_skb2event
(
pos
);
ctsn
=
cevent
->
sndrcvinfo
.
sinfo_tsn
;
...
...
@@ -334,7 +334,7 @@ static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *
*/
static
inline
struct
sctp_ulpevent
*
sctp_ulpq_retrieve_reassembled
(
struct
sctp_ulpq
*
ulpq
)
{
struct
sk_buff
*
pos
,
*
tmp
;
struct
sk_buff
*
pos
;
struct
sctp_ulpevent
*
cevent
;
struct
sk_buff
*
first_frag
=
NULL
;
__u32
ctsn
,
next_tsn
;
...
...
@@ -355,7 +355,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u
* fragment in order. If not, first_frag is reset to NULL and we
* start the next pass when we find another first fragment.
*/
s
ctp_skb_for_each
(
pos
,
&
ulpq
->
reasm
,
tmp
)
{
s
kb_queue_walk
(
&
ulpq
->
reasm
,
pos
)
{
cevent
=
sctp_skb2event
(
pos
);
ctsn
=
cevent
->
sndrcvinfo
.
sinfo_tsn
;
...
...
@@ -374,29 +374,26 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u
case
SCTP_DATA_LAST_FRAG
:
if
(
first_frag
&&
(
ctsn
==
next_tsn
))
retval
=
sctp_make_reassembled_event
(
first_frag
,
pos
);
goto
found
;
else
first_frag
=
NULL
;
break
;
};
/* We have the reassembled event. There is no need to look
* further.
*/
if
(
retval
)
{
retval
->
msg_flags
|=
MSG_EOR
;
break
;
}
}
done:
return
retval
;
found:
retval
=
sctp_make_reassembled_event
(
first_frag
,
pos
);
if
(
retval
)
retval
->
msg_flags
|=
MSG_EOR
;
goto
done
;
}
/* Retrieve the next set of fragments of a partial message. */
static
inline
struct
sctp_ulpevent
*
sctp_ulpq_retrieve_partial
(
struct
sctp_ulpq
*
ulpq
)
{
struct
sk_buff
*
pos
,
*
tmp
,
*
last_frag
,
*
first_frag
;
struct
sk_buff
*
pos
,
*
last_frag
,
*
first_frag
;
struct
sctp_ulpevent
*
cevent
;
__u32
ctsn
,
next_tsn
;
int
is_last
;
...
...
@@ -415,7 +412,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq
next_tsn
=
0
;
is_last
=
0
;
s
ctp_skb_for_each
(
pos
,
&
ulpq
->
reasm
,
tmp
)
{
s
kb_queue_walk
(
&
ulpq
->
reasm
,
pos
)
{
cevent
=
sctp_skb2event
(
pos
);
ctsn
=
cevent
->
sndrcvinfo
.
sinfo_tsn
;
...
...
@@ -448,7 +445,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq
*/
done:
retval
=
sctp_make_reassembled_event
(
first_frag
,
last_frag
);
if
(
is_last
)
if
(
retval
&&
is_last
)
retval
->
msg_flags
|=
MSG_EOR
;
return
retval
;
...
...
@@ -490,7 +487,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
/* Retrieve the first part (sequential fragments) for partial delivery. */
static
inline
struct
sctp_ulpevent
*
sctp_ulpq_retrieve_first
(
struct
sctp_ulpq
*
ulpq
)
{
struct
sk_buff
*
pos
,
*
tmp
,
*
last_frag
,
*
first_frag
;
struct
sk_buff
*
pos
,
*
last_frag
,
*
first_frag
;
struct
sctp_ulpevent
*
cevent
;
__u32
ctsn
,
next_tsn
;
struct
sctp_ulpevent
*
retval
;
...
...
@@ -507,7 +504,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *u
retval
=
NULL
;
next_tsn
=
0
;
s
ctp_skb_for_each
(
pos
,
&
ulpq
->
reasm
,
tmp
)
{
s
kb_queue_walk
(
&
ulpq
->
reasm
,
pos
)
{
cevent
=
sctp_skb2event
(
pos
);
ctsn
=
cevent
->
sndrcvinfo
.
sinfo_tsn
;
...
...
@@ -590,7 +587,7 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
static
inline
void
sctp_ulpq_store_ordered
(
struct
sctp_ulpq
*
ulpq
,
struct
sctp_ulpevent
*
event
)
{
struct
sk_buff
*
pos
,
*
tmp
;
struct
sk_buff
*
pos
;
struct
sctp_ulpevent
*
cevent
;
__u16
sid
,
csid
;
__u16
ssn
,
cssn
;
...
...
@@ -601,7 +598,7 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
/* Find the right place in this list. We store them by
* stream ID and then by SSN.
*/
s
ctp_skb_for_each
(
pos
,
&
ulpq
->
lobby
,
tmp
)
{
s
kb_queue_walk
(
&
ulpq
->
lobby
,
pos
)
{
cevent
=
(
struct
sctp_ulpevent
*
)
pos
->
cb
;
csid
=
cevent
->
sndrcvinfo
.
sinfo_stream
;
cssn
=
cevent
->
sndrcvinfo
.
sinfo_ssn
;
...
...
@@ -786,9 +783,9 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, int priority)
SCTP_PARTIAL_DELIVERY_ABORTED
,
priority
);
if
(
ev
)
skb_queue_tail
(
&
sk
->
receive_queue
,
sctp_event2skb
(
ev
));
__
skb_queue_tail
(
&
sk
->
receive_queue
,
sctp_event2skb
(
ev
));
/* If there is data waiting, send it up the socket now. */
if
(
sctp_ulpq_clear_pd
(
ulpq
)
||
ev
)
wake_up_interruptible
(
sk
->
sleep
);
sk
->
data_ready
(
sk
,
0
);
}
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