aboutsummaryrefslogtreecommitdiffstats
path: root/net/can/raw.c
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 /net/can/raw.c
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>
Diffstat (limited to 'net/can/raw.c')
-rw-r--r--net/can/raw.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/net/can/raw.c b/net/can/raw.c
index 7d77e67e57af..e88f610fdb7b 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;