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
76d3406b
Commit
76d3406b
authored
Jan 11, 2004
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.6.1
into us.ibm.com:/home/sridhar/BK/lksctp-2.6.1
parents
79d434c1
e10e81fb
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
716 additions
and
71 deletions
+716
-71
include/linux/sctp.h
include/linux/sctp.h
+2
-1
include/linux/sysctl.h
include/linux/sysctl.h
+1
-0
include/net/sctp/constants.h
include/net/sctp/constants.h
+1
-3
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+4
-2
include/net/sctp/sm.h
include/net/sctp/sm.h
+21
-6
include/net/sctp/structs.h
include/net/sctp/structs.h
+11
-0
net/sctp/associola.c
net/sctp/associola.c
+47
-0
net/sctp/input.c
net/sctp/input.c
+3
-6
net/sctp/outqueue.c
net/sctp/outqueue.c
+1
-1
net/sctp/protocol.c
net/sctp/protocol.c
+3
-0
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+408
-10
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+4
-3
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+119
-16
net/sctp/sm_statetable.c
net/sctp/sm_statetable.c
+8
-6
net/sctp/socket.c
net/sctp/socket.c
+75
-17
net/sctp/sysctl.c
net/sctp/sysctl.c
+8
-0
No files found.
include/linux/sctp.h
View file @
76d3406b
...
@@ -439,12 +439,13 @@ typedef enum {
...
@@ -439,12 +439,13 @@ typedef enum {
* 0x0101 Operation Refused Due to Resource Shortage.
* 0x0101 Operation Refused Due to Resource Shortage.
* 0x0102 Request to Delete Source IP Address.
* 0x0102 Request to Delete Source IP Address.
* 0x0103 Association Aborted due to illegal ASCONF-ACK
* 0x0103 Association Aborted due to illegal ASCONF-ACK
* 0x0104 Request refused - no authorization.
*/
*/
SCTP_ERROR_DEL_LAST_IP
=
__constant_htons
(
0x0100
),
SCTP_ERROR_DEL_LAST_IP
=
__constant_htons
(
0x0100
),
SCTP_ERROR_RSRC_LOW
=
__constant_htons
(
0x0101
),
SCTP_ERROR_RSRC_LOW
=
__constant_htons
(
0x0101
),
SCTP_ERROR_DEL_SRC_IP
=
__constant_htons
(
0x0102
),
SCTP_ERROR_DEL_SRC_IP
=
__constant_htons
(
0x0102
),
SCTP_ERROR_ASCONF_ACK
=
__constant_htons
(
0x0103
),
SCTP_ERROR_ASCONF_ACK
=
__constant_htons
(
0x0103
),
SCTP_ERROR_REQ_REFUSED
=
__constant_htons
(
0x0104
)
}
sctp_error_t
;
}
sctp_error_t
;
...
...
include/linux/sysctl.h
View file @
76d3406b
...
@@ -577,6 +577,7 @@ enum {
...
@@ -577,6 +577,7 @@ enum {
NET_SCTP_HB_INTERVAL
=
10
,
NET_SCTP_HB_INTERVAL
=
10
,
NET_SCTP_PRESERVE_ENABLE
=
11
,
NET_SCTP_PRESERVE_ENABLE
=
11
,
NET_SCTP_MAX_BURST
=
12
,
NET_SCTP_MAX_BURST
=
12
,
NET_SCTP_ADDIP_ENABLE
=
13
,
};
};
/* /proc/sys/net/bridge */
/* /proc/sys/net/bridge */
...
...
include/net/sctp/constants.h
View file @
76d3406b
/* SCTP kernel reference Implementation
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-2002 International Business Machines Corp.
*
*
* This file is part of the SCTP kernel reference Implementation
* This file is part of the SCTP kernel reference Implementation
*
*
...
@@ -75,8 +75,6 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
...
@@ -75,8 +75,6 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
#define SCTP_NUM_BASE_CHUNK_TYPES (SCTP_CID_BASE_MAX + 1)
#define SCTP_NUM_BASE_CHUNK_TYPES (SCTP_CID_BASE_MAX + 1)
#define SCTP_NUM_CHUNK_TYPES (SCTP_NUM_BASE_CHUNKTYPES + 2)
#define SCTP_NUM_CHUNK_TYPES (SCTP_NUM_BASE_CHUNKTYPES + 2)
#define SCTP_CID_ADDIP_MIN SCTP_CID_ASCONF
#define SCTP_CID_ADDIP_MAX SCTP_CID_ASCONF_ACK
#define SCTP_NUM_ADDIP_CHUNK_TYPES 2
#define SCTP_NUM_ADDIP_CHUNK_TYPES 2
/* These are the different flavours of event. */
/* These are the different flavours of event. */
...
...
include/net/sctp/sctp.h
View file @
76d3406b
...
@@ -115,8 +115,10 @@
...
@@ -115,8 +115,10 @@
#define SCTP_STATIC static
#define SCTP_STATIC static
#endif
#endif
#define MSECS_TO_JIFFIES(msec) (msec * HZ / 1000)
#define MSECS_TO_JIFFIES(msec) \
#define JIFFIES_TO_MSECS(jiff) (jiff * 1000 / HZ)
(((msec / 1000) * HZ) + ((msec % 1000) * HZ) / 1000)
#define JIFFIES_TO_MSECS(jiff) \
(((jiff / HZ) * 1000) + ((jiff % HZ) * 1000) / HZ)
/*
/*
* Function declarations.
* Function declarations.
...
...
include/net/sctp/sm.h
View file @
76d3406b
...
@@ -268,15 +268,15 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
...
@@ -268,15 +268,15 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
struct
sctp_chunk
*
sctp_make_asconf_update_ip
(
struct
sctp_association
*
,
struct
sctp_chunk
*
sctp_make_asconf_update_ip
(
struct
sctp_association
*
,
union
sctp_addr
*
,
union
sctp_addr
*
,
struct
sockaddr
*
,
struct
sockaddr
*
,
int
,
int
);
int
,
__u16
);
struct
sctp_chunk
*
sctp_make_asconf_set_prim
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
sctp_make_asconf_set_prim
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
);
union
sctp_addr
*
addr
);
struct
sctp_chunk
*
sctp_make_asconf_ack
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
sctp_make_asconf_ack
(
const
struct
sctp_association
*
asoc
,
int
serial
,
int
vparam_len
);
__u32
serial
,
int
vparam_len
);
struct
sctp_chunk
*
sctp_process_asconf
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
sctp_process_asconf
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
asconf
,
struct
sctp_chunk
*
asconf
);
int
vparam_len
);
int
sctp_process_asconf_ack
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
asconf_ack
);
void
sctp_chunk_assign_tsn
(
struct
sctp_chunk
*
);
void
sctp_chunk_assign_tsn
(
struct
sctp_chunk
*
);
void
sctp_chunk_assign_ssn
(
struct
sctp_chunk
*
);
void
sctp_chunk_assign_ssn
(
struct
sctp_chunk
*
);
...
@@ -431,6 +431,21 @@ static inline int SSN_lte(__u16 s, __u16 t)
...
@@ -431,6 +431,21 @@ static inline int SSN_lte(__u16 s, __u16 t)
return
(((
s
)
==
(
t
))
||
(((
s
)
-
(
t
))
&
SSN_SIGN_BIT
));
return
(((
s
)
==
(
t
))
||
(((
s
)
-
(
t
))
&
SSN_SIGN_BIT
));
}
}
/*
* ADDIP 3.1.1
* The valid range of Serial Number is from 0 to 4294967295 (2**32 - 1). Serial
* Numbers wrap back to 0 after reaching 4294967295.
*/
enum
{
ADDIP_SERIAL_SIGN_BIT
=
(
1
<<
31
)
};
static
inline
int
ADDIP_SERIAL_gte
(
__u16
s
,
__u16
t
)
{
return
(((
s
)
==
(
t
))
||
(((
t
)
-
(
s
))
&
ADDIP_SERIAL_SIGN_BIT
));
}
/* Run sctp_add_cmd() generating a BUG() if there is a failure. */
/* Run sctp_add_cmd() generating a BUG() if there is a failure. */
static
inline
void
sctp_add_cmd_sf
(
sctp_cmd_seq_t
*
seq
,
sctp_verb_t
verb
,
sctp_arg_t
obj
)
static
inline
void
sctp_add_cmd_sf
(
sctp_cmd_seq_t
*
seq
,
sctp_verb_t
verb
,
sctp_arg_t
obj
)
{
{
...
...
include/net/sctp/structs.h
View file @
76d3406b
...
@@ -190,6 +190,9 @@ extern struct sctp_globals {
...
@@ -190,6 +190,9 @@ extern struct sctp_globals {
*/
*/
struct
list_head
local_addr_list
;
struct
list_head
local_addr_list
;
spinlock_t
local_addr_lock
;
spinlock_t
local_addr_lock
;
/* Flag to indicate if addip is enabled. */
int
addip_enable
;
}
sctp_globals
;
}
sctp_globals
;
#define sctp_rto_initial (sctp_globals.rto_initial)
#define sctp_rto_initial (sctp_globals.rto_initial)
...
@@ -217,6 +220,7 @@ extern struct sctp_globals {
...
@@ -217,6 +220,7 @@ extern struct sctp_globals {
#define sctp_port_hashtable (sctp_globals.port_hashtable)
#define sctp_port_hashtable (sctp_globals.port_hashtable)
#define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_lock (sctp_globals.local_addr_lock)
#define sctp_local_addr_lock (sctp_globals.local_addr_lock)
#define sctp_addip_enable (sctp_globals.addip_enable)
/* SCTP Socket type: UDP or TCP style. */
/* SCTP Socket type: UDP or TCP style. */
typedef
enum
{
typedef
enum
{
...
@@ -1397,6 +1401,11 @@ struct sctp_association {
...
@@ -1397,6 +1401,11 @@ struct sctp_association {
/* Does peer support ADDIP? */
/* Does peer support ADDIP? */
__u8
asconf_capable
;
__u8
asconf_capable
;
/* This mask is used to disable sending the ASCONF chunk
* with specified parameter to peer.
*/
__u16
addip_disabled_mask
;
struct
sctp_inithdr
i
;
struct
sctp_inithdr
i
;
int
cookie_len
;
int
cookie_len
;
void
*
cookie
;
void
*
cookie
;
...
@@ -1708,6 +1717,8 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
...
@@ -1708,6 +1717,8 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
struct
sctp_transport
*
sctp_assoc_add_peer
(
struct
sctp_association
*
,
struct
sctp_transport
*
sctp_assoc_add_peer
(
struct
sctp_association
*
,
const
union
sctp_addr
*
address
,
const
union
sctp_addr
*
address
,
const
int
gfp
);
const
int
gfp
);
void
sctp_assoc_del_peer
(
struct
sctp_association
*
asoc
,
const
union
sctp_addr
*
addr
);
void
sctp_assoc_control_transport
(
struct
sctp_association
*
,
void
sctp_assoc_control_transport
(
struct
sctp_association
*
,
struct
sctp_transport
*
,
struct
sctp_transport
*
,
sctp_transport_cmd_t
,
sctp_sn_error_t
);
sctp_transport_cmd_t
,
sctp_sn_error_t
);
...
...
net/sctp/associola.c
View file @
76d3406b
...
@@ -362,6 +362,14 @@ void sctp_association_free(struct sctp_association *asoc)
...
@@ -362,6 +362,14 @@ void sctp_association_free(struct sctp_association *asoc)
asoc
->
eyecatcher
=
0
;
asoc
->
eyecatcher
=
0
;
/* Free any cached ASCONF_ACK chunk. */
if
(
asoc
->
addip_last_asconf_ack
)
sctp_chunk_free
(
asoc
->
addip_last_asconf_ack
);
/* Free any cached ASCONF chunk. */
if
(
asoc
->
addip_last_asconf
)
sctp_chunk_free
(
asoc
->
addip_last_asconf
);
sctp_association_put
(
asoc
);
sctp_association_put
(
asoc
);
}
}
...
@@ -525,6 +533,45 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
...
@@ -525,6 +533,45 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
return
peer
;
return
peer
;
}
}
/* Delete a transport address from an association. */
void
sctp_assoc_del_peer
(
struct
sctp_association
*
asoc
,
const
union
sctp_addr
*
addr
)
{
struct
list_head
*
pos
;
struct
list_head
*
temp
;
struct
sctp_transport
*
peer
=
NULL
;
struct
sctp_transport
*
transport
;
list_for_each_safe
(
pos
,
temp
,
&
asoc
->
peer
.
transport_addr_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
if
(
sctp_cmp_addr_exact
(
addr
,
&
transport
->
ipaddr
))
{
peer
=
transport
;
list_del
(
pos
);
break
;
}
}
/* The address we want delete is not in the association. */
if
(
!
peer
)
return
;
/* Get the first transport of asoc. */
pos
=
asoc
->
peer
.
transport_addr_list
.
next
;
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
/* Update any entries that match the peer to be deleted. */
if
(
asoc
->
peer
.
primary_path
==
peer
)
sctp_assoc_set_primary
(
asoc
,
transport
);
if
(
asoc
->
peer
.
active_path
==
peer
)
asoc
->
peer
.
active_path
=
transport
;
if
(
asoc
->
peer
.
retran_path
==
peer
)
asoc
->
peer
.
retran_path
=
transport
;
if
(
asoc
->
peer
.
last_data_from
==
peer
)
asoc
->
peer
.
last_data_from
=
transport
;
sctp_transport_free
(
peer
);
}
/* Lookup a transport by address. */
/* Lookup a transport by address. */
struct
sctp_transport
*
sctp_assoc_lookup_paddr
(
struct
sctp_transport
*
sctp_assoc_lookup_paddr
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_association
*
asoc
,
...
...
net/sctp/input.c
View file @
76d3406b
...
@@ -124,16 +124,16 @@ int sctp_rcv(struct sk_buff *skb)
...
@@ -124,16 +124,16 @@ int sctp_rcv(struct sk_buff *skb)
/* Pull up the IP and SCTP headers. */
/* Pull up the IP and SCTP headers. */
__skb_pull
(
skb
,
skb
->
h
.
raw
-
skb
->
data
);
__skb_pull
(
skb
,
skb
->
h
.
raw
-
skb
->
data
);
if
(
skb
->
len
<
sizeof
(
struct
sctphdr
))
if
(
skb
->
len
<
sizeof
(
struct
sctphdr
))
goto
bad_packe
t
;
goto
discard_i
t
;
if
(
sctp_rcv_checksum
(
skb
)
<
0
)
if
(
sctp_rcv_checksum
(
skb
)
<
0
)
goto
bad_packe
t
;
goto
discard_i
t
;
skb_pull
(
skb
,
sizeof
(
struct
sctphdr
));
skb_pull
(
skb
,
sizeof
(
struct
sctphdr
));
family
=
ipver2af
(
skb
->
nh
.
iph
->
version
);
family
=
ipver2af
(
skb
->
nh
.
iph
->
version
);
af
=
sctp_get_af_specific
(
family
);
af
=
sctp_get_af_specific
(
family
);
if
(
unlikely
(
!
af
))
if
(
unlikely
(
!
af
))
goto
bad_packe
t
;
goto
discard_i
t
;
/* Initialize local addresses for lookups. */
/* Initialize local addresses for lookups. */
af
->
from_skb
(
&
src
,
skb
,
1
);
af
->
from_skb
(
&
src
,
skb
,
1
);
...
@@ -223,9 +223,6 @@ int sctp_rcv(struct sk_buff *skb)
...
@@ -223,9 +223,6 @@ int sctp_rcv(struct sk_buff *skb)
sock_put
(
sk
);
sock_put
(
sk
);
return
ret
;
return
ret
;
bad_packet:
SCTP_INC_STATS
(
SctpChecksumErrors
);
discard_it:
discard_it:
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
ret
;
return
ret
;
...
...
net/sctp/outqueue.c
View file @
76d3406b
...
@@ -150,7 +150,7 @@ static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary,
...
@@ -150,7 +150,7 @@ static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary,
if
(
!
primary
->
cacc
.
cycling_changeover
)
{
if
(
!
primary
->
cacc
.
cycling_changeover
)
{
if
(
sctp_cacc_skip_3_1_d
(
primary
,
transport
,
count_of_newacks
))
if
(
sctp_cacc_skip_3_1_d
(
primary
,
transport
,
count_of_newacks
))
return
1
;
return
1
;
if
(
sctp_cacc_skip_3_1_f
(
transport
,
count_of_newacks
))
;
if
(
sctp_cacc_skip_3_1_f
(
transport
,
count_of_newacks
))
return
1
;
return
1
;
return
0
;
return
0
;
}
}
...
...
net/sctp/protocol.c
View file @
76d3406b
...
@@ -1115,6 +1115,9 @@ __init int sctp_init(void)
...
@@ -1115,6 +1115,9 @@ __init int sctp_init(void)
"(established %d bind %d)
\n
"
,
"(established %d bind %d)
\n
"
,
sctp_assoc_hashsize
,
sctp_port_hashsize
);
sctp_assoc_hashsize
,
sctp_port_hashsize
);
/* Disable ADDIP by default. */
sctp_addip_enable
=
0
;
sctp_sysctl_register
();
sctp_sysctl_register
();
INIT_LIST_HEAD
(
&
sctp_address_families
);
INIT_LIST_HEAD
(
&
sctp_address_families
);
...
...
net/sctp/sm_make_chunk.c
View file @
76d3406b
This diff is collapsed.
Click to expand it.
net/sctp/sm_sideeffect.c
View file @
76d3406b
...
@@ -663,10 +663,11 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds,
...
@@ -663,10 +663,11 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds,
struct
sock
*
sk
=
asoc
->
base
.
sk
;
struct
sock
*
sk
=
asoc
->
base
.
sk
;
/* If it is a non-temporary association belonging to a TCP-style
/* If it is a non-temporary association belonging to a TCP-style
* listening socket
, do not free it so that accept() can pick it
* listening socket
that is not closed, do not free it so that accept()
* up later.
*
can pick it
up later.
*/
*/
if
(
sctp_style
(
sk
,
TCP
)
&&
sctp_sstate
(
sk
,
LISTENING
)
&&
(
!
asoc
->
temp
))
if
(
sctp_style
(
sk
,
TCP
)
&&
sctp_sstate
(
sk
,
LISTENING
)
&&
(
!
asoc
->
temp
)
&&
(
sk
->
sk_shutdown
!=
SHUTDOWN_MASK
))
return
;
return
;
sctp_unhash_established
(
asoc
);
sctp_unhash_established
(
asoc
);
...
...
net/sctp/sm_statefuns.c
View file @
76d3406b
...
@@ -46,6 +46,7 @@
...
@@ -46,6 +46,7 @@
* Daisy Chang <daisyc@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
* Ryan Layer <rmlayer@us.ibm.com>
* Kevin Gao <kevin.gao@intel.com>
*
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
* be incorporated into the next SCTP release.
...
@@ -3066,19 +3067,57 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
...
@@ -3066,19 +3067,57 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
return
sctp_sf_shut_8_4_5
(
ep
,
NULL
,
type
,
arg
,
commands
);
return
sctp_sf_shut_8_4_5
(
ep
,
NULL
,
type
,
arg
,
commands
);
}
}
/*
/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */
* ADDIP Section 4.2 Upon reception of an ASCONF Chunk
* When an endpoint receive an ASCONF Chunk from the remote peer
* special procedures MAY be needed to identify the association the
* ASCONF Chunk is associated with. To properly find the association
* the following procedures should be L1 to L4 and C1 to C5
*/
sctp_disposition_t
sctp_sf_do_asconf
(
const
struct
sctp_endpoint
*
ep
,
sctp_disposition_t
sctp_sf_do_asconf
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
sctp_cmd_seq_t
*
commands
)
{
{
// FIXME: Handle the ASCONF chunk
struct
sctp_chunk
*
chunk
=
arg
;
struct
sctp_chunk
*
asconf_ack
=
NULL
;
sctp_addiphdr_t
*
hdr
;
__u32
serial
;
hdr
=
(
sctp_addiphdr_t
*
)
chunk
->
skb
->
data
;
serial
=
ntohl
(
hdr
->
serial
);
/* ADDIP 4.2 C1) Compare the value of the serial number to the value
* the endpoint stored in a new association variable
* 'Peer-Serial-Number'.
*/
if
(
serial
==
asoc
->
peer
.
addip_serial
+
1
)
{
/* ADDIP 4.2 C2) If the value found in the serial number is
* equal to the ('Peer-Serial-Number' + 1), the endpoint MUST
* do V1-V5.
*/
asconf_ack
=
sctp_process_asconf
((
struct
sctp_association
*
)
asoc
,
chunk
);
if
(
!
asconf_ack
)
return
SCTP_DISPOSITION_NOMEM
;
}
else
if
(
serial
==
asoc
->
peer
.
addip_serial
)
{
/* ADDIP 4.2 C3) If the value found in the serial number is
* equal to the value stored in the 'Peer-Serial-Number'
* IMPLEMENTATION NOTE: As an optimization a receiver may wish
* to save the last ASCONF-ACK for some predetermined period of * time and instead of re-processing the ASCONF (with the same
* serial number) it may just re-transmit the ASCONF-ACK.
*/
if
(
asoc
->
addip_last_asconf_ack
)
asconf_ack
=
asoc
->
addip_last_asconf_ack
;
else
return
SCTP_DISPOSITION_DISCARD
;
}
else
{
/* ADDIP 4.2 C4) Otherwise, the ASCONF Chunk is discarded since
* it must be either a stale packet or from an attacker.
*/
return
SCTP_DISPOSITION_DISCARD
;
}
/* ADDIP 4.2 C5) In both cases C2 and C3 the ASCONF-ACK MUST be sent
* back to the source address contained in the IP header of the ASCONF
* being responded to.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
asconf_ack
));
return
SCTP_DISPOSITION_CONSUME
;
return
SCTP_DISPOSITION_CONSUME
;
}
}
...
@@ -3088,12 +3127,76 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
...
@@ -3088,12 +3127,76 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
* delete IP addresses the D0 to D13 rules should be applied:
* delete IP addresses the D0 to D13 rules should be applied:
*/
*/
sctp_disposition_t
sctp_sf_do_asconf_ack
(
const
struct
sctp_endpoint
*
ep
,
sctp_disposition_t
sctp_sf_do_asconf_ack
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
sctp_cmd_seq_t
*
commands
)
{
{
// FIXME: Handle the ASCONF-ACK chunk
struct
sctp_chunk
*
asconf_ack
=
arg
;
return
SCTP_DISPOSITION_CONSUME
;
struct
sctp_chunk
*
last_asconf
=
asoc
->
addip_last_asconf
;
struct
sctp_chunk
*
abort
;
sctp_addiphdr_t
*
addip_hdr
;
__u32
sent_serial
,
rcvd_serial
;
addip_hdr
=
(
sctp_addiphdr_t
*
)
asconf_ack
->
skb
->
data
;
rcvd_serial
=
ntohl
(
addip_hdr
->
serial
);
if
(
last_asconf
)
{
addip_hdr
=
(
sctp_addiphdr_t
*
)
last_asconf
->
subh
.
addip_hdr
;
sent_serial
=
ntohl
(
addip_hdr
->
serial
);
}
else
{
sent_serial
=
asoc
->
addip_serial
-
1
;
}
/* D0) If an endpoint receives an ASCONF-ACK that is greater than or
* equal to the next serial number to be used but no ASCONF chunk is
* outstanding the endpoint MUST ABORT the association. Note that a
* sequence number is greater than if it is no more than 2^^31-1
* larger than the current sequence number (using serial arithmetic).
*/
if
(
ADDIP_SERIAL_gte
(
rcvd_serial
,
sent_serial
+
1
)
&&
!
(
asoc
->
addip_last_asconf
))
{
abort
=
sctp_make_abort
(
asoc
,
asconf_ack
,
sizeof
(
sctp_errhdr_t
));
if
(
abort
)
{
sctp_init_cause
(
abort
,
SCTP_ERROR_ASCONF_ACK
,
NULL
,
0
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
abort
));
}
/* We are going to ABORT, so we might as well stop
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_ASCONF_ACK
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_ABORT
;
}
if
((
rcvd_serial
==
sent_serial
)
&&
asoc
->
addip_last_asconf
)
{
if
(
!
sctp_process_asconf_ack
((
struct
sctp_association
*
)
asoc
,
asconf_ack
))
return
SCTP_DISPOSITION_CONSUME
;
abort
=
sctp_make_abort
(
asoc
,
asconf_ack
,
sizeof
(
sctp_errhdr_t
));
if
(
abort
)
{
sctp_init_cause
(
abort
,
SCTP_ERROR_RSRC_LOW
,
NULL
,
0
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
abort
));
}
/* We are going to ABORT, so we might as well stop
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_ASCONF_ACK
));
SCTP_INC_STATS
(
SctpAborteds
);
SCTP_DEC_STATS
(
SctpCurrEstab
);
return
SCTP_DISPOSITION_ABORT
;
}
return
SCTP_DISPOSITION_DISCARD
;
}
}
/*
/*
...
...
net/sctp/sm_statetable.c
View file @
76d3406b
/* SCTP kernel reference Implementation
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 Nokia, Inc.
*
*
...
@@ -921,13 +921,15 @@ const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
...
@@ -921,13 +921,15 @@ const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
if
(
state
>
SCTP_STATE_MAX
)
if
(
state
>
SCTP_STATE_MAX
)
return
&
bug
;
return
&
bug
;
if
(
cid
>=
0
&&
cid
<=
SCTP_CID_BASE_MAX
)
{
if
(
cid
>=
0
&&
cid
<=
SCTP_CID_BASE_MAX
)
return
&
chunk_event_table
[
cid
][
state
];
return
&
chunk_event_table
[
cid
][
state
];
}
if
(
cid
>=
SCTP_CID_ADDIP_MIN
&&
cid
<=
SCTP_CID_ADDIP_MAX
)
{
if
(
sctp_addip_enable
)
{
return
&
addip_chunk_event_table
if
(
cid
==
SCTP_CID_ASCONF
)
[
cid
-
SCTP_CID_ADDIP_MIN
][
state
];
return
&
addip_chunk_event_table
[
0
][
state
];
if
(
cid
==
SCTP_CID_ASCONF_ACK
)
return
&
addip_chunk_event_table
[
1
][
state
];
}
}
return
&
chunk_event_table_unknown
[
state
];
return
&
chunk_event_table_unknown
[
state
];
...
...
net/sctp/socket.c
View file @
76d3406b
...
@@ -100,6 +100,8 @@ static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
...
@@ -100,6 +100,8 @@ static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
static
int
sctp_bindx_rem
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_bindx_rem
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_send_asconf_add_ip
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_send_asconf_add_ip
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_send_asconf_del_ip
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_send_asconf_del_ip
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_send_asconf
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
);
static
int
sctp_do_bind
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
static
int
sctp_do_bind
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
static
int
sctp_autobind
(
struct
sock
*
sk
);
static
int
sctp_autobind
(
struct
sock
*
sk
);
static
void
sctp_sock_migrate
(
struct
sock
*
,
struct
sock
*
,
static
void
sctp_sock_migrate
(
struct
sock
*
,
struct
sock
*
,
...
@@ -300,6 +302,41 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
...
@@ -300,6 +302,41 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
return
ret
;
return
ret
;
}
}
/* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
*
* R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged
* at any one time. If a sender, after sending an ASCONF chunk, decides
* it needs to transfer another ASCONF Chunk, it MUST wait until the
* ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a
* subsequent ASCONF. Note this restriction binds each side, so at any
* time two ASCONF may be in-transit on any given association (one sent
* from each endpoint).
*/
static
int
sctp_send_asconf
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
)
{
int
retval
=
0
;
/* If there is an outstanding ASCONF chunk, queue it for later
* transmission.
*/
if
(
asoc
->
addip_last_asconf
)
{
__skb_queue_tail
(
&
asoc
->
addip_chunks
,
(
struct
sk_buff
*
)
chunk
);
goto
out
;
}
/* Hold the chunk until an ASCONF_ACK is received. */
sctp_chunk_hold
(
chunk
);
retval
=
sctp_primitive_ASCONF
(
asoc
,
chunk
);
if
(
retval
)
sctp_chunk_free
(
chunk
);
else
asoc
->
addip_last_asconf
=
chunk
;
out:
return
retval
;
}
/* Add a list of addresses as bind addresses to local endpoint or
/* Add a list of addresses as bind addresses to local endpoint or
* association.
* association.
*
*
...
@@ -380,6 +417,9 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
...
@@ -380,6 +417,9 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
int
i
;
int
i
;
int
retval
=
0
;
int
retval
=
0
;
if
(
!
sctp_addip_enable
)
return
retval
;
sp
=
sctp_sk
(
sk
);
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
ep
=
sp
->
ep
;
...
@@ -389,12 +429,15 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
...
@@ -389,12 +429,15 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
list_for_each
(
pos
,
&
ep
->
asocs
)
{
list_for_each
(
pos
,
&
ep
->
asocs
)
{
asoc
=
list_entry
(
pos
,
struct
sctp_association
,
asocs
);
asoc
=
list_entry
(
pos
,
struct
sctp_association
,
asocs
);
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
)
)
if
(
!
asoc
->
peer
.
asconf_capable
)
continue
;
continue
;
if
(
!
asoc
->
peer
.
asconf_capable
)
if
(
asoc
->
peer
.
addip_disabled_mask
&
SCTP_PARAM_ADD_IP
)
continue
;
continue
;
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
continue
;
/* Check if any address in the packed array of addresses is
/* Check if any address in the packed array of addresses is
* in the bind address list of the association. If so,
* in the bind address list of the association. If so,
* do not send the asconf chunk to its peer, but continue with
* do not send the asconf chunk to its peer, but continue with
...
@@ -409,9 +452,9 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
...
@@ -409,9 +452,9 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
goto
out
;
goto
out
;
}
}
if
(
sctp_assoc_lookup_laddr
(
asoc
,
addr
))
if
(
sctp_assoc_lookup_laddr
(
asoc
,
addr
))
break
;
break
;
addr_buf
+=
af
->
sockaddr_len
;
addr_buf
+=
af
->
sockaddr_len
;
}
}
if
(
i
<
addrcnt
)
if
(
i
<
addrcnt
)
...
@@ -433,14 +476,14 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
...
@@ -433,14 +476,14 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
goto
out
;
goto
out
;
}
}
retval
=
sctp_
primitive_ASCONF
(
asoc
,
chunk
);
retval
=
sctp_
send_asconf
(
asoc
,
chunk
);
if
(
retval
)
{
if
(
retval
)
{
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
goto
out
;
goto
out
;
}
}
/* FIXME: After sending the add address ASCONF chunk, we
/* FIXME: After sending the add address ASCONF chunk, we
* cannot append the address to the association's binding
* cannot append the address to the association's binding
* address list, because the new address may be used as the
* address list, because the new address may be used as the
* source of a message sent to the peer before the ASCONF
* source of a message sent to the peer before the ASCONF
* chunk is received by the peer. So we should wait until
* chunk is received by the peer. So we should wait until
...
@@ -565,6 +608,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
...
@@ -565,6 +608,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
int
i
;
int
i
;
int
retval
=
0
;
int
retval
=
0
;
if
(
!
sctp_addip_enable
)
return
retval
;
sp
=
sctp_sk
(
sk
);
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
ep
=
sp
->
ep
;
...
@@ -574,10 +620,13 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
...
@@ -574,10 +620,13 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
list_for_each
(
pos
,
&
ep
->
asocs
)
{
list_for_each
(
pos
,
&
ep
->
asocs
)
{
asoc
=
list_entry
(
pos
,
struct
sctp_association
,
asocs
);
asoc
=
list_entry
(
pos
,
struct
sctp_association
,
asocs
);
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
)
)
if
(
!
asoc
->
peer
.
asconf_capable
)
continue
;
continue
;
if
(
!
asoc
->
peer
.
asconf_capable
)
if
(
asoc
->
peer
.
addip_disabled_mask
&
SCTP_PARAM_DEL_IP
)
continue
;
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
continue
;
continue
;
/* Check if any address in the packed array of addresses is
/* Check if any address in the packed array of addresses is
...
@@ -594,9 +643,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
...
@@ -594,9 +643,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
goto
out
;
goto
out
;
}
}
if
(
!
sctp_assoc_lookup_laddr
(
asoc
,
laddr
))
if
(
!
sctp_assoc_lookup_laddr
(
asoc
,
laddr
))
break
;
break
;
addr_buf
+=
af
->
sockaddr_len
;
addr_buf
+=
af
->
sockaddr_len
;
}
}
if
(
i
<
addrcnt
)
if
(
i
<
addrcnt
)
...
@@ -611,18 +660,18 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
...
@@ -611,18 +660,18 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
bp
=
&
asoc
->
base
.
bind_addr
;
bp
=
&
asoc
->
base
.
bind_addr
;
laddr
=
sctp_find_unmatch_addr
(
bp
,
(
union
sctp_addr
*
)
addrs
,
laddr
=
sctp_find_unmatch_addr
(
bp
,
(
union
sctp_addr
*
)
addrs
,
addrcnt
,
sp
);
addrcnt
,
sp
);
sctp_read_unlock
(
&
asoc
->
base
.
addr_lock
);
sctp_read_unlock
(
&
asoc
->
base
.
addr_lock
);
if
(
!
laddr
)
if
(
!
laddr
)
continue
;
continue
;
chunk
=
sctp_make_asconf_update_ip
(
asoc
,
laddr
,
addrs
,
addrcnt
,
chunk
=
sctp_make_asconf_update_ip
(
asoc
,
laddr
,
addrs
,
addrcnt
,
SCTP_PARAM_DEL_IP
);
SCTP_PARAM_DEL_IP
);
if
(
!
chunk
)
{
if
(
!
chunk
)
{
retval
=
-
ENOMEM
;
retval
=
-
ENOMEM
;
goto
out
;
goto
out
;
}
}
retval
=
sctp_
primitive_ASCONF
(
asoc
,
chunk
);
retval
=
sctp_
send_asconf
(
asoc
,
chunk
);
if
(
retval
)
{
if
(
retval
)
{
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
goto
out
;
goto
out
;
...
@@ -631,7 +680,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
...
@@ -631,7 +680,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
/* FIXME: After sending the delete address ASCONF chunk, we
/* FIXME: After sending the delete address ASCONF chunk, we
* cannot remove the addresses from the association's bind
* cannot remove the addresses from the association's bind
* address list, because there maybe some packet send to
* address list, because there maybe some packet send to
* the delete addresses, so we should wait until ASCONF_ACK
* the delete addresses, so we should wait until ASCONF_ACK
* packet is received.
* packet is received.
*/
*/
}
}
...
@@ -1920,6 +1969,9 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
...
@@ -1920,6 +1969,9 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
sp
=
sctp_sk
(
sk
);
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
ep
=
sp
->
ep
;
if
(
!
sctp_addip_enable
)
return
-
EPERM
;
if
(
optlen
!=
sizeof
(
struct
sctp_setpeerprim
))
if
(
optlen
!=
sizeof
(
struct
sctp_setpeerprim
))
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -1930,6 +1982,12 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
...
@@ -1930,6 +1982,12 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
if
(
!
asoc
)
if
(
!
asoc
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
!
asoc
->
peer
.
asconf_capable
)
return
-
EPERM
;
if
(
asoc
->
peer
.
addip_disabled_mask
&
SCTP_PARAM_SET_PRIMARY
)
return
-
EPERM
;
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
return
-
ENOTCONN
;
return
-
ENOTCONN
;
...
@@ -1942,7 +2000,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
...
@@ -1942,7 +2000,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
if
(
!
chunk
)
if
(
!
chunk
)
return
-
ENOMEM
;
return
-
ENOMEM
;
err
=
sctp_
primitive_ASCONF
(
asoc
,
chunk
);
err
=
sctp_
send_asconf
(
asoc
,
chunk
);
if
(
err
)
{
if
(
err
)
{
sctp_chunk_free
(
chunk
);
sctp_chunk_free
(
chunk
);
return
err
;
return
err
;
...
...
net/sctp/sysctl.c
View file @
76d3406b
...
@@ -162,6 +162,14 @@ static ctl_table sctp_table[] = {
...
@@ -162,6 +162,14 @@ static ctl_table sctp_table[] = {
.
mode
=
0644
,
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
.
proc_handler
=
&
proc_dointvec
},
},
{
.
ctl_name
=
NET_SCTP_ADDIP_ENABLE
,
.
procname
=
"addip_enable"
,
.
data
=
&
sctp_addip_enable
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
},
{
.
ctl_name
=
0
}
{
.
ctl_name
=
0
}
};
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment