..and move part of j1939_sk_sendmsg to it. This function is needed for multi skb support within single session. Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx> --- net/can/j1939/socket.c | 99 +++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c index e003d3cae24c..b1ab7df7eef6 100644 --- a/net/can/j1939/socket.c +++ b/net/can/j1939/socket.c @@ -620,47 +620,14 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg, return size; } -static int j1939_sk_sendmsg(struct socket *sock, struct msghdr *msg, - size_t size) +static struct sk_buff *j1939_sk_alloc_skb(struct net_device *ndev, struct sock *sk, + struct msghdr *msg, size_t size, int *errcode) { - struct sock *sk = sock->sk; struct j1939_sock *jsk = j1939_sk(sk); - struct sockaddr_can *addr = msg->msg_name; struct j1939_sk_buff_cb *skcb; - struct j1939_priv *priv; struct sk_buff *skb; - struct net_device *ndev; - int ifindex; int ret; - /* various socket state tests */ - if (!(jsk->state & J1939_SOCK_BOUND)) - return -EBADFD; - - ifindex = jsk->ifindex; - - if (jsk->addr.sa == J1939_NO_ADDR && !jsk->addr.src_name) - /* no address assigned yet */ - return -EBADFD; - - /* deal with provided address info */ - if (msg->msg_name) { - if (msg->msg_namelen < J1939_MIN_NAMELEN) - return -EINVAL; - if (addr->can_family != AF_CAN) - return -EINVAL; - if (j1939_pgn_is_valid(addr->can_addr.j1939.pgn) && - !j1939_pgn_is_clean_pdu(addr->can_addr.j1939.pgn)) - return -EINVAL; - /* TODO: always check if ifindex is correct? */ - if (addr->can_ifindex && ifindex != addr->can_ifindex) - return -EBADFD; - } - - ndev = dev_get_by_index(sock_net(sk), ifindex); - if (!ndev) - return -ENXIO; - skb = sock_alloc_send_skb(sk, size + sizeof(struct can_frame) - @@ -668,7 +635,7 @@ static int j1939_sk_sendmsg(struct socket *sock, struct msghdr *msg, sizeof(struct can_skb_priv), msg->msg_flags & MSG_DONTWAIT, &ret); if (!skb) - goto put_dev; + goto failure; can_skb_reserve(skb); can_skb_prv(skb)->ifindex = ndev->ifindex; @@ -699,13 +666,63 @@ static int j1939_sk_sendmsg(struct socket *sock, struct msghdr *msg, if (j1939_pgn_is_valid(addr->can_addr.j1939.pgn)) skcb->addr.pgn = addr->can_addr.j1939.pgn; } - if (!j1939_pgn_is_valid(skcb->addr.pgn)) { - ret = -EINVAL; - goto free_skb; + + *errcode = ret; + return skb; + +free_skb: + kfree_skb(skb); +failure: + *errcode = ret; + return NULL; +} + +static int j1939_sk_sendmsg(struct socket *sock, struct msghdr *msg, + size_t size) +{ + struct sock *sk = sock->sk; + struct j1939_sock *jsk = j1939_sk(sk); + struct sockaddr_can *addr = msg->msg_name; + struct j1939_priv *priv; + struct sk_buff *skb; + struct net_device *ndev; + int ifindex; + int ret; + + /* various socket state tests */ + if (!(jsk->state & J1939_SOCK_BOUND)) + return -EBADFD; + + ifindex = jsk->ifindex; + + if (jsk->addr.sa == J1939_NO_ADDR && !jsk->addr.src_name) + /* no address assigned yet */ + return -EBADFD; + + /* deal with provided address info */ + if (msg->msg_name) { + if (msg->msg_namelen < J1939_MIN_NAMELEN) + return -EINVAL; + if (addr->can_family != AF_CAN) + return -EINVAL; + if (j1939_pgn_is_valid(addr->can_addr.j1939.pgn) && + !j1939_pgn_is_clean_pdu(addr->can_addr.j1939.pgn)) + return -EINVAL; + /* TODO: always check if ifindex is correct? */ + if (addr->can_ifindex && ifindex != addr->can_ifindex) + return -EBADFD; } - if (skcb->msg_flags & MSG_SYN) { - if (skcb->msg_flags & MSG_DONTWAIT) { + ndev = dev_get_by_index(sock_net(sk), ifindex); + if (!ndev) + return -ENXIO; + + skb = j1939_sk_alloc_skb(ndev, sk, msg, size, &ret); + if (!skb) + goto put_dev; + + if (msg->msg_flags & MSG_SYN) { + if (msg->msg_flags & MSG_DONTWAIT) { ret = j1939_sock_pending_add_first(&jsk->sk); if (ret > 0) ret = -EAGAIN; -- 2.19.1