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
cabbb4de
Commit
cabbb4de
authored
Jan 09, 2005
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-lksctp.bkbits.net/lksctp-2.5.work
into nuts.davemloft.net:/disk1/BK/net-2.6
parents
c7e670c0
a271fa8b
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1030 additions
and
614 deletions
+1030
-614
include/linux/sctp.h
include/linux/sctp.h
+1
-1
include/net/sctp/command.h
include/net/sctp/command.h
+0
-13
include/net/sctp/constants.h
include/net/sctp/constants.h
+3
-5
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+9
-15
include/net/sctp/sm.h
include/net/sctp/sm.h
+8
-61
include/net/sctp/structs.h
include/net/sctp/structs.h
+9
-28
include/net/sctp/tsnmap.h
include/net/sctp/tsnmap.h
+0
-16
include/net/sctp/ulpevent.h
include/net/sctp/ulpevent.h
+0
-2
include/net/sctp/ulpqueue.h
include/net/sctp/ulpqueue.h
+0
-1
net/sctp/associola.c
net/sctp/associola.c
+32
-51
net/sctp/bind_addr.c
net/sctp/bind_addr.c
+0
-17
net/sctp/chunk.c
net/sctp/chunk.c
+4
-4
net/sctp/command.c
net/sctp/command.c
+0
-23
net/sctp/debug.c
net/sctp/debug.c
+2
-18
net/sctp/endpointola.c
net/sctp/endpointola.c
+28
-28
net/sctp/input.c
net/sctp/input.c
+76
-26
net/sctp/inqueue.c
net/sctp/inqueue.c
+24
-15
net/sctp/ipv6.c
net/sctp/ipv6.c
+17
-9
net/sctp/objcnt.c
net/sctp/objcnt.c
+1
-1
net/sctp/outqueue.c
net/sctp/outqueue.c
+1
-14
net/sctp/proc.c
net/sctp/proc.c
+1
-1
net/sctp/protocol.c
net/sctp/protocol.c
+17
-17
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+104
-55
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+45
-23
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+426
-49
net/sctp/sm_statetable.c
net/sctp/sm_statetable.c
+42
-8
net/sctp/socket.c
net/sctp/socket.c
+122
-20
net/sctp/ssnmap.c
net/sctp/ssnmap.c
+5
-2
net/sctp/transport.c
net/sctp/transport.c
+38
-29
net/sctp/tsnmap.c
net/sctp/tsnmap.c
+5
-34
net/sctp/ulpevent.c
net/sctp/ulpevent.c
+9
-8
net/sctp/ulpqueue.c
net/sctp/ulpqueue.c
+1
-20
No files found.
include/linux/sctp.h
View file @
cabbb4de
...
...
@@ -364,7 +364,7 @@ typedef struct sctp_heartbeat_chunk {
*/
typedef
struct
sctp_abort_chunk
{
sctp_chunkhdr_t
uh
;
}
__attribute__
((
packed
))
sctp_abort_chunk
t
_t
;
}
__attribute__
((
packed
))
sctp_abort_chunk_t
;
/* For the graceful shutdown we must carry the tag (in common header)
...
...
include/net/sctp/command.h
View file @
cabbb4de
...
...
@@ -189,11 +189,6 @@ typedef struct {
}
sctp_cmd_seq_t
;
/* Create a new sctp_command_sequence.
* Return NULL if creating a new sequence fails.
*/
sctp_cmd_seq_t
*
sctp_new_cmd_seq
(
int
gfp
);
/* Initialize a block of memory as a command sequence.
* Return 0 if the initialization fails.
*/
...
...
@@ -207,18 +202,10 @@ int sctp_init_cmd_seq(sctp_cmd_seq_t *seq);
*/
int
sctp_add_cmd
(
sctp_cmd_seq_t
*
seq
,
sctp_verb_t
verb
,
sctp_arg_t
obj
);
/* Rewind an sctp_cmd_seq_t to iterate from the start.
* Return 0 if the rewind fails.
*/
int
sctp_rewind_sequence
(
sctp_cmd_seq_t
*
seq
);
/* Return the next command structure in an sctp_cmd_seq.
* Return NULL at the end of the sequence.
*/
sctp_cmd_t
*
sctp_next_cmd
(
sctp_cmd_seq_t
*
seq
);
/* Dispose of a command sequence. */
void
sctp_free_cmd_seq
(
sctp_cmd_seq_t
*
seq
);
#endif
/* __net_sctp_command_h__ */
include/net/sctp/constants.h
View file @
cabbb4de
...
...
@@ -105,9 +105,10 @@ typedef enum {
typedef
enum
{
SCTP_EVENT_NO_PENDING_TSN
=
0
,
SCTP_EVENT_ICMP_PROTO_UNREACH
,
}
sctp_event_other_t
;
#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_
NO_PENDING_TSN
#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_
ICMP_PROTO_UNREACH
#define SCTP_NUM_OTHER_TYPES (SCTP_EVENT_OTHER_MAX + 1)
/* These are primitive requests from the ULP. */
...
...
@@ -155,10 +156,6 @@ SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, sctp_event_primitive_t, primitive)
- (unsigned long)(c->chunk_hdr)\
- sizeof(sctp_data_chunk_t)))
/* This is a table of printable names of sctp_param_t's. */
extern
const
char
*
sctp_param_tbl
[];
#define SCTP_MAX_ERROR_CAUSE SCTP_ERROR_NONEXIST_IP
#define SCTP_NUM_ERROR_CAUSE 10
...
...
@@ -179,6 +176,7 @@ typedef enum {
SCTP_IERROR_IGNORE_TSN
,
SCTP_IERROR_NO_DATA
,
SCTP_IERROR_BAD_STREAM
,
SCTP_IERROR_BAD_PORTS
,
}
sctp_ierror_t
;
...
...
include/net/sctp/sctp.h
View file @
cabbb4de
...
...
@@ -162,17 +162,9 @@ __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
int
sctp_rcv
(
struct
sk_buff
*
skb
);
void
sctp_v4_err
(
struct
sk_buff
*
skb
,
u32
info
);
void
sctp_hash_established
(
struct
sctp_association
*
);
void
__sctp_hash_established
(
struct
sctp_association
*
);
void
sctp_unhash_established
(
struct
sctp_association
*
);
void
__sctp_unhash_established
(
struct
sctp_association
*
);
void
sctp_hash_endpoint
(
struct
sctp_endpoint
*
);
void
__sctp_hash_endpoint
(
struct
sctp_endpoint
*
);
void
sctp_unhash_endpoint
(
struct
sctp_endpoint
*
);
void
__sctp_unhash_endpoint
(
struct
sctp_endpoint
*
);
struct
sctp_association
*
__sctp_lookup_association
(
const
union
sctp_addr
*
,
const
union
sctp_addr
*
,
struct
sctp_transport
**
);
struct
sock
*
sctp_err_lookup
(
int
family
,
struct
sk_buff
*
,
struct
sctphdr
*
,
struct
sctp_endpoint
**
,
struct
sctp_association
**
,
...
...
@@ -181,6 +173,10 @@ void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct
sctp_association
*
);
void
sctp_icmp_frag_needed
(
struct
sock
*
,
struct
sctp_association
*
,
struct
sctp_transport
*
t
,
__u32
pmtu
);
void
sctp_icmp_proto_unreachable
(
struct
sock
*
sk
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
t
);
/*
* Section: Macros, externs, and inlines
...
...
@@ -310,8 +306,6 @@ static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int
int
sctp_v6_init
(
void
);
void
sctp_v6_exit
(
void
);
void
sctp_v6_err
(
struct
sk_buff
*
skb
,
struct
inet6_skb_parm
*
opt
,
int
type
,
int
code
,
int
offset
,
__u32
info
);
#else
/* #ifdef defined(CONFIG_IPV6) */
...
...
@@ -455,7 +449,8 @@ _sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)),
#define _sctp_walk_params(pos, chunk, end, member)\
for (pos.v = chunk->member;\
pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\
pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \
pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\
ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
pos.v += WORD_ROUND(ntohs(pos.p->length)))
#define sctp_walk_errors(err, chunk_hdr)\
...
...
@@ -465,10 +460,9 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))
for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
sizeof(sctp_chunkhdr_t));\
(void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\
(void *)err <= (void *)chunk_hdr + end - \
WORD_ROUND(ntohs(err->length));\
err = (sctp_errhdr_t *)((void *)err + \
WORD_ROUND(ntohs(err->length))))
(void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length)) &&\
ntohs(err->length) >= sizeof(sctp_errhdr_t); \
err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))
#define sctp_walk_fwdtsn(pos, chunk)\
_sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - sizeof(struct sctp_fwdtsn_chunk))
...
...
include/net/sctp/sm.h
View file @
cabbb4de
...
...
@@ -128,9 +128,9 @@ sctp_state_fn_t sctp_sf_do_9_2_shutdown;
sctp_state_fn_t
sctp_sf_do_ecn_cwr
;
sctp_state_fn_t
sctp_sf_do_ecne
;
sctp_state_fn_t
sctp_sf_ootb
;
sctp_state_fn_t
sctp_sf_shut_8_4_5
;
sctp_state_fn_t
sctp_sf_pdiscard
;
sctp_state_fn_t
sctp_sf_violation
;
sctp_state_fn_t
sctp_sf_violation_chunklen
;
sctp_state_fn_t
sctp_sf_discard_chunk
;
sctp_state_fn_t
sctp_sf_do_5_2_1_siminit
;
sctp_state_fn_t
sctp_sf_do_5_2_2_dupinit
;
...
...
@@ -138,7 +138,6 @@ sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t
sctp_sf_unk_chunk
;
sctp_state_fn_t
sctp_sf_do_8_5_1_E_sa
;
sctp_state_fn_t
sctp_sf_cookie_echoed_err
;
sctp_state_fn_t
sctp_sf_do_5_2_6_stale
;
sctp_state_fn_t
sctp_sf_do_asconf
;
sctp_state_fn_t
sctp_sf_do_asconf_ack
;
sctp_state_fn_t
sctp_sf_do_9_2_reshutack
;
...
...
@@ -167,6 +166,7 @@ sctp_state_fn_t sctp_sf_do_prm_asconf;
sctp_state_fn_t
sctp_sf_do_9_2_start_shutdown
;
sctp_state_fn_t
sctp_sf_do_9_2_shutdown_ack
;
sctp_state_fn_t
sctp_sf_ignore_other
;
sctp_state_fn_t
sctp_sf_cookie_wait_icmp_abort
;
/* Prototypes for timeout event state functions. */
sctp_state_fn_t
sctp_sf_do_6_3_3_rtx
;
...
...
@@ -200,19 +200,10 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
struct
sctp_chunk
*
sctp_make_cwr
(
const
struct
sctp_association
*
,
const
__u32
lowest_tsn
,
const
struct
sctp_chunk
*
);
struct
sctp_chunk
*
sctp_make_datafrag
(
struct
sctp_association
*
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
len
,
const
__u8
*
data
,
__u8
flags
,
__u16
ssn
);
struct
sctp_chunk
*
sctp_make_datafrag_empty
(
struct
sctp_association
*
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
len
,
const
__u8
flags
,
__u16
ssn
);
struct
sctp_chunk
*
sctp_make_data
(
struct
sctp_association
*
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
len
,
const
__u8
*
data
);
struct
sctp_chunk
*
sctp_make_data_empty
(
struct
sctp_association
*
,
const
struct
sctp_sndrcvinfo
*
,
int
len
);
struct
sctp_chunk
*
sctp_make_ecne
(
const
struct
sctp_association
*
,
const
__u32
);
struct
sctp_chunk
*
sctp_make_sack
(
const
struct
sctp_association
*
);
...
...
@@ -232,6 +223,10 @@ struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
struct
sctp_chunk
*
sctp_make_abort_user
(
const
struct
sctp_association
*
,
const
struct
sctp_chunk
*
,
const
struct
msghdr
*
);
struct
sctp_chunk
*
sctp_make_abort_violation
(
const
struct
sctp_association
*
,
const
struct
sctp_chunk
*
,
const
__u8
*
,
const
size_t
);
struct
sctp_chunk
*
sctp_make_heartbeat
(
const
struct
sctp_association
*
,
const
struct
sctp_transport
*
,
const
void
*
payload
,
...
...
@@ -246,17 +241,12 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
const
void
*
payload
,
size_t
paylen
);
struct
sctp_chunk
*
sctp_make_asconf
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
,
int
vparam_len
);
struct
sctp_chunk
*
sctp_make_asconf_update_ip
(
struct
sctp_association
*
,
union
sctp_addr
*
,
struct
sockaddr
*
,
int
,
__u16
);
struct
sctp_chunk
*
sctp_make_asconf_set_prim
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
);
struct
sctp_chunk
*
sctp_make_asconf_ack
(
const
struct
sctp_association
*
asoc
,
__u32
serial
,
int
vparam_len
);
struct
sctp_chunk
*
sctp_process_asconf
(
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
asconf
);
int
sctp_process_asconf_ack
(
struct
sctp_association
*
asoc
,
...
...
@@ -268,6 +258,8 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
void
sctp_chunk_assign_tsn
(
struct
sctp_chunk
*
);
void
sctp_chunk_assign_ssn
(
struct
sctp_chunk
*
);
void
sctp_stop_t1_and_abort
(
sctp_cmd_seq_t
*
commands
,
__u16
error
);
/* Prototypes for statetable processing. */
int
sctp_do_sm
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
...
...
@@ -277,71 +269,26 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
void
*
event_arg
,
int
gfp
);
int
sctp_side_effects
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
);
/* 2nd level prototypes */
int
sctp_cmd_interpreter
(
sctp_event_t
,
sctp_subtype_t
,
sctp_state_t
,
struct
sctp_endpoint
*
,
struct
sctp_association
*
,
void
*
event_arg
,
sctp_disposition_t
,
sctp_cmd_seq_t
*
retval
,
int
gfp
);
int
sctp_gen_sack
(
struct
sctp_association
*
,
int
force
,
sctp_cmd_seq_t
*
);
void
sctp_generate_t3_rtx_event
(
unsigned
long
peer
);
void
sctp_generate_heartbeat_event
(
unsigned
long
peer
);
sctp_sackhdr_t
*
sctp_sm_pull_sack
(
struct
sctp_chunk
*
);
struct
sctp_packet
*
sctp_abort_pkt_new
(
const
struct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
struct
sctp_chunk
*
chunk
,
const
void
*
payload
,
size_t
paylen
);
struct
sctp_packet
*
sctp_ootb_pkt_new
(
const
struct
sctp_association
*
,
const
struct
sctp_chunk
*
);
void
sctp_ootb_pkt_free
(
struct
sctp_packet
*
);
struct
sctp_cookie_param
*
sctp_pack_cookie
(
const
struct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
const
struct
sctp_chunk
*
,
int
*
cookie_len
,
const
__u8
*
,
int
addrs_len
);
struct
sctp_association
*
sctp_unpack_cookie
(
const
struct
sctp_endpoint
*
,
const
struct
sctp_association
*
,
struct
sctp_chunk
*
,
int
gfp
,
int
*
err
,
struct
sctp_chunk
**
err_chk_p
);
int
sctp_addip_addr_config
(
struct
sctp_association
*
,
sctp_param_t
,
struct
sockaddr_storage
*
,
int
);
void
sctp_send_stale_cookie_err
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
,
struct
sctp_chunk
*
err_chunk
);
int
sctp_eat_data
(
const
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
);
/* 3rd level prototypes */
__u32
sctp_generate_tag
(
const
struct
sctp_endpoint
*
);
__u32
sctp_generate_tsn
(
const
struct
sctp_endpoint
*
);
/* Extern declarations for major data structures. */
const
sctp_sm_table_entry_t
*
sctp_chunk_event_lookup
(
sctp_cid_t
,
sctp_state_t
);
extern
const
sctp_sm_table_entry_t
primitive_event_table
[
SCTP_NUM_PRIMITIVE_TYPES
][
SCTP_STATE_NUM_STATES
];
extern
const
sctp_sm_table_entry_t
other_event_table
[
SCTP_NUM_OTHER_TYPES
][
SCTP_STATE_NUM_STATES
];
extern
const
sctp_sm_table_entry_t
timeout_event_table
[
SCTP_NUM_TIMEOUT_TYPES
][
SCTP_STATE_NUM_STATES
];
extern
sctp_timer_event_t
*
sctp_timer_events
[
SCTP_NUM_TIMEOUT_TYPES
];
/* These are some handy utility macros... */
/* Get the size of a DATA chunk payload. */
static
inline
__u16
sctp_data_size
(
struct
sctp_chunk
*
chunk
)
...
...
include/net/sctp/structs.h
View file @
cabbb4de
...
...
@@ -322,10 +322,19 @@ struct sctp_cookie {
/* This holds the originating address of the INIT packet. */
union
sctp_addr
peer_addr
;
/* IG Section 2.35.3
* Include the source port of the INIT-ACK
*/
__u16
my_port
;
__u8
prsctp_capable
;
/* Padding for future use */
__u8
padding
;
__u32
adaption_ind
;
/* This is a shim for my peer's INIT packet, followed by
* a copy of the raw address list of the association.
* The length of the raw address list is saved in the
...
...
@@ -406,7 +415,6 @@ struct sctp_ssnmap {
int
malloced
;
};
struct
sctp_ssnmap
*
sctp_ssnmap_init
(
struct
sctp_ssnmap
*
,
__u16
,
__u16
);
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
);
...
...
@@ -538,12 +546,9 @@ struct sctp_datamsg {
struct
sctp_datamsg
*
sctp_datamsg_from_user
(
struct
sctp_association
*
,
struct
sctp_sndrcvinfo
*
,
struct
msghdr
*
,
int
len
);
struct
sctp_datamsg
*
sctp_datamsg_new
(
int
gfp
);
void
sctp_datamsg_put
(
struct
sctp_datamsg
*
);
void
sctp_datamsg_hold
(
struct
sctp_datamsg
*
);
void
sctp_datamsg_free
(
struct
sctp_datamsg
*
);
void
sctp_datamsg_track
(
struct
sctp_chunk
*
);
void
sctp_datamsg_assign
(
struct
sctp_datamsg
*
,
struct
sctp_chunk
*
);
void
sctp_chunk_fail
(
struct
sctp_chunk
*
,
int
error
);
int
sctp_chunk_abandoned
(
struct
sctp_chunk
*
);
...
...
@@ -651,8 +656,6 @@ void sctp_chunk_hold(struct sctp_chunk *);
void
sctp_chunk_put
(
struct
sctp_chunk
*
);
int
sctp_user_addto_chunk
(
struct
sctp_chunk
*
chunk
,
int
off
,
int
len
,
struct
iovec
*
data
);
struct
sctp_chunk
*
sctp_make_chunk
(
const
struct
sctp_association
*
,
__u8
type
,
__u8
flags
,
int
size
);
void
sctp_chunk_free
(
struct
sctp_chunk
*
);
void
*
sctp_addto_chunk
(
struct
sctp_chunk
*
,
int
len
,
const
void
*
data
);
struct
sctp_chunk
*
sctp_chunkify
(
struct
sk_buff
*
,
...
...
@@ -853,12 +856,6 @@ struct sctp_transport {
/* Error count : The current error count for this destination. */
unsigned
short
error_count
;
/* Error : Current error threshold for this destination
* Threshold : i.e. what value marks the destination down if
* : errorCount reaches this value.
*/
unsigned
short
error_threshold
;
/* This is the max_retrans value for the transport and will
* be initialized to proto.max_retrans.path. This can be changed
* using SCTP_SET_PEER_ADDR_PARAMS socket option.
...
...
@@ -922,15 +919,12 @@ 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
*
,
struct
sctp_association
*
);
void
sctp_transport_route
(
struct
sctp_transport
*
,
union
sctp_addr
*
,
struct
sctp_opt
*
);
void
sctp_transport_pmtu
(
struct
sctp_transport
*
);
void
sctp_transport_free
(
struct
sctp_transport
*
);
void
sctp_transport_destroy
(
struct
sctp_transport
*
);
void
sctp_transport_reset_timers
(
struct
sctp_transport
*
);
void
sctp_transport_hold
(
struct
sctp_transport
*
);
void
sctp_transport_put
(
struct
sctp_transport
*
);
...
...
@@ -961,7 +955,6 @@ struct sctp_inq {
int
malloced
;
/* Is this structure kfree()able? */
};
struct
sctp_inq
*
sctp_inq_new
(
void
);
void
sctp_inq_init
(
struct
sctp_inq
*
);
void
sctp_inq_free
(
struct
sctp_inq
*
);
void
sctp_inq_push
(
struct
sctp_inq
*
,
struct
sctp_chunk
*
packet
);
...
...
@@ -1029,7 +1022,6 @@ struct sctp_outq {
char
malloced
;
};
struct
sctp_outq
*
sctp_outq_new
(
struct
sctp_association
*
);
void
sctp_outq_init
(
struct
sctp_association
*
,
struct
sctp_outq
*
);
void
sctp_outq_teardown
(
struct
sctp_outq
*
);
void
sctp_outq_free
(
struct
sctp_outq
*
);
...
...
@@ -1070,7 +1062,6 @@ struct sctp_bind_addr {
int
malloced
;
/* Are we kfree()able? */
};
struct
sctp_bind_addr
*
sctp_bind_addr_new
(
int
gfp_mask
);
void
sctp_bind_addr_init
(
struct
sctp_bind_addr
*
,
__u16
port
);
void
sctp_bind_addr_free
(
struct
sctp_bind_addr
*
);
int
sctp_bind_addr_copy
(
struct
sctp_bind_addr
*
dest
,
...
...
@@ -1220,8 +1211,6 @@ static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base)
/* These are function signatures for manipulating endpoints. */
struct
sctp_endpoint
*
sctp_endpoint_new
(
struct
sock
*
,
int
);
struct
sctp_endpoint
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
,
struct
sock
*
,
int
gfp
);
void
sctp_endpoint_free
(
struct
sctp_endpoint
*
);
void
sctp_endpoint_put
(
struct
sctp_endpoint
*
);
void
sctp_endpoint_hold
(
struct
sctp_endpoint
*
);
...
...
@@ -1243,8 +1232,6 @@ int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
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
struct
sctp_endpoint
*
);
__u32
sctp_generate_tsn
(
const
struct
sctp_endpoint
*
);
...
...
@@ -1690,10 +1677,6 @@ static inline struct sctp_association *sctp_assoc(struct sctp_ep_common *base)
struct
sctp_association
*
sctp_association_new
(
const
struct
sctp_endpoint
*
,
const
struct
sock
*
,
sctp_scope_t
scope
,
int
gfp
);
struct
sctp_association
*
sctp_association_init
(
struct
sctp_association
*
,
const
struct
sctp_endpoint
*
,
const
struct
sock
*
,
sctp_scope_t
scope
,
int
gfp
);
void
sctp_association_free
(
struct
sctp_association
*
);
void
sctp_association_put
(
struct
sctp_association
*
);
void
sctp_association_hold
(
struct
sctp_association
*
);
...
...
@@ -1722,7 +1705,6 @@ 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
);
void
sctp_assoc_sync_pmtu
(
struct
sctp_association
*
);
void
sctp_assoc_rwnd_increase
(
struct
sctp_association
*
,
unsigned
);
...
...
@@ -1736,7 +1718,6 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
int
sctp_cmp_addr_exact
(
const
union
sctp_addr
*
ss1
,
const
union
sctp_addr
*
ss2
);
struct
sctp_chunk
*
sctp_get_ecne_prepend
(
struct
sctp_association
*
asoc
);
struct
sctp_chunk
*
sctp_get_no_prepend
(
struct
sctp_association
*
asoc
);
/* A convenience structure to parse out SCTP specific CMSGs. */
typedef
struct
sctp_cmsgs
{
...
...
include/net/sctp/tsnmap.h
View file @
cabbb4de
...
...
@@ -120,12 +120,6 @@ struct sctp_tsnmap_iter {
__u32
start
;
};
/* Create a new tsnmap. */
struct
sctp_tsnmap
*
sctp_tsnmap_new
(
__u16
len
,
__u32
init_tsn
,
int
gfp
);
/* Dispose of a tsnmap. */
void
sctp_tsnmap_free
(
struct
sctp_tsnmap
*
);
/* This macro assists in creation of external storage for variable length
* internal buffers. We double allocate so the overflow map works.
*/
...
...
@@ -210,14 +204,4 @@ void sctp_tsnmap_renege(struct sctp_tsnmap *, __u32 tsn);
/* Is there a gap in the TSN map? */
int
sctp_tsnmap_has_gap
(
const
struct
sctp_tsnmap
*
);
/* Initialize a gap ack block interator from user-provided memory. */
void
sctp_tsnmap_iter_init
(
const
struct
sctp_tsnmap
*
,
struct
sctp_tsnmap_iter
*
);
/* Get the next gap ack blocks. We return 0 if there are no more
* gap ack blocks.
*/
int
sctp_tsnmap_next_gap_ack
(
const
struct
sctp_tsnmap
*
,
struct
sctp_tsnmap_iter
*
,
__u16
*
start
,
__u16
*
end
);
#endif
/* __sctp_tsnmap_h__ */
include/net/sctp/ulpevent.h
View file @
cabbb4de
...
...
@@ -77,8 +77,6 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
return
(
struct
sctp_ulpevent
*
)
skb
->
cb
;
}
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
flags
,
int
gfp
);
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
,
int
flags
);
void
sctp_ulpevent_free
(
struct
sctp_ulpevent
*
);
int
sctp_ulpevent_is_notification
(
const
struct
sctp_ulpevent
*
);
void
sctp_queue_purge_ulpevents
(
struct
sk_buff_head
*
list
);
...
...
include/net/sctp/ulpqueue.h
View file @
cabbb4de
...
...
@@ -57,7 +57,6 @@ struct sctp_ulpq {
};
/* Prototypes. */
struct
sctp_ulpq
*
sctp_ulpq_new
(
struct
sctp_association
*
asoc
,
int
gfp
);
struct
sctp_ulpq
*
sctp_ulpq_init
(
struct
sctp_ulpq
*
,
struct
sctp_association
*
);
void
sctp_ulpq_free
(
struct
sctp_ulpq
*
);
...
...
net/sctp/associola.c
View file @
cabbb4de
...
...
@@ -66,33 +66,8 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc);
/* 1st Level Abstractions. */
/* Allocate and initialize a new association */
struct
sctp_association
*
sctp_association_new
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sock
*
sk
,
sctp_scope_t
scope
,
int
gfp
)
{
struct
sctp_association
*
asoc
;
asoc
=
t_new
(
struct
sctp_association
,
gfp
);
if
(
!
asoc
)
goto
fail
;
if
(
!
sctp_association_init
(
asoc
,
ep
,
sk
,
scope
,
gfp
))
goto
fail_init
;
asoc
->
base
.
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
assoc
);
return
asoc
;
fail_init:
kfree
(
asoc
);
fail:
return
NULL
;
}
/* Initialize a new association from provided memory. */
struct
sctp_association
*
sctp_association_init
(
struct
sctp_association
*
asoc
,
st
atic
st
ruct
sctp_association
*
sctp_association_init
(
struct
sctp_association
*
asoc
,
const
struct
sctp_endpoint
*
ep
,
const
struct
sock
*
sk
,
sctp_scope_t
scope
,
...
...
@@ -204,6 +179,7 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc
->
c
.
peer_vtag
=
0
;
asoc
->
c
.
my_ttag
=
0
;
asoc
->
c
.
peer_ttag
=
0
;
asoc
->
c
.
my_port
=
ep
->
base
.
bind_addr
.
port
;
asoc
->
c
.
initial_tsn
=
sctp_generate_tsn
(
ep
);
...
...
@@ -296,6 +272,31 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
return
NULL
;
}
/* Allocate and initialize a new association */
struct
sctp_association
*
sctp_association_new
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sock
*
sk
,
sctp_scope_t
scope
,
int
gfp
)
{
struct
sctp_association
*
asoc
;
asoc
=
t_new
(
struct
sctp_association
,
gfp
);
if
(
!
asoc
)
goto
fail
;
if
(
!
sctp_association_init
(
asoc
,
ep
,
sk
,
scope
,
gfp
))
goto
fail_init
;
asoc
->
base
.
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
assoc
);
return
asoc
;
fail_init:
kfree
(
asoc
);
fail:
return
NULL
;
}
/* Free this association if possible. There may still be users, so
* the actual deallocation may be delayed.
*/
...
...
@@ -500,7 +501,6 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer
->
partial_bytes_acked
=
0
;
peer
->
flight_size
=
0
;
peer
->
error_threshold
=
peer
->
max_retrans
;
/* By default, enable heartbeat for peer address. */
peer
->
hb_allowed
=
1
;
...
...
@@ -511,7 +511,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer
->
hb_interval
=
msecs_to_jiffies
(
sp
->
paddrparam
.
spp_hbinterval
);
/* Set the path max_retrans. */
peer
->
max_retrans
=
asoc
->
max_retrans
;
peer
->
max_retrans
=
sp
->
paddrparam
.
spp_pathmaxrxt
;
/* Set the transport's RTO.initial value */
peer
->
rto
=
asoc
->
rto_initial
;
...
...
@@ -714,18 +714,6 @@ __u32 sctp_association_get_next_tsn(struct sctp_association *asoc)
return
retval
;
}
/* Allocate 'num' TSNs by incrementing the association's TSN by num. */
__u32
sctp_association_get_tsn_block
(
struct
sctp_association
*
asoc
,
int
num
)
{
__u32
retval
=
asoc
->
next_tsn
;
asoc
->
next_tsn
+=
num
;
asoc
->
unack_data
+=
num
;
return
retval
;
}
/* Compare two addresses to see if they match. Wildcard addresses
* only match themselves.
*/
...
...
@@ -760,14 +748,6 @@ struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc)
return
chunk
;
}
/* Use this function for the packet prepend callback when no ECNE
* packet is desired (e.g. some packets don't like to be bundled).
*/
struct
sctp_chunk
*
sctp_get_no_prepend
(
struct
sctp_association
*
asoc
)
{
return
NULL
;
}
/*
* Find which transport this TSN was sent on.
*/
...
...
@@ -861,7 +841,8 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
struct
sctp_chunk
*
chunk
;
struct
sock
*
sk
;
struct
sctp_inq
*
inqueue
;
int
state
,
subtype
;
int
state
;
sctp_subtype_t
subtype
;
int
error
=
0
;
/* The association should be held so we should be safe. */
...
...
@@ -872,7 +853,7 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
sctp_association_hold
(
asoc
);
while
(
NULL
!=
(
chunk
=
sctp_inq_pop
(
inqueue
)))
{
state
=
asoc
->
state
;
subtype
=
chunk
->
chunk_hdr
->
type
;
subtype
=
SCTP_ST_CHUNK
(
chunk
->
chunk_hdr
->
type
)
;
/* Remember where the last DATA chunk came from so we
* know where to send the SACK.
...
...
@@ -886,7 +867,7 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
chunk
->
transport
->
last_time_heard
=
jiffies
;
/* Run through the state machine. */
error
=
sctp_do_sm
(
SCTP_EVENT_T_CHUNK
,
SCTP_ST_CHUNK
(
subtype
)
,
error
=
sctp_do_sm
(
SCTP_EVENT_T_CHUNK
,
subtype
,
state
,
ep
,
asoc
,
chunk
,
GFP_ATOMIC
);
/* Check to see if the association is freed in response to
...
...
net/sctp/bind_addr.c
View file @
cabbb4de
...
...
@@ -104,23 +104,6 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
return
error
;
}
/* Create a new SCTP_bind_addr from nothing. */
struct
sctp_bind_addr
*
sctp_bind_addr_new
(
int
gfp
)
{
struct
sctp_bind_addr
*
retval
;
retval
=
t_new
(
struct
sctp_bind_addr
,
gfp
);
if
(
!
retval
)
goto
nomem
;
sctp_bind_addr_init
(
retval
,
0
);
retval
->
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
bind_addr
);
nomem:
return
retval
;
}
/* Initialize the SCTP_bind_addr structure for either an endpoint or
* an association.
*/
...
...
net/sctp/chunk.c
View file @
cabbb4de
...
...
@@ -51,7 +51,7 @@
*/
/* Initialize datamsg from memory. */
void
sctp_datamsg_init
(
struct
sctp_datamsg
*
msg
)
static
void
sctp_datamsg_init
(
struct
sctp_datamsg
*
msg
)
{
atomic_set
(
&
msg
->
refcnt
,
1
);
msg
->
send_failed
=
0
;
...
...
@@ -62,7 +62,7 @@ void sctp_datamsg_init(struct sctp_datamsg *msg)
}
/* Allocate and initialize datamsg. */
struct
sctp_datamsg
*
sctp_datamsg_new
(
int
gfp
)
SCTP_STATIC
struct
sctp_datamsg
*
sctp_datamsg_new
(
int
gfp
)
{
struct
sctp_datamsg
*
msg
;
msg
=
kmalloc
(
sizeof
(
struct
sctp_datamsg
),
gfp
);
...
...
@@ -124,7 +124,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
}
/* Hold a reference. */
void
sctp_datamsg_hold
(
struct
sctp_datamsg
*
msg
)
static
void
sctp_datamsg_hold
(
struct
sctp_datamsg
*
msg
)
{
atomic_inc
(
&
msg
->
refcnt
);
}
...
...
@@ -151,7 +151,7 @@ void sctp_datamsg_track(struct sctp_chunk *chunk)
}
/* Assign a chunk to this datamsg. */
void
sctp_datamsg_assign
(
struct
sctp_datamsg
*
msg
,
struct
sctp_chunk
*
chunk
)
static
void
sctp_datamsg_assign
(
struct
sctp_datamsg
*
msg
,
struct
sctp_chunk
*
chunk
)
{
sctp_datamsg_hold
(
msg
);
chunk
->
msg
=
msg
;
...
...
net/sctp/command.c
View file @
cabbb4de
...
...
@@ -42,17 +42,6 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Create a new sctp_command_sequence. */
sctp_cmd_seq_t
*
sctp_new_cmd_seq
(
int
gfp
)
{
sctp_cmd_seq_t
*
retval
=
t_new
(
sctp_cmd_seq_t
,
gfp
);
if
(
retval
)
sctp_init_cmd_seq
(
retval
);
return
retval
;
}
/* Initialize a block of memory as a command sequence. */
int
sctp_init_cmd_seq
(
sctp_cmd_seq_t
*
seq
)
{
...
...
@@ -77,13 +66,6 @@ int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
return
0
;
}
/* Rewind an sctp_cmd_seq_t to iterate from the start. */
int
sctp_rewind_sequence
(
sctp_cmd_seq_t
*
seq
)
{
seq
->
next_cmd
=
0
;
return
1
;
/* We always succeed. */
}
/* Return the next command structure in a sctp_cmd_seq.
* Returns NULL at the end of the sequence.
*/
...
...
@@ -97,8 +79,3 @@ sctp_cmd_t *sctp_next_cmd(sctp_cmd_seq_t *seq)
return
retval
;
}
/* Dispose of a command sequence. */
void
sctp_free_cmd_seq
(
sctp_cmd_seq_t
*
seq
)
{
kfree
(
seq
);
}
net/sctp/debug.c
View file @
cabbb4de
...
...
@@ -98,23 +98,6 @@ const char *sctp_cname(const sctp_subtype_t cid)
return
"unknown chunk"
;
}
/* These are printable form of variable-length parameters. */
const
char
*
sctp_param_tbl
[
SCTP_PARAM_ECN_CAPABLE
+
1
]
=
{
""
,
"PARAM_HEARTBEAT_INFO"
,
""
,
""
,
""
,
"PARAM_IPV4_ADDRESS"
,
"PARAM_IPV6_ADDRESS"
,
"PARAM_STATE_COOKIE"
,
"PARAM_UNRECOGNIZED_PARAMETERS"
,
"PARAM_COOKIE_PRESERVATIVE"
,
""
,
"PARAM_HOST_NAME_ADDRESS"
,
"PARAM_SUPPORTED_ADDRESS_TYPES"
,
};
/* These are printable forms of the states. */
const
char
*
sctp_state_tbl
[
SCTP_STATE_NUM_STATES
]
=
{
"STATE_EMPTY"
,
...
...
@@ -171,6 +154,7 @@ const char *sctp_pname(const sctp_subtype_t id)
static
const
char
*
sctp_other_tbl
[]
=
{
"NO_PENDING_TSN"
,
"ICMP_PROTO_UNREACH"
,
};
/* Lookup "other" debug name. */
...
...
@@ -178,7 +162,7 @@ const char *sctp_oname(const sctp_subtype_t id)
{
if
(
id
.
other
<
0
)
return
"illegal 'other' event"
;
if
(
id
.
other
<
SCTP_EVENT_OTHER_MAX
)
if
(
id
.
other
<
=
SCTP_EVENT_OTHER_MAX
)
return
sctp_other_tbl
[
id
.
other
];
return
"unknown 'other' event"
;
}
...
...
net/sctp/endpointola.c
View file @
cabbb4de
...
...
@@ -63,34 +63,11 @@
/* Forward declarations for internal helpers. */
static
void
sctp_endpoint_bh_rcv
(
struct
sctp_endpoint
*
ep
);
/* Create a sctp_endpoint with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
struct
sctp_endpoint
*
sctp_endpoint_new
(
struct
sock
*
sk
,
int
gfp
)
{
struct
sctp_endpoint
*
ep
;
/* Build a local endpoint. */
ep
=
t_new
(
struct
sctp_endpoint
,
gfp
);
if
(
!
ep
)
goto
fail
;
if
(
!
sctp_endpoint_init
(
ep
,
sk
,
gfp
))
goto
fail_init
;
ep
->
base
.
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
ep
);
return
ep
;
fail_init:
kfree
(
ep
);
fail:
return
NULL
;
}
/*
* Initialize the base fields of the endpoint structure.
*/
struct
sctp_endpoint
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
ep
,
struct
sock
*
sk
,
int
gfp
)
st
atic
st
ruct
sctp_endpoint
*
sctp_endpoint_init
(
struct
sctp_endpoint
*
ep
,
struct
sock
*
sk
,
int
gfp
)
{
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
memset
(
ep
,
0
,
sizeof
(
struct
sctp_endpoint
));
...
...
@@ -160,6 +137,29 @@ struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
return
ep
;
}
/* Create a sctp_endpoint with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
struct
sctp_endpoint
*
sctp_endpoint_new
(
struct
sock
*
sk
,
int
gfp
)
{
struct
sctp_endpoint
*
ep
;
/* Build a local endpoint. */
ep
=
t_new
(
struct
sctp_endpoint
,
gfp
);
if
(
!
ep
)
goto
fail
;
if
(
!
sctp_endpoint_init
(
ep
,
sk
,
gfp
))
goto
fail_init
;
ep
->
base
.
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
ep
);
return
ep
;
fail_init:
kfree
(
ep
);
fail:
return
NULL
;
}
/* Add an association to an endpoint. */
void
sctp_endpoint_add_asoc
(
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
)
...
...
@@ -184,7 +184,7 @@ void sctp_endpoint_free(struct sctp_endpoint *ep)
}
/* Final destructor for endpoint. */
void
sctp_endpoint_destroy
(
struct
sctp_endpoint
*
ep
)
static
void
sctp_endpoint_destroy
(
struct
sctp_endpoint
*
ep
)
{
SCTP_ASSERT
(
ep
->
base
.
dead
,
"Endpoint is not dead"
,
return
);
...
...
@@ -257,7 +257,7 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
struct
sctp_association
*
__sctp_endpoint_lookup_assoc
(
st
atic
st
ruct
sctp_association
*
__sctp_endpoint_lookup_assoc
(
const
struct
sctp_endpoint
*
ep
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
transport
)
...
...
@@ -345,7 +345,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
sk
=
ep
->
base
.
sk
;
while
(
NULL
!=
(
chunk
=
sctp_inq_pop
(
inqueue
)))
{
subtype
.
chunk
=
chunk
->
chunk_hdr
->
type
;
subtype
=
SCTP_ST_CHUNK
(
chunk
->
chunk_hdr
->
type
)
;
/* We might have grown an association since last we
* looked, so try again.
...
...
net/sctp/input.c
View file @
cabbb4de
...
...
@@ -63,11 +63,15 @@
/* Forward declarations for internal helpers. */
static
int
sctp_rcv_ootb
(
struct
sk_buff
*
);
struct
sctp_association
*
__sctp_rcv_lookup
(
struct
sk_buff
*
skb
,
st
atic
st
ruct
sctp_association
*
__sctp_rcv_lookup
(
struct
sk_buff
*
skb
,
const
union
sctp_addr
*
laddr
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
transportp
);
struct
sctp_endpoint
*
__sctp_rcv_lookup_endpoint
(
const
union
sctp_addr
*
laddr
);
static
struct
sctp_endpoint
*
__sctp_rcv_lookup_endpoint
(
const
union
sctp_addr
*
laddr
);
static
struct
sctp_association
*
__sctp_lookup_association
(
const
union
sctp_addr
*
local
,
const
union
sctp_addr
*
peer
,
struct
sctp_transport
**
pt
);
/* Calculate the SCTP checksum of an SCTP packet. */
...
...
@@ -130,6 +134,10 @@ int sctp_rcv(struct sk_buff *skb)
skb_pull
(
skb
,
sizeof
(
struct
sctphdr
));
/* Make sure we at least have chunk headers worth of data left. */
if
(
skb
->
len
<
sizeof
(
struct
sctp_chunkhdr
))
goto
discard_it
;
family
=
ipver2af
(
skb
->
nh
.
iph
->
version
);
af
=
sctp_get_af_specific
(
family
);
if
(
unlikely
(
!
af
))
...
...
@@ -284,6 +292,31 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
}
}
/*
* SCTP Implementer's Guide, 2.37 ICMP handling procedures
*
* ICMP8) If the ICMP code is a "Unrecognized next header type encountered"
* or a "Protocol Unreachable" treat this message as an abort
* with the T bit set.
*
* This function sends an event to the state machine, which will abort the
* association.
*
*/
void
sctp_icmp_proto_unreachable
(
struct
sock
*
sk
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
t
)
{
SCTP_DEBUG_PRINTK
(
"%s
\n
"
,
__FUNCTION__
);
sctp_do_sm
(
SCTP_EVENT_T_OTHER
,
SCTP_ST_OTHER
(
SCTP_EVENT_ICMP_PROTO_UNREACH
),
asoc
->
state
,
asoc
->
ep
,
asoc
,
NULL
,
GFP_ATOMIC
);
}
/* Common lookup code for icmp/icmpv6 error handler. */
struct
sock
*
sctp_err_lookup
(
int
family
,
struct
sk_buff
*
skb
,
struct
sctphdr
*
sctphdr
,
...
...
@@ -326,11 +359,12 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
}
if
(
asoc
)
{
sk
=
asoc
->
base
.
sk
;
if
(
ntohl
(
sctphdr
->
vtag
)
!=
asoc
->
c
.
peer_vtag
)
{
ICMP_INC_STATS_BH
(
ICMP_MIB_INERRORS
);
goto
out
;
}
sk
=
asoc
->
base
.
sk
;
}
else
sk
=
ep
->
base
.
sk
;
...
...
@@ -432,7 +466,13 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
sctp_icmp_frag_needed
(
sk
,
asoc
,
transport
,
info
);
goto
out_unlock
;
}
else
{
if
(
ICMP_PROT_UNREACH
==
code
)
{
sctp_icmp_proto_unreachable
(
sk
,
ep
,
asoc
,
transport
);
goto
out_unlock
;
}
}
err
=
icmp_err_convert
[
code
].
errno
;
break
;
case
ICMP_TIME_EXCEEDED
:
...
...
@@ -479,10 +519,10 @@ int sctp_rcv_ootb(struct sk_buff *skb)
sctp_errhdr_t
*
err
;
ch
=
(
sctp_chunkhdr_t
*
)
skb
->
data
;
ch_end
=
((
__u8
*
)
ch
)
+
WORD_ROUND
(
ntohs
(
ch
->
length
));
/* Scan through all the chunks in the packet. */
do
{
ch_end
=
((
__u8
*
)
ch
)
+
WORD_ROUND
(
ntohs
(
ch
->
length
));
while
(
ch_end
>
(
__u8
*
)
ch
&&
ch_end
<
skb
->
tail
)
{
/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
* receiver MUST silently discard the OOTB packet and take no
...
...
@@ -513,7 +553,8 @@ int sctp_rcv_ootb(struct sk_buff *skb)
}
ch
=
(
sctp_chunkhdr_t
*
)
ch_end
;
}
while
(
ch_end
<
skb
->
tail
);
ch_end
=
((
__u8
*
)
ch
)
+
WORD_ROUND
(
ntohs
(
ch
->
length
));
}
return
0
;
...
...
@@ -522,7 +563,7 @@ int sctp_rcv_ootb(struct sk_buff *skb)
}
/* Insert endpoint into the hash table. */
void
__sctp_hash_endpoint
(
struct
sctp_endpoint
*
ep
)
static
void
__sctp_hash_endpoint
(
struct
sctp_endpoint
*
ep
)
{
struct
sctp_ep_common
**
epp
;
struct
sctp_ep_common
*
epb
;
...
...
@@ -552,7 +593,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
}
/* Remove endpoint from the hash table. */
void
__sctp_unhash_endpoint
(
struct
sctp_endpoint
*
ep
)
static
void
__sctp_unhash_endpoint
(
struct
sctp_endpoint
*
ep
)
{
struct
sctp_hashbucket
*
head
;
struct
sctp_ep_common
*
epb
;
...
...
@@ -584,7 +625,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
}
/* Look up an endpoint. */
struct
sctp_endpoint
*
__sctp_rcv_lookup_endpoint
(
const
union
sctp_addr
*
laddr
)
st
atic
st
ruct
sctp_endpoint
*
__sctp_rcv_lookup_endpoint
(
const
union
sctp_addr
*
laddr
)
{
struct
sctp_hashbucket
*
head
;
struct
sctp_ep_common
*
epb
;
...
...
@@ -610,16 +651,8 @@ struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
return
ep
;
}
/* Add an association to the hash. Local BH-safe. */
void
sctp_hash_established
(
struct
sctp_association
*
asoc
)
{
sctp_local_bh_disable
();
__sctp_hash_established
(
asoc
);
sctp_local_bh_enable
();
}
/* Insert association into the hash table. */
void
__sctp_hash_established
(
struct
sctp_association
*
asoc
)
static
void
__sctp_hash_established
(
struct
sctp_association
*
asoc
)
{
struct
sctp_ep_common
**
epp
;
struct
sctp_ep_common
*
epb
;
...
...
@@ -642,16 +675,16 @@ void __sctp_hash_established(struct sctp_association *asoc)
sctp_write_unlock
(
&
head
->
lock
);
}
/*
Remove association from the hash table.
Local BH-safe. */
void
sctp_
un
hash_established
(
struct
sctp_association
*
asoc
)
/*
Add an association to the hash.
Local BH-safe. */
void
sctp_hash_established
(
struct
sctp_association
*
asoc
)
{
sctp_local_bh_disable
();
__sctp_
un
hash_established
(
asoc
);
__sctp_hash_established
(
asoc
);
sctp_local_bh_enable
();
}
/* Remove association from the hash table. */
void
__sctp_unhash_established
(
struct
sctp_association
*
asoc
)
static
void
__sctp_unhash_established
(
struct
sctp_association
*
asoc
)
{
struct
sctp_hashbucket
*
head
;
struct
sctp_ep_common
*
epb
;
...
...
@@ -675,8 +708,16 @@ void __sctp_unhash_established(struct sctp_association *asoc)
sctp_write_unlock
(
&
head
->
lock
);
}
/* Remove association from the hash table. Local BH-safe. */
void
sctp_unhash_established
(
struct
sctp_association
*
asoc
)
{
sctp_local_bh_disable
();
__sctp_unhash_established
(
asoc
);
sctp_local_bh_enable
();
}
/* Look up an association. */
struct
sctp_association
*
__sctp_lookup_association
(
st
atic
st
ruct
sctp_association
*
__sctp_lookup_association
(
const
union
sctp_addr
*
local
,
const
union
sctp_addr
*
peer
,
struct
sctp_transport
**
pt
)
...
...
@@ -713,8 +754,9 @@ struct sctp_association *__sctp_lookup_association(
}
/* Look up an association. BH-safe. */
SCTP_STATIC
struct
sctp_association
*
sctp_lookup_association
(
const
union
sctp_addr
*
laddr
,
const
union
sctp_addr
*
paddr
,
const
union
sctp_addr
*
paddr
,
struct
sctp_transport
**
transportp
)
{
struct
sctp_association
*
asoc
;
...
...
@@ -784,6 +826,14 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
return
NULL
;
}
/* The code below will attempt to walk the chunk and extract
* parameter information. Before we do that, we need to verify
* that the chunk length doesn't cause overflow. Otherwise, we'll
* walk off the end.
*/
if
(
WORD_ROUND
(
ntohs
(
ch
->
length
))
>
skb
->
len
)
return
NULL
;
/*
* This code will NOT touch anything inside the chunk--it is
* strictly READ-ONLY.
...
...
@@ -821,7 +871,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
}
/* Lookup an association for an inbound skb. */
struct
sctp_association
*
__sctp_rcv_lookup
(
struct
sk_buff
*
skb
,
st
atic
st
ruct
sctp_association
*
__sctp_rcv_lookup
(
struct
sk_buff
*
skb
,
const
union
sctp_addr
*
paddr
,
const
union
sctp_addr
*
laddr
,
struct
sctp_transport
**
transportp
)
...
...
net/sctp/inqueue.c
View file @
cabbb4de
...
...
@@ -59,19 +59,6 @@ void sctp_inq_init(struct sctp_inq *queue)
queue
->
malloced
=
0
;
}
/* Create an initialized sctp_inq. */
struct
sctp_inq
*
sctp_inq_new
(
void
)
{
struct
sctp_inq
*
retval
;
retval
=
t_new
(
struct
sctp_inq
,
GFP_ATOMIC
);
if
(
retval
)
{
sctp_inq_init
(
retval
);
retval
->
malloced
=
1
;
}
return
retval
;
}
/* Release the memory associated with an SCTP inqueue. */
void
sctp_inq_free
(
struct
sctp_inq
*
queue
)
{
...
...
@@ -157,14 +144,36 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
}
chunk
->
chunk_hdr
=
ch
;
chunk
->
chunk_end
=
((
__u8
*
)
ch
)
+
WORD_ROUND
(
ntohs
(
ch
->
length
));
chunk
->
chunk_end
=
((
__u8
*
)
ch
)
+
WORD_ROUND
(
ntohs
(
ch
->
length
));
/* In the unlikely case of an IP reassembly, the skb could be
* non-linear. If so, update chunk_end so that it doesn't go past
* the skb->tail.
*/
if
(
unlikely
(
skb_is_nonlinear
(
chunk
->
skb
)))
{
if
(
chunk
->
chunk_end
>
chunk
->
skb
->
tail
)
chunk
->
chunk_end
=
chunk
->
skb
->
tail
;
}
skb_pull
(
chunk
->
skb
,
sizeof
(
sctp_chunkhdr_t
));
chunk
->
subh
.
v
=
NULL
;
/* Subheader is no longer valid. */
if
(
chunk
->
chunk_end
<
chunk
->
skb
->
tail
)
{
/* This is not a singleton */
chunk
->
singleton
=
0
;
}
else
if
(
chunk
->
chunk_end
>
chunk
->
skb
->
tail
)
{
/* RFC 2960, Section 6.10 Bundling
*
* Partial chunks MUST NOT be placed in an SCTP packet.
* If the receiver detects a partial chunk, it MUST drop
* the chunk.
*
* Since the end of the chunk is past the end of our buffer
* (which contains the whole packet, we can freely discard
* the whole packet.
*/
sctp_chunk_free
(
chunk
);
chunk
=
queue
->
in_progress
=
NULL
;
return
NULL
;
}
else
{
/* We are at the end of the packet, so mark the chunk
* in case we need to send a SACK.
...
...
net/sctp/ipv6.c
View file @
cabbb4de
...
...
@@ -84,8 +84,8 @@ static struct notifier_block sctp_inet6addr_notifier = {
};
/* ICMP error handler. */
void
sctp_v6_err
(
struct
sk_buff
*
skb
,
struct
inet6_skb_parm
*
opt
,
int
type
,
int
code
,
int
offset
,
__u32
info
)
SCTP_STATIC
void
sctp_v6_err
(
struct
sk_buff
*
skb
,
struct
inet6_skb_parm
*
opt
,
int
type
,
int
code
,
int
offset
,
__u32
info
)
{
struct
inet6_dev
*
idev
;
struct
ipv6hdr
*
iph
=
(
struct
ipv6hdr
*
)
skb
->
data
;
...
...
@@ -122,6 +122,12 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
case
ICMPV6_PKT_TOOBIG
:
sctp_icmp_frag_needed
(
sk
,
asoc
,
transport
,
ntohl
(
info
));
goto
out_unlock
;
case
ICMPV6_PARAMPROB
:
if
(
ICMPV6_UNK_NEXTHDR
==
code
)
{
sctp_icmp_proto_unreachable
(
sk
,
ep
,
asoc
,
transport
);
goto
out_unlock
;
}
break
;
default:
break
;
}
...
...
@@ -188,9 +194,9 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
struct
dst_entry
*
sctp_v6_get_dst
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
st
atic
st
ruct
dst_entry
*
sctp_v6_get_dst
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
{
struct
dst_entry
*
dst
;
struct
flowi
fl
;
...
...
@@ -251,8 +257,10 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
/* Fills in the source address(saddr) based on the destination address(daddr)
* and asoc's bind address list.
*/
void
sctp_v6_get_saddr
(
struct
sctp_association
*
asoc
,
struct
dst_entry
*
dst
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
static
void
sctp_v6_get_saddr
(
struct
sctp_association
*
asoc
,
struct
dst_entry
*
dst
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
{
struct
sctp_bind_addr
*
bp
;
rwlock_t
*
addr_lock
;
...
...
@@ -577,8 +585,8 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
}
/* Create and initialize a new sk for the socket to be returned by accept(). */
struct
sock
*
sctp_v6_create_accept_sk
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
)
st
atic
st
ruct
sock
*
sctp_v6_create_accept_sk
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
)
{
struct
inet_sock
*
inet
=
inet_sk
(
sk
);
struct
sock
*
newsk
;
...
...
net/sctp/objcnt.c
View file @
cabbb4de
...
...
@@ -62,7 +62,7 @@ SCTP_DBG_OBJCNT(datamsg);
/* An array to make it easy to pretty print the debug information
* to the proc fs.
*/
sctp_dbg_objcnt_entry_t
sctp_dbg_objcnt
[]
=
{
s
tatic
s
ctp_dbg_objcnt_entry_t
sctp_dbg_objcnt
[]
=
{
SCTP_DBG_OBJCNT_ENTRY
(
sock
),
SCTP_DBG_OBJCNT_ENTRY
(
ep
),
SCTP_DBG_OBJCNT_ENTRY
(
assoc
),
...
...
net/sctp/outqueue.c
View file @
cabbb4de
...
...
@@ -190,19 +190,6 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary,
return
0
;
}
/* Generate a new outqueue. */
struct
sctp_outq
*
sctp_outq_new
(
struct
sctp_association
*
asoc
)
{
struct
sctp_outq
*
q
;
q
=
t_new
(
struct
sctp_outq
,
GFP_KERNEL
);
if
(
q
)
{
sctp_outq_init
(
asoc
,
q
);
q
->
malloced
=
1
;
}
return
q
;
}
/* Initialize an existing sctp_outq. This does the boring stuff.
* You still need to define handlers if you really want to DO
* something with this structure...
...
...
@@ -362,7 +349,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
/* Insert a chunk into the sorted list based on the TSNs. The retransmit list
* and the abandoned list are in ascending order.
*/
void
sctp_insert_list
(
struct
list_head
*
head
,
struct
list_head
*
new
)
static
void
sctp_insert_list
(
struct
list_head
*
head
,
struct
list_head
*
new
)
{
struct
list_head
*
pos
;
struct
sctp_chunk
*
nchunk
,
*
lchunk
;
...
...
net/sctp/proc.c
View file @
cabbb4de
...
...
@@ -39,7 +39,7 @@
#include <linux/init.h>
#include <net/sctp/sctp.h>
struct
snmp_mib
sctp_snmp_list
[]
=
{
st
atic
st
ruct
snmp_mib
sctp_snmp_list
[]
=
{
SNMP_MIB_ITEM
(
"SctpCurrEstab"
,
SCTP_MIB_CURRESTAB
),
SNMP_MIB_ITEM
(
"SctpActiveEstabs"
,
SCTP_MIB_ACTIVEESTABS
),
SNMP_MIB_ITEM
(
"SctpPassiveEstabs"
,
SCTP_MIB_PASSIVEESTABS
),
...
...
net/sctp/protocol.c
View file @
cabbb4de
...
...
@@ -95,7 +95,7 @@ struct sock *sctp_get_ctl_sock(void)
}
/* Set up the proc fs entry for the SCTP protocol. */
__init
int
sctp_proc_init
(
void
)
static
__init
int
sctp_proc_init
(
void
)
{
if
(
!
proc_net_sctp
)
{
struct
proc_dir_entry
*
ent
;
...
...
@@ -124,7 +124,7 @@ __init int sctp_proc_init(void)
* Note: Do not make this __exit as it is used in the init error
* path.
*/
void
sctp_proc_exit
(
void
)
static
void
sctp_proc_exit
(
void
)
{
sctp_snmp_proc_exit
();
sctp_eps_proc_exit
();
...
...
@@ -428,9 +428,9 @@ 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 address that matches an address in the bind address list.
*/
struct
dst_entry
*
sctp_v4_get_dst
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
st
atic
st
ruct
dst_entry
*
sctp_v4_get_dst
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
{
struct
rtable
*
rt
;
struct
flowi
fl
;
...
...
@@ -520,10 +520,10 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
/* For v4, the source address is cached in the route entry(dst). So no need
* to cache it separately and hence this is an empty routine.
*/
void
sctp_v4_get_saddr
(
struct
sctp_association
*
asoc
,
struct
dst_entry
*
dst
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
static
void
sctp_v4_get_saddr
(
struct
sctp_association
*
asoc
,
struct
dst_entry
*
dst
,
union
sctp_addr
*
daddr
,
union
sctp_addr
*
saddr
)
{
struct
rtable
*
rt
=
(
struct
rtable
*
)
dst
;
...
...
@@ -547,8 +547,8 @@ static int sctp_v4_is_ce(const struct sk_buff *skb)
}
/* 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
)
st
atic
st
ruct
sock
*
sctp_v4_create_accept_sk
(
struct
sock
*
sk
,
struct
sctp_association
*
asoc
)
{
struct
sock
*
newsk
;
struct
inet_sock
*
inet
=
inet_sk
(
sk
);
...
...
@@ -639,7 +639,7 @@ int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
* Initialize the control inode/socket with a control endpoint data
* structure. This endpoint is reserved exclusively for the OOTB processing.
*/
int
sctp_ctl_sock_init
(
void
)
static
int
sctp_ctl_sock_init
(
void
)
{
int
err
;
sa_family_t
family
;
...
...
@@ -808,7 +808,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
return
ip_queue_xmit
(
skb
,
ipfragok
);
}
struct
sctp_af
sctp_ipv4_specific
;
st
atic
st
ruct
sctp_af
sctp_ipv4_specific
;
static
struct
sctp_pf
sctp_pf_inet
=
{
.
event_msgname
=
sctp_inet_event_msgname
,
...
...
@@ -829,7 +829,7 @@ static struct notifier_block sctp_inetaddr_notifier = {
};
/* Socket operations. */
struct
proto_ops
inet_seqpacket_ops
=
{
st
atic
st
ruct
proto_ops
inet_seqpacket_ops
=
{
.
family
=
PF_INET
,
.
owner
=
THIS_MODULE
,
.
release
=
inet_release
,
/* Needs to be wrapped... */
...
...
@@ -878,7 +878,7 @@ static struct net_protocol sctp_protocol = {
};
/* IPv4 address related functions. */
struct
sctp_af
sctp_ipv4_specific
=
{
st
atic
st
ruct
sctp_af
sctp_ipv4_specific
=
{
.
sctp_xmit
=
sctp_v4_xmit
,
.
setsockopt
=
ip_setsockopt
,
.
getsockopt
=
ip_getsockopt
,
...
...
@@ -959,7 +959,7 @@ static void cleanup_sctp_mibs(void)
}
/* Initialize the universe into something sensible. */
__init
int
sctp_init
(
void
)
SCTP_STATIC
__init
int
sctp_init
(
void
)
{
int
i
;
int
status
=
-
EINVAL
;
...
...
@@ -1196,7 +1196,7 @@ __init int sctp_init(void)
}
/* Exit handler for the SCTP protocol. */
__exit
void
sctp_exit
(
void
)
SCTP_STATIC
__exit
void
sctp_exit
(
void
)
{
/* BUG. This should probably do something useful like clean
* up all the remaining associations and all that memory.
...
...
net/sctp/sm_make_chunk.c
View file @
cabbb4de
...
...
@@ -67,6 +67,19 @@
extern
kmem_cache_t
*
sctp_chunk_cachep
;
SCTP_STATIC
struct
sctp_chunk
*
sctp_make_chunk
(
const
struct
sctp_association
*
asoc
,
__u8
type
,
__u8
flags
,
int
paylen
);
static
sctp_cookie_param_t
*
sctp_pack_cookie
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
init_chunk
,
int
*
cookie_len
,
const
__u8
*
raw_addrs
,
int
addrs_len
);
static
int
sctp_process_param
(
struct
sctp_association
*
asoc
,
union
sctp_params
param
,
const
union
sctp_addr
*
peer_addr
,
int
gfp
);
/* What was the inbound interface for this chunk? */
int
sctp_chunk_iif
(
const
struct
sctp_chunk
*
chunk
)
{
...
...
@@ -559,52 +572,6 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
return
retval
;
}
/* Make a DATA chunk for the given association. Populate the data
* payload.
*/
struct
sctp_chunk
*
sctp_make_datafrag
(
struct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
,
const
__u8
*
data
,
__u8
flags
,
__u16
ssn
)
{
struct
sctp_chunk
*
retval
;
retval
=
sctp_make_datafrag_empty
(
asoc
,
sinfo
,
data_len
,
flags
,
ssn
);
if
(
retval
)
sctp_addto_chunk
(
retval
,
data_len
,
data
);
return
retval
;
}
/* Make a DATA chunk for the given association to ride on stream id
* 'stream', with a payload id of 'payload', and a body of 'data'.
*/
struct
sctp_chunk
*
sctp_make_data
(
struct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
,
const
__u8
*
data
)
{
struct
sctp_chunk
*
retval
=
NULL
;
retval
=
sctp_make_data_empty
(
asoc
,
sinfo
,
data_len
);
if
(
retval
)
sctp_addto_chunk
(
retval
,
data_len
,
data
);
return
retval
;
}
/* Make a DATA chunk for the given association to ride on stream id
* 'stream', with a payload id of 'payload', and a body big enough to
* hold 'data_len' octets of data. We use this version when we need
* to build the message AFTER allocating memory.
*/
struct
sctp_chunk
*
sctp_make_data_empty
(
struct
sctp_association
*
asoc
,
const
struct
sctp_sndrcvinfo
*
sinfo
,
int
data_len
)
{
__u8
flags
=
SCTP_DATA_NOT_FRAG
;
return
sctp_make_datafrag_empty
(
asoc
,
sinfo
,
data_len
,
flags
,
0
);
}
/* Create a selective ackowledgement (SACK) for the given
* association. This reports on which TSN's we've seen to date,
* including duplicates and gaps.
...
...
@@ -881,6 +848,31 @@ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
return
retval
;
}
/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */
struct
sctp_chunk
*
sctp_make_abort_violation
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
,
const
__u8
*
payload
,
const
size_t
paylen
)
{
struct
sctp_chunk
*
retval
;
struct
sctp_paramhdr
phdr
;
retval
=
sctp_make_abort
(
asoc
,
chunk
,
sizeof
(
sctp_errhdr_t
)
+
paylen
+
sizeof
(
sctp_chunkhdr_t
));
if
(
!
retval
)
goto
end
;
sctp_init_cause
(
retval
,
SCTP_ERROR_PROTO_VIOLATION
,
payload
,
paylen
);
phdr
.
type
=
htons
(
chunk
->
chunk_hdr
->
type
);
phdr
.
length
=
chunk
->
chunk_hdr
->
length
;
sctp_addto_chunk
(
retval
,
sizeof
(
sctp_paramhdr_t
),
&
phdr
);
end:
return
retval
;
}
/* Make a HEARTBEAT chunk. */
struct
sctp_chunk
*
sctp_make_heartbeat
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_transport
*
transport
,
...
...
@@ -933,7 +925,7 @@ struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *asoc,
/* Create an Operation Error chunk with the specified space reserved.
* This routine can be used for containing multiple causes in the chunk.
*/
struct
sctp_chunk
*
sctp_make_op_error_space
(
st
atic
st
ruct
sctp_chunk
*
sctp_make_op_error_space
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
,
size_t
size
)
...
...
@@ -1034,7 +1026,6 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
SCTP_DBG_OBJCNT_INC
(
chunk
);
atomic_set
(
&
retval
->
refcnt
,
1
);
nodata:
return
retval
;
}
...
...
@@ -1062,6 +1053,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
/* Create a new chunk, setting the type and flags headers from the
* arguments, reserving enough space for a 'paylen' byte payload.
*/
SCTP_STATIC
struct
sctp_chunk
*
sctp_make_chunk
(
const
struct
sctp_association
*
asoc
,
__u8
type
,
__u8
flags
,
int
paylen
)
{
...
...
@@ -1261,7 +1253,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
/* Build a cookie representing asoc.
* This INCLUDES the param header needed to put the cookie in the INIT ACK.
*/
sctp_cookie_param_t
*
sctp_pack_cookie
(
const
struct
sctp_endpoint
*
ep
,
s
tatic
s
ctp_cookie_param_t
*
sctp_pack_cookie
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
init_chunk
,
int
*
cookie_len
,
...
...
@@ -1409,6 +1401,24 @@ struct sctp_association *sctp_unpack_cookie(
}
no_hmac:
/* IG Section 2.35.2:
* 3) Compare the port numbers and the verification tag contained
* within the COOKIE ECHO chunk to the actual port numbers and the
* verification tag within the SCTP common header of the received
* packet. If these values do not match the packet MUST be silently
* discarded,
*/
if
(
ntohl
(
chunk
->
sctp_hdr
->
vtag
)
!=
bear_cookie
->
my_vtag
)
{
*
error
=
-
SCTP_IERROR_BAD_TAG
;
goto
fail
;
}
if
(
ntohs
(
chunk
->
sctp_hdr
->
source
)
!=
bear_cookie
->
peer_addr
.
v4
.
sin_port
||
ntohs
(
chunk
->
sctp_hdr
->
dest
)
!=
bear_cookie
->
my_port
)
{
*
error
=
-
SCTP_IERROR_BAD_PORTS
;
goto
fail
;
}
/* Check to see if the cookie is stale. If there is already
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
...
...
@@ -1547,6 +1557,30 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
return
0
;
}
static
int
sctp_process_inv_paramlength
(
const
struct
sctp_association
*
asoc
,
struct
sctp_paramhdr
*
param
,
const
struct
sctp_chunk
*
chunk
,
struct
sctp_chunk
**
errp
)
{
char
error
[]
=
"The following parameter had invalid length:"
;
size_t
payload_len
=
WORD_ROUND
(
sizeof
(
error
))
+
sizeof
(
sctp_paramhdr_t
);
/* Create an error chunk and fill it in with our payload. */
if
(
!*
errp
)
*
errp
=
sctp_make_op_error_space
(
asoc
,
chunk
,
payload_len
);
if
(
*
errp
)
{
sctp_init_cause
(
*
errp
,
SCTP_ERROR_PROTO_VIOLATION
,
error
,
sizeof
(
error
));
sctp_addto_chunk
(
*
errp
,
sizeof
(
sctp_paramhdr_t
),
param
);
}
return
0
;
}
/* Do not attempt to handle the HOST_NAME parm. However, do
* send back an indicator to the peer.
*/
...
...
@@ -1725,6 +1759,18 @@ int sctp_verify_init(const struct sctp_association *asoc,
}
/* for (loop through all parameters) */
/* There is a possibility that a parameter length was bad and
* in that case we would have stoped walking the parameters.
* The current param.p would point at the bad one.
* Current consensus on the mailing list is to generate a PROTOCOL
* VIOLATION error. We build the ERROR chunk here and let the normal
* error handling code build and send the packet.
*/
if
(
param
.
v
<
(
void
*
)
chunk
->
chunk_end
-
sizeof
(
sctp_paramhdr_t
))
{
sctp_process_inv_paramlength
(
asoc
,
param
.
p
,
chunk
,
errp
);
return
0
;
}
/* The only missing mandatory param possible today is
* the state cookie for an INIT-ACK chunk.
*/
...
...
@@ -1912,8 +1958,10 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* work we do. In particular, we should not build transport
* structures for the addresses.
*/
int
sctp_process_param
(
struct
sctp_association
*
asoc
,
union
sctp_params
param
,
const
union
sctp_addr
*
peer_addr
,
int
gfp
)
static
int
sctp_process_param
(
struct
sctp_association
*
asoc
,
union
sctp_params
param
,
const
union
sctp_addr
*
peer_addr
,
int
gfp
)
{
union
sctp_addr
addr
;
int
i
;
...
...
@@ -2078,8 +2126,9 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
*
* Address Parameter and other parameter will not be wrapped in this function
*/
struct
sctp_chunk
*
sctp_make_asconf
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
,
int
vparam_len
)
static
struct
sctp_chunk
*
sctp_make_asconf
(
struct
sctp_association
*
asoc
,
union
sctp_addr
*
addr
,
int
vparam_len
)
{
sctp_addiphdr_t
asconf
;
struct
sctp_chunk
*
retval
;
...
...
@@ -2248,8 +2297,8 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
*
* Create an ASCONF_ACK chunk with enough space for the parameter responses.
*/
struct
sctp_chunk
*
sctp_make_asconf_ack
(
const
struct
sctp_association
*
asoc
,
__u32
serial
,
int
vparam_len
)
st
atic
st
ruct
sctp_chunk
*
sctp_make_asconf_ack
(
const
struct
sctp_association
*
asoc
,
__u32
serial
,
int
vparam_len
)
{
sctp_addiphdr_t
asconf
;
struct
sctp_chunk
*
retval
;
...
...
net/sctp/sm_sideeffect.c
View file @
cabbb4de
...
...
@@ -55,6 +55,24 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static
int
sctp_cmd_interpreter
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
);
static
int
sctp_side_effects
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
);
/********************************************************************
* Helper functions
********************************************************************/
...
...
@@ -134,8 +152,8 @@ static void sctp_do_ecn_cwr_work(struct sctp_association *asoc,
}
/* Generate SACK if necessary. We call this at the end of a packet. */
int
sctp_gen_sack
(
struct
sctp_association
*
asoc
,
int
force
,
sctp_cmd_seq_t
*
commands
)
static
int
sctp_gen_sack
(
struct
sctp_association
*
asoc
,
int
force
,
sctp_cmd_seq_t
*
commands
)
{
__u32
ctsn
,
max_tsn_seen
;
struct
sctp_chunk
*
sack
;
...
...
@@ -276,31 +294,31 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
sctp_association_put
(
asoc
);
}
void
sctp_generate_t1_cookie_event
(
unsigned
long
data
)
static
void
sctp_generate_t1_cookie_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
SCTP_EVENT_TIMEOUT_T1_COOKIE
);
}
void
sctp_generate_t1_init_event
(
unsigned
long
data
)
static
void
sctp_generate_t1_init_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
SCTP_EVENT_TIMEOUT_T1_INIT
);
}
void
sctp_generate_t2_shutdown_event
(
unsigned
long
data
)
static
void
sctp_generate_t2_shutdown_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN
);
}
void
sctp_generate_t4_rto_event
(
unsigned
long
data
)
static
void
sctp_generate_t4_rto_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
SCTP_EVENT_TIMEOUT_T4_RTO
);
}
void
sctp_generate_t5_shutdown_guard_event
(
unsigned
long
data
)
static
void
sctp_generate_t5_shutdown_guard_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
...
...
@@ -308,7 +326,7 @@ void sctp_generate_t5_shutdown_guard_event(unsigned long data)
}
/* sctp_generate_t5_shutdown_guard_event() */
void
sctp_generate_autoclose_event
(
unsigned
long
data
)
static
void
sctp_generate_autoclose_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
SCTP_EVENT_TIMEOUT_AUTOCLOSE
);
...
...
@@ -353,7 +371,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
}
/* Inject a SACK Timeout event into the state machine. */
void
sctp_generate_sack_event
(
unsigned
long
data
)
static
void
sctp_generate_sack_event
(
unsigned
long
data
)
{
struct
sctp_association
*
asoc
=
(
struct
sctp_association
*
)
data
;
sctp_generate_timeout_event
(
asoc
,
SCTP_EVENT_TIMEOUT_SACK
);
...
...
@@ -397,7 +415,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
asoc
->
overall_error_count
++
;
if
(
transport
->
active
&&
(
transport
->
error_count
++
>=
transport
->
error_threshold
))
{
(
transport
->
error_count
++
>=
transport
->
max_retrans
))
{
SCTP_DEBUG_PRINTK
(
"transport_strike: transport "
"IP:%d.%d.%d.%d failed.
\n
"
,
NIPQUAD
(
transport
->
ipaddr
.
v4
.
sin_addr
));
...
...
@@ -857,14 +875,14 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
/*****************************************************************
* This the master state function side effect processing function.
*****************************************************************/
int
sctp_side_effects
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
)
static
int
sctp_side_effects
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
)
{
int
error
;
...
...
@@ -944,11 +962,15 @@ int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
********************************************************************/
/* This is the side-effect interpreter. */
int
sctp_cmd_interpreter
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
)
static
int
sctp_cmd_interpreter
(
sctp_event_t
event_type
,
sctp_subtype_t
subtype
,
sctp_state_t
state
,
struct
sctp_endpoint
*
ep
,
struct
sctp_association
*
asoc
,
void
*
event_arg
,
sctp_disposition_t
status
,
sctp_cmd_seq_t
*
commands
,
int
gfp
)
{
int
error
=
0
;
int
force
;
...
...
net/sctp/sm_statefuns.c
View file @
cabbb4de
...
...
@@ -65,6 +65,53 @@
#include <net/sctp/sm.h>
#include <net/sctp/structs.h>
static
struct
sctp_packet
*
sctp_abort_pkt_new
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
const
void
*
payload
,
size_t
paylen
);
static
int
sctp_eat_data
(
const
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
);
static
struct
sctp_packet
*
sctp_ootb_pkt_new
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
);
static
void
sctp_send_stale_cookie_err
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
,
struct
sctp_chunk
*
err_chunk
);
static
sctp_disposition_t
sctp_sf_do_5_2_6_stale
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
);
static
sctp_disposition_t
sctp_sf_shut_8_4_5
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
);
static
struct
sctp_sackhdr
*
sctp_sm_pull_sack
(
struct
sctp_chunk
*
chunk
);
/* Small helper function that checks if the chunk length
* is of the appropriate length. The 'required_length' argument
* is set to be the size of a specific chunk we are testing.
* Return Values: 1 = Valid length
* 0 = Invalid length
*
*/
static
inline
int
sctp_chunk_length_valid
(
struct
sctp_chunk
*
chunk
,
__u16
required_length
)
{
__u16
chunk_length
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
if
(
unlikely
(
chunk_length
<
required_length
))
return
0
;
return
1
;
}
/**********************************************************
* These are the state functions for handling chunk events.
**********************************************************/
...
...
@@ -199,9 +246,14 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
*
* IG Section 2.11.2
* Furthermore, we require that the receiver of an INIT chunk MUST
* enforce these rules by silently discarding an arriving packet
* with an INIT chunk that is bundled with other chunks.
*/
if
(
!
chunk
->
singleton
)
return
SCTP_DISPOSITION_VIOLATION
;
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
)
;
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
...
...
@@ -225,6 +277,14 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
if
(
chunk
->
sctp_hdr
->
vtag
!=
0
)
return
sctp_sf_tabort_8_4_8
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the INIT chunk has a valid length.
* Normally, this would cause an ABORT with a Protocol Violation
* error, but since we don't have an association, we'll
* just discard the packet.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_init_chunk_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Verify the INIT chunk before processing it. */
err_chunk
=
NULL
;
if
(
!
sctp_verify_init
(
asoc
,
chunk
->
chunk_hdr
->
type
,
...
...
@@ -376,6 +436,13 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
struct
sctp_packet
*
packet
;
sctp_disposition_t
ret
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the INIT-ACK chunk has a valid length */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_initack_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
...
...
@@ -383,9 +450,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
if
(
!
chunk
->
singleton
)
return
SCTP_DISPOSITION_VIOLATION
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Grab the INIT header. */
chunk
->
subh
.
init_hdr
=
(
sctp_inithdr_t
*
)
chunk
->
skb
->
data
;
...
...
@@ -542,6 +606,14 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
if
(
ep
==
sctp_sk
((
sctp_get_ctl_sock
()))
->
ep
)
return
sctp_sf_ootb
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the COOKIE_ECHO chunk has a valid length.
* In this case, we check that we have enough for at least a
* chunk header. More detailed verification is done
* in sctp_unpack_cookie().
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_chunkhdr_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
...
...
@@ -687,6 +759,13 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Verify that the chunk length for the COOKIE-ACK is OK.
* If we don't do this, any bundled chunks may be junked.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_chunkhdr_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Reset init error count upon receipt of COOKIE-ACK,
* to avoid problems with the managemement of this
* counter in stale cookie situations when a transition back
...
...
@@ -748,11 +827,11 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
}
/* Generate and sendout a heartbeat packet. */
sctp_disposition_t
sctp_sf_heartbeat
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
s
tatic
s
ctp_disposition_t
sctp_sf_heartbeat
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
struct
sctp_transport
*
transport
=
(
struct
sctp_transport
*
)
arg
;
struct
sctp_chunk
*
reply
;
...
...
@@ -859,6 +938,11 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the HEARTBEAT chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_heartbeat_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* 8.3 The receiver of the HEARTBEAT should immediately
* respond with a HEARTBEAT ACK that contains the Heartbeat
* Information field copied from the received HEARTBEAT chunk.
...
...
@@ -922,6 +1006,11 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the HEARTBEAT-ACK chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_heartbeat_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
hbinfo
=
(
sctp_sender_hb_info_t
*
)
chunk
->
skb
->
data
;
from_addr
=
hbinfo
->
daddr
;
link
=
sctp_assoc_lookup_paddr
(
asoc
,
&
from_addr
);
...
...
@@ -1165,9 +1254,14 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
*
* IG Section 2.11.2
* Furthermore, we require that the receiver of an INIT chunk MUST
* enforce these rules by silently discarding an arriving packet
* with an INIT chunk that is bundled with other chunks.
*/
if
(
!
chunk
->
singleton
)
return
SCTP_DISPOSITION_VIOLATION
;
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
)
;
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
...
...
@@ -1175,6 +1269,13 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
if
(
chunk
->
sctp_hdr
->
vtag
!=
0
)
return
sctp_sf_tabort_8_4_8
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the INIT chunk has a valid length.
* In this case, we generate a protocol violation since we have
* an association established.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_init_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Grab the INIT header. */
chunk
->
subh
.
init_hdr
=
(
sctp_inithdr_t
*
)
chunk
->
skb
->
data
;
...
...
@@ -1718,6 +1819,15 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
char
action
;
struct
sctp_chunk
*
err_chk_p
;
/* Make sure that the chunk has a valid length from the protocol
* perspective. In this case check to make sure we have at least
* enough for the chunk header. Cookie length verification is
* done later.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_chunkhdr_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
...
...
@@ -1815,6 +1925,19 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
if
(
!
sctp_vtag_verify_either
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
* because of the following text:
* RFC 2960, Section 3.3.7
* If an endpoint receives an ABORT with a format error or for an
* association that doesn't exist, it MUST silently discard it.
* Becasue the length is "invalid", we can't really discard just
* as we do not know its true length. So, to be safe, discard the
* packet.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_abort_chunk_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD
));
...
...
@@ -1838,6 +1961,19 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify_either
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
* because of the following text:
* RFC 2960, Section 3.3.7
* If an endpoint receives an ABORT with a format error or for an
* association that doesn't exist, it MUST silently discard it.
* Becasue the length is "invalid", we can't really discard just
* as we do not know its true length. So, to be safe, discard the
* packet.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_abort_chunk_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Stop the T2-shutdown timer. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN
));
...
...
@@ -1890,6 +2026,16 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
struct
sctp_chunk
*
chunk
=
arg
;
sctp_errhdr_t
*
err
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the ERROR chunk has a valid length.
* The parameter walking depends on this as well.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_operr_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Process the error here */
/* FUTURE FIXME: When PR-SCTP related and other optional
* parms are emitted, this will have to change to handle multiple
...
...
@@ -1900,6 +2046,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
return
sctp_sf_do_5_2_6_stale
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/* It is possible to have malformed error causes, and that
* will cause us to end the walk early. However, since
* we are discarding the packet, there should be no adverse
* affects.
*/
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
...
...
@@ -1928,11 +2080,11 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t
sctp_sf_do_5_2_6_stale
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
s
tatic
s
ctp_disposition_t
sctp_sf_do_5_2_6_stale
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
struct
sctp_chunk
*
chunk
=
arg
;
time_t
stale
;
...
...
@@ -2064,12 +2216,24 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify_either
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Check that chunk header looks valid. */
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
* because of the following text:
* RFC 2960, Section 3.3.7
* If an endpoint receives an ABORT with a format error or for an
* association that doesn't exist, it MUST silently discard it.
* Becasue the length is "invalid", we can't really discard just
* as we do not know its true length. So, to be safe, discard the
* packet.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_abort_chunk_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* See if we have an error cause code in the chunk. */
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
if
(
len
>=
sizeof
(
struct
sctp_chunkhdr
)
+
sizeof
(
struct
sctp_errhdr
))
error
=
((
sctp_errhdr_t
*
)
chunk
->
skb
->
data
)
->
cause
;
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
error
));
SCTP_INC_STATS
(
SCTP_MIB_ABORTEDS
);
...
...
@@ -2096,27 +2260,43 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify_either
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_NEW_STATE
,
SCTP_STATE
(
SCTP_STATE_CLOSED
));
SCTP_INC_STATS
(
SCTP_MIB_ABORTEDS
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_INIT
));
/* Make sure that the ABORT chunk has a valid length.
* Since this is an ABORT chunk, we have to discard it
* because of the following text:
* RFC 2960, Section 3.3.7
* If an endpoint receives an ABORT with a format error or for an
* association that doesn't exist, it MUST silently discard it.
* Becasue the length is "invalid", we can't really discard just
* as we do not know its true length. So, to be safe, discard the
* packet.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_abort_chunk_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/*
Check that chunk header looks valid
. */
/*
See if we have an error cause code in the chunk
. */
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
if
(
len
>=
sizeof
(
struct
sctp_chunkhdr
)
+
sizeof
(
struct
sctp_errhdr
))
error
=
((
sctp_errhdr_t
*
)
chunk
->
skb
->
data
)
->
cause
;
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
error
));
sctp_stop_t1_and_abort
(
commands
,
error
);
return
SCTP_DISPOSITION_ABORT
;
}
/*
* Process an incoming ICMP as an ABORT. (COOKIE-WAIT state)
*/
sctp_disposition_t
sctp_sf_cookie_wait_icmp_abort
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
sctp_stop_t1_and_abort
(
commands
,
SCTP_ERROR_NO_ERROR
);
return
SCTP_DISPOSITION_ABORT
;
}
/*
* Process an ABORT. (COOKIE-ECHOED state)
*
* See sctp_sf_do_9_1_abort() above.
*/
sctp_disposition_t
sctp_sf_cookie_echoed_abort
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
...
...
@@ -2130,6 +2310,23 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
return
sctp_sf_cookie_wait_abort
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/*
* Stop T1 timer and abort association with "INIT failed".
*
* This is common code called by several sctp_sf_*_abort() functions above.
*/
void
sctp_stop_t1_and_abort
(
sctp_cmd_seq_t
*
commands
,
__u16
error
)
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_NEW_STATE
,
SCTP_STATE
(
SCTP_STATE_CLOSED
));
SCTP_INC_STATS
(
SCTP_MIB_ABORTEDS
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_INIT
));
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
error
));
}
/*
* sctp_sf_do_9_2_shut
*
...
...
@@ -2174,14 +2371,20 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
sctp_disposition_t
disposition
;
struct
sctp_ulpevent
*
ev
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the SHUTDOWN chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
struct
sctp_shutdown_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Convert the elaborate header. */
sdh
=
(
sctp_shutdownhdr_t
*
)
chunk
->
skb
->
data
;
skb_pull
(
chunk
->
skb
,
sizeof
(
sctp_shutdownhdr_t
));
chunk
->
subh
.
shutdown_hdr
=
sdh
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Upon the reception of the SHUTDOWN, the peer endpoint shall
* - enter the SHUTDOWN-RECEIVED state,
* - stop accepting new data from its SCTP user
...
...
@@ -2238,6 +2441,10 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep,
struct
sctp_chunk
*
chunk
=
(
struct
sctp_chunk
*
)
arg
;
struct
sctp_chunk
*
reply
;
/* Since we are not going to really process this INIT, there
* is no point in verifying chunk boundries. Just generate
* the SHUTDOWN ACK.
*/
reply
=
sctp_make_shutdown_ack
(
asoc
,
chunk
);
if
(
NULL
==
reply
)
goto
nomem
;
...
...
@@ -2295,6 +2502,10 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_ecne_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
cwr
=
(
sctp_cwrhdr_t
*
)
chunk
->
skb
->
data
;
skb_pull
(
chunk
->
skb
,
sizeof
(
sctp_cwrhdr_t
));
...
...
@@ -2345,6 +2556,10 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_ecne_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
ecne
=
(
sctp_ecnehdr_t
*
)
chunk
->
skb
->
data
;
skb_pull
(
chunk
->
skb
,
sizeof
(
sctp_ecnehdr_t
));
...
...
@@ -2400,6 +2615,10 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_data_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
error
=
sctp_eat_data
(
asoc
,
chunk
,
commands
);
switch
(
error
)
{
case
SCTP_IERROR_NO_ERROR
:
...
...
@@ -2517,6 +2736,10 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_data_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
error
=
sctp_eat_data
(
asoc
,
chunk
,
commands
);
switch
(
error
)
{
case
SCTP_IERROR_NO_ERROR
:
...
...
@@ -2598,6 +2821,11 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the SACK chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_sack_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Pull the SACK chunk from the data buffer */
sackh
=
sctp_sm_pull_sack
(
chunk
);
/* Was this a bogus SACK? */
...
...
@@ -2700,6 +2928,14 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
struct
sctp_chunk
*
chunk
=
arg
;
struct
sctp_ulpevent
*
ev
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the ERROR chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_operr_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
while
(
chunk
->
chunk_end
>
chunk
->
skb
->
data
)
{
ev
=
sctp_ulpevent_make_remote_error
(
asoc
,
chunk
,
0
,
GFP_ATOMIC
);
...
...
@@ -2744,6 +2980,11 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_chunkhdr_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* 10.2 H) SHUTDOWN COMPLETE notification
*
* When SCTP completes the shutdown procedures (section 9.2) this
...
...
@@ -2818,11 +3059,23 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
ch
=
(
sctp_chunkhdr_t
*
)
chunk
->
chunk_hdr
;
do
{
/* Break out if chunk length is less then minimal. */
if
(
ntohs
(
ch
->
length
)
<
sizeof
(
sctp_chunkhdr_t
))
break
;
ch_end
=
((
__u8
*
)
ch
)
+
WORD_ROUND
(
ntohs
(
ch
->
length
));
if
(
SCTP_CID_SHUTDOWN_ACK
==
ch
->
type
)
ootb_shut_ack
=
1
;
/* RFC 2960, Section 3.3.7
* Moreover, under any circumstances, an endpoint that
* receives an ABORT MUST NOT respond to that ABORT by
* sending an ABORT of its own.
*/
if
(
SCTP_CID_ABORT
==
ch
->
type
)
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
ch
=
(
sctp_chunkhdr_t
*
)
ch_end
;
}
while
(
ch_end
<
skb
->
tail
);
...
...
@@ -2853,11 +3106,11 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t
sctp_sf_shut_8_4_5
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
s
tatic
s
ctp_disposition_t
sctp_sf_shut_8_4_5
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
struct
sctp_packet
*
packet
=
NULL
;
struct
sctp_chunk
*
chunk
=
arg
;
...
...
@@ -2885,6 +3138,12 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
SCTP_INC_STATS
(
SCTP_MIB_OUTCTRLCHUNKS
);
/* If the chunk length is invalid, we don't want to process
* the reset of the packet.
*/
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_chunkhdr_t
)))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
return
SCTP_DISPOSITION_CONSUME
;
}
...
...
@@ -2927,6 +3186,17 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
sctp_addiphdr_t
*
hdr
;
__u32
serial
;
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPORT_BAD_TAG
,
SCTP_NULL
());
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/* Make sure that the ASCONF ADDIP chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
sctp_addip_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
hdr
=
(
sctp_addiphdr_t
*
)
chunk
->
skb
->
data
;
serial
=
ntohl
(
hdr
->
serial
);
...
...
@@ -2947,7 +3217,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
/* ADDIP 4.2 C3) If the value found in the serial number is
* equal to the value stored in the 'Peer-Serial-Number'
* IMPLEMENTATION NOTE: As an optimization a receiver may wish
* to save the last ASCONF-ACK for some predetermined period of * time and instead of re-processing the ASCONF (with the same
* to save the last ASCONF-ACK for some predetermined period of
* time and instead of re-processing the ASCONF (with the same
* serial number) it may just re-transmit the ASCONF-ACK.
*/
if
(
asoc
->
addip_last_asconf_ack
)
...
...
@@ -2986,6 +3257,17 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
sctp_addiphdr_t
*
addip_hdr
;
__u32
sent_serial
,
rcvd_serial
;
if
(
!
sctp_vtag_verify
(
asconf_ack
,
asoc
))
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPORT_BAD_TAG
,
SCTP_NULL
());
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/* Make sure that the ADDIP chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
asconf_ack
,
sizeof
(
sctp_addip_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
addip_hdr
=
(
sctp_addiphdr_t
*
)
asconf_ack
->
skb
->
data
;
rcvd_serial
=
ntohl
(
addip_hdr
->
serial
);
...
...
@@ -3084,6 +3366,11 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/* Make sure that the FORWARD_TSN chunk has valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
struct
sctp_fwdtsn_chunk
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
fwdtsn_hdr
=
(
struct
sctp_fwdtsn_hdr
*
)
chunk
->
skb
->
data
;
chunk
->
subh
.
fwdtsn_hdr
=
fwdtsn_hdr
;
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
...
...
@@ -3142,6 +3429,11 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/* Make sure that the FORWARD_TSN chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
struct
sctp_fwdtsn_chunk
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
fwdtsn_hdr
=
(
struct
sctp_fwdtsn_hdr
*
)
chunk
->
skb
->
data
;
chunk
->
subh
.
fwdtsn_hdr
=
fwdtsn_hdr
;
len
=
ntohs
(
chunk
->
chunk_hdr
->
length
);
...
...
@@ -3216,6 +3508,14 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
if
(
!
sctp_vtag_verify
(
unk_chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the chunk has a valid length.
* Since we don't know the chunk type, we use a general
* chunkhdr structure to make a comparison.
*/
if
(
!
sctp_chunk_length_valid
(
unk_chunk
,
sizeof
(
sctp_chunkhdr_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
switch
(
type
.
chunk
&
SCTP_CID_ACTION_MASK
)
{
case
SCTP_CID_ACTION_DISCARD
:
/* Discard the packet. */
...
...
@@ -3338,6 +3638,66 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
return
SCTP_DISPOSITION_VIOLATION
;
}
/*
* Handle a protocol violation when the chunk length is invalid.
* "Invalid" length is identified as smaller then the minimal length a
* given chunk can be. For example, a SACK chunk has invalid length
* if it's length is set to be smaller then the size of sctp_sack_chunk_t.
*
* We inform the other end by sending an ABORT with a Protocol Violation
* error code.
*
* Section: Not specified
* Verification Tag: Nothing to do
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (reply_msg, msg_up, counters)
*
* Generate an ABORT chunk and terminate the association.
*/
sctp_disposition_t
sctp_sf_violation_chunklen
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
struct
sctp_chunk
*
chunk
=
arg
;
struct
sctp_chunk
*
abort
=
NULL
;
char
err_str
[]
=
"The following chunk had invalid length:"
;
/* Make the abort chunk. */
abort
=
sctp_make_abort_violation
(
asoc
,
chunk
,
err_str
,
sizeof
(
err_str
));
if
(
!
abort
)
goto
nomem
;
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
abort
));
SCTP_INC_STATS
(
SCTP_MIB_OUTCTRLCHUNKS
);
if
(
asoc
->
state
<=
SCTP_STATE_COOKIE_ECHOED
)
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_INIT
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
SCTP_ERROR_PROTO_VIOLATION
));
}
else
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_ASSOC_FAILED
,
SCTP_U32
(
SCTP_ERROR_PROTO_VIOLATION
));
SCTP_DEC_STATS
(
SCTP_MIB_CURRESTAB
);
}
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_DISCARD_PACKET
,
SCTP_NULL
());
SCTP_INC_STATS
(
SCTP_MIB_ABORTEDS
);
return
SCTP_DISPOSITION_ABORT
;
nomem:
return
SCTP_DISPOSITION_NOMEM
;
}
/***************************************************************************
* These are the state functions for handling primitive (Section 10) events.
***************************************************************************/
...
...
@@ -4050,6 +4410,23 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
struct
sctp_chunk
*
chunk
=
(
struct
sctp_chunk
*
)
arg
;
struct
sctp_chunk
*
reply
;
/* There are 2 ways of getting here:
* 1) called in response to a SHUTDOWN chunk
* 2) called when SCTP_EVENT_NO_PENDING_TSN event is issued.
*
* For the case (2), the arg parameter is set to NULL. We need
* to check that we have a chunk before accessing it's fields.
*/
if
(
chunk
)
{
if
(
!
sctp_vtag_verify
(
chunk
,
asoc
))
return
sctp_sf_pdiscard
(
ep
,
asoc
,
type
,
arg
,
commands
);
/* Make sure that the SHUTDOWN chunk has a valid length. */
if
(
!
sctp_chunk_length_valid
(
chunk
,
sizeof
(
struct
sctp_shutdown_chunk_t
)))
return
sctp_sf_violation_chunklen
(
ep
,
asoc
,
type
,
arg
,
commands
);
}
/* If it has no more outstanding DATA chunks, the SHUTDOWN receiver
* shall send a SHUTDOWN ACK ...
*/
...
...
@@ -4537,7 +4914,7 @@ sctp_disposition_t sctp_sf_timer_ignore(const struct sctp_endpoint *ep,
********************************************************************/
/* Pull the SACK chunk based on the SACK header. */
struct
sctp_sackhdr
*
sctp_sm_pull_sack
(
struct
sctp_chunk
*
chunk
)
st
atic
st
ruct
sctp_sackhdr
*
sctp_sm_pull_sack
(
struct
sctp_chunk
*
chunk
)
{
struct
sctp_sackhdr
*
sack
;
unsigned
int
len
;
...
...
@@ -4564,7 +4941,7 @@ struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
/* Create an ABORT packet to be sent as a response, with the specified
* error causes.
*/
struct
sctp_packet
*
sctp_abort_pkt_new
(
const
struct
sctp_endpoint
*
ep
,
st
atic
st
ruct
sctp_packet
*
sctp_abort_pkt_new
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
const
void
*
payload
,
...
...
@@ -4600,8 +4977,8 @@ struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
}
/* Allocate a packet for responding in the OOTB conditions. */
struct
sctp_packet
*
sctp_ootb_pkt_new
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
)
st
atic
st
ruct
sctp_packet
*
sctp_ootb_pkt_new
(
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
)
{
struct
sctp_packet
*
packet
;
struct
sctp_transport
*
transport
;
...
...
@@ -4664,11 +5041,11 @@ void sctp_ootb_pkt_free(struct sctp_packet *packet)
}
/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */
void
sctp_send_stale_cookie_err
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
,
struct
sctp_chunk
*
err_chunk
)
static
void
sctp_send_stale_cookie_err
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
,
struct
sctp_chunk
*
err_chunk
)
{
struct
sctp_packet
*
packet
;
...
...
@@ -4694,9 +5071,9 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
/* Process a data chunk */
int
sctp_eat_data
(
const
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
)
static
int
sctp_eat_data
(
const
struct
sctp_association
*
asoc
,
struct
sctp_chunk
*
chunk
,
sctp_cmd_seq_t
*
commands
)
{
sctp_datahdr_t
*
data_hdr
;
struct
sctp_chunk
*
err
;
...
...
net/sctp/sm_statetable.c
View file @
cabbb4de
...
...
@@ -50,6 +50,17 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static
const
sctp_sm_table_entry_t
primitive_event_table
[
SCTP_NUM_PRIMITIVE_TYPES
][
SCTP_STATE_NUM_STATES
];
static
const
sctp_sm_table_entry_t
other_event_table
[
SCTP_NUM_OTHER_TYPES
][
SCTP_STATE_NUM_STATES
];
static
const
sctp_sm_table_entry_t
timeout_event_table
[
SCTP_NUM_TIMEOUT_TYPES
][
SCTP_STATE_NUM_STATES
];
static
const
sctp_sm_table_entry_t
*
sctp_chunk_event_lookup
(
sctp_cid_t
cid
,
sctp_state_t
state
);
static
const
sctp_sm_table_entry_t
bug
=
{
.
fn
=
sctp_sf_bug
,
.
name
=
"sctp_sf_bug"
...
...
@@ -419,7 +430,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
*
* For base protocol (RFC 2960).
*/
const
sctp_sm_table_entry_t
chunk_event_table
[
SCTP_NUM_BASE_CHUNK_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
static
const
sctp_sm_table_entry_t
chunk_event_table
[
SCTP_NUM_BASE_CHUNK_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
TYPE_SCTP_DATA
,
TYPE_SCTP_INIT
,
TYPE_SCTP_INIT_ACK
,
...
...
@@ -482,7 +493,7 @@ const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_ST
/* The primary index for this table is the chunk type.
* The secondary index for this table is the state.
*/
const
sctp_sm_table_entry_t
addip_chunk_event_table
[
SCTP_NUM_ADDIP_CHUNK_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
static
const
sctp_sm_table_entry_t
addip_chunk_event_table
[
SCTP_NUM_ADDIP_CHUNK_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
TYPE_SCTP_ASCONF
,
TYPE_SCTP_ASCONF_ACK
,
};
/*state_fn_t addip_chunk_event_table[][] */
...
...
@@ -511,7 +522,7 @@ const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][
/* The primary index for this table is the chunk type.
* The secondary index for this table is the state.
*/
const
sctp_sm_table_entry_t
prsctp_chunk_event_table
[
SCTP_NUM_PRSCTP_CHUNK_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
static
const
sctp_sm_table_entry_t
prsctp_chunk_event_table
[
SCTP_NUM_PRSCTP_CHUNK_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
TYPE_SCTP_FWD_TSN
,
};
/*state_fn_t prsctp_chunk_event_table[][] */
...
...
@@ -684,7 +695,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* The primary index for this table is the primitive type.
* The secondary index for this table is the state.
*/
const
sctp_sm_table_entry_t
primitive_event_table
[
SCTP_NUM_PRIMITIVE_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
static
const
sctp_sm_table_entry_t
primitive_event_table
[
SCTP_NUM_PRIMITIVE_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
TYPE_SCTP_PRIMITIVE_ASSOCIATE
,
TYPE_SCTP_PRIMITIVE_SHUTDOWN
,
TYPE_SCTP_PRIMITIVE_ABORT
,
...
...
@@ -716,8 +727,31 @@ const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
}
const
sctp_sm_table_entry_t
other_event_table
[
SCTP_NUM_OTHER_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
#define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \
/* SCTP_STATE_EMPTY */
\
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_COOKIE_WAIT */
\
{.fn = sctp_sf_cookie_wait_icmp_abort, \
.name = "sctp_sf_cookie_wait_icmp_abort"}, \
/* SCTP_STATE_COOKIE_ECHOED */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_ESTABLISHED */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_SHUTDOWN_SENT */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
\
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
}
static
const
sctp_sm_table_entry_t
other_event_table
[
SCTP_NUM_OTHER_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
TYPE_SCTP_OTHER_NO_PENDING_TSN
,
TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH
,
};
#define TYPE_SCTP_EVENT_TIMEOUT_NONE { \
...
...
@@ -931,7 +965,7 @@ const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_N
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
const
sctp_sm_table_entry_t
timeout_event_table
[
SCTP_NUM_TIMEOUT_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
static
const
sctp_sm_table_entry_t
timeout_event_table
[
SCTP_NUM_TIMEOUT_TYPES
][
SCTP_STATE_NUM_STATES
]
=
{
TYPE_SCTP_EVENT_TIMEOUT_NONE
,
TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE
,
TYPE_SCTP_EVENT_TIMEOUT_T1_INIT
,
...
...
@@ -944,8 +978,8 @@ const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STA
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE
,
};
const
sctp_sm_table_entry_t
*
sctp_chunk_event_lookup
(
sctp_cid_t
cid
,
sctp_state_t
state
)
static
const
sctp_sm_table_entry_t
*
sctp_chunk_event_lookup
(
sctp_cid_t
cid
,
sctp_state_t
state
)
{
if
(
state
>
SCTP_STATE_MAX
)
return
&
bug
;
...
...
net/sctp/socket.c
View file @
cabbb4de
...
...
@@ -208,7 +208,7 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
* id are specified, the associations matching the address and the id should be
* the same.
*/
struct
sctp_transport
*
sctp_addr_id2transport
(
struct
sock
*
sk
,
st
atic
st
ruct
sctp_transport
*
sctp_addr_id2transport
(
struct
sock
*
sk
,
struct
sockaddr_storage
*
addr
,
sctp_assoc_t
id
)
{
...
...
@@ -245,7 +245,7 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
* sockaddr_in6 [RFC 2553]),
* addr_len - the size of the address structure.
*/
int
sctp_bind
(
struct
sock
*
sk
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
SCTP_STATIC
int
sctp_bind
(
struct
sock
*
sk
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
{
int
retval
=
0
;
...
...
@@ -343,8 +343,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
}
/* Refresh ephemeral port. */
if
(
!
snum
)
snum
=
inet_sk
(
sk
)
->
num
;
if
(
!
bp
->
port
)
bp
->
port
=
inet_sk
(
sk
)
->
num
;
/* Add the address to the bind address list. */
sctp_local_bh_disable
();
...
...
@@ -354,8 +354,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
addr
->
v4
.
sin_port
=
ntohs
(
addr
->
v4
.
sin_port
);
ret
=
sctp_add_bind_addr
(
bp
,
addr
,
GFP_ATOMIC
);
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
();
...
...
@@ -1713,10 +1711,13 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
/* update default value for endpoint (all future associations) */
if
(
!
params
.
spp_assoc_id
&&
sctp_is_any
((
union
sctp_addr
*
)
&
params
.
spp_address
))
{
if
(
params
.
spp_hbinterval
)
/* Manual heartbeat on an endpoint is invalid. */
if
(
0xffffffff
==
params
.
spp_hbinterval
)
return
-
EINVAL
;
else
if
(
params
.
spp_hbinterval
)
sctp_sk
(
sk
)
->
paddrparam
.
spp_hbinterval
=
params
.
spp_hbinterval
;
if
(
sctp_max_retrans_path
)
if
(
params
.
spp_pathmaxrxt
)
sctp_sk
(
sk
)
->
paddrparam
.
spp_pathmaxrxt
=
params
.
spp_pathmaxrxt
;
return
0
;
...
...
@@ -1758,7 +1759,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
trans
->
error_threshold
=
params
.
spp_pathmaxrxt
;
if
(
params
.
spp_pathmaxrxt
)
trans
->
max_retrans
=
params
.
spp_pathmaxrxt
;
return
0
;
}
...
...
@@ -2937,7 +2939,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
params
.
spp_pathmaxrxt
=
trans
->
error_threshold
;
params
.
spp_pathmaxrxt
=
trans
->
max_retrans
;
done:
if
(
copy_to_user
(
optval
,
&
params
,
len
))
...
...
@@ -3049,6 +3051,9 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
struct
sctp_bind_addr
*
bp
;
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
struct
sctp_sockaddr_entry
*
addr
;
rwlock_t
*
addr_lock
;
unsigned
long
flags
;
int
cnt
=
0
;
if
(
len
!=
sizeof
(
sctp_assoc_t
))
...
...
@@ -3065,33 +3070,104 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
*/
if
(
0
==
id
)
{
bp
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
bind_addr
;
addr_lock
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
addr_lock
;
}
else
{
asoc
=
sctp_id2assoc
(
sk
,
id
);
if
(
!
asoc
)
return
-
EINVAL
;
bp
=
&
asoc
->
base
.
bind_addr
;
addr_lock
=
&
asoc
->
base
.
addr_lock
;
}
sctp_read_lock
(
addr_lock
);
/* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
* addresses from the global local address list.
*/
if
(
sctp_list_single_entry
(
&
bp
->
address_list
))
{
addr
=
list_entry
(
bp
->
address_list
.
next
,
struct
sctp_sockaddr_entry
,
list
);
if
(
sctp_is_any
(
&
addr
->
a
))
{
sctp_spin_lock_irqsave
(
&
sctp_local_addr_lock
,
flags
);
list_for_each
(
pos
,
&
sctp_local_addr_list
)
{
addr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
if
((
PF_INET
==
sk
->
sk_family
)
&&
(
AF_INET6
==
addr
->
a
.
sa
.
sa_family
))
continue
;
cnt
++
;
}
sctp_spin_unlock_irqrestore
(
&
sctp_local_addr_lock
,
flags
);
}
else
{
cnt
=
1
;
}
goto
done
;
}
list_for_each
(
pos
,
&
bp
->
address_list
)
{
cnt
++
;
}
done:
sctp_read_unlock
(
addr_lock
);
return
cnt
;
}
/* Helper function that copies local addresses to user and returns the number
* of addresses copied.
*/
static
int
sctp_copy_laddrs_to_user
(
struct
sock
*
sk
,
__u16
port
,
int
max_addrs
,
void
__user
*
to
)
{
struct
list_head
*
pos
;
struct
sctp_sockaddr_entry
*
addr
;
unsigned
long
flags
;
union
sctp_addr
temp
;
int
cnt
=
0
;
int
addrlen
;
sctp_spin_lock_irqsave
(
&
sctp_local_addr_lock
,
flags
);
list_for_each
(
pos
,
&
sctp_local_addr_list
)
{
addr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
if
((
PF_INET
==
sk
->
sk_family
)
&&
(
AF_INET6
==
addr
->
a
.
sa
.
sa_family
))
continue
;
memcpy
(
&
temp
,
&
addr
->
a
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sctp_sk
(
sk
),
&
temp
);
addrlen
=
sctp_get_af_specific
(
temp
.
sa
.
sa_family
)
->
sockaddr_len
;
temp
.
v4
.
sin_port
=
htons
(
port
);
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
{
sctp_spin_unlock_irqrestore
(
&
sctp_local_addr_lock
,
flags
);
return
-
EFAULT
;
}
to
+=
addrlen
;
cnt
++
;
if
(
cnt
>=
max_addrs
)
break
;
}
sctp_spin_unlock_irqrestore
(
&
sctp_local_addr_lock
,
flags
);
return
cnt
;
}
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sctp_bind_addr
*
bp
;
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_sockaddr_entry
*
from
;
struct
sctp_sockaddr_entry
*
addr
;
void
__user
*
to
;
union
sctp_addr
temp
;
struct
sctp_opt
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
rwlock_t
*
addr_lock
;
int
err
=
0
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
...
...
@@ -3108,33 +3184,59 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
*/
if
(
0
==
getaddrs
.
assoc_id
)
{
bp
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
bind_addr
;
addr_lock
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
addr_lock
;
}
else
{
asoc
=
sctp_id2assoc
(
sk
,
getaddrs
.
assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
bp
=
&
asoc
->
base
.
bind_addr
;
addr_lock
=
&
asoc
->
base
.
addr_lock
;
}
to
=
getaddrs
.
addrs
;
sctp_read_lock
(
addr_lock
);
/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
* addresses from the global local address list.
*/
if
(
sctp_list_single_entry
(
&
bp
->
address_list
))
{
addr
=
list_entry
(
bp
->
address_list
.
next
,
struct
sctp_sockaddr_entry
,
list
);
if
(
sctp_is_any
(
&
addr
->
a
))
{
cnt
=
sctp_copy_laddrs_to_user
(
sk
,
bp
->
port
,
getaddrs
.
addr_num
,
to
);
if
(
cnt
<
0
)
{
err
=
cnt
;
goto
unlock
;
}
goto
copy_getaddrs
;
}
}
list_for_each
(
pos
,
&
bp
->
address_list
)
{
from
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
memcpy
(
&
temp
,
&
from
->
a
,
sizeof
(
temp
));
addr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
memcpy
(
&
temp
,
&
addr
->
a
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
addrlen
=
sctp_get_af_specific
(
temp
.
sa
.
sa_family
)
->
sockaddr_len
;
temp
.
v4
.
sin_port
=
htons
(
temp
.
v4
.
sin_port
);
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
return
-
EFAULT
;
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
{
err
=
-
EFAULT
;
goto
unlock
;
}
to
+=
addrlen
;
cnt
++
;
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
copy_getaddrs:
getaddrs
.
addr_num
=
cnt
;
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
err
=
-
EFAULT
;
return
0
;
unlock:
sctp_read_unlock
(
addr_lock
);
return
err
;
}
/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
...
...
net/sctp/ssnmap.c
View file @
cabbb4de
...
...
@@ -42,6 +42,9 @@
#define MAX_KMALLOC_SIZE 131072
static
struct
sctp_ssnmap
*
sctp_ssnmap_init
(
struct
sctp_ssnmap
*
map
,
__u16
in
,
__u16
out
);
/* Storage size needed for map includes 2 headers and then the
* specific needs of in or out streams.
*/
...
...
@@ -87,8 +90,8 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp)
/* Initialize a block of memory as a ssnmap. */
struct
sctp_ssnmap
*
sctp_ssnmap_init
(
struct
sctp_ssnmap
*
map
,
__u16
in
,
__u16
out
)
st
atic
st
ruct
sctp_ssnmap
*
sctp_ssnmap_init
(
struct
sctp_ssnmap
*
map
,
__u16
in
,
__u16
out
)
{
memset
(
map
,
0x00
,
sctp_ssnmap_size
(
in
,
out
));
...
...
net/sctp/transport.c
View file @
cabbb4de
...
...
@@ -54,34 +54,10 @@
/* 1st Level Abstractions. */
/* Allocate and initialize a new transport. */
struct
sctp_transport
*
sctp_transport_new
(
const
union
sctp_addr
*
addr
,
int
gfp
)
{
struct
sctp_transport
*
transport
;
transport
=
t_new
(
struct
sctp_transport
,
gfp
);
if
(
!
transport
)
goto
fail
;
if
(
!
sctp_transport_init
(
transport
,
addr
,
gfp
))
goto
fail_init
;
transport
->
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
transport
);
return
transport
;
fail_init:
kfree
(
transport
);
fail:
return
NULL
;
}
/* Initialize a new transport from provided memory. */
struct
sctp_transport
*
sctp_transport_init
(
struct
sctp_transport
*
peer
,
const
union
sctp_addr
*
addr
,
int
gfp
)
st
atic
st
ruct
sctp_transport
*
sctp_transport_init
(
struct
sctp_transport
*
peer
,
const
union
sctp_addr
*
addr
,
int
gfp
)
{
/* Copy in the address. */
peer
->
ipaddr
=
*
addr
;
...
...
@@ -112,7 +88,6 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
/* Initialize the default path max_retrans. */
peer
->
max_retrans
=
sctp_max_retrans_path
;
peer
->
error_threshold
=
0
;
peer
->
error_count
=
0
;
INIT_LIST_HEAD
(
&
peer
->
transmitted
);
...
...
@@ -144,6 +119,30 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
return
peer
;
}
/* Allocate and initialize a new transport. */
struct
sctp_transport
*
sctp_transport_new
(
const
union
sctp_addr
*
addr
,
int
gfp
)
{
struct
sctp_transport
*
transport
;
transport
=
t_new
(
struct
sctp_transport
,
gfp
);
if
(
!
transport
)
goto
fail
;
if
(
!
sctp_transport_init
(
transport
,
addr
,
gfp
))
goto
fail_init
;
transport
->
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
transport
);
return
transport
;
fail_init:
kfree
(
transport
);
fail:
return
NULL
;
}
/* This transport is no longer needed. Free up if possible, or
* delay until it last reference count.
*/
...
...
@@ -155,13 +154,23 @@ void sctp_transport_free(struct sctp_transport *transport)
if
(
del_timer
(
&
transport
->
hb_timer
))
sctp_transport_put
(
transport
);
/* Delete the T3_rtx timer if it's active.
* There is no point in not doing this now and letting
* structure hang around in memory since we know
* the tranport is going away.
*/
if
(
timer_pending
(
&
transport
->
T3_rtx_timer
)
&&
del_timer
(
&
transport
->
T3_rtx_timer
))
sctp_transport_put
(
transport
);
sctp_transport_put
(
transport
);
}
/* Destroy the transport data structure.
* Assumes there are no more users of this structure.
*/
void
sctp_transport_destroy
(
struct
sctp_transport
*
transport
)
static
void
sctp_transport_destroy
(
struct
sctp_transport
*
transport
)
{
SCTP_ASSERT
(
transport
->
dead
,
"Transport is not dead"
,
return
);
...
...
net/sctp/tsnmap.c
View file @
cabbb4de
...
...
@@ -52,29 +52,6 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
int
*
started
,
__u16
*
start
,
int
*
ended
,
__u16
*
end
);
/* Create a new sctp_tsnmap.
* Allocate room to store at least 'len' contiguous TSNs.
*/
struct
sctp_tsnmap
*
sctp_tsnmap_new
(
__u16
len
,
__u32
initial_tsn
,
int
gfp
)
{
struct
sctp_tsnmap
*
retval
;
retval
=
kmalloc
(
sizeof
(
struct
sctp_tsnmap
)
+
sctp_tsnmap_storage_size
(
len
),
gfp
);
if
(
!
retval
)
goto
fail
;
if
(
!
sctp_tsnmap_init
(
retval
,
len
,
initial_tsn
))
goto
fail_map
;
retval
->
malloced
=
1
;
return
retval
;
fail_map:
kfree
(
retval
);
fail:
return
NULL
;
}
/* Initialize a block of memory as a tsnmap. */
struct
sctp_tsnmap
*
sctp_tsnmap_init
(
struct
sctp_tsnmap
*
map
,
__u16
len
,
__u32
initial_tsn
)
...
...
@@ -168,16 +145,9 @@ void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
}
/* Dispose of a tsnmap. */
void
sctp_tsnmap_free
(
struct
sctp_tsnmap
*
map
)
{
if
(
map
->
malloced
)
kfree
(
map
);
}
/* Initialize a Gap Ack Block iterator from memory being provided. */
void
sctp_tsnmap_iter_init
(
const
struct
sctp_tsnmap
*
map
,
struct
sctp_tsnmap_iter
*
iter
)
SCTP_STATIC
void
sctp_tsnmap_iter_init
(
const
struct
sctp_tsnmap
*
map
,
struct
sctp_tsnmap_iter
*
iter
)
{
/* Only start looking one past the Cumulative TSN Ack Point. */
iter
->
start
=
map
->
cumulative_tsn_ack_point
+
1
;
...
...
@@ -186,8 +156,9 @@ void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
/* Get the next Gap Ack Blocks. Returns 0 if there was not another block
* to get.
*/
int
sctp_tsnmap_next_gap_ack
(
const
struct
sctp_tsnmap
*
map
,
struct
sctp_tsnmap_iter
*
iter
,
__u16
*
start
,
__u16
*
end
)
SCTP_STATIC
int
sctp_tsnmap_next_gap_ack
(
const
struct
sctp_tsnmap
*
map
,
struct
sctp_tsnmap_iter
*
iter
,
__u16
*
start
,
__u16
*
end
)
{
int
started
,
ended
;
__u16
_start
,
_end
,
offset
;
...
...
net/sctp/ulpevent.c
View file @
cabbb4de
...
...
@@ -65,8 +65,16 @@ static void sctp_stub_rfree(struct sk_buff *skb)
*/
}
/* Initialize an ULP event from an given skb. */
SCTP_STATIC
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
event
,
int
msg_flags
)
{
memset
(
event
,
0
,
sizeof
(
struct
sctp_ulpevent
));
event
->
msg_flags
=
msg_flags
;
}
/* Create a new sctp_ulpevent. */
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
msg_flags
,
int
gfp
)
SCTP_STATIC
struct
sctp_ulpevent
*
sctp_ulpevent_new
(
int
size
,
int
msg_flags
,
int
gfp
)
{
struct
sctp_ulpevent
*
event
;
struct
sk_buff
*
skb
;
...
...
@@ -84,13 +92,6 @@ struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
return
NULL
;
}
/* Initialize an ULP event from an given skb. */
void
sctp_ulpevent_init
(
struct
sctp_ulpevent
*
event
,
int
msg_flags
)
{
memset
(
event
,
0
,
sizeof
(
struct
sctp_ulpevent
));
event
->
msg_flags
=
msg_flags
;
}
/* Is this a MSG_NOTIFICATION? */
int
sctp_ulpevent_is_notification
(
const
struct
sctp_ulpevent
*
event
)
{
...
...
net/sctp/ulpqueue.c
View file @
cabbb4de
...
...
@@ -56,25 +56,6 @@ static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
/* 1st Level Abstractions */
/* Create a new ULP queue. */
struct
sctp_ulpq
*
sctp_ulpq_new
(
struct
sctp_association
*
asoc
,
int
gfp
)
{
struct
sctp_ulpq
*
ulpq
;
ulpq
=
kmalloc
(
sizeof
(
struct
sctp_ulpq
),
gfp
);
if
(
!
ulpq
)
goto
fail
;
if
(
!
sctp_ulpq_init
(
ulpq
,
asoc
))
goto
fail_init
;
ulpq
->
malloced
=
1
;
return
ulpq
;
fail_init:
kfree
(
ulpq
);
fail:
return
NULL
;
}
/* Initialize a ULP queue from a block of memory. */
struct
sctp_ulpq
*
sctp_ulpq_init
(
struct
sctp_ulpq
*
ulpq
,
struct
sctp_association
*
asoc
)
...
...
@@ -92,7 +73,7 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
/* Flush the reassembly and ordering queues. */
void
sctp_ulpq_flush
(
struct
sctp_ulpq
*
ulpq
)
static
void
sctp_ulpq_flush
(
struct
sctp_ulpq
*
ulpq
)
{
struct
sk_buff
*
skb
;
struct
sctp_ulpevent
*
event
;
...
...
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