struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
struct sctp_transport *transport;
union sctp_addr *laddr = (union sctp_addr *)addr;
+ union sctp_addr tmp;
- laddr->v4.sin_port = ntohs(laddr->v4.sin_port);
+ flip_to_h(&tmp, laddr);
addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
- (union sctp_addr *)addr,
+ &tmp,
&transport);
- laddr->v4.sin_port = htons(laddr->v4.sin_port);
if (!addr_asoc)
return NULL;
struct sctp_af *af;
unsigned short snum;
int ret = 0;
+ union sctp_addr tmp;
/* Common sockaddr verification. */
af = sctp_sockaddr_af(sp, addr, len);
sctp_write_lock(&ep->base.addr_lock);
/* Use GFP_ATOMIC since BHs are disabled. */
- addr->v4.sin_port = ntohs(addr->v4.sin_port);
- ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC);
- addr->v4.sin_port = htons(addr->v4.sin_port);
+ flip_to_h(&tmp, addr);
+ ret = sctp_add_bind_addr(bp, &tmp, 1, GFP_ATOMIC);
sctp_write_unlock(&ep->base.addr_lock);
sctp_local_bh_enable();
laddr = list_entry(p, struct sctp_sockaddr_entry, list);
sctp_read_unlock(&asoc->base.addr_lock);
- chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs,
+ chunk = sctp_make_asconf_update_ip(asoc, &laddr->a_h, addrs,
addrcnt, SCTP_PARAM_ADD_IP);
if (!chunk) {
retval = -ENOMEM;
saddr = list_entry(pos1,
struct sctp_sockaddr_entry,
list);
- if (sctp_cmp_addr_exact(&saddr->a, &saveaddr))
+ if (sctp_cmp_addr_exact(&saddr->a_h, &saveaddr))
saddr->use_as_src = 0;
}
addr_buf += af->sockaddr_len;
* addrs is a pointer to an array of one or more socket addresses. Each
* address is contained in its appropriate structure (i.e. struct
* sockaddr_in or struct sockaddr_in6) the family of the address type
- * must be used to distengish the address length (note that this
+ * must be used to distinguish the address length (note that this
* representation is termed a "packed array" of addresses). The caller
* specifies the number of addresses in the array with addrcnt.
*
status.sstat_outstrms = asoc->c.sinit_num_ostreams;
status.sstat_fragmentation_point = asoc->frag_point;
status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
- memcpy(&status.sstat_primary.spinfo_address,
- &(transport->ipaddr), sizeof(union sctp_addr));
+ flip_to_n((union sctp_addr *)&status.sstat_primary.spinfo_address,
+ &transport->ipaddr_h);
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)&status.sstat_primary.spinfo_address);
{
struct sock *sk = asoc->base.sk;
struct socket *sock;
+ struct inet_sock *inetsk;
int err = 0;
/* An association cannot be branched off from an already peeled-off
* asoc to the newsk.
*/
sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
+
+ /* Make peeled-off sockets more like 1-1 accepted sockets.
+ * Set the daddr and initialize id to something more random
+ */
+ inetsk = inet_sk(sock->sk);
+ inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
+ inetsk->id = asoc->next_tsn ^ jiffies;
+
*sockp = sock;
return err;
to = (void __user *)getaddrs.addrs;
list_for_each(pos, &asoc->peer.transport_addr_list) {
from = list_entry(pos, struct sctp_transport, transports);
- memcpy(&temp, &from->ipaddr, sizeof(temp));
+ memcpy(&temp, &from->ipaddr_h, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
temp.v4.sin_port = htons(temp.v4.sin_port);
list_for_each(pos, &asoc->peer.transport_addr_list) {
from = list_entry(pos, struct sctp_transport, transports);
- memcpy(&temp, &from->ipaddr, sizeof(temp));
+ memcpy(&temp, &from->ipaddr_h, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
if(space_left < addrlen)
if (sctp_list_single_entry(&bp->address_list)) {
addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list);
- if (sctp_is_any(&addr->a)) {
+ if (sctp_is_any(&addr->a_h)) {
sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
list_for_each(pos, &sctp_local_addr_list) {
addr = list_entry(pos,
struct sctp_sockaddr_entry,
list);
if ((PF_INET == sk->sk_family) &&
- (AF_INET6 == addr->a.sa.sa_family))
+ (AF_INET6 == addr->a_h.sa.sa_family))
continue;
cnt++;
}
list_for_each(pos, &sctp_local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if ((PF_INET == sk->sk_family) &&
- (AF_INET6 == addr->a.sa.sa_family))
+ (AF_INET6 == addr->a_h.sa.sa_family))
continue;
- memcpy(&temp, &addr->a, sizeof(temp));
+ memcpy(&temp, &addr->a_h, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
&temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
list_for_each(pos, &sctp_local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if ((PF_INET == sk->sk_family) &&
- (AF_INET6 == addr->a.sa.sa_family))
+ (AF_INET6 == addr->a_h.sa.sa_family))
continue;
- memcpy(&temp, &addr->a, sizeof(temp));
+ memcpy(&temp, &addr->a_h, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
&temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
if (sctp_list_single_entry(&bp->address_list)) {
addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list);
- if (sctp_is_any(&addr->a)) {
+ if (sctp_is_any(&addr->a_h)) {
cnt = sctp_copy_laddrs_to_user_old(sk, bp->port,
getaddrs.addr_num,
to);
list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
- memcpy(&temp, &addr->a, sizeof(temp));
+ memcpy(&temp, &addr->a_h, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
temp.v4.sin_port = htons(temp.v4.sin_port);
if (sctp_list_single_entry(&bp->address_list)) {
addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list);
- if (sctp_is_any(&addr->a)) {
+ if (sctp_is_any(&addr->a_h)) {
cnt = sctp_copy_laddrs_to_user(sk, bp->port,
&to, space_left);
if (cnt < 0) {
list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
- memcpy(&temp, &addr->a, sizeof(temp));
+ memcpy(&temp, &addr->a_h, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
if(space_left < addrlen)
if (!asoc->peer.primary_path)
return -ENOTCONN;
- asoc->peer.primary_path->ipaddr.v4.sin_port =
- htons(asoc->peer.primary_path->ipaddr.v4.sin_port);
- memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
- sizeof(union sctp_addr));
- asoc->peer.primary_path->ipaddr.v4.sin_port =
- ntohs(asoc->peer.primary_path->ipaddr.v4.sin_port);
+ flip_to_n((union sctp_addr *)&prim.ssp_addr,
+ &asoc->peer.primary_path->ipaddr_h);
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
(union sctp_addr *)&prim.ssp_addr);
{
struct sctp_bind_hashbucket *head; /* hash list */
struct sctp_bind_bucket *pp; /* hash list port iterator */
+ union sctp_addr tmp;
unsigned short snum;
int ret;
- /* NOTE: Remember to put this back to net order. */
- addr->v4.sin_port = ntohs(addr->v4.sin_port);
- snum = addr->v4.sin_port;
+ flip_to_h(&tmp, addr);
+ snum = ntohs(addr->v4.sin_port);
SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum);
sctp_local_bh_disable();
if (reuse && sk2->sk_reuse)
continue;
- if (sctp_bind_addr_match(&ep2->base.bind_addr, addr,
+ if (sctp_bind_addr_match(&ep2->base.bind_addr, &tmp,
sctp_sk(sk))) {
ret = (long)sk2;
goto fail_unlock;
fail:
sctp_local_bh_enable();
- addr->v4.sin_port = htons(addr->v4.sin_port);
return ret;
}
sctp_association_put(asoc);
}
+/* Do accounting for the receive space on the socket.
+ * Accounting for the association is done in ulpevent.c
+ * We set this as a destructor for the cloned data skbs so that
+ * accounting is done at the correct time.
+ */
+void sctp_sock_rfree(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+ atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
+}
+
+
/* Helper function to wait for space in the sndbuf. */
static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
size_t msg_len)
sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
event = sctp_skb2event(skb);
if (event->asoc == assoc) {
- sock_rfree(skb);
+ sctp_sock_rfree(skb);
__skb_unlink(skb, &oldsk->sk_receive_queue);
__skb_queue_tail(&newsk->sk_receive_queue, skb);
- skb_set_owner_r(skb, newsk);
+ sctp_skb_set_owner_r(skb, newsk);
}
}
sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
event = sctp_skb2event(skb);
if (event->asoc == assoc) {
- sock_rfree(skb);
+ sctp_sock_rfree(skb);
__skb_unlink(skb, &oldsp->pd_lobby);
__skb_queue_tail(queue, skb);
- skb_set_owner_r(skb, newsk);
+ sctp_skb_set_owner_r(skb, newsk);
}
}