]> err.no Git - linux-2.6/blobdiff - net/sctp/socket.c
the scheduled ieee80211 softmac removal
[linux-2.6] / net / sctp / socket.c
index 7a8650f01d087133f319e5ba0f56b70c04a214f0..1316694d0a21ee77fe4473565f4d820ca7d2abbd 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -6,7 +6,7 @@
  * Copyright (c) 2001-2002 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions interface with the sockets layer to implement the
  * SCTP Extensions for the Sockets API.
  * functions--this file is the functions which populate the struct proto
  * for SCTP which is the BOTTOM of the sockets interface.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP 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
+ * This SCTP 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.
@@ -174,7 +174,8 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
                                sizeof(struct sctp_chunk);
 
        atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
-       sk_charge_skb(sk, chunk->skb);
+       sk->sk_wmem_queued += chunk->skb->truesize;
+       sk_mem_charge(sk, chunk->skb->truesize);
 }
 
 /* Verify that this is a valid address. */
@@ -524,7 +525,7 @@ static int sctp_send_asconf_add_ip(struct sock              *sk,
        ep = sp->ep;
 
        SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
-                         __FUNCTION__, sk, addrs, addrcnt);
+                         __func__, sk, addrs, addrcnt);
 
        list_for_each(pos, &ep->asocs) {
                asoc = list_entry(pos, struct sctp_association, asocs);
@@ -710,7 +711,7 @@ static int sctp_send_asconf_del_ip(struct sock              *sk,
        ep = sp->ep;
 
        SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
-                         __FUNCTION__, sk, addrs, addrcnt);
+                         __func__, sk, addrs, addrcnt);
 
        list_for_each(pos, &ep->asocs) {
                asoc = list_entry(pos, struct sctp_association, asocs);
@@ -1196,7 +1197,7 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
        struct sockaddr *kaddrs;
 
        SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
-                         __FUNCTION__, sk, addrs, addrs_size);
+                         __func__, sk, addrs, addrs_size);
 
        if (unlikely(addrs_size <= 0))
                return -EINVAL;
@@ -1910,7 +1911,8 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
                 * rwnd by that amount. If all the data in the skb is read,
                 * rwnd is updated when the event is freed.
                 */
-               sctp_assoc_rwnd_increase(event->asoc, copied);
+               if (!sctp_ulpevent_is_notification(event))
+                       sctp_assoc_rwnd_increase(event->asoc, copied);
                goto out;
        } else if ((event->msg_flags & MSG_NOTIFICATION) ||
                   (event->msg_flags & MSG_EOR))
@@ -1962,7 +1964,7 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk,
 static int sctp_setsockopt_events(struct sock *sk, char __user *optval,
                                        int optlen)
 {
-       if (optlen != sizeof(struct sctp_event_subscribe))
+       if (optlen > sizeof(struct sctp_event_subscribe))
                return -EINVAL;
        if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen))
                return -EFAULT;
@@ -3278,7 +3280,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
        sctp_lock_sock(sk);
 
        SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
-                         __FUNCTION__, sk, addr, addr_len);
+                         __func__, sk, addr, addr_len);
 
        /* Validate addr_len before calling common connect/connectx routine. */
        af = sctp_get_af_specific(addr->sa_family);
@@ -3799,7 +3801,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
                goto out;
        }
 
-       SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc);
+       SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __func__, sk, asoc);
 
        retval = sctp_do_peeloff(asoc, &newsock);
        if (retval < 0)
@@ -3813,7 +3815,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
        }
 
        SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n",
-                         __FUNCTION__, sk, asoc, newsock->sk, retval);
+                         __func__, sk, asoc, newsock->sk, retval);
 
        /* Return the fd mapped to the new socket.  */
        peeloff.sd = retval;
@@ -4313,6 +4315,9 @@ static int sctp_copy_laddrs_old(struct sock *sk, __u16 port,
                    (AF_INET6 == addr->a.sa.sa_family))
                        continue;
                memcpy(&temp, &addr->a, sizeof(temp));
+               if (!temp.v4.sin_port)
+                       temp.v4.sin_port = htons(port);
+
                sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
                                                                &temp);
                addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
@@ -4345,6 +4350,9 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
                    (AF_INET6 == addr->a.sa.sa_family))
                        continue;
                memcpy(&temp, &addr->a, sizeof(temp));
+               if (!temp.v4.sin_port)
+                       temp.v4.sin_port = htons(port);
+
                sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
                                                                &temp);
                addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
@@ -5062,6 +5070,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
        struct sctp_authchunks val;
        struct sctp_association *asoc;
        struct sctp_chunks_param *ch;
+       u32    num_chunks;
        char __user *to;
 
        if (len <= sizeof(struct sctp_authchunks))
@@ -5078,12 +5087,15 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
        ch = asoc->peer.peer_chunks;
 
        /* See if the user provided enough room for all the data */
-       if (len < ntohs(ch->param_hdr.length))
+       num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
+       if (len < num_chunks)
                return -EINVAL;
 
-       len = ntohs(ch->param_hdr.length);
+       len = num_chunks;
        if (put_user(len, optlen))
                return -EFAULT;
+       if (put_user(num_chunks, &p->gauth_number_of_chunks))
+               return -EFAULT;
        if (copy_to_user(to, ch->chunks, len))
                return -EFAULT;
 
@@ -5097,6 +5109,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
        struct sctp_authchunks val;
        struct sctp_association *asoc;
        struct sctp_chunks_param *ch;
+       u32    num_chunks;
        char __user *to;
 
        if (len <= sizeof(struct sctp_authchunks))
@@ -5115,12 +5128,15 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
        else
                ch = sctp_sk(sk)->ep->auth_chunk_list;
 
-       if (len < ntohs(ch->param_hdr.length))
+       num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
+       if (len < num_chunks)
                return -EINVAL;
 
-       len = ntohs(ch->param_hdr.length);
+       len = num_chunks;
        if (put_user(len, optlen))
                return -EFAULT;
+       if (put_user(num_chunks, &p->gauth_number_of_chunks))
+               return -EFAULT;
        if (copy_to_user(to, ch->chunks, len))
                return -EFAULT;
 
@@ -6035,10 +6051,10 @@ static void sctp_wfree(struct sk_buff *skb)
        atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
 
        /*
-        * This undoes what is done via sk_charge_skb
+        * This undoes what is done via sctp_set_owner_w and sk_mem_charge
         */
        sk->sk_wmem_queued   -= skb->truesize;
-       sk->sk_forward_alloc += skb->truesize;
+       sk_mem_uncharge(sk, skb->truesize);
 
        sock_wfree(skb);
        __sctp_write_space(asoc);
@@ -6059,9 +6075,9 @@ void sctp_sock_rfree(struct sk_buff *skb)
        atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
 
        /*
-        * Mimic the behavior of sk_stream_rfree
+        * Mimic the behavior of sock_rfree
         */
-       sk->sk_forward_alloc += event->rmem_len;
+       sk_mem_uncharge(sk, event->rmem_len);
 }
 
 
@@ -6170,7 +6186,7 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
        long current_timeo = *timeo_p;
        DEFINE_WAIT(wait);
 
-       SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
+       SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc,
                          (long)(*timeo_p));
 
        /* Increment the association's refcnt.  */
@@ -6480,6 +6496,7 @@ struct proto sctp_prot = {
        .memory_pressure = &sctp_memory_pressure,
        .enter_memory_pressure = sctp_enter_memory_pressure,
        .memory_allocated = &sctp_memory_allocated,
+       .sockets_allocated = &sctp_sockets_allocated,
        REF_PROTO_INUSE(sctp)
 };
 
@@ -6513,6 +6530,7 @@ struct proto sctpv6_prot = {
        .memory_pressure = &sctp_memory_pressure,
        .enter_memory_pressure = sctp_enter_memory_pressure,
        .memory_allocated = &sctp_memory_allocated,
+       .sockets_allocated = &sctp_sockets_allocated,
        REF_PROTO_INUSE(sctpv6)
 };
 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */