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
4cc42719
Commit
4cc42719
authored
Jan 10, 2003
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Plain Diff
Merge us.ibm.com:/home/sridhar/BK/linux-2.5.56
into us.ibm.com:/home/sridhar/BK/lksctp-2.5.56
parents
efa0596f
ea5d287f
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
351 additions
and
64 deletions
+351
-64
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+5
-2
include/net/sctp/user.h
include/net/sctp/user.h
+17
-0
net/sctp/adler32.c
net/sctp/adler32.c
+15
-1
net/sctp/crc32c.c
net/sctp/crc32c.c
+22
-6
net/sctp/input.c
net/sctp/input.c
+11
-2
net/sctp/output.c
net/sctp/output.c
+3
-3
net/sctp/outqueue.c
net/sctp/outqueue.c
+16
-4
net/sctp/sm_statetable.c
net/sctp/sm_statetable.c
+1
-1
net/sctp/socket.c
net/sctp/socket.c
+216
-30
net/sctp/ulpevent.c
net/sctp/ulpevent.c
+23
-11
net/sctp/ulpqueue.c
net/sctp/ulpqueue.c
+22
-4
No files found.
include/net/sctp/sctp.h
View file @
4cc42719
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-200
2
International Business Machines, Corp.
* Copyright (c) 2001-200
3
International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
...
...
@@ -37,6 +37,7 @@
* Xingang Guo <xingang.guo@intel.com>
* Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -147,7 +148,9 @@ extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg);
/*
* sctp_crc32c.c
*/
extern
__u32
count_crc
(
__u8
*
ptr
,
__u16
count
);
extern
__u32
sctp_start_cksum
(
__u8
*
ptr
,
__u16
count
);
extern
__u32
sctp_update_cksum
(
__u8
*
ptr
,
__u16
count
,
__u32
cksum
);
extern
__u32
sctp_end_cksum
(
__u32
cksum
);
/*
* sctp_input.c
...
...
include/net/sctp/user.h
View file @
4cc42719
...
...
@@ -100,6 +100,14 @@ enum sctp_optname {
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
SCTP_SOCKOPT_PEELOFF
,
/* peel off association. */
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
SCTP_GET_PEER_ADDRS_NUM
,
/* Get number of peer addresss. */
#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM
SCTP_GET_PEER_ADDRS
,
/* Get all peer addresss. */
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
SCTP_GET_LOCAL_ADDRS_NUM
,
/* Get number of local addresss. */
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS
,
/* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
};
...
...
@@ -576,6 +584,15 @@ struct sctp_setstrm_timeout {
__u16
ssto_streamid_end
;
};
/*
* 8.3 8.5 get all peer/local addresses on a socket
* This parameter struct is for getsockopt
*/
struct
sctp_getaddrs
{
sctp_assoc_t
assoc_id
;
int
addr_num
;
struct
sockaddr_storage
*
addrs
;
};
/* These are bit fields for msghdr->msg_flags. See section 5.1. */
/* On user space Linux, these live in <bits/socket.h> as an enum. */
...
...
net/sctp/adler32.c
View file @
4cc42719
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2003 International Business Machines, Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -36,6 +37,7 @@
* Randall Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -122,7 +124,7 @@ unsigned long update_adler32(unsigned long adler,
return
(
s2
<<
16
)
+
s1
;
}
__u32
count_crc
(
__u8
*
ptr
,
__u16
count
)
__u32
sctp_start_cksum
(
__u8
*
ptr
,
__u16
count
)
{
/*
* Update a running Adler-32 checksum with the bytes
...
...
@@ -146,3 +148,15 @@ __u32 count_crc(__u8 *ptr, __u16 count)
return
adler
;
}
__u32
sctp_update_cksum
(
__u8
*
ptr
,
__u16
count
,
__u32
adler
)
{
adler
=
update_adler32
(
adler
,
ptr
,
count
);
return
adler
;
}
__u32
sctp_end_cksum
(
__u32
adler
)
{
return
adler
;
}
net/sctp/crc32c.c
View file @
4cc42719
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001
-2003
International Business Machines, Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -33,6 +33,7 @@
* Written or modified by:
* Dinakaran Joseph
* Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -135,11 +136,10 @@ __u32 crc_c[256] = {
0xBE2DA0A5
,
0x4C4623A6
,
0x5F16D052
,
0xAD7D5351
,
};
__u32
count_crc
(
__u8
*
buffer
,
__u16
length
)
__u32
sctp_start_cksum
(
__u8
*
buffer
,
__u16
length
)
{
__u32
crc32
=
~
(
__u32
)
0
;
__u32
i
,
result
;
__u8
byte0
,
byte1
,
byte2
,
byte3
;
__u32
i
;
/* Optimize this routine to be SCTP specific, knowing how
* to skip the checksum field of the SCTP header.
...
...
@@ -157,6 +157,24 @@ __u32 count_crc(__u8 *buffer, __u16 length)
for
(
i
=
sizeof
(
struct
sctphdr
);
i
<
length
;
i
++
)
CRC32C
(
crc32
,
buffer
[
i
]);
return
crc32
;
}
__u32
sctp_update_cksum
(
__u8
*
buffer
,
__u16
length
,
__u32
crc32
)
{
__u32
i
;
for
(
i
=
0
;
i
<
length
;
i
++
)
CRC32C
(
crc32
,
buffer
[
i
]);
return
crc32
;
}
__u32
sctp_end_cksum
(
__u32
crc32
)
{
__u32
result
;
__u8
byte0
,
byte1
,
byte2
,
byte3
;
result
=
~
crc32
;
/* result now holds the negated polynomial remainder;
...
...
@@ -183,5 +201,3 @@ __u32 count_crc(__u8 *buffer, __u16 length)
byte3
);
return
crc32
;
}
net/sctp/input.c
View file @
4cc42719
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001
-2003
International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
...
...
@@ -72,10 +72,19 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
{
struct
sctphdr
*
sh
;
__u32
cmp
,
val
;
struct
sk_buff
*
list
=
skb_shinfo
(
skb
)
->
frag_list
;
sh
=
(
struct
sctphdr
*
)
skb
->
h
.
raw
;
cmp
=
ntohl
(
sh
->
checksum
);
val
=
count_crc
((
__u8
*
)
sh
,
skb
->
len
);
val
=
sctp_start_cksum
((
__u8
*
)
sh
,
skb_headlen
(
skb
));
for
(;
list
;
list
=
list
->
next
)
val
=
sctp_update_cksum
((
__u8
*
)
list
->
data
,
skb_headlen
(
list
),
val
);
val
=
sctp_end_cksum
(
val
);
if
(
val
!=
cmp
)
{
/* CRC failure, dump it. */
return
-
1
;
...
...
net/sctp/output.c
View file @
4cc42719
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001
-2003
International Business Machines, Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -62,7 +62,6 @@
#include <net/sctp/sm.h>
/* Forward declarations for private helpers. */
__u32
count_crc
(
__u8
*
ptr
,
__u16
count
);
static
void
sctp_packet_reset
(
sctp_packet_t
*
packet
);
static
sctp_xmit_t
sctp_packet_append_data
(
sctp_packet_t
*
packet
,
sctp_chunk_t
*
chunk
);
...
...
@@ -358,7 +357,8 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* Note: Adler-32 is no longer applicable, as has been replaced
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
*/
crc32
=
count_crc
((
__u8
*
)
sh
,
nskb
->
len
);
crc32
=
sctp_start_cksum
((
__u8
*
)
sh
,
nskb
->
len
);
crc32
=
sctp_end_cksum
(
crc32
);
/* 3) Put the resultant value into the checksum field in the
* common header, and leave the rest of the bits unchanged.
...
...
net/sctp/outqueue.c
View file @
4cc42719
...
...
@@ -2,7 +2,7 @@
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-200
2
International Business Machines Corp.
* Copyright (c) 2001-200
3
International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
...
...
@@ -230,7 +230,7 @@ void sctp_retransmit_insert(struct list_head *tlchunk, sctp_outqueue_t *q)
list_add_tail
(
tlchunk
,
&
q
->
retransmit
);
}
}
/* Mark all the eligible packets on a transport for retransmission. */
void
sctp_retransmit_mark
(
sctp_outqueue_t
*
q
,
sctp_transport_t
*
transport
,
__u8
fast_retransmit
)
...
...
@@ -374,6 +374,18 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt,
continue;
}
#endif
/* Make sure that Gap Acked TSNs are not retransmitted. A
* simple approach is just to move such TSNs out of the
* way and into a 'transmitted' queue and skip to the
* next chunk.
*/
if
(
chunk
->
tsn_gap_acked
)
{
list_add_tail
(
lchunk
,
&
transport
->
transmitted
);
lchunk
=
sctp_list_dequeue
(
lqueue
);
continue
;
}
/* Attempt to append this chunk to the packet. */
status
=
(
*
q
->
append_output
)(
pkt
,
chunk
);
...
...
@@ -1028,7 +1040,7 @@ static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack,
}
return
highest_new_tsn
;
}
}
/* This is where we REALLY process a SACK.
*
...
...
@@ -1053,7 +1065,7 @@ int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack)
sack_ctsn
=
ntohl
(
sack
->
cum_tsn_ack
);
/* Get the highest TSN in the sack. */
highest_tsn
=
sack_ctsn
+
highest_tsn
=
sack_ctsn
+
ntohs
(
frags
[
ntohs
(
sack
->
num_gap_ack_blocks
)
-
1
].
gab
.
end
);
if
(
TSN_lt
(
asoc
->
highest_sacked
,
highest_tsn
))
{
...
...
net/sctp/sm_statetable.c
View file @
4cc42719
...
...
@@ -49,7 +49,7 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
sctp_sm_table_entry_t
bug
=
{
s
tatic
s
ctp_sm_table_entry_t
bug
=
{
.
fn
=
sctp_sf_bug
,
.
name
=
"sctp_sf_bug"
};
...
...
net/sctp/socket.c
View file @
4cc42719
/* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-200
2
International Business Machines, Corp.
* Copyright (c) 2001-200
2
Intel Corp.
* Copyright (c) 2001-200
3
International Business Machines, Corp.
* Copyright (c) 2001-200
3
Intel Corp.
* Copyright (c) 2001-2002 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
*
...
...
@@ -47,6 +47,7 @@
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Inaky Perez-Gonzalez <inaky.gonzalez@intel.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -131,7 +132,7 @@ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
static
long
sctp_get_port_local
(
struct
sock
*
,
union
sctp_addr
*
);
/* Verify this is a valid sockaddr. */
static
struct
sctp_af
*
sctp_sockaddr_af
(
struct
sctp_opt
*
opt
,
static
struct
sctp_af
*
sctp_sockaddr_af
(
struct
sctp_opt
*
opt
,
union
sctp_addr
*
addr
,
int
len
)
{
struct
sctp_af
*
af
;
...
...
@@ -754,8 +755,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
*/
if
((
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
!=
sp
->
type
)
&&
msg
->
msg_name
)
{
int
msg_namelen
=
msg
->
msg_namelen
;
err
=
sctp_verify_addr
(
sk
,
(
union
sctp_addr
*
)
msg
->
msg_name
,
err
=
sctp_verify_addr
(
sk
,
(
union
sctp_addr
*
)
msg
->
msg_name
,
msg_namelen
);
if
(
err
)
return
err
;
...
...
@@ -806,7 +807,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
asoc
=
sctp_endpoint_lookup_assoc
(
ep
,
&
to
,
&
transport
);
if
(
!
asoc
)
{
/* If we could not find a matching association on the
* endpoint, make sure that there is no peeled-off
* endpoint, make sure that there is no peeled-off
* association on another socket.
*/
if
(
sctp_endpoint_is_peeled_off
(
ep
,
&
to
))
{
...
...
@@ -1086,23 +1087,30 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
* frag_list. len specifies the total amount of data that needs to be removed.
* when 'len' bytes could be removed from the skb, it returns 0.
* If 'len' exceeds the total skb length, it returns the no. of bytes that
* could not be removed.
*/
* could not be removed.
*/
static
int
sctp_skb_pull
(
struct
sk_buff
*
skb
,
int
len
)
{
struct
sk_buff
*
list
;
int
skb_len
=
skb_headlen
(
skb
);
int
rlen
;
if
(
len
<=
skb
->
len
)
{
if
(
len
<=
skb
_
len
)
{
__skb_pull
(
skb
,
len
);
return
0
;
}
len
-=
skb
->
len
;
__skb_pull
(
skb
,
skb
->
len
);
len
-=
skb
_
len
;
__skb_pull
(
skb
,
skb
_
len
);
for
(
list
=
skb_shinfo
(
skb
)
->
frag_list
;
list
;
list
=
list
->
next
)
{
len
=
sctp_skb_pull
(
list
,
len
);
if
(
!
len
)
rlen
=
sctp_skb_pull
(
list
,
len
);
skb
->
len
-=
(
len
-
rlen
);
skb
->
data_len
-=
(
len
-
rlen
);
if
(
!
rlen
)
return
0
;
len
=
rlen
;
}
return
len
;
...
...
@@ -1130,7 +1138,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
{
sctp_ulpevent_t
*
event
=
NULL
;
sctp_opt_t
*
sp
=
sctp_sk
(
sk
);
struct
sk_buff
*
skb
,
*
list
;
struct
sk_buff
*
skb
;
int
copied
;
int
err
=
0
;
int
skb_len
;
...
...
@@ -1152,10 +1160,8 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
/* Get the total length of the skb including any skb's in the
* frag_list.
*/
*/
skb_len
=
skb
->
len
;
for
(
list
=
skb_shinfo
(
skb
)
->
frag_list
;
list
;
list
=
list
->
next
)
skb_len
+=
list
->
len
;
copied
=
skb_len
;
if
(
copied
>
len
)
...
...
@@ -1190,12 +1196,12 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
/* If skb's length exceeds the user's buffer, update the skb and
* push it back to the receive_queue so that the next call to
* recvmsg() will return the remaining data. Don't set MSG_EOR.
* Otherwise, set MSG_EOR indicating the end of a message.
* Otherwise, set MSG_EOR indicating the end of a message.
*/
if
(
skb_len
>
copied
)
{
msg
->
msg_flags
&=
~
MSG_EOR
;
if
(
flags
&
MSG_PEEK
)
goto
out_free
;
goto
out_free
;
sctp_skb_pull
(
skb
,
copied
);
skb_queue_head
(
&
sk
->
receive_queue
,
skb
);
goto
out
;
...
...
@@ -1463,7 +1469,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
/* connect() cannot be done on a peeled-off socket. */
/* connect() cannot be done on a peeled-off socket. */
if
(
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
==
sp
->
type
)
{
err
=
-
EISCONN
;
goto
out_unlock
;
...
...
@@ -1471,7 +1477,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
err
=
sctp_verify_addr
(
sk
,
(
union
sctp_addr
*
)
uaddr
,
addr_len
);
if
(
err
)
goto
out_unlock
;
goto
out_unlock
;
memcpy
(
&
to
,
uaddr
,
addr_len
);
to
.
v4
.
sin_port
=
ntohs
(
to
.
v4
.
sin_port
);
...
...
@@ -1479,7 +1485,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
asoc
=
sctp_endpoint_lookup_assoc
(
ep
,
&
to
,
&
transport
);
if
(
asoc
)
{
if
(
asoc
->
state
>=
SCTP_STATE_ESTABLISHED
)
err
=
-
EISCONN
;
err
=
-
EISCONN
;
else
err
=
-
EALREADY
;
goto
out_unlock
;
...
...
@@ -1517,7 +1523,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
err
=
sctp_primitive_ASSOCIATE
(
asoc
,
NULL
);
if
(
err
<
0
)
{
sctp_association_free
(
asoc
);
sctp_association_free
(
asoc
);
goto
out_unlock
;
}
...
...
@@ -1915,7 +1921,7 @@ static inline int sctp_getsockopt_get_peer_addr_params(struct sock *sk,
* before this address shall be considered unreachable.
*/
params
.
spp_pathmaxrxt
=
trans
->
error_threshold
;
if
(
copy_to_user
(
optval
,
&
params
,
len
))
return
-
EFAULT
;
*
optlen
=
len
;
...
...
@@ -1932,6 +1938,166 @@ static inline int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval
return
0
;
}
static
inline
int
sctp_getsockopt_get_peer_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_assoc_t
id
;
sctp_association_t
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
if
(
len
!=
sizeof
(
sctp_assoc_t
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
id
,
optval
,
sizeof
(
sctp_assoc_t
)))
return
-
EFAULT
;
/*
* For UDP-style sockets, id specifies the association to query.
*/
asoc
=
sctp_id2assoc
(
sk
,
id
);
if
(
!
asoc
)
return
-
EINVAL
;
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
cnt
++
;
}
if
(
copy_to_user
(
optval
,
&
cnt
,
sizeof
(
int
)))
return
-
EFAULT
;
return
0
;
}
static
inline
int
sctp_getsockopt_get_peer_addrs
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_association_t
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
sctp_transport_t
*
from
;
struct
sockaddr_storage
*
to
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
/*
* For UDP-style sockets, id specifies the association to query.
*/
asoc
=
sctp_id2assoc
(
sk
,
getaddrs
.
assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
to
=
getaddrs
.
addrs
;
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
from
=
list_entry
(
pos
,
sctp_transport_t
,
transports
);
if
(
copy_to_user
(
to
,
&
from
->
ipaddr
,
sizeof
(
from
->
ipaddr
)))
return
-
EFAULT
;
to
++
;
cnt
++
;
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
getaddrs
.
addr_num
=
cnt
;
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
return
0
;
}
static
inline
int
sctp_getsockopt_get_local_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_assoc_t
id
;
sctp_bind_addr_t
*
bp
;
sctp_association_t
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
if
(
len
!=
sizeof
(
sctp_assoc_t
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
id
,
optval
,
sizeof
(
sctp_assoc_t
)))
return
-
EFAULT
;
/*
* For UDP-style sockets, id specifies the association to query.
* If the id field is set to the value '0' then the locally bound
* addresses are returned without regard to any particular
* association.
*/
if
(
0
==
id
)
{
bp
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
bind_addr
;
}
else
{
asoc
=
sctp_id2assoc
(
sk
,
id
);
if
(
!
asoc
)
return
-
EINVAL
;
bp
=
&
asoc
->
base
.
bind_addr
;
}
list_for_each
(
pos
,
&
bp
->
address_list
)
{
cnt
++
;
}
if
(
copy_to_user
(
optval
,
&
cnt
,
sizeof
(
int
)))
return
-
EFAULT
;
return
0
;
}
static
inline
int
sctp_getsockopt_get_local_addrs
(
struct
sock
*
sk
,
int
len
,
char
*
optval
,
int
*
optlen
)
{
sctp_bind_addr_t
*
bp
;
sctp_association_t
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sockaddr_storage_list
*
from
;
struct
sockaddr_storage
*
to
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
/*
* For UDP-style sockets, id specifies the association to query.
* If the id field is set to the value '0' then the locally bound
* addresses are returned without regard to any particular
* association.
*/
if
(
0
==
getaddrs
.
assoc_id
)
{
bp
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
bind_addr
;
}
else
{
asoc
=
sctp_id2assoc
(
sk
,
getaddrs
.
assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
bp
=
&
asoc
->
base
.
bind_addr
;
}
to
=
getaddrs
.
addrs
;
list_for_each
(
pos
,
&
bp
->
address_list
)
{
from
=
list_entry
(
pos
,
struct
sockaddr_storage_list
,
list
);
if
(
copy_to_user
(
to
,
&
from
->
a
,
sizeof
(
from
->
a
)))
return
-
EFAULT
;
to
++
;
cnt
++
;
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
getaddrs
.
addr_num
=
cnt
;
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
return
0
;
}
SCTP_STATIC
int
sctp_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
...
...
@@ -1989,6 +2155,26 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval
=
sctp_getsockopt_initmsg
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDRS_NUM
:
retval
=
sctp_getsockopt_get_peer_addrs_num
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_LOCAL_ADDRS_NUM
:
retval
=
sctp_getsockopt_get_local_addrs_num
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDRS
:
retval
=
sctp_getsockopt_get_peer_addrs
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_LOCAL_ADDRS
:
retval
=
sctp_getsockopt_get_local_addrs
(
sk
,
len
,
optval
,
optlen
);
break
;
default:
retval
=
-
ENOPROTOOPT
;
break
;
...
...
@@ -2029,7 +2215,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
sctp_protocol_t
*
sctp
=
sctp_get_protocol
();
unsigned
short
snum
;
int
ret
;
/* NOTE: Remember to put this back to net order. */
addr
->
v4
.
sin_port
=
ntohs
(
addr
->
v4
.
sin_port
);
snum
=
addr
->
v4
.
sin_port
;
...
...
@@ -2098,7 +2284,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
}
}
if
(
pp
!=
NULL
&&
pp
->
sk
!=
NULL
)
{
/* We had a port hash table hit - there is an
* available port (pp != NULL) and it is being
...
...
@@ -2129,7 +2315,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
if
(
sk_reuse
&&
sk2
->
reuse
)
continue
;
if
(
sctp_bind_addr_match
(
&
ep2
->
base
.
bind_addr
,
addr
,
sctp_sk
(
sk
)))
goto
found
;
...
...
@@ -2187,7 +2373,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
}
/* Assign a 'snum' port to the socket. If snum == 0, an ephemeral
* port is requested.
* port is requested.
*/
static
int
sctp_get_port
(
struct
sock
*
sk
,
unsigned
short
snum
)
{
...
...
@@ -2657,10 +2843,10 @@ static int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, int len)
return
-
EINVAL
;
/* Is this a valid SCTP address? */
if
(
!
af
->
addr_valid
((
union
sctp_addr
*
)
addr
))
if
(
!
af
->
addr_valid
((
union
sctp_addr
*
)
addr
))
return
-
EINVAL
;
return
0
;
return
0
;
}
/* Get the sndbuf space available at the time on the association. */
...
...
net/sctp/ulpevent.c
View file @
4cc42719
...
...
@@ -606,9 +606,9 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(
sctp_ulpevent_t
*
sctp_ulpevent_make_rcvmsg
(
sctp_association_t
*
asoc
,
sctp_chunk_t
*
chunk
,
int
priority
)
{
sctp_ulpevent_t
*
event
;
sctp_ulpevent_t
*
event
,
*
levent
;
struct
sctp_sndrcvinfo
*
info
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
,
*
list
;
size_t
padding
,
len
;
/* Clone the original skb, sharing the data. */
...
...
@@ -647,6 +647,16 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
event
->
malloced
=
1
;
for
(
list
=
skb_shinfo
(
skb
)
->
frag_list
;
list
;
list
=
list
->
next
)
{
sctp_ulpevent_set_owner_r
(
list
,
asoc
);
/* Initialize event with flags 0. */
levent
=
sctp_ulpevent_init
(
event
,
skb
,
0
);
if
(
!
levent
)
goto
fail_init
;
levent
->
malloced
=
1
;
}
info
=
(
struct
sctp_sndrcvinfo
*
)
&
event
->
sndrcvinfo
;
/* Sockets API Extensions for SCTP
...
...
@@ -764,6 +774,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
sctp_ulpevent_t
*
event
;
sctp_chunk_t
*
sack
;
struct
timer_list
*
timer
;
int
skb_len
=
skb_headlen
(
skb
);
/* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as
...
...
@@ -774,18 +785,18 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
event
=
(
sctp_ulpevent_t
*
)
skb
->
cb
;
asoc
=
event
->
asoc
;
if
(
asoc
->
rwnd_over
)
{
if
(
asoc
->
rwnd_over
>=
skb
->
len
)
{
asoc
->
rwnd_over
-=
skb
->
len
;
if
(
asoc
->
rwnd_over
>=
skb
_
len
)
{
asoc
->
rwnd_over
-=
skb
_
len
;
}
else
{
asoc
->
rwnd
+=
(
skb
->
len
-
asoc
->
rwnd_over
);
asoc
->
rwnd
+=
(
skb
_
len
-
asoc
->
rwnd_over
);
asoc
->
rwnd_over
=
0
;
}
}
else
{
asoc
->
rwnd
+=
skb
->
len
;
asoc
->
rwnd
+=
skb
_
len
;
}
SCTP_DEBUG_PRINTK
(
"rwnd increased by %d to (%u, %u) - %u
\n
"
,
skb
->
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
,
asoc
->
a_rwnd
);
skb
_
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
,
asoc
->
a_rwnd
);
/* Send a window update SACK if the rwnd has increased by at least the
* minimum of the association's PMTU and half of the receive buffer.
...
...
@@ -824,6 +835,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
static
void
sctp_ulpevent_set_owner_r
(
struct
sk_buff
*
skb
,
sctp_association_t
*
asoc
)
{
sctp_ulpevent_t
*
event
;
int
skb_len
=
skb_headlen
(
skb
);
/* The current stack structures assume that the rcv buffer is
* per socket. For UDP-style sockets this is not true as
...
...
@@ -840,14 +852,14 @@ static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *a
SCTP_ASSERT
(
asoc
->
rwnd
,
"rwnd zero"
,
return
);
SCTP_ASSERT
(
!
asoc
->
rwnd_over
,
"rwnd_over not zero"
,
return
);
if
(
asoc
->
rwnd
>=
skb
->
len
)
{
asoc
->
rwnd
-=
skb
->
len
;
if
(
asoc
->
rwnd
>=
skb
_
len
)
{
asoc
->
rwnd
-=
skb
_
len
;
}
else
{
asoc
->
rwnd_over
=
skb
->
len
-
asoc
->
rwnd
;
asoc
->
rwnd_over
=
skb
_
len
-
asoc
->
rwnd
;
asoc
->
rwnd
=
0
;
}
SCTP_DEBUG_PRINTK
(
"rwnd decreased by %d to (%u, %u)
\n
"
,
skb
->
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
);
skb
_
len
,
asoc
->
rwnd
,
asoc
->
rwnd_over
);
}
/* A simple destructor to give up the reference to the association. */
...
...
net/sctp/ulpqueue.c
View file @
4cc42719
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-200
2
International Business Machines, Corp.
* Copyright (c) 2001-200
3
International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
...
...
@@ -233,23 +233,41 @@ static inline void sctp_ulpqueue_store_reasm(sctp_ulpqueue_t *ulpq, sctp_ulpeven
/* Helper function to return an event corresponding to the reassembled
* datagram.
* This routine creates a re-assembled skb given the first and last skb's
* as stored in the reassembly queue. The skb's may be non-linear if the sctp
* payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist.
*/
static
inline
sctp_ulpevent_t
*
sctp_make_reassembled_event
(
struct
sk_buff
*
f_frag
,
struct
sk_buff
*
l_frag
)
{
struct
sk_buff
*
pos
;
sctp_ulpevent_t
*
event
;
struct
sk_buff
*
pnext
;
struct
sk_buff
*
pnext
,
*
last
;
struct
sk_buff
*
list
=
skb_shinfo
(
f_frag
)
->
frag_list
;
/* Store the pointer to the 2nd skb */
pos
=
f_frag
->
next
;
/* Set the first fragment's frag_list to point to the 2nd fragment. */
skb_shinfo
(
f_frag
)
->
frag_list
=
pos
;
/* Get the last skb in the f_frag's frag_list if present. */
for
(
last
=
list
;
list
;
last
=
list
,
list
=
list
->
next
);
/* Add the list of remaining fragments to the first fragments
* frag_list.
*/
if
(
last
)
last
->
next
=
pos
;
else
skb_shinfo
(
f_frag
)
->
frag_list
=
pos
;
/* Remove the first fragment from the reassembly queue. */
__skb_unlink
(
f_frag
,
f_frag
->
list
);
do
{
pnext
=
pos
->
next
;
/* Update the len and data_len fields of the first fragment. */
f_frag
->
len
+=
pos
->
len
;
f_frag
->
data_len
+=
pos
->
len
;
/* Remove the fragment from the reassembly queue. */
__skb_unlink
(
pos
,
pos
->
list
);
...
...
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