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
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
Expand all
Hide 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
...
...
@@ -199,28 +199,28 @@ extern void sctp_hash_digest(const char *secret, const int secret_len,
#define sctp_spin_unlock_irqrestore(lock, flags) \
spin_unlock_irqrestore(lock, flags)
#define sctp_local_bh_disable() local_bh_disable()
#define sctp_local_bh_enable() local_bh_enable()
#define sctp_spin_lock(lock) spin_lock(lock)
#define sctp_spin_unlock(lock) spin_unlock(lock)
#define sctp_write_lock(lock) write_lock(lock)
#define sctp_local_bh_enable()
local_bh_enable()
#define sctp_spin_lock(lock)
spin_lock(lock)
#define sctp_spin_unlock(lock)
spin_unlock(lock)
#define sctp_write_lock(lock)
write_lock(lock)
#define sctp_write_unlock(lock) write_unlock(lock)
#define sctp_read_lock(lock) read_lock(lock)
#define sctp_read_unlock(lock) read_unlock(lock)
#define sctp_read_lock(lock)
read_lock(lock)
#define sctp_read_unlock(lock)
read_unlock(lock)
/* sock lock wrappers. */
#define sctp_lock_sock(sk) lock_sock(sk)
#define sctp_release_sock(sk) release_sock(sk)
#define sctp_bh_lock_sock(sk) bh_lock_sock(sk)
#define sctp_bh_unlock_sock(sk) bh_unlock_sock(sk)
#define SCTP_SOCK_SLEEP_PRE(sk) SOCK_SLEEP_PRE(sk)
#define sctp_lock_sock(sk)
lock_sock(sk)
#define sctp_release_sock(sk)
release_sock(sk)
#define sctp_bh_lock_sock(sk)
bh_lock_sock(sk)
#define sctp_bh_unlock_sock(sk)
bh_unlock_sock(sk)
#define SCTP_SOCK_SLEEP_PRE(sk)
SOCK_SLEEP_PRE(sk)
#define SCTP_SOCK_SLEEP_POST(sk) SOCK_SLEEP_POST(sk)
/* SCTP SNMP MIB stats handlers */
DECLARE_SNMP_STAT
(
struct
sctp_mib
,
sctp_statistics
);
#define SCTP_INC_STATS(field)
SNMP_INC_STATS(sctp_statistics, field)
#define SCTP_INC_STATS_BH(field)
SNMP_INC_STATS_BH(sctp_statistics, field)
#define SCTP_INC_STATS_USER(field)
SNMP_INC_STATS_USER(sctp_statistics, field)
#define SCTP_DEC_STATS(field)
SNMP_DEC_STATS(sctp_statistics, field)
#define SCTP_INC_STATS(field)
SNMP_INC_STATS(sctp_statistics, field)
#define SCTP_INC_STATS_BH(field)
SNMP_INC_STATS_BH(sctp_statistics, field)
#define SCTP_INC_STATS_USER(field)
SNMP_INC_STATS_USER(sctp_statistics, field)
#define SCTP_DEC_STATS(field)
SNMP_DEC_STATS(sctp_statistics, field)
/* Determine if this is a valid kernel address. */
static
inline
int
sctp_is_valid_kaddr
(
unsigned
long
addr
)
...
...
@@ -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
This diff is collapsed.
Click to expand it.
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. */
...
...
@@ -61,9 +61,9 @@ static inline struct sk_buff *sctp_event2skb(struct sctp_ulpevent *ev)
/* Retrieve & cast the event sitting inside the skb. */
static
inline
struct
sctp_ulpevent
*
sctp_skb2event
(
struct
sk_buff
*
skb
)
{
return
(
struct
sctp_ulpevent
*
)
skb
->
cb
;
return
(
struct
sctp_ulpevent
*
)
skb
->
cb
;
}
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
flags
,
int
priority
);
struct
sctp_ulpevent
*
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
,
int
flags
);
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
);
...
...
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
);
...
...
@@ -664,14 +662,14 @@ sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc)
{
struct
sctp_chunk
*
chunk
;
/* Send ECNE if needed.
* Not being able to allocate a chunk here is not deadly.
/* Send ECNE if needed.
* Not being able to allocate a chunk here is not deadly.
*/
if
(
asoc
->
need_ecne
)
chunk
=
sctp_make_ecne
(
asoc
,
asoc
->
last_ecne_tsn
);
else
chunk
=
NULL
;
return
chunk
;
}
...
...
@@ -988,9 +986,9 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
case
SCTP_STATE_ESTABLISHED
:
case
SCTP_STATE_SHUTDOWN_PENDING
:
case
SCTP_STATE_SHUTDOWN_RECEIVED
:
if
((
asoc
->
rwnd
>
asoc
->
a_rwnd
)
&&
if
((
asoc
->
rwnd
>
asoc
->
a_rwnd
)
&&
((
asoc
->
rwnd
-
asoc
->
a_rwnd
)
>=
min_t
(
__u32
,
(
asoc
->
base
.
sk
->
rcvbuf
>>
1
),
asoc
->
pmtu
)))
min_t
(
__u32
,
(
asoc
->
base
.
sk
->
rcvbuf
>>
1
),
asoc
->
pmtu
)))
return
1
;
break
;
default:
...
...
@@ -1057,14 +1055,14 @@ void sctp_assoc_rwnd_decrease(sctp_association_t *asoc, int len)
asoc
->
rwnd
=
0
;
}
SCTP_DEBUG_PRINTK
(
"%s: asoc %p rwnd decreased by %d to (%u, %u)
\n
"
,
__FUNCTION__
,
asoc
,
len
,
asoc
->
rwnd
,
__FUNCTION__
,
asoc
,
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
);
}
/* 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
);
fl
.
oif
=
sk
->
bound_dev_if
;
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
;
...
...
@@ -1162,7 +1174,7 @@ int sctp_datachunks_from_user(sctp_association_t *asoc,
msg_len
-=
first_len
;
whole
=
1
;
}
}
}
/* How many full sized? How many bytes leftover? */
whole
+=
msg_len
/
max
;
...
...
@@ -1198,7 +1210,7 @@ int sctp_datachunks_from_user(sctp_association_t *asoc,
__skb_queue_tail
(
chunks
,
(
struct
sk_buff
*
)
chunk
);
/* The first chunk, the first chunk was likely short
/* The first chunk, the first chunk was likely short
* to allow bundling, so reset to full size.
*/
if
(
0
==
i
)
...
...
@@ -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
...
...
@@ -249,8 +249,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep,
/* The call, sctp_process_init(), can fail on memory allocation. */
if
(
!
sctp_process_init
(
new_asoc
,
chunk
->
chunk_hdr
->
type
,
sctp_source
(
chunk
),
(
sctp_init_chunk_t
*
)
chunk
->
chunk_hdr
,
sctp_source
(
chunk
),
(
sctp_init_chunk_t
*
)
chunk
->
chunk_hdr
,
GFP_ATOMIC
))
goto
nomem_init
;
...
...
@@ -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