Commit 1402a73c authored by Jon Grimm's avatar Jon Grimm

[SCTP] Add SCTP_SET_PEER_PRIMARY get/setsockopt.

Also, rename all sctp_protocol_t -> struct sctp_protocol.
Non-UDP-style SCTP sockets should ignore associd fields, so added
this function into sctp_id2assoc() in anticipation of Sridhar's
TCP-style work. 
parent 294cb923
...@@ -121,9 +121,10 @@ ...@@ -121,9 +121,10 @@
/* /*
* sctp_protocol.c * sctp_protocol.c
*/ */
extern sctp_protocol_t sctp_proto; extern struct sctp_protocol sctp_proto;
extern struct sock *sctp_get_ctl_sock(void); extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *, extern int sctp_copy_local_addr_list(struct sctp_protocol *,
struct sctp_bind_addr *,
sctp_scope_t, int priority, int flags); sctp_scope_t, int priority, int flags);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t); extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
...@@ -348,25 +349,10 @@ static inline sctp_assoc_t sctp_assoc2id(const sctp_association_t *asoc) ...@@ -348,25 +349,10 @@ static inline sctp_assoc_t sctp_assoc2id(const sctp_association_t *asoc)
return (sctp_assoc_t) asoc; return (sctp_assoc_t) asoc;
} }
/* Look up the association by its id. */
static inline sctp_association_t *sctp_id2assoc(const struct sock *sk, sctp_assoc_t id)
{
sctp_association_t *asoc = NULL;
/* First, verify that this is a kernel address. */ /* Look up the association by its id. */
if (sctp_is_valid_kaddr((unsigned long) id)) { sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
sctp_association_t *temp = (sctp_association_t *) id;
/* Verify that this _is_ an sctp_association_t
* data structure and if so, that the socket matches.
*/
if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) &&
(temp->base.sk == sk))
asoc = temp;
}
return asoc;
}
/* A macro to walk a list of skbs. */ /* A macro to walk a list of skbs. */
#define sctp_skb_for_each(pos, head, tmp) \ #define sctp_skb_for_each(pos, head, tmp) \
...@@ -494,7 +480,7 @@ extern void sctp_put_port(struct sock *sk); ...@@ -494,7 +480,7 @@ extern void sctp_put_port(struct sock *sk);
/* Static inline functions. */ /* Static inline functions. */
/* Return the SCTP protocol structure. */ /* Return the SCTP protocol structure. */
static inline sctp_protocol_t *sctp_get_protocol(void) static inline struct sctp_protocol *sctp_get_protocol(void)
{ {
return &sctp_proto; return &sctp_proto;
} }
...@@ -523,21 +509,21 @@ static inline int ipver2af(__u8 ipver) ...@@ -523,21 +509,21 @@ static inline int ipver2af(__u8 ipver)
/* This is the hash function for the SCTP port hash table. */ /* This is the hash function for the SCTP port hash table. */
static inline int sctp_phashfn(__u16 lport) static inline int sctp_phashfn(__u16 lport)
{ {
sctp_protocol_t *sctp_proto = sctp_get_protocol(); struct sctp_protocol *sctp_proto = sctp_get_protocol();
return (lport & (sctp_proto->port_hashsize - 1)); return (lport & (sctp_proto->port_hashsize - 1));
} }
/* This is the hash function for the endpoint hash table. */ /* This is the hash function for the endpoint hash table. */
static inline int sctp_ep_hashfn(__u16 lport) static inline int sctp_ep_hashfn(__u16 lport)
{ {
sctp_protocol_t *sctp_proto = sctp_get_protocol(); struct sctp_protocol *sctp_proto = sctp_get_protocol();
return (lport & (sctp_proto->ep_hashsize - 1)); return (lport & (sctp_proto->ep_hashsize - 1));
} }
/* This is the hash function for the association hash table. */ /* This is the hash function for the association hash table. */
static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport) static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
{ {
sctp_protocol_t *sctp_proto = sctp_get_protocol(); struct sctp_protocol *sctp_proto = sctp_get_protocol();
int h = (lport << 16) + rport; int h = (lport << 16) + rport;
h ^= h>>8; h ^= h>>8;
return (h & (sctp_proto->assoc_hashsize - 1)); return (h & (sctp_proto->assoc_hashsize - 1));
...@@ -549,7 +535,7 @@ static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport) ...@@ -549,7 +535,7 @@ static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
*/ */
static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag)
{ {
sctp_protocol_t *sctp_proto = sctp_get_protocol(); struct sctp_protocol *sctp_proto = sctp_get_protocol();
int h = (lport << 16) + rport; int h = (lport << 16) + rport;
h ^= vtag; h ^= vtag;
return (h & (sctp_proto->assoc_hashsize-1)); return (h & (sctp_proto->assoc_hashsize-1));
......
...@@ -118,7 +118,6 @@ struct sctp_opt; ...@@ -118,7 +118,6 @@ struct sctp_opt;
struct sctp_endpoint_common; struct sctp_endpoint_common;
struct sctp_ssnmap; struct sctp_ssnmap;
typedef struct sctp_protocol sctp_protocol_t;
typedef struct sctp_endpoint sctp_endpoint_t; typedef struct sctp_endpoint sctp_endpoint_t;
typedef struct sctp_association sctp_association_t; typedef struct sctp_association sctp_association_t;
typedef struct sctp_packet sctp_packet_t; typedef struct sctp_packet sctp_packet_t;
...@@ -1130,8 +1129,9 @@ static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base) ...@@ -1130,8 +1129,9 @@ static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
} }
/* These are function signatures for manipulating endpoints. */ /* These are function signatures for manipulating endpoints. */
sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *, struct sock *, int); sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *, struct sock *, int);
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *, sctp_protocol_t *, sctp_endpoint_t *sctp_endpoint_init(struct sctp_endpoint *,
struct sctp_protocol *,
struct sock *, int priority); struct sock *, int priority);
void sctp_endpoint_free(sctp_endpoint_t *); void sctp_endpoint_free(sctp_endpoint_t *);
void sctp_endpoint_put(sctp_endpoint_t *); void sctp_endpoint_put(sctp_endpoint_t *);
...@@ -1143,7 +1143,6 @@ sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep, ...@@ -1143,7 +1143,6 @@ sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *); int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *);
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *, sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
const union sctp_addr *); const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr, int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr); const union sctp_addr *paddr);
...@@ -1619,7 +1618,7 @@ struct sctp_transport *sctp_assoc_lookup_paddr(const sctp_association_t *, ...@@ -1619,7 +1618,7 @@ struct sctp_transport *sctp_assoc_lookup_paddr(const sctp_association_t *,
struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *, struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *,
const union sctp_addr *address, const union sctp_addr *address,
const int priority); const int priority);
void sctp_assoc_control_transport(sctp_association_t *, void sctp_assoc_control_transport(struct sctp_association *,
struct sctp_transport *, struct sctp_transport *,
sctp_transport_cmd_t, sctp_sn_error_t); sctp_transport_cmd_t, sctp_sn_error_t);
struct sctp_transport *sctp_assoc_lookup_tsn(sctp_association_t *, __u32); struct sctp_transport *sctp_assoc_lookup_tsn(sctp_association_t *, __u32);
...@@ -1629,14 +1628,14 @@ struct sctp_transport *sctp_assoc_is_match(sctp_association_t *, ...@@ -1629,14 +1628,14 @@ struct sctp_transport *sctp_assoc_is_match(sctp_association_t *,
void sctp_assoc_migrate(sctp_association_t *, struct sock *); void sctp_assoc_migrate(sctp_association_t *, struct sock *);
void sctp_assoc_update(sctp_association_t *dst, sctp_association_t *src); void sctp_assoc_update(sctp_association_t *dst, sctp_association_t *src);
__u32 __sctp_association_get_next_tsn(sctp_association_t *); __u32 sctp_association_get_next_tsn(struct sctp_association *);
__u32 __sctp_association_get_tsn_block(sctp_association_t *, int); __u32 sctp_association_get_tsn_block(struct sctp_association *, int);
__u16 __sctp_association_get_next_ssn(sctp_association_t *, __u16 sid);
void sctp_assoc_sync_pmtu(sctp_association_t *);
void sctp_assoc_rwnd_increase(sctp_association_t *, int);
void sctp_assoc_rwnd_decrease(sctp_association_t *, int);
void sctp_assoc_sync_pmtu(struct sctp_association *);
void sctp_assoc_rwnd_increase(struct sctp_association *, int);
void sctp_assoc_rwnd_decrease(struct sctp_association *, int);
void sctp_assoc_set_primary(struct sctp_association *,
struct sctp_transport *);
int sctp_assoc_set_bind_addr_from_ep(sctp_association_t *, int); int sctp_assoc_set_bind_addr_from_ep(sctp_association_t *, int);
int sctp_assoc_set_bind_addr_from_cookie(sctp_association_t *, int sctp_assoc_set_bind_addr_from_cookie(sctp_association_t *,
sctp_cookie_t *, int); sctp_cookie_t *, int);
......
...@@ -360,9 +360,25 @@ static void sctp_association_destroy(sctp_association_t *asoc) ...@@ -360,9 +360,25 @@ static void sctp_association_destroy(sctp_association_t *asoc)
} }
} }
/* Change the primary destination address for the peer. */
void sctp_assoc_set_primary(struct sctp_association *asoc,
struct sctp_transport *transport)
{
asoc->peer.primary_path = transport;
/* Set a default msg_name for events. */
memcpy(&asoc->peer.primary_addr, &transport->ipaddr,
sizeof(union sctp_addr));
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
if (transport->active)
asoc->peer.active_path = transport;
}
/* Add a transport address to an association. */ /* Add a transport address to an association. */
struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *asoc, struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
const union sctp_addr *addr, const union sctp_addr *addr,
int priority) int priority)
{ {
...@@ -460,11 +476,7 @@ struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *asoc, ...@@ -460,11 +476,7 @@ struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *asoc,
/* If we do not yet have a primary path, set one. */ /* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) { if (NULL == asoc->peer.primary_path) {
asoc->peer.primary_path = peer; sctp_assoc_set_primary(asoc, peer);
/* Set a default msg_name for events. */
memcpy(&asoc->peer.primary_addr, &peer->ipaddr,
sizeof(union sctp_addr));
asoc->peer.active_path = peer;
asoc->peer.retran_path = peer; asoc->peer.retran_path = peer;
} }
...@@ -603,7 +615,7 @@ void sctp_association_put(sctp_association_t *asoc) ...@@ -603,7 +615,7 @@ void sctp_association_put(sctp_association_t *asoc)
/* Allocate the next TSN, Transmission Sequence Number, for the given /* Allocate the next TSN, Transmission Sequence Number, for the given
* association. * association.
*/ */
__u32 __sctp_association_get_next_tsn(sctp_association_t *asoc) __u32 sctp_association_get_next_tsn(sctp_association_t *asoc)
{ {
/* From Section 1.6 Serial Number Arithmetic: /* From Section 1.6 Serial Number Arithmetic:
* Transmission Sequence Numbers wrap around when they reach * Transmission Sequence Numbers wrap around when they reach
...@@ -618,7 +630,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc) ...@@ -618,7 +630,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc)
} }
/* Allocate 'num' TSNs by incrementing the association's TSN by num. */ /* Allocate 'num' TSNs by incrementing the association's TSN by num. */
__u32 __sctp_association_get_tsn_block(sctp_association_t *asoc, int num) __u32 sctp_association_get_tsn_block(sctp_association_t *asoc, int num)
{ {
__u32 retval = asoc->next_tsn; __u32 retval = asoc->next_tsn;
......
...@@ -302,7 +302,7 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, ...@@ -302,7 +302,7 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr, static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr,
sctp_scope_t scope, int priority, int flags) sctp_scope_t scope, int priority, int flags)
{ {
sctp_protocol_t *proto = sctp_get_protocol(); struct sctp_protocol *proto = sctp_get_protocol();
int error = 0; int error = 0;
if (sctp_is_any(addr)) { if (sctp_is_any(addr)) {
......
...@@ -65,7 +65,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep); ...@@ -65,7 +65,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep);
/* Create a sctp_endpoint_t with all that boring stuff initialized. /* Create a sctp_endpoint_t with all that boring stuff initialized.
* Returns NULL if there isn't enough memory. * Returns NULL if there isn't enough memory.
*/ */
sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto, sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
struct sock *sk, int priority) struct sock *sk, int priority)
{ {
sctp_endpoint_t *ep; sctp_endpoint_t *ep;
...@@ -89,7 +89,8 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto, ...@@ -89,7 +89,8 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto,
/* /*
* Initialize the base fields of the endpoint structure. * Initialize the base fields of the endpoint structure.
*/ */
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto, sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
struct sctp_protocol *proto,
struct sock *sk, int priority) struct sock *sk, int priority)
{ {
struct sctp_opt *sp = sctp_sk(sk); struct sctp_opt *sp = sctp_sk(sk);
......
...@@ -553,7 +553,7 @@ void sctp_xmit_fragmented_chunks(struct sctp_outq *q, sctp_packet_t *packet, ...@@ -553,7 +553,7 @@ void sctp_xmit_fragmented_chunks(struct sctp_outq *q, sctp_packet_t *packet,
} }
/* Get a TSN block of nfrags TSNs. */ /* Get a TSN block of nfrags TSNs. */
tsn = __sctp_association_get_tsn_block(asoc, nfrags); tsn = sctp_association_get_tsn_block(asoc, nfrags);
pos = skb_peek(&q->out); pos = skb_peek(&q->out);
/* Transmit the first fragment. */ /* Transmit the first fragment. */
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
#include <net/inet_common.h> #include <net/inet_common.h>
/* Global data structures. */ /* Global data structures. */
sctp_protocol_t sctp_proto; struct sctp_protocol sctp_proto;
struct proc_dir_entry *proc_net_sctp; struct proc_dir_entry *proc_net_sctp;
DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics); DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
...@@ -152,7 +152,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, ...@@ -152,7 +152,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
/* Extract our IP addresses from the system and stash them in the /* Extract our IP addresses from the system and stash them in the
* protocol structure. * protocol structure.
*/ */
static void __sctp_get_local_addr_list(sctp_protocol_t *proto) static void __sctp_get_local_addr_list(struct sctp_protocol *proto)
{ {
struct net_device *dev; struct net_device *dev;
struct list_head *pos; struct list_head *pos;
...@@ -168,7 +168,7 @@ static void __sctp_get_local_addr_list(sctp_protocol_t *proto) ...@@ -168,7 +168,7 @@ static void __sctp_get_local_addr_list(sctp_protocol_t *proto)
read_unlock(&dev_base_lock); read_unlock(&dev_base_lock);
} }
static void sctp_get_local_addr_list(sctp_protocol_t *proto) static void sctp_get_local_addr_list(struct sctp_protocol *proto)
{ {
long flags __attribute__ ((unused)); long flags __attribute__ ((unused));
...@@ -178,7 +178,7 @@ static void sctp_get_local_addr_list(sctp_protocol_t *proto) ...@@ -178,7 +178,7 @@ static void sctp_get_local_addr_list(sctp_protocol_t *proto)
} }
/* Free the existing local addresses. */ /* Free the existing local addresses. */
static void __sctp_free_local_addr_list(sctp_protocol_t *proto) static void __sctp_free_local_addr_list(struct sctp_protocol *proto)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
struct list_head *pos, *temp; struct list_head *pos, *temp;
...@@ -191,7 +191,7 @@ static void __sctp_free_local_addr_list(sctp_protocol_t *proto) ...@@ -191,7 +191,7 @@ static void __sctp_free_local_addr_list(sctp_protocol_t *proto)
} }
/* Free the existing local addresses. */ /* Free the existing local addresses. */
static void sctp_free_local_addr_list(sctp_protocol_t *proto) static void sctp_free_local_addr_list(struct sctp_protocol *proto)
{ {
long flags __attribute__ ((unused)); long flags __attribute__ ((unused));
...@@ -201,8 +201,9 @@ static void sctp_free_local_addr_list(sctp_protocol_t *proto) ...@@ -201,8 +201,9 @@ static void sctp_free_local_addr_list(sctp_protocol_t *proto)
} }
/* Copy the local addresses which are valid for 'scope' into 'bp'. */ /* Copy the local addresses which are valid for 'scope' into 'bp'. */
int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp, int sctp_copy_local_addr_list(struct sctp_protocol *proto,
sctp_scope_t scope, int priority, int copy_flags) struct sctp_bind_addr *bp, sctp_scope_t scope,
int priority, int copy_flags)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
int error = 0; int error = 0;
......
...@@ -1282,7 +1282,7 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk) ...@@ -1282,7 +1282,7 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
* assign a TSN. * assign a TSN.
*/ */
chunk->subh.data_hdr->tsn = chunk->subh.data_hdr->tsn =
htonl(__sctp_association_get_next_tsn(chunk->asoc)); htonl(sctp_association_get_next_tsn(chunk->asoc));
chunk->has_tsn = 1; chunk->has_tsn = 1;
} }
} }
......
...@@ -94,6 +94,37 @@ static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int); ...@@ -94,6 +94,37 @@ static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int);
static int sctp_do_bind(struct sock *, union sctp_addr *, int); static int sctp_do_bind(struct sock *, union sctp_addr *, int);
static int sctp_autobind(struct sock *sk); static int sctp_autobind(struct sock *sk);
/* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored.
*/
sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
{
sctp_association_t *asoc = NULL;
/* If this is not a UDP-style socket, assoc id should be
* ignored.
*/
if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) {
if (!list_empty(&sctp_sk(sk)->ep->asocs))
asoc = list_entry(sctp_sk(sk)->ep->asocs.next,
sctp_association_t, asocs);
return asoc;
}
/* First, verify that this is a kernel address. */
if (sctp_is_valid_kaddr((unsigned long) id)) {
sctp_association_t *temp = (sctp_association_t *) id;
/* Verify that this _is_ an sctp_association_t
* data structure and if so, that the socket matches.
*/
if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) &&
(temp->base.sk == sk))
asoc = temp;
}
return asoc;
}
/* API 3.1.2 bind() - UDP Style Syntax /* API 3.1.2 bind() - UDP Style Syntax
* The syntax of bind() is, * The syntax of bind() is,
...@@ -818,19 +849,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -818,19 +849,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
} }
} }
} else { } else {
/* For a peeled-off socket, ignore any associd specified by
* the user with SNDRCVINFO.
*/
if (SCTP_SOCKET_UDP_HIGH_BANDWIDTH == sp->type) {
if (list_empty(&ep->asocs)) {
err = -EINVAL;
goto out_unlock;
}
asoc = list_entry(ep->asocs.next, sctp_association_t,
asocs);
} else if (associd) {
asoc = sctp_id2assoc(sk, associd); asoc = sctp_id2assoc(sk, associd);
}
if (!asoc) { if (!asoc) {
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_unlock;
...@@ -1126,15 +1145,10 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr ...@@ -1126,15 +1145,10 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
int err = 0; int err = 0;
int skb_len; int skb_len;
SCTP_DEBUG_PRINTK("sctp_recvmsg(" SCTP_DEBUG_PRINTK("sctp_recvmsg(%s: %p, %s: %p, %s: %d, %s: %d, %s: "
"%s: %p, %s: %p, %s: %d, %s: %d, %s: " "0x%x, %s: %p)\n", "sk", sk, "msghdr", msg,
"0x%x, %s: %p)\n", "len", len, "knoblauch", noblock,
"sk", sk, "flags", flags, "addr_len", addr_len);
"msghdr", msg,
"len", len,
"knoblauch", noblock,
"flags", flags,
"addr_len", addr_len);
sctp_lock_sock(sk); sctp_lock_sock(sk);
skb = sctp_skb_recv_datagram(sk, flags, noblock, &err); skb = sctp_skb_recv_datagram(sk, flags, noblock, &err);
...@@ -1223,7 +1237,7 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk, ...@@ -1223,7 +1237,7 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk,
return 0; return 0;
} }
static inline int sctp_setsockopt_set_events(struct sock *sk, char *optval, static inline int sctp_setsockopt_events(struct sock *sk, char *optval,
int optlen) int optlen)
{ {
if (optlen != sizeof(struct sctp_event_subscribe)) if (optlen != sizeof(struct sctp_event_subscribe))
...@@ -1250,9 +1264,8 @@ static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval, ...@@ -1250,9 +1264,8 @@ static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
return 0; return 0;
} }
static inline int sctp_setsockopt_set_peer_addr_params(struct sock *sk, static inline int sctp_setsockopt_peer_addr_params(struct sock *sk,
char *optval, char *optval, int optlen)
int optlen)
{ {
struct sctp_paddrparams params; struct sctp_paddrparams params;
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -1290,8 +1303,7 @@ static inline int sctp_setsockopt_set_peer_addr_params(struct sock *sk, ...@@ -1290,8 +1303,7 @@ static inline int sctp_setsockopt_set_peer_addr_params(struct sock *sk,
error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans); error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans);
if (error) if (error)
return error; return error;
} } else {
else {
/* The value of the heartbeat interval, in milliseconds. A value of 0, /* The value of the heartbeat interval, in milliseconds. A value of 0,
* when modifying the parameter, specifies that the heartbeat on this * when modifying the parameter, specifies that the heartbeat on this
* address should be disabled. * address should be disabled.
...@@ -1336,7 +1348,7 @@ static inline int sctp_setsockopt_initmsg(struct sock *sk, char *optval, ...@@ -1336,7 +1348,7 @@ static inline int sctp_setsockopt_initmsg(struct sock *sk, char *optval,
* sinfo_timetolive. The user must provide the sinfo_assoc_id field in * sinfo_timetolive. The user must provide the sinfo_assoc_id field in
* to this call if the caller is using the UDP model. * to this call if the caller is using the UDP model.
*/ */
static inline int sctp_setsockopt_set_default_send_param(struct sock *sk, static inline int sctp_setsockopt_default_send_param(struct sock *sk,
char *optval, int optlen) char *optval, int optlen)
{ {
struct sctp_sndrcvinfo info; struct sctp_sndrcvinfo info;
...@@ -1359,6 +1371,41 @@ static inline int sctp_setsockopt_set_default_send_param(struct sock *sk, ...@@ -1359,6 +1371,41 @@ static inline int sctp_setsockopt_set_default_send_param(struct sock *sk,
return 0; return 0;
} }
/* 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
* the association primary. The enclosed address must be one of the
* association peer's addresses.
*/
static int sctp_setsockopt_peer_prim(struct sock *sk, char *optval, int optlen)
{
struct sctp_setpeerprim prim;
struct sctp_association *asoc;
union sctp_addr *addr;
struct sctp_transport *trans;
if (optlen != sizeof(struct sctp_setpeerprim))
return -EINVAL;
if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim)))
return -EFAULT;
asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
if (!asoc)
return -EINVAL;
/* Find the requested address. */
addr = (union sctp_addr *) &(prim.sspp_addr);
trans = sctp_assoc_lookup_paddr(asoc, addr);
if (!trans)
return -ENOENT;
sctp_assoc_set_primary(asoc, trans);
return 0;
}
/* API 6.2 setsockopt(), getsockopt() /* API 6.2 setsockopt(), getsockopt()
* *
* Applications use setsockopt() and getsockopt() to set or retrieve * Applications use setsockopt() and getsockopt() to set or retrieve
...@@ -1434,7 +1481,7 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, ...@@ -1434,7 +1481,7 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
break; break;
case SCTP_SET_EVENTS: case SCTP_SET_EVENTS:
retval = sctp_setsockopt_set_events(sk, optval, optlen); retval = sctp_setsockopt_events(sk, optval, optlen);
break; break;
case SCTP_AUTOCLOSE: case SCTP_AUTOCLOSE:
...@@ -1442,8 +1489,7 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, ...@@ -1442,8 +1489,7 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
break; break;
case SCTP_SET_PEER_ADDR_PARAMS: case SCTP_SET_PEER_ADDR_PARAMS:
retval = sctp_setsockopt_set_peer_addr_params(sk, optval, retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
optlen);
break; break;
case SCTP_INITMSG: case SCTP_INITMSG:
...@@ -1451,8 +1497,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, ...@@ -1451,8 +1497,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
break; break;
case SCTP_SET_DEFAULT_SEND_PARAM: case SCTP_SET_DEFAULT_SEND_PARAM:
retval = sctp_setsockopt_set_default_send_param(sk, retval = sctp_setsockopt_default_send_param(sk, optval,
optval, optlen); optlen);
break;
case SCTP_SET_PEER_PRIMARY_ADDR:
retval = sctp_setsockopt_peer_prim(sk, optval, optlen);
break; break;
default: default:
...@@ -1607,7 +1657,7 @@ SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) ...@@ -1607,7 +1657,7 @@ SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
SCTP_STATIC int sctp_init_sock(struct sock *sk) SCTP_STATIC int sctp_init_sock(struct sock *sk)
{ {
sctp_endpoint_t *ep; sctp_endpoint_t *ep;
sctp_protocol_t *proto; struct sctp_protocol *proto;
struct sctp_opt *sp; struct sctp_opt *sp;
SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk); SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk);
...@@ -1714,6 +1764,13 @@ SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) ...@@ -1714,6 +1764,13 @@ SCTP_STATIC void sctp_shutdown(struct sock *sk, int how)
/* STUB */ /* STUB */
} }
/* 7.2.1 Association Status (SCTP_STATUS)
* Applications can retrieve current status information about an
* association, including association state, peer receiver window size,
* number of unacked data chunks, and number of data chunks pending
* receipt. This information is read-only.
*/
static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval, static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
int *optlen) int *optlen)
{ {
...@@ -1735,21 +1792,11 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval, ...@@ -1735,21 +1792,11 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
} }
associd = status.sstat_assoc_id; associd = status.sstat_assoc_id;
if ((SCTP_SOCKET_UDP_HIGH_BANDWIDTH != sctp_sk(sk)->type) && associd) {
assoc = sctp_id2assoc(sk, associd); assoc = sctp_id2assoc(sk, associd);
if (!assoc) { if (!assoc) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
} else {
ep = sctp_sk(sk)->ep;
if (list_empty(&ep->asocs)) {
retval = -EINVAL;
goto out;
}
assoc = list_entry(ep->asocs.next, sctp_association_t, asocs);
}
transport = assoc->peer.primary_path; transport = assoc->peer.primary_path;
...@@ -1970,8 +2017,8 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval ...@@ -1970,8 +2017,8 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
return retval; return retval;
} }
static inline int sctp_getsockopt_get_peer_addr_params(struct sock *sk, static inline int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
int len, char *optval, int *optlen) char *optval, int *optlen)
{ {
struct sctp_paddrparams params; struct sctp_paddrparams params;
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -2023,7 +2070,7 @@ static inline int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval ...@@ -2023,7 +2070,7 @@ static inline int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval
return 0; return 0;
} }
static inline int sctp_getsockopt_get_peer_addrs_num(struct sock *sk, int len, static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
sctp_assoc_t id; sctp_assoc_t id;
...@@ -2053,7 +2100,7 @@ static inline int sctp_getsockopt_get_peer_addrs_num(struct sock *sk, int len, ...@@ -2053,7 +2100,7 @@ static inline int sctp_getsockopt_get_peer_addrs_num(struct sock *sk, int len,
return 0; return 0;
} }
static inline int sctp_getsockopt_get_peer_addrs(struct sock *sk, int len, static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -2093,7 +2140,7 @@ static inline int sctp_getsockopt_get_peer_addrs(struct sock *sk, int len, ...@@ -2093,7 +2140,7 @@ static inline int sctp_getsockopt_get_peer_addrs(struct sock *sk, int len,
return 0; return 0;
} }
static inline int sctp_getsockopt_get_local_addrs_num(struct sock *sk, int len, static inline 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;
...@@ -2132,7 +2179,7 @@ static inline int sctp_getsockopt_get_local_addrs_num(struct sock *sk, int len, ...@@ -2132,7 +2179,7 @@ static inline int sctp_getsockopt_get_local_addrs_num(struct sock *sk, int len,
return 0; return 0;
} }
static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len, static inline int sctp_getsockopt_local_addrs(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
sctp_bind_addr_t *bp; sctp_bind_addr_t *bp;
...@@ -2183,6 +2230,40 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len, ...@@ -2183,6 +2230,40 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len,
return 0; return 0;
} }
/* 7.1.10 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
* the association primary. The enclosed address must be one of the
* association peer's addresses.
*/
static int sctp_getsockopt_peer_prim(struct sock *sk, int len,
char *optval, int *optlen)
{
struct sctp_setpeerprim prim;
struct sctp_association *asoc;
if (len != sizeof(struct sctp_setpeerprim))
return -EINVAL;
if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim)))
return -EFAULT;
asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
if (!asoc)
return -EINVAL;
if (!asoc->peer.primary_path)
return -ENOTCONN;
memcpy(&prim.sspp_addr, &asoc->peer.primary_path->ipaddr,
sizeof(union sctp_addr));
if (copy_to_user(optval, &prim, sizeof(struct sctp_setpeerprim)))
return -EFAULT;
return 0;
}
/* /*
* *
* 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM) * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM)
...@@ -2200,7 +2281,7 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len, ...@@ -2200,7 +2281,7 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len,
* *
* For getsockopt, it get the default sctp_sndrcvinfo structure. * For getsockopt, it get the default sctp_sndrcvinfo structure.
*/ */
static inline int sctp_getsockopt_set_default_send_param(struct sock *sk, static inline int sctp_getsockopt_default_send_param(struct sock *sk,
int len, char *optval, int *optlen) int len, char *optval, int *optlen)
{ {
struct sctp_sndrcvinfo info; struct sctp_sndrcvinfo info;
...@@ -2257,58 +2338,49 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, ...@@ -2257,58 +2338,49 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case SCTP_STATUS: case SCTP_STATUS:
retval = sctp_getsockopt_sctp_status(sk, len, optval, optlen); retval = sctp_getsockopt_sctp_status(sk, len, optval, optlen);
break; break;
case SCTP_DISABLE_FRAGMENTS: case SCTP_DISABLE_FRAGMENTS:
retval = sctp_getsockopt_disable_fragments(sk, len, optval, retval = sctp_getsockopt_disable_fragments(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_SET_EVENTS: case SCTP_SET_EVENTS:
retval = sctp_getsockopt_set_events(sk, len, optval, optlen); retval = sctp_getsockopt_set_events(sk, len, optval, optlen);
break; break;
case SCTP_AUTOCLOSE: case SCTP_AUTOCLOSE:
retval = sctp_getsockopt_autoclose(sk, len, optval, optlen); retval = sctp_getsockopt_autoclose(sk, len, optval, optlen);
break; break;
case SCTP_SOCKOPT_PEELOFF: case SCTP_SOCKOPT_PEELOFF:
retval = sctp_getsockopt_peeloff(sk, len, optval, optlen); retval = sctp_getsockopt_peeloff(sk, len, optval, optlen);
break; break;
case SCTP_GET_PEER_ADDR_PARAMS: case SCTP_GET_PEER_ADDR_PARAMS:
retval = sctp_getsockopt_get_peer_addr_params(sk, len, optval, retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_INITMSG: case SCTP_INITMSG:
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
break; break;
case SCTP_GET_PEER_ADDRS_NUM: case SCTP_GET_PEER_ADDRS_NUM:
retval = sctp_getsockopt_get_peer_addrs_num(sk, len, optval, retval = sctp_getsockopt_peer_addrs_num(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_GET_LOCAL_ADDRS_NUM: case SCTP_GET_LOCAL_ADDRS_NUM:
retval = sctp_getsockopt_get_local_addrs_num(sk, len, optval, retval = sctp_getsockopt_local_addrs_num(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_GET_PEER_ADDRS: case SCTP_GET_PEER_ADDRS:
retval = sctp_getsockopt_get_peer_addrs(sk, len, optval, retval = sctp_getsockopt_peer_addrs(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_GET_LOCAL_ADDRS: case SCTP_GET_LOCAL_ADDRS:
retval = sctp_getsockopt_get_local_addrs(sk, len, optval, retval = sctp_getsockopt_local_addrs(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_SET_DEFAULT_SEND_PARAM: case SCTP_SET_DEFAULT_SEND_PARAM:
retval = sctp_getsockopt_set_default_send_param(sk, len, retval = sctp_getsockopt_default_send_param(sk, len,
optval, optlen); optval, optlen);
break; break;
case SCTP_SET_PEER_PRIMARY_ADDR:
retval = sctp_getsockopt_peer_prim(sk, len, optval, optlen);
break;
default: default:
retval = -ENOPROTOOPT; retval = -ENOPROTOOPT;
break; break;
...@@ -2331,7 +2403,7 @@ static void sctp_unhash(struct sock *sk) ...@@ -2331,7 +2403,7 @@ static void sctp_unhash(struct sock *sk)
/* Check if port is acceptable. Possibly find first available port. /* Check if port is acceptable. Possibly find first available port.
* *
* The port hash table (contained in the 'global' SCTP protocol storage * The port hash table (contained in the 'global' SCTP protocol storage
* returned by sctp_protocol_t * sctp_get_protocol()). The hash * returned by struct sctp_protocol *sctp_get_protocol()). The hash
* table is an array of 4096 lists (sctp_bind_hashbucket_t). Each * table is an array of 4096 lists (sctp_bind_hashbucket_t). Each
* list (the list number is the port number hashed out, so as you * list (the list number is the port number hashed out, so as you
* would expect from a hash function, all the ports in a given list have * would expect from a hash function, all the ports in a given list have
...@@ -2346,7 +2418,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) ...@@ -2346,7 +2418,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
{ {
sctp_bind_hashbucket_t *head; /* hash list */ sctp_bind_hashbucket_t *head; /* hash list */
sctp_bind_bucket_t *pp; /* hash list port iterator */ sctp_bind_bucket_t *pp; /* hash list port iterator */
sctp_protocol_t *sctp = sctp_get_protocol(); struct sctp_protocol *sctp = sctp_get_protocol();
unsigned short snum; unsigned short snum;
int ret; int ret;
...@@ -2684,7 +2756,7 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi ...@@ -2684,7 +2756,7 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
/* FIXME: Commments! */ /* FIXME: Commments! */
static __inline__ void __sctp_put_port(struct sock *sk) static __inline__ void __sctp_put_port(struct sock *sk)
{ {
sctp_protocol_t *sctp_proto = sctp_get_protocol(); struct sctp_protocol *sctp_proto = sctp_get_protocol();
sctp_bind_hashbucket_t *head = sctp_bind_hashbucket_t *head =
&sctp_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)]; &sctp_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
sctp_bind_bucket_t *pp; sctp_bind_bucket_t *pp;
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include <net/sctp/structs.h> #include <net/sctp/structs.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
extern sctp_protocol_t sctp_proto; extern struct sctp_protocol sctp_proto;
static ctl_table sctp_table[] = { static ctl_table sctp_table[] = {
{ {
......
...@@ -83,7 +83,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, ...@@ -83,7 +83,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
const union sctp_addr *addr, const union sctp_addr *addr,
int priority) int priority)
{ {
sctp_protocol_t *proto = sctp_get_protocol(); struct sctp_protocol *proto = sctp_get_protocol();
/* Copy in the address. */ /* Copy in the address. */
peer->ipaddr = *addr; peer->ipaddr = *addr;
...@@ -262,7 +262,7 @@ void sctp_transport_put(struct sctp_transport *transport) ...@@ -262,7 +262,7 @@ void sctp_transport_put(struct sctp_transport *transport)
/* Update transport's RTO based on the newly calculated RTT. */ /* Update transport's RTO based on the newly calculated RTT. */
void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
{ {
sctp_protocol_t *proto = sctp_get_protocol(); struct sctp_protocol *proto = sctp_get_protocol();
/* Check for valid transport. */ /* Check for valid transport. */
SCTP_ASSERT(tp, "NULL transport", return); SCTP_ASSERT(tp, "NULL transport", return);
......
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