vserver 1.9.3
[linux-2.6.git] / net / packet / af_packet.c
index 7ebb64d..1b441a6 100644 (file)
@@ -65,6 +65,8 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
+#include <asm/page.h>
+#include <asm/io.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/poll.h>
@@ -172,7 +174,7 @@ struct packet_opt
 {
        struct tpacket_stats    stats;
 #ifdef CONFIG_PACKET_MMAP
-       unsigned long           *pg_vec;
+       char *                  *pg_vec;
        unsigned int            head;
        unsigned int            frames_per_block;
        unsigned int            frame_size;
@@ -197,15 +199,15 @@ struct packet_opt
 
 #ifdef CONFIG_PACKET_MMAP
 
-static inline unsigned long packet_lookup_frame(struct packet_opt *po, unsigned int position)
+static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int position)
 {
        unsigned int pg_vec_pos, frame_offset;
-       unsigned long frame;
+       char *frame;
 
        pg_vec_pos = position / po->frames_per_block;
        frame_offset = position % po->frames_per_block;
 
-       frame = (unsigned long) (po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
+       frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
        
        return frame;
 }
@@ -784,11 +786,13 @@ out:
 static int packet_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       struct packet_opt *po = pkt_sk(sk);
+       struct packet_opt *po;
 
        if (!sk)
                return 0;
 
+       po = pkt_sk(sk);
+
        write_lock_bh(&packet_sklist_lock);
        sk_del_node_init(sk);
        write_unlock_bh(&packet_sklist_lock);
@@ -1037,7 +1041,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
        int copied, err;
 
        err = -EINVAL;
-       if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC))
+       if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
                goto out;
 
 #if 0
@@ -1292,7 +1296,7 @@ static void packet_flush_mclist(struct sock *sk)
 #endif
 
 static int
-packet_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
+packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
 {
        struct sock *sk = sock->sk;
        int ret;
@@ -1347,7 +1351,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char *optval, int
 }
 
 int packet_getsockopt(struct socket *sock, int level, int optname,
-                     char *optval, int *optlen)
+                     char __user *optval, int __user *optlen)
 {
        int len;
        struct sock *sk = sock->sk;
@@ -1450,7 +1454,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
                case SIOCOUTQ:
                {
                        int amount = atomic_read(&sk->sk_wmem_alloc);
-                       return put_user(amount, (int *)arg);
+                       return put_user(amount, (int __user *)arg);
                }
                case SIOCINQ:
                {
@@ -1462,10 +1466,10 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
                        if (skb)
                                amount = skb->len;
                        spin_unlock_bh(&sk->sk_receive_queue.lock);
-                       return put_user(amount, (int *)arg);
+                       return put_user(amount, (int __user *)arg);
                }
                case SIOCGSTAMP:
-                       return sock_get_timestamp(sk, (struct timeval *)arg);
+                       return sock_get_timestamp(sk, (struct timeval __user *)arg);
                        
 #ifdef CONFIG_INET
                case SIOCADDRT:
@@ -1486,7 +1490,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
 #endif
 
                default:
-                       return dev_ioctl(cmd, (void *)arg);
+                       return dev_ioctl(cmd, (void __user *)arg);
        }
        return 0;
 }
@@ -1548,7 +1552,12 @@ static struct vm_operations_struct packet_mmap_ops = {
        .close =packet_mm_close,
 };
 
-static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
+static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
+{
+       return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
+}
+
+static void free_pg_vec(char **pg_vec, unsigned order, unsigned len)
 {
        int i;
 
@@ -1556,10 +1565,10 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
                if (pg_vec[i]) {
                        struct page *page, *pend;
 
-                       pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
+                       pend = pg_vec_endpage(pg_vec[i], order);
                        for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
                                ClearPageReserved(page);
-                       free_pages(pg_vec[i], order);
+                       free_pages((unsigned long)pg_vec[i], order);
                }
        }
        kfree(pg_vec);
@@ -1568,7 +1577,7 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
 
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
 {
-       unsigned long *pg_vec = NULL;
+       char **pg_vec = NULL;
        struct packet_opt *po = pkt_sk(sk);
        int was_running, num, order = 0;
        int err = 0;
@@ -1603,18 +1612,18 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
                err = -ENOMEM;
 
-               pg_vec = kmalloc(req->tp_block_nr*sizeof(unsigned long*), GFP_KERNEL);
+               pg_vec = kmalloc(req->tp_block_nr*sizeof(char *), GFP_KERNEL);
                if (pg_vec == NULL)
                        goto out;
-               memset(pg_vec, 0, req->tp_block_nr*sizeof(unsigned long*));
+               memset(pg_vec, 0, req->tp_block_nr*sizeof(char **));
 
                for (i=0; i<req->tp_block_nr; i++) {
                        struct page *page, *pend;
-                       pg_vec[i] = __get_free_pages(GFP_KERNEL, order);
+                       pg_vec[i] = (char *)__get_free_pages(GFP_KERNEL, order);
                        if (!pg_vec[i])
                                goto out_free_pgvec;
 
-                       pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
+                       pend = pg_vec_endpage(pg_vec[i], order);
                        for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
                                SetPageReserved(page);
                }
@@ -1622,7 +1631,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
                l = 0;
                for (i=0; i<req->tp_block_nr; i++) {
-                       unsigned long ptr = pg_vec[i];
+                       char *ptr = pg_vec[i];
                        struct tpacket_hdr *header;
                        int k;