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
c09d36c8
Commit
c09d36c8
authored
Jul 18, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-lksctp.bkbits.net/lksctp-2.5
into nuts.ninka.net:/home/davem/src/BK/sctp-2.5
parents
1d02c2c0
9bb68814
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
553 additions
and
442 deletions
+553
-442
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+20
-0
include/net/sctp/sm.h
include/net/sctp/sm.h
+2
-1
include/net/sctp/structs.h
include/net/sctp/structs.h
+6
-3
include/net/sctp/ulpevent.h
include/net/sctp/ulpevent.h
+3
-2
include/net/sctp/user.h
include/net/sctp/user.h
+123
-177
net/sctp/associola.c
net/sctp/associola.c
+3
-3
net/sctp/chunk.c
net/sctp/chunk.c
+2
-2
net/sctp/input.c
net/sctp/input.c
+1
-1
net/sctp/ipv6.c
net/sctp/ipv6.c
+100
-35
net/sctp/output.c
net/sctp/output.c
+25
-12
net/sctp/outqueue.c
net/sctp/outqueue.c
+6
-8
net/sctp/protocol.c
net/sctp/protocol.c
+16
-6
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+7
-3
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+1
-1
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+2
-2
net/sctp/socket.c
net/sctp/socket.c
+102
-78
net/sctp/transport.c
net/sctp/transport.c
+1
-0
net/sctp/ulpevent.c
net/sctp/ulpevent.c
+129
-103
net/sctp/ulpqueue.c
net/sctp/ulpqueue.c
+4
-5
No files found.
include/net/sctp/sctp.h
View file @
c09d36c8
...
...
@@ -588,6 +588,7 @@ struct sctp6_sock {
#endif
/* CONFIG_IPV6 */
#define sctp_sk(__sk) (&((struct sctp_sock *)__sk)->sctp)
#define sctp_opt2sk(__sp) &container_of(__sp, struct sctp_sock, sctp)->sk
/* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
...
...
@@ -611,4 +612,23 @@ int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
return
sk
->
sk_state
==
state
;
}
/* Map v4-mapped v6 address back to v4 address */
static
inline
void
sctp_v6_map_v4
(
union
sctp_addr
*
addr
)
{
addr
->
v4
.
sin_family
=
AF_INET
;
addr
->
v4
.
sin_port
=
addr
->
v6
.
sin6_port
;
addr
->
v4
.
sin_addr
.
s_addr
=
addr
->
v6
.
sin6_addr
.
s6_addr32
[
3
];
}
/* Map v4 address to v4-mapped v6 address */
static
inline
void
sctp_v4_map_v6
(
union
sctp_addr
*
addr
)
{
addr
->
v6
.
sin6_family
=
AF_INET6
;
addr
->
v6
.
sin6_port
=
addr
->
v4
.
sin_port
;
addr
->
v6
.
sin6_addr
.
s6_addr32
[
3
]
=
addr
->
v4
.
sin_addr
.
s_addr
;
addr
->
v6
.
sin6_addr
.
s6_addr32
[
0
]
=
0
;
addr
->
v6
.
sin6_addr
.
s6_addr32
[
1
]
=
0
;
addr
->
v6
.
sin6_addr
.
s6_addr32
[
2
]
=
htonl
(
0x0000ffff
);
}
#endif
/* __net_sctp_h__ */
include/net/sctp/sm.h
View file @
c09d36c8
...
...
@@ -231,7 +231,8 @@ struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
struct
sctp_chunk
*
sctp_make_ecne
(
const
struct
sctp_association
*
,
const
__u32
);
struct
sctp_chunk
*
sctp_make_sack
(
const
struct
sctp_association
*
);
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
);
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
);
struct
sctp_chunk
*
sctp_make_shutdown_ack
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
);
struct
sctp_chunk
*
sctp_make_shutdown_complete
(
const
struct
sctp_association
*
,
...
...
include/net/sctp/structs.h
View file @
c09d36c8
...
...
@@ -260,11 +260,13 @@ struct sctp_af {
struct
sock
*
sk
);
void
(
*
to_sk_daddr
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
int
(
*
addr_valid
)
(
union
sctp_addr
*
);
int
(
*
addr_valid
)
(
union
sctp_addr
*
,
struct
sctp_opt
*
);
sctp_scope_t
(
*
scope
)
(
union
sctp_addr
*
);
void
(
*
inaddr_any
)
(
union
sctp_addr
*
,
unsigned
short
);
int
(
*
is_any
)
(
const
union
sctp_addr
*
);
int
(
*
available
)
(
const
union
sctp_addr
*
);
int
(
*
available
)
(
union
sctp_addr
*
,
struct
sctp_opt
*
);
int
(
*
skb_iif
)
(
const
struct
sk_buff
*
sk
);
int
(
*
is_ce
)
(
const
struct
sk_buff
*
sk
);
void
(
*
seq_dump_addr
)(
struct
seq_file
*
seq
,
...
...
@@ -282,7 +284,7 @@ int sctp_register_af(struct sctp_af *);
struct
sctp_pf
{
void
(
*
event_msgname
)(
struct
sctp_ulpevent
*
,
char
*
,
int
*
);
void
(
*
skb_msgname
)
(
struct
sk_buff
*
,
char
*
,
int
*
);
int
(
*
af_supported
)
(
sa_family_t
);
int
(
*
af_supported
)
(
sa_family_t
,
struct
sctp_opt
*
);
int
(
*
cmp_addr
)
(
const
union
sctp_addr
*
,
const
union
sctp_addr
*
,
struct
sctp_opt
*
);
...
...
@@ -291,6 +293,7 @@ struct sctp_pf {
int
(
*
supported_addrs
)(
const
struct
sctp_opt
*
,
__u16
*
);
struct
sock
*
(
*
create_accept_sk
)
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
);
void
(
*
addr_v4map
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
struct
sctp_af
*
af
;
};
...
...
include/net/sctp/ulpevent.h
View file @
c09d36c8
...
...
@@ -40,6 +40,7 @@
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Sridhar Samudrala <sri@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.
...
...
@@ -53,7 +54,6 @@
* growing this structure as it is at the maximum limit now.
*/
struct
sctp_ulpevent
{
struct
sctp_association
*
asoc
;
struct
sctp_sndrcvinfo
sndrcvinfo
;
int
msg_flags
;
int
iif
;
...
...
@@ -72,9 +72,10 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
}
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
flags
,
int
gfp
);
struct
sctp_ulpevent
*
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
,
int
flags
);
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
,
int
flags
);
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
);
int
sctp_ulpevent_is_notification
(
const
struct
sctp_ulpevent
*
);
void
sctp_queue_purge_ulpevents
(
struct
sk_buff_head
*
list
);
struct
sctp_ulpevent
*
sctp_ulpevent_make_assoc_change
(
const
struct
sctp_association
*
asoc
,
...
...
include/net/sctp/user.h
View file @
c09d36c8
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
*
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2002 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
*
* This header represents the structures and constants needed to support
* the SCTP Extension to the Sockets API.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the SCTP Extension to the Sockets API.
*
* 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
*
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* 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.
*
* Boston, MA 02111-1307, USA.
*
* 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
*
* Written or modified by:
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
* R. Stewart <randall@sctp.chicago.il.us>
* K. Morneau <kmorneau@cisco.com>
...
...
@@ -41,61 +42,62 @@
* Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ryan Layer <rmlayer@us.ibm.com>
*
*
* Ardelle Fan <ardelle.fan@intel.com>
* Sridhar Samudrala <sri@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.
*/
#include <linux/types.h>
#include <linux/socket.h>
#ifndef __net_sctp_user_h__
#define __net_sctp_user_h__
#include <linux/types.h>
#include <linux/socket.h>
typedef
void
*
sctp_assoc_t
;
/* The following symbols come from the Sockets API Extensions for
* SCTP <draft-ietf-tsvwg-sctpsocket-0
4
.txt>.
* SCTP <draft-ietf-tsvwg-sctpsocket-0
7
.txt>.
*/
enum
sctp_optname
{
SCTP_RTOINFO
,
#define SCTP_RTOINFO SCTP_RTOINFO
SCTP_ASSOC
RTX
INFO
,
#define SCTP_ASSOC
RTXINFO SCTP_ASSOCRTX
INFO
SCTP_ASSOCINFO
,
#define SCTP_ASSOC
INFO SCTP_ASSOC
INFO
SCTP_INITMSG
,
#define SCTP_INITMSG SCTP_INITMSG
SCTP_
AUTO_CLOSE
,
#define SCTP_
AUTO_CLOSE SCTP_AUTO_CLOSE
SCTP_
SET_PRIMARY_ADDR
,
#define SCTP_
SET_PRIMARY_ADDR SCTP_SET_PRIMARY_ADDR
SCTP_
NODELAY
,
/* Get/set nodelay option. */
#define SCTP_
NODELAY SCTP_NODELAY
SCTP_
AUTOCLOSE
,
#define SCTP_
AUTOCLOSE SCTP_AUTOCLOSE
SCTP_SET_PEER_PRIMARY_ADDR
,
#define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR
SCTP_
SET_ADAPTATION_LAYER
,
#define SCTP_
SET_ADAPTATION_LAYER SCTP_SET_ADAPTATION_LAYE
R
SCTP_
SET_STREAM_TIMEOUTS
,
#define SCTP_
SET_STREAM_TIMEOUTS SCTP_SET_STREAM_TIMEOUTS
SCTP_
PRIMARY_ADDR
,
#define SCTP_
PRIMARY_ADDR SCTP_PRIMARY_ADD
R
SCTP_
ADAPTION_LAYER
,
#define SCTP_
ADAPTION_LAYER SCTP_ADAPTION_LAYER
SCTP_DISABLE_FRAGMENTS
,
#define SCTP_DISABLE_FRAGMENTS SCTP_DISABLE_FRAGMENTS
SCTP_SET_PEER_ADDR_PARAMS
,
#define SCTP_SET_PEER_ADDR_PARAMS SCTP_SET_PEER_ADDR_PARAMS
SCTP_GET_PEER_ADDR_PARAMS
,
#define SCTP_GET_PEER_ADDR_PARAMS SCTP_GET_PEER_ADDR_PARAMS
SCTP_PEER_ADDR_PARAMS
,
#define SCTP_PEER_ADDR_PARAMS SCTP_PEER_ADDR_PARAMS
SCTP_DEFAULT_SEND_PARAM
,
#define SCTP_DEFAULT_SEND_PARAM SCTP_DEFAULT_SEND_PARAM
SCTP_EVENTS
,
#define SCTP_EVENTS SCTP_EVENTS
SCTP_I_WANT_MAPPED_V4_ADDR
,
/* Turn on/off mapped v4 addresses */
#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR
SCTP_MAXSEG
,
/* Get/set maximum fragment. */
#define SCTP_MAXSEG SCTP_MAXSEG
SCTP_STATUS
,
#define SCTP_STATUS SCTP_STATUS
SCTP_GET_PEER_ADDR_INFO
,
#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
SCTP_SET_EVENTS
,
#define SCTP_SET_EVENTS SCTP_SET_EVENTS
SCTP_AUTOCLOSE
,
#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE
SCTP_SET_DEFAULT_SEND_PARAM
,
#define SCTP_SET_DEFAULT_SEND_PARAM SCTP_SET_DEFAULT_SEND_PARAM
SCTP_SOCKOPT_DEBUG_NAME
=
42
,
/* FIXME */
#define SCTP_SOCKOPT_DEBUG_NAME SCTP_SOCKOPT_DEBUG_NAME
SCTP_SOCKOPT_BINDX_ADD
,
/* BINDX requests for adding addresses. */
/* Internal Socket Options. Some of the sctp library functions are
* implemented using these socket options.
*/
SCTP_SOCKOPT_BINDX_ADD
=
100
,
/* BINDX requests for adding addresses. */
#define SCTP_SOCKOPT_BINDX_ADD SCTP_SOCKOPT_BINDX_ADD
SCTP_SOCKOPT_BINDX_REM
,
/* BINDX requests for removing addresses. */
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
...
...
@@ -109,29 +111,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
SCTP_I_WANT_MAPPED_V4_ADDR
,
/* Turn on/off mapped v4 addresses */
#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR
SCTP_MAXSEG
,
/* Get/set maximum fragment. */
#define SCTP_MAXSEG SCTP_MAXSEG
};
/*
* 5.2 SCTP msg_control Structures
*
* A key element of all SCTP-specific socket extensions is the use of
* ancillary data to specify and access SCTP-specific data via the
* struct msghdr's msg_control member used in sendmsg() and recvmsg().
* Fine-grained control over initialization and sending parameters are
* handled with ancillary data.
*
* Each ancillary data item is preceeded by a struct cmsghdr (see
* Section 5.1), which defines the function and purpose of the data
* contained in in the cmsg_data[] member.
*/
/*
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
*
...
...
@@ -152,7 +133,6 @@ struct sctp_initmsg {
__u16
sinit_max_init_timeo
;
};
/*
* 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
*
...
...
@@ -214,7 +194,6 @@ typedef enum sctp_cmsg_type {
* following format:
*
*/
struct
sctp_assoc_change
{
__u16
sac_type
;
__u16
sac_flags
;
...
...
@@ -267,11 +246,11 @@ struct sctp_paddr_change {
* event that happened to the address. They include:
*/
enum
sctp_spc_state
{
ADDRESS_AVAIL
ABLE
,
ADDRESS
_UNREACHABLE
,
ADDRESS
_REMOVED
,
ADDRESS
_ADDED
,
ADDRESS
_MADE_PRIM
,
SCTP_ADDR_REACH
ABLE
,
SCTP_ADDR
_UNREACHABLE
,
SCTP_ADDR
_REMOVED
,
SCTP_ADDR
_ADDED
,
SCTP_ADDR
_MADE_PRIM
,
};
...
...
@@ -290,7 +269,6 @@ struct sctp_remote_error {
__u16
sre_flags
;
__u32
sre_length
;
__u16
sre_error
;
__u16
sre_len
;
sctp_assoc_t
sre_assoc_id
;
__u8
sre_data
[
0
];
};
...
...
@@ -324,7 +302,6 @@ struct sctp_send_failed {
* Note that this does not necessarily mean that the
* data was (or was not) successfully delivered.
*/
enum
sctp_ssf_flags
{
SCTP_DATA_UNSENT
,
SCTP_DATA_SENT
,
...
...
@@ -336,7 +313,6 @@ enum sctp_ssf_flags {
* When a peer sends a SHUTDOWN, SCTP delivers this notification to
* inform the application that it should cease sending data.
*/
struct
sctp_shutdown_event
{
__u16
sse_type
;
__u16
sse_flags
;
...
...
@@ -355,8 +331,8 @@ struct sctp_adaption_event {
__u16
sai_type
;
__u16
sai_flags
;
__u32
sai_length
;
__u32
sai_adapt
ation_bits
;
sctp_assoc_t
s
se
_assoc_id
;
__u32
sai_adapt
ion_ind
;
sctp_assoc_t
s
ai
_assoc_id
;
};
/*
...
...
@@ -366,8 +342,7 @@ struct sctp_adaption_event {
* message this notification will be used to inidicate
* various events.
*/
struct
sctp_rcv_pdapi_event
{
struct
sctp_pdapi_event
{
__u16
pdapi_type
;
__u16
pdapi_flags
;
__u32
pdapi_length
;
...
...
@@ -404,14 +379,14 @@ union sctp_notification {
__u16
sn_type
;
/* Notification type. */
__u16
sn_flags
;
__u32
sn_length
;
}
h
;
}
sn_header
;
struct
sctp_assoc_change
sn_assoc_change
;
struct
sctp_paddr_change
sn_padr_change
;
struct
sctp_paddr_change
sn_pad
d
r_change
;
struct
sctp_remote_error
sn_remote_error
;
struct
sctp_send_failed
sn_send_failed
;
struct
sctp_shutdown_event
sn_shutdown_event
;
struct
sctp_adaption_event
sn_adaption_event
;
struct
sctp_
rcv_pdapi_event
sn_rcv
_pdapi_event
;
struct
sctp_
pdapi_event
sn
_pdapi_event
;
};
/* Section 5.3.1
...
...
@@ -447,76 +422,26 @@ typedef enum sctp_sn_error {
SCTP_PEER_FAULTY
,
}
sctp_sn_error_t
;
/*
*
* 7.1.14 Peer Address Parameters
*
* Applications can enable or disable heartbeats for any peer address
* of an association, modify an address's heartbeat interval, force a
* heartbeat to be sent immediately, and adjust the address's maximum
* number of retransmissions sent before an address is considered
* unreachable. The following structure is used to access and modify an
* address's parameters:
*/
struct
sctp_paddrparams
{
struct
sockaddr_storage
spp_address
;
__u32
spp_hbinterval
;
__u16
spp_pathmaxrxt
;
sctp_assoc_t
spp_assoc_id
;
};
/*
* 7.2.2 Peer Address Information
*
* Applications can retrieve information about a specific peer address
* of an association, including its reachability state, congestion
* window, and retransmission timer values. This information is
* read-only. The following structure is used to access this
* information:
*/
struct
sctp_paddrinfo
{
sctp_assoc_t
spinfo_assoc_id
;
struct
sockaddr_storage
spinfo_address
;
__s32
spinfo_state
;
__u32
spinfo_cwnd
;
__u32
spinfo_srtt
;
__u32
spinfo_rto
;
__u32
spinfo_mtu
;
};
/* Peer addresses's state. */
enum
sctp_spinfo_state
{
SCTP_INACTIVE
,
SCTP_ACTIVE
,
};
/*
* 7.1.1 Retransmission Timeout Parameters (SCTP_RTOINFO)
*
* The protocol parameters used to initialize and bound retransmission
* timeout (RTO) are tunable. See [SCTP] for more information on how
* these parameters are used in RTO calculation. The peer address
* parameter is ignored for TCP style socket.
* these parameters are used in RTO calculation.
*/
struct
sctp_rtoinfo
{
sctp_assoc_t
srto_assoc_id
;
__u32
srto_initial
;
__u32
srto_max
;
__u32
srto_min
;
sctp_assoc_t
srto_assoc_id
;
};
/*
* 7.1.2 Association
Retransmission Parameter (SCTP_ASSOCRTX
INFO)
* 7.1.2 Association
Parameters (SCTP_ASSOC
INFO)
*
* The protocol parameter used to set the number of retransmissions
* sent before an association is considered unreachable.
* See [SCTP] for more information on how this parameter is used. The
* peer address parameter is ignored for TCP style socket.
* This option is used to both examine and set various association and
* endpoint parameters.
*/
struct
sctp_assocparams
{
sctp_assoc_t
sasoc_assoc_id
;
__u16
sasoc_asocmaxrxt
;
...
...
@@ -527,31 +452,81 @@ struct sctp_assocparams {
};
/*
* 7.1.9 Set P
rimary Address (SCTP_SET
_PRIMARY_ADDR)
* 7.1.9 Set P
eer Primary Address (SCTP_SET_PEER
_PRIMARY_ADDR)
*
* Requests that the peer mark the enclosed address as the association
* primary. The enclosed address must be one of the association's
* locally bound addresses. The following structure is used to make a
* set primary request:
*/
struct
sctp_setprim
{
struct
sockaddr_storage
ssp_addr
;
sctp_assoc_t
ssp_assoc_id
;
struct
sctp_setpeerprim
{
sctp_assoc_t
sspp_assoc_id
;
struct
sockaddr_storage
sspp_addr
;
};
/*
* 7.1.10 Set P
eer Primary Address (SCTP_SET_PEER
_PRIMARY_ADDR)
* 7.1.10 Set P
rimary Address (SCTP
_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
* the association primary. The enclosed address must be one of the
* association peer's addresses. The following structure is used to
* make a set peer primary request:
*/
struct
sctp_prim
{
sctp_assoc_t
ssp_assoc_id
;
struct
sockaddr_storage
ssp_addr
;
};
struct
sctp_setpeerprim
{
struct
sockaddr_storage
sspp_addr
;
sctp_assoc_t
sspp_assoc_id
;
/*
* 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
*
* Requests that the local endpoint set the specified Adaption Layer
* Indication parameter for all future INIT and INIT-ACK exchanges.
*/
struct
sctp_setadaption
{
__u32
ssb_adaption_ind
;
};
/*
* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
*
* Applications can enable or disable heartbeats for any peer address
* of an association, modify an address's heartbeat interval, force a
* heartbeat to be sent immediately, and adjust the address's maximum
* number of retransmissions sent before an address is considered
* unreachable. The following structure is used to access and modify an
* address's parameters:
*/
struct
sctp_paddrparams
{
sctp_assoc_t
spp_assoc_id
;
struct
sockaddr_storage
spp_address
;
__u32
spp_hbinterval
;
__u16
spp_pathmaxrxt
;
};
/*
* 7.2.2 Peer Address Information
*
* Applications can retrieve information about a specific peer address
* of an association, including its reachability state, congestion
* window, and retransmission timer values. This information is
* read-only. The following structure is used to access this
* information:
*/
struct
sctp_paddrinfo
{
sctp_assoc_t
spinfo_assoc_id
;
struct
sockaddr_storage
spinfo_address
;
__s32
spinfo_state
;
__u32
spinfo_cwnd
;
__u32
spinfo_srtt
;
__u32
spinfo_rto
;
__u32
spinfo_mtu
;
};
/* Peer addresses's state. */
enum
sctp_spinfo_state
{
SCTP_INACTIVE
,
SCTP_ACTIVE
,
};
/*
...
...
@@ -575,34 +550,8 @@ struct sctp_status {
struct
sctp_paddrinfo
sstat_primary
;
};
/*
* 7.1.12 Set Adaption Layer Indicator
*
* Requests that the local endpoint set the specified Adaption Layer
* Indication parameter for all future
* INIT and INIT-ACK exchanges.
*/
struct
sctp_setadaption
{
__u32
ssb_adaption_ind
;
};
/*
* 7.1.12 Set default message time outs (SCTP_SET_STREAM_TIMEOUTS)
*
* This option requests that the requested stream apply a
* default time-out for messages in queue.
*/
struct
sctp_setstrm_timeout
{
sctp_assoc_t
ssto_assoc_id
;
__u32
ssto_timeout
;
__u16
ssto_streamid_start
;
__u16
ssto_streamid_end
;
};
/*
* 8.3 8.5 get all peer/local addresses on a socket
* 8.3
,
8.5 get all peer/local addresses on a socket
* This parameter struct is for getsockopt
*/
struct
sctp_getaddrs
{
...
...
@@ -624,8 +573,8 @@ enum sctp_msg_flags {
* The flags parameter is formed from the bitwise OR of zero or more of the
* following currently defined flags:
*/
#define BINDX_ADD_ADDR 0x01
#define BINDX_REM_ADDR 0x02
#define
SCTP_
BINDX_ADD_ADDR 0x01
#define
SCTP_
BINDX_REM_ADDR 0x02
/* This is the structure that is passed as an argument(optval) to
* getsockopt(SCTP_SOCKOPT_PEELOFF).
...
...
@@ -636,6 +585,3 @@ typedef struct {
}
sctp_peeloff_arg_t
;
#endif
/* __net_sctp_user_h__ */
net/sctp/associola.c
View file @
c09d36c8
...
...
@@ -556,12 +556,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
switch
(
command
)
{
case
SCTP_TRANSPORT_UP
:
transport
->
active
=
SCTP_ACTIVE
;
spc_state
=
ADDRESS_AVAIL
ABLE
;
spc_state
=
SCTP_ADDR_REACH
ABLE
;
break
;
case
SCTP_TRANSPORT_DOWN
:
transport
->
active
=
SCTP_INACTIVE
;
spc_state
=
ADDRESS
_UNREACHABLE
;
spc_state
=
SCTP_ADDR
_UNREACHABLE
;
break
;
default:
...
...
@@ -877,7 +877,7 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
/* Delete the association from the old endpoint's list of
* associations.
*/
list_del
(
&
assoc
->
asocs
);
list_del
_init
(
&
assoc
->
asocs
);
/* Decrement the backlog value for a TCP-style socket. */
if
(
sctp_style
(
oldsk
,
TCP
))
...
...
net/sctp/chunk.c
View file @
c09d36c8
...
...
@@ -85,7 +85,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
/* Release all references. */
list_for_each_safe
(
pos
,
temp
,
&
msg
->
chunks
)
{
list_del
(
pos
);
list_del
_init
(
pos
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
/* Check whether we _really_ need to notify. */
if
(
notify
<
0
)
{
...
...
@@ -294,7 +294,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
errout:
list_for_each_safe
(
pos
,
temp
,
&
msg
->
chunks
)
{
list_del
(
pos
);
list_del
_init
(
pos
);
chunk
=
list_entry
(
pos
,
struct
sctp_chunk
,
frag_list
);
sctp_chunk_free
(
chunk
);
}
...
...
net/sctp/input.c
View file @
c09d36c8
...
...
@@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb)
* IP broadcast addresses cannot be used in an SCTP transport
* address."
*/
if
(
!
af
->
addr_valid
(
&
src
)
||
!
af
->
addr_valid
(
&
dest
))
if
(
!
af
->
addr_valid
(
&
src
,
NULL
)
||
!
af
->
addr_valid
(
&
dest
,
NULL
))
goto
discard_it
;
asoc
=
__sctp_rcv_lookup
(
skb
,
&
src
,
&
dest
,
&
transport
);
...
...
net/sctp/ipv6.c
View file @
c09d36c8
...
...
@@ -2,6 +2,7 @@
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
* Copyright (c) 2002-2003 International Business Machines, Corp.
* Copyright (c) 2002-2003 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -15,7 +16,7 @@
*
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
*
************************
*
************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
...
...
@@ -32,14 +33,15 @@
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Le Yanqun
<yanqun.le@nokia.com>
* Le Yanqun
<yanqun.le@nokia.com>
* Hui Huang <hui.huang@nokia.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Sridhar Samudrala <sri@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Based on:
*
linux/net/ipv6/tcp_ipv6.c
*
linux/net/ipv6/tcp_ipv6.c
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -172,7 +174,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
SCTP_DEBUG_PRINTK
(
"%s: skb:%p, len:%d, "
"src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x
\n
"
,
__FUNCTION__
,
skb
,
skb
->
len
,
__FUNCTION__
,
skb
,
skb
->
len
,
NIP6
(
fl
.
fl6_src
),
NIP6
(
fl
.
fl6_dst
));
SCTP_INC_STATS
(
SctpOutSCTPPacks
);
...
...
@@ -192,6 +194,9 @@ struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
memset
(
&
fl
,
0
,
sizeof
(
fl
));
ipv6_addr_copy
(
&
fl
.
fl6_dst
,
&
daddr
->
v6
.
sin6_addr
);
if
(
ipv6_addr_type
(
&
daddr
->
v6
.
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
)
fl
.
oif
=
daddr
->
v6
.
sin6_scope_id
;
SCTP_DEBUG_PRINTK
(
"%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
,
__FUNCTION__
,
NIP6
(
fl
.
fl6_dst
));
...
...
@@ -370,13 +375,28 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
/* Initialize sk->sk_rcv_saddr from sctp_addr. */
static
void
sctp_v6_to_sk_saddr
(
union
sctp_addr
*
addr
,
struct
sock
*
sk
)
{
inet6_sk
(
sk
)
->
rcv_saddr
=
addr
->
v6
.
sin6_addr
;
if
(
addr
->
sa
.
sa_family
==
AF_INET
&&
sctp_sk
(
sk
)
->
v4mapped
)
{
inet6_sk
(
sk
)
->
rcv_saddr
.
s6_addr32
[
0
]
=
0
;
inet6_sk
(
sk
)
->
rcv_saddr
.
s6_addr32
[
1
]
=
0
;
inet6_sk
(
sk
)
->
rcv_saddr
.
s6_addr32
[
2
]
=
htonl
(
0x0000ffff
);
inet6_sk
(
sk
)
->
rcv_saddr
.
s6_addr32
[
3
]
=
addr
->
v4
.
sin_addr
.
s_addr
;
}
else
{
inet6_sk
(
sk
)
->
rcv_saddr
=
addr
->
v6
.
sin6_addr
;
}
}
/* Initialize sk->sk_daddr from sctp_addr. */
static
void
sctp_v6_to_sk_daddr
(
union
sctp_addr
*
addr
,
struct
sock
*
sk
)
{
inet6_sk
(
sk
)
->
daddr
=
addr
->
v6
.
sin6_addr
;
if
(
addr
->
sa
.
sa_family
==
AF_INET
&&
sctp_sk
(
sk
)
->
v4mapped
)
{
inet6_sk
(
sk
)
->
daddr
.
s6_addr32
[
0
]
=
0
;
inet6_sk
(
sk
)
->
daddr
.
s6_addr32
[
1
]
=
0
;
inet6_sk
(
sk
)
->
daddr
.
s6_addr32
[
2
]
=
htonl
(
0x0000ffff
);
inet6_sk
(
sk
)
->
daddr
.
s6_addr32
[
3
]
=
addr
->
v4
.
sin_addr
.
s_addr
;
}
else
{
inet6_sk
(
sk
)
->
daddr
=
addr
->
v6
.
sin6_addr
;
}
}
/* Initialize a sctp_addr from a dst_entry. */
...
...
@@ -390,13 +410,30 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
}
/* Compare addresses exactly.
*
FIXME: v4-mapped-v6
.
*
v4-mapped-v6 is also in consideration
.
*/
static
int
sctp_v6_cmp_addr
(
const
union
sctp_addr
*
addr1
,
const
union
sctp_addr
*
addr2
)
{
if
(
addr1
->
sa
.
sa_family
!=
addr2
->
sa
.
sa_family
)
if
(
addr1
->
sa
.
sa_family
!=
addr2
->
sa
.
sa_family
)
{
if
(
addr1
->
sa
.
sa_family
==
AF_INET
&&
addr2
->
sa
.
sa_family
==
AF_INET6
&&
IPV6_ADDR_MAPPED
==
ipv6_addr_type
(
&
addr2
->
v6
.
sin6_addr
))
{
if
(
addr2
->
v6
.
sin6_port
==
addr1
->
v4
.
sin_port
&&
addr2
->
v6
.
sin6_addr
.
s6_addr32
[
3
]
==
addr1
->
v4
.
sin_addr
.
s_addr
)
return
1
;
}
if
(
addr2
->
sa
.
sa_family
==
AF_INET
&&
addr1
->
sa
.
sa_family
==
AF_INET6
&&
IPV6_ADDR_MAPPED
==
ipv6_addr_type
(
&
addr1
->
v6
.
sin6_addr
))
{
if
(
addr1
->
v6
.
sin6_port
==
addr2
->
v4
.
sin_port
&&
addr1
->
v6
.
sin6_addr
.
s6_addr32
[
3
]
==
addr2
->
v4
.
sin_addr
.
s_addr
)
return
1
;
}
return
0
;
}
if
(
ipv6_addr_cmp
(
&
addr1
->
v6
.
sin6_addr
,
&
addr2
->
v6
.
sin6_addr
))
return
0
;
/* If this is a linklocal address, compare the scope_id. */
...
...
@@ -427,7 +464,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
}
/* Should this be available for binding? */
static
int
sctp_v6_available
(
const
union
sctp_addr
*
addr
)
static
int
sctp_v6_available
(
union
sctp_addr
*
addr
,
struct
sctp_opt
*
sp
)
{
int
type
;
struct
in6_addr
*
in6
=
(
struct
in6_addr
*
)
&
addr
->
v6
.
sin6_addr
;
...
...
@@ -435,6 +472,14 @@ static int sctp_v6_available(const union sctp_addr *addr)
type
=
ipv6_addr_type
(
in6
);
if
(
IPV6_ADDR_ANY
==
type
)
return
1
;
if
(
type
==
IPV6_ADDR_MAPPED
)
{
if
(
sp
&&
!
sp
->
v4mapped
)
return
0
;
if
(
sp
&&
ipv6_only_sock
(
sctp_opt2sk
(
sp
)))
return
0
;
sctp_v6_map_v4
(
addr
);
return
sctp_get_af_specific
(
AF_INET
)
->
available
(
addr
,
sp
);
}
if
(
!
(
type
&
IPV6_ADDR_UNICAST
))
return
0
;
...
...
@@ -448,11 +493,22 @@ static int sctp_v6_available(const union sctp_addr *addr)
* Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast.
*/
static
int
sctp_v6_addr_valid
(
union
sctp_addr
*
addr
)
static
int
sctp_v6_addr_valid
(
union
sctp_addr
*
addr
,
struct
sctp_opt
*
sp
)
{
int
ret
=
ipv6_addr_type
(
&
addr
->
v6
.
sin6_addr
);
/* FIXME: v4-mapped-v6 address support. */
/* Support v4-mapped-v6 address. */
if
(
ret
==
IPV6_ADDR_MAPPED
)
{
/* Note: This routine is used in input, so v4-mapped-v6
* are disallowed here when there is no sctp_opt.
*/
if
(
!
sp
||
!
sp
->
v4mapped
)
return
0
;
if
(
sp
&&
ipv6_only_sock
(
sctp_opt2sk
(
sp
)))
return
0
;
sctp_v6_map_v4
(
addr
);
return
sctp_get_af_specific
(
AF_INET
)
->
addr_valid
(
addr
,
sp
);
}
/* Is this a non-unicast address */
if
(
!
(
ret
&
IPV6_ADDR_UNICAST
))
...
...
@@ -536,7 +592,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp
->
saddr
=
np
->
saddr
;
newnp
->
rcv_saddr
=
np
->
rcv_saddr
;
newinet
->
dport
=
htons
(
asoc
->
peer
.
port
);
newnp
->
daddr
=
asoc
->
peer
.
primary_addr
.
v6
.
sin6_addr
;
sctp_v6_to_sk_daddr
(
&
asoc
->
peer
.
primary_addr
,
newsk
)
;
/* Init the ipv4 part of the socket since we can have sockets
* using v6 API for ipv4.
...
...
@@ -566,6 +622,13 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
return
newsk
;
}
/* Map v4 address to mapped v6 address */
static
void
sctp_v6_addr_v4map
(
struct
sctp_opt
*
sp
,
union
sctp_addr
*
addr
)
{
if
(
sp
->
v4mapped
&&
AF_INET
==
addr
->
sa
.
sa_family
)
sctp_v4_map_v6
(
addr
);
}
/* Where did this skb come from? */
static
int
sctp_v6_skb_iif
(
const
struct
sk_buff
*
skb
)
{
...
...
@@ -606,25 +669,28 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
if
(
msgname
)
{
union
sctp_addr
*
addr
;
struct
sctp_association
*
asoc
;
asoc
=
event
->
sndrcvinfo
.
sinfo_assoc_id
;
sctp_inet6_msgname
(
msgname
,
addrlen
);
sin6
=
(
struct
sockaddr_in6
*
)
msgname
;
sin6
->
sin6_port
=
htons
(
event
->
asoc
->
peer
.
port
);
addr
=
&
event
->
asoc
->
peer
.
primary_addr
;
sin6
->
sin6_port
=
htons
(
asoc
->
peer
.
port
);
addr
=
&
asoc
->
peer
.
primary_addr
;
/* Note: If we go to a common v6 format, this code
* will change.
*/
/* Map ipv4 address into v4-mapped-on-v6 address. */
if
(
AF_INET
==
addr
->
sa
.
sa_family
)
{
/* FIXME: Easy, but there was no way to test this
* yet.
*/
if
(
sctp_sk
(
asoc
->
base
.
sk
)
->
v4mapped
&&
AF_INET
==
addr
->
sa
.
sa_family
)
{
sctp_v4_map_v6
((
union
sctp_addr
*
)
sin6
);
sin6
->
sin6_addr
.
s6_addr32
[
3
]
=
addr
->
v4
.
sin_addr
.
s_addr
;
return
;
}
sin6from
=
&
event
->
asoc
->
peer
.
primary_addr
.
v6
;
sin6from
=
&
asoc
->
peer
.
primary_addr
.
v6
;
ipv6_addr_copy
(
&
sin6
->
sin6_addr
,
&
sin6from
->
sin6_addr
);
if
(
ipv6_addr_type
(
&
sin6
->
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
)
sin6
->
sin6_scope_id
=
sin6from
->
sin6_scope_id
;
...
...
@@ -644,16 +710,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
sh
=
(
struct
sctphdr
*
)
skb
->
h
.
raw
;
sin6
->
sin6_port
=
sh
->
source
;
/*
FIXME:
Map ipv4 address into v4-mapped-on-v6 address. */
if
(
__constant_htons
(
ETH_P_IP
)
==
skb
->
protocol
)
{
/* FIXME: The latest I-D added options for two
* behaviors.
*/
/* Map ipv4 address into v4-mapped-on-v6 address. */
if
(
sctp_sk
(
skb
->
sk
)
->
v4mapped
&&
skb
->
nh
.
iph
->
version
==
4
)
{
sctp_v4_map_v6
((
union
sctp_addr
*
)
sin6
);
sin6
->
sin6_addr
.
s6_addr32
[
3
]
=
skb
->
nh
.
iph
->
saddr
;
return
;
}
/* Otherwise, just copy the v6 address. */
ipv6_addr_copy
(
&
sin6
->
sin6_addr
,
&
skb
->
nh
.
ipv6h
->
saddr
);
if
(
ipv6_addr_type
(
&
sin6
->
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
)
{
struct
sctp_ulpevent
*
ev
=
sctp_skb2event
(
skb
);
...
...
@@ -663,16 +728,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
}
/* Do we support this AF? */
static
int
sctp_inet6_af_supported
(
sa_family_t
family
)
static
int
sctp_inet6_af_supported
(
sa_family_t
family
,
struct
sctp_opt
*
sp
)
{
/* FIXME: v4-mapped-v6 addresses. The I-D is still waffling
* on what to do with sockaddr formats for PF_INET6 sockets.
* For now assume we'll support both.
*/
switch
(
family
)
{
case
AF_INET6
:
case
AF_INET
:
return
1
;
/* v4-mapped-v6 addresses */
case
AF_INET
:
if
(
!
__ipv6_only_sock
(
sctp_opt2sk
(
sp
))
&&
sp
->
v4mapped
)
return
1
;
default:
return
0
;
}
...
...
@@ -716,7 +780,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
else
{
struct
sock
*
sk
;
int
type
=
ipv6_addr_type
(
&
addr
->
v6
.
sin6_addr
);
sk
=
&
container_of
(
opt
,
struct
sctp6_sock
,
sctp
)
->
sk
;
sk
=
sctp_opt2sk
(
opt
)
;
if
(
type
&
IPV6_ADDR_LINKLOCAL
)
{
/* Note: Behavior similar to af_inet6.c:
* 1) Overrides previous bound_dev_if
...
...
@@ -730,7 +794,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
}
af
=
opt
->
pf
->
af
;
}
return
af
->
available
(
addr
);
return
af
->
available
(
addr
,
opt
);
}
/* Verify that the provided sockaddr looks bindable. Common verification,
...
...
@@ -746,7 +810,7 @@ static int sctp_inet6_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
else
{
struct
sock
*
sk
;
int
type
=
ipv6_addr_type
(
&
addr
->
v6
.
sin6_addr
);
sk
=
&
container_of
(
opt
,
struct
sctp6_sock
,
sctp
)
->
sk
;
sk
=
sctp_opt2sk
(
opt
)
;
if
(
type
&
IPV6_ADDR_LINKLOCAL
)
{
/* Note: Behavior similar to af_inet6.c:
* 1) Overrides previous bound_dev_if
...
...
@@ -863,6 +927,7 @@ static struct sctp_pf sctp_pf_inet6_specific = {
.
send_verify
=
sctp_inet6_send_verify
,
.
supported_addrs
=
sctp_inet6_supported_addrs
,
.
create_accept_sk
=
sctp_v6_create_accept_sk
,
.
addr_v4map
=
sctp_v6_addr_v4map
,
.
af
=
&
sctp_ipv6_specific
,
};
...
...
net/sctp/output.c
View file @
c09d36c8
...
...
@@ -97,6 +97,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
packet
->
source_port
=
sport
;
packet
->
destination_port
=
dport
;
skb_queue_head_init
(
&
packet
->
chunks
);
packet
->
size
=
SCTP_IP_OVERHEAD
;
packet
->
vtag
=
0
;
packet
->
ecn_capable
=
0
;
packet
->
get_prepend_chunk
=
NULL
;
...
...
@@ -219,9 +220,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
/* Both control chunks and data chunks with TSNs are
* non-fragmentable.
*/
if
(
packet_empty
)
{
/* We no longer do refragmentation at all.
if
(
packet_empty
||
!
sctp_chunk_is_data
(
chunk
))
{
/* We no longer do re-fragmentation.
* Just fragment at the IP layer, if we
* actually hit this condition
*/
...
...
@@ -229,7 +229,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
packet
->
ipfragok
=
1
;
goto
append
;
}
else
{
/* !packet_empty */
}
else
{
retval
=
SCTP_XMIT_PMTU_FULL
;
goto
finish
;
}
...
...
@@ -283,20 +283,18 @@ int sctp_packet_transmit(struct sctp_packet *packet)
__u8
has_data
=
0
;
struct
dst_entry
*
dst
;
/* Do NOT generate a chunkless packet... */
if
(
skb_queue_empty
(
&
packet
->
chunks
))
/* Do NOT generate a chunkless packet. */
chunk
=
(
struct
sctp_chunk
*
)
skb_peek
(
&
packet
->
chunks
);
if
(
unlikely
(
!
chunk
))
return
err
;
/* Set up convenience variables... */
chunk
=
(
struct
sctp_chunk
*
)
(
packet
->
chunks
.
next
);
sk
=
chunk
->
skb
->
sk
;
/* Allocate the new skb. */
nskb
=
dev_alloc_skb
(
packet
->
size
);
if
(
!
nskb
)
{
err
=
-
ENOMEM
;
goto
out
;
}
if
(
!
nskb
)
goto
nomem
;
/* Make sure the outbound skb has enough header room reserved. */
skb_reserve
(
nskb
,
SCTP_IP_OVERHEAD
);
...
...
@@ -468,9 +466,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
if
(
!
nskb
->
dst
)
goto
no_route
;
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet*** skb len
gth
%d
\n
"
,
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet*** skb len %d
\n
"
,
nskb
->
len
);
(
*
tp
->
af_specific
->
sctp_xmit
)(
nskb
,
tp
,
packet
->
ipfragok
);
out:
packet
->
size
=
SCTP_IP_OVERHEAD
;
return
err
;
...
...
@@ -486,7 +486,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* required.
*/
/* err = -EHOSTUNREACH; */
err:
/* Control chunks are unreliable so just drop them. DATA chunks
* will get resent or dropped later.
*/
while
((
chunk
=
(
struct
sctp_chunk
*
)
__skb_dequeue
(
&
packet
->
chunks
)))
{
if
(
!
sctp_chunk_is_data
(
chunk
))
sctp_chunk_free
(
chunk
);
}
goto
out
;
nomem:
err
=
-
ENOMEM
;
printk
(
"%s alloc_skb failed.
\n
"
,
__FUNCTION__
);
goto
err
;
}
/********************************************************************
...
...
net/sctp/outqueue.c
View file @
c09d36c8
...
...
@@ -258,7 +258,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
/* Throw away chunks that have been gap ACKed. */
list_for_each_safe
(
lchunk
,
temp
,
&
q
->
sacked
)
{
list_del
(
lchunk
);
list_del
_init
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
...
...
@@ -267,7 +267,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
/* Throw away any chunks in the retransmit queue. */
list_for_each_safe
(
lchunk
,
temp
,
&
q
->
retransmit
)
{
list_del
(
lchunk
);
list_del
_init
(
lchunk
);
chunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
sctp_datamsg_fail
(
chunk
,
q
->
error
);
...
...
@@ -445,7 +445,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
/* Move the chunk to the retransmit queue. The chunks
* on the retransmit queue is always kept in order.
*/
list_del
(
lchunk
);
list_del
_init
(
lchunk
);
sctp_retransmit_insert
(
lchunk
,
q
);
}
}
...
...
@@ -1007,7 +1007,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
struct
sctp_association
*
asoc
=
q
->
asoc
;
struct
sctp_transport
*
transport
;
struct
sctp_chunk
*
tchunk
;
struct
list_head
*
lchunk
,
*
transport_list
,
*
pos
;
struct
list_head
*
lchunk
,
*
transport_list
,
*
pos
,
*
temp
;
sctp_sack_variable_t
*
frags
=
sack
->
variable
;
__u32
sack_ctsn
,
ctsn
,
tsn
;
__u32
highest_tsn
,
highest_new_tsn
;
...
...
@@ -1115,14 +1115,12 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
"%p is 0x%x.
\n
"
,
__FUNCTION__
,
asoc
,
ctsn
);
/* Throw away stuff rotting on the sack queue. */
list_for_each
(
lchunk
,
&
q
->
sacked
)
{
list_for_each
_safe
(
lchunk
,
temp
,
&
q
->
sacked
)
{
tchunk
=
list_entry
(
lchunk
,
struct
sctp_chunk
,
transmitted_list
);
tsn
=
ntohl
(
tchunk
->
subh
.
data_hdr
->
tsn
);
if
(
TSN_lte
(
tsn
,
ctsn
))
{
lchunk
=
lchunk
->
prev
;
if
(
TSN_lte
(
tsn
,
ctsn
))
sctp_chunk_free
(
tchunk
);
}
}
/* ii) Set rwnd equal to the newly received a_rwnd minus the
...
...
net/sctp/protocol.c
View file @
c09d36c8
...
...
@@ -340,7 +340,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
* Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast.
*/
static
int
sctp_v4_addr_valid
(
union
sctp_addr
*
addr
)
static
int
sctp_v4_addr_valid
(
union
sctp_addr
*
addr
,
struct
sctp_opt
*
sp
)
{
/* Is this a non-unicast address or a unusable SCTP address? */
if
(
IS_IPV4_UNUSABLE_ADDRESS
(
&
addr
->
v4
.
sin_addr
.
s_addr
))
...
...
@@ -350,7 +350,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr)
}
/* Should this be available for binding? */
static
int
sctp_v4_available
(
const
union
sctp_addr
*
addr
)
static
int
sctp_v4_available
(
union
sctp_addr
*
addr
,
struct
sctp_opt
*
sp
)
{
int
ret
=
inet_addr_type
(
addr
->
v4
.
sin_addr
.
s_addr
);
...
...
@@ -580,6 +580,12 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
return
newsk
;
}
/* Map address, empty for v4 family */
static
void
sctp_v4_addr_v4map
(
struct
sctp_opt
*
sp
,
union
sctp_addr
*
addr
)
{
/* Empty */
}
/* Dump the v4 addr to the seq file. */
static
void
sctp_v4_seq_dump_addr
(
struct
seq_file
*
seq
,
union
sctp_addr
*
addr
)
{
...
...
@@ -685,10 +691,13 @@ static void sctp_inet_event_msgname(struct sctp_ulpevent *event, char *msgname,
struct
sockaddr_in
*
sin
,
*
sinfrom
;
if
(
msgname
)
{
struct
sctp_association
*
asoc
;
asoc
=
event
->
sndrcvinfo
.
sinfo_assoc_id
;
sctp_inet_msgname
(
msgname
,
addr_len
);
sin
=
(
struct
sockaddr_in
*
)
msgname
;
sinfrom
=
&
event
->
asoc
->
peer
.
primary_addr
.
v4
;
sin
->
sin_port
=
htons
(
event
->
asoc
->
peer
.
port
);
sinfrom
=
&
asoc
->
peer
.
primary_addr
.
v4
;
sin
->
sin_port
=
htons
(
asoc
->
peer
.
port
);
sin
->
sin_addr
.
s_addr
=
sinfrom
->
sin_addr
.
s_addr
;
}
}
...
...
@@ -709,7 +718,7 @@ static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len)
}
/* Do we support this AF? */
static
int
sctp_inet_af_supported
(
sa_family_t
family
)
static
int
sctp_inet_af_supported
(
sa_family_t
family
,
struct
sctp_opt
*
sp
)
{
/* PF_INET only supports AF_INET addresses. */
return
(
AF_INET
==
family
);
...
...
@@ -737,7 +746,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
*/
static
int
sctp_inet_bind_verify
(
struct
sctp_opt
*
opt
,
union
sctp_addr
*
addr
)
{
return
sctp_v4_available
(
addr
);
return
sctp_v4_available
(
addr
,
opt
);
}
/* Verify that sockaddr looks sendable. Common verification has already
...
...
@@ -783,6 +792,7 @@ static struct sctp_pf sctp_pf_inet = {
.
send_verify
=
sctp_inet_send_verify
,
.
supported_addrs
=
sctp_inet_supported_addrs
,
.
create_accept_sk
=
sctp_v4_create_accept_sk
,
.
addr_v4map
=
sctp_v4_addr_v4map
,
.
af
=
&
sctp_ipv4_specific
,
};
...
...
net/sctp/sm_make_chunk.c
View file @
c09d36c8
...
...
@@ -667,7 +667,8 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
}
/* Make a SHUTDOWN chunk. */
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
)
struct
sctp_chunk
*
sctp_make_shutdown
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
)
{
struct
sctp_chunk
*
retval
;
sctp_shutdownhdr_t
shut
;
...
...
@@ -683,6 +684,9 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc)
retval
->
subh
.
shutdown_hdr
=
sctp_addto_chunk
(
retval
,
sizeof
(
shut
),
&
shut
);
if
(
chunk
)
retval
->
transport
=
chunk
->
transport
;
nodata:
return
retval
;
}
...
...
@@ -1089,7 +1093,7 @@ void sctp_chunk_free(struct sctp_chunk *chunk)
{
/* Make sure that we are not on any list. */
skb_unlink
((
struct
sk_buff
*
)
chunk
);
list_del
(
&
chunk
->
transmitted_list
);
list_del
_init
(
&
chunk
->
transmitted_list
);
/* Release our reference on the message tracker. */
if
(
chunk
->
msg
)
...
...
@@ -1850,7 +1854,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
/* Release the transport structures. */
list_for_each_safe
(
pos
,
temp
,
&
asoc
->
peer
.
transport_addr_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
list_del
(
pos
);
list_del
_init
(
pos
);
sctp_transport_free
(
transport
);
}
nomem:
...
...
net/sctp/sm_sideeffect.c
View file @
c09d36c8
...
...
@@ -962,7 +962,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
asoc
->
overall_error_count
=
0
;
/* Generate a SHUTDOWN chunk. */
new_obj
=
sctp_make_shutdown
(
asoc
);
new_obj
=
sctp_make_shutdown
(
asoc
,
chunk
);
if
(
!
new_obj
)
goto
nomem
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
...
...
net/sctp/sm_statefuns.c
View file @
c09d36c8
...
...
@@ -3862,7 +3862,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
* in the Cumulative TSN Ack field the last sequential TSN it
* has received from the peer.
*/
reply
=
sctp_make_shutdown
(
asoc
);
reply
=
sctp_make_shutdown
(
asoc
,
NULL
);
if
(
!
reply
)
goto
nomem
;
...
...
@@ -4179,7 +4179,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
switch
(
asoc
->
state
)
{
case
SCTP_STATE_SHUTDOWN_SENT
:
reply
=
sctp_make_shutdown
(
asoc
);
reply
=
sctp_make_shutdown
(
asoc
,
NULL
);
break
;
case
SCTP_STATE_SHUTDOWN_ACK_SENT
:
...
...
net/sctp/socket.c
View file @
c09d36c8
...
...
@@ -156,6 +156,9 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
if
(
id_asoc
&&
(
id_asoc
!=
addr_asoc
))
return
NULL
;
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sctp_sk
(
sk
),
(
union
sctp_addr
*
)
addr
);
return
transport
;
}
...
...
@@ -206,7 +209,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt,
return
NULL
;
/* Does this PF support this AF? */
if
(
!
opt
->
pf
->
af_supported
(
addr
->
sa
.
sa_family
))
if
(
!
opt
->
pf
->
af_supported
(
addr
->
sa
.
sa_family
,
opt
))
return
NULL
;
/* If we get this far, af is valid. */
...
...
@@ -365,15 +368,15 @@ static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs,
SCTP_DEBUG_PRINTK
(
"__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, "
"flags: %s)
\n
"
,
sk
,
addrs
,
addrcnt
,
(
BINDX_ADD_ADDR
==
flags
)
?
"ADD"
:
((
BINDX_REM_ADDR
==
flags
)
?
"REM"
:
"BOGUS"
));
(
SCTP_
BINDX_ADD_ADDR
==
flags
)
?
"ADD"
:
((
SCTP_
BINDX_REM_ADDR
==
flags
)
?
"REM"
:
"BOGUS"
));
switch
(
flags
)
{
case
BINDX_ADD_ADDR
:
case
SCTP_
BINDX_ADD_ADDR
:
retval
=
sctp_bindx_add
(
sk
,
addrs
,
addrcnt
);
break
;
case
BINDX_REM_ADDR
:
case
SCTP_
BINDX_REM_ADDR
:
retval
=
sctp_bindx_rem
(
sk
,
addrs
,
addrcnt
);
break
;
...
...
@@ -768,8 +771,8 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
}
/* Clean up any skbs sitting on the receive queue. */
s
kb_queue_purge
(
&
sk
->
sk_receive_queue
);
s
kb_queue_purge
(
&
sctp_sk
(
sk
)
->
pd_lobby
);
s
ctp_queue_purge_ulpevents
(
&
sk
->
sk_receive_queue
);
s
ctp_queue_purge_ulpevents
(
&
sctp_sk
(
sk
)
->
pd_lobby
);
/* On a TCP-style socket, block for at most linger_time if set. */
if
(
sctp_style
(
sk
,
TCP
)
&&
timeout
)
...
...
@@ -1342,10 +1345,10 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
/* When only partial message is copied to the user, increase
* rwnd by that amount. If all the data in the skb is read,
* rwnd is updated when the skb's destructor is called via
* sctp_ulpevent_free().
* rwnd is updated when the event is freed.
*/
sctp_assoc_rwnd_increase
(
event
->
asoc
,
copied
);
sctp_assoc_rwnd_increase
(
event
->
sndrcvinfo
.
sinfo_assoc_id
,
copied
);
goto
out
;
}
else
if
((
event
->
msg_flags
&
MSG_NOTIFICATION
)
||
(
event
->
msg_flags
&
MSG_EOR
))
...
...
@@ -1354,7 +1357,18 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
msg
->
msg_flags
&=
~
MSG_EOR
;
out_free:
sctp_ulpevent_free
(
event
);
/* Free the skb. */
if
(
flags
&
MSG_PEEK
)
{
/* Release the skb reference acquired after peeking the skb in
* sctp_skb_recv_datagram().
*/
kfree_skb
(
skb
);
}
else
{
/* Free the event which includes releasing the reference to
* the owner of the skb, freeing the skb and updating the
* rwnd.
*/
sctp_ulpevent_free
(
event
);
}
out:
sctp_release_sock
(
sk
);
return
err
;
...
...
@@ -1421,7 +1435,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
return
0
;
}
/* 7.1.13 Peer Address Parameters (SCTP_
SET_
PEER_ADDR_PARAMS)
/* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
*
* Applications can enable or disable heartbeats for any peer address of
* an association, modify an address's heartbeat interval, force a
...
...
@@ -1571,24 +1585,25 @@ static int sctp_setsockopt_default_send_param(struct sock *sk,
return
0
;
}
/* 7.1.10 Set Peer Primary Address (SCTP_
SET_PEER_
PRIMARY_ADDR)
/* 7.1.10 Set Peer Primary Address (SCTP_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
* the association primary. The enclosed address must be one of the
* association peer's addresses.
*/
static
int
sctp_setsockopt_peer_prim
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
static
int
sctp_setsockopt_primary_addr
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_
setpeer
prim
prim
;
struct
sctp_prim
prim
;
struct
sctp_transport
*
trans
;
if
(
optlen
!=
sizeof
(
struct
sctp_
setpeer
prim
))
if
(
optlen
!=
sizeof
(
struct
sctp_prim
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
prim
,
optval
,
sizeof
(
struct
sctp_
setpeer
prim
)))
if
(
copy_from_user
(
&
prim
,
optval
,
sizeof
(
struct
sctp_prim
)))
return
-
EFAULT
;
trans
=
sctp_addr_id2transport
(
sk
,
&
prim
.
ssp
p_addr
,
prim
.
ssp
p_assoc_id
);
trans
=
sctp_addr_id2transport
(
sk
,
&
prim
.
ssp
_addr
,
prim
.
ss
p_assoc_id
);
if
(
!
trans
)
return
-
EINVAL
;
...
...
@@ -1682,8 +1697,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char *optval, int optlen) {
* See [SCTP] for more information.
*
*/
static
int
sctp_setsockopt_assoc
rtx
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
static
int
sctp_setsockopt_assoc
info
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_assocparams
assocparams
;
struct
sctp_association
*
asoc
;
...
...
@@ -1736,14 +1751,18 @@ static int sctp_setsockopt_assocrtx(struct sock *sk, char *optval,
static
int
sctp_setsockopt_mappedv4
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
int
val
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
if
(
optlen
<
sizeof
(
int
))
return
-
EINVAL
;
if
(
get_user
(
val
,
(
int
*
)
optval
))
return
-
EFAULT
;
/* FIXME: Put real support here. */
if
(
val
)
sp
->
v4mapped
=
1
;
else
sp
->
v4mapped
=
0
;
return
-
ENOPROTOOPT
;
return
0
;
}
/*
...
...
@@ -1794,7 +1813,6 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
char
*
optval
,
int
optlen
)
{
int
retval
=
0
;
char
*
tmp
;
SCTP_DEBUG_PRINTK
(
"sctp_setsockopt(sk: %p... optname: %d)
\n
"
,
sk
,
optname
);
...
...
@@ -1814,38 +1832,25 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
sctp_lock_sock
(
sk
);
switch
(
optname
)
{
case
SCTP_SOCKOPT_DEBUG_NAME
:
/* BUG! we don't ever seem to free this memory. --jgrimm */
if
(
NULL
==
(
tmp
=
kmalloc
(
optlen
+
1
,
GFP_KERNEL
)))
{
retval
=
-
ENOMEM
;
goto
out_unlock
;
}
if
(
copy_from_user
(
tmp
,
optval
,
optlen
))
{
retval
=
-
EFAULT
;
goto
out_unlock
;
}
tmp
[
optlen
]
=
'\000'
;
sctp_sk
(
sk
)
->
ep
->
debug_name
=
tmp
;
break
;
case
SCTP_SOCKOPT_BINDX_ADD
:
/* 'optlen' is the size of the addresses buffer. */
retval
=
sctp_setsockopt_bindx
(
sk
,
(
struct
sockaddr_storage
*
)
optval
,
optlen
,
BINDX_ADD_ADDR
);
optval
,
optlen
,
SCTP_BINDX_ADD_ADDR
);
break
;
case
SCTP_SOCKOPT_BINDX_REM
:
/* 'optlen' is the size of the addresses buffer. */
retval
=
sctp_setsockopt_bindx
(
sk
,
(
struct
sockaddr_storage
*
)
optval
,
optlen
,
BINDX_REM_ADDR
);
optval
,
optlen
,
SCTP_BINDX_REM_ADDR
);
break
;
case
SCTP_DISABLE_FRAGMENTS
:
retval
=
sctp_setsockopt_disable_fragments
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_
SET_
EVENTS
:
case
SCTP_EVENTS
:
retval
=
sctp_setsockopt_events
(
sk
,
optval
,
optlen
);
break
;
...
...
@@ -1853,19 +1858,19 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_setsockopt_autoclose
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_
SET_
PEER_ADDR_PARAMS
:
case
SCTP_PEER_ADDR_PARAMS
:
retval
=
sctp_setsockopt_peer_addr_params
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_INITMSG
:
retval
=
sctp_setsockopt_initmsg
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_
SET_
DEFAULT_SEND_PARAM
:
case
SCTP_DEFAULT_SEND_PARAM
:
retval
=
sctp_setsockopt_default_send_param
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_
SET_PEER_
PRIMARY_ADDR
:
retval
=
sctp_setsockopt_p
eer_prim
(
sk
,
optval
,
optlen
);
case
SCTP_PRIMARY_ADDR
:
retval
=
sctp_setsockopt_p
rimary_addr
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_NODELAY
:
retval
=
sctp_setsockopt_nodelay
(
sk
,
optval
,
optlen
);
...
...
@@ -1873,8 +1878,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
case
SCTP_RTOINFO
:
retval
=
sctp_setsockopt_rtoinfo
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_ASSOC
RTX
INFO
:
retval
=
sctp_setsockopt_assoc
rtx
(
sk
,
optval
,
optlen
);
case
SCTP_ASSOCINFO
:
retval
=
sctp_setsockopt_assoc
info
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_I_WANT_MAPPED_V4_ADDR
:
retval
=
sctp_setsockopt_mappedv4
(
sk
,
optval
,
optlen
);
...
...
@@ -1887,7 +1892,6 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
break
;
};
out_unlock:
sctp_release_sock
(
sk
);
out_nounlock:
...
...
@@ -2163,7 +2167,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
}
/* Default Peer Address Parameters. These defaults can
* be modified via SCTP_
SET_
PEER_ADDR_PARAMS
* be modified via SCTP_PEER_ADDR_PARAMS
*/
sp
->
paddrparam
.
spp_hbinterval
=
(
sctp_hb_interval
/
HZ
)
*
1000
;
sp
->
paddrparam
.
spp_pathmaxrxt
=
sctp_max_retrans_path
;
...
...
@@ -2309,6 +2313,9 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
status
.
sstat_primary
.
spinfo_assoc_id
=
sctp_assoc2id
(
transport
->
asoc
);
memcpy
(
&
status
.
sstat_primary
.
spinfo_address
,
&
(
transport
->
ipaddr
),
sizeof
(
union
sctp_addr
));
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sctp_sk
(
sk
),
(
union
sctp_addr
*
)
&
status
.
sstat_primary
.
spinfo_address
);
status
.
sstat_primary
.
spinfo_state
=
transport
->
active
;
status
.
sstat_primary
.
spinfo_cwnd
=
transport
->
cwnd
;
status
.
sstat_primary
.
spinfo_srtt
=
transport
->
srtt
;
...
...
@@ -2408,12 +2415,13 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
return
0
;
}
/* 7.1.15 Set notification and ancillary events (SCTP_
SET_
EVENTS)
/* 7.1.15 Set notification and ancillary events (SCTP_EVENTS)
*
* This socket option is used to specify various notifications and
* ancillary data the user wishes to receive.
*/
static
int
sctp_getsockopt_set_events
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
static
int
sctp_getsockopt_events
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
if
(
len
!=
sizeof
(
struct
sctp_event_subscribe
))
return
-
EINVAL
;
...
...
@@ -2516,7 +2524,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
return
retval
;
}
/* 7.1.13 Peer Address Parameters (SCTP_
SET_
PEER_ADDR_PARAMS)
/* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
*
* Applications can enable or disable heartbeats for any peer address of
* an association, modify an address's heartbeat interval, force a
...
...
@@ -2645,6 +2653,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
struct
sctp_getaddrs
getaddrs
;
struct
sctp_transport
*
from
;
struct
sockaddr_storage
*
to
;
union
sctp_addr
temp
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
...
...
@@ -2663,7 +2673,9 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
to
=
getaddrs
.
addrs
;
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
from
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
if
(
copy_to_user
(
to
,
&
from
->
ipaddr
,
sizeof
(
from
->
ipaddr
)))
memcpy
(
&
temp
,
&
from
->
ipaddr
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
if
(
copy_to_user
(
to
,
&
temp
,
sizeof
(
temp
)))
return
-
EFAULT
;
to
++
;
cnt
++
;
...
...
@@ -2725,6 +2737,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
struct
sctp_getaddrs
getaddrs
;
struct
sctp_sockaddr_entry
*
from
;
struct
sockaddr_storage
*
to
;
union
sctp_addr
temp
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
...
...
@@ -2753,7 +2767,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
from
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
if
(
copy_to_user
(
to
,
&
from
->
a
,
sizeof
(
from
->
a
)))
memcpy
(
&
temp
,
&
from
->
a
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
if
(
copy_to_user
(
to
,
&
temp
,
sizeof
(
temp
)))
return
-
EFAULT
;
to
++
;
cnt
++
;
...
...
@@ -2766,35 +2782,39 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
return
0
;
}
/* 7.1.10 Set P
eer Primary Address (SCTP_SET_PEER
_PRIMARY_ADDR)
/* 7.1.10 Set P
rimary Address (SCTP
_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
* the association primary. The enclosed address must be one of the
* association peer's addresses.
*/
static
int
sctp_getsockopt_p
eer_prim
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
static
int
sctp_getsockopt_p
rimary_addr
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_
setpeer
prim
prim
;
struct
sctp_prim
prim
;
struct
sctp_association
*
asoc
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
if
(
len
!=
sizeof
(
struct
sctp_
setpeer
prim
))
if
(
len
!=
sizeof
(
struct
sctp_prim
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
prim
,
optval
,
sizeof
(
struct
sctp_
setpeer
prim
)))
if
(
copy_from_user
(
&
prim
,
optval
,
sizeof
(
struct
sctp_prim
)))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
prim
.
ssp
p
_assoc_id
);
asoc
=
sctp_id2assoc
(
sk
,
prim
.
ssp_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
if
(
!
asoc
->
peer
.
primary_path
)
return
-
ENOTCONN
;
memcpy
(
&
prim
.
ssp
p
_addr
,
&
asoc
->
peer
.
primary_path
->
ipaddr
,
memcpy
(
&
prim
.
ssp_addr
,
&
asoc
->
peer
.
primary_path
->
ipaddr
,
sizeof
(
union
sctp_addr
));
if
(
copy_to_user
(
optval
,
&
prim
,
sizeof
(
struct
sctp_setpeerprim
)))
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
(
union
sctp_addr
*
)
&
prim
.
ssp_addr
);
if
(
copy_to_user
(
optval
,
&
prim
,
sizeof
(
struct
sctp_prim
)))
return
-
EFAULT
;
return
0
;
...
...
@@ -2808,6 +2828,8 @@ static int sctp_getsockopt_peer_prim(struct sock *sk, int len,
* specify a default set of parameters that would normally be supplied
* through the inclusion of ancillary data. This socket option allows
* such an application to set the default sctp_sndrcvinfo structure.
* The application that wishes to use this socket option simply passes
* in to this call the sctp_sndrcvinfo structure defined in Section
* 5.2.2) The input parameters accepted by this call include
...
...
@@ -2942,8 +2964,9 @@ static int sctp_getsockopt_rtoinfo(struct sock *sk, int len, char *optval,
* See [SCTP] for more information.
*
*/
static
int
sctp_getsockopt_assocrtx
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
static
int
sctp_getsockopt_associnfo
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_assocparams
assocparams
;
struct
sctp_association
*
asoc
;
...
...
@@ -3014,12 +3037,13 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
char
*
optval
,
int
*
optlen
)
{
int
val
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
if
(
len
<
sizeof
(
int
))
return
-
EINVAL
;
len
=
sizeof
(
int
);
/* FIXME: Until we have support, return disabled. */
val
=
0
;
val
=
sp
->
v4mapped
;
if
(
put_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
copy_to_user
(
optval
,
&
val
,
len
))
...
...
@@ -3091,8 +3115,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_getsockopt_disable_fragments
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_
SET_
EVENTS
:
retval
=
sctp_getsockopt_
set_
events
(
sk
,
len
,
optval
,
optlen
);
case
SCTP_EVENTS
:
retval
=
sctp_getsockopt_events
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_AUTOCLOSE
:
retval
=
sctp_getsockopt_autoclose
(
sk
,
len
,
optval
,
optlen
);
...
...
@@ -3100,7 +3124,7 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case
SCTP_SOCKOPT_PEELOFF
:
retval
=
sctp_getsockopt_peeloff
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_
GET_
PEER_ADDR_PARAMS
:
case
SCTP_PEER_ADDR_PARAMS
:
retval
=
sctp_getsockopt_peer_addr_params
(
sk
,
len
,
optval
,
optlen
);
break
;
...
...
@@ -3123,12 +3147,12 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_getsockopt_local_addrs
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_
SET_
DEFAULT_SEND_PARAM
:
case
SCTP_DEFAULT_SEND_PARAM
:
retval
=
sctp_getsockopt_default_send_param
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_
SET_PEER_
PRIMARY_ADDR
:
retval
=
sctp_getsockopt_p
eer_prim
(
sk
,
len
,
optval
,
optlen
);
case
SCTP_PRIMARY_ADDR
:
retval
=
sctp_getsockopt_p
rimary_addr
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_NODELAY
:
retval
=
sctp_getsockopt_nodelay
(
sk
,
len
,
optval
,
optlen
);
...
...
@@ -3136,8 +3160,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case
SCTP_RTOINFO
:
retval
=
sctp_getsockopt_rtoinfo
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_ASSOC
RTX
INFO
:
retval
=
sctp_getsockopt_assoc
rtx
(
sk
,
len
,
optval
,
optlen
);
case
SCTP_ASSOCINFO
:
retval
=
sctp_getsockopt_assoc
info
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_I_WANT_MAPPED_V4_ADDR
:
retval
=
sctp_getsockopt_mappedv4
(
sk
,
len
,
optval
,
optlen
);
...
...
@@ -3865,7 +3889,7 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
return
-
EINVAL
;
/* Is this a valid SCTP address? */
if
(
!
af
->
addr_valid
(
addr
))
if
(
!
af
->
addr_valid
(
addr
,
sctp_sk
(
sk
)
))
return
-
EINVAL
;
if
(
!
sctp_sk
(
sk
)
->
pf
->
send_verify
(
sctp_sk
(
sk
),
(
addr
)))
...
...
@@ -4210,7 +4234,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
*/
sctp_skb_for_each
(
skb
,
&
oldsk
->
sk_receive_queue
,
tmp
)
{
event
=
sctp_skb2event
(
skb
);
if
(
event
->
asoc
==
assoc
)
{
if
(
event
->
sndrcvinfo
.
sinfo_assoc_id
==
assoc
)
{
__skb_unlink
(
skb
,
skb
->
list
);
__skb_queue_tail
(
&
newsk
->
sk_receive_queue
,
skb
);
}
...
...
@@ -4239,7 +4263,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
*/
sctp_skb_for_each
(
skb
,
&
oldsp
->
pd_lobby
,
tmp
)
{
event
=
sctp_skb2event
(
skb
);
if
(
event
->
asoc
==
assoc
)
{
if
(
event
->
sndrcvinfo
.
sinfo_assoc_id
==
assoc
)
{
__skb_unlink
(
skb
,
skb
->
list
);
__skb_queue_tail
(
queue
,
skb
);
}
...
...
net/sctp/transport.c
View file @
c09d36c8
...
...
@@ -117,6 +117,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
INIT_LIST_HEAD
(
&
peer
->
transmitted
);
INIT_LIST_HEAD
(
&
peer
->
send_ready
);
INIT_LIST_HEAD
(
&
peer
->
transports
);
sctp_packet_init
(
&
peer
->
packet
,
peer
,
0
,
0
);
/* Set up the retransmission timer. */
init_timer
(
&
peer
->
T3_rtx_timer
);
...
...
net/sctp/ulpevent.c
View file @
c09d36c8
...
...
@@ -35,6 +35,8 @@
* Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Ardelle Fan <ardelle.fan@intel.com>
* Sridhar Samudrala <sri@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.
...
...
@@ -46,10 +48,12 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static
void
sctp_ulpevent_set_owner_r
(
struct
sk_buff
*
skb
,
struct
sctp_association
*
asoc
);
static
void
sctp_ulpevent_set_owner
(
struct
sk_buff
*
skb
,
const
struct
sctp_association
*
asoc
);
static
inline
void
sctp_ulpevent_set_owner
(
struct
sctp_ulpevent
*
event
,
const
struct
sctp_association
*
asoc
);
static
inline
void
sctp_ulpevent_release_owner
(
struct
sctp_ulpevent
*
event
);
static
void
sctp_ulpevent_receive_data
(
struct
sctp_ulpevent
*
event
,
struct
sctp_association
*
asoc
);
static
void
sctp_ulpevent_release_data
(
struct
sctp_ulpevent
*
event
);
/* Create a new sctp_ulpevent. */
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
msg_flags
,
int
gfp
)
...
...
@@ -62,30 +66,19 @@ struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
goto
fail
;
event
=
sctp_skb2event
(
skb
);
event
=
sctp_ulpevent_init
(
event
,
msg_flags
);
if
(
!
event
)
goto
fail_init
;
sctp_ulpevent_init
(
event
,
msg_flags
);
return
event
;
fail_init:
kfree_skb
(
skb
);
fail:
return
NULL
;
}
/* Initialize an ULP event from an given skb. */
struct
sctp_ulpevent
*
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
event
,
int
msg_flags
)
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
event
,
int
msg_flags
)
{
memset
(
event
,
sizeof
(
struct
sctp_ulpevent
),
0x00
);
event
->
msg_flags
=
msg_flags
;
return
event
;
}
/* Dispose of an event. */
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
event
)
{
kfree_skb
(
sctp_event2skb
(
event
));
}
/* Is this a MSG_NOTIFICATION? */
...
...
@@ -189,7 +182,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
sac
->
sac_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -281,7 +274,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
spc
->
spc_assoc_id
=
sctp_assoc2id
(
asoc
);
/* Sockets API Extensions for SCTP
...
...
@@ -294,6 +287,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
*/
memcpy
(
&
spc
->
spc_aaddr
,
aaddr
,
sizeof
(
struct
sockaddr_storage
));
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific
(
asoc
->
base
.
sk
->
sk_family
)
->
addr_v4map
(
sctp_sk
(
asoc
->
base
.
sk
),
(
union
sctp_addr
*
)
&
spc
->
spc_aaddr
);
return
event
;
fail:
...
...
@@ -336,7 +334,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
/* Copy the skb to a new skb with room for us to prepend
* notification with.
*/
skb
=
skb_copy_expand
(
chunk
->
skb
,
sizeof
(
struct
sctp_remote_error
),
skb
=
skb_copy_expand
(
chunk
->
skb
,
sizeof
(
struct
sctp_remote_error
),
0
,
gfp
);
/* Pull off the rest of the cause TLV from the chunk. */
...
...
@@ -346,10 +344,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
event
=
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
if
(
!
event
)
goto
fail
;
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
sre
=
(
struct
sctp_remote_error
*
)
skb_push
(
skb
,
sizeof
(
struct
sctp_remote_error
));
...
...
@@ -402,8 +397,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
skb
=
sctp_event2skb
(
event
);
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
sre
->
sre_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -442,9 +436,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
event
=
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
if
(
!
event
)
goto
fail
;
sctp_ulpevent_init
(
event
,
MSG_NOTIFICATION
);
ssf
=
(
struct
sctp_send_failed
*
)
skb_push
(
skb
,
sizeof
(
struct
sctp_send_failed
));
...
...
@@ -502,7 +494,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
memcpy
(
&
ssf
->
ssf_info
,
&
chunk
->
sinfo
,
sizeof
(
struct
sctp_sndrcvinfo
));
/* Per TSVWG discussion with Randy. Allow the application to
* ressemble a fragmented message.
* ressemble a fragmented message.
*/
ssf
->
ssf_info
.
sinfo_flags
=
chunk
->
chunk_hdr
->
flags
;
...
...
@@ -515,8 +507,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
* same association identifier. For TCP style socket, this field is
* ignored.
*/
skb
=
sctp_event2skb
(
event
);
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
ssf
->
ssf_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -579,7 +570,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner
(
skb
,
asoc
);
sctp_ulpevent_set_owner
(
event
,
asoc
);
sse
->
sse_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -596,12 +587,12 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
* 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
*/
struct
sctp_ulpevent
*
sctp_ulpevent_make_rcvmsg
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
struct
sctp_chunk
*
chunk
,
int
gfp
)
{
struct
sctp_ulpevent
*
event
;
struct
sctp_sndrcvinfo
*
info
;
struct
sk_buff
*
skb
,
*
list
;
struct
sk_buff
*
skb
;
size_t
padding
,
len
;
/* Clone the original skb, sharing the data. */
...
...
@@ -627,24 +618,15 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
/* Fixup cloned skb with just this chunks data. */
skb_trim
(
skb
,
chunk
->
chunk_end
-
padding
-
skb
->
data
);
/* Set up a destructor to do rwnd accounting. */
sctp_ulpevent_set_owner_r
(
skb
,
asoc
);
/* Embed the event fields inside the cloned skb. */
event
=
sctp_skb2event
(
skb
);
/* Initialize event with flags 0. */
event
=
sctp_ulpevent_init
(
event
,
0
);
if
(
!
event
)
goto
fail_init
;
sctp_ulpevent_init
(
event
,
0
);
event
->
iif
=
sctp_chunk_iif
(
chunk
);
/* Note: Not clearing the entire event struct as
* this is just a fragment of the real event. However,
* we still need to do rwnd accounting.
*/
for
(
list
=
skb_shinfo
(
skb
)
->
frag_list
;
list
;
list
=
list
->
next
)
sctp_ulpevent_set_owner_r
(
list
,
asoc
);
sctp_ulpevent_receive_data
(
event
,
asoc
);
info
=
(
struct
sctp_sndrcvinfo
*
)
&
event
->
sndrcvinfo
;
...
...
@@ -735,9 +717,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
return
event
;
fail_init:
kfree_skb
(
skb
);
fail:
return
NULL
;
}
...
...
@@ -754,7 +733,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
const
struct
sctp_association
*
asoc
,
__u32
indication
,
int
gfp
)
{
struct
sctp_ulpevent
*
event
;
struct
sctp_
rcv_
pdapi_event
*
pd
;
struct
sctp_pdapi_event
*
pd
;
struct
sk_buff
*
skb
;
event
=
sctp_ulpevent_new
(
sizeof
(
struct
sctp_assoc_change
),
...
...
@@ -763,8 +742,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
goto
fail
;
skb
=
sctp_event2skb
(
event
);
pd
=
(
struct
sctp_
rcv_
pdapi_event
*
)
skb_put
(
skb
,
sizeof
(
struct
sctp_
rcv_
pdapi_event
));
pd
=
(
struct
sctp_pdapi_event
*
)
skb_put
(
skb
,
sizeof
(
struct
sctp_pdapi_event
));
/* pdapi_type
* It should be SCTP_PARTIAL_DELIVERY_EVENT
...
...
@@ -779,9 +758,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
*
* This field is the total length of the notification data, including
* the notification header. It will generally be sizeof (struct
* sctp_
rcv_
pdapi_event).
* sctp_pdapi_event).
*/
pd
->
pdapi_length
=
sizeof
(
struct
sctp_
rcv_
pdapi_event
);
pd
->
pdapi_length
=
sizeof
(
struct
sctp_pdapi_event
);
/* pdapi_indication: 32 bits (unsigned integer)
*
...
...
@@ -793,6 +772,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
*
* The association id field, holds the identifier for the association.
*/
sctp_ulpevent_set_owner
(
event
,
asoc
);
pd
->
pdapi_assoc_id
=
sctp_assoc2id
(
asoc
);
return
event
;
...
...
@@ -810,7 +790,7 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event)
skb
=
sctp_event2skb
((
struct
sctp_ulpevent
*
)
event
);
notification
=
(
union
sctp_notification
*
)
skb
->
data
;
return
notification
->
h
.
sn_type
;
return
notification
->
sn_header
.
sn_type
;
}
/* Copy out the sndrcvinfo into a msghdr. */
...
...
@@ -824,69 +804,115 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
}
}
/*
Do accounting for bytes just read by use
r. */
static
void
sctp_
rcvmsg
_rfree
(
struct
sk_buff
*
skb
)
/*
Stub skb destructo
r. */
static
void
sctp_
stub
_rfree
(
struct
sk_buff
*
skb
)
{
struct
sctp_association
*
asoc
;
struct
sctp_ulpevent
*
event
;
/* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as
* multiple associations may be on a single UDP-style socket.
* Use the local private area of the skb to track the owning
* association.
*/
event
=
sctp_skb2event
(
skb
);
asoc
=
event
->
asoc
;
sctp_assoc_rwnd_increase
(
asoc
,
skb_headlen
(
skb
));
sctp_association_put
(
asoc
);
/* WARNING: This function is just a warning not to use the
* skb destructor. If the skb is shared, we may get the destructor
* callback on some processor that does not own the sock_lock. This
* was occuring with PACKET socket applications that were monitoring
* our skbs. We can't take the sock_lock, because we can't risk
* recursing if we do really own the sock lock. Instead, do all
* of our rwnd manipulation while we own the sock_lock outright.
*/
}
/* Charge receive window for bytes received. */
static
void
sctp_ulpevent_set_owner_r
(
struct
sk_buff
*
skb
,
struct
sctp_association
*
asoc
)
/* Hold the association in case the msg_name needs read out of
* the association.
*/
static
inline
void
sctp_ulpevent_set_owner
(
struct
sctp_ulpevent
*
event
,
const
struct
sctp_association
*
asoc
)
{
struct
s
ctp_ulpevent
*
event
;
struct
s
k_buff
*
skb
;
/* The current stack structures assume that the rcv buffer is
* per socket. For UDP-style sockets this is not true as
* multiple associations may be on a single UDP-style socket.
* We use the local private area of the skb to track the owning
* association.
/* Cast away the const, as we are just wanting to
* bump the reference count.
*/
sctp_association_hold
(
asoc
);
sctp_association_hold
((
struct
sctp_association
*
)
asoc
);
skb
=
sctp_event2skb
(
event
);
skb
->
sk
=
asoc
->
base
.
sk
;
event
=
sctp_skb2event
(
skb
);
event
->
asoc
=
asoc
;
event
->
sndrcvinfo
.
sinfo_assoc_id
=
sctp_assoc2id
(
asoc
);
skb
->
destructor
=
sctp_stub_rfree
;
}
skb
->
destructor
=
sctp_rcvmsg_rfree
;
/* A simple destructor to give up the reference to the association. */
static
inline
void
sctp_ulpevent_release_owner
(
struct
sctp_ulpevent
*
event
)
{
sctp_association_put
(
event
->
sndrcvinfo
.
sinfo_assoc_id
);
}
/* Do accounting for bytes received and hold a reference to the association
* for each skb.
*/
static
void
sctp_ulpevent_receive_data
(
struct
sctp_ulpevent
*
event
,
struct
sctp_association
*
asoc
)
{
struct
sk_buff
*
skb
,
*
frag
;
skb
=
sctp_event2skb
(
event
);
/* Set the owner and charge rwnd for bytes received. */
sctp_ulpevent_set_owner
(
event
,
asoc
);
sctp_assoc_rwnd_decrease
(
asoc
,
skb_headlen
(
skb
));
/* Note: Not clearing the entire event struct as this is just a
* fragment of the real event. However, we still need to do rwnd
* accounting.
* In general, the skb passed from IP can have only 1 level of
* fragments. But we allow multiple levels of fragments.
*/
for
(
frag
=
skb_shinfo
(
skb
)
->
frag_list
;
frag
;
frag
=
frag
->
next
)
{
sctp_ulpevent_receive_data
(
sctp_skb2event
(
frag
),
asoc
);
}
}
/* A simple destructor to give up the reference to the association. */
static
void
sctp_ulpevent_rfree
(
struct
sk_buff
*
skb
)
/* Do accounting for bytes just read by user and release the references to
* the association.
*/
static
void
sctp_ulpevent_release_data
(
struct
sctp_ulpevent
*
event
)
{
struct
s
ctp_ulpevent
*
event
;
struct
s
k_buff
*
skb
,
*
frag
;
event
=
sctp_skb2event
(
skb
);
sctp_association_put
(
event
->
asoc
);
/* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as
* multiple associations may be on a single UDP-style socket.
* Use the local private area of the skb to track the owning
* association.
*/
skb
=
sctp_event2skb
(
event
);
sctp_assoc_rwnd_increase
(
event
->
sndrcvinfo
.
sinfo_assoc_id
,
skb_headlen
(
skb
));
/* Don't forget the fragments. */
for
(
frag
=
skb_shinfo
(
skb
)
->
frag_list
;
frag
;
frag
=
frag
->
next
)
{
/* NOTE: skb_shinfos are recursive. Although IP returns
* skb's with only 1 level of fragments, SCTP reassembly can
* increase the levels.
*/
sctp_ulpevent_release_data
(
sctp_skb2event
(
frag
));
}
sctp_ulpevent_release_owner
(
event
);
}
/* Hold the association in case the msg_name needs read out of
* the association.
/* Free a ulpevent that has an owner. It includes releasing the reference
* to the owner, updating the rwnd in case of a DATA event and freeing the
* skb.
* See comments in sctp_stub_rfree().
*/
static
void
sctp_ulpevent_set_owner
(
struct
sk_buff
*
skb
,
const
struct
sctp_association
*
asoc
)
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
event
)
{
struct
sctp_ulpevent
*
event
;
if
(
sctp_ulpevent_is_notification
(
event
))
sctp_ulpevent_release_owner
(
event
);
else
sctp_ulpevent_release_data
(
event
);
/* Cast away the const, as we are just wanting to
* bump the reference count.
*/
sctp_association_hold
((
struct
sctp_association
*
)
asoc
);
skb
->
sk
=
asoc
->
base
.
sk
;
event
=
sctp_skb2event
(
skb
);
event
->
asoc
=
(
struct
sctp_association
*
)
asoc
;
skb
->
destructor
=
sctp_ulpevent_rfree
;
kfree_skb
(
sctp_event2skb
(
event
));
}
/* Purge the skb lists holding ulpevents. */
void
sctp_queue_purge_ulpevents
(
struct
sk_buff_head
*
list
)
{
struct
sk_buff
*
skb
;
while
((
skb
=
skb_dequeue
(
list
))
!=
NULL
)
sctp_ulpevent_free
(
sctp_skb2event
(
skb
));
}
net/sctp/ulpqueue.c
View file @
c09d36c8
...
...
@@ -235,9 +235,9 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
out_free:
if
(
sctp_event2skb
(
event
)
->
list
)
s
kb_queue_purge
(
sctp_event2skb
(
event
)
->
list
);
s
ctp_queue_purge_ulpevents
(
sctp_event2skb
(
event
)
->
list
);
else
kfree_skb
(
sctp_event2skb
(
event
)
);
sctp_ulpevent_free
(
event
);
return
0
;
}
...
...
@@ -289,7 +289,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
* payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist.
*/
static
inline
struct
sctp_ulpevent
*
sctp_make_reassembled_event
(
struct
sk_buff
*
f_frag
,
struct
sk_buff
*
l_frag
)
static
struct
sctp_ulpevent
*
sctp_make_reassembled_event
(
struct
sk_buff
*
f_frag
,
struct
sk_buff
*
l_frag
)
{
struct
sk_buff
*
pos
;
struct
sctp_ulpevent
*
event
;
...
...
@@ -325,11 +325,10 @@ static inline struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *
/* Remove the fragment from the reassembly queue. */
__skb_unlink
(
pos
,
pos
->
list
);
/* Break if we have reached the last fragment. */
if
(
pos
==
l_frag
)
break
;
pos
->
next
=
pnext
;
pos
=
pnext
;
};
...
...
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