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 @@
/*
* sctp_protocol.c
*/
extern sctp_protocol_t sctp_proto;
extern struct sctp_protocol sctp_proto;
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);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
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)
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. */
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;
}
/* Look up the association by its id. */
sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
return asoc;
}
/* A macro to walk a list of skbs. */
#define sctp_skb_for_each(pos, head, tmp) \
......@@ -494,7 +480,7 @@ extern void sctp_put_port(struct sock *sk);
/* Static inline functions. */
/* 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;
}
......@@ -523,21 +509,21 @@ static inline int ipver2af(__u8 ipver)
/* This is the hash function for the SCTP port hash table. */
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));
}
/* This is the hash function for the endpoint hash table. */
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));
}
/* This is the hash function for the association hash table. */
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;
h ^= h>>8;
return (h & (sctp_proto->assoc_hashsize - 1));
......@@ -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)
{
sctp_protocol_t *sctp_proto = sctp_get_protocol();
struct sctp_protocol *sctp_proto = sctp_get_protocol();
int h = (lport << 16) + rport;
h ^= vtag;
return (h & (sctp_proto->assoc_hashsize-1));
......
......@@ -118,7 +118,6 @@ struct sctp_opt;
struct sctp_endpoint_common;
struct sctp_ssnmap;
typedef struct sctp_protocol sctp_protocol_t;
typedef struct sctp_endpoint sctp_endpoint_t;
typedef struct sctp_association sctp_association_t;
typedef struct sctp_packet sctp_packet_t;
......@@ -1130,8 +1129,9 @@ static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
}
/* These are function signatures for manipulating endpoints. */
sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *, struct sock *, int);
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *, sctp_protocol_t *,
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *, struct sock *, int);
sctp_endpoint_t *sctp_endpoint_init(struct sctp_endpoint *,
struct sctp_protocol *,
struct sock *, int priority);
void sctp_endpoint_free(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,
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *);
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr);
......@@ -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 *,
const union sctp_addr *address,
const int priority);
void sctp_assoc_control_transport(sctp_association_t *,
void sctp_assoc_control_transport(struct sctp_association *,
struct sctp_transport *,
sctp_transport_cmd_t, sctp_sn_error_t);
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 *,
void sctp_assoc_migrate(sctp_association_t *, struct sock *);
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_tsn_block(sctp_association_t *, 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);
__u32 sctp_association_get_next_tsn(struct sctp_association *);
__u32 sctp_association_get_tsn_block(struct sctp_association *, int);
void sctp_assoc_sync_pmtu(struct sctp_association *);
void sctp_assoc_rwnd_increase(struct sctp_association *, 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_cookie(sctp_association_t *,
sctp_cookie_t *, int);
......
......@@ -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. */
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,
int priority)
{
......@@ -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 (NULL == asoc->peer.primary_path) {
asoc->peer.primary_path = peer;
/* Set a default msg_name for events. */
memcpy(&asoc->peer.primary_addr, &peer->ipaddr,
sizeof(union sctp_addr));
asoc->peer.active_path = peer;
sctp_assoc_set_primary(asoc, peer);
asoc->peer.retran_path = peer;
}
......@@ -603,7 +615,7 @@ void sctp_association_put(sctp_association_t *asoc)
/* Allocate the next TSN, Transmission Sequence Number, for the given
* 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:
* Transmission Sequence Numbers wrap around when they reach
......@@ -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. */
__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;
......
......@@ -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,
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;
if (sctp_is_any(addr)) {
......
......@@ -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.
* 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)
{
sctp_endpoint_t *ep;
......@@ -89,7 +89,8 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto,
/*
* 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 sctp_opt *sp = sctp_sk(sk);
......
......@@ -553,7 +553,7 @@ void sctp_xmit_fragmented_chunks(struct sctp_outq *q, sctp_packet_t *packet,
}
/* 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);
/* Transmit the first fragment. */
......
......@@ -58,7 +58,7 @@
#include <net/inet_common.h>
/* Global data structures. */
sctp_protocol_t sctp_proto;
struct sctp_protocol sctp_proto;
struct proc_dir_entry *proc_net_sctp;
DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
......@@ -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
* 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 list_head *pos;
......@@ -168,7 +168,7 @@ static void __sctp_get_local_addr_list(sctp_protocol_t *proto)
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));
......@@ -178,7 +178,7 @@ static void sctp_get_local_addr_list(sctp_protocol_t *proto)
}
/* 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 list_head *pos, *temp;
......@@ -191,7 +191,7 @@ static void __sctp_free_local_addr_list(sctp_protocol_t *proto)
}
/* 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));
......@@ -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'. */
int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp,
sctp_scope_t scope, int priority, int copy_flags)
int sctp_copy_local_addr_list(struct sctp_protocol *proto,
struct sctp_bind_addr *bp, sctp_scope_t scope,
int priority, int copy_flags)
{
struct sockaddr_storage_list *addr;
int error = 0;
......
......@@ -1282,7 +1282,7 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
* assign a 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;
}
}
......
......@@ -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_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
* The syntax of bind() is,
......@@ -818,19 +849,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
}
} 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);
}
if (!asoc) {
err = -EINVAL;
goto out_unlock;
......@@ -1126,15 +1145,10 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
int err = 0;
int skb_len;
SCTP_DEBUG_PRINTK("sctp_recvmsg("
"%s: %p, %s: %p, %s: %d, %s: %d, %s: "
"0x%x, %s: %p)\n",
"sk", sk,
"msghdr", msg,
"len", len,
"knoblauch", noblock,
"flags", flags,
"addr_len", addr_len);
SCTP_DEBUG_PRINTK("sctp_recvmsg(%s: %p, %s: %p, %s: %d, %s: %d, %s: "
"0x%x, %s: %p)\n", "sk", sk, "msghdr", msg,
"len", len, "knoblauch", noblock,
"flags", flags, "addr_len", addr_len);
sctp_lock_sock(sk);
skb = sctp_skb_recv_datagram(sk, flags, noblock, &err);
......@@ -1223,7 +1237,7 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk,
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)
{
if (optlen != sizeof(struct sctp_event_subscribe))
......@@ -1250,9 +1264,8 @@ static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
return 0;
}
static inline int sctp_setsockopt_set_peer_addr_params(struct sock *sk,
char *optval,
int optlen)
static inline int sctp_setsockopt_peer_addr_params(struct sock *sk,
char *optval, int optlen)
{
struct sctp_paddrparams params;
sctp_association_t *asoc;
......@@ -1290,8 +1303,7 @@ static inline int sctp_setsockopt_set_peer_addr_params(struct sock *sk,
error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans);
if (error)
return error;
}
else {
} else {
/* The value of the heartbeat interval, in milliseconds. A value of 0,
* when modifying the parameter, specifies that the heartbeat on this
* address should be disabled.
......@@ -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
* 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)
{
struct sctp_sndrcvinfo info;
......@@ -1359,6 +1371,41 @@ static inline int sctp_setsockopt_set_default_send_param(struct sock *sk,
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()
*
* 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,
break;
case SCTP_SET_EVENTS:
retval = sctp_setsockopt_set_events(sk, optval, optlen);
retval = sctp_setsockopt_events(sk, optval, optlen);
break;
case SCTP_AUTOCLOSE:
......@@ -1442,8 +1489,7 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
break;
case SCTP_SET_PEER_ADDR_PARAMS:
retval = sctp_setsockopt_set_peer_addr_params(sk, optval,
optlen);
retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
break;
case SCTP_INITMSG:
......@@ -1451,8 +1497,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
break;
case SCTP_SET_DEFAULT_SEND_PARAM:
retval = sctp_setsockopt_set_default_send_param(sk,
optval, optlen);
retval = sctp_setsockopt_default_send_param(sk, optval,
optlen);
break;
case SCTP_SET_PEER_PRIMARY_ADDR:
retval = sctp_setsockopt_peer_prim(sk, optval, optlen);
break;
default:
......@@ -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_endpoint_t *ep;
sctp_protocol_t *proto;
struct sctp_protocol *proto;
struct sctp_opt *sp;
SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk);
......@@ -1714,6 +1764,13 @@ SCTP_STATIC void sctp_shutdown(struct sock *sk, int how)
/* 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,
int *optlen)
{
......@@ -1735,21 +1792,11 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
}
associd = status.sstat_assoc_id;
if ((SCTP_SOCKET_UDP_HIGH_BANDWIDTH != sctp_sk(sk)->type) && associd) {
assoc = sctp_id2assoc(sk, associd);
if (!assoc) {
retval = -EINVAL;
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;
......@@ -1970,8 +2017,8 @@ static inline int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval
return retval;
}
static inline int sctp_getsockopt_get_peer_addr_params(struct sock *sk,
int len, char *optval, int *optlen)
static inline int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
char *optval, int *optlen)
{
struct sctp_paddrparams params;
sctp_association_t *asoc;
......@@ -2023,7 +2070,7 @@ static inline int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval
return 0;
}
static inline int sctp_getsockopt_get_peer_addrs_num(struct sock *sk, int len,
static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
char *optval, int *optlen)
{
sctp_assoc_t id;
......@@ -2053,7 +2100,7 @@ static inline int sctp_getsockopt_get_peer_addrs_num(struct sock *sk, int len,
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)
{
sctp_association_t *asoc;
......@@ -2093,7 +2140,7 @@ static inline int sctp_getsockopt_get_peer_addrs(struct sock *sk, int len,
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)
{
sctp_assoc_t id;
......@@ -2132,7 +2179,7 @@ static inline int sctp_getsockopt_get_local_addrs_num(struct sock *sk, int len,
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)
{
sctp_bind_addr_t *bp;
......@@ -2183,6 +2230,40 @@ static inline int sctp_getsockopt_get_local_addrs(struct sock *sk, int len,
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)
......@@ -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.
*/
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)
{
struct sctp_sndrcvinfo info;
......@@ -2257,58 +2338,49 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case SCTP_STATUS:
retval = sctp_getsockopt_sctp_status(sk, len, optval, optlen);
break;
case SCTP_DISABLE_FRAGMENTS:
retval = sctp_getsockopt_disable_fragments(sk, len, optval,
optlen);
break;
case SCTP_SET_EVENTS:
retval = sctp_getsockopt_set_events(sk, len, optval, optlen);
break;
case SCTP_AUTOCLOSE:
retval = sctp_getsockopt_autoclose(sk, len, optval, optlen);
break;
case SCTP_SOCKOPT_PEELOFF:
retval = sctp_getsockopt_peeloff(sk, len, optval, optlen);
break;
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);
break;
case SCTP_INITMSG:
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
break;
case SCTP_GET_PEER_ADDRS_NUM:
retval = sctp_getsockopt_get_peer_addrs_num(sk, len, optval,
retval = sctp_getsockopt_peer_addrs_num(sk, len, optval,
optlen);
break;
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);
break;
case SCTP_GET_PEER_ADDRS:
retval = sctp_getsockopt_get_peer_addrs(sk, len, optval,
retval = sctp_getsockopt_peer_addrs(sk, len, optval,
optlen);
break;
case SCTP_GET_LOCAL_ADDRS:
retval = sctp_getsockopt_get_local_addrs(sk, len, optval,
retval = sctp_getsockopt_local_addrs(sk, len, optval,
optlen);
break;
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);
break;
case SCTP_SET_PEER_PRIMARY_ADDR:
retval = sctp_getsockopt_peer_prim(sk, len, optval, optlen);
break;
default:
retval = -ENOPROTOOPT;
break;
......@@ -2331,7 +2403,7 @@ static void sctp_unhash(struct sock *sk)
/* Check if port is acceptable. Possibly find first available port.
*
* 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
* 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
......@@ -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_bucket_t *pp; /* hash list port iterator */
sctp_protocol_t *sctp = sctp_get_protocol();
struct sctp_protocol *sctp = sctp_get_protocol();
unsigned short snum;
int ret;
......@@ -2684,7 +2756,7 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
/* FIXME: Commments! */
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_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
sctp_bind_bucket_t *pp;
......
......@@ -42,7 +42,7 @@
#include <net/sctp/structs.h>
#include <linux/sysctl.h>
extern sctp_protocol_t sctp_proto;
extern struct sctp_protocol sctp_proto;
static ctl_table sctp_table[] = {
{
......
......@@ -83,7 +83,7 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
const union sctp_addr *addr,
int priority)
{
sctp_protocol_t *proto = sctp_get_protocol();
struct sctp_protocol *proto = sctp_get_protocol();
/* Copy in the address. */
peer->ipaddr = *addr;
......@@ -262,7 +262,7 @@ void sctp_transport_put(struct sctp_transport *transport)
/* Update transport's RTO based on the newly calculated 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. */
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