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
f72c208b
Commit
f72c208b
authored
Sep 04, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-lksctp.bkbits.net/lksctp-2.5
into nuts.ninka.net:/disk1/davem/BK/net-2.5
parents
f3e971e4
4a542137
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
570 additions
and
461 deletions
+570
-461
include/linux/sctp.h
include/linux/sctp.h
+8
-1
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+22
-1
include/net/sctp/sm.h
include/net/sctp/sm.h
+5
-7
include/net/sctp/structs.h
include/net/sctp/structs.h
+90
-81
include/net/sctp/user.h
include/net/sctp/user.h
+5
-3
net/sctp/associola.c
net/sctp/associola.c
+22
-1
net/sctp/bind_addr.c
net/sctp/bind_addr.c
+20
-20
net/sctp/input.c
net/sctp/input.c
+5
-3
net/sctp/ipv6.c
net/sctp/ipv6.c
+29
-0
net/sctp/primitive.c
net/sctp/primitive.c
+14
-0
net/sctp/protocol.c
net/sctp/protocol.c
+27
-0
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+64
-115
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+2
-1
net/sctp/socket.c
net/sctp/socket.c
+255
-226
net/sctp/sysctl.c
net/sctp/sysctl.c
+2
-2
No files found.
include/linux/sctp.h
View file @
f72c208b
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
...
...
@@ -42,6 +42,8 @@
* randall@sctp.chicago.il.us
* kmorneau@cisco.com
* qxie1@email.mot.com
* Sridhar Samudrala <sri@us.ibm.com>
* Kevin Gao <kevin.gao@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -507,6 +509,11 @@ typedef struct sctp_cwr_chunk {
* The ASCONF Parameter Response is used in the ASCONF-ACK to
* report status of ASCONF processing.
*/
typedef
struct
sctp_addip_param
{
sctp_paramhdr_t
param_hdr
;
__u32
crr_id
;
}
sctp_addip_param_t
__attribute__
((
packed
));
typedef
struct
sctp_addiphdr
{
__u32
serial
;
__u8
params
[
0
];
...
...
include/net/sctp/sctp.h
View file @
f72c208b
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001-2003 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
...
...
@@ -40,6 +40,7 @@
* Sridhar Samudrala <sri@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.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
* be incorporated into the next SCTP release.
...
...
@@ -145,6 +146,7 @@ int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
int
sctp_primitive_ABORT
(
struct
sctp_association
*
,
void
*
arg
);
int
sctp_primitive_SEND
(
struct
sctp_association
*
,
void
*
arg
);
int
sctp_primitive_REQUESTHEARTBEAT
(
struct
sctp_association
*
,
void
*
arg
);
int
sctp_primitive_ASCONF
(
struct
sctp_association
*
,
void
*
arg
);
/*
* sctp/crc32c.c
...
...
@@ -404,6 +406,12 @@ static inline struct list_head *sctp_list_dequeue(struct list_head *list)
return
result
;
}
/* Tests if the list has one and only one entry. */
static
inline
int
sctp_list_single_entry
(
struct
list_head
*
head
)
{
return
((
head
->
next
!=
head
)
&&
(
head
->
next
==
head
->
prev
));
}
/* Calculate the size (in bytes) occupied by the data of an iovec. */
static
inline
size_t
get_user_iov_size
(
struct
iovec
*
iov
,
int
iovlen
)
{
...
...
@@ -525,6 +533,19 @@ static inline int ipver2af(__u8 ipver)
};
}
/* Convert from an address parameter type to an address family. */
static
inline
int
param_type2af
(
__u16
type
)
{
switch
(
type
)
{
case
SCTP_PARAM_IPV4_ADDRESS
:
return
AF_INET
;
case
SCTP_PARAM_IPV6_ADDRESS
:
return
AF_INET6
;
default:
return
0
;
};
}
/* Perform some sanity checks. */
static
inline
int
sctp_sanity_check
(
void
)
{
...
...
include/net/sctp/sm.h
View file @
f72c208b
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-2002 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -41,6 +41,7 @@
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Kevin Gao <kevin.gao@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -268,6 +269,9 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
struct
sctp_chunk
*
asconf
,
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_ssn
(
struct
sctp_chunk
*
);
...
...
@@ -330,12 +334,6 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
__u32
sctp_generate_tag
(
const
struct
sctp_endpoint
*
);
__u32
sctp_generate_tsn
(
const
struct
sctp_endpoint
*
);
/* 4th level prototypes */
void
sctp_param2sockaddr
(
union
sctp_addr
*
addr
,
union
sctp_addr_param
*
,
__u16
port
,
int
iif
);
int
sctp_addr2sockaddr
(
const
union
sctp_params
,
union
sctp_addr
*
);
int
sockaddr2sctp_addr
(
const
union
sctp_addr
*
,
union
sctp_addr_param
*
);
/* Extern declarations for major data structures. */
const
sctp_sm_table_entry_t
*
sctp_chunk_event_lookup
(
sctp_cid_t
,
sctp_state_t
);
extern
const
sctp_sm_table_entry_t
...
...
include/net/sctp/structs.h
View file @
f72c208b
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-2003 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -45,6 +45,7 @@
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
* Anup Pemmaiah <pemmaiah@cc.usu.edu>
* Kevin Gao <kevin.gao@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -217,86 +218,6 @@ extern struct sctp_globals {
#define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_lock (sctp_globals.local_addr_lock)
/*
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
*/
struct
sctp_af
{
int
(
*
sctp_xmit
)
(
struct
sk_buff
*
skb
,
struct
sctp_transport
*
,
int
ipfragok
);
int
(
*
setsockopt
)
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
);
int
(
*
getsockopt
)
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
);
struct
dst_entry
*
(
*
get_dst
)
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
);
void
(
*
get_saddr
)
(
struct
sctp_association
*
asoc
,
struct
dst_entry
*
dst
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
);
void
(
*
copy_addrlist
)
(
struct
list_head
*
,
struct
net_device
*
);
void
(
*
dst_saddr
)
(
union
sctp_addr
*
saddr
,
struct
dst_entry
*
dst
,
unsigned
short
port
);
int
(
*
cmp_addr
)
(
const
union
sctp_addr
*
addr1
,
const
union
sctp_addr
*
addr2
);
void
(
*
addr_copy
)
(
union
sctp_addr
*
dst
,
union
sctp_addr
*
src
);
void
(
*
from_skb
)
(
union
sctp_addr
*
,
struct
sk_buff
*
skb
,
int
saddr
);
void
(
*
from_sk
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
void
(
*
to_sk_saddr
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
void
(
*
to_sk_daddr
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
int
(
*
addr_valid
)
(
union
sctp_addr
*
,
struct
sctp_opt
*
);
sctp_scope_t
(
*
scope
)
(
union
sctp_addr
*
);
void
(
*
inaddr_any
)
(
union
sctp_addr
*
,
unsigned
short
);
int
(
*
is_any
)
(
const
union
sctp_addr
*
);
int
(
*
available
)
(
union
sctp_addr
*
,
struct
sctp_opt
*
);
int
(
*
skb_iif
)
(
const
struct
sk_buff
*
sk
);
int
(
*
is_ce
)
(
const
struct
sk_buff
*
sk
);
void
(
*
seq_dump_addr
)(
struct
seq_file
*
seq
,
union
sctp_addr
*
addr
);
__u16
net_header_len
;
int
sockaddr_len
;
sa_family_t
sa_family
;
struct
list_head
list
;
};
struct
sctp_af
*
sctp_get_af_specific
(
sa_family_t
);
int
sctp_register_af
(
struct
sctp_af
*
);
/* Protocol family functions. */
struct
sctp_pf
{
void
(
*
event_msgname
)(
struct
sctp_ulpevent
*
,
char
*
,
int
*
);
void
(
*
skb_msgname
)
(
struct
sk_buff
*
,
char
*
,
int
*
);
int
(
*
af_supported
)
(
sa_family_t
,
struct
sctp_opt
*
);
int
(
*
cmp_addr
)
(
const
union
sctp_addr
*
,
const
union
sctp_addr
*
,
struct
sctp_opt
*
);
int
(
*
bind_verify
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
int
(
*
send_verify
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
int
(
*
supported_addrs
)(
const
struct
sctp_opt
*
,
__u16
*
);
struct
sock
*
(
*
create_accept_sk
)
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
);
void
(
*
addr_v4map
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
struct
sctp_af
*
af
;
};
/* SCTP Socket type: UDP or TCP style. */
typedef
enum
{
SCTP_SOCKET_UDP
=
0
,
...
...
@@ -488,6 +409,92 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
return
stream
->
ssn
[
id
]
++
;
}
/*
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
*/
struct
sctp_af
{
int
(
*
sctp_xmit
)
(
struct
sk_buff
*
skb
,
struct
sctp_transport
*
,
int
ipfragok
);
int
(
*
setsockopt
)
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
);
int
(
*
getsockopt
)
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
);
struct
dst_entry
*
(
*
get_dst
)
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
);
void
(
*
get_saddr
)
(
struct
sctp_association
*
asoc
,
struct
dst_entry
*
dst
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
);
void
(
*
copy_addrlist
)
(
struct
list_head
*
,
struct
net_device
*
);
void
(
*
dst_saddr
)
(
union
sctp_addr
*
saddr
,
struct
dst_entry
*
dst
,
unsigned
short
port
);
int
(
*
cmp_addr
)
(
const
union
sctp_addr
*
addr1
,
const
union
sctp_addr
*
addr2
);
void
(
*
addr_copy
)
(
union
sctp_addr
*
dst
,
union
sctp_addr
*
src
);
void
(
*
from_skb
)
(
union
sctp_addr
*
,
struct
sk_buff
*
skb
,
int
saddr
);
void
(
*
from_sk
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
void
(
*
to_sk_saddr
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
void
(
*
to_sk_daddr
)
(
union
sctp_addr
*
,
struct
sock
*
sk
);
void
(
*
from_addr_param
)
(
union
sctp_addr
*
,
union
sctp_addr_param
*
,
__u16
port
,
int
iif
);
int
(
*
to_addr_param
)
(
const
union
sctp_addr
*
,
union
sctp_addr_param
*
);
int
(
*
addr_valid
)
(
union
sctp_addr
*
,
struct
sctp_opt
*
);
sctp_scope_t
(
*
scope
)
(
union
sctp_addr
*
);
void
(
*
inaddr_any
)
(
union
sctp_addr
*
,
unsigned
short
);
int
(
*
is_any
)
(
const
union
sctp_addr
*
);
int
(
*
available
)
(
union
sctp_addr
*
,
struct
sctp_opt
*
);
int
(
*
skb_iif
)
(
const
struct
sk_buff
*
sk
);
int
(
*
is_ce
)
(
const
struct
sk_buff
*
sk
);
void
(
*
seq_dump_addr
)(
struct
seq_file
*
seq
,
union
sctp_addr
*
addr
);
__u16
net_header_len
;
int
sockaddr_len
;
sa_family_t
sa_family
;
struct
list_head
list
;
};
struct
sctp_af
*
sctp_get_af_specific
(
sa_family_t
);
int
sctp_register_af
(
struct
sctp_af
*
);
/* Protocol family functions. */
struct
sctp_pf
{
void
(
*
event_msgname
)(
struct
sctp_ulpevent
*
,
char
*
,
int
*
);
void
(
*
skb_msgname
)
(
struct
sk_buff
*
,
char
*
,
int
*
);
int
(
*
af_supported
)
(
sa_family_t
,
struct
sctp_opt
*
);
int
(
*
cmp_addr
)
(
const
union
sctp_addr
*
,
const
union
sctp_addr
*
,
struct
sctp_opt
*
);
int
(
*
bind_verify
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
int
(
*
send_verify
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
int
(
*
supported_addrs
)(
const
struct
sctp_opt
*
,
__u16
*
);
struct
sock
*
(
*
create_accept_sk
)
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
);
void
(
*
addr_v4map
)
(
struct
sctp_opt
*
,
union
sctp_addr
*
);
struct
sctp_af
*
af
;
};
/* Structure to track chunk fragments that have been acked, but peer
* fragments of the same message have not.
*/
...
...
@@ -1688,6 +1695,8 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport(
void
sctp_assoc_update_retran_path
(
struct
sctp_association
*
);
struct
sctp_transport
*
sctp_assoc_lookup_paddr
(
const
struct
sctp_association
*
,
const
union
sctp_addr
*
);
int
sctp_assoc_lookup_laddr
(
struct
sctp_association
*
asoc
,
const
union
sctp_addr
*
laddr
);
struct
sctp_transport
*
sctp_assoc_add_peer
(
struct
sctp_association
*
,
const
union
sctp_addr
*
address
,
const
int
gfp
);
...
...
include/net/sctp/user.h
View file @
f72c208b
...
...
@@ -551,13 +551,15 @@ struct sctp_status {
};
/*
* 8.3, 8.5 get all peer/local addresses on a socket
* This parameter struct is for getsockopt
* 8.3, 8.5 get all peer/local addresses in an association.
* This parameter struct is used by SCTP_GET_PEER_ADDRS and
* SCTP_GET_LOCAL_ADDRS socket options used internally to implement
* sctp_getpaddrs() and sctp_getladdrs() API.
*/
struct
sctp_getaddrs
{
sctp_assoc_t
assoc_id
;
int
addr_num
;
struct
sockaddr
_storage
*
addrs
;
struct
sockaddr
*
addrs
;
};
/* These are bit fields for msghdr->msg_flags. See section 5.1. */
...
...
net/sctp/associola.c
View file @
f72c208b
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 La Monte H.P. Yarroll
*
...
...
@@ -42,6 +42,7 @@
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@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
* be incorporated into the next SCTP release.
...
...
@@ -1155,3 +1156,23 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
return
sctp_raw_to_bind_addrs
(
&
asoc
->
base
.
bind_addr
,
raw
,
var_size3
,
asoc
->
ep
->
base
.
bind_addr
.
port
,
gfp
);
}
/* Lookup laddr in the bind address list of an association. */
int
sctp_assoc_lookup_laddr
(
struct
sctp_association
*
asoc
,
const
union
sctp_addr
*
laddr
)
{
int
found
;
sctp_read_lock
(
&
asoc
->
base
.
addr_lock
);
if
((
asoc
->
base
.
bind_addr
.
port
==
ntohs
(
laddr
->
v4
.
sin_port
))
&&
sctp_bind_addr_match
(
&
asoc
->
base
.
bind_addr
,
laddr
,
sctp_sk
(
asoc
->
base
.
sk
)))
{
found
=
1
;
goto
out
;
}
found
=
0
;
out:
sctp_read_unlock
(
&
asoc
->
base
.
addr_lock
);
return
found
;
}
net/sctp/bind_addr.c
View file @
f72c208b
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) Cisco 1999,2000
* Copyright (c) Motorola 1999,2000,2001
* Copyright (c) International Business Machines Corp., 2001,2002
* Copyright (c) La Monte H.P. Yarroll 2001
*
* This file is part of the SCTP kernel reference implementation.
...
...
@@ -223,6 +223,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
int
len
;
struct
sctp_sockaddr_entry
*
addr
;
struct
list_head
*
pos
;
struct
sctp_af
*
af
;
addrparms_len
=
0
;
len
=
0
;
...
...
@@ -247,7 +249,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
list_for_each
(
pos
,
&
bp
->
address_list
)
{
addr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
len
=
sockaddr2sctp_addr
(
&
addr
->
a
,
&
rawaddr
);
af
=
sctp_get_af_specific
(
addr
->
a
.
v4
.
sin_family
);
len
=
af
->
to_addr_param
(
&
addr
->
a
,
&
rawaddr
);
memcpy
(
addrparms
.
v
,
&
rawaddr
,
len
);
addrparms
.
v
+=
len
;
addrparms_len
+=
len
;
...
...
@@ -270,34 +273,31 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
union
sctp_addr
addr
;
int
retval
=
0
;
int
len
;
struct
sctp_af
*
af
;
/* Convert the raw address to standard address format */
while
(
addrs_len
)
{
param
=
(
struct
sctp_paramhdr
*
)
raw_addr_list
;
rawaddr
=
(
union
sctp_addr_param
*
)
raw_addr_list
;
switch
(
param
->
type
)
{
case
SCTP_PARAM_IPV4_ADDRESS
:
case
SCTP_PARAM_IPV6_ADDRESS
:
sctp_param2sockaddr
(
&
addr
,
rawaddr
,
port
,
0
);
retval
=
sctp_add_bind_addr
(
bp
,
&
addr
,
gfp
);
if
(
retval
)
{
/* Can't finish building the list, clean up. */
sctp_bind_addr_clean
(
bp
);
break
;;
}
len
=
ntohs
(
param
->
length
);
addrs_len
-=
len
;
raw_addr_list
+=
len
;
break
;
default:
/* Corrupted raw addr list! */
af
=
sctp_get_af_specific
(
param_type2af
(
param
->
type
));
if
(
unlikely
(
!
af
))
{
retval
=
-
EINVAL
;
sctp_bind_addr_clean
(
bp
);
break
;
}
if
(
retval
)
break
;
af
->
from_addr_param
(
&
addr
,
rawaddr
,
port
,
0
);
retval
=
sctp_add_bind_addr
(
bp
,
&
addr
,
gfp
);
if
(
retval
)
{
/* Can't finish building the list, clean up. */
sctp_bind_addr_clean
(
bp
);
break
;;
}
len
=
ntohs
(
param
->
length
);
addrs_len
-=
len
;
raw_addr_list
+=
len
;
}
return
retval
;
...
...
net/sctp/input.c
View file @
f72c208b
...
...
@@ -768,6 +768,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
union
sctp_params
params
;
sctp_init_chunk_t
*
init
;
struct
sctp_transport
*
transport
;
struct
sctp_af
*
af
;
ch
=
(
sctp_chunkhdr_t
*
)
skb
->
data
;
...
...
@@ -802,11 +803,12 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
sctp_walk_params
(
params
,
init
,
init_hdr
.
params
)
{
/* Note: Ignoring hostname addresses. */
if
((
SCTP_PARAM_IPV4_ADDRESS
!=
params
.
p
->
type
)
&&
(
SCTP_PARAM_IPV6_ADDRESS
!=
params
.
p
->
type
)
)
af
=
sctp_get_af_specific
(
param_type2af
(
params
.
p
->
type
));
if
(
!
af
)
continue
;
sctp_param2sockaddr
(
paddr
,
params
.
addr
,
ntohs
(
sh
->
source
),
0
);
af
->
from_addr_param
(
paddr
,
params
.
addr
,
ntohs
(
sh
->
source
),
0
);
asoc
=
__sctp_lookup_association
(
laddr
,
paddr
,
&
transport
);
if
(
asoc
)
return
asoc
;
...
...
net/sctp/ipv6.c
View file @
f72c208b
...
...
@@ -399,6 +399,33 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
}
}
/* Initialize a sctp_addr from an address parameter. */
static
void
sctp_v6_from_addr_param
(
union
sctp_addr
*
addr
,
union
sctp_addr_param
*
param
,
__u16
port
,
int
iif
)
{
addr
->
v6
.
sin6_family
=
AF_INET6
;
addr
->
v6
.
sin6_port
=
port
;
addr
->
v6
.
sin6_flowinfo
=
0
;
/* BUG */
ipv6_addr_copy
(
&
addr
->
v6
.
sin6_addr
,
&
param
->
v6
.
addr
);
addr
->
v6
.
sin6_scope_id
=
iif
;
}
/* Initialize an address parameter from a sctp_addr and return the length
* of the address parameter.
*/
static
int
sctp_v6_to_addr_param
(
const
union
sctp_addr
*
addr
,
union
sctp_addr_param
*
param
)
{
int
length
=
sizeof
(
sctp_ipv6addr_param_t
);
param
->
v6
.
param_hdr
.
type
=
SCTP_PARAM_IPV6_ADDRESS
;
param
->
v6
.
param_hdr
.
length
=
ntohs
(
length
);
ipv6_addr_copy
(
&
param
->
v6
.
addr
,
&
addr
->
v6
.
sin6_addr
);
return
length
;
}
/* Initialize a sctp_addr from a dst_entry. */
static
void
sctp_v6_dst_saddr
(
union
sctp_addr
*
addr
,
struct
dst_entry
*
dst
,
unsigned
short
port
)
...
...
@@ -903,6 +930,8 @@ static struct sctp_af sctp_ipv6_specific = {
.
from_sk
=
sctp_v6_from_sk
,
.
to_sk_saddr
=
sctp_v6_to_sk_saddr
,
.
to_sk_daddr
=
sctp_v6_to_sk_daddr
,
.
from_addr_param
=
sctp_v6_from_addr_param
,
.
to_addr_param
=
sctp_v6_to_addr_param
,
.
dst_saddr
=
sctp_v6_dst_saddr
,
.
cmp_addr
=
sctp_v6_cmp_addr
,
.
scope
=
sctp_v6_scope
,
...
...
net/sctp/primitive.c
View file @
f72c208b
...
...
@@ -39,6 +39,7 @@
* Narasimha Budihal <narasimha@refcode.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Ardelle Fan <ardelle.fan@intel.com>
* Kevin Gao <kevin.gao@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -203,3 +204,16 @@ DECLARE_PRIMITIVE(SEND);
*/
DECLARE_PRIMITIVE
(
REQUESTHEARTBEAT
);
/* ADDIP
* 3.1.1 Address 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
* Type-Length-Value (TLV), as described in "3.2.1 Optional/
* Variable-length Parameter Format" in RFC2960 [5], forall variable
* parameters.
*/
DECLARE_PRIMITIVE
(
ASCONF
);
net/sctp/protocol.c
View file @
f72c208b
...
...
@@ -295,6 +295,31 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
inet_sk
(
sk
)
->
daddr
=
addr
->
v4
.
sin_addr
.
s_addr
;
}
/* Initialize a sctp_addr from an address parameter. */
static
void
sctp_v4_from_addr_param
(
union
sctp_addr
*
addr
,
union
sctp_addr_param
*
param
,
__u16
port
,
int
iif
)
{
addr
->
v4
.
sin_family
=
AF_INET
;
addr
->
v4
.
sin_port
=
port
;
addr
->
v4
.
sin_addr
.
s_addr
=
param
->
v4
.
addr
.
s_addr
;
}
/* Initialize an address parameter from a sctp_addr and return the length
* of the address parameter.
*/
static
int
sctp_v4_to_addr_param
(
const
union
sctp_addr
*
addr
,
union
sctp_addr_param
*
param
)
{
int
length
=
sizeof
(
sctp_ipv4addr_param_t
);
param
->
v4
.
param_hdr
.
type
=
SCTP_PARAM_IPV4_ADDRESS
;
param
->
v4
.
param_hdr
.
length
=
ntohs
(
length
);
param
->
v4
.
addr
.
s_addr
=
addr
->
v4
.
sin_addr
.
s_addr
;
return
length
;
}
/* Initialize a sctp_addr from a dst_entry. */
static
void
sctp_v4_dst_saddr
(
union
sctp_addr
*
saddr
,
struct
dst_entry
*
dst
,
unsigned
short
port
)
...
...
@@ -862,6 +887,8 @@ struct sctp_af sctp_ipv4_specific = {
.
from_sk
=
sctp_v4_from_sk
,
.
to_sk_saddr
=
sctp_v4_to_sk_saddr
,
.
to_sk_daddr
=
sctp_v4_to_sk_daddr
,
.
from_addr_param
=
sctp_v4_from_addr_param
,
.
to_addr_param
=
sctp_v4_to_addr_param
,
.
dst_saddr
=
sctp_v4_dst_saddr
,
.
cmp_addr
=
sctp_v4_cmp_addr
,
.
addr_valid
=
sctp_v4_addr_valid
,
...
...
net/sctp/sm_make_chunk.c
View file @
f72c208b
/* SCTP kernel reference Implementation
* Copyright (C) IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 Intel Corp.
* Copyright (c) 2001-2002 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -48,6 +48,7 @@
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Kevin Gao <kevin.gao@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -1213,6 +1214,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
struct
sctp_association
*
asoc
;
struct
sk_buff
*
skb
;
sctp_scope_t
scope
;
struct
sctp_af
*
af
;
/* Create the bare association. */
scope
=
sctp_scope
(
sctp_source
(
chunk
));
...
...
@@ -1222,29 +1224,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
asoc
->
temp
=
1
;
skb
=
chunk
->
skb
;
/* Create an entry for the source address of the packet. */
/* FIXME: Use the af specific helpers. */
switch
(
skb
->
nh
.
iph
->
version
)
{
case
4
:
asoc
->
c
.
peer_addr
.
v4
.
sin_family
=
AF_INET
;
asoc
->
c
.
peer_addr
.
v4
.
sin_port
=
ntohs
(
chunk
->
sctp_hdr
->
source
);
asoc
->
c
.
peer_addr
.
v4
.
sin_addr
.
s_addr
=
skb
->
nh
.
iph
->
saddr
;
break
;
case
6
:
asoc
->
c
.
peer_addr
.
v6
.
sin6_family
=
AF_INET6
;
asoc
->
c
.
peer_addr
.
v6
.
sin6_port
=
ntohs
(
chunk
->
sctp_hdr
->
source
);
asoc
->
c
.
peer_addr
.
v6
.
sin6_flowinfo
=
0
;
/* BUG BUG BUG */
asoc
->
c
.
peer_addr
.
v6
.
sin6_addr
=
skb
->
nh
.
ipv6h
->
saddr
;
asoc
->
c
.
peer_addr
.
v6
.
sin6_scope_id
=
((
struct
inet6_skb_parm
*
)
skb
->
cb
)
->
iif
;
break
;
default:
/* Yikes! I never heard of this kind of address. */
af
=
sctp_get_af_specific
(
ipver2af
(
skb
->
nh
.
iph
->
version
));
if
(
unlikely
(
!
af
))
goto
fail
;
};
af
->
from_skb
(
&
asoc
->
c
.
peer_addr
,
skb
,
1
);
nodata:
return
asoc
;
...
...
@@ -1830,11 +1813,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* stream sequence number shall be set to 0.
*/
/* Allocate storage for the negotiated streams. */
asoc
->
ssnmap
=
sctp_ssnmap_new
(
asoc
->
peer
.
i
.
num_outbound_streams
,
asoc
->
c
.
sinit_num_ostreams
,
gfp
);
if
(
!
asoc
->
ssnmap
)
goto
nomem_ssnmap
;
/* Allocate storage for the negotiated streams if it is not a temporary * association.
*/
if
(
!
asoc
->
temp
)
{
asoc
->
ssnmap
=
sctp_ssnmap_new
(
asoc
->
c
.
sinit_max_instreams
,
asoc
->
c
.
sinit_num_ostreams
,
gfp
);
if
(
!
asoc
->
ssnmap
)
goto
nomem_ssnmap
;
}
/* ADDIP Section 4.1 ASCONF Chunk Procedures
*
...
...
@@ -1882,6 +1868,7 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
int
retval
=
1
;
sctp_scope_t
scope
;
time_t
stale
;
struct
sctp_af
*
af
;
/* We maintain all INIT parameters in network byte order all the
* time. This allows us to not worry about whether the parameters
...
...
@@ -1893,7 +1880,8 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
break
;
/* Fall through. */
case
SCTP_PARAM_IPV4_ADDRESS
:
sctp_param2sockaddr
(
&
addr
,
param
.
addr
,
asoc
->
peer
.
port
,
0
);
af
=
sctp_get_af_specific
(
param_type2af
(
param
.
p
->
type
));
af
->
from_addr_param
(
&
addr
,
param
.
addr
,
asoc
->
peer
.
port
,
0
);
scope
=
sctp_scope
(
peer_addr
);
if
(
sctp_in_scope
(
&
addr
,
scope
))
if
(
!
sctp_assoc_add_peer
(
asoc
,
&
addr
,
gfp
))
...
...
@@ -2005,90 +1993,6 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
return
retval
;
}
/********************************************************************
* 4th Level Abstractions
********************************************************************/
/* Convert from an SCTP IP parameter to a union sctp_addr. */
void
sctp_param2sockaddr
(
union
sctp_addr
*
addr
,
union
sctp_addr_param
*
param
,
__u16
port
,
int
iif
)
{
switch
(
param
->
v4
.
param_hdr
.
type
)
{
case
SCTP_PARAM_IPV4_ADDRESS
:
addr
->
v4
.
sin_family
=
AF_INET
;
addr
->
v4
.
sin_port
=
port
;
addr
->
v4
.
sin_addr
.
s_addr
=
param
->
v4
.
addr
.
s_addr
;
break
;
case
SCTP_PARAM_IPV6_ADDRESS
:
addr
->
v6
.
sin6_family
=
AF_INET6
;
addr
->
v6
.
sin6_port
=
port
;
addr
->
v6
.
sin6_flowinfo
=
0
;
/* BUG */
addr
->
v6
.
sin6_addr
=
param
->
v6
.
addr
;
addr
->
v6
.
sin6_scope_id
=
iif
;
break
;
default:
SCTP_DEBUG_PRINTK
(
"Illegal address type %d
\n
"
,
ntohs
(
param
->
v4
.
param_hdr
.
type
));
break
;
};
}
/* Convert an IP address in an SCTP param into a sockaddr_in. */
/* Returns true if a valid conversion was possible. */
int
sctp_addr2sockaddr
(
union
sctp_params
p
,
union
sctp_addr
*
sa
)
{
switch
(
p
.
p
->
type
)
{
case
SCTP_PARAM_IPV4_ADDRESS
:
sa
->
v4
.
sin_addr
=
*
((
struct
in_addr
*
)
&
p
.
v4
->
addr
);
sa
->
v4
.
sin_family
=
AF_INET
;
break
;
case
SCTP_PARAM_IPV6_ADDRESS
:
*
((
struct
in6_addr
*
)
&
sa
->
v4
.
sin_addr
)
=
p
.
v6
->
addr
;
sa
->
v4
.
sin_family
=
AF_INET6
;
break
;
default:
return
0
;
};
return
1
;
}
/* Convert a sockaddr_in to an IP address in an SCTP param.
* Returns len if a valid conversion was possible.
*/
int
sockaddr2sctp_addr
(
const
union
sctp_addr
*
sa
,
union
sctp_addr_param
*
p
)
{
int
len
=
0
;
switch
(
sa
->
v4
.
sin_family
)
{
case
AF_INET
:
p
->
v4
.
param_hdr
.
type
=
SCTP_PARAM_IPV4_ADDRESS
;
p
->
v4
.
param_hdr
.
length
=
ntohs
(
sizeof
(
sctp_ipv4addr_param_t
));
len
=
sizeof
(
sctp_ipv4addr_param_t
);
p
->
v4
.
addr
.
s_addr
=
sa
->
v4
.
sin_addr
.
s_addr
;
break
;
case
AF_INET6
:
p
->
v6
.
param_hdr
.
type
=
SCTP_PARAM_IPV6_ADDRESS
;
p
->
v6
.
param_hdr
.
length
=
ntohs
(
sizeof
(
sctp_ipv6addr_param_t
));
len
=
sizeof
(
sctp_ipv6addr_param_t
);
p
->
v6
.
addr
=
*
(
&
sa
->
v6
.
sin6_addr
);
break
;
default:
printk
(
KERN_WARNING
"sockaddr2sctp_addr: Illegal family %d.
\n
"
,
sa
->
v4
.
sin_family
);
return
0
;
};
return
len
;
}
/*
* ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF)
* 0 1 2 3
...
...
@@ -2119,8 +2023,9 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
int
length
=
sizeof
(
asconf
)
+
vparam_len
;
union
sctp_params
addrparam
;
int
addrlen
;
struct
sctp_af
*
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
addrlen
=
sockaddr2sctp_addr
(
addr
,
(
union
sctp_addr_param
*
)
&
addrparam
);
addrlen
=
af
->
to_addr_param
(
addr
,
(
union
sctp_addr_param
*
)
&
addrparam
);
if
(
!
addrlen
)
return
NULL
;
length
+=
addrlen
;
...
...
@@ -2135,7 +2040,51 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
retval
->
subh
.
addip_hdr
=
sctp_addto_chunk
(
retval
,
sizeof
(
asconf
),
&
asconf
);
retval
->
param_hdr
.
v
=
sctp_addto_chunk
(
retval
,
addrlen
,
&
addr
);
sctp_addto_chunk
(
retval
,
addrlen
,
&
addrparam
);
return
retval
;
}
/* ADDIP
* 3.2.4 Set Primary 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 =0xC004 | Length = Variable |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ASCONF-Request Correlation ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Address Parameter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Create an ASCONF chunk with Set Primary IP address parameter.
*/
struct
sctp_chunk
*
sctp_make_asconf_set_prim
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
)
{
sctp_addip_param_t
param
;
struct
sctp_chunk
*
retval
;
int
len
=
sizeof
(
param
);
union
sctp_params
addrparam
;
int
addrlen
;
struct
sctp_af
*
af
=
sctp_get_af_specific
(
addr
->
v4
.
sin_family
);
addrlen
=
af
->
to_addr_param
(
addr
,
(
union
sctp_addr_param
*
)
&
addrparam
);
if
(
!
addrlen
)
return
NULL
;
len
+=
addrlen
;
/* Create the chunk and make asconf header. */
retval
=
sctp_make_asconf
(
asoc
,
addr
,
len
);
if
(
!
retval
)
return
NULL
;
param
.
param_hdr
.
type
=
SCTP_PARAM_SET_PRIMARY
;
param
.
param_hdr
.
length
=
htons
(
len
);
param
.
crr_id
=
0
;
sctp_addto_chunk
(
retval
,
sizeof
(
param
),
&
param
);
sctp_addto_chunk
(
retval
,
addrlen
,
&
addrparam
);
return
retval
;
}
...
...
net/sctp/sm_statefuns.c
View file @
f72c208b
...
...
@@ -929,6 +929,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
struct
sctp_errhdr
*
errhdr
;
struct
sctp_endpoint
*
ep
;
char
buffer
[
sizeof
(
struct
sctp_errhdr
)
+
sizeof
(
union
sctp_addr_param
)];
struct
sctp_af
*
af
=
sctp_get_af_specific
(
ssa
->
v4
.
sin_family
);
/* Build the error on the stack. We are way to malloc crazy
* throughout the code today.
...
...
@@ -937,7 +938,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
addrparm
=
(
union
sctp_addr_param
*
)
errhdr
->
variable
;
/* Copy into a parm format. */
len
=
sockaddr2sctp_addr
(
ssa
,
addrparm
);
len
=
af
->
to_addr_param
(
ssa
,
addrparm
);
len
+=
sizeof
(
sctp_errhdr_t
);
errhdr
->
cause
=
SCTP_ERROR_RESTART
;
...
...
net/sctp/socket.c
View file @
f72c208b
/* Copyright (c) 1999-2000 Cisco, Inc.
/* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001-2003 Intel Corp.
* Copyright (c) 2001-2002 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
...
...
@@ -50,6 +51,7 @@
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
* Anup Pemmaiah <pemmaiah@cc.usu.edu>
* Kevin Gao <kevin.gao@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -93,8 +95,8 @@ static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
static
int
sctp_wait_for_accept
(
struct
sock
*
sk
,
long
timeo
);
static
void
sctp_wait_for_close
(
struct
sock
*
sk
,
long
timeo
);
static
inline
int
sctp_verify_addr
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
static
int
sctp_bindx_add
(
struct
sock
*
,
struct
sockaddr
_storage
*
,
int
);
static
int
sctp_bindx_rem
(
struct
sock
*
,
struct
sockaddr
_storage
*
,
int
);
static
int
sctp_bindx_add
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_bindx_rem
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_do_bind
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
static
int
sctp_autobind
(
struct
sock
*
sk
);
static
void
sctp_sock_migrate
(
struct
sock
*
,
struct
sock
*
,
...
...
@@ -170,10 +172,7 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
* sd - the socket descriptor returned by socket().
* addr - the address structure (struct sockaddr_in or struct
* sockaddr_in6 [RFC 2553]),
* addrlen - the size of the address structure.
*
* The caller should use struct sockaddr_storage described in RFC 2553
* to represent addr for portability reason.
* addr_len - the size of the address structure.
*/
int
sctp_bind
(
struct
sock
*
sk
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
{
...
...
@@ -298,112 +297,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
return
ret
;
}
/* API 8.1 sctp_bindx()
*
* The syntax of sctp_bindx() is,
*
* ret = sctp_bindx(int sd,
* struct sockaddr_storage *addrs,
* int addrcnt,
* int flags);
*
* If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
* If the sd is an IPv6 socket, the addresses passed can either be IPv4
* or IPv6 addresses.
*
* A single address may be specified as INADDR_ANY or IPV6_ADDR_ANY, see
* section 3.1.2 for this usage.
*
* addrs is a pointer to an array of one or more socket addresses. Each
* address is contained in a struct sockaddr_storage, so each address is
* fixed length. The caller specifies the number of addresses in the
* array with addrcnt.
*
* On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns -1,
* and sets errno to the appropriate error code. [ Editor's note: need
* to fill in all error code? ]
*
* For SCTP, the port given in each socket address must be the same, or
* sctp_bindx() will fail, setting errno to EINVAL .
*
* The flags parameter is formed from the bitwise OR of zero or
* more of the following currently defined flags:
*
* SCTP_BINDX_ADD_ADDR
* SCTP_BINDX_REM_ADDR
*
* SCTP_BIND_ADD_ADDR directs SCTP to add the given addresses to the
* association, and SCTP_BIND_REM_ADDR directs SCTP to remove the given
* addresses from the association. The two flags are mutually exclusive;
* if both are given, sctp_bindx() will fail with EINVAL. A caller may not
* remove all addresses from an association; sctp_bindx() will reject such
* an attempt with EINVAL.
*
* An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate
* additional addresses with an endpoint after calling bind(). Or use
* sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening
* socket is associated with so that no new association accepted will be
* associated with those addresses.
*
* SCTP_BIND_ADD_ADDR is defined as 0, so that it becomes the default
* behavior for sctp_bindx() when no flags are given.
*
* Adding and removing addresses from a connected association is optional
* functionality. Implementations that do not support this functionality
* should return EOPNOTSUPP.
*
* NOTE: This could be integrated into sctp_setsockopt_bindx(),
* but keeping it this way makes it easier if sometime sys_bindx is
* added.
*/
/* Unprotected by locks. Call only with socket lock sk->sk_lock held! See
* sctp_bindx() for a lock-protected call.
*/
static
int
__sctp_bindx
(
struct
sock
*
sk
,
struct
sockaddr_storage
*
addrs
,
int
addrcnt
,
int
flags
)
{
int
retval
=
0
;
SCTP_DEBUG_PRINTK
(
"__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, "
"flags: %s)
\n
"
,
sk
,
addrs
,
addrcnt
,
(
SCTP_BINDX_ADD_ADDR
==
flags
)
?
"ADD"
:
((
SCTP_BINDX_REM_ADDR
==
flags
)
?
"REM"
:
"BOGUS"
));
switch
(
flags
)
{
case
SCTP_BINDX_ADD_ADDR
:
retval
=
sctp_bindx_add
(
sk
,
addrs
,
addrcnt
);
break
;
case
SCTP_BINDX_REM_ADDR
:
retval
=
sctp_bindx_rem
(
sk
,
addrs
,
addrcnt
);
break
;
default:
retval
=
-
EINVAL
;
break
;
};
return
retval
;
}
/* BINDX with locks.
*
* NOTE: Currently unused at all ...
*/
int
sctp_bindx
(
struct
sock
*
sk
,
struct
sockaddr_storage
*
addrs
,
int
addrcnt
,
int
flags
)
{
int
retval
;
sctp_lock_sock
(
sk
);
retval
=
__sctp_bindx
(
sk
,
addrs
,
addrcnt
,
flags
);
sctp_release_sock
(
sk
);
return
retval
;
}
/* Add a list of addresses as bind addresses to local endpoint or
* association.
*
...
...
@@ -414,41 +307,39 @@ int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt,
* If any of them fails, then the operation will be reversed and the
* ones that were added will be removed.
*
* Only
__sctp
_bindx() is supposed to call this function.
* Only
sctp_setsockopt
_bindx() is supposed to call this function.
*/
int
sctp_bindx_add
(
struct
sock
*
sk
,
struct
sockaddr
_storage
*
addrs
,
int
addrcnt
)
int
sctp_bindx_add
(
struct
sock
*
sk
,
struct
sockaddr
*
addrs
,
int
addrcnt
)
{
int
cnt
;
int
retval
=
0
;
int
addr_len
;
void
*
addr_buf
;
struct
sockaddr
*
sa_addr
;
struct
sctp_af
*
af
;
SCTP_DEBUG_PRINTK
(
"sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)
\n
"
,
sk
,
addrs
,
addrcnt
);
addr_buf
=
addrs
;
for
(
cnt
=
0
;
cnt
<
addrcnt
;
cnt
++
)
{
/* The list may contain either IPv4 or IPv6 address;
* determine the address length for walking thru the list.
*/
switch
(((
struct
sockaddr
*
)
&
addrs
[
cnt
])
->
sa_family
)
{
case
AF_INET
:
addr_len
=
sizeof
(
struct
sockaddr_in
);
break
;
case
AF_INET6
:
addr_len
=
sizeof
(
struct
sockaddr_in6
);
break
;
default:
sa_addr
=
(
struct
sockaddr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
sa_addr
->
sa_family
);
if
(
!
af
)
{
retval
=
-
EINVAL
;
goto
err_bindx_add
;
}
;
}
retval
=
sctp_do_bind
(
sk
,
(
union
sctp_addr
*
)
&
addrs
[
cnt
],
addr_len
);
retval
=
sctp_do_bind
(
sk
,
(
union
sctp_addr
*
)
sa_addr
,
af
->
sockaddr_len
);
addr_buf
+=
af
->
sockaddr_len
;
err_bindx_add:
if
(
retval
<
0
)
{
/* Failed. Cleanup the ones that ha
s
been added */
/* Failed. Cleanup the ones that ha
ve
been added */
if
(
cnt
>
0
)
sctp_bindx_rem
(
sk
,
addrs
,
cnt
);
return
retval
;
...
...
@@ -471,9 +362,9 @@ int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
* At least one address has to be left; if only one address is
* available, the operation will return -EBUSY.
*
* Only
__sctp
_bindx() is supposed to call this function.
* Only
sctp_setsockopt
_bindx() is supposed to call this function.
*/
int
sctp_bindx_rem
(
struct
sock
*
sk
,
struct
sockaddr
_storage
*
addrs
,
int
addrcnt
)
int
sctp_bindx_rem
(
struct
sock
*
sk
,
struct
sockaddr
*
addrs
,
int
addrcnt
)
{
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
struct
sctp_endpoint
*
ep
=
sp
->
ep
;
...
...
@@ -481,50 +372,41 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
struct
sctp_bind_addr
*
bp
=
&
ep
->
base
.
bind_addr
;
int
retval
=
0
;
union
sctp_addr
saveaddr
;
void
*
addr_buf
;
struct
sockaddr
*
sa_addr
;
struct
sctp_af
*
af
;
SCTP_DEBUG_PRINTK
(
"sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)
\n
"
,
sk
,
addrs
,
addrcnt
);
addr_buf
=
addrs
;
for
(
cnt
=
0
;
cnt
<
addrcnt
;
cnt
++
)
{
/* If there is only one bind address, there is nothing more
* to be removed (we need at least one address here).
/* If the bind address list is empty or if there is only one
* bind address, there is nothing more to be removed (we need
* at least one address here).
*/
if
(
list_empty
(
&
bp
->
address_list
))
{
if
(
list_empty
(
&
bp
->
address_list
)
||
(
sctp_list_single_entry
(
&
bp
->
address_list
)))
{
retval
=
-
EBUSY
;
goto
err_bindx_rem
;
}
/* The list may contain either IPv4 or IPv6 address;
* determine the address length for walking thru the list.
* determine the address length to copy the address to
* saveaddr.
*/
switch
(((
struct
sockaddr
*
)
&
addrs
[
cnt
])
->
sa_family
)
{
case
AF_INET
:
saveaddr
=
*
((
union
sctp_addr
*
)
&
addrs
[
cnt
]);
saveaddr
.
v4
.
sin_port
=
ntohs
(
saveaddr
.
v4
.
sin_port
);
/* Verify the port. */
if
(
saveaddr
.
v4
.
sin_port
!=
bp
->
port
)
{
retval
=
-
EINVAL
;
goto
err_bindx_rem
;
}
break
;
case
AF_INET6
:
saveaddr
=
*
((
union
sctp_addr
*
)
&
addrs
[
cnt
]);
saveaddr
.
v6
.
sin6_port
=
ntohs
(
saveaddr
.
v6
.
sin6_port
);
/* verify the port */
if
(
saveaddr
.
v6
.
sin6_port
!=
bp
->
port
)
{
retval
=
-
EINVAL
;
goto
err_bindx_rem
;
}
break
;
default:
sa_addr
=
(
struct
sockaddr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
sa_addr
->
sa_family
);
if
(
!
af
)
{
retval
=
-
EINVAL
;
goto
err_bindx_rem
;
};
}
memcpy
(
&
saveaddr
,
sa_addr
,
af
->
sockaddr_len
);
saveaddr
.
v4
.
sin_port
=
ntohs
(
saveaddr
.
v4
.
sin_port
);
if
(
saveaddr
.
v4
.
sin_port
!=
bp
->
port
)
{
retval
=
-
EINVAL
;
goto
err_bindx_rem
;
}
/* FIXME - There is probably a need to check if sk->sk_saddr and
* sk->sk_rcv_addr are currently set to one of the addresses to
...
...
@@ -541,6 +423,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
sctp_write_unlock
(
&
ep
->
base
.
addr_lock
);
sctp_local_bh_enable
();
addr_buf
+=
af
->
sockaddr_len
;
err_bindx_rem:
if
(
retval
<
0
)
{
/* Failed. Add the ones that has been removed back */
...
...
@@ -553,18 +436,62 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
return
retval
;
}
/* Helper for tunneling sys_bindx() requests through sctp_setsockopt()
/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
*
* API 8.1
* int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt,
* int flags);
*
* If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
* If the sd is an IPv6 socket, the addresses passed can either be IPv4
* or IPv6 addresses.
*
* A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
* Section 3.1.2 for this usage.
*
* addrs is a pointer to an array of one or more socket addresses. Each
* address is contained in its appropriate structure (i.e. struct
* sockaddr_in or struct sockaddr_in6) the family of the address type
* must be used to distengish the address length (note that this
* representation is termed a "packed array" of addresses). The caller
* specifies the number of addresses in the array with addrcnt.
*
* On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns
* -1, and sets errno to the appropriate error code.
*
* For SCTP, the port given in each socket address must be the same, or
* sctp_bindx() will fail, setting errno to EINVAL.
*
* The flags parameter is formed from the bitwise OR of zero or more of
* the following currently defined flags:
*
* SCTP_BINDX_ADD_ADDR
*
* SCTP_BINDX_REM_ADDR
*
* SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the
* association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given
* addresses from the association. The two flags are mutually exclusive;
* if both are given, sctp_bindx() will fail with EINVAL. A caller may
* not remove all addresses from an association; sctp_bindx() will
* reject such an attempt with EINVAL.
*
* An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate
* additional addresses with an endpoint after calling bind(). Or use
* sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening
* socket is associated with so that no new association accepted will be
* associated with those addresses. If the endpoint supports dynamic
* address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a
* endpoint to send the appropriate message to the peer to change the
* peers address lists.
*
* Adding and removing addresses from a connected association is
* optional functionality. Implementations that do not support this
* functionality should return EOPNOTSUPP.
*
* Basically do nothing but copying the addresses from user to kernel
* land and invoking sctp_bindx on the sk. This is used for tunneling
* the sctp_bindx() [sys_bindx()] request through sctp_setsockopt()
* from userspace.
*
* Note I don't use move_addr_to_kernel(): the reason is we would be
* iterating over an array of struct sockaddr_storage passing always
* what we know is a good size (sizeof (struct sock...)), so it is
* pointless. Instead check the whole area for read access and copy
* it.
* land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
* This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
*
* We don't use copy_from_user() for optimization: we first do the
* sanity checks (buffer size -fast- and access check-healthy
...
...
@@ -584,38 +511,70 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
*
* Returns 0 if ok, <0 errno code on error.
*/
SCTP_STATIC
int
sctp_setsockopt_bindx
(
struct
sock
*
sk
,
struct
sockaddr_storage
*
addrs
,
int
addrssize
,
int
op
)
SCTP_STATIC
int
sctp_setsockopt_bindx
(
struct
sock
*
sk
,
struct
sockaddr
*
addrs
,
int
addrs_size
,
int
op
)
{
struct
sockaddr
_storage
*
kaddrs
;
struct
sockaddr
*
kaddrs
;
int
err
;
size_t
addrcnt
;
int
addrcnt
=
0
;
int
walk_size
=
0
;
struct
sockaddr
*
sa_addr
;
void
*
addr_buf
;
struct
sctp_af
*
af
;
SCTP_DEBUG_PRINTK
(
"sctp_
do_
setsocktopt_bindx: sk %p addrs %p"
" addrs
size %d opt %d
\n
"
,
sk
,
addrs
,
addrs
size
,
op
);
SCTP_DEBUG_PRINTK
(
"sctp_setsocktopt_bindx: sk %p addrs %p"
" addrs
_size %d opt %d
\n
"
,
sk
,
addrs
,
addrs_
size
,
op
);
/* Do we have an integer number of structs sockaddr_storage? */
if
(
unlikely
(
addrssize
<=
0
||
addrssize
%
sizeof
(
struct
sockaddr_storage
)
!=
0
))
if
(
unlikely
(
addrs_size
<=
0
))
return
-
EINVAL
;
/* Check the user passed a healthy pointer. */
if
(
unlikely
(
!
access_ok
(
VERIFY_READ
,
addrs
,
addrssize
)))
if
(
unlikely
(
!
access_ok
(
VERIFY_READ
,
addrs
,
addrs
_
size
)))
return
-
EFAULT
;
/* Alloc space for the address array in kernel memory. */
kaddrs
=
(
struct
sockaddr
_storage
*
)
kmalloc
(
addrs
size
,
GFP_KERNEL
);
kaddrs
=
(
struct
sockaddr
*
)
kmalloc
(
addrs_
size
,
GFP_KERNEL
);
if
(
unlikely
(
!
kaddrs
))
return
-
ENOMEM
;
if
(
copy_from_user
(
kaddrs
,
addrs
,
addrs
size
))
{
if
(
__copy_from_user
(
kaddrs
,
addrs
,
addrs_
size
))
{
kfree
(
kaddrs
);
return
-
EFAULT
;
}
addrcnt
=
addrssize
/
sizeof
(
struct
sockaddr_storage
);
err
=
__sctp_bindx
(
sk
,
kaddrs
,
addrcnt
,
op
);
/* Do the work. */
/* Walk through the addrs buffer and count the number of addresses. */
addr_buf
=
kaddrs
;
while
(
walk_size
<
addrs_size
)
{
sa_addr
=
(
struct
sockaddr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
sa_addr
->
sa_family
);
/* If the address family is not supported or if this address
* causes the address buffer to overflow return EINVAL.
*/
if
(
!
af
||
(
walk_size
+
af
->
sockaddr_len
)
>
addrs_size
)
{
kfree
(
kaddrs
);
return
-
EINVAL
;
}
addrcnt
++
;
addr_buf
+=
af
->
sockaddr_len
;
walk_size
+=
af
->
sockaddr_len
;
}
/* Do the work. */
switch
(
op
)
{
case
SCTP_BINDX_ADD_ADDR
:
err
=
sctp_bindx_add
(
sk
,
kaddrs
,
addrcnt
);
break
;
case
SCTP_BINDX_REM_ADDR
:
err
=
sctp_bindx_rem
(
sk
,
kaddrs
,
addrcnt
);
break
;
default:
err
=
-
EINVAL
;
break
;
};
kfree
(
kaddrs
);
return
err
;
...
...
@@ -1476,7 +1435,7 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen)
}
/*
* 7.1.14 Set default send parameters (S
ET
_DEFAULT_SEND_PARAM)
* 7.1.14 Set default send parameters (S
CTP
_DEFAULT_SEND_PARAM)
*
* Applications that wish to use the sendto() system call may wish to
* specify a default set of parameters that would normally be supplied
...
...
@@ -1522,7 +1481,7 @@ static int sctp_setsockopt_default_send_param(struct sock *sk,
return
0
;
}
/* 7.1.10 Set P
eer P
rimary Address (SCTP_PRIMARY_ADDR)
/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
* the association primary. The enclosed address must be one of the
...
...
@@ -1727,6 +1686,62 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen)
return
0
;
}
/*
* 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
*
* Requests that the peer mark the enclosed address as the association
* primary. The enclosed address must be one of the association's
* locally bound addresses. The following structure is used to make a
* set primary request:
*/
static
int
sctp_setsockopt_peer_primary_addr
(
struct
sock
*
sk
,
char
*
optval
,
int
optlen
)
{
struct
sctp_opt
*
sp
;
struct
sctp_endpoint
*
ep
;
struct
sctp_association
*
asoc
=
NULL
;
struct
sctp_setpeerprim
prim
;
struct
sctp_chunk
*
chunk
;
int
err
;
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
if
(
optlen
!=
sizeof
(
struct
sctp_setpeerprim
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
prim
,
optval
,
optlen
))
return
-
EFAULT
;
asoc
=
sctp_id2assoc
(
sk
,
prim
.
sspp_assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
if
(
!
sctp_state
(
asoc
,
ESTABLISHED
))
return
-
ENOTCONN
;
if
(
!
sctp_assoc_lookup_laddr
(
asoc
,
(
union
sctp_addr
*
)
&
prim
.
sspp_addr
))
return
-
EADDRNOTAVAIL
;
/* Create an ASCONF chunk with SET_PRIMARY parameter */
chunk
=
sctp_make_asconf_set_prim
(
asoc
,
(
union
sctp_addr
*
)
&
prim
.
sspp_addr
);
if
(
!
chunk
)
return
-
ENOMEM
;
err
=
sctp_primitive_ASCONF
(
asoc
,
chunk
);
if
(
err
)
{
sctp_chunk_free
(
chunk
);
return
err
;
}
SCTP_DEBUG_PRINTK
(
"We set peer primary addr primitively.
\n
"
);
return
0
;
}
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
...
...
@@ -1771,16 +1786,14 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
switch
(
optname
)
{
case
SCTP_SOCKOPT_BINDX_ADD
:
/* 'optlen' is the size of the addresses buffer. */
retval
=
sctp_setsockopt_bindx
(
sk
,
(
struct
sockaddr_storage
*
)
optval
,
optlen
,
SCTP_BINDX_ADD_ADDR
);
retval
=
sctp_setsockopt_bindx
(
sk
,
(
struct
sockaddr
*
)
optval
,
optlen
,
SCTP_BINDX_ADD_ADDR
);
break
;
case
SCTP_SOCKOPT_BINDX_REM
:
/* 'optlen' is the size of the addresses buffer. */
retval
=
sctp_setsockopt_bindx
(
sk
,
(
struct
sockaddr_storage
*
)
optval
,
optlen
,
SCTP_BINDX_REM_ADDR
);
retval
=
sctp_setsockopt_bindx
(
sk
,
(
struct
sockaddr
*
)
optval
,
optlen
,
SCTP_BINDX_REM_ADDR
);
break
;
case
SCTP_DISABLE_FRAGMENTS
:
...
...
@@ -1809,6 +1822,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
case
SCTP_PRIMARY_ADDR
:
retval
=
sctp_setsockopt_primary_addr
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_SET_PEER_PRIMARY_ADDR
:
retval
=
sctp_setsockopt_peer_primary_addr
(
sk
,
optval
,
optlen
);
break
;
case
SCTP_NODELAY
:
retval
=
sctp_setsockopt_nodelay
(
sk
,
optval
,
optlen
);
break
;
...
...
@@ -2056,9 +2072,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
return
-
ESOCKTNOSUPPORT
;
}
/* FIXME: The next draft (04) of the SCTP Sockets Extensions
* should include a socket option for manipulating these
* message parameters (and a few others).
/* Initialize default send parameters. These parameters can be
* modified with the SCTP_DEFAULT_SEND_PARAM socket option.
*/
sp
->
default_stream
=
0
;
sp
->
default_ppid
=
0
;
...
...
@@ -2077,7 +2092,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Initialize default RTO related parameters. These parameters can
* be modified for with the SCTP_RTOINFO socket option.
* FIXME: These are not used yet.
*/
sp
->
rtoinfo
.
srto_initial
=
(
sctp_rto_initial
/
HZ
)
*
1000
;
sp
->
rtoinfo
.
srto_max
=
(
sctp_rto_max
/
HZ
)
*
1000
;
...
...
@@ -2093,15 +2107,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp
->
assocparams
.
sasoc_cookie_life
=
(
sctp_valid_cookie_life
/
HZ
)
*
1000
;
/* Initialize default event subscriptions.
* the struct sock is initialized to zero, so only
* enable the events needed. By default, UDP-style
* sockets enable io and association change notifications.
/* Initialize default event subscriptions. By default, all the
* options are off.
*/
if
(
sctp_style
(
sk
,
UDP
))
{
sp
->
subscribe
.
sctp_data_io_event
=
1
;
sp
->
subscribe
.
sctp_association_event
=
1
;
}
memset
(
&
sp
->
subscribe
,
0
,
sizeof
(
struct
sctp_event_subscribe
));
/* Default Peer Address Parameters. These defaults can
* be modified via SCTP_PEER_ADDR_PARAMS
...
...
@@ -2552,7 +2561,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *
}
static
int
sctp_getsockopt_peer_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
char
*
optval
,
int
*
optlen
)
{
sctp_assoc_t
id
;
struct
sctp_association
*
asoc
;
...
...
@@ -2565,9 +2574,7 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
if
(
copy_from_user
(
&
id
,
optval
,
sizeof
(
sctp_assoc_t
)))
return
-
EFAULT
;
/*
* For UDP-style sockets, id specifies the association to query.
*/
/* For UDP-style sockets, id specifies the association to query. */
asoc
=
sctp_id2assoc
(
sk
,
id
);
if
(
!
asoc
)
return
-
EINVAL
;
...
...
@@ -2582,16 +2589,17 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
}
static
int
sctp_getsockopt_peer_addrs
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
char
*
optval
,
int
*
optlen
)
{
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_transport
*
from
;
struct
sockaddr_storage
*
to
;
void
*
to
;
union
sctp_addr
temp
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
...
...
@@ -2600,21 +2608,21 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
/*
* For UDP-style sockets, id specifies the association to query.
*/
/* For UDP-style sockets, id specifies the association to query. */
asoc
=
sctp_id2assoc
(
sk
,
getaddrs
.
assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
to
=
getaddrs
.
addrs
;
to
=
(
void
*
)
getaddrs
.
addrs
;
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
from
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
memcpy
(
&
temp
,
&
from
->
ipaddr
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
if
(
copy_to_user
(
to
,
&
temp
,
sizeof
(
temp
)))
addrlen
=
sctp_get_af_specific
(
sk
->
sk_family
)
->
sockaddr_len
;
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
return
-
EFAULT
;
to
+
+
;
to
+
=
addrlen
;
cnt
++
;
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
...
...
@@ -2673,9 +2681,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_sockaddr_entry
*
from
;
struct
sockaddr_storage
*
to
;
void
*
to
;
union
sctp_addr
temp
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
...
...
@@ -2699,16 +2708,17 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
bp
=
&
asoc
->
base
.
bind_addr
;
}
to
=
getaddrs
.
addrs
;
to
=
(
void
*
)
getaddrs
.
addrs
;
list_for_each
(
pos
,
&
bp
->
address_list
)
{
from
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
memcpy
(
&
temp
,
&
from
->
a
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
if
(
copy_to_user
(
to
,
&
temp
,
sizeof
(
temp
)))
addrlen
=
sctp_get_af_specific
(
temp
.
sa
.
sa_family
)
->
sockaddr_len
;
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
return
-
EFAULT
;
to
+
+
;
to
+
=
addrlen
;
cnt
++
;
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
...
...
@@ -2759,7 +2769,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
/*
*
* 7.1.14 Set default send parameters (S
ET
_DEFAULT_SEND_PARAM)
* 7.1.14 Set default send parameters (S
CTP
_DEFAULT_SEND_PARAM)
*
* Applications that wish to use the sendto() system call may wish to
* specify a default set of parameters that would normally be supplied
...
...
@@ -3331,9 +3341,19 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
if
(
!
sctp_style
(
sk
,
UDP
))
return
-
EINVAL
;
/* If backlog is zero, disable listening. */
if
(
!
backlog
)
{
if
(
sctp_sstate
(
sk
,
CLOSED
))
return
0
;
sctp_unhash_endpoint
(
ep
);
sk
->
sk_state
=
SCTP_SS_CLOSED
;
}
/* Return if we are already listening. */
if
(
sctp_sstate
(
sk
,
LISTENING
))
return
0
;
/*
* If a bind() or sctp_bindx() is not called prior to a listen()
* call that allows new associations to be accepted, the system
...
...
@@ -3364,6 +3384,15 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
struct
sctp_endpoint
*
ep
=
sp
->
ep
;
/* If backlog is zero, disable listening. */
if
(
!
backlog
)
{
if
(
sctp_sstate
(
sk
,
CLOSED
))
return
0
;
sctp_unhash_endpoint
(
ep
);
sk
->
sk_state
=
SCTP_SS_CLOSED
;
}
if
(
sctp_sstate
(
sk
,
LISTENING
))
return
0
;
...
...
net/sctp/sysctl.c
View file @
f72c208b
...
...
@@ -214,7 +214,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
if
(
olen
!=
sizeof
(
int
))
return
-
EINVAL
;
}
if
(
put_user
((
*
(
int
*
)(
table
->
data
)
/
HZ
)
*
1000
,
if
(
put_user
((
*
(
int
*
)(
table
->
data
)
*
1000
)
/
HZ
,
(
int
*
)
oldval
)
||
(
oldlenp
&&
put_user
(
sizeof
(
int
),
oldlenp
)))
return
-
EFAULT
;
...
...
@@ -228,7 +228,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
if
(
get_user
(
new
,
(
int
*
)
newval
))
return
-
EFAULT
;
*
(
int
*
)(
table
->
data
)
=
(
new
*
HZ
)
*
1000
;
*
(
int
*
)(
table
->
data
)
=
(
new
*
HZ
)
/
1000
;
}
return
1
;
}
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