aboutsummaryrefslogtreecommitdiffstats
path: root/net/can/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/can/raw.c')
-rw-r--r--net/can/raw.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/net/can/raw.c b/net/can/raw.c
index a10e3338f084..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}
@@ -647,12 +671,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
647 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 671 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
648 if (err < 0) 672 if (err < 0)
649 goto free_skb; 673 goto free_skb;
650 err = sock_tx_timestamp(msg, sk, skb_tx(skb)); 674 err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
651 if (err < 0) 675 if (err < 0)
652 goto free_skb; 676 goto free_skb;
653 677
654 /* to be able to check the received tx sock reference in raw_rcv() */ 678 /* to be able to check the received tx sock reference in raw_rcv() */
655 skb_tx(skb)->prevent_sk_orphan = 1; 679 skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
656 680
657 skb->dev = dev; 681 skb->dev = dev;
658 skb->sk = sk; 682 skb->sk = sk;
@@ -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;