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
c425b68c
Commit
c425b68c
authored
Mar 28, 2003
by
Jon Grimm
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCTP] Add LINKLOCAL/sin6_scope_id support.
parent
1bafb09e
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
306 additions
and
214 deletions
+306
-214
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+27
-24
include/net/sctp/sm.h
include/net/sctp/sm.h
+6
-7
include/net/sctp/structs.h
include/net/sctp/structs.h
+63
-64
include/net/sctp/ulpevent.h
include/net/sctp/ulpevent.h
+3
-3
net/sctp/associola.c
net/sctp/associola.c
+13
-17
net/sctp/bind_addr.c
net/sctp/bind_addr.c
+15
-15
net/sctp/input.c
net/sctp/input.c
+7
-7
net/sctp/ipv6.c
net/sctp/ipv6.c
+86
-22
net/sctp/protocol.c
net/sctp/protocol.c
+21
-2
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+50
-37
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+4
-7
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+6
-4
net/sctp/socket.c
net/sctp/socket.c
+4
-5
net/sctp/ulpevent.c
net/sctp/ulpevent.c
+1
-0
No files found.
include/net/sctp/sctp.h
View file @
c425b68c
...
...
@@ -488,21 +488,24 @@ static inline struct sctp_protocol *sctp_get_protocol(void)
/* Convert from an IP version number to an Address Family symbol. */
static
inline
int
ipver2af
(
__u8
ipver
)
{
int
family
;
switch
(
ipver
)
{
case
4
:
family
=
AF_INET
;
break
;
return
AF_INET
;
case
6
:
family
=
AF_INET6
;
break
;
return
AF_INET6
;
default:
family
=
0
;
break
;
return
0
;
};
}
return
family
;
/* Perform some sanity checks. */
static
inline
int
sctp_sanity_check
(
void
)
{
SCTP_ASSERT
(
sizeof
(
struct
sctp_ulpevent
)
<=
sizeof
(((
struct
sk_buff
*
)
0
)
->
cb
),
"SCTP: ulpevent does not fit in skb!
\n
"
,
return
0
);
return
1
;
}
/* Warning: The following hash functions assume a power of two 'size'. */
...
...
include/net/sctp/sm.h
View file @
c425b68c
...
...
@@ -197,15 +197,14 @@ sctp_state_fn_t sctp_addip_do_asconf;
sctp_state_fn_t
sctp_addip_do_asconf_ack
;
/* Prototypes for utility support functions. */
__u8
sctp_get_chunk_type
(
s
ctp_chunk_t
*
chunk
);
__u8
sctp_get_chunk_type
(
s
truct
sctp_chunk
*
chunk
);
sctp_sm_table_entry_t
*
sctp_sm_lookup_event
(
sctp_event_t
event_type
,
sctp_state_t
state
,
sctp_subtype_t
event_subtype
);
time_t
timeval_sub
(
struct
timeval
*
,
struct
timeval
*
);
sctp_association_t
*
sctp_make_temp_asoc
(
const
sctp_endpoint_t
*
,
sctp_chunk_t
*
,
const
int
priority
);
int
sctp_chunk_iif
(
const
struct
sctp_chunk
*
);
struct
sctp_association
*
sctp_make_temp_asoc
(
const
struct
sctp_endpoint
*
,
struct
sctp_chunk
*
,
int
gfp
);
__u32
sctp_generate_verification_tag
(
void
);
void
sctp_populate_tie_tags
(
__u8
*
cookie
,
__u32
curTag
,
__u32
hisTag
);
...
...
@@ -344,7 +343,7 @@ __u32 sctp_generate_tsn(const sctp_endpoint_t *);
/* 4th level prototypes */
void
sctp_param2sockaddr
(
union
sctp_addr
*
addr
,
sctp_addr_param_t
*
,
__u16
port
);
__u16
port
,
int
iif
);
int
sctp_addr2sockaddr
(
const
union
sctp_params
,
union
sctp_addr
*
);
int
sockaddr2sctp_addr
(
const
union
sctp_addr
*
,
sctp_addr_param_t
*
);
...
...
include/net/sctp/structs.h
View file @
c425b68c
...
...
@@ -242,6 +242,7 @@ struct sctp_af {
void
(
*
inaddr_any
)
(
union
sctp_addr
*
,
unsigned
short
);
int
(
*
is_any
)
(
const
union
sctp_addr
*
);
int
(
*
available
)
(
const
union
sctp_addr
*
);
int
(
*
skb_iif
)
(
const
struct
sk_buff
*
sk
);
__u16
net_header_len
;
int
sockaddr_len
;
sa_family_t
sa_family
;
...
...
@@ -260,6 +261,7 @@ struct sctp_pf {
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
);
...
...
@@ -430,7 +432,7 @@ struct sctp_ssnmap {
};
struct
sctp_ssnmap
*
sctp_ssnmap_init
(
struct
sctp_ssnmap
*
,
__u16
,
__u16
);
struct
sctp_ssnmap
*
sctp_ssnmap_new
(
__u16
in
,
__u16
out
,
int
priority
);
struct
sctp_ssnmap
*
sctp_ssnmap_new
(
__u16
in
,
__u16
out
,
int
gfp
);
void
sctp_ssnmap_free
(
struct
sctp_ssnmap
*
map
);
void
sctp_ssnmap_clear
(
struct
sctp_ssnmap
*
map
);
...
...
@@ -509,7 +511,7 @@ struct sctp_chunk {
struct
sctp_sndrcvinfo
sinfo
;
/* Which association does this belong to? */
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
/* What endpoint received this chunk? */
sctp_endpoint_common_t
*
rcvr
;
...
...
@@ -541,11 +543,11 @@ struct sctp_chunk {
struct
sctp_transport
*
transport
;
};
sctp_chunk_t
*
sctp_make_chunk
(
const
s
ctp_association_t
*
,
__u8
type
,
sctp_chunk_t
*
sctp_make_chunk
(
const
s
truct
sctp_association
*
,
__u8
type
,
__u8
flags
,
int
size
);
void
sctp_free_chunk
(
sctp_chunk_t
*
);
void
*
sctp_addto_chunk
(
sctp_chunk_t
*
chunk
,
int
len
,
const
void
*
data
);
sctp_chunk_t
*
sctp_chunkify
(
struct
sk_buff
*
,
const
s
ctp_association_t
*
,
sctp_chunk_t
*
sctp_chunkify
(
struct
sk_buff
*
,
const
s
truct
sctp_association
*
,
struct
sock
*
);
void
sctp_init_addrs
(
sctp_chunk_t
*
,
union
sctp_addr
*
,
union
sctp_addr
*
);
const
union
sctp_addr
*
sctp_source
(
const
sctp_chunk_t
*
chunk
);
...
...
@@ -560,7 +562,7 @@ struct sockaddr_storage_list {
union
sctp_addr
a
;
};
typedef
sctp_chunk_t
*
(
sctp_packet_phandler_t
)(
s
ctp_association_t
*
);
typedef
sctp_chunk_t
*
(
sctp_packet_phandler_t
)(
s
truct
sctp_association
*
);
/* This structure holds lists of chunks as we are assembling for
* transmission.
...
...
@@ -663,7 +665,7 @@ struct sctp_transport {
struct
sctp_af
*
af_specific
;
/* Which association do we belong to? */
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
/* RFC2960
*
...
...
@@ -802,7 +804,8 @@ struct sctp_transport {
struct
sctp_transport
*
sctp_transport_new
(
const
union
sctp_addr
*
,
int
);
struct
sctp_transport
*
sctp_transport_init
(
struct
sctp_transport
*
,
const
union
sctp_addr
*
,
int
);
void
sctp_transport_set_owner
(
struct
sctp_transport
*
,
sctp_association_t
*
);
void
sctp_transport_set_owner
(
struct
sctp_transport
*
,
struct
sctp_association
*
);
void
sctp_transport_route
(
struct
sctp_transport
*
,
union
sctp_addr
*
,
struct
sctp_opt
*
);
void
sctp_transport_pmtu
(
struct
sctp_transport
*
);
...
...
@@ -865,7 +868,7 @@ void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
* When free()'d, it empties itself out via output_handler().
*/
struct
sctp_outq
{
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
/* Data pending that has never been transmitted. */
struct
sk_buff_head
out
;
...
...
@@ -908,8 +911,8 @@ struct sctp_outq {
int
malloced
;
};
struct
sctp_outq
*
sctp_outq_new
(
s
ctp_association_t
*
);
void
sctp_outq_init
(
s
ctp_association_t
*
,
struct
sctp_outq
*
);
struct
sctp_outq
*
sctp_outq_new
(
s
truct
sctp_association
*
);
void
sctp_outq_init
(
s
truct
sctp_association
*
,
struct
sctp_outq
*
);
void
sctp_outq_teardown
(
struct
sctp_outq
*
);
void
sctp_outq_free
(
struct
sctp_outq
*
);
int
sctp_outq_tail
(
struct
sctp_outq
*
,
sctp_chunk_t
*
chunk
);
...
...
@@ -953,20 +956,16 @@ sctp_bind_addr_t *sctp_bind_addr_new(int gfp_mask);
void
sctp_bind_addr_init
(
sctp_bind_addr_t
*
,
__u16
port
);
void
sctp_bind_addr_free
(
sctp_bind_addr_t
*
);
int
sctp_bind_addr_copy
(
sctp_bind_addr_t
*
dest
,
const
sctp_bind_addr_t
*
src
,
sctp_scope_t
scope
,
int
priority
,
int
flags
);
sctp_scope_t
scope
,
int
gfp
,
int
flags
);
int
sctp_add_bind_addr
(
sctp_bind_addr_t
*
,
union
sctp_addr
*
,
int
priority
);
int
gfp
);
int
sctp_del_bind_addr
(
sctp_bind_addr_t
*
,
union
sctp_addr
*
);
int
sctp_bind_addr_match
(
sctp_bind_addr_t
*
,
const
union
sctp_addr
*
,
struct
sctp_opt
*
);
union
sctp_params
sctp_bind_addrs_to_raw
(
const
sctp_bind_addr_t
*
bp
,
int
*
addrs_len
,
int
priority
);
int
sctp_raw_to_bind_addrs
(
sctp_bind_addr_t
*
bp
,
__u8
*
raw_addr_list
,
int
addrs_len
,
unsigned
short
port
,
int
priority
);
union
sctp_params
sctp_bind_addrs_to_raw
(
const
struct
sctp_bind_addr
*
bp
,
int
*
addrs_len
,
int
gfp
);
int
sctp_raw_to_bind_addrs
(
struct
sctp_bind_addr
*
bp
,
__u8
*
raw
,
int
len
,
__u16
port
,
int
gfp
);
sctp_scope_t
sctp_scope
(
const
union
sctp_addr
*
);
int
sctp_in_scope
(
const
union
sctp_addr
*
addr
,
const
sctp_scope_t
scope
);
...
...
@@ -1069,7 +1068,7 @@ struct sctp_endpoint {
* pointer, or table pointers dependent on how SCTP
* is implemented.
*/
/* This is really a list of s
ctp_association_t
entries. */
/* This is really a list of s
truct sctp_association
entries. */
struct
list_head
asocs
;
/* Secret Key: A secret key used by this endpoint to compute
...
...
@@ -1105,12 +1104,12 @@ static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
sctp_endpoint_t
*
sctp_endpoint_new
(
struct
sctp_protocol
*
,
struct
sock
*
,
int
);
sctp_endpoint_t
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
,
struct
sctp_protocol
*
,
struct
sock
*
,
int
priority
);
struct
sock
*
,
int
gfp
);
void
sctp_endpoint_free
(
sctp_endpoint_t
*
);
void
sctp_endpoint_put
(
sctp_endpoint_t
*
);
void
sctp_endpoint_hold
(
sctp_endpoint_t
*
);
void
sctp_endpoint_add_asoc
(
sctp_endpoint_t
*
,
s
ctp_association_t
*
asoc
);
s
ctp_association_t
*
sctp_endpoint_lookup_assoc
(
const
sctp_endpoint_t
*
ep
,
void
sctp_endpoint_add_asoc
(
sctp_endpoint_t
*
,
s
truct
sctp_association
*
asoc
);
s
truct
sctp_association
*
sctp_endpoint_lookup_assoc
(
const
sctp_endpoint_t
*
ep
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
);
int
sctp_endpoint_is_peeled_off
(
sctp_endpoint_t
*
,
const
union
sctp_addr
*
);
...
...
@@ -1119,18 +1118,16 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
int
sctp_has_association
(
const
union
sctp_addr
*
laddr
,
const
union
sctp_addr
*
paddr
);
int
sctp_verify_init
(
const
sctp_association_t
*
asoc
,
sctp_cid_t
cid
,
sctp_init_chunk_t
*
peer_init
,
sctp_chunk_t
*
chunk
,
sctp_chunk_t
**
err_chunk
);
int
sctp_process_init
(
sctp_association_t
*
asoc
,
sctp_cid_t
cid
,
const
union
sctp_addr
*
peer_addr
,
sctp_init_chunk_t
*
peer_init
,
int
priority
);
int
sctp_process_param
(
sctp_association_t
*
asoc
,
union
sctp_params
param
,
const
union
sctp_addr
*
peer_addr
,
int
priority
);
__u32
sctp_generate_tag
(
const
sctp_endpoint_t
*
ep
);
__u32
sctp_generate_tsn
(
const
sctp_endpoint_t
*
ep
);
int
sctp_verify_init
(
const
struct
sctp_association
*
asoc
,
sctp_cid_t
,
sctp_init_chunk_t
*
peer_init
,
struct
sctp_chunk
*
chunk
,
struct
sctp_chunk
**
err_chunk
);
int
sctp_process_init
(
struct
sctp_association
*
,
sctp_cid_t
cid
,
const
union
sctp_addr
*
peer
,
sctp_init_chunk_t
*
init
,
int
gfp
);
int
sctp_process_param
(
struct
sctp_association
*
,
union
sctp_params
param
,
const
union
sctp_addr
*
from
,
int
gfp
);
__u32
sctp_generate_tag
(
const
sctp_endpoint_t
*
);
__u32
sctp_generate_tsn
(
const
sctp_endpoint_t
*
);
/* RFC2960
...
...
@@ -1159,7 +1156,7 @@ struct sctp_association {
struct
list_head
asocs
;
/* This is a signature that lets us know that this is a
* s
ctp_association_t
data structure. Used for mapping an
* s
truct sctp_association
data structure. Used for mapping an
* association id to an association.
*/
__u32
eyecatcher
;
...
...
@@ -1562,44 +1559,46 @@ enum {
};
/* Recover the outter association structure. */
static
inline
s
ctp_association_t
*
sctp_assoc
(
sctp_endpoint_common_t
*
base
)
static
inline
s
truct
sctp_association
*
sctp_assoc
(
sctp_endpoint_common_t
*
base
)
{
s
ctp_association_t
*
asoc
;
s
truct
sctp_association
*
asoc
;
asoc
=
container_of
(
base
,
s
ctp_association_t
,
base
);
asoc
=
container_of
(
base
,
s
truct
sctp_association
,
base
);
return
asoc
;
}
/* These are function signatures for manipulating associations. */
s
ctp_association_t
*
s
truct
sctp_association
*
sctp_association_new
(
const
sctp_endpoint_t
*
,
const
struct
sock
*
,
sctp_scope_t
scope
,
int
priority
);
s
ctp_association_t
*
sctp_association_init
(
s
ctp_association_t
*
,
const
sctp_endpoint_t
*
,
sctp_scope_t
scope
,
int
gfp
);
s
truct
sctp_association
*
sctp_association_init
(
s
truct
sctp_association
*
,
const
sctp_endpoint_t
*
,
const
struct
sock
*
,
sctp_scope_t
scope
,
int
priority
);
void
sctp_association_free
(
sctp_association_t
*
);
void
sctp_association_put
(
sctp_association_t
*
);
void
sctp_association_hold
(
sctp_association_t
*
);
struct
sctp_transport
*
sctp_assoc_choose_shutdown_transport
(
sctp_association_t
*
);
void
sctp_assoc_update_retran_path
(
sctp_association_t
*
);
struct
sctp_transport
*
sctp_assoc_lookup_paddr
(
const
sctp_association_t
*
,
int
gfp
);
void
sctp_association_free
(
struct
sctp_association
*
);
void
sctp_association_put
(
struct
sctp_association
*
);
void
sctp_association_hold
(
struct
sctp_association
*
);
struct
sctp_transport
*
sctp_assoc_choose_shutdown_transport
(
struct
sctp_association
*
);
void
sctp_assoc_update_retran_path
(
struct
sctp_association
*
);
struct
sctp_transport
*
sctp_assoc_lookup_paddr
(
const
struct
sctp_association
*
,
const
union
sctp_addr
*
);
struct
sctp_transport
*
sctp_assoc_add_peer
(
s
ctp_association_t
*
,
struct
sctp_transport
*
sctp_assoc_add_peer
(
s
truct
sctp_association
*
,
const
union
sctp_addr
*
address
,
const
int
priority
);
const
int
gfp
);
void
sctp_assoc_control_transport
(
struct
sctp_association
*
,
struct
sctp_transport
*
,
sctp_transport_cmd_t
,
sctp_sn_error_t
);
struct
sctp_transport
*
sctp_assoc_lookup_tsn
(
s
ctp_association_t
*
,
__u32
);
struct
sctp_transport
*
sctp_assoc_is_match
(
s
ctp_association_t
*
,
struct
sctp_transport
*
sctp_assoc_lookup_tsn
(
s
truct
sctp_association
*
,
__u32
);
struct
sctp_transport
*
sctp_assoc_is_match
(
s
truct
sctp_association
*
,
const
union
sctp_addr
*
,
const
union
sctp_addr
*
);
void
sctp_assoc_migrate
(
sctp_association_t
*
,
struct
sock
*
);
void
sctp_assoc_update
(
sctp_association_t
*
dst
,
sctp_association_t
*
src
);
void
sctp_assoc_migrate
(
struct
sctp_association
*
,
struct
sock
*
);
void
sctp_assoc_update
(
struct
sctp_association
*
old
,
struct
sctp_association
*
new
);
__u32
sctp_association_get_next_tsn
(
struct
sctp_association
*
);
__u32
sctp_association_get_tsn_block
(
struct
sctp_association
*
,
int
);
...
...
@@ -1609,14 +1608,14 @@ void sctp_assoc_rwnd_increase(struct sctp_association *, int);
void
sctp_assoc_rwnd_decrease
(
struct
sctp_association
*
,
int
);
void
sctp_assoc_set_primary
(
struct
sctp_association
*
,
struct
sctp_transport
*
);
int
sctp_assoc_set_bind_addr_from_ep
(
s
ctp_association_t
*
,
int
);
int
sctp_assoc_set_bind_addr_from_cookie
(
s
ctp_association_t
*
,
sctp_cookie_t
*
,
int
);
int
sctp_assoc_set_bind_addr_from_ep
(
s
truct
sctp_association
*
,
int
);
int
sctp_assoc_set_bind_addr_from_cookie
(
s
truct
sctp_association
*
,
sctp_cookie_t
*
,
int
gfp
);
int
sctp_cmp_addr_exact
(
const
union
sctp_addr
*
ss1
,
const
union
sctp_addr
*
ss2
);
sctp_chunk_t
*
sctp_get_ecne_prepend
(
s
ctp_association_t
*
asoc
);
sctp_chunk_t
*
sctp_get_no_prepend
(
s
ctp_association_t
*
asoc
);
sctp_chunk_t
*
sctp_get_ecne_prepend
(
s
truct
sctp_association
*
asoc
);
sctp_chunk_t
*
sctp_get_no_prepend
(
s
truct
sctp_association
*
asoc
);
/* A convenience structure to parse out SCTP specific CMSGs. */
typedef
struct
sctp_cmsgs
{
...
...
include/net/sctp/ulpevent.h
View file @
c425b68c
...
...
@@ -38,7 +38,6 @@
* be incorporated into the next SCTP release.
*/
#ifndef __sctp_ulpevent_h__
#define __sctp_ulpevent_h__
...
...
@@ -50,6 +49,7 @@ struct sctp_ulpevent {
struct
sctp_association
*
asoc
;
struct
sctp_sndrcvinfo
sndrcvinfo
;
int
msg_flags
;
int
iif
;
};
/* Retrieve the skb this event sits inside of. */
...
...
net/sctp/associola.c
View file @
c425b68c
...
...
@@ -641,8 +641,6 @@ __u32 sctp_association_get_tsn_block(sctp_association_t *asoc, int num)
/* Compare two addresses to see if they match. Wildcard addresses
* only match themselves.
*
* FIXME: We do not match address scopes correctly.
*/
int
sctp_cmp_addr_exact
(
const
union
sctp_addr
*
ss1
,
const
union
sctp_addr
*
ss2
)
...
...
@@ -650,7 +648,7 @@ int sctp_cmp_addr_exact(const union sctp_addr *ss1,
struct
sctp_af
*
af
;
af
=
sctp_get_af_specific
(
ss1
->
sa
.
sa_family
);
if
(
!
af
)
if
(
unlikely
(
!
af
)
)
return
0
;
return
af
->
cmp_addr
(
ss1
,
ss2
);
...
...
@@ -1064,7 +1062,7 @@ void sctp_assoc_rwnd_decrease(sctp_association_t *asoc, int len)
/* Build the bind address list for the association based on info from the
* local endpoint and the remote peer.
*/
int
sctp_assoc_set_bind_addr_from_ep
(
s
ctp_association_t
*
asoc
,
int
priority
)
int
sctp_assoc_set_bind_addr_from_ep
(
s
truct
sctp_association
*
asoc
,
int
gfp
)
{
sctp_scope_t
scope
;
int
flags
;
...
...
@@ -1081,19 +1079,17 @@ int sctp_assoc_set_bind_addr_from_ep(sctp_association_t *asoc, int priority)
return
sctp_bind_addr_copy
(
&
asoc
->
base
.
bind_addr
,
&
asoc
->
ep
->
base
.
bind_addr
,
scope
,
priority
,
flags
);
scope
,
gfp
,
flags
);
}
/* Build the association's bind address list from the cookie. */
int
sctp_assoc_set_bind_addr_from_cookie
(
sctp_association_t
*
asoc
,
sctp_cookie_t
*
cookie
,
int
priority
)
sctp_cookie_t
*
cookie
,
int
gfp
)
{
int
var_size2
=
ntohs
(
cookie
->
peer_init
->
chunk_hdr
.
length
);
int
var_size3
=
cookie
->
raw_addr_list_len
;
__u8
*
raw_addr_list
=
(
__u8
*
)
cookie
+
sizeof
(
sctp_cookie_t
)
+
var_size2
;
__u8
*
raw
=
(
__u8
*
)
cookie
+
sizeof
(
sctp_cookie_t
)
+
var_size2
;
return
sctp_raw_to_bind_addrs
(
&
asoc
->
base
.
bind_addr
,
raw_addr_list
,
var_size3
,
asoc
->
ep
->
base
.
bind_addr
.
port
,
priority
);
return
sctp_raw_to_bind_addrs
(
&
asoc
->
base
.
bind_addr
,
raw
,
var_size3
,
asoc
->
ep
->
base
.
bind_addr
.
port
,
gfp
);
}
net/sctp/bind_addr.c
View file @
c425b68c
...
...
@@ -53,7 +53,7 @@
/* Forward declarations for internal helpers. */
static
int
sctp_copy_one_addr
(
sctp_bind_addr_t
*
,
union
sctp_addr
*
,
sctp_scope_t
scope
,
int
priority
,
int
flags
);
sctp_scope_t
scope
,
int
gfp
,
int
flags
);
static
void
sctp_bind_addr_clean
(
sctp_bind_addr_t
*
);
/* First Level Abstractions. */
...
...
@@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(sctp_bind_addr_t *);
* in 'src' which have a broader scope than 'scope'.
*/
int
sctp_bind_addr_copy
(
sctp_bind_addr_t
*
dest
,
const
sctp_bind_addr_t
*
src
,
sctp_scope_t
scope
,
int
priority
,
int
flags
)
sctp_scope_t
scope
,
int
gfp
,
int
flags
)
{
struct
sockaddr_storage_list
*
addr
;
struct
list_head
*
pos
;
...
...
@@ -75,7 +75,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
list_for_each
(
pos
,
&
src
->
address_list
)
{
addr
=
list_entry
(
pos
,
struct
sockaddr_storage_list
,
list
);
error
=
sctp_copy_one_addr
(
dest
,
&
addr
->
a
,
scope
,
priority
,
flags
);
gfp
,
flags
);
if
(
error
<
0
)
goto
out
;
}
...
...
@@ -88,11 +88,11 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
}
/* Create a new SCTP_bind_addr from nothing. */
sctp_bind_addr_t
*
sctp_bind_addr_new
(
int
priority
)
sctp_bind_addr_t
*
sctp_bind_addr_new
(
int
gfp
)
{
sctp_bind_addr_t
*
retval
;
retval
=
t_new
(
sctp_bind_addr_t
,
priority
);
retval
=
t_new
(
sctp_bind_addr_t
,
gfp
);
if
(
!
retval
)
goto
nomem
;
...
...
@@ -144,12 +144,12 @@ void sctp_bind_addr_free(sctp_bind_addr_t *bp)
/* Add an address to the bind address list in the SCTP_bind_addr structure. */
int
sctp_add_bind_addr
(
sctp_bind_addr_t
*
bp
,
union
sctp_addr
*
new
,
int
priority
)
int
gfp
)
{
struct
sockaddr_storage_list
*
addr
;
/* Add the address to the bind address list. */
addr
=
t_new
(
struct
sockaddr_storage_list
,
priority
);
addr
=
t_new
(
struct
sockaddr_storage_list
,
gfp
);
if
(
!
addr
)
return
-
ENOMEM
;
...
...
@@ -197,7 +197,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr)
* The second argument is the return value for the length.
*/
union
sctp_params
sctp_bind_addrs_to_raw
(
const
sctp_bind_addr_t
*
bp
,
int
*
addrs_len
,
int
priority
)
int
*
addrs_len
,
int
gfp
)
{
union
sctp_params
addrparms
;
union
sctp_params
retval
;
...
...
@@ -214,7 +214,7 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
len
+=
sizeof
(
sctp_addr_param_t
);
}
retval
.
v
=
kmalloc
(
len
,
priority
);
retval
.
v
=
kmalloc
(
len
,
gfp
);
if
(
!
retval
.
v
)
goto
end_raw
;
...
...
@@ -238,7 +238,7 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
* address parameters).
*/
int
sctp_raw_to_bind_addrs
(
sctp_bind_addr_t
*
bp
,
__u8
*
raw_addr_list
,
int
addrs_len
,
__u16
port
,
int
priority
)
int
addrs_len
,
__u16
port
,
int
gfp
)
{
sctp_addr_param_t
*
rawaddr
;
sctp_paramhdr_t
*
param
;
...
...
@@ -254,8 +254,8 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
switch
(
param
->
type
)
{
case
SCTP_PARAM_IPV4_ADDRESS
:
case
SCTP_PARAM_IPV6_ADDRESS
:
sctp_param2sockaddr
(
&
addr
,
rawaddr
,
port
);
retval
=
sctp_add_bind_addr
(
bp
,
&
addr
,
priority
);
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
);
...
...
@@ -300,14 +300,14 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
/* Copy out addresses from the global local address list. */
static
int
sctp_copy_one_addr
(
sctp_bind_addr_t
*
dest
,
union
sctp_addr
*
addr
,
sctp_scope_t
scope
,
int
priority
,
int
flags
)
sctp_scope_t
scope
,
int
gfp
,
int
flags
)
{
struct
sctp_protocol
*
proto
=
sctp_get_protocol
();
int
error
=
0
;
if
(
sctp_is_any
(
addr
))
{
error
=
sctp_copy_local_addr_list
(
proto
,
dest
,
scope
,
priority
,
flags
);
gfp
,
flags
);
}
else
if
(
sctp_in_scope
(
addr
,
scope
))
{
/* Now that the address is in scope, check to see if
* the address type is supported by local sock as
...
...
@@ -318,7 +318,7 @@ static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr,
(((
AF_INET6
==
addr
->
sa
.
sa_family
)
&&
(
flags
&
SCTP_ADDR6_ALLOWED
)
&&
(
flags
&
SCTP_ADDR6_PEERSUPP
))))
error
=
sctp_add_bind_addr
(
dest
,
addr
,
priority
);
error
=
sctp_add_bind_addr
(
dest
,
addr
,
gfp
);
}
return
error
;
...
...
net/sctp/input.c
View file @
c425b68c
...
...
@@ -674,9 +674,9 @@ void __sctp_unhash_established(sctp_association_t *asoc)
}
/* Look up an association. */
sctp_association_t
*
__sctp_lookup_association
(
const
union
sctp_addr
*
l
addr
,
const
union
sctp_addr
*
p
add
r
,
struct
sctp_transport
**
transportp
)
sctp_association_t
*
__sctp_lookup_association
(
const
union
sctp_addr
*
l
ocal
,
const
union
sctp_addr
*
p
ee
r
,
struct
sctp_transport
**
pt
)
{
sctp_hashbucket_t
*
head
;
sctp_endpoint_common_t
*
epb
;
...
...
@@ -687,12 +687,12 @@ sctp_association_t *__sctp_lookup_association(const union sctp_addr *laddr,
/* Optimize here for direct hit, only listening connections can
* have wildcards anyways.
*/
hash
=
sctp_assoc_hashfn
(
l
addr
->
v4
.
sin_port
,
padd
r
->
v4
.
sin_port
);
hash
=
sctp_assoc_hashfn
(
l
ocal
->
v4
.
sin_port
,
pee
r
->
v4
.
sin_port
);
head
=
&
sctp_proto
.
assoc_hashbucket
[
hash
];
read_lock
(
&
head
->
lock
);
for
(
epb
=
head
->
chain
;
epb
;
epb
=
epb
->
next
)
{
asoc
=
sctp_assoc
(
epb
);
transport
=
sctp_assoc_is_match
(
asoc
,
l
addr
,
padd
r
);
transport
=
sctp_assoc_is_match
(
asoc
,
l
ocal
,
pee
r
);
if
(
transport
)
goto
hit
;
}
...
...
@@ -702,7 +702,7 @@ sctp_association_t *__sctp_lookup_association(const union sctp_addr *laddr,
return
NULL
;
hit:
*
transportp
=
transport
;
*
pt
=
transport
;
sctp_association_hold
(
asoc
);
sock_hold
(
epb
->
sk
);
read_unlock
(
&
head
->
lock
);
...
...
@@ -805,7 +805,7 @@ static sctp_association_t *__sctp_rcv_init_lookup(struct sk_buff *skb,
(
SCTP_PARAM_IPV6_ADDRESS
!=
params
.
p
->
type
))
continue
;
sctp_param2sockaddr
(
paddr
,
params
.
addr
,
ntohs
(
sh
->
source
));
sctp_param2sockaddr
(
paddr
,
params
.
addr
,
ntohs
(
sh
->
source
)
,
0
);
asoc
=
__sctp_lookup_association
(
laddr
,
paddr
,
transportp
);
if
(
asoc
)
return
asoc
;
...
...
net/sctp/ipv6.c
View file @
c425b68c
...
...
@@ -161,9 +161,12 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
fl
.
fl6_flowlabel
=
np
->
flow_label
;
IP6_ECN_flow_xmit
(
sk
,
fl
.
fl6_flowlabel
);
if
(
ipv6_addr_type
(
fl
.
fl6_src
)
&
IPV6_ADDR_LINKLOCAL
)
fl
.
oif
=
transport
->
saddr
.
v6
.
sin6_scope_id
;
else
fl
.
oif
=
sk
->
bound_dev_if
;
fl
.
uli_u
.
ports
.
sport
=
inet_sk
(
sk
)
->
sport
;
fl
.
uli_u
.
ports
.
dport
=
inet_sk
(
sk
)
->
d
port
;
fl
.
uli_u
.
ports
.
dport
=
transport
->
ipaddr
.
v6
.
sin6_
port
;
if
(
np
->
opt
&&
np
->
opt
->
srcrt
)
{
struct
rt0_hdr
*
rt0
=
(
struct
rt0_hdr
*
)
np
->
opt
->
srcrt
;
...
...
@@ -259,7 +262,7 @@ void sctp_v6_get_saddr(sctp_association_t *asoc, struct dst_entry *dst,
__FUNCTION__
,
asoc
,
dst
,
NIP6
(
&
daddr
->
v6
.
sin6_addr
));
if
(
!
asoc
)
{
ipv6_get_saddr
(
dst
,
&
daddr
->
v6
.
sin6_addr
,
&
saddr
->
v6
.
sin6_addr
);
ipv6_get_saddr
(
dst
,
&
daddr
->
v6
.
sin6_addr
,
&
saddr
->
v6
.
sin6_addr
);
SCTP_DEBUG_PRINTK
(
"saddr from ipv6_get_saddr: "
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x
\n
"
,
NIP6
(
&
saddr
->
v6
.
sin6_addr
));
...
...
@@ -324,6 +327,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
addr
->
a
.
v6
.
sin6_family
=
AF_INET6
;
addr
->
a
.
v6
.
sin6_port
=
0
;
addr
->
a
.
v6
.
sin6_addr
=
ifp
->
addr
;
addr
->
a
.
v6
.
sin6_scope_id
=
dev
->
ifindex
;
INIT_LIST_HEAD
(
&
addr
->
list
);
list_add_tail
(
&
addr
->
list
,
addrlist
);
}
...
...
@@ -344,7 +348,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
port
=
&
addr
->
v6
.
sin6_port
;
addr
->
v6
.
sin6_family
=
AF_INET6
;
addr
->
v6
.
sin6_flowinfo
=
0
;
/* FIXME */
addr
->
v6
.
sin6_scope_id
=
0
;
/* FIXME */
addr
->
v6
.
sin6_scope_id
=
((
struct
inet6_skb_parm
*
)
skb
->
cb
)
->
iif
;
sh
=
(
struct
sctphdr
*
)
skb
->
h
.
raw
;
if
(
is_saddr
)
{
...
...
@@ -381,19 +385,25 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
ipv6_addr_copy
(
&
addr
->
v6
.
sin6_addr
,
&
rt
->
rt6i_src
.
addr
);
}
/* Compare addresses exactly.
Well.. almost exactly; ignore scope_id
*
for now.
FIXME: v4-mapped-v6.
/* Compare addresses exactly.
* FIXME: v4-mapped-v6.
*/
static
int
sctp_v6_cmp_addr
(
const
union
sctp_addr
*
addr1
,
const
union
sctp_addr
*
addr2
)
{
int
match
;
if
(
addr1
->
sa
.
sa_family
!=
addr2
->
sa
.
sa_family
)
return
0
;
match
=
!
ipv6_addr_cmp
((
struct
in6_addr
*
)
&
addr1
->
v6
.
sin6_addr
,
(
struct
in6_addr
*
)
&
addr2
->
v6
.
sin6_addr
);
if
(
ipv6_addr_cmp
(
&
addr1
->
v6
.
sin6_addr
,
&
addr2
->
v6
.
sin6_addr
))
return
0
;
/* If this is a linklocal address, compare the scope_id. */
if
(
ipv6_addr_type
(
&
addr1
->
v6
.
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
)
{
if
(
addr1
->
v6
.
sin6_scope_id
&&
addr2
->
v6
.
sin6_scope_id
&&
(
addr1
->
v6
.
sin6_scope_id
!=
addr2
->
v6
.
sin6_scope_id
))
{
return
0
;
}
}
return
match
;
return
1
;
}
/* Initialize addr struct to INADDR_ANY. */
...
...
@@ -427,7 +437,6 @@ static int sctp_v6_available(const union sctp_addr *addr)
return
ipv6_chk_addr
(
in6
,
NULL
);
}
/* This function checks if the address is a valid address to be used for
* SCTP.
*
...
...
@@ -533,6 +542,13 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
return
newsk
;
}
/* Where did this skb come from? */
static
int
sctp_v6_skb_iif
(
const
struct
sk_buff
*
skb
)
{
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
return
opt
->
iif
;
}
/* Initialize a PF_INET6 socket msg_name. */
static
void
sctp_inet6_msgname
(
char
*
msgname
,
int
*
addr_len
)
{
...
...
@@ -541,13 +557,13 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len)
sin6
=
(
struct
sockaddr_in6
*
)
msgname
;
sin6
->
sin6_family
=
AF_INET6
;
sin6
->
sin6_flowinfo
=
0
;
sin6
->
sin6_scope_id
=
0
;
sin6
->
sin6_scope_id
=
0
;
/*FIXME */
*
addr_len
=
sizeof
(
struct
sockaddr_in6
);
}
/* Initialize a PF_INET msgname from a ulpevent. */
static
void
sctp_inet6_event_msgname
(
struct
sctp_ulpevent
*
event
,
char
*
msgname
,
int
*
addrlen
)
static
void
sctp_inet6_event_msgname
(
struct
sctp_ulpevent
*
event
,
char
*
msgname
,
int
*
addrlen
)
{
struct
sockaddr_in6
*
sin6
,
*
sin6from
;
...
...
@@ -573,6 +589,8 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, char *msgname,
sin6from
=
&
event
->
asoc
->
peer
.
primary_addr
.
v6
;
ipv6_addr_copy
(
&
sin6
->
sin6_addr
,
&
sin6from
->
sin6_addr
);
if
(
ipv6_addr_type
(
&
sin6
->
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
)
sin6
->
sin6_scope_id
=
sin6from
->
sin6_scope_id
;
}
}
...
...
@@ -591,8 +609,8 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
/* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */
if
(
__constant_htons
(
ETH_P_IP
)
==
skb
->
protocol
)
{
/* FIXME:
Easy, but there was no way to test this
*
yet
.
/* FIXME:
The latest I-D added options for two
*
behaviors
.
*/
return
;
}
...
...
@@ -601,9 +619,8 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
ipv6_addr_copy
(
&
sin6
->
sin6_addr
,
&
skb
->
nh
.
ipv6h
->
saddr
);
if
(
ipv6_addr_type
(
&
sin6
->
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
)
{
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
sin6
->
sin6_scope_id
=
opt
->
iif
;
struct
sctp_ulpevent
*
ev
=
sctp_skb2event
(
skb
);
sin6
->
sin6_scope_id
=
ev
->
iif
;
}
}
}
...
...
@@ -657,14 +674,59 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
struct
sctp_af
*
af
;
/* ASSERT: address family has already been verified. */
if
(
addr
->
sa
.
sa_family
!=
AF_INET6
)
{
if
(
addr
->
sa
.
sa_family
!=
AF_INET6
)
af
=
sctp_get_af_specific
(
addr
->
sa
.
sa_family
);
}
else
af
=
opt
->
pf
->
af
;
else
{
struct
sock
*
sk
;
int
type
=
ipv6_addr_type
(
&
addr
->
v6
.
sin6_addr
);
sk
=
&
container_of
(
opt
,
struct
sctp6_sock
,
sctp
)
->
sk
;
if
(
type
&
IPV6_ADDR_LINKLOCAL
)
{
/* Note: Behavior similar to af_inet6.c:
* 1) Overrides previous bound_dev_if
* 2) Destructive even if bind isn't successful.
*/
if
(
addr
->
v6
.
sin6_scope_id
)
sk
->
bound_dev_if
=
addr
->
v6
.
sin6_scope_id
;
if
(
!
sk
->
bound_dev_if
)
return
0
;
}
af
=
opt
->
pf
->
af
;
}
return
af
->
available
(
addr
);
}
/* Verify that the provided sockaddr looks bindable. Common verification,
* has already been taken care of.
*/
static
int
sctp_inet6_send_verify
(
struct
sctp_opt
*
opt
,
union
sctp_addr
*
addr
)
{
struct
sctp_af
*
af
=
NULL
;
/* ASSERT: address family has already been verified. */
if
(
addr
->
sa
.
sa_family
!=
AF_INET6
)
af
=
sctp_get_af_specific
(
addr
->
sa
.
sa_family
);
else
{
struct
sock
*
sk
;
int
type
=
ipv6_addr_type
(
&
addr
->
v6
.
sin6_addr
);
sk
=
&
container_of
(
opt
,
struct
sctp6_sock
,
sctp
)
->
sk
;
if
(
type
&
IPV6_ADDR_LINKLOCAL
)
{
/* Note: Behavior similar to af_inet6.c:
* 1) Overrides previous bound_dev_if
* 2) Destructive even if bind isn't successful.
*/
if
(
addr
->
v6
.
sin6_scope_id
)
sk
->
bound_dev_if
=
addr
->
v6
.
sin6_scope_id
;
if
(
!
sk
->
bound_dev_if
)
return
0
;
}
af
=
opt
->
pf
->
af
;
}
return
af
!=
NULL
;
}
/* Fill in Supported Address Type information for INIT and INIT-ACK
* chunks. Note: In the future, we may want to look at sock options
* to determine whether a PF_INET6 socket really wants to have IPV4
...
...
@@ -744,6 +806,7 @@ static struct sctp_af sctp_ipv6_specific = {
.
inaddr_any
=
sctp_v6_inaddr_any
,
.
is_any
=
sctp_v6_is_any
,
.
available
=
sctp_v6_available
,
.
skb_iif
=
sctp_v6_skb_iif
,
.
net_header_len
=
sizeof
(
struct
ipv6hdr
),
.
sockaddr_len
=
sizeof
(
struct
sockaddr_in6
),
.
sa_family
=
AF_INET6
,
...
...
@@ -755,6 +818,7 @@ static struct sctp_pf sctp_pf_inet6_specific = {
.
af_supported
=
sctp_inet6_af_supported
,
.
cmp_addr
=
sctp_inet6_cmp_addr
,
.
bind_verify
=
sctp_inet6_bind_verify
,
.
send_verify
=
sctp_inet6_send_verify
,
.
supported_addrs
=
sctp_inet6_supported_addrs
,
.
create_accept_sk
=
sctp_v6_create_accept_sk
,
.
af
=
&
sctp_ipv6_specific
,
...
...
net/sctp/protocol.c
View file @
c425b68c
...
...
@@ -233,7 +233,6 @@ int sctp_copy_local_addr_list(struct sctp_protocol *proto,
end_copy:
sctp_spin_unlock_irqrestore
(
&
proto
->
local_addr_lock
,
flags
);
return
error
;
}
...
...
@@ -383,7 +382,7 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
* addresses. If an association is passed, trys to get a dst entry with a
* source adddress that matches an address in the bind address list.
*/
struct
dst_entry
*
sctp_v4_get_dst
(
s
ctp_association_t
*
asoc
,
struct
dst_entry
*
sctp_v4_get_dst
(
s
truct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
{
...
...
@@ -480,6 +479,12 @@ void sctp_v4_get_saddr(sctp_association_t *asoc,
}
/* What interface did this skb arrive on? */
int
sctp_v4_skb_iif
(
const
struct
sk_buff
*
skb
)
{
return
((
struct
rtable
*
)
skb
->
dst
)
->
rt_iif
;
}
/* Create and initialize a new sk for the socket returned by accept(). */
struct
sock
*
sctp_v4_create_accept_sk
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
)
...
...
@@ -689,6 +694,14 @@ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
return
sctp_v4_available
(
addr
);
}
/* Verify that sockaddr looks sendable. Common verification has already
* been taken care of.
*/
static
int
sctp_inet_send_verify
(
struct
sctp_opt
*
opt
,
union
sctp_addr
*
addr
)
{
return
1
;
}
/* Fill in Supported Address Type information for INIT and INIT-ACK
* chunks. Returns number of addresses supported.
*/
...
...
@@ -721,6 +734,7 @@ static struct sctp_pf sctp_pf_inet = {
.
af_supported
=
sctp_inet_af_supported
,
.
cmp_addr
=
sctp_inet_cmp_addr
,
.
bind_verify
=
sctp_inet_bind_verify
,
.
send_verify
=
sctp_inet_send_verify
,
.
supported_addrs
=
sctp_inet_supported_addrs
,
.
create_accept_sk
=
sctp_v4_create_accept_sk
,
.
af
=
&
sctp_ipv4_specific
,
...
...
@@ -796,6 +810,7 @@ struct sctp_af sctp_ipv4_specific = {
.
is_any
=
sctp_v4_is_any
,
.
available
=
sctp_v4_available
,
.
scope
=
sctp_v4_scope
,
.
skb_iif
=
sctp_v4_skb_iif
,
.
net_header_len
=
sizeof
(
struct
iphdr
),
.
sockaddr_len
=
sizeof
(
struct
sockaddr_in
),
.
sa_family
=
AF_INET
,
...
...
@@ -873,6 +888,10 @@ __init int sctp_init(void)
int
i
;
int
status
=
0
;
/* SCTP_DEBUG sanity check. */
if
(
!
sctp_sanity_check
())
return
-
EINVAL
;
/* Add SCTP to inet_protos hash table. */
if
(
inet_add_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
)
<
0
)
return
-
EAGAIN
;
...
...
net/sctp/sm_make_chunk.c
View file @
c425b68c
...
...
@@ -66,6 +66,19 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* What was the inbound interface for this chunk? */
int
sctp_chunk_iif
(
const
struct
sctp_chunk
*
chunk
)
{
struct
sctp_af
*
af
;
int
iif
=
0
;
af
=
sctp_get_af_specific
(
ipver2af
(
chunk
->
skb
->
nh
.
iph
->
version
));
if
(
af
)
iif
=
af
->
skb_iif
(
chunk
->
skb
);
return
iif
;
}
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
* Note 2: The ECN capable field is reserved for future use of
...
...
@@ -145,7 +158,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
*/
sctp_chunk_t
*
sctp_make_init
(
const
sctp_association_t
*
asoc
,
const
sctp_bind_addr_t
*
bp
,
int
priority
,
int
vparam_len
)
int
gfp
,
int
vparam_len
)
{
sctp_inithdr_t
init
;
union
sctp_params
addrs
;
...
...
@@ -165,7 +178,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
addrs
.
v
=
NULL
;
/* Convert the provided bind address list to raw format */
addrs
=
sctp_bind_addrs_to_raw
(
bp
,
&
addrs_len
,
priority
);
addrs
=
sctp_bind_addrs_to_raw
(
bp
,
&
addrs_len
,
gfp
);
if
(
!
addrs
.
v
)
goto
nodata
;
...
...
@@ -225,7 +238,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
sctp_chunk_t
*
sctp_make_init_ack
(
const
sctp_association_t
*
asoc
,
const
sctp_chunk_t
*
chunk
,
int
priority
,
int
unkparam_len
)
int
gfp
,
int
unkparam_len
)
{
sctp_inithdr_t
initack
;
sctp_chunk_t
*
retval
;
...
...
@@ -237,8 +250,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
retval
=
NULL
;
addrs
=
sctp_bind_addrs_to_raw
(
&
asoc
->
base
.
bind_addr
,
&
addrs_len
,
priority
);
addrs
=
sctp_bind_addrs_to_raw
(
&
asoc
->
base
.
bind_addr
,
&
addrs_len
,
gfp
);
if
(
!
addrs
.
v
)
goto
nomem_rawaddr
;
...
...
@@ -1282,26 +1294,26 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
}
/* Create a CLOSED association to use with an incoming packet. */
sctp_association_t
*
sctp_make_temp_asoc
(
const
sctp_endpoint_t
*
ep
,
sctp_chunk_t
*
chunk
,
int
priority
)
sctp_association_t
*
sctp_make_temp_asoc
(
const
struct
sctp_endpoint
*
ep
,
struct
sctp_chunk
*
chunk
,
int
gfp
)
{
sctp_association_t
*
asoc
;
struct
sk_buff
*
skb
;
sctp_scope_t
scope
;
/* Create the bare association. */
scope
=
sctp_scope
(
sctp_source
(
chunk
));
asoc
=
sctp_association_new
(
ep
,
ep
->
base
.
sk
,
scope
,
priority
);
asoc
=
sctp_association_new
(
ep
,
ep
->
base
.
sk
,
scope
,
gfp
);
if
(
!
asoc
)
goto
nodata
;
skb
=
chunk
->
skb
;
/* Create an entry for the source address of the packet. */
switch
(
chunk
->
skb
->
nh
.
iph
->
version
)
{
/* 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
=
chunk
->
skb
->
nh
.
iph
->
saddr
;
asoc
->
c
.
peer_addr
.
v4
.
sin_addr
.
s_addr
=
skb
->
nh
.
iph
->
saddr
;
break
;
case
6
:
...
...
@@ -1309,8 +1321,9 @@ sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *ep,
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
=
chunk
->
skb
->
nh
.
ipv6h
->
saddr
;
asoc
->
c
.
peer_addr
.
v6
.
sin6_scope_id
=
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:
...
...
@@ -1397,7 +1410,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
/* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */
sctp_association_t
*
sctp_unpack_cookie
(
const
sctp_endpoint_t
*
ep
,
const
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
int
priority
,
sctp_chunk_t
*
chunk
,
int
gfp
,
int
*
error
,
sctp_chunk_t
**
err_chk_p
)
{
sctp_association_t
*
retval
=
NULL
;
...
...
@@ -1408,6 +1421,7 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
__u8
digest_buf
[
SCTP_SIGNATURE_SIZE
];
int
secret
;
sctp_scope_t
scope
;
struct
sk_buff
*
skb
=
chunk
->
skb
;
headersize
=
sizeof
(
sctp_chunkhdr_t
)
+
SCTP_SECRET_SIZE
;
bodysize
=
ntohs
(
chunk
->
chunk_hdr
->
length
)
-
headersize
;
...
...
@@ -1450,7 +1464,7 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
*/
if
(
!
asoc
&&
tv_lt
(
bear_cookie
->
expiration
,
chunk
->
skb
->
stamp
))
{
if
(
!
asoc
&&
tv_lt
(
bear_cookie
->
expiration
,
skb
->
stamp
))
{
__u16
len
;
/*
* Section 3.3.10.3 Stale Cookie Error (3)
...
...
@@ -1463,9 +1477,9 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
*
err_chk_p
=
sctp_make_op_error_space
(
asoc
,
chunk
,
len
);
if
(
*
err_chk_p
)
{
suseconds_t
usecs
=
(
chunk
->
skb
->
stamp
.
tv_sec
-
suseconds_t
usecs
=
(
skb
->
stamp
.
tv_sec
-
bear_cookie
->
expiration
.
tv_sec
)
*
1000000L
+
chunk
->
skb
->
stamp
.
tv_usec
-
skb
->
stamp
.
tv_usec
-
bear_cookie
->
expiration
.
tv_usec
;
usecs
=
htonl
(
usecs
);
...
...
@@ -1480,7 +1494,7 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
/* Make a new base association. */
scope
=
sctp_scope
(
sctp_source
(
chunk
));
retval
=
sctp_association_new
(
ep
,
ep
->
base
.
sk
,
scope
,
priority
);
retval
=
sctp_association_new
(
ep
,
ep
->
base
.
sk
,
scope
,
gfp
);
if
(
!
retval
)
{
*
error
=
-
SCTP_IERROR_NOMEM
;
goto
fail
;
...
...
@@ -1522,13 +1536,14 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* 3rd Level Abstractions
********************************************************************/
/*
* Report a missing mandatory parameter.
*/
struct
__sctp_missing
{
__u32
num_missing
;
__u16
type
;
}
__attribute__
((
packed
));;
/*
* Report a missing mandatory parameter.
*/
static
int
sctp_process_missing_param
(
const
sctp_association_t
*
asoc
,
sctp_param_t
paramtype
,
sctp_chunk_t
*
chunk
,
...
...
@@ -1774,8 +1789,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
*/
int
sctp_process_init
(
sctp_association_t
*
asoc
,
sctp_cid_t
cid
,
const
union
sctp_addr
*
peer_addr
,
sctp_init_chunk_t
*
peer_init
,
int
priority
)
sctp_init_chunk_t
*
peer_init
,
int
gfp
)
{
union
sctp_params
param
;
struct
sctp_transport
*
transport
;
...
...
@@ -1793,14 +1807,14 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* be a a better choice than any of the embedded addresses.
*/
if
(
peer_addr
)
if
(
!
sctp_assoc_add_peer
(
asoc
,
peer_addr
,
priority
))
if
(
!
sctp_assoc_add_peer
(
asoc
,
peer_addr
,
gfp
))
goto
nomem
;
/* Process the initialization parameters. */
sctp_walk_params
(
param
,
peer_init
,
init_hdr
.
params
)
{
if
(
!
sctp_process_param
(
asoc
,
param
,
peer_addr
,
priority
))
if
(
!
sctp_process_param
(
asoc
,
param
,
peer_addr
,
gfp
))
goto
clean_up
;
}
...
...
@@ -1842,7 +1856,7 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
/* Copy cookie in case we need to resend COOKIE-ECHO. */
cookie
=
asoc
->
peer
.
cookie
;
if
(
cookie
)
{
asoc
->
peer
.
cookie
=
kmalloc
(
asoc
->
peer
.
cookie_len
,
priority
);
asoc
->
peer
.
cookie
=
kmalloc
(
asoc
->
peer
.
cookie_len
,
gfp
);
if
(
!
asoc
->
peer
.
cookie
)
goto
clean_up
;
memcpy
(
asoc
->
peer
.
cookie
,
cookie
,
asoc
->
peer
.
cookie_len
);
...
...
@@ -1871,8 +1885,7 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
/* Allocate storage for the negotiated streams. */
asoc
->
ssnmap
=
sctp_ssnmap_new
(
asoc
->
peer
.
i
.
num_outbound_streams
,
asoc
->
c
.
sinit_num_ostreams
,
priority
);
asoc
->
c
.
sinit_num_ostreams
,
gfp
);
if
(
!
asoc
->
ssnmap
)
goto
nomem_ssnmap
;
...
...
@@ -1914,7 +1927,7 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* structures for the addresses.
*/
int
sctp_process_param
(
sctp_association_t
*
asoc
,
union
sctp_params
param
,
const
union
sctp_addr
*
peer_addr
,
int
priority
)
const
union
sctp_addr
*
peer_addr
,
int
gfp
)
{
union
sctp_addr
addr
;
int
i
;
...
...
@@ -1933,10 +1946,10 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
break
;
/* Fall through. */
case
SCTP_PARAM_IPV4_ADDRESS
:
sctp_param2sockaddr
(
&
addr
,
param
.
addr
,
asoc
->
peer
.
port
);
sctp_param2sockaddr
(
&
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
,
priority
))
if
(
!
sctp_assoc_add_peer
(
asoc
,
&
addr
,
gfp
))
return
0
;
break
;
...
...
@@ -2051,7 +2064,7 @@ __u32 sctp_generate_tsn(const sctp_endpoint_t *ep)
/* Convert from an SCTP IP parameter to a union sctp_addr. */
void
sctp_param2sockaddr
(
union
sctp_addr
*
addr
,
sctp_addr_param_t
*
param
,
__u16
port
)
__u16
port
,
int
iif
)
{
switch
(
param
->
v4
.
param_hdr
.
type
)
{
case
SCTP_PARAM_IPV4_ADDRESS
:
...
...
@@ -2065,7 +2078,7 @@ void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *param,
addr
->
v6
.
sin6_port
=
port
;
addr
->
v6
.
sin6_flowinfo
=
0
;
/* BUG */
addr
->
v6
.
sin6_addr
=
param
->
v6
.
addr
;
addr
->
v6
.
sin6_scope_id
=
0
;
/* BUG */
addr
->
v6
.
sin6_scope_id
=
iif
;
break
;
default:
...
...
net/sctp/sm_sideeffect.c
View file @
c425b68c
...
...
@@ -461,10 +461,9 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
* their work in statefuns directly.
*/
static
int
sctp_cmd_process_init
(
sctp_cmd_seq_t
*
commands
,
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
sctp_init_chunk_t
*
peer_init
,
int
priority
)
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
sctp_init_chunk_t
*
peer_init
,
int
gfp
)
{
int
error
;
...
...
@@ -473,10 +472,8 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands,
* fail during INIT processing (due to malloc problems),
* just return the error and stop processing the stack.
*/
if
(
!
sctp_process_init
(
asoc
,
chunk
->
chunk_hdr
->
type
,
sctp_source
(
chunk
),
peer_init
,
priority
))
sctp_source
(
chunk
),
peer_init
,
gfp
))
error
=
-
ENOMEM
;
else
error
=
0
;
...
...
net/sctp/sm_statefuns.c
View file @
c425b68c
...
...
@@ -1380,7 +1380,8 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const sctp_endpoint_t *ep,
peer_init
=
&
chunk
->
subh
.
cookie_hdr
->
c
.
peer_init
[
0
];
if
(
!
sctp_process_init
(
new_asoc
,
chunk
->
chunk_hdr
->
type
,
sctp_source
(
chunk
),
peer_init
,
GFP_ATOMIC
))
sctp_source
(
chunk
),
peer_init
,
GFP_ATOMIC
))
goto
nomem
;
/* Make sure no new addresses are being added during the
...
...
@@ -1445,7 +1446,8 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const sctp_endpoint_t *ep,
*/
peer_init
=
&
chunk
->
subh
.
cookie_hdr
->
c
.
peer_init
[
0
];
if
(
!
sctp_process_init
(
new_asoc
,
chunk
->
chunk_hdr
->
type
,
sctp_source
(
chunk
),
peer_init
,
GFP_ATOMIC
))
sctp_source
(
chunk
),
peer_init
,
GFP_ATOMIC
))
goto
nomem
;
/* Update the content of current association. */
...
...
net/sctp/socket.c
View file @
c425b68c
...
...
@@ -244,9 +244,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
if
(
!
snum
)
snum
=
inet_sk
(
sk
)
->
num
;
/* Add the address to the bind address list. */
sctp_local_bh_disable
();
sctp_write_lock
(
&
ep
->
base
.
addr_lock
);
...
...
@@ -257,7 +254,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
addr
->
v4
.
sin_port
=
htons
(
addr
->
v4
.
sin_port
);
if
(
!
ret
&&
!
bp
->
port
)
bp
->
port
=
snum
;
sctp_write_unlock
(
&
ep
->
base
.
addr_lock
);
sctp_local_bh_enable
();
...
...
@@ -3152,7 +3148,10 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
return
-
EINVAL
;
/* Is this a valid SCTP address? */
if
(
!
af
->
addr_valid
((
union
sctp_addr
*
)
addr
))
if
(
!
af
->
addr_valid
(
addr
))
return
-
EINVAL
;
if
(
!
sctp_sk
(
sk
)
->
pf
->
send_verify
(
sctp_sk
(
sk
),
(
addr
)))
return
-
EINVAL
;
return
0
;
...
...
net/sctp/ulpevent.c
View file @
c425b68c
...
...
@@ -628,6 +628,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
if
(
!
event
)
goto
fail_init
;
event
->
iif
=
sctp_chunk_iif
(
chunk
);
/* Note: Not clearing the entire event struct as
* this is just a fragment of the real event. However,
* we still need to do rwnd accounting.
...
...
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