On do, 25 apr 2019 13:46:19 +0200, Oleksij Rempel wrote: > Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx> > --- > include/uapi/linux/can/j1939.h | 6 +++++ > net/can/j1939/j1939-priv.h | 2 ++ > net/can/j1939/socket.c | 48 +++++++++++++++++++++++++++++++--- > net/can/j1939/transport.c | 33 ++++++++++++++++++++--- > 4 files changed, 83 insertions(+), 6 deletions(-) > > diff --git a/include/uapi/linux/can/j1939.h b/include/uapi/linux/can/j1939.h > index c7eb94d2ab10..77f8068bcc62 100644 > --- a/include/uapi/linux/can/j1939.h > +++ b/include/uapi/linux/can/j1939.h > @@ -72,6 +72,8 @@ enum { > SCM_J1939_DEST_ADDR = 1, > SCM_J1939_DEST_NAME = 2, > SCM_J1939_PRIO = 3, > + SCM_J1939_RECVERR = 4, > + SCM_J1939_PKTINFO = 5, > }; > > struct j1939_filter { > @@ -83,6 +85,10 @@ struct j1939_filter { > __u8 addr_mask; > }; > > +struct j1939_pktinfo { > + __u64 cookie; > +}; > + > #define J1939_FILTER_MAX 512 /* maximum number of j1939_filter set via setsockopt() */ > > #endif /* !_UAPI_CAN_J1939_H_ */ > diff --git a/net/can/j1939/j1939-priv.h b/net/can/j1939/j1939-priv.h > index 4cb2e63a86c4..cf42550de6d2 100644 > --- a/net/can/j1939/j1939-priv.h > +++ b/net/can/j1939/j1939-priv.h > @@ -207,6 +207,8 @@ struct j1939_session { > bool transmission; > bool extd; > unsigned int total_message_size; /* Total message size, number of bytes */ > + int err; > + u64 cookie; > > /* Packets counters for a (extended) transfer session. The packet is > * maximal of 7 bytes. */ > diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c > index ea9ce6d99332..c88c67e93536 100644 > --- a/net/can/j1939/socket.c > +++ b/net/can/j1939/socket.c > @@ -608,6 +608,10 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg, > struct j1939_sk_buff_cb *skcb; > int ret = 0; > > + if (flags & MSG_ERRQUEUE) > + return sock_recv_errqueue(sock->sk, msg, size, SOL_CAN_J1939, > + SCM_J1939_RECVERR); > + > skb = skb_recv_datagram(sk, flags, 0, &ret); > if (!skb) > return ret; > @@ -721,8 +725,9 @@ void j1939_sk_send_multi_abort(struct j1939_priv *priv, struct sock *sk, > sk->sk_error_report(sk); > } > > -static int j1939_sk_send_multi(struct j1939_priv *priv, struct sock *sk, > - struct msghdr *msg, size_t size) > +static int j1939_sk_send_multi(struct j1939_priv *priv, struct sock *sk, > + struct msghdr *msg, size_t size, > + struct j1939_pktinfo *info) > > { > struct j1939_sock *jsk = j1939_sk(sk); > @@ -788,6 +793,7 @@ static int j1939_sk_send_multi(struct j1939_priv *priv, struct sock *sk, > ret = PTR_ERR(session); > goto kfree_skb; > } > + session->cookie = info->cookie; > } > } else { > j1939_session_skb_queue(session, skb); > @@ -845,6 +851,35 @@ static int j1939_sk_send_one(struct j1939_priv *priv, struct sock *sk, > return ret ? ret : size; > } > > +static int j1939_sk_cmsg_send(struct sock *sk, struct msghdr *msg, > + struct j1939_pktinfo *info) > +{ > + struct cmsghdr *cmsg; > + > + for_each_cmsghdr(cmsg, msg) { > + if (!CMSG_OK(msg, cmsg)) > + return -EINVAL; > + > + if (cmsg->cmsg_level != SOL_CAN_J1939) > + continue; > + switch (cmsg->cmsg_type) { > + case SCM_J1939_PKTINFO: > + { > + struct j1939_pktinfo *tinfo; > + > + if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct j1939_pktinfo))) > + return -EINVAL; > + tinfo = (struct j1939_pktinfo *)CMSG_DATA(cmsg); > + memcpy(info, tinfo, sizeof(*info)); > + break; > + } > + default: > + return -EINVAL; > + } > + } > + return 0; > +} > + > static int j1939_sk_sendmsg(struct socket *sock, struct msghdr *msg, > size_t size) > { > @@ -852,6 +887,7 @@ static int j1939_sk_sendmsg(struct socket *sock, struct msghdr *msg, > struct j1939_sock *jsk = j1939_sk(sk); > struct j1939_priv *priv; > struct net_device *ndev; > + struct j1939_pktinfo info; info is initialized only when msg_controllen is set. This is not necessarily always the case?