aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Hartkopp <socketcan@hartkopp.net>2010-10-19 05:32:04 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-21 07:27:03 -0400
commit1e55659ce6ddb5247cee0b1f720d77a799902b85 (patch)
tree335e43324d5ad5e0979fb30e333cb1a4e1a47085
parent32a875adcdcf5f470bf967250cfd01722e23844f (diff)
can-raw: add msg_flags to distinguish local traffic
CAN has no addressing scheme. It is currently impossible for userspace to tell is a received CAN frame comes from another process on the local host, or from a remote CAN device. This patch add support for userspace applications to distinguish between 'own', 'local' and 'remote' CAN traffic. The distinction is made by returning flags in msg->msg_flags in the call to recvmsg(). The added documentation explains the introduced flags. Signed-off-by: Kurt Van Dijck <kurt.van.dijck@eia.be> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/can.txt12
-rw-r--r--net/can/raw.c33
2 files changed, 42 insertions, 3 deletions
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index cd79735013f..5b04b67ddca 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -22,6 +22,7 @@ This file contains
22 4.1.2 RAW socket option CAN_RAW_ERR_FILTER 22 4.1.2 RAW socket option CAN_RAW_ERR_FILTER
23 4.1.3 RAW socket option CAN_RAW_LOOPBACK 23 4.1.3 RAW socket option CAN_RAW_LOOPBACK
24 4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS 24 4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS
25 4.1.5 RAW socket returned message flags
25 4.2 Broadcast Manager protocol sockets (SOCK_DGRAM) 26 4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
26 4.3 connected transport protocols (SOCK_SEQPACKET) 27 4.3 connected transport protocols (SOCK_SEQPACKET)
27 4.4 unconnected transport protocols (SOCK_DGRAM) 28 4.4 unconnected transport protocols (SOCK_DGRAM)
@@ -471,6 +472,17 @@ solution for a couple of reasons:
471 setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, 472 setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
472 &recv_own_msgs, sizeof(recv_own_msgs)); 473 &recv_own_msgs, sizeof(recv_own_msgs));
473 474
475 4.1.5 RAW socket returned message flags
476
477 When using recvmsg() call, the msg->msg_flags may contain following flags:
478
479 MSG_DONTROUTE: set when the received frame was created on the local host.
480
481 MSG_CONFIRM: set when the frame was sent via the socket it is received on.
482 This flag can be interpreted as a 'transmission confirmation' when the
483 CAN driver supports the echo of frames on driver level, see 3.2 and 6.2.
484 In order to receive such messages, CAN_RAW_RECV_OWN_MSGS must be set.
485
474 4.2 Broadcast Manager protocol sockets (SOCK_DGRAM) 486 4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
475 4.3 connected transport protocols (SOCK_SEQPACKET) 487 4.3 connected transport protocols (SOCK_SEQPACKET)
476 4.4 unconnected transport protocols (SOCK_DGRAM) 488 4.4 unconnected transport protocols (SOCK_DGRAM)
diff --git a/net/can/raw.c b/net/can/raw.c
index 7d77e67e57a..e88f610fdb7 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -90,23 +90,39 @@ struct raw_sock {
90 can_err_mask_t err_mask; 90 can_err_mask_t err_mask;
91}; 91};
92 92
93/*
94 * Return pointer to store the extra msg flags for raw_recvmsg().
95 * We use the space of one unsigned int beyond the 'struct sockaddr_can'
96 * in skb->cb.
97 */
98static inline unsigned int *raw_flags(struct sk_buff *skb)
99{
100 BUILD_BUG_ON(sizeof(skb->cb) <= (sizeof(struct sockaddr_can) +
101 sizeof(unsigned int)));
102
103 /* return pointer after struct sockaddr_can */
104 return (unsigned int *)(&((struct sockaddr_can *)skb->cb)[1]);
105}
106
93static inline struct raw_sock *raw_sk(const struct sock *sk) 107static inline struct raw_sock *raw_sk(const struct sock *sk)
94{ 108{
95 return (struct raw_sock *)sk; 109 return (struct raw_sock *)sk;
96} 110}
97 111
98static void raw_rcv(struct sk_buff *skb, void *data) 112static void raw_rcv(struct sk_buff *oskb, void *data)
99{ 113{
100 struct sock *sk = (struct sock *)data; 114 struct sock *sk = (struct sock *)data;
101 struct raw_sock *ro = raw_sk(sk); 115 struct raw_sock *ro = raw_sk(sk);
102 struct sockaddr_can *addr; 116 struct sockaddr_can *addr;
117 struct sk_buff *skb;
118 unsigned int *pflags;
103 119
104 /* check the received tx sock reference */ 120 /* check the received tx sock reference */
105 if (!ro->recv_own_msgs && skb->sk == sk) 121 if (!ro->recv_own_msgs && oskb->sk == sk)
106 return; 122 return;
107 123
108 /* clone the given skb to be able to enqueue it into the rcv queue */ 124 /* clone the given skb to be able to enqueue it into the rcv queue */
109 skb = skb_clone(skb, GFP_ATOMIC); 125 skb = skb_clone(oskb, GFP_ATOMIC);
110 if (!skb) 126 if (!skb)
111 return; 127 return;
112 128
@@ -123,6 +139,14 @@ static void raw_rcv(struct sk_buff *skb, void *data)
123 addr->can_family = AF_CAN; 139 addr->can_family = AF_CAN;
124 addr->can_ifindex = skb->dev->ifindex; 140 addr->can_ifindex = skb->dev->ifindex;
125 141
142 /* add CAN specific message flags for raw_recvmsg() */
143 pflags = raw_flags(skb);
144 *pflags = 0;
145 if (oskb->sk)
146 *pflags |= MSG_DONTROUTE;
147 if (oskb->sk == sk)
148 *pflags |= MSG_CONFIRM;
149
126 if (sock_queue_rcv_skb(sk, skb) < 0) 150 if (sock_queue_rcv_skb(sk, skb) < 0)
127 kfree_skb(skb); 151 kfree_skb(skb);
128} 152}
@@ -707,6 +731,9 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
707 memcpy(msg->msg_name, skb->cb, msg->msg_namelen); 731 memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
708 } 732 }
709 733
734 /* assign the flags that have been recorded in raw_rcv() */
735 msg->msg_flags |= *(raw_flags(skb));
736
710 skb_free_datagram(sk, skb); 737 skb_free_datagram(sk, skb);
711 738
712 return size; 739 return size;