Commit 6cf4b403 authored by Jon Grimm's avatar Jon Grimm

Merge

parents 6a074a55 deabf854
...@@ -277,6 +277,7 @@ extern atomic_t sctp_dbg_objcnt_chunk; ...@@ -277,6 +277,7 @@ extern atomic_t sctp_dbg_objcnt_chunk;
extern atomic_t sctp_dbg_objcnt_bind_addr; extern atomic_t sctp_dbg_objcnt_bind_addr;
extern atomic_t sctp_dbg_objcnt_addr; extern atomic_t sctp_dbg_objcnt_addr;
extern atomic_t sctp_dbg_objcnt_ssnmap; extern atomic_t sctp_dbg_objcnt_ssnmap;
extern atomic_t sctp_dbg_objcnt_datamsg;
/* Macros to atomically increment/decrement objcnt counters. */ /* Macros to atomically increment/decrement objcnt counters. */
#define SCTP_DBG_OBJCNT_INC(name) \ #define SCTP_DBG_OBJCNT_INC(name) \
......
...@@ -6,10 +6,6 @@ ...@@ -6,10 +6,6 @@
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation.
*
* These are definitions needed by the state machine. * These are definitions needed by the state machine.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
...@@ -50,7 +46,6 @@ ...@@ -50,7 +46,6 @@
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -209,71 +204,66 @@ __u32 sctp_generate_verification_tag(void); ...@@ -209,71 +204,66 @@ __u32 sctp_generate_verification_tag(void);
void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag); void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
/* Prototypes for chunk-building functions. */ /* Prototypes for chunk-building functions. */
sctp_chunk_t *sctp_make_init(const struct sctp_association *, struct sctp_chunk *sctp_make_init(const struct sctp_association *,
const sctp_bind_addr_t *, const struct sctp_bind_addr *,
int gfp, int vparam_len); int gfp, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *, struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const int gfp, const int gfp,
const int unkparam_len); const int unkparam_len);
sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *, struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *, struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_cwr(const struct sctp_association *, struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
const __u32 lowest_tsn, const __u32 lowest_tsn,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_datafrag(struct sctp_association *, struct sctp_chunk *sctp_make_datafrag(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 *data, int len, const __u8 *data,
__u8 flags, __u16 ssn); __u8 flags, __u16 ssn);
sctp_chunk_t * sctp_make_datafrag_empty(struct sctp_association *, struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 flags, int len, const __u8 flags,
__u16 ssn); __u16 ssn);
sctp_chunk_t *sctp_make_data(struct sctp_association *, struct sctp_chunk *sctp_make_data(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 *data); int len, const __u8 *data);
sctp_chunk_t *sctp_make_data_empty(struct sctp_association *, struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *, int len); const struct sctp_sndrcvinfo *, int len);
sctp_chunk_t *sctp_make_ecne(const struct sctp_association *, struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
const __u32); const __u32);
sctp_chunk_t *sctp_make_sack(const struct sctp_association *); struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc); struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc);
sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc, struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *, struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
const sctp_chunk_t *); const struct sctp_chunk *);
void sctp_init_cause(sctp_chunk_t *, __u16 cause, const void *, size_t); void sctp_init_cause(struct sctp_chunk *, __u16 cause, const void *, size_t);
sctp_chunk_t *sctp_make_abort(const struct sctp_association *, struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const size_t hint); const size_t hint);
sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *, struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
__u32 tsn); __u32 tsn);
sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *, struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const struct msghdr *); const struct msghdr *);
sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *, struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *, const struct sctp_transport *,
const void *payload, const void *payload,
const size_t paylen); const size_t paylen);
sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *, struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const void *payload, const void *payload,
const size_t paylen); const size_t paylen);
sctp_chunk_t *sctp_make_op_error(const struct sctp_association *, struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
const sctp_chunk_t *chunk, const struct sctp_chunk *chunk,
__u16 cause_code, __u16 cause_code,
const void *payload, const void *payload,
size_t paylen); size_t paylen);
void sctp_chunk_assign_tsn(sctp_chunk_t *); void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(sctp_chunk_t *); void sctp_chunk_assign_ssn(struct sctp_chunk *);
int sctp_datachunks_from_user(struct sctp_association *,
const struct sctp_sndrcvinfo *,
struct msghdr *, int len,
struct sk_buff_head *);
/* Prototypes for statetable processing. */ /* Prototypes for statetable processing. */
...@@ -306,12 +296,12 @@ sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -306,12 +296,12 @@ sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *); int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
void sctp_do_TSNdup(struct sctp_association *, sctp_chunk_t *, long gap); void sctp_do_TSNdup(struct sctp_association *, struct sctp_chunk *, long gap);
void sctp_generate_t3_rtx_event(unsigned long peer); void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer); void sctp_generate_heartbeat_event(unsigned long peer);
sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *); sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *);
struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *, struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *,
const struct sctp_association *, const struct sctp_association *,
struct sctp_chunk *chunk, struct sctp_chunk *chunk,
...@@ -327,15 +317,15 @@ sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *, ...@@ -327,15 +317,15 @@ sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
const __u8 *, int addrs_len); const __u8 *, int addrs_len);
struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *, struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
const struct sctp_association *, const struct sctp_association *,
sctp_chunk_t *, int gfp, int *err, struct sctp_chunk *, int gfp, int *err,
sctp_chunk_t **err_chk_p); struct sctp_chunk **err_chk_p);
int sctp_addip_addr_config(struct sctp_association *, sctp_param_t, int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
struct sockaddr_storage*, int); struct sockaddr_storage*, int);
void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
const struct sctp_association *asoc, const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands, sctp_cmd_seq_t *commands,
sctp_chunk_t *err_chunk); struct sctp_chunk *err_chunk);
/* 3rd level prototypes */ /* 3rd level prototypes */
__u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tag(const struct sctp_endpoint *);
...@@ -361,7 +351,7 @@ extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES]; ...@@ -361,7 +351,7 @@ extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
/* Get the size of a DATA chunk payload. */ /* Get the size of a DATA chunk payload. */
static inline __u16 sctp_data_size(sctp_chunk_t *chunk) static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
{ {
__u16 size; __u16 size;
...@@ -449,7 +439,7 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a ...@@ -449,7 +439,7 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a
* tag and the T bit is set in the Chunk Flags. * tag and the T bit is set in the Chunk Flags.
*/ */
static inline int static inline int
sctp_vtag_verify_either(const sctp_chunk_t *chunk, sctp_vtag_verify_either(const struct sctp_chunk *chunk,
const struct sctp_association *asoc) const struct sctp_association *asoc)
{ {
/* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2 /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
......
...@@ -70,7 +70,6 @@ union sctp_addr { ...@@ -70,7 +70,6 @@ union sctp_addr {
struct sockaddr sa; struct sockaddr sa;
}; };
/* Forward declarations for data structures. */ /* Forward declarations for data structures. */
struct sctp_protocol; struct sctp_protocol;
struct sctp_endpoint; struct sctp_endpoint;
...@@ -86,8 +85,6 @@ struct sctp_opt; ...@@ -86,8 +85,6 @@ struct sctp_opt;
struct sctp_ep_common; struct sctp_ep_common;
struct sctp_ssnmap; struct sctp_ssnmap;
typedef struct sctp_chunk sctp_chunk_t;
typedef struct sctp_bind_addr sctp_bind_addr_t;
#include <net/sctp/tsnmap.h> #include <net/sctp/tsnmap.h>
#include <net/sctp/ulpevent.h> #include <net/sctp/ulpevent.h>
...@@ -450,6 +447,29 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) ...@@ -450,6 +447,29 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
return stream->ssn[id]++; return stream->ssn[id]++;
} }
/* Structure to track chunk fragments that have been acked, but peer
* fragments of the same message have not.
*/
struct sctp_datamsg {
/* Chunks waiting to be submitted to lower layer. */
struct list_head chunks;
/* Chunks that have been transmitted. */
struct list_head track;
/* Reference counting. */
atomic_t refcnt;
/* Have the SEND_FAILED notifications been done. */
__u8 notify_done;
};
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 *);
/* RFC2960 1.4 Key Terms /* RFC2960 1.4 Key Terms
* *
...@@ -464,9 +484,10 @@ struct sctp_chunk { ...@@ -464,9 +484,10 @@ struct sctp_chunk {
* three elements of struct sk_buff. This allows us to reuse * three elements of struct sk_buff. This allows us to reuse
* all the skb_* queue management functions. * all the skb_* queue management functions.
*/ */
sctp_chunk_t *next; struct sctp_chunk *next;
sctp_chunk_t *prev; struct sctp_chunk *prev;
struct sk_buff_head *list; struct sk_buff_head *list;
atomic_t refcnt;
/* This is our link to the per-transport transmitted list. */ /* This is our link to the per-transport transmitted list. */
struct list_head transmitted_list; struct list_head transmitted_list;
...@@ -522,13 +543,13 @@ struct sctp_chunk { ...@@ -522,13 +543,13 @@ struct sctp_chunk {
unsigned long sent_at; unsigned long sent_at;
__u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */ __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */
__u8 num_times_sent; /* How man times did we send this? */ __u8 resent; /* Has this chunk ever been retransmitted. */
__u8 has_tsn; /* Does this chunk have a TSN yet? */ __u8 has_tsn; /* Does this chunk have a TSN yet? */
__u8 has_ssn; /* Does this chunk have a SSN yet? */ __u8 has_ssn; /* Does this chunk have a SSN yet? */
__u8 singleton; /* Was this the only chunk in the packet? */ __u8 singleton; /* Was this the only chunk in the packet? */
__u8 end_of_packet; /* Was this the last chunk in the packet? */ __u8 end_of_packet; /* Was this the last chunk in the packet? */
__u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */
__u8 pdiscard; /* Discard the whole packet now? */ __u8 pdiscard; /* Discard the whole packet now? */
__u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */
__u8 fast_retransmit; /* Is this chunk fast retransmitted? */ __u8 fast_retransmit; /* Is this chunk fast retransmitted? */
__u8 tsn_missing_report; /* Data chunk missing counter. */ __u8 tsn_missing_report; /* Data chunk missing counter. */
...@@ -538,6 +559,9 @@ struct sctp_chunk { ...@@ -538,6 +559,9 @@ struct sctp_chunk {
/* Destination address for this chunk. */ /* Destination address for this chunk. */
union sctp_addr dest; union sctp_addr dest;
/* For outbound message, track all fragments for SEND_FAILED. */
struct sctp_datamsg *msg;
/* For an inbound chunk, this tells us where it came from. /* For an inbound chunk, this tells us where it came from.
* For an outbound chunk, it tells us where we'd like it to * For an outbound chunk, it tells us where we'd like it to
* go. It is NULL if we have no preference. * go. It is NULL if we have no preference.
...@@ -545,14 +569,20 @@ struct sctp_chunk { ...@@ -545,14 +569,20 @@ struct sctp_chunk {
struct sctp_transport *transport; struct sctp_transport *transport;
}; };
sctp_chunk_t *sctp_make_chunk(const struct sctp_association *, __u8 type, void sctp_chunk_hold(struct sctp_chunk *);
__u8 flags, int size); void sctp_chunk_put(struct sctp_chunk *);
void sctp_free_chunk(sctp_chunk_t *); int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data); struct iovec *data);
sctp_chunk_t *sctp_chunkify(struct sk_buff *, const struct sctp_association *, struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
struct sock *); __u8 flags, int size);
void sctp_init_addrs(sctp_chunk_t *, union sctp_addr *, union sctp_addr *); void sctp_chunk_free(struct sctp_chunk *);
const union sctp_addr *sctp_source(const sctp_chunk_t *chunk); void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
struct sctp_chunk *sctp_chunkify(struct sk_buff *,
const struct sctp_association *,
struct sock *);
void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
union sctp_addr *);
const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
/* This is a structure for holding either an IPv6 or an IPv4 address. */ /* This is a structure for holding either an IPv6 or an IPv4 address. */
/* sin_family -- AF_INET or AF_INET6 /* sin_family -- AF_INET or AF_INET6
...@@ -564,7 +594,7 @@ struct sockaddr_storage_list { ...@@ -564,7 +594,7 @@ struct sockaddr_storage_list {
union sctp_addr a; union sctp_addr a;
}; };
typedef sctp_chunk_t *(sctp_packet_phandler_t)(struct sctp_association *); typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
/* This structure holds lists of chunks as we are assembling for /* This structure holds lists of chunks as we are assembling for
* transmission. * transmission.
...@@ -621,7 +651,7 @@ typedef struct sctp_packet *(sctp_outq_ohandler_config_t) ...@@ -621,7 +651,7 @@ typedef struct sctp_packet *(sctp_outq_ohandler_config_t)
int ecn_capable, int ecn_capable,
sctp_packet_phandler_t *get_prepend_chunk); sctp_packet_phandler_t *get_prepend_chunk);
typedef sctp_xmit_t (sctp_outq_ohandler_t)(struct sctp_packet *, typedef sctp_xmit_t (sctp_outq_ohandler_t)(struct sctp_packet *,
sctp_chunk_t *); struct sctp_chunk *);
typedef int (sctp_outq_ohandler_force_t)(struct sctp_packet *); typedef int (sctp_outq_ohandler_force_t)(struct sctp_packet *);
sctp_outq_ohandler_init_t sctp_packet_init; sctp_outq_ohandler_init_t sctp_packet_init;
...@@ -832,7 +862,7 @@ struct sctp_inq { ...@@ -832,7 +862,7 @@ struct sctp_inq {
/* This is the packet which is currently off the in queue and is /* This is the packet which is currently off the in queue and is
* being worked on through the inbound chunk processing. * being worked on through the inbound chunk processing.
*/ */
sctp_chunk_t *in_progress; struct sctp_chunk *in_progress;
/* This is the delayed task to finish delivering inbound /* This is the delayed task to finish delivering inbound
* messages. * messages.
...@@ -845,7 +875,7 @@ struct sctp_inq { ...@@ -845,7 +875,7 @@ struct sctp_inq {
struct sctp_inq *sctp_inq_new(void); struct sctp_inq *sctp_inq_new(void);
void sctp_inq_init(struct sctp_inq *); void sctp_inq_init(struct sctp_inq *);
void sctp_inq_free(struct sctp_inq *); void sctp_inq_free(struct sctp_inq *);
void sctp_inq_push(struct sctp_inq *, sctp_chunk_t *packet); void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
struct sctp_chunk *sctp_inq_pop(struct sctp_inq *); struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *); void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
...@@ -916,7 +946,7 @@ struct sctp_outq *sctp_outq_new(struct sctp_association *); ...@@ -916,7 +946,7 @@ struct sctp_outq *sctp_outq_new(struct sctp_association *);
void sctp_outq_init(struct sctp_association *, struct sctp_outq *); void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
void sctp_outq_teardown(struct sctp_outq *); void sctp_outq_teardown(struct sctp_outq *);
void sctp_outq_free(struct sctp_outq*); void sctp_outq_free(struct sctp_outq*);
int sctp_outq_tail(struct sctp_outq *, sctp_chunk_t *chunk); int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
int sctp_outq_flush(struct sctp_outq *, int); int sctp_outq_flush(struct sctp_outq *, int);
int sctp_outq_sack(struct sctp_outq *, sctp_sackhdr_t *); int sctp_outq_sack(struct sctp_outq *, sctp_sackhdr_t *);
int sctp_outq_is_empty(const struct sctp_outq *); int sctp_outq_is_empty(const struct sctp_outq *);
...@@ -953,15 +983,16 @@ struct sctp_bind_addr { ...@@ -953,15 +983,16 @@ struct sctp_bind_addr {
int malloced; /* Are we kfree()able? */ int malloced; /* Are we kfree()able? */
}; };
sctp_bind_addr_t *sctp_bind_addr_new(int gfp_mask); struct sctp_bind_addr *sctp_bind_addr_new(int gfp_mask);
void sctp_bind_addr_init(sctp_bind_addr_t *, __u16 port); void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
void sctp_bind_addr_free(sctp_bind_addr_t *); void sctp_bind_addr_free(struct sctp_bind_addr *);
int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, int gfp,int flags); sctp_scope_t scope, int gfp,int flags);
int sctp_add_bind_addr(sctp_bind_addr_t *, union sctp_addr *, int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
int gfp); int gfp);
int sctp_del_bind_addr(sctp_bind_addr_t *, union sctp_addr *); int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(sctp_bind_addr_t *, const union sctp_addr *, int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_opt *); struct sctp_opt *);
union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
int *addrs_len, int gfp); int *addrs_len, int gfp);
...@@ -1025,7 +1056,7 @@ struct sctp_ep_common { ...@@ -1025,7 +1056,7 @@ struct sctp_ep_common {
* bind_addr.port is our shared port number. * bind_addr.port is our shared port number.
* bind_addr.address_list is our set of local IP addresses. * bind_addr.address_list is our set of local IP addresses.
*/ */
sctp_bind_addr_t bind_addr; struct sctp_bind_addr bind_addr;
/* Protection during address list comparisons. */ /* Protection during address list comparisons. */
rwlock_t addr_lock; rwlock_t addr_lock;
...@@ -1477,7 +1508,7 @@ struct sctp_association { ...@@ -1477,7 +1508,7 @@ struct sctp_association {
* [This is our one-and-only-one ASCONF in flight. If we do * [This is our one-and-only-one ASCONF in flight. If we do
* not have an ASCONF in flight, this is NULL.] * not have an ASCONF in flight, this is NULL.]
*/ */
sctp_chunk_t *addip_last_asconf; struct sctp_chunk *addip_last_asconf;
/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.
* *
...@@ -1492,7 +1523,7 @@ struct sctp_association { ...@@ -1492,7 +1523,7 @@ struct sctp_association {
* [This is our saved ASCONF-ACK. We invalidate it when a new * [This is our saved ASCONF-ACK. We invalidate it when a new
* ASCONF serial number arrives.] * ASCONF serial number arrives.]
*/ */
sctp_chunk_t *addip_last_asconf_ack; struct sctp_chunk *addip_last_asconf_ack;
/* These ASCONF chunks are waiting to be sent. /* These ASCONF chunks are waiting to be sent.
* *
...@@ -1614,8 +1645,8 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *, ...@@ -1614,8 +1645,8 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
int sctp_cmp_addr_exact(const union sctp_addr *ss1, int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2); const union sctp_addr *ss2);
sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc); struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
sctp_chunk_t *sctp_get_no_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. */ /* A convenience structure to parse out SCTP specific CMSGs. */
typedef struct sctp_cmsgs { typedef struct sctp_cmsgs {
......
...@@ -6,7 +6,7 @@ obj-$(CONFIG_IP_SCTP) += sctp.o ...@@ -6,7 +6,7 @@ obj-$(CONFIG_IP_SCTP) += sctp.o
sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
protocol.o endpointola.o associola.o \ protocol.o endpointola.o associola.o \
transport.o sm_make_chunk.o ulpevent.o \ transport.o chunk.o sm_make_chunk.o ulpevent.o \
inqueue.o outqueue.o ulpqueue.o command.o \ inqueue.o outqueue.o ulpqueue.o command.o \
tsnmap.o bind_addr.o socket.o primitive.o \ tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o debug.o ssnmap.o proc.o output.o input.o debug.o ssnmap.o proc.o
......
...@@ -664,7 +664,7 @@ int sctp_cmp_addr_exact(const union sctp_addr *ss1, ...@@ -664,7 +664,7 @@ int sctp_cmp_addr_exact(const union sctp_addr *ss1,
* Note: We are sly and return a shared, prealloced chunk. FIXME: * Note: We are sly and return a shared, prealloced chunk. FIXME:
* No we don't, but we could/should. * No we don't, but we could/should.
*/ */
sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc) struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc)
{ {
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
...@@ -682,7 +682,7 @@ sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc) ...@@ -682,7 +682,7 @@ sctp_chunk_t *sctp_get_ecne_prepend(struct sctp_association *asoc)
/* Use this function for the packet prepend callback when no ECNE /* Use this function for the packet prepend callback when no ECNE
* packet is desired (e.g. some packets don't like to be bundled). * packet is desired (e.g. some packets don't like to be bundled).
*/ */
sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc) struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc)
{ {
return NULL; return NULL;
} }
...@@ -690,13 +690,14 @@ sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc) ...@@ -690,13 +690,14 @@ sctp_chunk_t *sctp_get_no_prepend(struct sctp_association *asoc)
/* /*
* Find which transport this TSN was sent on. * Find which transport this TSN was sent on.
*/ */
struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u32 tsn) struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
__u32 tsn)
{ {
struct sctp_transport *active; struct sctp_transport *active;
struct sctp_transport *match; struct sctp_transport *match;
struct list_head *entry, *pos; struct list_head *entry, *pos;
struct sctp_transport *transport; struct sctp_transport *transport;
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
__u32 key = htonl(tsn); __u32 key = htonl(tsn);
match = NULL; match = NULL;
...@@ -719,7 +720,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u3 ...@@ -719,7 +720,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u3
active = asoc->peer.active_path; active = asoc->peer.active_path;
list_for_each(entry, &active->transmitted) { list_for_each(entry, &active->transmitted) {
chunk = list_entry(entry, sctp_chunk_t, transmitted_list); chunk = list_entry(entry, struct sctp_chunk, transmitted_list);
if (key == chunk->subh.data_hdr->tsn) { if (key == chunk->subh.data_hdr->tsn) {
match = active; match = active;
...@@ -734,7 +735,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u3 ...@@ -734,7 +735,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, __u3
if (transport == active) if (transport == active)
break; break;
list_for_each(entry, &transport->transmitted) { list_for_each(entry, &transport->transmitted) {
chunk = list_entry(entry, sctp_chunk_t, chunk = list_entry(entry, struct sctp_chunk,
transmitted_list); transmitted_list);
if (key == chunk->subh.data_hdr->tsn) { if (key == chunk->subh.data_hdr->tsn) {
match = transport; match = transport;
...@@ -776,7 +777,7 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, ...@@ -776,7 +777,7 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
static void sctp_assoc_bh_rcv(struct sctp_association *asoc) static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
{ {
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
struct sock *sk; struct sock *sk;
struct sctp_inq *inqueue; struct sctp_inq *inqueue;
int state, subtype; int state, subtype;
...@@ -852,7 +853,8 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk) ...@@ -852,7 +853,8 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
} }
/* Update an association (possibly from unexpected COOKIE-ECHO processing). */ /* Update an association (possibly from unexpected COOKIE-ECHO processing). */
void sctp_assoc_update(struct sctp_association *asoc, struct sctp_association *new) void sctp_assoc_update(struct sctp_association *asoc,
struct sctp_association *new)
{ {
/* Copy in new parameters of peer. */ /* Copy in new parameters of peer. */
asoc->c = new->c; asoc->c = new->c;
...@@ -946,7 +948,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) ...@@ -946,7 +948,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
} }
/* Choose the transport for sending a SHUTDOWN packet. */ /* Choose the transport for sending a SHUTDOWN packet. */
struct sctp_transport *sctp_assoc_choose_shutdown_transport(struct sctp_association *asoc) struct sctp_transport *sctp_assoc_choose_shutdown_transport(
struct sctp_association *asoc)
{ {
/* If this is the first time SHUTDOWN is sent, use the active path, /* If this is the first time SHUTDOWN is sent, use the active path,
* else use the retran path. If the last SHUTDOWN was sent over the * else use the retran path. If the last SHUTDOWN was sent over the
...@@ -1011,7 +1014,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc) ...@@ -1011,7 +1014,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
/* Increase asoc's rwnd by len and send any window update SACK if needed. */ /* Increase asoc's rwnd by len and send any window update SACK if needed. */
void sctp_assoc_rwnd_increase(struct sctp_association *asoc, int len) void sctp_assoc_rwnd_increase(struct sctp_association *asoc, int len)
{ {
sctp_chunk_t *sack; struct sctp_chunk *sack;
struct timer_list *timer; struct timer_list *timer;
if (asoc->rwnd_over) { if (asoc->rwnd_over) {
......
...@@ -52,16 +52,17 @@ ...@@ -52,16 +52,17 @@
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */ /* Forward declarations for internal helpers. */
static int sctp_copy_one_addr(sctp_bind_addr_t *, union sctp_addr *, static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
sctp_scope_t scope, int gfp, int flags); sctp_scope_t scope, int gfp, int flags);
static void sctp_bind_addr_clean(sctp_bind_addr_t *); static void sctp_bind_addr_clean(struct sctp_bind_addr *);
/* First Level Abstractions. */ /* First Level Abstractions. */
/* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses
* in 'src' which have a broader scope than 'scope'. * in 'src' which have a broader scope than 'scope'.
*/ */
int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, int gfp, int flags) sctp_scope_t scope, int gfp, int flags)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
...@@ -104,11 +105,11 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, ...@@ -104,11 +105,11 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
} }
/* Create a new SCTP_bind_addr from nothing. */ /* Create a new SCTP_bind_addr from nothing. */
sctp_bind_addr_t *sctp_bind_addr_new(int gfp) struct sctp_bind_addr *sctp_bind_addr_new(int gfp)
{ {
sctp_bind_addr_t *retval; struct sctp_bind_addr *retval;
retval = t_new(sctp_bind_addr_t, gfp); retval = t_new(struct sctp_bind_addr, gfp);
if (!retval) if (!retval)
goto nomem; goto nomem;
...@@ -123,7 +124,7 @@ sctp_bind_addr_t *sctp_bind_addr_new(int gfp) ...@@ -123,7 +124,7 @@ sctp_bind_addr_t *sctp_bind_addr_new(int gfp)
/* Initialize the SCTP_bind_addr structure for either an endpoint or /* Initialize the SCTP_bind_addr structure for either an endpoint or
* an association. * an association.
*/ */
void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port) void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
{ {
bp->malloced = 0; bp->malloced = 0;
...@@ -132,7 +133,7 @@ void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port) ...@@ -132,7 +133,7 @@ void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port)
} }
/* Dispose of the address list. */ /* Dispose of the address list. */
static void sctp_bind_addr_clean(sctp_bind_addr_t *bp) static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
struct list_head *pos, *temp; struct list_head *pos, *temp;
...@@ -147,7 +148,7 @@ static void sctp_bind_addr_clean(sctp_bind_addr_t *bp) ...@@ -147,7 +148,7 @@ static void sctp_bind_addr_clean(sctp_bind_addr_t *bp)
} }
/* Dispose of an SCTP_bind_addr structure */ /* Dispose of an SCTP_bind_addr structure */
void sctp_bind_addr_free(sctp_bind_addr_t *bp) void sctp_bind_addr_free(struct sctp_bind_addr *bp)
{ {
/* Empty the bind address list. */ /* Empty the bind address list. */
sctp_bind_addr_clean(bp); sctp_bind_addr_clean(bp);
...@@ -159,7 +160,7 @@ void sctp_bind_addr_free(sctp_bind_addr_t *bp) ...@@ -159,7 +160,7 @@ void sctp_bind_addr_free(sctp_bind_addr_t *bp)
} }
/* Add an address to the bind address list in the SCTP_bind_addr structure. */ /* Add an address to the bind address list in the SCTP_bind_addr structure. */
int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new, int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
int gfp) int gfp)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
...@@ -187,7 +188,7 @@ int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new, ...@@ -187,7 +188,7 @@ int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new,
/* Delete an address from the bind address list in the SCTP_bind_addr /* Delete an address from the bind address list in the SCTP_bind_addr
* structure. * structure.
*/ */
int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
{ {
struct list_head *pos, *temp; struct list_head *pos, *temp;
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
...@@ -212,7 +213,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) ...@@ -212,7 +213,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr)
* *
* The second argument is the return value for the length. * The second argument is the return value for the length.
*/ */
union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
int *addrs_len, int gfp) int *addrs_len, int gfp)
{ {
union sctp_params addrparms; union sctp_params addrparms;
...@@ -261,7 +262,7 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, ...@@ -261,7 +262,7 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
* Create an address list out of the raw address list format (IPv4 and IPv6 * Create an address list out of the raw address list format (IPv4 and IPv6
* address parameters). * address parameters).
*/ */
int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
int addrs_len, __u16 port, int gfp) int addrs_len, __u16 port, int gfp)
{ {
sctp_addr_param_t *rawaddr; sctp_addr_param_t *rawaddr;
...@@ -307,7 +308,8 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, ...@@ -307,7 +308,8 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
********************************************************************/ ********************************************************************/
/* Does this contain a specified address? Allow wildcarding. */ /* Does this contain a specified address? Allow wildcarding. */
int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, int sctp_bind_addr_match(struct sctp_bind_addr *bp,
const union sctp_addr *addr,
struct sctp_opt *opt) struct sctp_opt *opt)
{ {
struct sockaddr_storage_list *laddr; struct sockaddr_storage_list *laddr;
...@@ -323,7 +325,8 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, ...@@ -323,7 +325,8 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
} }
/* Copy out addresses from the global local address list. */ /* Copy out addresses from the global local address list. */
static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr, static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
union sctp_addr *addr,
sctp_scope_t scope, int gfp, int flags) sctp_scope_t scope, int gfp, int flags)
{ {
struct sctp_protocol *proto = sctp_get_protocol(); struct sctp_protocol *proto = sctp_get_protocol();
......
/* SCTP kernel reference Implementation
* Copyright (c) 2003 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
* This file contains the code relating the the chunk abstraction.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* This file is mostly in anticipation of future work, but initially
* populate with fragment tracking for an outbound message.
*/
/* Initialize datamsg from memory. */
void sctp_datamsg_init(struct sctp_datamsg *msg)
{
atomic_set(&msg->refcnt, 1);
msg->notify_done = 0;
INIT_LIST_HEAD(&msg->chunks);
INIT_LIST_HEAD(&msg->track);
}
/* Allocate and initialize datamsg. */
struct sctp_datamsg *sctp_datamsg_new(int gfp)
{
struct sctp_datamsg *msg;
msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
if (msg)
sctp_datamsg_init(msg);
SCTP_DBG_OBJCNT_INC(datamsg);
return msg;
}
/* Final destructruction of datamsg memory. */
static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
{
struct list_head *pos, *temp;
struct sctp_chunk *chunk;
/* Release all references, if there are any left. */
list_for_each_safe(pos, temp, &msg->track) {
list_del(pos);
chunk = list_entry(pos, struct sctp_chunk, frag_list);
sctp_chunk_put(chunk);
}
SCTP_DBG_OBJCNT_DEC(datamsg);
kfree(msg);
}
/* Hold a reference. */
void sctp_datamsg_hold(struct sctp_datamsg *msg)
{
atomic_inc(&msg->refcnt);
}
/* Release a reference. */
void sctp_datamsg_put(struct sctp_datamsg *msg)
{
if (atomic_dec_and_test(&msg->refcnt))
sctp_datamsg_destroy(msg);
}
/* Free a message. Really just give up a reference, the
* really free happens in sctp_datamsg_destroy().
*/
void sctp_datamsg_free(struct sctp_datamsg *msg)
{
sctp_datamsg_put(msg);
}
/* Hold on to all the fragments until all chunks have been sent. */
void sctp_datamsg_track(struct sctp_chunk *chunk)
{
sctp_chunk_hold(chunk);
list_add_tail(&chunk->frag_list, &chunk->msg->track);
}
/* Assign a chunk to this datamsg. */
void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
{
sctp_datamsg_hold(msg);
chunk->msg = msg;
}
/* A data chunk can have a maximum payload of (2^16 - 20). Break
* down any such message into smaller chunks. Opportunistically, fragment
* the chunks down to the current MTU constraints. We may get refragmented
* later if the PMTU changes, but it is _much better_ to fragment immediately
* with a reasonable guess than always doing our fragmentation on the
* soft-interrupt.
*/
struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct sctp_sndrcvinfo *sinfo,
struct msghdr *msgh, int msg_len)
{
int max, whole, i, offset, over, err;
int len, first_len;
struct sctp_chunk *chunk;
struct sctp_datamsg *msg;
struct list_head *pos, *temp;
__u8 frag;
msg = sctp_datamsg_new(GFP_KERNEL);
if (!msg)
return NULL;
/* What is a reasonable fragmentation point right now? */
max = asoc->pmtu;
if (max < SCTP_MIN_PMTU)
max = SCTP_MIN_PMTU;
max -= SCTP_IP_OVERHEAD;
/* Make sure not beyond maximum chunk size. */
if (max > SCTP_MAX_CHUNK_LEN)
max = SCTP_MAX_CHUNK_LEN;
/* Subtract out the overhead of a data chunk header. */
max -= sizeof(struct sctp_data_chunk);
whole = 0;
first_len = max;
/* Encourage Cookie-ECHO bundling. */
if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);
/* Account for the DATA to be bundled with the COOKIE-ECHO. */
if (whole) {
first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
msg_len -= first_len;
whole = 1;
}
}
/* How many full sized? How many bytes leftover? */
whole += msg_len / max;
over = msg_len % max;
offset = 0;
if (whole && over)
SCTP_INC_STATS_USER(SctpFragUsrMsgs);
/* Create chunks for all the full sized DATA chunks. */
for (i=0, len=first_len; i < whole; i++) {
frag = SCTP_DATA_MIDDLE_FRAG;
if (0 == i)
frag |= SCTP_DATA_FIRST_FRAG;
if ((i == (whole - 1)) && !over)
frag |= SCTP_DATA_LAST_FRAG;
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
if (!chunk)
goto errout;
err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
if (err < 0)
goto errout;
offset += len;
/* Put the chunk->skb back into the form expected by send. */
__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
- (__u8 *)chunk->skb->data);
sctp_datamsg_assign(msg, chunk);
list_add_tail(&chunk->frag_list, &msg->chunks);
/* The first chunk, the first chunk was likely short
* to allow bundling, so reset to full size.
*/
if (0 == i)
len = max;
}
/* .. now the leftover bytes. */
if (over) {
if (!whole)
frag = SCTP_DATA_NOT_FRAG;
else
frag = SCTP_DATA_LAST_FRAG;
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
if (!chunk)
goto errout;
err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
/* Put the chunk->skb back into the form expected by send. */
__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
- (__u8 *)chunk->skb->data);
if (err < 0)
goto errout;
sctp_datamsg_assign(msg, chunk);
list_add_tail(&chunk->frag_list, &msg->chunks);
}
return msg;
errout:
list_for_each_safe(pos, temp, &msg->chunks) {
list_del(pos);
chunk = list_entry(pos, struct sctp_chunk, frag_list);
sctp_chunk_free(chunk);
}
sctp_datamsg_free(msg);
return NULL;
}
...@@ -315,7 +315,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, ...@@ -315,7 +315,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
{ {
struct list_head *pos; struct list_head *pos;
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
sctp_read_lock(&ep->base.addr_lock); sctp_read_lock(&ep->base.addr_lock);
bp = &ep->base.bind_addr; bp = &ep->base.bind_addr;
...@@ -339,7 +339,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep) ...@@ -339,7 +339,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
struct sctp_association *asoc; struct sctp_association *asoc;
struct sock *sk; struct sock *sk;
struct sctp_transport *transport; struct sctp_transport *transport;
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
struct sctp_inq *inqueue; struct sctp_inq *inqueue;
sctp_subtype_t subtype; sctp_subtype_t subtype;
sctp_state_t state; sctp_state_t state;
......
...@@ -106,7 +106,7 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -106,7 +106,7 @@ int sctp_rcv(struct sk_buff *skb)
struct sctp_endpoint *ep = NULL; struct sctp_endpoint *ep = NULL;
struct sctp_ep_common *rcvr; struct sctp_ep_common *rcvr;
struct sctp_transport *transport = NULL; struct sctp_transport *transport = NULL;
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
struct sctphdr *sh; struct sctphdr *sh;
union sctp_addr src; union sctp_addr src;
union sctp_addr dest; union sctp_addr dest;
...@@ -250,13 +250,13 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -250,13 +250,13 @@ int sctp_rcv(struct sk_buff *skb)
*/ */
int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{ {
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
struct sctp_inq *inqueue; struct sctp_inq *inqueue;
/* One day chunk will live inside the skb, but for /* One day chunk will live inside the skb, but for
* now this works. * now this works.
*/ */
chunk = (sctp_chunk_t *) skb; chunk = (struct sctp_chunk *) skb;
inqueue = &chunk->rcvr->inqueue; inqueue = &chunk->rcvr->inqueue;
sctp_inq_push(inqueue, chunk); sctp_inq_push(inqueue, chunk);
......
...@@ -75,17 +75,17 @@ struct sctp_inq *sctp_inq_new(void) ...@@ -75,17 +75,17 @@ struct sctp_inq *sctp_inq_new(void)
/* Release the memory associated with an SCTP inqueue. */ /* Release the memory associated with an SCTP inqueue. */
void sctp_inq_free(struct sctp_inq *queue) void sctp_inq_free(struct sctp_inq *queue)
{ {
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
/* Empty the queue. */ /* Empty the queue. */
while ((chunk = (sctp_chunk_t *) skb_dequeue(&queue->in))) while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)))
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
/* If there is a packet which is currently being worked on, /* If there is a packet which is currently being worked on,
* free it as well. * free it as well.
*/ */
if (queue->in_progress) if (queue->in_progress)
sctp_free_chunk(queue->in_progress); sctp_chunk_free(queue->in_progress);
if (queue->malloced) { if (queue->malloced) {
/* Dump the master memory segment. */ /* Dump the master memory segment. */
...@@ -96,7 +96,7 @@ void sctp_inq_free(struct sctp_inq *queue) ...@@ -96,7 +96,7 @@ void sctp_inq_free(struct sctp_inq *queue)
/* Put a new packet in an SCTP inqueue. /* Put a new packet in an SCTP inqueue.
* We assume that packet->sctp_hdr is set and in host byte order. * We assume that packet->sctp_hdr is set and in host byte order.
*/ */
void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet) void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet)
{ {
/* Directly call the packet handling routine. */ /* Directly call the packet handling routine. */
...@@ -114,9 +114,9 @@ void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet) ...@@ -114,9 +114,9 @@ void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet)
* WARNING: If you need to put the chunk on another queue, you need to * WARNING: If you need to put the chunk on another queue, you need to
* make a shallow copy (clone) of it. * make a shallow copy (clone) of it.
*/ */
sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue) struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
{ {
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
sctp_chunkhdr_t *ch = NULL; sctp_chunkhdr_t *ch = NULL;
/* The assumption is that we are safe to process the chunks /* The assumption is that we are safe to process the chunks
...@@ -130,7 +130,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue) ...@@ -130,7 +130,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue)
if (chunk->singleton || if (chunk->singleton ||
chunk->end_of_packet || chunk->end_of_packet ||
chunk->pdiscard) { chunk->pdiscard) {
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
chunk = queue->in_progress = NULL; chunk = queue->in_progress = NULL;
} else { } else {
/* Nothing to do. Next chunk in the packet, please. */ /* Nothing to do. Next chunk in the packet, please. */
...@@ -149,7 +149,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue) ...@@ -149,7 +149,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue)
return NULL; return NULL;
chunk = queue->in_progress = chunk = queue->in_progress =
(sctp_chunk_t *) skb_dequeue(&queue->in); (struct sctp_chunk *) skb_dequeue(&queue->in);
/* This is the first chunk in the packet. */ /* This is the first chunk in the packet. */
chunk->singleton = 1; chunk->singleton = 1;
......
...@@ -246,7 +246,7 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, ...@@ -246,7 +246,7 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst, void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
union sctp_addr *daddr, union sctp_addr *saddr) union sctp_addr *daddr, union sctp_addr *saddr)
{ {
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
rwlock_t *addr_lock; rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr; struct sockaddr_storage_list *laddr;
struct list_head *pos; struct list_head *pos;
......
...@@ -55,6 +55,7 @@ SCTP_DBG_OBJCNT(bind_addr); ...@@ -55,6 +55,7 @@ SCTP_DBG_OBJCNT(bind_addr);
SCTP_DBG_OBJCNT(chunk); SCTP_DBG_OBJCNT(chunk);
SCTP_DBG_OBJCNT(addr); SCTP_DBG_OBJCNT(addr);
SCTP_DBG_OBJCNT(ssnmap); SCTP_DBG_OBJCNT(ssnmap);
SCTP_DBG_OBJCNT(datamsg);
/* An array to make it easy to pretty print the debug information /* An array to make it easy to pretty print the debug information
* to the proc fs. * to the proc fs.
...@@ -68,6 +69,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = { ...@@ -68,6 +69,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
SCTP_DBG_OBJCNT_ENTRY(bind_addr), SCTP_DBG_OBJCNT_ENTRY(bind_addr),
SCTP_DBG_OBJCNT_ENTRY(addr), SCTP_DBG_OBJCNT_ENTRY(addr),
SCTP_DBG_OBJCNT_ENTRY(ssnmap), SCTP_DBG_OBJCNT_ENTRY(ssnmap),
SCTP_DBG_OBJCNT_ENTRY(datamsg),
}; };
/* Callback from procfs to read out objcount information. /* Callback from procfs to read out objcount information.
......
...@@ -114,7 +114,7 @@ void sctp_packet_free(struct sctp_packet *packet) ...@@ -114,7 +114,7 @@ void sctp_packet_free(struct sctp_packet *packet)
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)))
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
if (packet->malloced) if (packet->malloced)
kfree(packet); kfree(packet);
...@@ -327,7 +327,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -327,7 +327,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
sh->vtag = htonl(packet->vtag); sh->vtag = htonl(packet->vtag);
sh->checksum = 0; sh->checksum = 0;
/* 2) Calculate the Adler-32 checksum of the whole packet, /* 2) Calculate the Adler-32 checksum of the whole packet,
* including the SCTP common header and all the * including the SCTP common header and all the
* chunks. * chunks.
...@@ -358,10 +357,11 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -358,10 +357,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/ */
SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
chunk->num_times_sent++;
chunk->sent_at = jiffies;
if (sctp_chunk_is_data(chunk)) { if (sctp_chunk_is_data(chunk)) {
sctp_chunk_assign_tsn(chunk);
if (!chunk->has_tsn) {
sctp_chunk_assign_tsn(chunk);
/* 6.3.1 C4) When data is in flight and when allowed /* 6.3.1 C4) When data is in flight and when allowed
* by rule C5, a new RTT measurement MUST be made each * by rule C5, a new RTT measurement MUST be made each
...@@ -369,23 +369,28 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -369,23 +369,28 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* SHOULD be made no more than once per round-trip * SHOULD be made no more than once per round-trip
* for a given destination transport address. * for a given destination transport address.
*/ */
if ((1 == chunk->num_times_sent) &&
(!tp->rto_pending)) { if (!tp->rto_pending) {
chunk->rtt_in_progress = 1; chunk->rtt_in_progress = 1;
tp->rto_pending = 1; tp->rto_pending = 1;
} }
sctp_datamsg_track(chunk);
} else
chunk->resent = 1;
chunk->sent_at = jiffies;
has_data = 1; has_data = 1;
} }
padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len; padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len;
if (padding) if (padding)
memset(skb_put(chunk->skb, padding), 0, padding); memset(skb_put(chunk->skb, padding), 0, padding);
crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len), crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
chunk->skb->data, chunk->skb->data,
chunk->skb->len, crc32); chunk->skb->len, crc32);
SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, " SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
"%s %d\n",
"*** Chunk", chunk, "*** Chunk", chunk,
sctp_cname(SCTP_ST_CHUNK( sctp_cname(SCTP_ST_CHUNK(
chunk->chunk_hdr->type)), chunk->chunk_hdr->type)),
...@@ -394,7 +399,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -394,7 +399,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
ntohl(chunk->subh.data_hdr->tsn) : 0, ntohl(chunk->subh.data_hdr->tsn) : 0,
"length", ntohs(chunk->chunk_hdr->length), "length", ntohs(chunk->chunk_hdr->length),
"chunk->skb->len", chunk->skb->len, "chunk->skb->len", chunk->skb->len,
"num_times_sent", chunk->num_times_sent,
"rtt_in_progress", chunk->rtt_in_progress); "rtt_in_progress", chunk->rtt_in_progress);
/* /*
...@@ -403,7 +407,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -403,7 +407,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* acknowledged or have failed. * acknowledged or have failed.
*/ */
if (!sctp_chunk_is_data(chunk)) if (!sctp_chunk_is_data(chunk))
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
} }
/* Perform final transformation on checksum. */ /* Perform final transformation on checksum. */
......
This diff is collapsed.
...@@ -393,7 +393,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, ...@@ -393,7 +393,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
{ {
struct rtable *rt; struct rtable *rt;
struct flowi fl; struct flowi fl;
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
rwlock_t *addr_lock; rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr; struct sockaddr_storage_list *laddr;
struct list_head *pos; struct list_head *pos;
......
This diff is collapsed.
...@@ -81,11 +81,11 @@ static void sctp_do_ecn_ce_work(struct sctp_association *asoc, ...@@ -81,11 +81,11 @@ static void sctp_do_ecn_ce_work(struct sctp_association *asoc,
* This element represents the lowest TSN number in the datagram * This element represents the lowest TSN number in the datagram
* that was originally marked with the CE bit. * that was originally marked with the CE bit.
*/ */
static sctp_chunk_t *sctp_do_ecn_ecne_work(struct sctp_association *asoc, static struct sctp_chunk *sctp_do_ecn_ecne_work(struct sctp_association *asoc,
__u32 lowest_tsn, __u32 lowest_tsn,
sctp_chunk_t *chunk) struct sctp_chunk *chunk)
{ {
sctp_chunk_t *repl; struct sctp_chunk *repl;
/* Our previously transmitted packet ran into some congestion /* Our previously transmitted packet ran into some congestion
* so we should take action by reducing cwnd and ssthresh * so we should take action by reducing cwnd and ssthresh
...@@ -528,7 +528,7 @@ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds, ...@@ -528,7 +528,7 @@ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
struct sctp_association *asoc, struct sctp_association *asoc,
struct sctp_transport *t, struct sctp_transport *t,
sctp_chunk_t *chunk) struct sctp_chunk *chunk)
{ {
sctp_sender_hb_info_t *hbinfo; sctp_sender_hb_info_t *hbinfo;
...@@ -596,7 +596,7 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, ...@@ -596,7 +596,7 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
*/ */
static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds,
struct sctp_association *asoc, struct sctp_association *asoc,
sctp_chunk_t *chunk) struct sctp_chunk *chunk)
{ {
struct sctp_transport *t; struct sctp_transport *t;
...@@ -836,8 +836,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -836,8 +836,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
int error = 0; int error = 0;
int force; int force;
sctp_cmd_t *cmd; sctp_cmd_t *cmd;
sctp_chunk_t *new_obj; struct sctp_chunk *new_obj;
sctp_chunk_t *chunk = NULL; struct sctp_chunk *chunk = NULL;
struct sctp_packet *packet; struct sctp_packet *packet;
struct list_head *pos; struct list_head *pos;
struct timer_list *timer; struct timer_list *timer;
...@@ -845,8 +845,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -845,8 +845,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
struct sctp_transport *t; struct sctp_transport *t;
sctp_sackhdr_t sackh; sctp_sackhdr_t sackh;
if(SCTP_EVENT_T_TIMEOUT != event_type) if (SCTP_EVENT_T_TIMEOUT != event_type)
chunk = (sctp_chunk_t *) event_arg; chunk = (struct sctp_chunk *) event_arg;
/* Note: This whole file is a huge candidate for rework. /* Note: This whole file is a huge candidate for rework.
* For example, each command could either have its own handler, so * For example, each command could either have its own handler, so
...@@ -935,7 +935,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -935,7 +935,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
new_obj = sctp_make_cookie_echo(asoc, chunk); new_obj = sctp_make_cookie_echo(asoc, chunk);
if (!new_obj) { if (!new_obj) {
if (cmd->obj.ptr) if (cmd->obj.ptr)
sctp_free_chunk(cmd->obj.ptr); sctp_chunk_free(cmd->obj.ptr);
goto nomem; goto nomem;
} }
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
......
This diff is collapsed.
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
/* Forward declarations for internal helper functions. */ /* Forward declarations for internal helper functions. */
static int sctp_writeable(struct sock *sk); static int sctp_writeable(struct sock *sk);
static inline int sctp_wspace(struct sctp_association *asoc); static inline int sctp_wspace(struct sctp_association *asoc);
static inline void sctp_set_owner_w(sctp_chunk_t *chunk); static inline void sctp_set_owner_w(struct sctp_chunk *chunk);
static void sctp_wfree(struct sk_buff *skb); static void sctp_wfree(struct sk_buff *skb);
static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p, static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p,
int msg_len); int msg_len);
...@@ -195,7 +195,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) ...@@ -195,7 +195,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
{ {
struct sctp_opt *sp = sctp_sk(sk); struct sctp_opt *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep; struct sctp_endpoint *ep = sp->ep;
sctp_bind_addr_t *bp = &ep->base.bind_addr; struct sctp_bind_addr *bp = &ep->base.bind_addr;
struct sctp_af *af; struct sctp_af *af;
unsigned short snum; unsigned short snum;
int ret = 0; int ret = 0;
...@@ -488,7 +488,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) ...@@ -488,7 +488,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
struct sctp_opt *sp = sctp_sk(sk); struct sctp_opt *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep; struct sctp_endpoint *ep = sp->ep;
int cnt; int cnt;
sctp_bind_addr_t *bp = &ep->base.bind_addr; struct sctp_bind_addr *bp = &ep->base.bind_addr;
int retval = 0; int retval = 0;
union sctp_addr saveaddr; union sctp_addr saveaddr;
...@@ -769,8 +769,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -769,8 +769,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
struct sctp_opt *sp; struct sctp_opt *sp;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
struct sctp_association *new_asoc=NULL, *asoc=NULL; struct sctp_association *new_asoc=NULL, *asoc=NULL;
struct sctp_transport *transport; struct sctp_transport *transport, *chunk_tp;
sctp_chunk_t *chunk = NULL; struct sctp_chunk *chunk = NULL;
union sctp_addr to; union sctp_addr to;
struct sockaddr *msg_name = NULL; struct sockaddr *msg_name = NULL;
struct sctp_sndrcvinfo default_sinfo = { 0 }; struct sctp_sndrcvinfo default_sinfo = { 0 };
...@@ -782,7 +782,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -782,7 +782,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
sctp_scope_t scope; sctp_scope_t scope;
long timeo; long timeo;
__u16 sinfo_flags = 0; __u16 sinfo_flags = 0;
struct sk_buff_head chunks; struct sctp_datamsg *datamsg;
struct list_head *pos, *temp;
int msg_flags = msg->msg_flags; int msg_flags = msg->msg_flags;
SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %d)\n", SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %d)\n",
...@@ -855,12 +856,20 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -855,12 +856,20 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
goto out_nounlock; goto out_nounlock;
} }
sctp_lock_sock(sk); /* If MSG_ADDR_OVER is set, there must be an address
* specified in msg_name.
*/
if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) {
err = -EINVAL;
goto out_nounlock;
}
transport = NULL; transport = NULL;
SCTP_DEBUG_PRINTK("About to look up association.\n"); SCTP_DEBUG_PRINTK("About to look up association.\n");
sctp_lock_sock(sk);
/* If a msg_name has been specified, assume this is to be used. */ /* If a msg_name has been specified, assume this is to be used. */
if (msg_name) { if (msg_name) {
/* Look for a matching association on the endpoint. */ /* Look for a matching association on the endpoint. */
...@@ -1044,11 +1053,25 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -1044,11 +1053,25 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
goto out_free; goto out_free;
} }
/* This flag, in the UDP model, requests the SCTP stack to
* override the primary destination address with the
* address found with the sendto/sendmsg call.
*/
if (sinfo_flags & MSG_ADDR_OVER) {
chunk_tp = sctp_assoc_lookup_paddr(asoc, &to);
if (!chunk_tp) {
err = -EINVAL;
goto out_free;
}
} else
chunk_tp = NULL;
/* Break the message into multiple chunks of maximum size. */ /* Break the message into multiple chunks of maximum size. */
skb_queue_head_init(&chunks); datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
err = sctp_datachunks_from_user(asoc, sinfo, msg, msg_len, &chunks); if (!datamsg) {
if (err) err = -ENOMEM;
goto out_free; goto out_free;
}
/* Auto-connect, if we aren't connected already. */ /* Auto-connect, if we aren't connected already. */
if (SCTP_STATE_CLOSED == asoc->state) { if (SCTP_STATE_CLOSED == asoc->state) {
...@@ -1059,31 +1082,20 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -1059,31 +1082,20 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
} }
/* Now send the (possibly) fragmented message. */ /* Now send the (possibly) fragmented message. */
while ((chunk = (sctp_chunk_t *)__skb_dequeue(&chunks))) { list_for_each_safe(pos, temp, &datamsg->chunks) {
chunk = list_entry(pos, struct sctp_chunk, frag_list);
list_del_init(pos);
/* Do accounting for the write space. */ /* Do accounting for the write space. */
sctp_set_owner_w(chunk); sctp_set_owner_w(chunk);
/* This flag, in the UDP model, requests the SCTP stack to chunk->transport = chunk_tp;
* override the primary destination address with the
* address found with the sendto/sendmsg call.
*/
if (sinfo_flags & MSG_ADDR_OVER) {
if (!msg->msg_name) {
err = -EINVAL;
goto out_free;
}
chunk->transport = sctp_assoc_lookup_paddr(asoc, &to);
if (!chunk->transport) {
err = -EINVAL;
goto out_free;
}
}
/* Send it to the lower layers. */ /* Send it to the lower layers. */
sctp_primitive_SEND(asoc, chunk); sctp_primitive_SEND(asoc, chunk);
SCTP_DEBUG_PRINTK("We sent primitively.\n"); SCTP_DEBUG_PRINTK("We sent primitively.\n");
} }
sctp_datamsg_free(datamsg);
if (!err) { if (!err) {
err = msg_len; err = msg_len;
...@@ -1099,8 +1111,9 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -1099,8 +1111,9 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
sctp_association_free(asoc); sctp_association_free(asoc);
out_free_chunk: out_free_chunk:
/* The datamsg struct will auto-destruct via ref counting. */
if (chunk) if (chunk)
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
out_unlock: out_unlock:
sctp_release_sock(sk); sctp_release_sock(sk);
...@@ -2243,7 +2256,7 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, ...@@ -2243,7 +2256,7 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
sctp_assoc_t id; sctp_assoc_t id;
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
struct sctp_association *asoc; struct sctp_association *asoc;
struct list_head *pos; struct list_head *pos;
int cnt = 0; int cnt = 0;
...@@ -2281,7 +2294,7 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, ...@@ -2281,7 +2294,7 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
static int sctp_getsockopt_local_addrs(struct sock *sk, int len, static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
struct sctp_association *asoc; struct sctp_association *asoc;
struct list_head *pos; struct list_head *pos;
int cnt = 0; int cnt = 0;
...@@ -3269,7 +3282,7 @@ static inline int sctp_wspace(struct sctp_association *asoc) ...@@ -3269,7 +3282,7 @@ static inline int sctp_wspace(struct sctp_association *asoc)
* destructor in the data chunk skb for the purpose of the sndbuf space * destructor in the data chunk skb for the purpose of the sndbuf space
* tracking. * tracking.
*/ */
static inline void sctp_set_owner_w(sctp_chunk_t *chunk) static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
{ {
struct sctp_association *asoc = chunk->asoc; struct sctp_association *asoc = chunk->asoc;
struct sock *sk = asoc->base.sk; struct sock *sk = asoc->base.sk;
...@@ -3279,7 +3292,7 @@ static inline void sctp_set_owner_w(sctp_chunk_t *chunk) ...@@ -3279,7 +3292,7 @@ static inline void sctp_set_owner_w(sctp_chunk_t *chunk)
chunk->skb->destructor = sctp_wfree; chunk->skb->destructor = sctp_wfree;
/* Save the chunk pointer in skb for sctp_wfree to use later. */ /* Save the chunk pointer in skb for sctp_wfree to use later. */
*((sctp_chunk_t **)(chunk->skb->cb)) = chunk; *((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
sk->wmem_queued += SCTP_DATA_SNDSIZE(chunk); sk->wmem_queued += SCTP_DATA_SNDSIZE(chunk);
...@@ -3317,11 +3330,11 @@ static void __sctp_write_space(struct sctp_association *asoc) ...@@ -3317,11 +3330,11 @@ static void __sctp_write_space(struct sctp_association *asoc)
static void sctp_wfree(struct sk_buff *skb) static void sctp_wfree(struct sk_buff *skb)
{ {
struct sctp_association *asoc; struct sctp_association *asoc;
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
struct sock *sk; struct sock *sk;
/* Get the saved chunk pointer. */ /* Get the saved chunk pointer. */
chunk = *((sctp_chunk_t **)(skb->cb)); chunk = *((struct sctp_chunk **)(skb->cb));
asoc = chunk->asoc; asoc = chunk->asoc;
sk = asoc->base.sk; sk = asoc->base.sk;
asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk); asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk);
......
...@@ -316,7 +316,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( ...@@ -316,7 +316,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
* error formats. * error formats.
*/ */
struct sctp_ulpevent *sctp_ulpevent_make_remote_error( struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
const struct sctp_association *asoc, sctp_chunk_t *chunk, const struct sctp_association *asoc, struct sctp_chunk *chunk,
__u16 flags, int gfp) __u16 flags, int gfp)
{ {
struct sctp_ulpevent *event; struct sctp_ulpevent *event;
...@@ -420,7 +420,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error( ...@@ -420,7 +420,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
* 5.3.1.4 SCTP_SEND_FAILED * 5.3.1.4 SCTP_SEND_FAILED
*/ */
struct sctp_ulpevent *sctp_ulpevent_make_send_failed( struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
const struct sctp_association *asoc, sctp_chunk_t *chunk, const struct sctp_association *asoc, struct sctp_chunk *chunk,
__u16 flags, __u32 error, int gfp) __u16 flags, __u32 error, int gfp)
{ {
struct sctp_ulpevent *event; struct sctp_ulpevent *event;
...@@ -588,7 +588,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event( ...@@ -588,7 +588,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
* 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
*/ */
struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
sctp_chunk_t *chunk, int gfp) struct sctp_chunk *chunk,
int gfp)
{ {
struct sctp_ulpevent *event; struct sctp_ulpevent *event;
struct sctp_sndrcvinfo *info; struct sctp_sndrcvinfo *info;
......
...@@ -118,7 +118,7 @@ void sctp_ulpq_free(struct sctp_ulpq *ulpq) ...@@ -118,7 +118,7 @@ void sctp_ulpq_free(struct sctp_ulpq *ulpq)
} }
/* Process an incoming DATA chunk. */ /* Process an incoming DATA chunk. */
int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, sctp_chunk_t *chunk, int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
int gfp) int gfp)
{ {
struct sk_buff_head temp; struct sk_buff_head temp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment