]> rtime.felk.cvut.cz Git - socketcan-devel.git/blobdiff - kernel/2.6/net/can/raw.c
can: make struct proto const
[socketcan-devel.git] / kernel / 2.6 / net / can / raw.c
index 5647f72776e7abbed09162fd320c2d0577b54dc6..5ab46cea80890f3c440ba616055fff3330a5526c 100644 (file)
@@ -50,9 +50,9 @@
 #include <linux/socket.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
-#include <linux/can.h>
-#include <linux/can/core.h>
-#include <linux/can/raw.h>
+#include <socketcan/can.h>
+#include <socketcan/can/core.h>
+#include <socketcan/can/raw.h>
 #include <net/sock.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
 #include <net/net_namespace.h>
@@ -61,7 +61,7 @@
 #include "compat.h"
 #endif
 
-#include <linux/can/version.h> /* for RCSID. Removed by mkpatch script */
+#include <socketcan/can/version.h> /* for RCSID. Removed by mkpatch script */
 RCSID("$Id$");
 
 #define CAN_RAW_VERSION CAN_VERSION
@@ -71,6 +71,7 @@ static __initdata const char banner[] =
 MODULE_DESCRIPTION("PF_CAN raw protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
+MODULE_ALIAS("can-proto-1");
 
 #define MASK_ALL 0
 
@@ -101,6 +102,20 @@ struct raw_sock {
        can_err_mask_t err_mask;
 };
 
+/*
+ * Return pointer to store the extra msg flags for raw_recvmsg().
+ * We use the space of one unsigned int beyond the 'struct sockaddr_can'
+ * in skb->cb.
+ */
+static inline unsigned int *raw_flags(struct sk_buff *skb)
+{
+       BUILD_BUG_ON(sizeof(skb->cb) <= (sizeof(struct sockaddr_can) +
+                                        sizeof(unsigned int)));
+
+       /* return pointer after struct sockaddr_can */
+       return (unsigned int *)(&((struct sockaddr_can *)skb->cb)[1]);
+}
+
 static inline struct raw_sock *raw_sk(const struct sock *sk)
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
@@ -110,18 +125,20 @@ static inline struct raw_sock *raw_sk(const struct sock *sk)
 #endif
 }
 
-static void raw_rcv(struct sk_buff *skb, void *data)
+static void raw_rcv(struct sk_buff *oskb, void *data)
 {
        struct sock *sk = (struct sock *)data;
        struct raw_sock *ro = raw_sk(sk);
        struct sockaddr_can *addr;
+       struct sk_buff *skb;
+       unsigned int *pflags;
 
        /* check the received tx sock reference */
-       if ((!ro->recv_own_msgs) && (skb->sk == sk))
+       if (!ro->recv_own_msgs && oskb->sk == sk)
                return;
 
        /* clone the given skb to be able to enqueue it into the rcv queue */
-       skb = skb_clone(skb, GFP_ATOMIC);
+       skb = skb_clone(oskb, GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -138,6 +155,14 @@ static void raw_rcv(struct sk_buff *skb, void *data)
        addr->can_family  = AF_CAN;
        addr->can_ifindex = skb->dev->ifindex;
 
+       /* add CAN specific message flags for raw_recvmsg() */
+       pflags = raw_flags(skb);
+       *pflags = 0;
+       if (oskb->sk)
+               *pflags |= MSG_DONTROUTE;
+       if (oskb->sk == sk)
+               *pflags |= MSG_CONFIRM;
+
        if (sock_queue_rcv_skb(sk, skb) < 0)
                kfree_skb(skb);
 }
@@ -335,6 +360,9 @@ static int raw_release(struct socket *sock)
        ro->bound   = 0;
        ro->count   = 0;
 
+       sock_orphan(sk);
+       sock->sk = NULL;
+
        release_sock(sk);
        sock_put(sk);
 
@@ -434,8 +462,13 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr,
        return 0;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+static int raw_setsockopt(struct socket *sock, int level, int optname,
+                         char __user *optval, unsigned int optlen)
+#else
 static int raw_setsockopt(struct socket *sock, int level, int optname,
                          char __user *optval, int optlen)
+#endif
 {
        struct sock *sk = sock->sk;
        struct raw_sock *ro = raw_sk(sk);
@@ -655,6 +688,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
                struct sockaddr_can *addr =
                        (struct sockaddr_can *)msg->msg_name;
 
+               if (msg->msg_namelen < sizeof(*addr))
+                       return -EINVAL;
+
                if (addr->can_family != AF_CAN)
                        return -EINVAL;
 
@@ -730,12 +766,15 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
                memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
        }
 
+       /* assign the flags that have been recorded in raw_rcv() */
+       msg->msg_flags |= *(raw_flags(skb));
+
        skb_free_datagram(sk, skb);
 
        return size;
 }
 
-static struct proto_ops raw_ops __read_mostly = {
+static const struct proto_ops raw_ops = {
        .family        = PF_CAN,
        .release       = raw_release,
        .bind          = raw_bind,
@@ -744,7 +783,7 @@ static struct proto_ops raw_ops __read_mostly = {
        .accept        = sock_no_accept,
        .getname       = raw_getname,
        .poll          = datagram_poll,
-       .ioctl         = NULL,          /* use can_ioctl() from af_can.c */
+       .ioctl         = can_ioctl,     /* use can_ioctl() from af_can.c */
        .listen        = sock_no_listen,
        .shutdown      = sock_no_shutdown,
        .setsockopt    = raw_setsockopt,
@@ -755,7 +794,22 @@ static struct proto_ops raw_ops __read_mostly = {
        .sendpage      = sock_no_sendpage,
 };
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
+static struct proto raw_proto __read_mostly = {
+       .name       = "CAN_RAW",
+       .owner      = THIS_MODULE,
+       .obj_size   = sizeof(struct raw_sock),
+       .init       = raw_init,
+};
+
+static struct can_proto raw_can_proto __read_mostly = {
+       .type       = SOCK_RAW,
+       .protocol   = CAN_RAW,
+       .ops        = &raw_ops,
+       .prot       = &raw_proto,
+};
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
 static struct proto raw_proto __read_mostly = {
        .name       = "CAN_RAW",
        .owner      = THIS_MODULE,