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
3e94542b
Commit
3e94542b
authored
Sep 28, 2003
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.6.0-test6
into us.ibm.com:/home/sridhar/BK/lksctp-2.6.0-test6
parents
e0618466
f51c1494
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
438 additions
and
150 deletions
+438
-150
include/linux/sctp.h
include/linux/sctp.h
+0
-109
include/net/sctp/command.h
include/net/sctp/command.h
+4
-2
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+13
-16
include/net/sctp/sm.h
include/net/sctp/sm.h
+9
-3
include/net/sctp/structs.h
include/net/sctp/structs.h
+8
-0
net/sctp/associola.c
net/sctp/associola.c
+5
-0
net/sctp/bind_addr.c
net/sctp/bind_addr.c
+37
-0
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+105
-12
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+42
-1
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+4
-1
net/sctp/socket.c
net/sctp/socket.c
+211
-6
No files found.
include/linux/sctp.h
View file @
3e94542b
...
@@ -524,113 +524,4 @@ typedef struct sctp_addip_chunk {
...
@@ -524,113 +524,4 @@ typedef struct sctp_addip_chunk {
sctp_addiphdr_t
addip_hdr
;
sctp_addiphdr_t
addip_hdr
;
}
sctp_addip_chunk_t
__attribute__
((
packed
));
}
sctp_addip_chunk_t
__attribute__
((
packed
));
/* FIXME: Cleanup needs to continue below this line. */
/* ADDIP Section 3.1.1
*
* ASCONF-Request Correlation ID: 32 bits (unsigned integer)
*
* This is an opaque integer assigned by the sender to identify each
* request parameter. It is in host byte order and is only meaningful
* to the sender. The receiver of the ASCONF Chunk will copy this 32
* bit value into the ASCONF Correlation ID field of the
* ASCONF-ACK. The sender of the ASCONF can use this same value in the
* ASCONF-ACK to find which request the response is for.
*
* ASCONF Parameter: TLV format
*
* Each Address configuration change is represented by a TLV parameter
* as defined in Section 3.2. One or more requests may be present in
* an ASCONF Chunk.
*/
typedef
struct
{
__u32
correlation
;
sctp_paramhdr_t
p
;
__u8
payload
[
0
];
}
sctpAsconfReq_t
;
/* ADDIP
* 3.1.1 Address/Stream Configuration Change Chunk (ASCONF)
*
* This chunk is used to communicate to the remote endpoint one of the
* configuration change requests that MUST be acknowledged. The
* information carried in the ASCONF Chunk uses the form of a
* Tag-Length-Value (TLV), as described in "3.2.1
* Optional/Variable-length Parameter Format" in [RFC2960], for all
* variable parameters.
*/
typedef
struct
{
__u32
serial
;
__u8
reserved
[
3
];
__u8
addr_type
;
__u32
addr
[
4
];
sctpAsconfReq_t
requests
[
0
];
}
sctpAsconf_t
;
/* ADDIP
* 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK)
*
* ASCONF-Request Correlation ID: 32 bits (unsigned integer)
*
* This value is copied from the ASCONF Correlation ID received in the
* ASCONF Chunk. It is used by the receiver of the ASCONF-ACK to identify
* which ASCONF parameter this response is associated with.
*
* ASCONF Parameter Response : TLV format
*
* The ASCONF Parameter Response is used in the ASCONF-ACK to report
* status of ASCONF processing. By default, if a responding endpoint
* does not include any Error Cause, a success is indicated. Thus a
* sender of an ASCONF-ACK MAY indicate complete success of all TLVs in
* an ASCONF by returning only the Chunk Type, Chunk Flags, Chunk Length
* (set to 8) and the Serial Number.
*/
typedef
union
{
struct
{
__u32
correlation
;
sctp_paramhdr_t
header
;
/* success report */
}
success
;
struct
{
__u32
correlation
;
sctp_paramhdr_t
header
;
/* error cause indication */
sctp_paramhdr_t
errcause
;
uint8_t
request
[
0
];
/* original request from ASCONF */
}
error
;
#define __correlation success.correlation
#define __header success.header
#define __cause error.errcause
#define __request error.request
}
sctpAsconfAckRsp_t
;
/* ADDIP
* 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK)
*
* This chunk is used by the receiver of an ASCONF Chunk to
* acknowledge the reception. It carries zero or more results for any
* ASCONF Parameters that were processed by the receiver.
*/
typedef
struct
{
__u32
serial
;
sctpAsconfAckRsp_t
responses
[
0
];
}
sctpAsconfAck_t
;
/*********************************************************************
* Internal structures
*
* These are data structures which never go out on the wire.
*********************************************************************/
/* What is this data structure for? The TLV isn't one--it is just a
* value. Perhaps this data structure ought to have a type--otherwise
* it is not unambigiously parseable. --piggy
*/
typedef
struct
{
struct
list_head
hook
;
int
length
;
/* length of the TLV */
/* the actually TLV to be copied into ASCONF_ACK */
sctpAsconfAckRsp_t
TLV
;
}
sctpAsconfAckRspNode_t
;
#endif
/* __LINUX_SCTP_H__ */
#endif
/* __LINUX_SCTP_H__ */
include/net/sctp/command.h
View file @
3e94542b
/* SCTP kernel reference Implementation Copyright (C) 1999-2001
/* SCTP kernel reference Implementation
* Cisco, Motorola, and IBM
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (C) 1999-2001 Cisco, Motorola
*
*
* This file is part of the SCTP kernel reference Implementation
* This file is part of the SCTP kernel reference Implementation
*
*
...
@@ -88,6 +89,7 @@ typedef enum {
...
@@ -88,6 +89,7 @@ typedef enum {
SCTP_CMD_PART_DELIVER
,
/* Partial data delivery considerations. */
SCTP_CMD_PART_DELIVER
,
/* Partial data delivery considerations. */
SCTP_CMD_RENEGE
,
/* Renege data on an association. */
SCTP_CMD_RENEGE
,
/* Renege data on an association. */
SCTP_CMD_SETUP_T4
,
/* ADDIP, setup T4 RTO timer parms. */
SCTP_CMD_SETUP_T4
,
/* ADDIP, setup T4 RTO timer parms. */
SCTP_CMD_PROCESS_OPERR
,
/* Process an ERROR chunk. */
SCTP_CMD_LAST
SCTP_CMD_LAST
}
sctp_verb_t
;
}
sctp_verb_t
;
...
...
include/net/sctp/sctp.h
View file @
3e94542b
...
@@ -495,22 +495,19 @@ for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
...
@@ -495,22 +495,19 @@ for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
#define tv_lt(s, t) \
#define tv_lt(s, t) \
(s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec))
(s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec))
/* Stolen from net/profile.h. Using it from there is more grief than
/* Add tv1 to tv2. */
* it is worth.
#define TIMEVAL_ADD(tv1, tv2) \
*/
({ \
static
inline
void
tv_add
(
const
struct
timeval
*
entered
,
struct
timeval
*
leaved
)
suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \
{
time_t secs = (tv2).tv_sec + (tv1).tv_sec; \
time_t
usecs
=
leaved
->
tv_usec
+
entered
->
tv_usec
;
\
time_t
secs
=
leaved
->
tv_sec
+
entered
->
tv_sec
;
if (usecs >= 1000000) { \
usecs -= 1000000; \
if
(
usecs
>=
1000000
)
{
secs++; \
usecs
-=
1000000
;
} \
secs
++
;
(tv2).tv_sec = secs; \
}
(tv2).tv_usec = usecs; \
leaved
->
tv_sec
=
secs
;
})
leaved
->
tv_usec
=
usecs
;
}
/* External references. */
/* External references. */
...
...
include/net/sctp/sm.h
View file @
3e94542b
...
@@ -265,13 +265,19 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
...
@@ -265,13 +265,19 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
struct
sctp_chunk
*
sctp_make_asconf
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
sctp_make_asconf
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
,
union
sctp_addr
*
addr
,
int
vparam_len
);
int
vparam_len
);
struct
sctp_chunk
*
sctp_make_asconf_update_ip
(
struct
sctp_association
*
,
union
sctp_addr
*
,
struct
sockaddr
*
,
int
,
int
);
struct
sctp_chunk
*
sctp_make_asconf_set_prim
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
);
struct
sctp_chunk
*
sctp_make_asconf_ack
(
struct
sctp_association
*
asoc
,
int
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
vparam_len
);
struct
sctp_chunk
*
sctp_make_asconf_set_prim
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
);
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
*
);
...
...
include/net/sctp/structs.h
View file @
3e94542b
...
@@ -1085,6 +1085,10 @@ int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
...
@@ -1085,6 +1085,10 @@ int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
int
sctp_del_bind_addr
(
struct
sctp_bind_addr
*
,
union
sctp_addr
*
);
int
sctp_del_bind_addr
(
struct
sctp_bind_addr
*
,
union
sctp_addr
*
);
int
sctp_bind_addr_match
(
struct
sctp_bind_addr
*
,
const
union
sctp_addr
*
,
int
sctp_bind_addr_match
(
struct
sctp_bind_addr
*
,
const
union
sctp_addr
*
,
struct
sctp_opt
*
);
struct
sctp_opt
*
);
union
sctp_addr
*
sctp_find_unmatch_addr
(
struct
sctp_bind_addr
*
bp
,
const
union
sctp_addr
*
addrs
,
int
addrcnt
,
struct
sctp_opt
*
opt
);
union
sctp_params
sctp_bind_addrs_to_raw
(
const
struct
sctp_bind_addr
*
bp
,
union
sctp_params
sctp_bind_addrs_to_raw
(
const
struct
sctp_bind_addr
*
bp
,
int
*
addrs_len
,
int
gfp
);
int
*
addrs_len
,
int
gfp
);
int
sctp_raw_to_bind_addrs
(
struct
sctp_bind_addr
*
bp
,
__u8
*
raw
,
int
len
,
int
sctp_raw_to_bind_addrs
(
struct
sctp_bind_addr
*
bp
,
__u8
*
raw
,
int
len
,
...
@@ -1389,6 +1393,10 @@ struct sctp_association {
...
@@ -1389,6 +1393,10 @@ struct sctp_association {
__u8
ipv4_address
;
/* Peer understands IPv4 addresses? */
__u8
ipv4_address
;
/* Peer understands IPv4 addresses? */
__u8
ipv6_address
;
/* Peer understands IPv6 addresses? */
__u8
ipv6_address
;
/* Peer understands IPv6 addresses? */
__u8
hostname_address
;
/* Peer understands DNS addresses? */
__u8
hostname_address
;
/* Peer understands DNS addresses? */
/* Does peer support ADDIP? */
__u8
asconf_capable
;
struct
sctp_inithdr
i
;
struct
sctp_inithdr
i
;
int
cookie_len
;
int
cookie_len
;
void
*
cookie
;
void
*
cookie
;
...
...
net/sctp/associola.c
View file @
3e94542b
...
@@ -246,6 +246,11 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
...
@@ -246,6 +246,11 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
*/
*/
asoc
->
peer
.
sack_needed
=
1
;
asoc
->
peer
.
sack_needed
=
1
;
/* Assume that the peer recongizes ASCONF until reported otherwise
* via an ERROR chunk.
*/
asoc
->
peer
.
asconf_capable
=
1
;
/* Create an input queue. */
/* Create an input queue. */
sctp_inq_init
(
&
asoc
->
base
.
inqueue
);
sctp_inq_init
(
&
asoc
->
base
.
inqueue
);
sctp_inq_set_th_handler
(
&
asoc
->
base
.
inqueue
,
sctp_inq_set_th_handler
(
&
asoc
->
base
.
inqueue
,
...
...
net/sctp/bind_addr.c
View file @
3e94542b
...
@@ -324,6 +324,43 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp,
...
@@ -324,6 +324,43 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp,
return
0
;
return
0
;
}
}
/* Find the first address in the bind address list that is not present in
* the addrs packed array.
*/
union
sctp_addr
*
sctp_find_unmatch_addr
(
struct
sctp_bind_addr
*
bp
,
const
union
sctp_addr
*
addrs
,
int
addrcnt
,
struct
sctp_opt
*
opt
)
{
struct
sctp_sockaddr_entry
*
laddr
;
union
sctp_addr
*
addr
;
void
*
addr_buf
;
struct
sctp_af
*
af
;
struct
list_head
*
pos
;
int
i
;
list_for_each
(
pos
,
&
bp
->
address_list
)
{
laddr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
addr_buf
=
(
union
sctp_addr
*
)
addrs
;
for
(
i
=
0
;
i
<
addrcnt
;
i
++
)
{
addr
=
(
union
sctp_addr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
if
(
!
af
)
return
NULL
;
if
(
opt
->
pf
->
cmp_addr
(
&
laddr
->
a
,
addr
,
opt
))
break
;
addr_buf
+=
af
->
sockaddr_len
;
}
if
(
i
==
addrcnt
)
return
&
laddr
->
a
;
}
return
NULL
;
}
/* Copy out addresses from the global local address list. */
/* Copy out addresses from the global local address list. */
static
int
sctp_copy_one_addr
(
struct
sctp_bind_addr
*
dest
,
static
int
sctp_copy_one_addr
(
struct
sctp_bind_addr
*
dest
,
union
sctp_addr
*
addr
,
union
sctp_addr
*
addr
,
...
...
net/sctp/sm_make_chunk.c
View file @
3e94542b
/* SCTP kernel reference Implementation
/* SCTP kernel reference Implementation
*
Copyright (C)
IBM Corp. 2001, 2003
*
(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-2002 Intel Corp.
* Copyright (c) 2001-2002 Intel Corp.
...
@@ -1288,7 +1288,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
...
@@ -1288,7 +1288,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
/* Set an expiration time for the cookie. */
/* Set an expiration time for the cookie. */
do_gettimeofday
(
&
cookie
->
c
.
expiration
);
do_gettimeofday
(
&
cookie
->
c
.
expiration
);
tv_add
(
&
asoc
->
cookie_life
,
&
cookie
->
c
.
expiration
);
TIMEVAL_ADD
(
asoc
->
cookie_life
,
cookie
->
c
.
expiration
);
/* Copy the peer's init packet. */
/* Copy the peer's init packet. */
memcpy
(
&
cookie
->
c
.
peer_init
[
0
],
init_chunk
->
chunk_hdr
,
memcpy
(
&
cookie
->
c
.
peer_init
[
0
],
init_chunk
->
chunk_hdr
,
...
@@ -2021,11 +2021,11 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
...
@@ -2021,11 +2021,11 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
sctp_addiphdr_t
asconf
;
sctp_addiphdr_t
asconf
;
struct
sctp_chunk
*
retval
;
struct
sctp_chunk
*
retval
;
int
length
=
sizeof
(
asconf
)
+
vparam_len
;
int
length
=
sizeof
(
asconf
)
+
vparam_len
;
union
sctp_
params
addrparam
;
union
sctp_
addr_param
addrparam
;
int
addrlen
;
int
addrlen
;
struct
sctp_af
*
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
struct
sctp_af
*
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
addrlen
=
af
->
to_addr_param
(
addr
,
(
union
sctp_addr_param
*
)
&
addrparam
);
addrlen
=
af
->
to_addr_param
(
addr
,
&
addrparam
);
if
(
!
addrlen
)
if
(
!
addrlen
)
return
NULL
;
return
NULL
;
length
+=
addrlen
;
length
+=
addrlen
;
...
@@ -2045,6 +2045,83 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
...
@@ -2045,6 +2045,83 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
return
retval
;
return
retval
;
}
}
/* ADDIP
* 3.2.1 Add IP Address
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type = 0xC001 | Length = Variable |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ASCONF-Request Correlation ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Address Parameter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* 3.2.2 Delete IP Address
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type = 0xC002 | Length = Variable |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ASCONF-Request Correlation ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Address Parameter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
struct
sctp_chunk
*
sctp_make_asconf_update_ip
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
laddr
,
struct
sockaddr
*
addrs
,
int
addrcnt
,
int
flags
)
{
sctp_addip_param_t
param
;
struct
sctp_chunk
*
retval
;
union
sctp_addr_param
addr_param
;
union
sctp_addr
*
addr
;
void
*
addr_buf
;
struct
sctp_af
*
af
;
int
paramlen
=
sizeof
(
param
);
int
addr_param_len
=
0
;
int
totallen
=
0
;
int
i
;
/* Get total length of all the address parameters. */
addr_buf
=
addrs
;
for
(
i
=
0
;
i
<
addrcnt
;
i
++
)
{
addr
=
(
union
sctp_addr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
addr_param_len
=
af
->
to_addr_param
(
addr
,
&
addr_param
);
totallen
+=
paramlen
;
totallen
+=
addr_param_len
;
addr_buf
+=
af
->
sockaddr_len
;
}
/* Create an asconf chunk with the required length. */
retval
=
sctp_make_asconf
(
asoc
,
laddr
,
totallen
);
if
(
!
retval
)
return
NULL
;
/* Add the address parameters to the asconf chunk. */
addr_buf
=
addrs
;
for
(
i
=
0
;
i
<
addrcnt
;
i
++
)
{
addr
=
(
union
sctp_addr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
addr_param_len
=
af
->
to_addr_param
(
addr
,
&
addr_param
);
param
.
param_hdr
.
type
=
flags
;
param
.
param_hdr
.
length
=
htons
(
paramlen
+
addr_param_len
);
param
.
crr_id
=
htonl
(
i
);
sctp_addto_chunk
(
retval
,
paramlen
,
&
param
);
sctp_addto_chunk
(
retval
,
addr_param_len
,
&
addr_param
);
addr_buf
+=
af
->
sockaddr_len
;
}
return
retval
;
}
/* ADDIP
/* ADDIP
* 3.2.4 Set Primary IP Address
* 3.2.4 Set Primary IP Address
* 0 1 2 3
* 0 1 2 3
...
@@ -2065,11 +2142,11 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
...
@@ -2065,11 +2142,11 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
sctp_addip_param_t
param
;
sctp_addip_param_t
param
;
struct
sctp_chunk
*
retval
;
struct
sctp_chunk
*
retval
;
int
len
=
sizeof
(
param
);
int
len
=
sizeof
(
param
);
union
sctp_
params
addrparam
;
union
sctp_
addr_param
addrparam
;
int
addrlen
;
int
addrlen
;
struct
sctp_af
*
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
struct
sctp_af
*
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
addrlen
=
af
->
to_addr_param
(
addr
,
(
union
sctp_addr_param
*
)
&
addrparam
);
addrlen
=
af
->
to_addr_param
(
addr
,
&
addrparam
);
if
(
!
addrlen
)
if
(
!
addrlen
)
return
NULL
;
return
NULL
;
len
+=
addrlen
;
len
+=
addrlen
;
...
@@ -2089,11 +2166,7 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
...
@@ -2089,11 +2166,7 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
return
retval
;
return
retval
;
}
}
/*
/* ADDIP 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK)
* Unpack the parameters in an ASCONF chunk into an association and
* generate ASCONF-ACK chunk.
*
* ADDIP 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK)
* 0 1 2 3
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...
@@ -2110,8 +2183,28 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
...
@@ -2110,8 +2183,28 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
* | ASCONF Parameter Response#N |
* | ASCONF Parameter Response#N |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
*
All the parameter respoinces will be added in this function.
*
Create an ASCONF_ACK chunk with enough space for the parameter responses.
*/
*/
struct
sctp_chunk
*
sctp_make_asconf_ack
(
struct
sctp_association
*
asoc
,
int
serial
,
int
vparam_len
)
{
sctp_addiphdr_t
asconf
;
struct
sctp_chunk
*
retval
;
int
length
=
sizeof
(
asconf
)
+
vparam_len
;
/* Create the chunk. */
retval
=
sctp_make_chunk
(
asoc
,
SCTP_CID_ASCONF_ACK
,
0
,
length
);
if
(
!
retval
)
return
NULL
;
asconf
.
serial
=
serial
;
retval
->
subh
.
addip_hdr
=
sctp_addto_chunk
(
retval
,
sizeof
(
asconf
),
&
asconf
);
return
retval
;
}
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
vparam_len
)
...
...
net/sctp/sm_sideeffect.c
View file @
3e94542b
/* SCTP kernel reference Implementation
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999 Cisco, Inc.
* Copyright (c) 1999 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* 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
*
*
...
@@ -690,6 +690,44 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
...
@@ -690,6 +690,44 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
chunk
->
transport
=
t
;
chunk
->
transport
=
t
;
}
}
/* Process an incoming Operation Error Chunk. */
static
void
sctp_cmd_process_operr
(
sctp_cmd_seq_t
*
cmds
,
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
)
{
struct
sctp_operr_chunk
*
operr_chunk
;
struct
sctp_errhdr
*
err_hdr
;
operr_chunk
=
(
struct
sctp_operr_chunk
*
)
chunk
->
chunk_hdr
;
err_hdr
=
&
operr_chunk
->
err_hdr
;
switch
(
err_hdr
->
cause
)
{
case
SCTP_ERROR_UNKNOWN_CHUNK
:
{
struct
sctp_chunkhdr
*
unk_chunk_hdr
;
unk_chunk_hdr
=
(
struct
sctp_chunkhdr
*
)
err_hdr
->
variable
;
switch
(
unk_chunk_hdr
->
type
)
{
/* ADDIP 4.1 A9) If the peer responds to an ASCONF with an
* ERROR chunk reporting that it did not recognized the ASCONF
* chunk type, the sender of the ASCONF MUST NOT send any
* further ASCONF chunks and MUST stop its T-4 timer.
*/
case
SCTP_CID_ASCONF
:
asoc
->
peer
.
asconf_capable
=
0
;
sctp_add_cmd_sf
(
cmds
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T4_RTO
));
break
;
default:
break
;
}
break
;
}
default:
break
;
}
}
/* These three macros allow us to pull the debugging code out of the
/* These three macros allow us to pull the debugging code out of the
* main flow of sctp_do_sm() to keep attention focused on the real
* main flow of sctp_do_sm() to keep attention focused on the real
* functionality there.
* functionality there.
...
@@ -1205,6 +1243,9 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
...
@@ -1205,6 +1243,9 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_cmd_setup_t4
(
commands
,
asoc
,
cmd
->
obj
.
ptr
);
sctp_cmd_setup_t4
(
commands
,
asoc
,
cmd
->
obj
.
ptr
);
break
;
break
;
case
SCTP_CMD_PROCESS_OPERR
:
sctp_cmd_process_operr
(
commands
,
asoc
,
chunk
);
break
;
default:
default:
printk
(
KERN_WARNING
"Impossible command: %u, %p
\n
"
,
printk
(
KERN_WARNING
"Impossible command: %u, %p
\n
"
,
cmd
->
verb
,
cmd
->
obj
.
ptr
);
cmd
->
verb
,
cmd
->
obj
.
ptr
);
...
...
net/sctp/sm_statefuns.c
View file @
3e94542b
/* 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-2002 International Business Machines, Corp.
* Copyright (c) 2001-2002 Intel Corp.
* Copyright (c) 2001-2002 Intel Corp.
* Copyright (c) 2002 Nokia Corp.
* Copyright (c) 2002 Nokia Corp.
*
*
...
@@ -2864,6 +2864,9 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
...
@@ -2864,6 +2864,9 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
sctp_ulpevent_free
(
ev
);
sctp_ulpevent_free
(
ev
);
goto
nomem
;
goto
nomem
;
}
}
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_PROCESS_OPERR
,
SCTP_CHUNK
(
chunk
));
}
}
return
SCTP_DISPOSITION_CONSUME
;
return
SCTP_DISPOSITION_CONSUME
;
...
...
net/sctp/socket.c
View file @
3e94542b
...
@@ -97,6 +97,8 @@ static void sctp_wait_for_close(struct sock *sk, long timeo);
...
@@ -97,6 +97,8 @@ static void sctp_wait_for_close(struct sock *sk, long timeo);
static
inline
int
sctp_verify_addr
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
static
inline
int
sctp_verify_addr
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
static
int
sctp_bindx_add
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
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_del_ip
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
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
*
,
...
@@ -349,6 +351,106 @@ int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
...
@@ -349,6 +351,106 @@ int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
return
retval
;
return
retval
;
}
}
/* Send an ASCONF chunk with Add IP address parameters to all the peers of the
* associations that are part of the endpoint indicating that a list of local
* addresses are added to the endpoint.
*
* If any of the addresses is already in the bind address list of the
* association, we do not send the chunk for that association. But it will not
* affect other associations.
*
* Only sctp_setsockopt_bindx() is supposed to call this function.
*/
static
int
sctp_send_asconf_add_ip
(
struct
sock
*
sk
,
struct
sockaddr
*
addrs
,
int
addrcnt
)
{
struct
sctp_opt
*
sp
;
struct
sctp_endpoint
*
ep
;
struct
sctp_association
*
asoc
;
struct
sctp_bind_addr
*
bp
;
struct
sctp_chunk
*
chunk
;
struct
sctp_sockaddr_entry
*
laddr
;
union
sctp_addr
*
addr
;
void
*
addr_buf
;
struct
sctp_af
*
af
;
struct
list_head
*
pos
;
struct
list_head
*
p
;
int
i
;
int
retval
=
0
;
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
SCTP_DEBUG_PRINTK
(
"%s: (sk: %p, addrs: %p, addrcnt: %d)
\n
"
,
__FUNCTION__
,
sk
,
addrs
,
addrcnt
);
list_for_each
(
pos
,
&
ep
->
asocs
)
{
asoc
=
list_entry
(
pos
,
struct
sctp_association
,
asocs
);
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
continue
;
if
(
!
asoc
->
peer
.
asconf_capable
)
continue
;
/* Check if any address in the packed array of addresses is
* in the bind address list of the association. If so,
* do not send the asconf chunk to its peer, but continue with
* other associations.
*/
addr_buf
=
addrs
;
for
(
i
=
0
;
i
<
addrcnt
;
i
++
)
{
addr
=
(
union
sctp_addr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
if
(
!
af
)
{
retval
=
-
EINVAL
;
goto
out
;
}
if
(
sctp_assoc_lookup_laddr
(
asoc
,
addr
))
break
;
addr_buf
+=
af
->
sockaddr_len
;
}
if
(
i
<
addrcnt
)
continue
;
/* Use the first address in bind addr list of association as
* Address Parameter of ASCONF CHUNK.
*/
sctp_read_lock
(
&
asoc
->
base
.
addr_lock
);
bp
=
&
asoc
->
base
.
bind_addr
;
p
=
bp
->
address_list
.
next
;
laddr
=
list_entry
(
p
,
struct
sctp_sockaddr_entry
,
list
);
sctp_read_unlock
(
&
asoc
->
base
.
addr_lock
);
chunk
=
sctp_make_asconf_update_ip
(
asoc
,
&
laddr
->
a
,
addrs
,
addrcnt
,
SCTP_PARAM_ADD_IP
);
if
(
!
chunk
)
{
retval
=
-
ENOMEM
;
goto
out
;
}
retval
=
sctp_primitive_ASCONF
(
asoc
,
chunk
);
if
(
retval
)
{
sctp_chunk_free
(
chunk
);
goto
out
;
}
/* FIXME: After sending the add address ASCONF chunk, we
* cannot append the address to the association's binding
* address list, because the new address may be used as the
* source of a message sent to the peer before the ASCONF
* chunk is received by the peer. So we should wait until
* ASCONF_ACK is received.
*/
}
out:
return
retval
;
}
/* Remove a list of addresses from bind addresses list. Do not remove the
/* Remove a list of addresses from bind addresses list. Do not remove the
* last address.
* last address.
*
*
...
@@ -436,6 +538,106 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
...
@@ -436,6 +538,106 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
return
retval
;
return
retval
;
}
}
/* Send an ASCONF chunk with Delete IP address parameters to all the peers of
* the associations that are part of the endpoint indicating that a list of
* local addresses are removed from the endpoint.
*
* If any of the addresses is already in the bind address list of the
* association, we do not send the chunk for that association. But it will not
* affect other associations.
*
* Only sctp_setsockopt_bindx() is supposed to call this function.
*/
static
int
sctp_send_asconf_del_ip
(
struct
sock
*
sk
,
struct
sockaddr
*
addrs
,
int
addrcnt
)
{
struct
sctp_opt
*
sp
;
struct
sctp_endpoint
*
ep
;
struct
sctp_association
*
asoc
;
struct
sctp_bind_addr
*
bp
;
struct
sctp_chunk
*
chunk
;
union
sctp_addr
*
laddr
;
void
*
addr_buf
;
struct
sctp_af
*
af
;
struct
list_head
*
pos
;
int
i
;
int
retval
=
0
;
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
SCTP_DEBUG_PRINTK
(
"%s: (sk: %p, addrs: %p, addrcnt: %d)
\n
"
,
__FUNCTION__
,
sk
,
addrs
,
addrcnt
);
list_for_each
(
pos
,
&
ep
->
asocs
)
{
asoc
=
list_entry
(
pos
,
struct
sctp_association
,
asocs
);
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
continue
;
if
(
!
asoc
->
peer
.
asconf_capable
)
continue
;
/* Check if any address in the packed array of addresses is
* not present in the bind address list of the association.
* If so, do not send the asconf chunk to its peer, but
* continue with other associations.
*/
addr_buf
=
addrs
;
for
(
i
=
0
;
i
<
addrcnt
;
i
++
)
{
laddr
=
(
union
sctp_addr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
laddr
->
v4
.
sin_family
);
if
(
!
af
)
{
retval
=
-
EINVAL
;
goto
out
;
}
if
(
!
sctp_assoc_lookup_laddr
(
asoc
,
laddr
))
break
;
addr_buf
+=
af
->
sockaddr_len
;
}
if
(
i
<
addrcnt
)
continue
;
/* Find one address in the association's bind address list
* that is not in the packed array of addresses. This is to
* make sure that we do not delete all the addresses in the
* association.
*/
sctp_read_lock
(
&
asoc
->
base
.
addr_lock
);
bp
=
&
asoc
->
base
.
bind_addr
;
laddr
=
sctp_find_unmatch_addr
(
bp
,
(
union
sctp_addr
*
)
addrs
,
addrcnt
,
sp
);
sctp_read_unlock
(
&
asoc
->
base
.
addr_lock
);
if
(
!
laddr
)
continue
;
chunk
=
sctp_make_asconf_update_ip
(
asoc
,
laddr
,
addrs
,
addrcnt
,
SCTP_PARAM_DEL_IP
);
if
(
!
chunk
)
{
retval
=
-
ENOMEM
;
goto
out
;
}
retval
=
sctp_primitive_ASCONF
(
asoc
,
chunk
);
if
(
retval
)
{
sctp_chunk_free
(
chunk
);
goto
out
;
}
/* FIXME: After sending the delete address ASCONF chunk, we
* cannot remove the addresses from the association's bind
* address list, because there maybe some packet send to
* the delete addresses, so we should wait until ASCONF_ACK
* packet is received.
*/
}
out:
return
retval
;
}
/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
*
*
* API 8.1
* API 8.1
...
@@ -564,10 +766,16 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs,
...
@@ -564,10 +766,16 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs,
switch
(
op
)
{
switch
(
op
)
{
case
SCTP_BINDX_ADD_ADDR
:
case
SCTP_BINDX_ADD_ADDR
:
err
=
sctp_bindx_add
(
sk
,
kaddrs
,
addrcnt
);
err
=
sctp_bindx_add
(
sk
,
kaddrs
,
addrcnt
);
if
(
err
)
goto
out
;
err
=
sctp_send_asconf_add_ip
(
sk
,
kaddrs
,
addrcnt
);
break
;
break
;
case
SCTP_BINDX_REM_ADDR
:
case
SCTP_BINDX_REM_ADDR
:
err
=
sctp_bindx_rem
(
sk
,
kaddrs
,
addrcnt
);
err
=
sctp_bindx_rem
(
sk
,
kaddrs
,
addrcnt
);
if
(
err
)
goto
out
;
err
=
sctp_send_asconf_del_ip
(
sk
,
kaddrs
,
addrcnt
);
break
;
break
;
default:
default:
...
@@ -575,6 +783,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs,
...
@@ -575,6 +783,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs,
break
;
break
;
};
};
out:
kfree
(
kaddrs
);
kfree
(
kaddrs
);
return
err
;
return
err
;
...
@@ -2582,10 +2791,8 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
...
@@ -2582,10 +2791,8 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
cnt
++
;
cnt
++
;
}
}
if
(
copy_to_user
(
optval
,
&
cnt
,
sizeof
(
int
)))
return
-
EFAULT
;
return
0
;
return
cnt
;
}
}
static
int
sctp_getsockopt_peer_addrs
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_peer_addrs
(
struct
sock
*
sk
,
int
len
,
...
@@ -2666,10 +2873,8 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
...
@@ -2666,10 +2873,8 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
list_for_each
(
pos
,
&
bp
->
address_list
)
{
list_for_each
(
pos
,
&
bp
->
address_list
)
{
cnt
++
;
cnt
++
;
}
}
if
(
copy_to_user
(
optval
,
&
cnt
,
sizeof
(
int
)))
return
-
EFAULT
;
return
0
;
return
cnt
;
}
}
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
...
...
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