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
63c6e5b3
Commit
63c6e5b3
authored
Nov 03, 2002
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCTP] Support for Peer address parameters socket option.
parent
cd722282
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
293 additions
and
80 deletions
+293
-80
include/net/sctp/command.h
include/net/sctp/command.h
+2
-0
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+1
-1
include/net/sctp/sm.h
include/net/sctp/sm.h
+1
-0
include/net/sctp/structs.h
include/net/sctp/structs.h
+8
-6
net/sctp/associola.c
net/sctp/associola.c
+8
-5
net/sctp/outqueue.c
net/sctp/outqueue.c
+3
-3
net/sctp/primitive.c
net/sctp/primitive.c
+23
-0
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+21
-6
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+78
-29
net/sctp/sm_statetable.c
net/sctp/sm_statetable.c
+16
-8
net/sctp/socket.c
net/sctp/socket.c
+130
-20
net/sctp/transport.c
net/sctp/transport.c
+2
-2
No files found.
include/net/sctp/command.h
View file @
63c6e5b3
...
...
@@ -27,6 +27,7 @@
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -72,6 +73,7 @@ typedef enum {
SCTP_CMD_STRIKE
,
/* Mark a strike against a transport. */
SCTP_CMD_TRANSMIT
,
/* Transmit the outqueue. */
SCTP_CMD_HB_TIMERS_START
,
/* Start the heartbeat timers. */
SCTP_CMD_HB_TIMERS_UPDATE
,
/* Update the heartbeat timers. */
SCTP_CMD_TRANSPORT_RESET
,
/* Reset the status of a transport. */
SCTP_CMD_TRANSPORT_ON
,
/* Mark the transport as active. */
SCTP_CMD_REPORT_ERROR
,
/* Pass this error back out of the sm. */
...
...
include/net/sctp/sctp.h
View file @
63c6e5b3
...
...
@@ -142,7 +142,7 @@ extern int sctp_primitive_ASSOCIATE(sctp_association_t *, void *arg);
extern
int
sctp_primitive_SHUTDOWN
(
sctp_association_t
*
,
void
*
arg
);
extern
int
sctp_primitive_ABORT
(
sctp_association_t
*
,
void
*
arg
);
extern
int
sctp_primitive_SEND
(
sctp_association_t
*
,
void
*
arg
);
extern
int
sctp_primitive_REQUESTHEARTBEAT
(
sctp_association_t
*
,
void
*
arg
);
/*
* sctp_crc32c.c
...
...
include/net/sctp/sm.h
View file @
63c6e5b3
...
...
@@ -157,6 +157,7 @@ sctp_state_fn_t sctp_sf_shutdown_ack_sent_prm_abort;
sctp_state_fn_t
sctp_sf_error_closed
;
sctp_state_fn_t
sctp_sf_error_shutdown
;
sctp_state_fn_t
sctp_sf_ignore_primitive
;
sctp_state_fn_t
sctp_sf_do_prm_requestheartbeat
;
/* Prototypes for other event state functions. */
sctp_state_fn_t
sctp_sf_do_9_2_start_shutdown
;
...
...
include/net/sctp/structs.h
View file @
63c6e5b3
...
...
@@ -684,13 +684,15 @@ struct SCTP_transport {
*/
unsigned
long
last_time_ecne_reduced
;
/*
state : The current
state of this destination,
* : i.e. DOWN, UP,
ALLOW-HB, NO-HEARTBEAT,
etc.
/*
active : The current active
state of this destination,
* : i.e. DOWN, UP, etc.
*/
struct
{
int
active
;
/* hb_allowed : The current heartbeat state of this destination,
* : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
*/
int
hb_allowed
;
}
state
;
/* These are the error stats for this destination. */
...
...
net/sctp/associola.c
View file @
63c6e5b3
...
...
@@ -461,6 +461,9 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
min
(
asoc
->
overall_error_threshold
+
peer
->
error_threshold
,
asoc
->
max_retrans
);
/* By default, enable heartbeat for peer address. */
peer
->
hb_allowed
=
1
;
/* Initialize the peer's heartbeat interval based on the
* sock configured value.
*/
...
...
@@ -523,12 +526,12 @@ void sctp_assoc_control_transport(sctp_association_t *asoc,
/* Record the transition on the transport. */
switch
(
command
)
{
case
SCTP_TRANSPORT_UP
:
transport
->
state
.
active
=
1
;
transport
->
active
=
1
;
spc_state
=
ADDRESS_AVAILABLE
;
break
;
case
SCTP_TRANSPORT_DOWN
:
transport
->
state
.
active
=
0
;
transport
->
active
=
0
;
spc_state
=
ADDRESS_UNREACHABLE
;
break
;
...
...
@@ -558,7 +561,7 @@ void sctp_assoc_control_transport(sctp_association_t *asoc,
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
t
=
list_entry
(
pos
,
sctp_transport_t
,
transports
);
if
(
!
t
->
state
.
active
)
if
(
!
t
->
active
)
continue
;
if
(
!
first
||
t
->
last_time_heard
>
first
->
last_time_heard
)
{
second
=
first
;
...
...
@@ -578,7 +581,7 @@ void sctp_assoc_control_transport(sctp_association_t *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
if
(
asoc
->
peer
.
primary_path
->
state
.
active
&&
if
(
asoc
->
peer
.
primary_path
->
active
&&
first
!=
asoc
->
peer
.
primary_path
)
{
second
=
first
;
first
=
asoc
->
peer
.
primary_path
;
...
...
@@ -1018,7 +1021,7 @@ sctp_transport_t *sctp_assoc_choose_shutdown_transport(sctp_association_t *asoc)
/* Try to find an active transport. */
if
(
t
->
state
.
active
)
{
if
(
t
->
active
)
{
break
;
}
else
{
/* Keep track of the next transport in case
...
...
net/sctp/outqueue.c
View file @
63c6e5b3
...
...
@@ -678,7 +678,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
if
(
!
new_transport
)
{
new_transport
=
asoc
->
peer
.
active_path
;
}
else
if
(
!
new_transport
->
state
.
active
)
{
}
else
if
(
!
new_transport
->
active
)
{
/* If the chunk is Heartbeat, send it to
* chunk->transport, even it's inactive.
*/
...
...
@@ -835,7 +835,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
*/
new_transport
=
chunk
->
transport
;
if
(
new_transport
==
NULL
||
!
new_transport
->
state
.
active
)
!
new_transport
->
active
)
new_transport
=
asoc
->
peer
.
active_path
;
/* Change packets if necessary. */
...
...
@@ -1404,7 +1404,7 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
if
(
!
transport
->
state
.
active
)
{
if
(
!
transport
->
active
)
{
sctp_assoc_control_transport
(
transport
->
asoc
,
transport
,
...
...
net/sctp/primitive.c
View file @
63c6e5b3
...
...
@@ -38,6 +38,7 @@
* La Monte H.P. Yarroll <piggy@acm.org>
* Narasimha Budihal <narasimha@refcode.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -181,6 +182,28 @@ DECLARE_PRIMITIVE(ABORT);
DECLARE_PRIMITIVE
(
SEND
);
/* 10.1 ULP-to-SCTP
* J) Request Heartbeat
*
* Format: REQUESTHEARTBEAT(association id, destination transport address)
*
* -> result
*
* Instructs the local endpoint to perform a HeartBeat on the specified
* destination transport address of the given association. The returned
* result should indicate whether the transmission of the HEARTBEAT
* chunk to the destination address is successful.
*
* Mandatory attributes:
*
* o association id - local handle to the SCTP association
*
* o destination transport address - the transport address of the
* asociation on which a heartbeat should be issued.
*/
DECLARE_PRIMITIVE
(
REQUESTHEARTBEAT
);
/* COMMENT BUG. Find out where this is mentioned in the spec. */
int
sctp_other_icmp_unreachfrag
(
sctp_association_t
*
asoc
,
void
*
arg
)
{
...
...
net/sctp/sm_sideeffect.c
View file @
63c6e5b3
...
...
@@ -41,6 +41,7 @@
* Dajiang Zhang <dajiang.zhang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -73,6 +74,8 @@ static void sctp_cmd_process_init(sctp_cmd_seq_t *, sctp_association_t *asoc,
sctp_init_chunk_t
*
peer_init
,
int
priority
);
static
void
sctp_cmd_hb_timers_start
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
);
static
void
sctp_cmd_hb_timers_update
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
,
sctp_transport_t
*
);
static
void
sctp_cmd_set_bind_addrs
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
,
sctp_bind_addr_t
*
);
static
void
sctp_cmd_transport_reset
(
sctp_cmd_seq_t
*
,
sctp_association_t
*
,
...
...
@@ -193,6 +196,7 @@ int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
/* BUG--we should now recover some memory, probably by
* reneging...
*/
error
=
-
ENOMEM
;
break
;
case
SCTP_DISPOSITION_DELETE_TCB
:
...
...
@@ -561,6 +565,11 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_cmd_hb_timers_start
(
commands
,
asoc
);
break
;
case
SCTP_CMD_HB_TIMERS_UPDATE
:
t
=
command
->
obj
.
transport
;
sctp_cmd_hb_timers_update
(
commands
,
asoc
,
t
);
break
;
case
SCTP_CMD_REPORT_ERROR
:
error
=
command
->
obj
.
error
;
break
;
...
...
@@ -978,7 +987,7 @@ static void sctp_do_8_2_transport_strike(sctp_association_t *asoc,
*/
asoc
->
overall_error_count
++
;
if
(
transport
->
state
.
active
&&
if
(
transport
->
active
&&
(
transport
->
error_count
++
>=
transport
->
error_threshold
))
{
SCTP_DEBUG_PRINTK
(
"transport_strike: transport "
"IP:%d.%d.%d.%d failed.
\n
"
,
...
...
@@ -1096,6 +1105,16 @@ static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *cmds,
}
}
/* Helper function to update the heartbeat timer. */
static
void
sctp_cmd_hb_timers_update
(
sctp_cmd_seq_t
*
cmds
,
sctp_association_t
*
asoc
,
sctp_transport_t
*
t
)
{
/* Update the heartbeat timer. */
if
(
!
mod_timer
(
&
t
->
hb_timer
,
t
->
hb_interval
+
t
->
rto
+
jiffies
))
sctp_transport_hold
(
t
);
}
/* Helper function to break out SCTP_CMD_SET_BIND_ADDR handling. */
void
sctp_cmd_set_bind_addrs
(
sctp_cmd_seq_t
*
cmds
,
sctp_association_t
*
asoc
,
sctp_bind_addr_t
*
bp
)
...
...
@@ -1131,7 +1150,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* Mark the destination transport address as active if it is not so
* marked.
*/
if
(
!
t
->
state
.
active
)
if
(
!
t
->
active
)
sctp_assoc_control_transport
(
asoc
,
t
,
SCTP_TRANSPORT_UP
,
SCTP_HEARTBEAT_SUCCESS
);
...
...
@@ -1154,10 +1173,6 @@ static void sctp_cmd_transport_reset(sctp_cmd_seq_t *cmds,
/* Mark one strike against a transport. */
sctp_do_8_2_transport_strike
(
asoc
,
t
);
/* Update the heartbeat timer. */
if
(
!
mod_timer
(
&
t
->
hb_timer
,
t
->
hb_interval
+
t
->
rto
+
jiffies
))
sctp_transport_hold
(
t
);
}
/* Helper function to process the process SACK command. */
...
...
net/sctp/sm_statefuns.c
View file @
63c6e5b3
...
...
@@ -664,8 +664,8 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const sctp_endpoint_t *ep,
return
SCTP_DISPOSITION_NOMEM
;
}
/* Generate a
HEARTBEAT packet on the given transpor
t. */
sctp_disposition_t
sctp_sf_
sendbeat_8_3
(
const
sctp_endpoint_t
*
ep
,
/* Generate a
nd sendout a heartbeat packe
t. */
sctp_disposition_t
sctp_sf_
heartbeat
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
...
...
@@ -676,26 +676,13 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
sctp_sender_hb_info_t
hbinfo
;
size_t
paylen
=
0
;
if
(
asoc
->
overall_error_count
>=
asoc
->
overall_error_threshold
)
{
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
return
SCTP_DISPOSITION_DELETE_TCB
;
}
/* Section 3.3.5.
* The Sender-specific Heartbeat Info field should normally include
* information about the sender's current time when this HEARTBEAT
* chunk is sent and the destination transport address to which this
* HEARTBEAT is sent (see Section 8.3).
*/
hbinfo
.
param_hdr
.
type
=
SCTP_PARAM_HEARTBEAT_INFO
;
hbinfo
.
param_hdr
.
length
=
htons
(
sizeof
(
sctp_sender_hb_info_t
));
hbinfo
.
daddr
=
transport
->
ipaddr
;
hbinfo
.
sent_at
=
jiffies
;
/* Set rto_pending indicating that an RTT measurement
is started
* with this heartbeat chunk.
/* Set rto_pending indicating that an RTT measurement
*
is started
with this heartbeat chunk.
*/
transport
->
rto_pending
=
1
;
...
...
@@ -703,20 +690,49 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
paylen
=
sizeof
(
sctp_sender_hb_info_t
);
reply
=
sctp_make_heartbeat
(
asoc
,
transport
,
&
hbinfo
,
paylen
);
if
(
!
reply
)
goto
nomem
;
return
SCTP_DISPOSITION_NOMEM
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
reply
));
return
SCTP_DISPOSITION_CONSUME
;
}
/* Generate a HEARTBEAT packet on the given transport. */
sctp_disposition_t
sctp_sf_sendbeat_8_3
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
sctp_transport_t
*
transport
=
(
sctp_transport_t
*
)
arg
;
if
(
asoc
->
overall_error_count
>=
asoc
->
overall_error_threshold
)
{
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_NULL
());
return
SCTP_DISPOSITION_DELETE_TCB
;
}
/* Section 3.3.5.
* The Sender-specific Heartbeat Info field should normally include
* information about the sender's current time when this HEARTBEAT
* chunk is sent and the destination transport address to which this
* HEARTBEAT is sent (see Section 8.3).
*/
if
(
transport
->
hb_allowed
)
{
if
(
SCTP_DISPOSITION_NOMEM
==
sctp_sf_heartbeat
(
ep
,
asoc
,
type
,
arg
,
commands
))
return
SCTP_DISPOSITION_NOMEM
;
/* Set transport error counter and association error counter
* when sending heartbeat.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TRANSPORT_RESET
,
SCTP_TRANSPORT
(
transport
));
}
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_HB_TIMERS_UPDATE
,
SCTP_TRANSPORT
(
transport
));
return
SCTP_DISPOSITION_CONSUME
;
nomem:
return
SCTP_DISPOSITION_NOMEM
;
}
/*
...
...
@@ -3656,6 +3672,39 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort(
return
sctp_sf_shutdown_sent_prm_abort
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/*
* Process the REQUESTHEARTBEAT primitive
*
* 10.1 ULP-to-SCTP
* J) Request Heartbeat
*
* Format: REQUESTHEARTBEAT(association id, destination transport address)
*
* -> result
*
* Instructs the local endpoint to perform a HeartBeat on the specified
* destination transport address of the given association. The returned
* result should indicate whether the transmission of the HEARTBEAT
* chunk to the destination address is successful.
*
* Mandatory attributes:
*
* o association id - local handle to the SCTP association
*
* o destination transport address - the transport address of the
* asociation on which a heartbeat should be issued.
*/
sctp_disposition_t
sctp_sf_do_prm_requestheartbeat
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
return
sctp_sf_heartbeat
(
ep
,
asoc
,
type
,
(
sctp_transport_t
*
)
arg
,
commands
);
}
/*
* Ignore the primitive event
*
...
...
net/sctp/sm_statetable.c
View file @
63c6e5b3
...
...
@@ -39,6 +39,7 @@
* Jon Grimm <jgrimm@us.ibm.com>
* Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -706,21 +707,28 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
\
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */
\
{.fn = sctp_sf_
not_impl, .name = "sctp_sf_not_impl
"}, \
{.fn = sctp_sf_
bug, .name = "sctp_sf_bug
"}, \
/* SCTP_STATE_COOKIE_WAIT */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_COOKIE_ECHOED */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_ESTABLISHED */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_SENT */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
\
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
}
/* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_GETSRTTREPORT { \
...
...
net/sctp/socket.c
View file @
63c6e5b3
...
...
@@ -1252,6 +1252,67 @@ static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
return
0
;
}
static
inline
int
sctp_setsockopt_set_peer_addr_params
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_paddrparams
params
;
sctp_association_t
*
asoc
;
sockaddr_storage_t
*
addr
;
sctp_transport_t
*
trans
;
int
error
;
if
(
optlen
!=
sizeof
(
struct
sctp_paddrparams
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
params
,
optval
,
optlen
))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
params
.
spp_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
addr
=
(
sockaddr_storage_t
*
)
&
(
params
.
spp_address
);
trans
=
sctp_assoc_lookup_paddr
(
asoc
,
addr
);
if
(
!
trans
)
return
-
ENOENT
;
/* 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 value of the heartbeat interval, in milliseconds. A value of
* UINT32_MAX (4294967295), when modifying the parameter, specifies
* that a heartbeat should be sent immediately to the peer address,
* and the current interval should remain unchanged.
*/
if
(
0xffffffff
==
params
.
spp_hbinterval
)
{
error
=
sctp_primitive_REQUESTHEARTBEAT
(
asoc
,
trans
);
if
(
error
)
return
error
;
}
else
{
/* The value of the heartbeat interval, in milliseconds. A value of 0,
* when modifying the parameter, specifies that the heartbeat on this
* address should be disabled.
*/
if
(
params
.
spp_hbinterval
)
{
trans
->
hb_allowed
=
1
;
trans
->
hb_interval
=
params
.
spp_hbinterval
*
HZ
/
1000
;
}
else
trans
->
hb_allowed
=
0
;
}
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
trans
->
error_threshold
=
params
.
spp_pathmaxrxt
;
return
0
;
}
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
...
...
@@ -1342,6 +1403,11 @@ 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
:
retval
=
sctp_setsockopt_set_peer_addr_params
(
sk
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
...
...
@@ -1503,28 +1569,26 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
if
(
len
!=
sizeof
(
status
))
{
retval
=
-
EINVAL
;
goto
out
_nounlock
;
goto
out
;
}
if
(
copy_from_user
(
&
status
,
optval
,
sizeof
(
status
)))
{
retval
=
-
EFAULT
;
goto
out
_nounlock
;
goto
out
;
}
sctp_lock_sock
(
sk
);
associd
=
status
.
sstat_assoc_id
;
if
((
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
!=
sctp_sk
(
sk
)
->
type
)
&&
associd
)
{
assoc
=
sctp_id2assoc
(
sk
,
associd
);
if
(
!
assoc
)
{
retval
=
-
EINVAL
;
goto
out
_unlock
;
goto
out
;
}
}
else
{
ep
=
sctp_sk
(
sk
)
->
ep
;
if
(
list_empty
(
&
ep
->
asocs
))
{
retval
=
-
EINVAL
;
goto
out
_unlock
;
goto
out
;
}
assoc
=
list_entry
(
ep
->
asocs
.
next
,
sctp_association_t
,
asocs
);
...
...
@@ -1543,7 +1607,7 @@ 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
(
sockaddr_storage_t
));
status
.
sstat_primary
.
spinfo_state
=
transport
->
state
.
active
;
status
.
sstat_primary
.
spinfo_state
=
transport
->
active
;
status
.
sstat_primary
.
spinfo_cwnd
=
transport
->
cwnd
;
status
.
sstat_primary
.
spinfo_srtt
=
transport
->
srtt
;
status
.
sstat_primary
.
spinfo_rto
=
transport
->
rto
;
...
...
@@ -1551,7 +1615,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
if
(
put_user
(
len
,
optlen
))
{
retval
=
-
EFAULT
;
goto
out
_unlock
;
goto
out
;
}
SCTP_DEBUG_PRINTK
(
"sctp_getsockopt_sctp_status(%d): %d %d %p
\n
"
,
...
...
@@ -1560,13 +1624,10 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
if
(
copy_to_user
(
optval
,
&
status
,
len
))
{
retval
=
-
EFAULT
;
goto
out
_unlock
;
goto
out
;
}
out_unlock:
sctp_release_sock
(
sk
);
out_nounlock:
out:
return
(
retval
);
}
...
...
@@ -1684,25 +1745,23 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
if
(
copy_from_user
(
&
peeloff
,
optval
,
len
))
return
-
EFAULT
;
sctp_lock_sock
(
sk
);
assoc
=
sctp_id2assoc
(
sk
,
peeloff
.
associd
);
if
(
NULL
==
assoc
)
{
retval
=
-
EINVAL
;
goto
out
_unlock
;
goto
out
;
}
SCTP_DEBUG_PRINTK
(
"%s: sk: %p assoc: %p
\n
"
,
__FUNCTION__
,
sk
,
assoc
);
retval
=
sctp_do_peeloff
(
assoc
,
&
newsock
);
if
(
retval
<
0
)
goto
out
_unlock
;
goto
out
;
/* Map the socket to an unused fd that can be returned to the user. */
retval
=
sock_map_fd
(
newsock
);
if
(
retval
<
0
)
{
sock_release
(
newsock
);
goto
out
_unlock
;
goto
out
;
}
SCTP_DEBUG_PRINTK
(
"%s: sk: %p assoc: %p newsk: %p sd: %d
\n
"
,
...
...
@@ -1713,11 +1772,54 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
if
(
copy_to_user
(
optval
,
&
peeloff
,
len
))
retval
=
-
EFAULT
;
out_unlock:
sctp_release_sock
(
sk
);
out:
return
retval
;
}
static
inline
int
sctp_getsockopt_get_peer_addr_params
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
struct
sctp_paddrparams
params
;
sctp_association_t
*
asoc
;
sockaddr_storage_t
*
addr
;
sctp_transport_t
*
trans
;
if
(
len
!=
sizeof
(
struct
sctp_paddrparams
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
params
,
optval
,
*
optlen
))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
params
.
spp_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
addr
=
(
sockaddr_storage_t
*
)
&
(
params
.
spp_address
);
trans
=
sctp_assoc_lookup_paddr
(
asoc
,
addr
);
if
(
!
trans
)
return
-
ENOENT
;
/* The value of the heartbeat interval, in milliseconds. A value of 0,
* when modifying the parameter, specifies that the heartbeat on this
* address should be disabled.
*/
if
(
!
trans
->
hb_allowed
)
params
.
spp_hbinterval
=
0
;
else
params
.
spp_hbinterval
=
trans
->
hb_interval
*
1000
/
HZ
;
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
params
.
spp_pathmaxrxt
=
trans
->
error_threshold
;
if
(
copy_to_user
(
optval
,
&
params
,
len
))
return
-
EFAULT
;
*
optlen
=
len
;
return
0
;
}
SCTP_STATIC
int
sctp_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
...
...
@@ -1748,6 +1850,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
sctp_lock_sock
(
sk
);
switch
(
optname
)
{
case
SCTP_STATUS
:
retval
=
sctp_getsockopt_sctp_status
(
sk
,
len
,
optval
,
optlen
);
...
...
@@ -1770,11 +1874,17 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_getsockopt_peeloff
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDR_PARAMS
:
retval
=
sctp_getsockopt_get_peer_addr_params
(
sk
,
len
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
};
sctp_release_sock
(
sk
);
return
retval
;
}
...
...
net/sctp/transport.c
View file @
63c6e5b3
...
...
@@ -104,8 +104,8 @@ sctp_transport_t *sctp_transport_init(sctp_transport_t *peer,
peer
->
last_time_used
=
jiffies
;
peer
->
last_time_ecne_reduced
=
jiffies
;
peer
->
state
.
active
=
1
;
peer
->
state
.
hb_allowed
=
0
;
peer
->
active
=
1
;
peer
->
hb_allowed
=
0
;
/* Initialize the default path max_retrans. */
peer
->
max_retrans
=
proto
->
max_retrans_path
;
...
...
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