aboutsummaryrefslogtreecommitdiff
path: root/net/can/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/can/raw.c')
-rw-r--r--net/can/raw.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/net/can/raw.c b/net/can/raw.c
index e88f610fdb7..081e81fd017 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -37,8 +37,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
@@ -52,12 +50,13 @@
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
+#include <linux/can/skb.h>
#include <linux/can/raw.h>
#include <net/sock.h>
#include <net/net_namespace.h>
#define CAN_RAW_VERSION CAN_VERSION
-static __initdata const char banner[] =
+static __initconst const char banner[] =
KERN_INFO "can: raw protocol (rev " CAN_RAW_VERSION ")\n";
MODULE_DESCRIPTION("PF_CAN raw protocol");
@@ -84,6 +83,7 @@ struct raw_sock {
struct notifier_block notifier;
int loopback;
int recv_own_msgs;
+ int fd_frames;
int count; /* number of active filters */
struct can_filter dfilter; /* default/single filter */
struct can_filter *filter; /* pointer to filter(s) */
@@ -121,6 +121,10 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
if (!ro->recv_own_msgs && oskb->sk == sk)
return;
+ /* do not pass non-CAN2.0 frames to a legacy socket */
+ if (!ro->fd_frames && oskb->len != CAN_MTU)
+ return;
+
/* clone the given skb to be able to enqueue it into the rcv queue */
skb = skb_clone(oskb, GFP_ATOMIC);
if (!skb)
@@ -231,9 +235,9 @@ static int raw_enable_allfilters(struct net_device *dev, struct sock *sk)
}
static int raw_notifier(struct notifier_block *nb,
- unsigned long msg, void *data)
+ unsigned long msg, void *ptr)
{
- struct net_device *dev = (struct net_device *)data;
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
struct sock *sk = &ro->sk;
@@ -293,6 +297,7 @@ static int raw_init(struct sock *sk)
/* set default loopback behaviour */
ro->loopback = 1;
ro->recv_own_msgs = 0;
+ ro->fd_frames = 0;
/* set notifier */
ro->notifier.notifier_call = raw_notifier;
@@ -305,7 +310,12 @@ static int raw_init(struct sock *sk)
static int raw_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct raw_sock *ro = raw_sk(sk);
+ struct raw_sock *ro;
+
+ if (!sk)
+ return 0;
+
+ ro = raw_sk(sk);
unregister_netdevice_notifier(&ro->notifier);
@@ -566,6 +576,15 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
break;
+ case CAN_RAW_FD_FRAMES:
+ if (optlen != sizeof(ro->fd_frames))
+ return -EINVAL;
+
+ if (copy_from_user(&ro->fd_frames, optval, optlen))
+ return -EFAULT;
+
+ break;
+
default:
return -ENOPROTOOPT;
}
@@ -624,6 +643,12 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
val = &ro->recv_own_msgs;
break;
+ case CAN_RAW_FD_FRAMES:
+ if (len > sizeof(int))
+ len = sizeof(int);
+ val = &ro->fd_frames;
+ break;
+
default:
return -ENOPROTOOPT;
}
@@ -646,8 +671,10 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
int err;
if (msg->msg_name) {
- struct sockaddr_can *addr =
- (struct sockaddr_can *)msg->msg_name;
+ DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name);
+
+ if (msg->msg_namelen < sizeof(*addr))
+ return -EINVAL;
if (addr->can_family != AF_CAN)
return -EINVAL;
@@ -656,30 +683,35 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
} else
ifindex = ro->ifindex;
- if (size != sizeof(struct can_frame))
- return -EINVAL;
+ if (ro->fd_frames) {
+ if (unlikely(size != CANFD_MTU && size != CAN_MTU))
+ return -EINVAL;
+ } else {
+ if (unlikely(size != CAN_MTU))
+ return -EINVAL;
+ }
dev = dev_get_by_index(&init_net, ifindex);
if (!dev)
return -ENXIO;
- skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
- &err);
+ skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
+ msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
goto put_dev;
+ can_skb_reserve(skb);
+ can_skb_prv(skb)->ifindex = dev->ifindex;
+
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err < 0)
goto free_skb;
- err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
- if (err < 0)
- goto free_skb;
- /* to be able to check the received tx sock reference in raw_rcv() */
- skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
+ sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
skb->dev = dev;
skb->sk = sk;
+ skb->priority = sk->sk_priority;
err = can_send(skb, ro->loopback);
@@ -727,6 +759,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
sock_recv_ts_and_drops(msg, sk, skb);
if (msg->msg_name) {
+ __sockaddr_check_size(sizeof(struct sockaddr_can));
msg->msg_namelen = sizeof(struct sockaddr_can);
memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
}
@@ -739,7 +772,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
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,
@@ -748,7 +781,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,
@@ -766,7 +799,7 @@ static struct proto raw_proto __read_mostly = {
.init = raw_init,
};
-static struct can_proto raw_can_proto __read_mostly = {
+static const struct can_proto raw_can_proto = {
.type = SOCK_RAW,
.protocol = CAN_RAW,
.ops = &raw_ops,