xref: /openbmc/linux/net/can/isotp.c (revision e8c127b0576660da9195504fe8393fe9da3de9ce)
1e057dd3fSOliver Hartkopp // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2e057dd3fSOliver Hartkopp /* isotp.c - ISO 15765-2 CAN transport protocol for protocol family CAN
3e057dd3fSOliver Hartkopp  *
4e057dd3fSOliver Hartkopp  * This implementation does not provide ISO-TP specific return values to the
5e057dd3fSOliver Hartkopp  * userspace.
6e057dd3fSOliver Hartkopp  *
7e057dd3fSOliver Hartkopp  * - RX path timeout of data reception leads to -ETIMEDOUT
8e057dd3fSOliver Hartkopp  * - RX path SN mismatch leads to -EILSEQ
9e057dd3fSOliver Hartkopp  * - RX path data reception with wrong padding leads to -EBADMSG
10e057dd3fSOliver Hartkopp  * - TX path flowcontrol reception timeout leads to -ECOMM
11e057dd3fSOliver Hartkopp  * - TX path flowcontrol reception overflow leads to -EMSGSIZE
12e057dd3fSOliver Hartkopp  * - TX path flowcontrol reception with wrong layout/padding leads to -EBADMSG
13e057dd3fSOliver Hartkopp  * - when a transfer (tx) is on the run the next write() blocks until it's done
14e057dd3fSOliver Hartkopp  * - use CAN_ISOTP_WAIT_TX_DONE flag to block the caller until the PDU is sent
15e057dd3fSOliver Hartkopp  * - as we have static buffers the check whether the PDU fits into the buffer
16e057dd3fSOliver Hartkopp  *   is done at FF reception time (no support for sending 'wait frames')
17e057dd3fSOliver Hartkopp  *
18e057dd3fSOliver Hartkopp  * Copyright (c) 2020 Volkswagen Group Electronic Research
19e057dd3fSOliver Hartkopp  * All rights reserved.
20e057dd3fSOliver Hartkopp  *
21e057dd3fSOliver Hartkopp  * Redistribution and use in source and binary forms, with or without
22e057dd3fSOliver Hartkopp  * modification, are permitted provided that the following conditions
23e057dd3fSOliver Hartkopp  * are met:
24e057dd3fSOliver Hartkopp  * 1. Redistributions of source code must retain the above copyright
25e057dd3fSOliver Hartkopp  *    notice, this list of conditions and the following disclaimer.
26e057dd3fSOliver Hartkopp  * 2. Redistributions in binary form must reproduce the above copyright
27e057dd3fSOliver Hartkopp  *    notice, this list of conditions and the following disclaimer in the
28e057dd3fSOliver Hartkopp  *    documentation and/or other materials provided with the distribution.
29e057dd3fSOliver Hartkopp  * 3. Neither the name of Volkswagen nor the names of its contributors
30e057dd3fSOliver Hartkopp  *    may be used to endorse or promote products derived from this software
31e057dd3fSOliver Hartkopp  *    without specific prior written permission.
32e057dd3fSOliver Hartkopp  *
33e057dd3fSOliver Hartkopp  * Alternatively, provided that this notice is retained in full, this
34e057dd3fSOliver Hartkopp  * software may be distributed under the terms of the GNU General
35e057dd3fSOliver Hartkopp  * Public License ("GPL") version 2, in which case the provisions of the
36e057dd3fSOliver Hartkopp  * GPL apply INSTEAD OF those given above.
37e057dd3fSOliver Hartkopp  *
38e057dd3fSOliver Hartkopp  * The provided data structures and external interfaces from this code
39e057dd3fSOliver Hartkopp  * are not restricted to be used by modules with a GPL compatible license.
40e057dd3fSOliver Hartkopp  *
41e057dd3fSOliver Hartkopp  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
42e057dd3fSOliver Hartkopp  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
43e057dd3fSOliver Hartkopp  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
44e057dd3fSOliver Hartkopp  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
45e057dd3fSOliver Hartkopp  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46e057dd3fSOliver Hartkopp  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47e057dd3fSOliver Hartkopp  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48e057dd3fSOliver Hartkopp  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49e057dd3fSOliver Hartkopp  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50e057dd3fSOliver Hartkopp  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51e057dd3fSOliver Hartkopp  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52e057dd3fSOliver Hartkopp  * DAMAGE.
53e057dd3fSOliver Hartkopp  */
54e057dd3fSOliver Hartkopp 
55e057dd3fSOliver Hartkopp #include <linux/module.h>
56e057dd3fSOliver Hartkopp #include <linux/init.h>
57e057dd3fSOliver Hartkopp #include <linux/interrupt.h>
587c759040SOliver Hartkopp #include <linux/spinlock.h>
59e057dd3fSOliver Hartkopp #include <linux/hrtimer.h>
60e057dd3fSOliver Hartkopp #include <linux/wait.h>
61e057dd3fSOliver Hartkopp #include <linux/uio.h>
62e057dd3fSOliver Hartkopp #include <linux/net.h>
63e057dd3fSOliver Hartkopp #include <linux/netdevice.h>
64e057dd3fSOliver Hartkopp #include <linux/socket.h>
65e057dd3fSOliver Hartkopp #include <linux/if_arp.h>
66e057dd3fSOliver Hartkopp #include <linux/skbuff.h>
67e057dd3fSOliver Hartkopp #include <linux/can.h>
68e057dd3fSOliver Hartkopp #include <linux/can/core.h>
69e057dd3fSOliver Hartkopp #include <linux/can/skb.h>
70e057dd3fSOliver Hartkopp #include <linux/can/isotp.h>
71e057dd3fSOliver Hartkopp #include <linux/slab.h>
72e057dd3fSOliver Hartkopp #include <net/sock.h>
73e057dd3fSOliver Hartkopp #include <net/net_namespace.h>
74e057dd3fSOliver Hartkopp 
75e057dd3fSOliver Hartkopp MODULE_DESCRIPTION("PF_CAN isotp 15765-2:2016 protocol");
76e057dd3fSOliver Hartkopp MODULE_LICENSE("Dual BSD/GPL");
77e057dd3fSOliver Hartkopp MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
78e057dd3fSOliver Hartkopp MODULE_ALIAS("can-proto-6");
79e057dd3fSOliver Hartkopp 
80f522d955SOliver Hartkopp #define ISOTP_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_addr.tp)
81f522d955SOliver Hartkopp 
82e057dd3fSOliver Hartkopp #define SINGLE_MASK(id) (((id) & CAN_EFF_FLAG) ? \
83e057dd3fSOliver Hartkopp 			 (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \
84e057dd3fSOliver Hartkopp 			 (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
85e057dd3fSOliver Hartkopp 
86e057dd3fSOliver Hartkopp /* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
87e057dd3fSOliver Hartkopp  * take full 32 bit values (4 Gbyte). We would need some good concept to handle
8896d1c81eSOliver Hartkopp  * this between user space and kernel space. For now set the static buffer to
8996d1c81eSOliver Hartkopp  * something about 8 kbyte to be able to test this new functionality.
90e057dd3fSOliver Hartkopp  */
9196d1c81eSOliver Hartkopp #define DEFAULT_MAX_PDU_SIZE 8300
9296d1c81eSOliver Hartkopp 
9396d1c81eSOliver Hartkopp /* maximum PDU size before ISO 15765-2:2016 extension was 4095 */
9496d1c81eSOliver Hartkopp #define MAX_12BIT_PDU_SIZE 4095
9596d1c81eSOliver Hartkopp 
9696d1c81eSOliver Hartkopp /* limit the isotp pdu size from the optional module parameter to 1MByte */
9796d1c81eSOliver Hartkopp #define MAX_PDU_SIZE (1025 * 1024U)
9896d1c81eSOliver Hartkopp 
9996d1c81eSOliver Hartkopp static unsigned int max_pdu_size __read_mostly = DEFAULT_MAX_PDU_SIZE;
10096d1c81eSOliver Hartkopp module_param(max_pdu_size, uint, 0444);
10196d1c81eSOliver Hartkopp MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default "
10296d1c81eSOliver Hartkopp 		 __stringify(DEFAULT_MAX_PDU_SIZE) ")");
103e057dd3fSOliver Hartkopp 
104e057dd3fSOliver Hartkopp /* N_PCI type values in bits 7-4 of N_PCI bytes */
105e057dd3fSOliver Hartkopp #define N_PCI_SF 0x00	/* single frame */
106e057dd3fSOliver Hartkopp #define N_PCI_FF 0x10	/* first frame */
107e057dd3fSOliver Hartkopp #define N_PCI_CF 0x20	/* consecutive frame */
108e057dd3fSOliver Hartkopp #define N_PCI_FC 0x30	/* flow control */
109e057dd3fSOliver Hartkopp 
110e057dd3fSOliver Hartkopp #define N_PCI_SZ 1	/* size of the PCI byte #1 */
111e057dd3fSOliver Hartkopp #define SF_PCI_SZ4 1	/* size of SingleFrame PCI including 4 bit SF_DL */
112e057dd3fSOliver Hartkopp #define SF_PCI_SZ8 2	/* size of SingleFrame PCI including 8 bit SF_DL */
113e057dd3fSOliver Hartkopp #define FF_PCI_SZ12 2	/* size of FirstFrame PCI including 12 bit FF_DL */
114e057dd3fSOliver Hartkopp #define FF_PCI_SZ32 6	/* size of FirstFrame PCI including 32 bit FF_DL */
115e057dd3fSOliver Hartkopp #define FC_CONTENT_SZ 3	/* flow control content size in byte (FS/BS/STmin) */
116e057dd3fSOliver Hartkopp 
117e057dd3fSOliver Hartkopp #define ISOTP_CHECK_PADDING (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA)
1189f39d365SOliver Hartkopp #define ISOTP_ALL_BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
119e057dd3fSOliver Hartkopp 
120e057dd3fSOliver Hartkopp /* Flow Status given in FC frame */
121e057dd3fSOliver Hartkopp #define ISOTP_FC_CTS 0		/* clear to send */
122e057dd3fSOliver Hartkopp #define ISOTP_FC_WT 1		/* wait */
123e057dd3fSOliver Hartkopp #define ISOTP_FC_OVFLW 2	/* overflow */
124e057dd3fSOliver Hartkopp 
12586633786SOliver Hartkopp #define ISOTP_FC_TIMEOUT 1	/* 1 sec */
12686633786SOliver Hartkopp #define ISOTP_ECHO_TIMEOUT 2	/* 2 secs */
12786633786SOliver Hartkopp 
128e057dd3fSOliver Hartkopp enum {
129e057dd3fSOliver Hartkopp 	ISOTP_IDLE = 0,
130e057dd3fSOliver Hartkopp 	ISOTP_WAIT_FIRST_FC,
131e057dd3fSOliver Hartkopp 	ISOTP_WAIT_FC,
132e057dd3fSOliver Hartkopp 	ISOTP_WAIT_DATA,
13305173743SOliver Hartkopp 	ISOTP_SENDING,
13405173743SOliver Hartkopp 	ISOTP_SHUTDOWN,
135e057dd3fSOliver Hartkopp };
136e057dd3fSOliver Hartkopp 
137e057dd3fSOliver Hartkopp struct tpcon {
13896d1c81eSOliver Hartkopp 	u8 *buf;
13996d1c81eSOliver Hartkopp 	unsigned int buflen;
1405f33a09eSMarc Kleine-Budde 	unsigned int len;
14196d1c81eSOliver Hartkopp 	unsigned int idx;
14243a08c3bSZiyang Xuan 	u32 state;
143e057dd3fSOliver Hartkopp 	u8 bs;
144e057dd3fSOliver Hartkopp 	u8 sn;
145e057dd3fSOliver Hartkopp 	u8 ll_dl;
14696d1c81eSOliver Hartkopp 	u8 sbuf[DEFAULT_MAX_PDU_SIZE];
147e057dd3fSOliver Hartkopp };
148e057dd3fSOliver Hartkopp 
149e057dd3fSOliver Hartkopp struct isotp_sock {
150e057dd3fSOliver Hartkopp 	struct sock sk;
151e057dd3fSOliver Hartkopp 	int bound;
152e057dd3fSOliver Hartkopp 	int ifindex;
153e057dd3fSOliver Hartkopp 	canid_t txid;
154e057dd3fSOliver Hartkopp 	canid_t rxid;
155e057dd3fSOliver Hartkopp 	ktime_t tx_gap;
156e057dd3fSOliver Hartkopp 	ktime_t lastrxcf_tstamp;
1574f027cbaSOliver Hartkopp 	struct hrtimer rxtimer, txtimer, txfrtimer;
158e057dd3fSOliver Hartkopp 	struct can_isotp_options opt;
159e057dd3fSOliver Hartkopp 	struct can_isotp_fc_options rxfc, txfc;
160e057dd3fSOliver Hartkopp 	struct can_isotp_ll_options ll;
161530e0d46SOliver Hartkopp 	u32 frame_txtime;
162e057dd3fSOliver Hartkopp 	u32 force_tx_stmin;
163e057dd3fSOliver Hartkopp 	u32 force_rx_stmin;
1644b7fe92cSOliver Hartkopp 	u32 cfecho; /* consecutive frame echo tag */
165e057dd3fSOliver Hartkopp 	struct tpcon rx, tx;
1668d0caedbSTetsuo Handa 	struct list_head notifier;
167e057dd3fSOliver Hartkopp 	wait_queue_head_t wait;
1687c759040SOliver Hartkopp 	spinlock_t rx_lock; /* protect single thread state machine */
169e057dd3fSOliver Hartkopp };
170e057dd3fSOliver Hartkopp 
1718d0caedbSTetsuo Handa static LIST_HEAD(isotp_notifier_list);
1728d0caedbSTetsuo Handa static DEFINE_SPINLOCK(isotp_notifier_lock);
1738d0caedbSTetsuo Handa static struct isotp_sock *isotp_busy_notifier;
1748d0caedbSTetsuo Handa 
isotp_sk(const struct sock * sk)175e057dd3fSOliver Hartkopp static inline struct isotp_sock *isotp_sk(const struct sock *sk)
176e057dd3fSOliver Hartkopp {
177e057dd3fSOliver Hartkopp 	return (struct isotp_sock *)sk;
178e057dd3fSOliver Hartkopp }
179e057dd3fSOliver Hartkopp 
isotp_bc_flags(struct isotp_sock * so)1809f39d365SOliver Hartkopp static u32 isotp_bc_flags(struct isotp_sock *so)
1819f39d365SOliver Hartkopp {
1829f39d365SOliver Hartkopp 	return so->opt.flags & ISOTP_ALL_BC_FLAGS;
1839f39d365SOliver Hartkopp }
1849f39d365SOliver Hartkopp 
isotp_register_rxid(struct isotp_sock * so)1859f39d365SOliver Hartkopp static bool isotp_register_rxid(struct isotp_sock *so)
1869f39d365SOliver Hartkopp {
1879f39d365SOliver Hartkopp 	/* no broadcast modes => register rx_id for FC frame reception */
1889f39d365SOliver Hartkopp 	return (isotp_bc_flags(so) == 0);
1899f39d365SOliver Hartkopp }
1909f39d365SOliver Hartkopp 
isotp_rx_timer_handler(struct hrtimer * hrtimer)191e057dd3fSOliver Hartkopp static enum hrtimer_restart isotp_rx_timer_handler(struct hrtimer *hrtimer)
192e057dd3fSOliver Hartkopp {
193e057dd3fSOliver Hartkopp 	struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
194e057dd3fSOliver Hartkopp 					     rxtimer);
195e057dd3fSOliver Hartkopp 	struct sock *sk = &so->sk;
196e057dd3fSOliver Hartkopp 
197e057dd3fSOliver Hartkopp 	if (so->rx.state == ISOTP_WAIT_DATA) {
198e057dd3fSOliver Hartkopp 		/* we did not get new data frames in time */
199e057dd3fSOliver Hartkopp 
200e057dd3fSOliver Hartkopp 		/* report 'connection timed out' */
201e057dd3fSOliver Hartkopp 		sk->sk_err = ETIMEDOUT;
202e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
203e3ae2365SAlexander Aring 			sk_error_report(sk);
204e057dd3fSOliver Hartkopp 
205e057dd3fSOliver Hartkopp 		/* reset rx state */
206e057dd3fSOliver Hartkopp 		so->rx.state = ISOTP_IDLE;
207e057dd3fSOliver Hartkopp 	}
208e057dd3fSOliver Hartkopp 
209e057dd3fSOliver Hartkopp 	return HRTIMER_NORESTART;
210e057dd3fSOliver Hartkopp }
211e057dd3fSOliver Hartkopp 
isotp_send_fc(struct sock * sk,int ae,u8 flowstatus)212e057dd3fSOliver Hartkopp static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus)
213e057dd3fSOliver Hartkopp {
214e057dd3fSOliver Hartkopp 	struct net_device *dev;
215e057dd3fSOliver Hartkopp 	struct sk_buff *nskb;
216e057dd3fSOliver Hartkopp 	struct canfd_frame *ncf;
217e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
218e057dd3fSOliver Hartkopp 	int can_send_ret;
219e057dd3fSOliver Hartkopp 
220e057dd3fSOliver Hartkopp 	nskb = alloc_skb(so->ll.mtu + sizeof(struct can_skb_priv), gfp_any());
221e057dd3fSOliver Hartkopp 	if (!nskb)
222e057dd3fSOliver Hartkopp 		return 1;
223e057dd3fSOliver Hartkopp 
224e057dd3fSOliver Hartkopp 	dev = dev_get_by_index(sock_net(sk), so->ifindex);
225e057dd3fSOliver Hartkopp 	if (!dev) {
226e057dd3fSOliver Hartkopp 		kfree_skb(nskb);
227e057dd3fSOliver Hartkopp 		return 1;
228e057dd3fSOliver Hartkopp 	}
229e057dd3fSOliver Hartkopp 
230e057dd3fSOliver Hartkopp 	can_skb_reserve(nskb);
231e057dd3fSOliver Hartkopp 	can_skb_prv(nskb)->ifindex = dev->ifindex;
232e057dd3fSOliver Hartkopp 	can_skb_prv(nskb)->skbcnt = 0;
233e057dd3fSOliver Hartkopp 
234e057dd3fSOliver Hartkopp 	nskb->dev = dev;
235e057dd3fSOliver Hartkopp 	can_skb_set_owner(nskb, sk);
236e057dd3fSOliver Hartkopp 	ncf = (struct canfd_frame *)nskb->data;
237b5f020f8SOliver Hartkopp 	skb_put_zero(nskb, so->ll.mtu);
238e057dd3fSOliver Hartkopp 
239e057dd3fSOliver Hartkopp 	/* create & send flow control reply */
240e057dd3fSOliver Hartkopp 	ncf->can_id = so->txid;
241e057dd3fSOliver Hartkopp 
242e057dd3fSOliver Hartkopp 	if (so->opt.flags & CAN_ISOTP_TX_PADDING) {
243e057dd3fSOliver Hartkopp 		memset(ncf->data, so->opt.txpad_content, CAN_MAX_DLEN);
244e057dd3fSOliver Hartkopp 		ncf->len = CAN_MAX_DLEN;
245e057dd3fSOliver Hartkopp 	} else {
246e057dd3fSOliver Hartkopp 		ncf->len = ae + FC_CONTENT_SZ;
247e057dd3fSOliver Hartkopp 	}
248e057dd3fSOliver Hartkopp 
249e057dd3fSOliver Hartkopp 	ncf->data[ae] = N_PCI_FC | flowstatus;
250e057dd3fSOliver Hartkopp 	ncf->data[ae + 1] = so->rxfc.bs;
251e057dd3fSOliver Hartkopp 	ncf->data[ae + 2] = so->rxfc.stmin;
252e057dd3fSOliver Hartkopp 
253e057dd3fSOliver Hartkopp 	if (ae)
254e057dd3fSOliver Hartkopp 		ncf->data[0] = so->opt.ext_address;
255e057dd3fSOliver Hartkopp 
256e057dd3fSOliver Hartkopp 	ncf->flags = so->ll.tx_flags;
257e057dd3fSOliver Hartkopp 
258e057dd3fSOliver Hartkopp 	can_send_ret = can_send(nskb, 1);
259e057dd3fSOliver Hartkopp 	if (can_send_ret)
26046d8657aSPatrick Menschel 		pr_notice_once("can-isotp: %s: can_send_ret %pe\n",
26146d8657aSPatrick Menschel 			       __func__, ERR_PTR(can_send_ret));
262e057dd3fSOliver Hartkopp 
263e057dd3fSOliver Hartkopp 	dev_put(dev);
264e057dd3fSOliver Hartkopp 
265e057dd3fSOliver Hartkopp 	/* reset blocksize counter */
266e057dd3fSOliver Hartkopp 	so->rx.bs = 0;
267e057dd3fSOliver Hartkopp 
268e057dd3fSOliver Hartkopp 	/* reset last CF frame rx timestamp for rx stmin enforcement */
269e057dd3fSOliver Hartkopp 	so->lastrxcf_tstamp = ktime_set(0, 0);
270e057dd3fSOliver Hartkopp 
271e057dd3fSOliver Hartkopp 	/* start rx timeout watchdog */
27286633786SOliver Hartkopp 	hrtimer_start(&so->rxtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
27386633786SOliver Hartkopp 		      HRTIMER_MODE_REL_SOFT);
274e057dd3fSOliver Hartkopp 	return 0;
275e057dd3fSOliver Hartkopp }
276e057dd3fSOliver Hartkopp 
isotp_rcv_skb(struct sk_buff * skb,struct sock * sk)277e057dd3fSOliver Hartkopp static void isotp_rcv_skb(struct sk_buff *skb, struct sock *sk)
278e057dd3fSOliver Hartkopp {
279e057dd3fSOliver Hartkopp 	struct sockaddr_can *addr = (struct sockaddr_can *)skb->cb;
280e057dd3fSOliver Hartkopp 
281e057dd3fSOliver Hartkopp 	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct sockaddr_can));
282e057dd3fSOliver Hartkopp 
283e057dd3fSOliver Hartkopp 	memset(addr, 0, sizeof(*addr));
284e057dd3fSOliver Hartkopp 	addr->can_family = AF_CAN;
285e057dd3fSOliver Hartkopp 	addr->can_ifindex = skb->dev->ifindex;
286e057dd3fSOliver Hartkopp 
287e057dd3fSOliver Hartkopp 	if (sock_queue_rcv_skb(sk, skb) < 0)
288e057dd3fSOliver Hartkopp 		kfree_skb(skb);
289e057dd3fSOliver Hartkopp }
290e057dd3fSOliver Hartkopp 
padlen(u8 datalen)291e057dd3fSOliver Hartkopp static u8 padlen(u8 datalen)
292e057dd3fSOliver Hartkopp {
293c3ddac4bSColin Ian King 	static const u8 plen[] = {
294c3ddac4bSColin Ian King 		8, 8, 8, 8, 8, 8, 8, 8, 8,	/* 0 - 8 */
295e057dd3fSOliver Hartkopp 		12, 12, 12, 12,			/* 9 - 12 */
296e057dd3fSOliver Hartkopp 		16, 16, 16, 16,			/* 13 - 16 */
297e057dd3fSOliver Hartkopp 		20, 20, 20, 20,			/* 17 - 20 */
298e057dd3fSOliver Hartkopp 		24, 24, 24, 24,			/* 21 - 24 */
299e057dd3fSOliver Hartkopp 		32, 32, 32, 32, 32, 32, 32, 32,	/* 25 - 32 */
300e057dd3fSOliver Hartkopp 		48, 48, 48, 48, 48, 48, 48, 48,	/* 33 - 40 */
301c3ddac4bSColin Ian King 		48, 48, 48, 48, 48, 48, 48, 48	/* 41 - 48 */
302c3ddac4bSColin Ian King 	};
303e057dd3fSOliver Hartkopp 
304e057dd3fSOliver Hartkopp 	if (datalen > 48)
305e057dd3fSOliver Hartkopp 		return 64;
306e057dd3fSOliver Hartkopp 
307e057dd3fSOliver Hartkopp 	return plen[datalen];
308e057dd3fSOliver Hartkopp }
309e057dd3fSOliver Hartkopp 
310e057dd3fSOliver Hartkopp /* check for length optimization and return 1/true when the check fails */
check_optimized(struct canfd_frame * cf,int start_index)311e057dd3fSOliver Hartkopp static int check_optimized(struct canfd_frame *cf, int start_index)
312e057dd3fSOliver Hartkopp {
313e057dd3fSOliver Hartkopp 	/* for CAN_DL <= 8 the start_index is equal to the CAN_DL as the
314e057dd3fSOliver Hartkopp 	 * padding would start at this point. E.g. if the padding would
315e057dd3fSOliver Hartkopp 	 * start at cf.data[7] cf->len has to be 7 to be optimal.
316e057dd3fSOliver Hartkopp 	 * Note: The data[] index starts with zero.
317e057dd3fSOliver Hartkopp 	 */
318e057dd3fSOliver Hartkopp 	if (cf->len <= CAN_MAX_DLEN)
319e057dd3fSOliver Hartkopp 		return (cf->len != start_index);
320e057dd3fSOliver Hartkopp 
321e057dd3fSOliver Hartkopp 	/* This relation is also valid in the non-linear DLC range, where
322e057dd3fSOliver Hartkopp 	 * we need to take care of the minimal next possible CAN_DL.
323e057dd3fSOliver Hartkopp 	 * The correct check would be (padlen(cf->len) != padlen(start_index)).
324e057dd3fSOliver Hartkopp 	 * But as cf->len can only take discrete values from 12, .., 64 at this
325e057dd3fSOliver Hartkopp 	 * point the padlen(cf->len) is always equal to cf->len.
326e057dd3fSOliver Hartkopp 	 */
327e057dd3fSOliver Hartkopp 	return (cf->len != padlen(start_index));
328e057dd3fSOliver Hartkopp }
329e057dd3fSOliver Hartkopp 
330e057dd3fSOliver Hartkopp /* check padding and return 1/true when the check fails */
check_pad(struct isotp_sock * so,struct canfd_frame * cf,int start_index,u8 content)331e057dd3fSOliver Hartkopp static int check_pad(struct isotp_sock *so, struct canfd_frame *cf,
332e057dd3fSOliver Hartkopp 		     int start_index, u8 content)
333e057dd3fSOliver Hartkopp {
334e057dd3fSOliver Hartkopp 	int i;
335e057dd3fSOliver Hartkopp 
336e057dd3fSOliver Hartkopp 	/* no RX_PADDING value => check length of optimized frame length */
337e057dd3fSOliver Hartkopp 	if (!(so->opt.flags & CAN_ISOTP_RX_PADDING)) {
338e057dd3fSOliver Hartkopp 		if (so->opt.flags & CAN_ISOTP_CHK_PAD_LEN)
339e057dd3fSOliver Hartkopp 			return check_optimized(cf, start_index);
340e057dd3fSOliver Hartkopp 
341e057dd3fSOliver Hartkopp 		/* no valid test against empty value => ignore frame */
342e057dd3fSOliver Hartkopp 		return 1;
343e057dd3fSOliver Hartkopp 	}
344e057dd3fSOliver Hartkopp 
345e057dd3fSOliver Hartkopp 	/* check datalength of correctly padded CAN frame */
346e057dd3fSOliver Hartkopp 	if ((so->opt.flags & CAN_ISOTP_CHK_PAD_LEN) &&
347e057dd3fSOliver Hartkopp 	    cf->len != padlen(cf->len))
348e057dd3fSOliver Hartkopp 		return 1;
349e057dd3fSOliver Hartkopp 
350e057dd3fSOliver Hartkopp 	/* check padding content */
351e057dd3fSOliver Hartkopp 	if (so->opt.flags & CAN_ISOTP_CHK_PAD_DATA) {
352e057dd3fSOliver Hartkopp 		for (i = start_index; i < cf->len; i++)
353e057dd3fSOliver Hartkopp 			if (cf->data[i] != content)
354e057dd3fSOliver Hartkopp 				return 1;
355e057dd3fSOliver Hartkopp 	}
356e057dd3fSOliver Hartkopp 	return 0;
357e057dd3fSOliver Hartkopp }
358e057dd3fSOliver Hartkopp 
35986633786SOliver Hartkopp static void isotp_send_cframe(struct isotp_sock *so);
36086633786SOliver Hartkopp 
isotp_rcv_fc(struct isotp_sock * so,struct canfd_frame * cf,int ae)361e057dd3fSOliver Hartkopp static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
362e057dd3fSOliver Hartkopp {
363e057dd3fSOliver Hartkopp 	struct sock *sk = &so->sk;
364e057dd3fSOliver Hartkopp 
365e057dd3fSOliver Hartkopp 	if (so->tx.state != ISOTP_WAIT_FC &&
366e057dd3fSOliver Hartkopp 	    so->tx.state != ISOTP_WAIT_FIRST_FC)
367e057dd3fSOliver Hartkopp 		return 0;
368e057dd3fSOliver Hartkopp 
369e057dd3fSOliver Hartkopp 	hrtimer_cancel(&so->txtimer);
370e057dd3fSOliver Hartkopp 
371e057dd3fSOliver Hartkopp 	if ((cf->len < ae + FC_CONTENT_SZ) ||
372e057dd3fSOliver Hartkopp 	    ((so->opt.flags & ISOTP_CHECK_PADDING) &&
373e057dd3fSOliver Hartkopp 	     check_pad(so, cf, ae + FC_CONTENT_SZ, so->opt.rxpad_content))) {
374e057dd3fSOliver Hartkopp 		/* malformed PDU - report 'not a data message' */
375e057dd3fSOliver Hartkopp 		sk->sk_err = EBADMSG;
376e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
377e3ae2365SAlexander Aring 			sk_error_report(sk);
378e057dd3fSOliver Hartkopp 
379e057dd3fSOliver Hartkopp 		so->tx.state = ISOTP_IDLE;
380e057dd3fSOliver Hartkopp 		wake_up_interruptible(&so->wait);
381e057dd3fSOliver Hartkopp 		return 1;
382e057dd3fSOliver Hartkopp 	}
383e057dd3fSOliver Hartkopp 
384e057dd3fSOliver Hartkopp 	/* get communication parameters only from the first FC frame */
385e057dd3fSOliver Hartkopp 	if (so->tx.state == ISOTP_WAIT_FIRST_FC) {
386e057dd3fSOliver Hartkopp 		so->txfc.bs = cf->data[ae + 1];
387e057dd3fSOliver Hartkopp 		so->txfc.stmin = cf->data[ae + 2];
388e057dd3fSOliver Hartkopp 
389e057dd3fSOliver Hartkopp 		/* fix wrong STmin values according spec */
390e057dd3fSOliver Hartkopp 		if (so->txfc.stmin > 0x7F &&
391e057dd3fSOliver Hartkopp 		    (so->txfc.stmin < 0xF1 || so->txfc.stmin > 0xF9))
392e057dd3fSOliver Hartkopp 			so->txfc.stmin = 0x7F;
393e057dd3fSOliver Hartkopp 
394e057dd3fSOliver Hartkopp 		so->tx_gap = ktime_set(0, 0);
395e057dd3fSOliver Hartkopp 		/* add transmission time for CAN frame N_As */
396530e0d46SOliver Hartkopp 		so->tx_gap = ktime_add_ns(so->tx_gap, so->frame_txtime);
397e057dd3fSOliver Hartkopp 		/* add waiting time for consecutive frames N_Cs */
398e057dd3fSOliver Hartkopp 		if (so->opt.flags & CAN_ISOTP_FORCE_TXSTMIN)
399e057dd3fSOliver Hartkopp 			so->tx_gap = ktime_add_ns(so->tx_gap,
400e057dd3fSOliver Hartkopp 						  so->force_tx_stmin);
401e057dd3fSOliver Hartkopp 		else if (so->txfc.stmin < 0x80)
402e057dd3fSOliver Hartkopp 			so->tx_gap = ktime_add_ns(so->tx_gap,
403e057dd3fSOliver Hartkopp 						  so->txfc.stmin * 1000000);
404e057dd3fSOliver Hartkopp 		else
405e057dd3fSOliver Hartkopp 			so->tx_gap = ktime_add_ns(so->tx_gap,
406e057dd3fSOliver Hartkopp 						  (so->txfc.stmin - 0xF0)
407e057dd3fSOliver Hartkopp 						  * 100000);
408e057dd3fSOliver Hartkopp 		so->tx.state = ISOTP_WAIT_FC;
409e057dd3fSOliver Hartkopp 	}
410e057dd3fSOliver Hartkopp 
411e057dd3fSOliver Hartkopp 	switch (cf->data[ae] & 0x0F) {
412e057dd3fSOliver Hartkopp 	case ISOTP_FC_CTS:
413e057dd3fSOliver Hartkopp 		so->tx.bs = 0;
414e057dd3fSOliver Hartkopp 		so->tx.state = ISOTP_SENDING;
41586633786SOliver Hartkopp 		/* send CF frame and enable echo timeout handling */
41686633786SOliver Hartkopp 		hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
417e057dd3fSOliver Hartkopp 			      HRTIMER_MODE_REL_SOFT);
41886633786SOliver Hartkopp 		isotp_send_cframe(so);
419e057dd3fSOliver Hartkopp 		break;
420e057dd3fSOliver Hartkopp 
421e057dd3fSOliver Hartkopp 	case ISOTP_FC_WT:
422e057dd3fSOliver Hartkopp 		/* start timer to wait for next FC frame */
42386633786SOliver Hartkopp 		hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
424e057dd3fSOliver Hartkopp 			      HRTIMER_MODE_REL_SOFT);
425e057dd3fSOliver Hartkopp 		break;
426e057dd3fSOliver Hartkopp 
427e057dd3fSOliver Hartkopp 	case ISOTP_FC_OVFLW:
428e057dd3fSOliver Hartkopp 		/* overflow on receiver side - report 'message too long' */
429e057dd3fSOliver Hartkopp 		sk->sk_err = EMSGSIZE;
430e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
431e3ae2365SAlexander Aring 			sk_error_report(sk);
432e057dd3fSOliver Hartkopp 		fallthrough;
433e057dd3fSOliver Hartkopp 
434e057dd3fSOliver Hartkopp 	default:
435e057dd3fSOliver Hartkopp 		/* stop this tx job */
436e057dd3fSOliver Hartkopp 		so->tx.state = ISOTP_IDLE;
437e057dd3fSOliver Hartkopp 		wake_up_interruptible(&so->wait);
438e057dd3fSOliver Hartkopp 	}
439e057dd3fSOliver Hartkopp 	return 0;
440e057dd3fSOliver Hartkopp }
441e057dd3fSOliver Hartkopp 
isotp_rcv_sf(struct sock * sk,struct canfd_frame * cf,int pcilen,struct sk_buff * skb,int len)442e057dd3fSOliver Hartkopp static int isotp_rcv_sf(struct sock *sk, struct canfd_frame *cf, int pcilen,
443e057dd3fSOliver Hartkopp 			struct sk_buff *skb, int len)
444e057dd3fSOliver Hartkopp {
445e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
446e057dd3fSOliver Hartkopp 	struct sk_buff *nskb;
447e057dd3fSOliver Hartkopp 
448e057dd3fSOliver Hartkopp 	hrtimer_cancel(&so->rxtimer);
449e057dd3fSOliver Hartkopp 	so->rx.state = ISOTP_IDLE;
450e057dd3fSOliver Hartkopp 
451e057dd3fSOliver Hartkopp 	if (!len || len > cf->len - pcilen)
452e057dd3fSOliver Hartkopp 		return 1;
453e057dd3fSOliver Hartkopp 
454e057dd3fSOliver Hartkopp 	if ((so->opt.flags & ISOTP_CHECK_PADDING) &&
455e057dd3fSOliver Hartkopp 	    check_pad(so, cf, pcilen + len, so->opt.rxpad_content)) {
456e057dd3fSOliver Hartkopp 		/* malformed PDU - report 'not a data message' */
457e057dd3fSOliver Hartkopp 		sk->sk_err = EBADMSG;
458e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
459e3ae2365SAlexander Aring 			sk_error_report(sk);
460e057dd3fSOliver Hartkopp 		return 1;
461e057dd3fSOliver Hartkopp 	}
462e057dd3fSOliver Hartkopp 
463e057dd3fSOliver Hartkopp 	nskb = alloc_skb(len, gfp_any());
464e057dd3fSOliver Hartkopp 	if (!nskb)
465e057dd3fSOliver Hartkopp 		return 1;
466e057dd3fSOliver Hartkopp 
467e057dd3fSOliver Hartkopp 	memcpy(skb_put(nskb, len), &cf->data[pcilen], len);
468e057dd3fSOliver Hartkopp 
469e057dd3fSOliver Hartkopp 	nskb->tstamp = skb->tstamp;
470e057dd3fSOliver Hartkopp 	nskb->dev = skb->dev;
471e057dd3fSOliver Hartkopp 	isotp_rcv_skb(nskb, sk);
472e057dd3fSOliver Hartkopp 	return 0;
473e057dd3fSOliver Hartkopp }
474e057dd3fSOliver Hartkopp 
isotp_rcv_ff(struct sock * sk,struct canfd_frame * cf,int ae)475e057dd3fSOliver Hartkopp static int isotp_rcv_ff(struct sock *sk, struct canfd_frame *cf, int ae)
476e057dd3fSOliver Hartkopp {
477e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
478e057dd3fSOliver Hartkopp 	int i;
479e057dd3fSOliver Hartkopp 	int off;
480e057dd3fSOliver Hartkopp 	int ff_pci_sz;
481e057dd3fSOliver Hartkopp 
482e057dd3fSOliver Hartkopp 	hrtimer_cancel(&so->rxtimer);
483e057dd3fSOliver Hartkopp 	so->rx.state = ISOTP_IDLE;
484e057dd3fSOliver Hartkopp 
485e057dd3fSOliver Hartkopp 	/* get the used sender LL_DL from the (first) CAN frame data length */
486e057dd3fSOliver Hartkopp 	so->rx.ll_dl = padlen(cf->len);
487e057dd3fSOliver Hartkopp 
488e057dd3fSOliver Hartkopp 	/* the first frame has to use the entire frame up to LL_DL length */
489e057dd3fSOliver Hartkopp 	if (cf->len != so->rx.ll_dl)
490e057dd3fSOliver Hartkopp 		return 1;
491e057dd3fSOliver Hartkopp 
492e057dd3fSOliver Hartkopp 	/* get the FF_DL */
493e057dd3fSOliver Hartkopp 	so->rx.len = (cf->data[ae] & 0x0F) << 8;
494e057dd3fSOliver Hartkopp 	so->rx.len += cf->data[ae + 1];
495e057dd3fSOliver Hartkopp 
496e057dd3fSOliver Hartkopp 	/* Check for FF_DL escape sequence supporting 32 bit PDU length */
497e057dd3fSOliver Hartkopp 	if (so->rx.len) {
498e057dd3fSOliver Hartkopp 		ff_pci_sz = FF_PCI_SZ12;
499e057dd3fSOliver Hartkopp 	} else {
500e057dd3fSOliver Hartkopp 		/* FF_DL = 0 => get real length from next 4 bytes */
501e057dd3fSOliver Hartkopp 		so->rx.len = cf->data[ae + 2] << 24;
502e057dd3fSOliver Hartkopp 		so->rx.len += cf->data[ae + 3] << 16;
503e057dd3fSOliver Hartkopp 		so->rx.len += cf->data[ae + 4] << 8;
504e057dd3fSOliver Hartkopp 		so->rx.len += cf->data[ae + 5];
505e057dd3fSOliver Hartkopp 		ff_pci_sz = FF_PCI_SZ32;
506e057dd3fSOliver Hartkopp 	}
507e057dd3fSOliver Hartkopp 
508e057dd3fSOliver Hartkopp 	/* take care of a potential SF_DL ESC offset for TX_DL > 8 */
509e057dd3fSOliver Hartkopp 	off = (so->rx.ll_dl > CAN_MAX_DLEN) ? 1 : 0;
510e057dd3fSOliver Hartkopp 
511e057dd3fSOliver Hartkopp 	if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl)
512e057dd3fSOliver Hartkopp 		return 1;
513e057dd3fSOliver Hartkopp 
51496d1c81eSOliver Hartkopp 	/* PDU size > default => try max_pdu_size */
51596d1c81eSOliver Hartkopp 	if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) {
51696d1c81eSOliver Hartkopp 		u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC);
51796d1c81eSOliver Hartkopp 
51896d1c81eSOliver Hartkopp 		if (newbuf) {
51996d1c81eSOliver Hartkopp 			so->rx.buf = newbuf;
52096d1c81eSOliver Hartkopp 			so->rx.buflen = max_pdu_size;
52196d1c81eSOliver Hartkopp 		}
52296d1c81eSOliver Hartkopp 	}
52396d1c81eSOliver Hartkopp 
52496d1c81eSOliver Hartkopp 	if (so->rx.len > so->rx.buflen) {
525e057dd3fSOliver Hartkopp 		/* send FC frame with overflow status */
526e057dd3fSOliver Hartkopp 		isotp_send_fc(sk, ae, ISOTP_FC_OVFLW);
527e057dd3fSOliver Hartkopp 		return 1;
528e057dd3fSOliver Hartkopp 	}
529e057dd3fSOliver Hartkopp 
530e057dd3fSOliver Hartkopp 	/* copy the first received data bytes */
531e057dd3fSOliver Hartkopp 	so->rx.idx = 0;
532e057dd3fSOliver Hartkopp 	for (i = ae + ff_pci_sz; i < so->rx.ll_dl; i++)
533e057dd3fSOliver Hartkopp 		so->rx.buf[so->rx.idx++] = cf->data[i];
534e057dd3fSOliver Hartkopp 
535e057dd3fSOliver Hartkopp 	/* initial setup for this pdu reception */
536e057dd3fSOliver Hartkopp 	so->rx.sn = 1;
537e057dd3fSOliver Hartkopp 	so->rx.state = ISOTP_WAIT_DATA;
538e057dd3fSOliver Hartkopp 
539e057dd3fSOliver Hartkopp 	/* no creation of flow control frames */
540e057dd3fSOliver Hartkopp 	if (so->opt.flags & CAN_ISOTP_LISTEN_MODE)
541e057dd3fSOliver Hartkopp 		return 0;
542e057dd3fSOliver Hartkopp 
543e057dd3fSOliver Hartkopp 	/* send our first FC frame */
544e057dd3fSOliver Hartkopp 	isotp_send_fc(sk, ae, ISOTP_FC_CTS);
545e057dd3fSOliver Hartkopp 	return 0;
546e057dd3fSOliver Hartkopp }
547e057dd3fSOliver Hartkopp 
isotp_rcv_cf(struct sock * sk,struct canfd_frame * cf,int ae,struct sk_buff * skb)548e057dd3fSOliver Hartkopp static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
549e057dd3fSOliver Hartkopp 			struct sk_buff *skb)
550e057dd3fSOliver Hartkopp {
551e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
552e057dd3fSOliver Hartkopp 	struct sk_buff *nskb;
553e057dd3fSOliver Hartkopp 	int i;
554e057dd3fSOliver Hartkopp 
555e057dd3fSOliver Hartkopp 	if (so->rx.state != ISOTP_WAIT_DATA)
556e057dd3fSOliver Hartkopp 		return 0;
557e057dd3fSOliver Hartkopp 
558e057dd3fSOliver Hartkopp 	/* drop if timestamp gap is less than force_rx_stmin nano secs */
559e057dd3fSOliver Hartkopp 	if (so->opt.flags & CAN_ISOTP_FORCE_RXSTMIN) {
560e057dd3fSOliver Hartkopp 		if (ktime_to_ns(ktime_sub(skb->tstamp, so->lastrxcf_tstamp)) <
561e057dd3fSOliver Hartkopp 		    so->force_rx_stmin)
562e057dd3fSOliver Hartkopp 			return 0;
563e057dd3fSOliver Hartkopp 
564e057dd3fSOliver Hartkopp 		so->lastrxcf_tstamp = skb->tstamp;
565e057dd3fSOliver Hartkopp 	}
566e057dd3fSOliver Hartkopp 
567e057dd3fSOliver Hartkopp 	hrtimer_cancel(&so->rxtimer);
568e057dd3fSOliver Hartkopp 
569e057dd3fSOliver Hartkopp 	/* CFs are never longer than the FF */
570e057dd3fSOliver Hartkopp 	if (cf->len > so->rx.ll_dl)
571e057dd3fSOliver Hartkopp 		return 1;
572e057dd3fSOliver Hartkopp 
573e057dd3fSOliver Hartkopp 	/* CFs have usually the LL_DL length */
574e057dd3fSOliver Hartkopp 	if (cf->len < so->rx.ll_dl) {
575e057dd3fSOliver Hartkopp 		/* this is only allowed for the last CF */
576e057dd3fSOliver Hartkopp 		if (so->rx.len - so->rx.idx > so->rx.ll_dl - ae - N_PCI_SZ)
577e057dd3fSOliver Hartkopp 			return 1;
578e057dd3fSOliver Hartkopp 	}
579e057dd3fSOliver Hartkopp 
580e057dd3fSOliver Hartkopp 	if ((cf->data[ae] & 0x0F) != so->rx.sn) {
581e057dd3fSOliver Hartkopp 		/* wrong sn detected - report 'illegal byte sequence' */
582e057dd3fSOliver Hartkopp 		sk->sk_err = EILSEQ;
583e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
584e3ae2365SAlexander Aring 			sk_error_report(sk);
585e057dd3fSOliver Hartkopp 
586e057dd3fSOliver Hartkopp 		/* reset rx state */
587e057dd3fSOliver Hartkopp 		so->rx.state = ISOTP_IDLE;
588e057dd3fSOliver Hartkopp 		return 1;
589e057dd3fSOliver Hartkopp 	}
590e057dd3fSOliver Hartkopp 	so->rx.sn++;
591e057dd3fSOliver Hartkopp 	so->rx.sn %= 16;
592e057dd3fSOliver Hartkopp 
593e057dd3fSOliver Hartkopp 	for (i = ae + N_PCI_SZ; i < cf->len; i++) {
594e057dd3fSOliver Hartkopp 		so->rx.buf[so->rx.idx++] = cf->data[i];
595e057dd3fSOliver Hartkopp 		if (so->rx.idx >= so->rx.len)
596e057dd3fSOliver Hartkopp 			break;
597e057dd3fSOliver Hartkopp 	}
598e057dd3fSOliver Hartkopp 
599e057dd3fSOliver Hartkopp 	if (so->rx.idx >= so->rx.len) {
600e057dd3fSOliver Hartkopp 		/* we are done */
601e057dd3fSOliver Hartkopp 		so->rx.state = ISOTP_IDLE;
602e057dd3fSOliver Hartkopp 
603e057dd3fSOliver Hartkopp 		if ((so->opt.flags & ISOTP_CHECK_PADDING) &&
604e057dd3fSOliver Hartkopp 		    check_pad(so, cf, i + 1, so->opt.rxpad_content)) {
605e057dd3fSOliver Hartkopp 			/* malformed PDU - report 'not a data message' */
606e057dd3fSOliver Hartkopp 			sk->sk_err = EBADMSG;
607e057dd3fSOliver Hartkopp 			if (!sock_flag(sk, SOCK_DEAD))
608e3ae2365SAlexander Aring 				sk_error_report(sk);
609e057dd3fSOliver Hartkopp 			return 1;
610e057dd3fSOliver Hartkopp 		}
611e057dd3fSOliver Hartkopp 
612e057dd3fSOliver Hartkopp 		nskb = alloc_skb(so->rx.len, gfp_any());
613e057dd3fSOliver Hartkopp 		if (!nskb)
614e057dd3fSOliver Hartkopp 			return 1;
615e057dd3fSOliver Hartkopp 
616e057dd3fSOliver Hartkopp 		memcpy(skb_put(nskb, so->rx.len), so->rx.buf,
617e057dd3fSOliver Hartkopp 		       so->rx.len);
618e057dd3fSOliver Hartkopp 
619e057dd3fSOliver Hartkopp 		nskb->tstamp = skb->tstamp;
620e057dd3fSOliver Hartkopp 		nskb->dev = skb->dev;
621e057dd3fSOliver Hartkopp 		isotp_rcv_skb(nskb, sk);
622e057dd3fSOliver Hartkopp 		return 0;
623e057dd3fSOliver Hartkopp 	}
624e057dd3fSOliver Hartkopp 
625e057dd3fSOliver Hartkopp 	/* perform blocksize handling, if enabled */
626e057dd3fSOliver Hartkopp 	if (!so->rxfc.bs || ++so->rx.bs < so->rxfc.bs) {
627e057dd3fSOliver Hartkopp 		/* start rx timeout watchdog */
62886633786SOliver Hartkopp 		hrtimer_start(&so->rxtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
629e057dd3fSOliver Hartkopp 			      HRTIMER_MODE_REL_SOFT);
630e057dd3fSOliver Hartkopp 		return 0;
631e057dd3fSOliver Hartkopp 	}
632e057dd3fSOliver Hartkopp 
63378656ea2SOliver Hartkopp 	/* no creation of flow control frames */
63478656ea2SOliver Hartkopp 	if (so->opt.flags & CAN_ISOTP_LISTEN_MODE)
63578656ea2SOliver Hartkopp 		return 0;
63678656ea2SOliver Hartkopp 
637e057dd3fSOliver Hartkopp 	/* we reached the specified blocksize so->rxfc.bs */
638e057dd3fSOliver Hartkopp 	isotp_send_fc(sk, ae, ISOTP_FC_CTS);
639e057dd3fSOliver Hartkopp 	return 0;
640e057dd3fSOliver Hartkopp }
641e057dd3fSOliver Hartkopp 
isotp_rcv(struct sk_buff * skb,void * data)642e057dd3fSOliver Hartkopp static void isotp_rcv(struct sk_buff *skb, void *data)
643e057dd3fSOliver Hartkopp {
644e057dd3fSOliver Hartkopp 	struct sock *sk = (struct sock *)data;
645e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
646e057dd3fSOliver Hartkopp 	struct canfd_frame *cf;
647e057dd3fSOliver Hartkopp 	int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
648e057dd3fSOliver Hartkopp 	u8 n_pci_type, sf_dl;
649e057dd3fSOliver Hartkopp 
650e057dd3fSOliver Hartkopp 	/* Strictly receive only frames with the configured MTU size
651e057dd3fSOliver Hartkopp 	 * => clear separation of CAN2.0 / CAN FD transport channels
652e057dd3fSOliver Hartkopp 	 */
653e057dd3fSOliver Hartkopp 	if (skb->len != so->ll.mtu)
654e057dd3fSOliver Hartkopp 		return;
655e057dd3fSOliver Hartkopp 
656e057dd3fSOliver Hartkopp 	cf = (struct canfd_frame *)skb->data;
657e057dd3fSOliver Hartkopp 
658e057dd3fSOliver Hartkopp 	/* if enabled: check reception of my configured extended address */
659e057dd3fSOliver Hartkopp 	if (ae && cf->data[0] != so->opt.rx_ext_address)
660e057dd3fSOliver Hartkopp 		return;
661e057dd3fSOliver Hartkopp 
662e057dd3fSOliver Hartkopp 	n_pci_type = cf->data[ae] & 0xF0;
663e057dd3fSOliver Hartkopp 
6647c759040SOliver Hartkopp 	/* Make sure the state changes and data structures stay consistent at
6657c759040SOliver Hartkopp 	 * CAN frame reception time. This locking is not needed in real world
6667c759040SOliver Hartkopp 	 * use cases but the inconsistency can be triggered with syzkaller.
6677c759040SOliver Hartkopp 	 */
6687c759040SOliver Hartkopp 	spin_lock(&so->rx_lock);
6697c759040SOliver Hartkopp 
670e057dd3fSOliver Hartkopp 	if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) {
671e057dd3fSOliver Hartkopp 		/* check rx/tx path half duplex expectations */
672e057dd3fSOliver Hartkopp 		if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) ||
673e057dd3fSOliver Hartkopp 		    (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC))
6747c759040SOliver Hartkopp 			goto out_unlock;
675e057dd3fSOliver Hartkopp 	}
676e057dd3fSOliver Hartkopp 
677e057dd3fSOliver Hartkopp 	switch (n_pci_type) {
678e057dd3fSOliver Hartkopp 	case N_PCI_FC:
679e057dd3fSOliver Hartkopp 		/* tx path: flow control frame containing the FC parameters */
680e057dd3fSOliver Hartkopp 		isotp_rcv_fc(so, cf, ae);
681e057dd3fSOliver Hartkopp 		break;
682e057dd3fSOliver Hartkopp 
683e057dd3fSOliver Hartkopp 	case N_PCI_SF:
684e057dd3fSOliver Hartkopp 		/* rx path: single frame
685e057dd3fSOliver Hartkopp 		 *
686e057dd3fSOliver Hartkopp 		 * As we do not have a rx.ll_dl configuration, we can only test
687e057dd3fSOliver Hartkopp 		 * if the CAN frames payload length matches the LL_DL == 8
688e057dd3fSOliver Hartkopp 		 * requirements - no matter if it's CAN 2.0 or CAN FD
689e057dd3fSOliver Hartkopp 		 */
690e057dd3fSOliver Hartkopp 
691e057dd3fSOliver Hartkopp 		/* get the SF_DL from the N_PCI byte */
692e057dd3fSOliver Hartkopp 		sf_dl = cf->data[ae] & 0x0F;
693e057dd3fSOliver Hartkopp 
694e057dd3fSOliver Hartkopp 		if (cf->len <= CAN_MAX_DLEN) {
695e057dd3fSOliver Hartkopp 			isotp_rcv_sf(sk, cf, SF_PCI_SZ4 + ae, skb, sf_dl);
696e057dd3fSOliver Hartkopp 		} else {
69796a7457aSOliver Hartkopp 			if (can_is_canfd_skb(skb)) {
698e057dd3fSOliver Hartkopp 				/* We have a CAN FD frame and CAN_DL is greater than 8:
699e057dd3fSOliver Hartkopp 				 * Only frames with the SF_DL == 0 ESC value are valid.
700e057dd3fSOliver Hartkopp 				 *
701e057dd3fSOliver Hartkopp 				 * If so take care of the increased SF PCI size
702e057dd3fSOliver Hartkopp 				 * (SF_PCI_SZ8) to point to the message content behind
703e057dd3fSOliver Hartkopp 				 * the extended SF PCI info and get the real SF_DL
704e057dd3fSOliver Hartkopp 				 * length value from the formerly first data byte.
705e057dd3fSOliver Hartkopp 				 */
706e057dd3fSOliver Hartkopp 				if (sf_dl == 0)
707e057dd3fSOliver Hartkopp 					isotp_rcv_sf(sk, cf, SF_PCI_SZ8 + ae, skb,
708e057dd3fSOliver Hartkopp 						     cf->data[SF_PCI_SZ4 + ae]);
709e057dd3fSOliver Hartkopp 			}
710e057dd3fSOliver Hartkopp 		}
711e057dd3fSOliver Hartkopp 		break;
712e057dd3fSOliver Hartkopp 
713e057dd3fSOliver Hartkopp 	case N_PCI_FF:
714e057dd3fSOliver Hartkopp 		/* rx path: first frame */
715e057dd3fSOliver Hartkopp 		isotp_rcv_ff(sk, cf, ae);
716e057dd3fSOliver Hartkopp 		break;
717e057dd3fSOliver Hartkopp 
718e057dd3fSOliver Hartkopp 	case N_PCI_CF:
719e057dd3fSOliver Hartkopp 		/* rx path: consecutive frame */
720e057dd3fSOliver Hartkopp 		isotp_rcv_cf(sk, cf, ae, skb);
721e057dd3fSOliver Hartkopp 		break;
722e057dd3fSOliver Hartkopp 	}
7237c759040SOliver Hartkopp 
7247c759040SOliver Hartkopp out_unlock:
7257c759040SOliver Hartkopp 	spin_unlock(&so->rx_lock);
726e057dd3fSOliver Hartkopp }
727e057dd3fSOliver Hartkopp 
isotp_fill_dataframe(struct canfd_frame * cf,struct isotp_sock * so,int ae,int off)728e057dd3fSOliver Hartkopp static void isotp_fill_dataframe(struct canfd_frame *cf, struct isotp_sock *so,
729e057dd3fSOliver Hartkopp 				 int ae, int off)
730e057dd3fSOliver Hartkopp {
731e057dd3fSOliver Hartkopp 	int pcilen = N_PCI_SZ + ae + off;
732e057dd3fSOliver Hartkopp 	int space = so->tx.ll_dl - pcilen;
733e057dd3fSOliver Hartkopp 	int num = min_t(int, so->tx.len - so->tx.idx, space);
734e057dd3fSOliver Hartkopp 	int i;
735e057dd3fSOliver Hartkopp 
736e057dd3fSOliver Hartkopp 	cf->can_id = so->txid;
737e057dd3fSOliver Hartkopp 	cf->len = num + pcilen;
738e057dd3fSOliver Hartkopp 
739e057dd3fSOliver Hartkopp 	if (num < space) {
740e057dd3fSOliver Hartkopp 		if (so->opt.flags & CAN_ISOTP_TX_PADDING) {
741e057dd3fSOliver Hartkopp 			/* user requested padding */
742e057dd3fSOliver Hartkopp 			cf->len = padlen(cf->len);
743e057dd3fSOliver Hartkopp 			memset(cf->data, so->opt.txpad_content, cf->len);
744e057dd3fSOliver Hartkopp 		} else if (cf->len > CAN_MAX_DLEN) {
745e057dd3fSOliver Hartkopp 			/* mandatory padding for CAN FD frames */
746e057dd3fSOliver Hartkopp 			cf->len = padlen(cf->len);
747e057dd3fSOliver Hartkopp 			memset(cf->data, CAN_ISOTP_DEFAULT_PAD_CONTENT,
748e057dd3fSOliver Hartkopp 			       cf->len);
749e057dd3fSOliver Hartkopp 		}
750e057dd3fSOliver Hartkopp 	}
751e057dd3fSOliver Hartkopp 
752e057dd3fSOliver Hartkopp 	for (i = 0; i < num; i++)
753e057dd3fSOliver Hartkopp 		cf->data[pcilen + i] = so->tx.buf[so->tx.idx++];
754e057dd3fSOliver Hartkopp 
755e057dd3fSOliver Hartkopp 	if (ae)
756e057dd3fSOliver Hartkopp 		cf->data[0] = so->opt.ext_address;
757e057dd3fSOliver Hartkopp }
758e057dd3fSOliver Hartkopp 
isotp_send_cframe(struct isotp_sock * so)7594b7fe92cSOliver Hartkopp static void isotp_send_cframe(struct isotp_sock *so)
7604b7fe92cSOliver Hartkopp {
7614b7fe92cSOliver Hartkopp 	struct sock *sk = &so->sk;
7624b7fe92cSOliver Hartkopp 	struct sk_buff *skb;
7634b7fe92cSOliver Hartkopp 	struct net_device *dev;
7644b7fe92cSOliver Hartkopp 	struct canfd_frame *cf;
7654b7fe92cSOliver Hartkopp 	int can_send_ret;
7664b7fe92cSOliver Hartkopp 	int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
7674b7fe92cSOliver Hartkopp 
7684b7fe92cSOliver Hartkopp 	dev = dev_get_by_index(sock_net(sk), so->ifindex);
7694b7fe92cSOliver Hartkopp 	if (!dev)
7704b7fe92cSOliver Hartkopp 		return;
7714b7fe92cSOliver Hartkopp 
7724b7fe92cSOliver Hartkopp 	skb = alloc_skb(so->ll.mtu + sizeof(struct can_skb_priv), GFP_ATOMIC);
7734b7fe92cSOliver Hartkopp 	if (!skb) {
7744b7fe92cSOliver Hartkopp 		dev_put(dev);
7754b7fe92cSOliver Hartkopp 		return;
7764b7fe92cSOliver Hartkopp 	}
7774b7fe92cSOliver Hartkopp 
7784b7fe92cSOliver Hartkopp 	can_skb_reserve(skb);
7794b7fe92cSOliver Hartkopp 	can_skb_prv(skb)->ifindex = dev->ifindex;
7804b7fe92cSOliver Hartkopp 	can_skb_prv(skb)->skbcnt = 0;
7814b7fe92cSOliver Hartkopp 
7824b7fe92cSOliver Hartkopp 	cf = (struct canfd_frame *)skb->data;
7834b7fe92cSOliver Hartkopp 	skb_put_zero(skb, so->ll.mtu);
7844b7fe92cSOliver Hartkopp 
7854b7fe92cSOliver Hartkopp 	/* create consecutive frame */
7864b7fe92cSOliver Hartkopp 	isotp_fill_dataframe(cf, so, ae, 0);
7874b7fe92cSOliver Hartkopp 
7884b7fe92cSOliver Hartkopp 	/* place consecutive frame N_PCI in appropriate index */
7894b7fe92cSOliver Hartkopp 	cf->data[ae] = N_PCI_CF | so->tx.sn++;
7904b7fe92cSOliver Hartkopp 	so->tx.sn %= 16;
7914b7fe92cSOliver Hartkopp 	so->tx.bs++;
7924b7fe92cSOliver Hartkopp 
7934b7fe92cSOliver Hartkopp 	cf->flags = so->ll.tx_flags;
7944b7fe92cSOliver Hartkopp 
7954b7fe92cSOliver Hartkopp 	skb->dev = dev;
7964b7fe92cSOliver Hartkopp 	can_skb_set_owner(skb, sk);
7974b7fe92cSOliver Hartkopp 
7984b7fe92cSOliver Hartkopp 	/* cfecho should have been zero'ed by init/isotp_rcv_echo() */
7994b7fe92cSOliver Hartkopp 	if (so->cfecho)
8004b7fe92cSOliver Hartkopp 		pr_notice_once("can-isotp: cfecho is %08X != 0\n", so->cfecho);
8014b7fe92cSOliver Hartkopp 
8024b7fe92cSOliver Hartkopp 	/* set consecutive frame echo tag */
8034b7fe92cSOliver Hartkopp 	so->cfecho = *(u32 *)cf->data;
8044b7fe92cSOliver Hartkopp 
8054b7fe92cSOliver Hartkopp 	/* send frame with local echo enabled */
8064b7fe92cSOliver Hartkopp 	can_send_ret = can_send(skb, 1);
8074b7fe92cSOliver Hartkopp 	if (can_send_ret) {
8084b7fe92cSOliver Hartkopp 		pr_notice_once("can-isotp: %s: can_send_ret %pe\n",
8094b7fe92cSOliver Hartkopp 			       __func__, ERR_PTR(can_send_ret));
8104b7fe92cSOliver Hartkopp 		if (can_send_ret == -ENOBUFS)
8114b7fe92cSOliver Hartkopp 			pr_notice_once("can-isotp: tx queue is full\n");
8124b7fe92cSOliver Hartkopp 	}
8134b7fe92cSOliver Hartkopp 	dev_put(dev);
8144b7fe92cSOliver Hartkopp }
8154b7fe92cSOliver Hartkopp 
isotp_create_fframe(struct canfd_frame * cf,struct isotp_sock * so,int ae)816e057dd3fSOliver Hartkopp static void isotp_create_fframe(struct canfd_frame *cf, struct isotp_sock *so,
817e057dd3fSOliver Hartkopp 				int ae)
818e057dd3fSOliver Hartkopp {
819e057dd3fSOliver Hartkopp 	int i;
820e057dd3fSOliver Hartkopp 	int ff_pci_sz;
821e057dd3fSOliver Hartkopp 
822e057dd3fSOliver Hartkopp 	cf->can_id = so->txid;
823e057dd3fSOliver Hartkopp 	cf->len = so->tx.ll_dl;
824e057dd3fSOliver Hartkopp 	if (ae)
825e057dd3fSOliver Hartkopp 		cf->data[0] = so->opt.ext_address;
826e057dd3fSOliver Hartkopp 
827e057dd3fSOliver Hartkopp 	/* create N_PCI bytes with 12/32 bit FF_DL data length */
82896d1c81eSOliver Hartkopp 	if (so->tx.len > MAX_12BIT_PDU_SIZE) {
829e057dd3fSOliver Hartkopp 		/* use 32 bit FF_DL notation */
830e057dd3fSOliver Hartkopp 		cf->data[ae] = N_PCI_FF;
831e057dd3fSOliver Hartkopp 		cf->data[ae + 1] = 0;
832e057dd3fSOliver Hartkopp 		cf->data[ae + 2] = (u8)(so->tx.len >> 24) & 0xFFU;
833e057dd3fSOliver Hartkopp 		cf->data[ae + 3] = (u8)(so->tx.len >> 16) & 0xFFU;
834e057dd3fSOliver Hartkopp 		cf->data[ae + 4] = (u8)(so->tx.len >> 8) & 0xFFU;
835e057dd3fSOliver Hartkopp 		cf->data[ae + 5] = (u8)so->tx.len & 0xFFU;
836e057dd3fSOliver Hartkopp 		ff_pci_sz = FF_PCI_SZ32;
837e057dd3fSOliver Hartkopp 	} else {
838e057dd3fSOliver Hartkopp 		/* use 12 bit FF_DL notation */
839e057dd3fSOliver Hartkopp 		cf->data[ae] = (u8)(so->tx.len >> 8) | N_PCI_FF;
840e057dd3fSOliver Hartkopp 		cf->data[ae + 1] = (u8)so->tx.len & 0xFFU;
841e057dd3fSOliver Hartkopp 		ff_pci_sz = FF_PCI_SZ12;
842e057dd3fSOliver Hartkopp 	}
843e057dd3fSOliver Hartkopp 
844e057dd3fSOliver Hartkopp 	/* add first data bytes depending on ae */
845e057dd3fSOliver Hartkopp 	for (i = ae + ff_pci_sz; i < so->tx.ll_dl; i++)
846e057dd3fSOliver Hartkopp 		cf->data[i] = so->tx.buf[so->tx.idx++];
847e057dd3fSOliver Hartkopp 
848e057dd3fSOliver Hartkopp 	so->tx.sn = 1;
849e057dd3fSOliver Hartkopp }
850e057dd3fSOliver Hartkopp 
isotp_rcv_echo(struct sk_buff * skb,void * data)8514b7fe92cSOliver Hartkopp static void isotp_rcv_echo(struct sk_buff *skb, void *data)
8524b7fe92cSOliver Hartkopp {
8534b7fe92cSOliver Hartkopp 	struct sock *sk = (struct sock *)data;
8544b7fe92cSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
8554b7fe92cSOliver Hartkopp 	struct canfd_frame *cf = (struct canfd_frame *)skb->data;
8564b7fe92cSOliver Hartkopp 
85786633786SOliver Hartkopp 	/* only handle my own local echo CF/SF skb's (no FF!) */
8584b7fe92cSOliver Hartkopp 	if (skb->sk != sk || so->cfecho != *(u32 *)cf->data)
8594b7fe92cSOliver Hartkopp 		return;
8604b7fe92cSOliver Hartkopp 
8614b7fe92cSOliver Hartkopp 	/* cancel local echo timeout */
8624b7fe92cSOliver Hartkopp 	hrtimer_cancel(&so->txtimer);
8634b7fe92cSOliver Hartkopp 
8644b7fe92cSOliver Hartkopp 	/* local echo skb with consecutive frame has been consumed */
8654b7fe92cSOliver Hartkopp 	so->cfecho = 0;
8664b7fe92cSOliver Hartkopp 
8674b7fe92cSOliver Hartkopp 	if (so->tx.idx >= so->tx.len) {
8684b7fe92cSOliver Hartkopp 		/* we are done */
8694b7fe92cSOliver Hartkopp 		so->tx.state = ISOTP_IDLE;
8704b7fe92cSOliver Hartkopp 		wake_up_interruptible(&so->wait);
8714b7fe92cSOliver Hartkopp 		return;
8724b7fe92cSOliver Hartkopp 	}
8734b7fe92cSOliver Hartkopp 
8744b7fe92cSOliver Hartkopp 	if (so->txfc.bs && so->tx.bs >= so->txfc.bs) {
8754b7fe92cSOliver Hartkopp 		/* stop and wait for FC with timeout */
8764b7fe92cSOliver Hartkopp 		so->tx.state = ISOTP_WAIT_FC;
87786633786SOliver Hartkopp 		hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
8784b7fe92cSOliver Hartkopp 			      HRTIMER_MODE_REL_SOFT);
8794b7fe92cSOliver Hartkopp 		return;
8804b7fe92cSOliver Hartkopp 	}
8814b7fe92cSOliver Hartkopp 
8824b7fe92cSOliver Hartkopp 	/* no gap between data frames needed => use burst mode */
8834b7fe92cSOliver Hartkopp 	if (!so->tx_gap) {
88486633786SOliver Hartkopp 		/* enable echo timeout handling */
88586633786SOliver Hartkopp 		hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
88686633786SOliver Hartkopp 			      HRTIMER_MODE_REL_SOFT);
8874b7fe92cSOliver Hartkopp 		isotp_send_cframe(so);
8884b7fe92cSOliver Hartkopp 		return;
8894b7fe92cSOliver Hartkopp 	}
8904b7fe92cSOliver Hartkopp 
8914b7fe92cSOliver Hartkopp 	/* start timer to send next consecutive frame with correct delay */
8924f027cbaSOliver Hartkopp 	hrtimer_start(&so->txfrtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
8934b7fe92cSOliver Hartkopp }
8944b7fe92cSOliver Hartkopp 
isotp_tx_timer_handler(struct hrtimer * hrtimer)895e057dd3fSOliver Hartkopp static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
896e057dd3fSOliver Hartkopp {
897e057dd3fSOliver Hartkopp 	struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
898e057dd3fSOliver Hartkopp 					     txtimer);
899e057dd3fSOliver Hartkopp 	struct sock *sk = &so->sk;
900e057dd3fSOliver Hartkopp 
90105173743SOliver Hartkopp 	/* don't handle timeouts in IDLE or SHUTDOWN state */
90205173743SOliver Hartkopp 	if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN)
9034f027cbaSOliver Hartkopp 		return HRTIMER_NORESTART;
9044b7fe92cSOliver Hartkopp 
9054f027cbaSOliver Hartkopp 	/* we did not get any flow control or echo frame in time */
906e057dd3fSOliver Hartkopp 
907e057dd3fSOliver Hartkopp 	/* report 'communication error on send' */
908e057dd3fSOliver Hartkopp 	sk->sk_err = ECOMM;
909e057dd3fSOliver Hartkopp 	if (!sock_flag(sk, SOCK_DEAD))
910e3ae2365SAlexander Aring 		sk_error_report(sk);
911e057dd3fSOliver Hartkopp 
912e057dd3fSOliver Hartkopp 	/* reset tx state */
913e057dd3fSOliver Hartkopp 	so->tx.state = ISOTP_IDLE;
914e057dd3fSOliver Hartkopp 	wake_up_interruptible(&so->wait);
915e057dd3fSOliver Hartkopp 
9164f027cbaSOliver Hartkopp 	return HRTIMER_NORESTART;
917e057dd3fSOliver Hartkopp }
918e057dd3fSOliver Hartkopp 
isotp_txfr_timer_handler(struct hrtimer * hrtimer)9194f027cbaSOliver Hartkopp static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer)
9204f027cbaSOliver Hartkopp {
9214f027cbaSOliver Hartkopp 	struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
9224f027cbaSOliver Hartkopp 					     txfrtimer);
9234f027cbaSOliver Hartkopp 
9244f027cbaSOliver Hartkopp 	/* start echo timeout handling and cover below protocol error */
9254f027cbaSOliver Hartkopp 	hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
9264f027cbaSOliver Hartkopp 		      HRTIMER_MODE_REL_SOFT);
9274f027cbaSOliver Hartkopp 
9284f027cbaSOliver Hartkopp 	/* cfecho should be consumed by isotp_rcv_echo() here */
9294f027cbaSOliver Hartkopp 	if (so->tx.state == ISOTP_SENDING && !so->cfecho)
9304f027cbaSOliver Hartkopp 		isotp_send_cframe(so);
9314f027cbaSOliver Hartkopp 
9324f027cbaSOliver Hartkopp 	return HRTIMER_NORESTART;
933e057dd3fSOliver Hartkopp }
934e057dd3fSOliver Hartkopp 
isotp_sendmsg(struct socket * sock,struct msghdr * msg,size_t size)935e057dd3fSOliver Hartkopp static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
936e057dd3fSOliver Hartkopp {
937e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
938e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
939e057dd3fSOliver Hartkopp 	struct sk_buff *skb;
940e057dd3fSOliver Hartkopp 	struct net_device *dev;
941e057dd3fSOliver Hartkopp 	struct canfd_frame *cf;
942e057dd3fSOliver Hartkopp 	int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
943e057dd3fSOliver Hartkopp 	int wait_tx_done = (so->opt.flags & CAN_ISOTP_WAIT_TX_DONE) ? 1 : 0;
94486633786SOliver Hartkopp 	s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT;
945e057dd3fSOliver Hartkopp 	int off;
946e057dd3fSOliver Hartkopp 	int err;
947e057dd3fSOliver Hartkopp 
94805173743SOliver Hartkopp 	if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
949e057dd3fSOliver Hartkopp 		return -EADDRNOTAVAIL;
950e057dd3fSOliver Hartkopp 
951*d9c2ba65SLukas Magel 	while (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) {
952e057dd3fSOliver Hartkopp 		/* we do not support multiple buffers - for now */
953*d9c2ba65SLukas Magel 		if (msg->msg_flags & MSG_DONTWAIT)
95405173743SOliver Hartkopp 			return -EAGAIN;
955e057dd3fSOliver Hartkopp 
956*d9c2ba65SLukas Magel 		if (so->tx.state == ISOTP_SHUTDOWN)
957*d9c2ba65SLukas Magel 			return -EADDRNOTAVAIL;
958*d9c2ba65SLukas Magel 
959e057dd3fSOliver Hartkopp 		/* wait for complete transmission of current pdu */
9609acf6362SZiyang Xuan 		err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
9619acf6362SZiyang Xuan 		if (err)
96205173743SOliver Hartkopp 			goto err_event_drop;
963e057dd3fSOliver Hartkopp 	}
964e057dd3fSOliver Hartkopp 
96596d1c81eSOliver Hartkopp 	/* PDU size > default => try max_pdu_size */
96696d1c81eSOliver Hartkopp 	if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) {
96796d1c81eSOliver Hartkopp 		u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL);
96896d1c81eSOliver Hartkopp 
96996d1c81eSOliver Hartkopp 		if (newbuf) {
97096d1c81eSOliver Hartkopp 			so->tx.buf = newbuf;
97196d1c81eSOliver Hartkopp 			so->tx.buflen = max_pdu_size;
97296d1c81eSOliver Hartkopp 		}
97396d1c81eSOliver Hartkopp 	}
97496d1c81eSOliver Hartkopp 
97596d1c81eSOliver Hartkopp 	if (!size || size > so->tx.buflen) {
97643a08c3bSZiyang Xuan 		err = -EINVAL;
9778375dfacSOliver Hartkopp 		goto err_out_drop;
97843a08c3bSZiyang Xuan 	}
979e057dd3fSOliver Hartkopp 
980921ca574SOliver Hartkopp 	/* take care of a potential SF_DL ESC offset for TX_DL > 8 */
981921ca574SOliver Hartkopp 	off = (so->tx.ll_dl > CAN_MAX_DLEN) ? 1 : 0;
982921ca574SOliver Hartkopp 
983921ca574SOliver Hartkopp 	/* does the given data fit into a single frame for SF_BROADCAST? */
9849f39d365SOliver Hartkopp 	if ((isotp_bc_flags(so) == CAN_ISOTP_SF_BROADCAST) &&
98543a08c3bSZiyang Xuan 	    (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) {
98643a08c3bSZiyang Xuan 		err = -EINVAL;
9878375dfacSOliver Hartkopp 		goto err_out_drop;
98843a08c3bSZiyang Xuan 	}
989921ca574SOliver Hartkopp 
990e057dd3fSOliver Hartkopp 	err = memcpy_from_msg(so->tx.buf, msg, size);
991e057dd3fSOliver Hartkopp 	if (err < 0)
9928375dfacSOliver Hartkopp 		goto err_out_drop;
993e057dd3fSOliver Hartkopp 
994e057dd3fSOliver Hartkopp 	dev = dev_get_by_index(sock_net(sk), so->ifindex);
99543a08c3bSZiyang Xuan 	if (!dev) {
99643a08c3bSZiyang Xuan 		err = -ENXIO;
9978375dfacSOliver Hartkopp 		goto err_out_drop;
99843a08c3bSZiyang Xuan 	}
999e057dd3fSOliver Hartkopp 
1000e057dd3fSOliver Hartkopp 	skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv),
1001e057dd3fSOliver Hartkopp 				  msg->msg_flags & MSG_DONTWAIT, &err);
1002e057dd3fSOliver Hartkopp 	if (!skb) {
1003e057dd3fSOliver Hartkopp 		dev_put(dev);
10048375dfacSOliver Hartkopp 		goto err_out_drop;
1005e057dd3fSOliver Hartkopp 	}
1006e057dd3fSOliver Hartkopp 
1007e057dd3fSOliver Hartkopp 	can_skb_reserve(skb);
1008e057dd3fSOliver Hartkopp 	can_skb_prv(skb)->ifindex = dev->ifindex;
1009e057dd3fSOliver Hartkopp 	can_skb_prv(skb)->skbcnt = 0;
1010e057dd3fSOliver Hartkopp 
1011e057dd3fSOliver Hartkopp 	so->tx.len = size;
1012e057dd3fSOliver Hartkopp 	so->tx.idx = 0;
1013e057dd3fSOliver Hartkopp 
1014e057dd3fSOliver Hartkopp 	cf = (struct canfd_frame *)skb->data;
1015b5f020f8SOliver Hartkopp 	skb_put_zero(skb, so->ll.mtu);
1016e057dd3fSOliver Hartkopp 
101786633786SOliver Hartkopp 	/* cfecho should have been zero'ed by init / former isotp_rcv_echo() */
101886633786SOliver Hartkopp 	if (so->cfecho)
101986633786SOliver Hartkopp 		pr_notice_once("can-isotp: uninit cfecho %08X\n", so->cfecho);
102086633786SOliver Hartkopp 
1021e057dd3fSOliver Hartkopp 	/* check for single frame transmission depending on TX_DL */
1022e057dd3fSOliver Hartkopp 	if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) {
1023e057dd3fSOliver Hartkopp 		/* The message size generally fits into a SingleFrame - good.
1024e057dd3fSOliver Hartkopp 		 *
1025e057dd3fSOliver Hartkopp 		 * SF_DL ESC offset optimization:
1026e057dd3fSOliver Hartkopp 		 *
1027e057dd3fSOliver Hartkopp 		 * When TX_DL is greater 8 but the message would still fit
1028e057dd3fSOliver Hartkopp 		 * into a 8 byte CAN frame, we can omit the offset.
1029e057dd3fSOliver Hartkopp 		 * This prevents a protocol caused length extension from
1030e057dd3fSOliver Hartkopp 		 * CAN_DL = 8 to CAN_DL = 12 due to the SF_SL ESC handling.
1031e057dd3fSOliver Hartkopp 		 */
1032e057dd3fSOliver Hartkopp 		if (size <= CAN_MAX_DLEN - SF_PCI_SZ4 - ae)
1033e057dd3fSOliver Hartkopp 			off = 0;
1034e057dd3fSOliver Hartkopp 
1035e057dd3fSOliver Hartkopp 		isotp_fill_dataframe(cf, so, ae, off);
1036e057dd3fSOliver Hartkopp 
1037e057dd3fSOliver Hartkopp 		/* place single frame N_PCI w/o length in appropriate index */
1038e057dd3fSOliver Hartkopp 		cf->data[ae] = N_PCI_SF;
1039e057dd3fSOliver Hartkopp 
1040e057dd3fSOliver Hartkopp 		/* place SF_DL size value depending on the SF_DL ESC offset */
1041e057dd3fSOliver Hartkopp 		if (off)
1042e057dd3fSOliver Hartkopp 			cf->data[SF_PCI_SZ4 + ae] = size;
1043e057dd3fSOliver Hartkopp 		else
1044e057dd3fSOliver Hartkopp 			cf->data[ae] |= size;
1045e057dd3fSOliver Hartkopp 
104686633786SOliver Hartkopp 		/* set CF echo tag for isotp_rcv_echo() (SF-mode) */
104786633786SOliver Hartkopp 		so->cfecho = *(u32 *)cf->data;
1048e057dd3fSOliver Hartkopp 	} else {
10499f39d365SOliver Hartkopp 		/* send first frame */
1050e057dd3fSOliver Hartkopp 
1051e057dd3fSOliver Hartkopp 		isotp_create_fframe(cf, so, ae);
1052e057dd3fSOliver Hartkopp 
10539f39d365SOliver Hartkopp 		if (isotp_bc_flags(so) == CAN_ISOTP_CF_BROADCAST) {
10549f39d365SOliver Hartkopp 			/* set timer for FC-less operation (STmin = 0) */
10559f39d365SOliver Hartkopp 			if (so->opt.flags & CAN_ISOTP_FORCE_TXSTMIN)
10569f39d365SOliver Hartkopp 				so->tx_gap = ktime_set(0, so->force_tx_stmin);
10579f39d365SOliver Hartkopp 			else
10589f39d365SOliver Hartkopp 				so->tx_gap = ktime_set(0, so->frame_txtime);
10599f39d365SOliver Hartkopp 
10609f39d365SOliver Hartkopp 			/* disable wait for FCs due to activated block size */
10619f39d365SOliver Hartkopp 			so->txfc.bs = 0;
10629f39d365SOliver Hartkopp 
106386633786SOliver Hartkopp 			/* set CF echo tag for isotp_rcv_echo() (CF-mode) */
10649f39d365SOliver Hartkopp 			so->cfecho = *(u32 *)cf->data;
10659f39d365SOliver Hartkopp 		} else {
10669f39d365SOliver Hartkopp 			/* standard flow control check */
10679f39d365SOliver Hartkopp 			so->tx.state = ISOTP_WAIT_FIRST_FC;
10689f39d365SOliver Hartkopp 
1069e057dd3fSOliver Hartkopp 			/* start timeout for FC */
107086633786SOliver Hartkopp 			hrtimer_sec = ISOTP_FC_TIMEOUT;
107186633786SOliver Hartkopp 
107286633786SOliver Hartkopp 			/* no CF echo tag for isotp_rcv_echo() (FF-mode) */
107386633786SOliver Hartkopp 			so->cfecho = 0;
107486633786SOliver Hartkopp 		}
10759f39d365SOliver Hartkopp 	}
10769f39d365SOliver Hartkopp 
1077d7349708SOliver Hartkopp 	hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
1078d7349708SOliver Hartkopp 		      HRTIMER_MODE_REL_SOFT);
1079e057dd3fSOliver Hartkopp 
1080e057dd3fSOliver Hartkopp 	/* send the first or only CAN frame */
1081e057dd3fSOliver Hartkopp 	cf->flags = so->ll.tx_flags;
1082e057dd3fSOliver Hartkopp 
1083e057dd3fSOliver Hartkopp 	skb->dev = dev;
1084e057dd3fSOliver Hartkopp 	skb->sk = sk;
1085e057dd3fSOliver Hartkopp 	err = can_send(skb, 1);
1086e057dd3fSOliver Hartkopp 	dev_put(dev);
1087e057dd3fSOliver Hartkopp 	if (err) {
108846d8657aSPatrick Menschel 		pr_notice_once("can-isotp: %s: can_send_ret %pe\n",
108946d8657aSPatrick Menschel 			       __func__, ERR_PTR(err));
1090d7349708SOliver Hartkopp 
1091d7349708SOliver Hartkopp 		/* no transmission -> no timeout monitoring */
1092d7349708SOliver Hartkopp 		hrtimer_cancel(&so->txtimer);
1093d7349708SOliver Hartkopp 
10949f39d365SOliver Hartkopp 		/* reset consecutive frame echo tag */
10959f39d365SOliver Hartkopp 		so->cfecho = 0;
10969f39d365SOliver Hartkopp 
10978375dfacSOliver Hartkopp 		goto err_out_drop;
1098e057dd3fSOliver Hartkopp 	}
1099e057dd3fSOliver Hartkopp 
1100e057dd3fSOliver Hartkopp 	if (wait_tx_done) {
1101e057dd3fSOliver Hartkopp 		/* wait for complete transmission of current pdu */
110205173743SOliver Hartkopp 		err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
110305173743SOliver Hartkopp 		if (err)
110405173743SOliver Hartkopp 			goto err_event_drop;
1105d674a8f1SMarc Kleine-Budde 
1106e38910c0SOliver Hartkopp 		err = sock_error(sk);
1107e38910c0SOliver Hartkopp 		if (err)
1108e38910c0SOliver Hartkopp 			return err;
1109e057dd3fSOliver Hartkopp 	}
1110e057dd3fSOliver Hartkopp 
1111e057dd3fSOliver Hartkopp 	return size;
111243a08c3bSZiyang Xuan 
111305173743SOliver Hartkopp err_event_drop:
111405173743SOliver Hartkopp 	/* got signal: force tx state machine to be idle */
111505173743SOliver Hartkopp 	so->tx.state = ISOTP_IDLE;
111605173743SOliver Hartkopp 	hrtimer_cancel(&so->txfrtimer);
111705173743SOliver Hartkopp 	hrtimer_cancel(&so->txtimer);
11188375dfacSOliver Hartkopp err_out_drop:
11198375dfacSOliver Hartkopp 	/* drop this PDU and unlock a potential wait queue */
112005173743SOliver Hartkopp 	so->tx.state = ISOTP_IDLE;
112143a08c3bSZiyang Xuan 	wake_up_interruptible(&so->wait);
112243a08c3bSZiyang Xuan 
112343a08c3bSZiyang Xuan 	return err;
1124e057dd3fSOliver Hartkopp }
1125e057dd3fSOliver Hartkopp 
isotp_recvmsg(struct socket * sock,struct msghdr * msg,size_t size,int flags)1126e057dd3fSOliver Hartkopp static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
1127e057dd3fSOliver Hartkopp 			 int flags)
1128e057dd3fSOliver Hartkopp {
1129e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
1130e057dd3fSOliver Hartkopp 	struct sk_buff *skb;
113130ffd533SOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
113242bf50a1SOliver Hartkopp 	int ret = 0;
1133e057dd3fSOliver Hartkopp 
1134db2773d6SOliver Hartkopp 	if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK | MSG_CMSG_COMPAT))
113542bf50a1SOliver Hartkopp 		return -EINVAL;
1136e057dd3fSOliver Hartkopp 
113730ffd533SOliver Hartkopp 	if (!so->bound)
113830ffd533SOliver Hartkopp 		return -EADDRNOTAVAIL;
113930ffd533SOliver Hartkopp 
1140f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &ret);
1141e057dd3fSOliver Hartkopp 	if (!skb)
114242bf50a1SOliver Hartkopp 		return ret;
1143e057dd3fSOliver Hartkopp 
1144e057dd3fSOliver Hartkopp 	if (size < skb->len)
1145e057dd3fSOliver Hartkopp 		msg->msg_flags |= MSG_TRUNC;
1146e057dd3fSOliver Hartkopp 	else
1147e057dd3fSOliver Hartkopp 		size = skb->len;
1148e057dd3fSOliver Hartkopp 
114942bf50a1SOliver Hartkopp 	ret = memcpy_to_msg(msg, skb->data, size);
115042bf50a1SOliver Hartkopp 	if (ret < 0)
115142bf50a1SOliver Hartkopp 		goto out_err;
1152e057dd3fSOliver Hartkopp 
11530145462fSOliver Hartkopp 	sock_recv_cmsgs(msg, sk, skb);
1154e057dd3fSOliver Hartkopp 
1155e057dd3fSOliver Hartkopp 	if (msg->msg_name) {
1156f522d955SOliver Hartkopp 		__sockaddr_check_size(ISOTP_MIN_NAMELEN);
1157f522d955SOliver Hartkopp 		msg->msg_namelen = ISOTP_MIN_NAMELEN;
1158e057dd3fSOliver Hartkopp 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
1159e057dd3fSOliver Hartkopp 	}
1160e057dd3fSOliver Hartkopp 
116142bf50a1SOliver Hartkopp 	/* set length of return value */
116242bf50a1SOliver Hartkopp 	ret = (flags & MSG_TRUNC) ? skb->len : size;
116342bf50a1SOliver Hartkopp 
116442bf50a1SOliver Hartkopp out_err:
1165e057dd3fSOliver Hartkopp 	skb_free_datagram(sk, skb);
1166e057dd3fSOliver Hartkopp 
116742bf50a1SOliver Hartkopp 	return ret;
1168e057dd3fSOliver Hartkopp }
1169e057dd3fSOliver Hartkopp 
isotp_release(struct socket * sock)1170e057dd3fSOliver Hartkopp static int isotp_release(struct socket *sock)
1171e057dd3fSOliver Hartkopp {
1172e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
1173e057dd3fSOliver Hartkopp 	struct isotp_sock *so;
1174e057dd3fSOliver Hartkopp 	struct net *net;
1175e057dd3fSOliver Hartkopp 
1176e057dd3fSOliver Hartkopp 	if (!sk)
1177e057dd3fSOliver Hartkopp 		return 0;
1178e057dd3fSOliver Hartkopp 
1179e057dd3fSOliver Hartkopp 	so = isotp_sk(sk);
1180e057dd3fSOliver Hartkopp 	net = sock_net(sk);
1181e057dd3fSOliver Hartkopp 
1182e057dd3fSOliver Hartkopp 	/* wait for complete transmission of current pdu */
118305173743SOliver Hartkopp 	while (wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0 &&
118405173743SOliver Hartkopp 	       cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SHUTDOWN) != ISOTP_IDLE)
118505173743SOliver Hartkopp 		;
1186e057dd3fSOliver Hartkopp 
1187823b2e42SOliver Hartkopp 	/* force state machines to be idle also when a signal occurred */
118805173743SOliver Hartkopp 	so->tx.state = ISOTP_SHUTDOWN;
1189823b2e42SOliver Hartkopp 	so->rx.state = ISOTP_IDLE;
1190823b2e42SOliver Hartkopp 
11918d0caedbSTetsuo Handa 	spin_lock(&isotp_notifier_lock);
11928d0caedbSTetsuo Handa 	while (isotp_busy_notifier == so) {
11938d0caedbSTetsuo Handa 		spin_unlock(&isotp_notifier_lock);
11948d0caedbSTetsuo Handa 		schedule_timeout_uninterruptible(1);
11958d0caedbSTetsuo Handa 		spin_lock(&isotp_notifier_lock);
11968d0caedbSTetsuo Handa 	}
11978d0caedbSTetsuo Handa 	list_del(&so->notifier);
11988d0caedbSTetsuo Handa 	spin_unlock(&isotp_notifier_lock);
1199e057dd3fSOliver Hartkopp 
1200e057dd3fSOliver Hartkopp 	lock_sock(sk);
1201e057dd3fSOliver Hartkopp 
1202e057dd3fSOliver Hartkopp 	/* remove current filters & unregister */
12030bfe7115SOliver Hartkopp 	if (so->bound) {
1204e057dd3fSOliver Hartkopp 		if (so->ifindex) {
1205e057dd3fSOliver Hartkopp 			struct net_device *dev;
1206e057dd3fSOliver Hartkopp 
1207e057dd3fSOliver Hartkopp 			dev = dev_get_by_index(net, so->ifindex);
1208e057dd3fSOliver Hartkopp 			if (dev) {
12099f39d365SOliver Hartkopp 				if (isotp_register_rxid(so))
1210e057dd3fSOliver Hartkopp 					can_rx_unregister(net, dev, so->rxid,
1211e057dd3fSOliver Hartkopp 							  SINGLE_MASK(so->rxid),
1212e057dd3fSOliver Hartkopp 							  isotp_rcv, sk);
12139f39d365SOliver Hartkopp 
12144b7fe92cSOliver Hartkopp 				can_rx_unregister(net, dev, so->txid,
12154b7fe92cSOliver Hartkopp 						  SINGLE_MASK(so->txid),
12164b7fe92cSOliver Hartkopp 						  isotp_rcv_echo, sk);
1217e057dd3fSOliver Hartkopp 				dev_put(dev);
121814a4696bSOliver Hartkopp 				synchronize_rcu();
1219e057dd3fSOliver Hartkopp 			}
1220e057dd3fSOliver Hartkopp 		}
1221e057dd3fSOliver Hartkopp 	}
1222e057dd3fSOliver Hartkopp 
12234f027cbaSOliver Hartkopp 	hrtimer_cancel(&so->txfrtimer);
122414a4696bSOliver Hartkopp 	hrtimer_cancel(&so->txtimer);
122514a4696bSOliver Hartkopp 	hrtimer_cancel(&so->rxtimer);
122614a4696bSOliver Hartkopp 
1227e057dd3fSOliver Hartkopp 	so->ifindex = 0;
1228e057dd3fSOliver Hartkopp 	so->bound = 0;
1229e057dd3fSOliver Hartkopp 
123096d1c81eSOliver Hartkopp 	if (so->rx.buf != so->rx.sbuf)
123196d1c81eSOliver Hartkopp 		kfree(so->rx.buf);
123296d1c81eSOliver Hartkopp 
123396d1c81eSOliver Hartkopp 	if (so->tx.buf != so->tx.sbuf)
123496d1c81eSOliver Hartkopp 		kfree(so->tx.buf);
123596d1c81eSOliver Hartkopp 
1236e057dd3fSOliver Hartkopp 	sock_orphan(sk);
1237e057dd3fSOliver Hartkopp 	sock->sk = NULL;
1238e057dd3fSOliver Hartkopp 
1239e057dd3fSOliver Hartkopp 	release_sock(sk);
1240e057dd3fSOliver Hartkopp 	sock_put(sk);
1241e057dd3fSOliver Hartkopp 
1242e057dd3fSOliver Hartkopp 	return 0;
1243e057dd3fSOliver Hartkopp }
1244e057dd3fSOliver Hartkopp 
isotp_bind(struct socket * sock,struct sockaddr * uaddr,int len)1245e057dd3fSOliver Hartkopp static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
1246e057dd3fSOliver Hartkopp {
1247e057dd3fSOliver Hartkopp 	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
1248e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
1249e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
1250e057dd3fSOliver Hartkopp 	struct net *net = sock_net(sk);
1251e057dd3fSOliver Hartkopp 	int ifindex;
1252e057dd3fSOliver Hartkopp 	struct net_device *dev;
1253b76b163fSOliver Hartkopp 	canid_t tx_id = addr->can_addr.tp.tx_id;
1254b76b163fSOliver Hartkopp 	canid_t rx_id = addr->can_addr.tp.rx_id;
1255e057dd3fSOliver Hartkopp 	int err = 0;
1256e057dd3fSOliver Hartkopp 	int notify_enetdown = 0;
1257e057dd3fSOliver Hartkopp 
1258f522d955SOliver Hartkopp 	if (len < ISOTP_MIN_NAMELEN)
1259e057dd3fSOliver Hartkopp 		return -EINVAL;
1260e057dd3fSOliver Hartkopp 
1261c6adf659SOliver Hartkopp 	if (addr->can_family != AF_CAN)
1262c6adf659SOliver Hartkopp 		return -EINVAL;
1263c6adf659SOliver Hartkopp 
1264b76b163fSOliver Hartkopp 	/* sanitize tx CAN identifier */
12653ea56642SOliver Hartkopp 	if (tx_id & CAN_EFF_FLAG)
12663ea56642SOliver Hartkopp 		tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
12673ea56642SOliver Hartkopp 	else
12683ea56642SOliver Hartkopp 		tx_id &= CAN_SFF_MASK;
12693ea56642SOliver Hartkopp 
1270b76b163fSOliver Hartkopp 	/* give feedback on wrong CAN-ID value */
1271b76b163fSOliver Hartkopp 	if (tx_id != addr->can_addr.tp.tx_id)
1272b76b163fSOliver Hartkopp 		return -EINVAL;
1273b76b163fSOliver Hartkopp 
1274b76b163fSOliver Hartkopp 	/* sanitize rx CAN identifier (if needed) */
1275b76b163fSOliver Hartkopp 	if (isotp_register_rxid(so)) {
12763ea56642SOliver Hartkopp 		if (rx_id & CAN_EFF_FLAG)
12773ea56642SOliver Hartkopp 			rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
12783ea56642SOliver Hartkopp 		else
12793ea56642SOliver Hartkopp 			rx_id &= CAN_SFF_MASK;
1280e057dd3fSOliver Hartkopp 
1281b76b163fSOliver Hartkopp 		/* give feedback on wrong CAN-ID value */
1282b76b163fSOliver Hartkopp 		if (rx_id != addr->can_addr.tp.rx_id)
12832aa39889SOliver Hartkopp 			return -EINVAL;
1284b76b163fSOliver Hartkopp 	}
12852aa39889SOliver Hartkopp 
1286e057dd3fSOliver Hartkopp 	if (!addr->can_ifindex)
1287e057dd3fSOliver Hartkopp 		return -ENODEV;
1288e057dd3fSOliver Hartkopp 
1289e057dd3fSOliver Hartkopp 	lock_sock(sk);
1290e057dd3fSOliver Hartkopp 
129172ed3ee9SOliver Hartkopp 	if (so->bound) {
129272ed3ee9SOliver Hartkopp 		err = -EINVAL;
129372ed3ee9SOliver Hartkopp 		goto out;
129472ed3ee9SOliver Hartkopp 	}
129572ed3ee9SOliver Hartkopp 
12969f39d365SOliver Hartkopp 	/* ensure different CAN IDs when the rx_id is to be registered */
12979f39d365SOliver Hartkopp 	if (isotp_register_rxid(so) && rx_id == tx_id) {
12982b17c400SNorbert Slusarek 		err = -EADDRNOTAVAIL;
12992b17c400SNorbert Slusarek 		goto out;
13002b17c400SNorbert Slusarek 	}
13012b17c400SNorbert Slusarek 
1302e057dd3fSOliver Hartkopp 	dev = dev_get_by_index(net, addr->can_ifindex);
1303e057dd3fSOliver Hartkopp 	if (!dev) {
1304e057dd3fSOliver Hartkopp 		err = -ENODEV;
1305e057dd3fSOliver Hartkopp 		goto out;
1306e057dd3fSOliver Hartkopp 	}
1307e057dd3fSOliver Hartkopp 	if (dev->type != ARPHRD_CAN) {
1308e057dd3fSOliver Hartkopp 		dev_put(dev);
1309e057dd3fSOliver Hartkopp 		err = -ENODEV;
1310e057dd3fSOliver Hartkopp 		goto out;
1311e057dd3fSOliver Hartkopp 	}
1312e057dd3fSOliver Hartkopp 	if (dev->mtu < so->ll.mtu) {
1313e057dd3fSOliver Hartkopp 		dev_put(dev);
1314e057dd3fSOliver Hartkopp 		err = -EINVAL;
1315e057dd3fSOliver Hartkopp 		goto out;
1316e057dd3fSOliver Hartkopp 	}
1317e057dd3fSOliver Hartkopp 	if (!(dev->flags & IFF_UP))
1318e057dd3fSOliver Hartkopp 		notify_enetdown = 1;
1319e057dd3fSOliver Hartkopp 
1320e057dd3fSOliver Hartkopp 	ifindex = dev->ifindex;
1321e057dd3fSOliver Hartkopp 
13229f39d365SOliver Hartkopp 	if (isotp_register_rxid(so))
13233ea56642SOliver Hartkopp 		can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
1324921ca574SOliver Hartkopp 				isotp_rcv, sk, "isotp", sk);
1325e057dd3fSOliver Hartkopp 
13264b7fe92cSOliver Hartkopp 	/* no consecutive frame echo skb in flight */
13274b7fe92cSOliver Hartkopp 	so->cfecho = 0;
13284b7fe92cSOliver Hartkopp 
13294b7fe92cSOliver Hartkopp 	/* register for echo skb's */
13303ea56642SOliver Hartkopp 	can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
13314b7fe92cSOliver Hartkopp 			isotp_rcv_echo, sk, "isotpe", sk);
13324b7fe92cSOliver Hartkopp 
1333e057dd3fSOliver Hartkopp 	dev_put(dev);
1334e057dd3fSOliver Hartkopp 
1335e057dd3fSOliver Hartkopp 	/* switch to new settings */
1336e057dd3fSOliver Hartkopp 	so->ifindex = ifindex;
13373ea56642SOliver Hartkopp 	so->rxid = rx_id;
13383ea56642SOliver Hartkopp 	so->txid = tx_id;
1339e057dd3fSOliver Hartkopp 	so->bound = 1;
1340e057dd3fSOliver Hartkopp 
1341e057dd3fSOliver Hartkopp out:
1342e057dd3fSOliver Hartkopp 	release_sock(sk);
1343e057dd3fSOliver Hartkopp 
1344e057dd3fSOliver Hartkopp 	if (notify_enetdown) {
1345e057dd3fSOliver Hartkopp 		sk->sk_err = ENETDOWN;
1346e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
1347e3ae2365SAlexander Aring 			sk_error_report(sk);
1348e057dd3fSOliver Hartkopp 	}
1349e057dd3fSOliver Hartkopp 
1350e057dd3fSOliver Hartkopp 	return err;
1351e057dd3fSOliver Hartkopp }
1352e057dd3fSOliver Hartkopp 
isotp_getname(struct socket * sock,struct sockaddr * uaddr,int peer)1353e057dd3fSOliver Hartkopp static int isotp_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
1354e057dd3fSOliver Hartkopp {
1355e057dd3fSOliver Hartkopp 	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
1356e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
1357e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
1358e057dd3fSOliver Hartkopp 
1359e057dd3fSOliver Hartkopp 	if (peer)
1360e057dd3fSOliver Hartkopp 		return -EOPNOTSUPP;
1361e057dd3fSOliver Hartkopp 
1362f522d955SOliver Hartkopp 	memset(addr, 0, ISOTP_MIN_NAMELEN);
1363e057dd3fSOliver Hartkopp 	addr->can_family = AF_CAN;
1364e057dd3fSOliver Hartkopp 	addr->can_ifindex = so->ifindex;
1365e057dd3fSOliver Hartkopp 	addr->can_addr.tp.rx_id = so->rxid;
1366e057dd3fSOliver Hartkopp 	addr->can_addr.tp.tx_id = so->txid;
1367e057dd3fSOliver Hartkopp 
1368f522d955SOliver Hartkopp 	return ISOTP_MIN_NAMELEN;
1369e057dd3fSOliver Hartkopp }
1370e057dd3fSOliver Hartkopp 
isotp_setsockopt_locked(struct socket * sock,int level,int optname,sockptr_t optval,unsigned int optlen)13712b17c400SNorbert Slusarek static int isotp_setsockopt_locked(struct socket *sock, int level, int optname,
1372e057dd3fSOliver Hartkopp 			    sockptr_t optval, unsigned int optlen)
1373e057dd3fSOliver Hartkopp {
1374e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
1375e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
1376e057dd3fSOliver Hartkopp 	int ret = 0;
1377e057dd3fSOliver Hartkopp 
1378323a391aSOliver Hartkopp 	if (so->bound)
1379323a391aSOliver Hartkopp 		return -EISCONN;
1380323a391aSOliver Hartkopp 
1381e057dd3fSOliver Hartkopp 	switch (optname) {
1382e057dd3fSOliver Hartkopp 	case CAN_ISOTP_OPTS:
1383e057dd3fSOliver Hartkopp 		if (optlen != sizeof(struct can_isotp_options))
1384e057dd3fSOliver Hartkopp 			return -EINVAL;
1385e057dd3fSOliver Hartkopp 
1386e057dd3fSOliver Hartkopp 		if (copy_from_sockptr(&so->opt, optval, optlen))
1387e057dd3fSOliver Hartkopp 			return -EFAULT;
1388e057dd3fSOliver Hartkopp 
1389e057dd3fSOliver Hartkopp 		/* no separate rx_ext_address is given => use ext_address */
1390e057dd3fSOliver Hartkopp 		if (!(so->opt.flags & CAN_ISOTP_RX_EXT_ADDR))
1391e057dd3fSOliver Hartkopp 			so->opt.rx_ext_address = so->opt.ext_address;
1392530e0d46SOliver Hartkopp 
13939f39d365SOliver Hartkopp 		/* these broadcast flags are not allowed together */
13949f39d365SOliver Hartkopp 		if (isotp_bc_flags(so) == ISOTP_ALL_BC_FLAGS) {
13959f39d365SOliver Hartkopp 			/* CAN_ISOTP_SF_BROADCAST is prioritized */
13969f39d365SOliver Hartkopp 			so->opt.flags &= ~CAN_ISOTP_CF_BROADCAST;
13979f39d365SOliver Hartkopp 
13989f39d365SOliver Hartkopp 			/* give user feedback on wrong config attempt */
13999f39d365SOliver Hartkopp 			ret = -EINVAL;
14009f39d365SOliver Hartkopp 		}
14019f39d365SOliver Hartkopp 
1402530e0d46SOliver Hartkopp 		/* check for frame_txtime changes (0 => no changes) */
1403530e0d46SOliver Hartkopp 		if (so->opt.frame_txtime) {
1404530e0d46SOliver Hartkopp 			if (so->opt.frame_txtime == CAN_ISOTP_FRAME_TXTIME_ZERO)
1405530e0d46SOliver Hartkopp 				so->frame_txtime = 0;
1406530e0d46SOliver Hartkopp 			else
1407530e0d46SOliver Hartkopp 				so->frame_txtime = so->opt.frame_txtime;
1408530e0d46SOliver Hartkopp 		}
1409e057dd3fSOliver Hartkopp 		break;
1410e057dd3fSOliver Hartkopp 
1411e057dd3fSOliver Hartkopp 	case CAN_ISOTP_RECV_FC:
1412e057dd3fSOliver Hartkopp 		if (optlen != sizeof(struct can_isotp_fc_options))
1413e057dd3fSOliver Hartkopp 			return -EINVAL;
1414e057dd3fSOliver Hartkopp 
1415e057dd3fSOliver Hartkopp 		if (copy_from_sockptr(&so->rxfc, optval, optlen))
1416e057dd3fSOliver Hartkopp 			return -EFAULT;
1417e057dd3fSOliver Hartkopp 		break;
1418e057dd3fSOliver Hartkopp 
1419e057dd3fSOliver Hartkopp 	case CAN_ISOTP_TX_STMIN:
1420e057dd3fSOliver Hartkopp 		if (optlen != sizeof(u32))
1421e057dd3fSOliver Hartkopp 			return -EINVAL;
1422e057dd3fSOliver Hartkopp 
1423e057dd3fSOliver Hartkopp 		if (copy_from_sockptr(&so->force_tx_stmin, optval, optlen))
1424e057dd3fSOliver Hartkopp 			return -EFAULT;
1425e057dd3fSOliver Hartkopp 		break;
1426e057dd3fSOliver Hartkopp 
1427e057dd3fSOliver Hartkopp 	case CAN_ISOTP_RX_STMIN:
1428e057dd3fSOliver Hartkopp 		if (optlen != sizeof(u32))
1429e057dd3fSOliver Hartkopp 			return -EINVAL;
1430e057dd3fSOliver Hartkopp 
1431e057dd3fSOliver Hartkopp 		if (copy_from_sockptr(&so->force_rx_stmin, optval, optlen))
1432e057dd3fSOliver Hartkopp 			return -EFAULT;
1433e057dd3fSOliver Hartkopp 		break;
1434e057dd3fSOliver Hartkopp 
1435e057dd3fSOliver Hartkopp 	case CAN_ISOTP_LL_OPTS:
1436e057dd3fSOliver Hartkopp 		if (optlen == sizeof(struct can_isotp_ll_options)) {
1437e057dd3fSOliver Hartkopp 			struct can_isotp_ll_options ll;
1438e057dd3fSOliver Hartkopp 
1439e057dd3fSOliver Hartkopp 			if (copy_from_sockptr(&ll, optval, optlen))
1440e057dd3fSOliver Hartkopp 				return -EFAULT;
1441e057dd3fSOliver Hartkopp 
1442e057dd3fSOliver Hartkopp 			/* check for correct ISO 11898-1 DLC data length */
1443e057dd3fSOliver Hartkopp 			if (ll.tx_dl != padlen(ll.tx_dl))
1444e057dd3fSOliver Hartkopp 				return -EINVAL;
1445e057dd3fSOliver Hartkopp 
1446e057dd3fSOliver Hartkopp 			if (ll.mtu != CAN_MTU && ll.mtu != CANFD_MTU)
1447e057dd3fSOliver Hartkopp 				return -EINVAL;
1448e057dd3fSOliver Hartkopp 
1449e4912459SMarc Kleine-Budde 			if (ll.mtu == CAN_MTU &&
1450e4912459SMarc Kleine-Budde 			    (ll.tx_dl > CAN_MAX_DLEN || ll.tx_flags != 0))
1451e057dd3fSOliver Hartkopp 				return -EINVAL;
1452e057dd3fSOliver Hartkopp 
1453e057dd3fSOliver Hartkopp 			memcpy(&so->ll, &ll, sizeof(ll));
1454e057dd3fSOliver Hartkopp 
1455e057dd3fSOliver Hartkopp 			/* set ll_dl for tx path to similar place as for rx */
1456e057dd3fSOliver Hartkopp 			so->tx.ll_dl = ll.tx_dl;
1457e057dd3fSOliver Hartkopp 		} else {
1458e057dd3fSOliver Hartkopp 			return -EINVAL;
1459e057dd3fSOliver Hartkopp 		}
1460e057dd3fSOliver Hartkopp 		break;
1461e057dd3fSOliver Hartkopp 
1462e057dd3fSOliver Hartkopp 	default:
1463e057dd3fSOliver Hartkopp 		ret = -ENOPROTOOPT;
1464e057dd3fSOliver Hartkopp 	}
1465e057dd3fSOliver Hartkopp 
1466e057dd3fSOliver Hartkopp 	return ret;
1467e057dd3fSOliver Hartkopp }
1468e057dd3fSOliver Hartkopp 
isotp_setsockopt(struct socket * sock,int level,int optname,sockptr_t optval,unsigned int optlen)14692b17c400SNorbert Slusarek static int isotp_setsockopt(struct socket *sock, int level, int optname,
14702b17c400SNorbert Slusarek 			    sockptr_t optval, unsigned int optlen)
14712b17c400SNorbert Slusarek 
14722b17c400SNorbert Slusarek {
14732b17c400SNorbert Slusarek 	struct sock *sk = sock->sk;
14742b17c400SNorbert Slusarek 	int ret;
14752b17c400SNorbert Slusarek 
14762b17c400SNorbert Slusarek 	if (level != SOL_CAN_ISOTP)
14772b17c400SNorbert Slusarek 		return -EINVAL;
14782b17c400SNorbert Slusarek 
14792b17c400SNorbert Slusarek 	lock_sock(sk);
14802b17c400SNorbert Slusarek 	ret = isotp_setsockopt_locked(sock, level, optname, optval, optlen);
14812b17c400SNorbert Slusarek 	release_sock(sk);
14822b17c400SNorbert Slusarek 	return ret;
14832b17c400SNorbert Slusarek }
14842b17c400SNorbert Slusarek 
isotp_getsockopt(struct socket * sock,int level,int optname,char __user * optval,int __user * optlen)1485e057dd3fSOliver Hartkopp static int isotp_getsockopt(struct socket *sock, int level, int optname,
1486e057dd3fSOliver Hartkopp 			    char __user *optval, int __user *optlen)
1487e057dd3fSOliver Hartkopp {
1488e057dd3fSOliver Hartkopp 	struct sock *sk = sock->sk;
1489e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
1490e057dd3fSOliver Hartkopp 	int len;
1491e057dd3fSOliver Hartkopp 	void *val;
1492e057dd3fSOliver Hartkopp 
1493e057dd3fSOliver Hartkopp 	if (level != SOL_CAN_ISOTP)
1494e057dd3fSOliver Hartkopp 		return -EINVAL;
1495e057dd3fSOliver Hartkopp 	if (get_user(len, optlen))
1496e057dd3fSOliver Hartkopp 		return -EFAULT;
1497e057dd3fSOliver Hartkopp 	if (len < 0)
1498e057dd3fSOliver Hartkopp 		return -EINVAL;
1499e057dd3fSOliver Hartkopp 
1500e057dd3fSOliver Hartkopp 	switch (optname) {
1501e057dd3fSOliver Hartkopp 	case CAN_ISOTP_OPTS:
1502e057dd3fSOliver Hartkopp 		len = min_t(int, len, sizeof(struct can_isotp_options));
1503e057dd3fSOliver Hartkopp 		val = &so->opt;
1504e057dd3fSOliver Hartkopp 		break;
1505e057dd3fSOliver Hartkopp 
1506e057dd3fSOliver Hartkopp 	case CAN_ISOTP_RECV_FC:
1507e057dd3fSOliver Hartkopp 		len = min_t(int, len, sizeof(struct can_isotp_fc_options));
1508e057dd3fSOliver Hartkopp 		val = &so->rxfc;
1509e057dd3fSOliver Hartkopp 		break;
1510e057dd3fSOliver Hartkopp 
1511e057dd3fSOliver Hartkopp 	case CAN_ISOTP_TX_STMIN:
1512e057dd3fSOliver Hartkopp 		len = min_t(int, len, sizeof(u32));
1513e057dd3fSOliver Hartkopp 		val = &so->force_tx_stmin;
1514e057dd3fSOliver Hartkopp 		break;
1515e057dd3fSOliver Hartkopp 
1516e057dd3fSOliver Hartkopp 	case CAN_ISOTP_RX_STMIN:
1517e057dd3fSOliver Hartkopp 		len = min_t(int, len, sizeof(u32));
1518e057dd3fSOliver Hartkopp 		val = &so->force_rx_stmin;
1519e057dd3fSOliver Hartkopp 		break;
1520e057dd3fSOliver Hartkopp 
1521e057dd3fSOliver Hartkopp 	case CAN_ISOTP_LL_OPTS:
1522e057dd3fSOliver Hartkopp 		len = min_t(int, len, sizeof(struct can_isotp_ll_options));
1523e057dd3fSOliver Hartkopp 		val = &so->ll;
1524e057dd3fSOliver Hartkopp 		break;
1525e057dd3fSOliver Hartkopp 
1526e057dd3fSOliver Hartkopp 	default:
1527e057dd3fSOliver Hartkopp 		return -ENOPROTOOPT;
1528e057dd3fSOliver Hartkopp 	}
1529e057dd3fSOliver Hartkopp 
1530e057dd3fSOliver Hartkopp 	if (put_user(len, optlen))
1531e057dd3fSOliver Hartkopp 		return -EFAULT;
1532e057dd3fSOliver Hartkopp 	if (copy_to_user(optval, val, len))
1533e057dd3fSOliver Hartkopp 		return -EFAULT;
1534e057dd3fSOliver Hartkopp 	return 0;
1535e057dd3fSOliver Hartkopp }
1536e057dd3fSOliver Hartkopp 
isotp_notify(struct isotp_sock * so,unsigned long msg,struct net_device * dev)15378d0caedbSTetsuo Handa static void isotp_notify(struct isotp_sock *so, unsigned long msg,
15388d0caedbSTetsuo Handa 			 struct net_device *dev)
1539e057dd3fSOliver Hartkopp {
1540e057dd3fSOliver Hartkopp 	struct sock *sk = &so->sk;
1541e057dd3fSOliver Hartkopp 
1542e057dd3fSOliver Hartkopp 	if (!net_eq(dev_net(dev), sock_net(sk)))
15438d0caedbSTetsuo Handa 		return;
1544e057dd3fSOliver Hartkopp 
1545e057dd3fSOliver Hartkopp 	if (so->ifindex != dev->ifindex)
15468d0caedbSTetsuo Handa 		return;
1547e057dd3fSOliver Hartkopp 
1548e057dd3fSOliver Hartkopp 	switch (msg) {
1549e057dd3fSOliver Hartkopp 	case NETDEV_UNREGISTER:
1550e057dd3fSOliver Hartkopp 		lock_sock(sk);
1551e057dd3fSOliver Hartkopp 		/* remove current filters & unregister */
15520bfe7115SOliver Hartkopp 		if (so->bound) {
15539f39d365SOliver Hartkopp 			if (isotp_register_rxid(so))
1554e057dd3fSOliver Hartkopp 				can_rx_unregister(dev_net(dev), dev, so->rxid,
1555e057dd3fSOliver Hartkopp 						  SINGLE_MASK(so->rxid),
1556e057dd3fSOliver Hartkopp 						  isotp_rcv, sk);
15579f39d365SOliver Hartkopp 
15584b7fe92cSOliver Hartkopp 			can_rx_unregister(dev_net(dev), dev, so->txid,
15594b7fe92cSOliver Hartkopp 					  SINGLE_MASK(so->txid),
15604b7fe92cSOliver Hartkopp 					  isotp_rcv_echo, sk);
15614b7fe92cSOliver Hartkopp 		}
1562e057dd3fSOliver Hartkopp 
1563e057dd3fSOliver Hartkopp 		so->ifindex = 0;
1564e057dd3fSOliver Hartkopp 		so->bound  = 0;
1565e057dd3fSOliver Hartkopp 		release_sock(sk);
1566e057dd3fSOliver Hartkopp 
1567e057dd3fSOliver Hartkopp 		sk->sk_err = ENODEV;
1568e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
1569e3ae2365SAlexander Aring 			sk_error_report(sk);
1570e057dd3fSOliver Hartkopp 		break;
1571e057dd3fSOliver Hartkopp 
1572e057dd3fSOliver Hartkopp 	case NETDEV_DOWN:
1573e057dd3fSOliver Hartkopp 		sk->sk_err = ENETDOWN;
1574e057dd3fSOliver Hartkopp 		if (!sock_flag(sk, SOCK_DEAD))
1575e3ae2365SAlexander Aring 			sk_error_report(sk);
1576e057dd3fSOliver Hartkopp 		break;
1577e057dd3fSOliver Hartkopp 	}
15788d0caedbSTetsuo Handa }
1579e057dd3fSOliver Hartkopp 
isotp_notifier(struct notifier_block * nb,unsigned long msg,void * ptr)15808d0caedbSTetsuo Handa static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
15818d0caedbSTetsuo Handa 			  void *ptr)
15828d0caedbSTetsuo Handa {
15838d0caedbSTetsuo Handa 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
15848d0caedbSTetsuo Handa 
15858d0caedbSTetsuo Handa 	if (dev->type != ARPHRD_CAN)
15868d0caedbSTetsuo Handa 		return NOTIFY_DONE;
15878d0caedbSTetsuo Handa 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
15888d0caedbSTetsuo Handa 		return NOTIFY_DONE;
15898d0caedbSTetsuo Handa 	if (unlikely(isotp_busy_notifier)) /* Check for reentrant bug. */
15908d0caedbSTetsuo Handa 		return NOTIFY_DONE;
15918d0caedbSTetsuo Handa 
15928d0caedbSTetsuo Handa 	spin_lock(&isotp_notifier_lock);
15938d0caedbSTetsuo Handa 	list_for_each_entry(isotp_busy_notifier, &isotp_notifier_list, notifier) {
15948d0caedbSTetsuo Handa 		spin_unlock(&isotp_notifier_lock);
15958d0caedbSTetsuo Handa 		isotp_notify(isotp_busy_notifier, msg, dev);
15968d0caedbSTetsuo Handa 		spin_lock(&isotp_notifier_lock);
15978d0caedbSTetsuo Handa 	}
15988d0caedbSTetsuo Handa 	isotp_busy_notifier = NULL;
15998d0caedbSTetsuo Handa 	spin_unlock(&isotp_notifier_lock);
1600e057dd3fSOliver Hartkopp 	return NOTIFY_DONE;
1601e057dd3fSOliver Hartkopp }
1602e057dd3fSOliver Hartkopp 
isotp_init(struct sock * sk)1603e057dd3fSOliver Hartkopp static int isotp_init(struct sock *sk)
1604e057dd3fSOliver Hartkopp {
1605e057dd3fSOliver Hartkopp 	struct isotp_sock *so = isotp_sk(sk);
1606e057dd3fSOliver Hartkopp 
1607e057dd3fSOliver Hartkopp 	so->ifindex = 0;
1608e057dd3fSOliver Hartkopp 	so->bound = 0;
1609e057dd3fSOliver Hartkopp 
1610e057dd3fSOliver Hartkopp 	so->opt.flags = CAN_ISOTP_DEFAULT_FLAGS;
1611e057dd3fSOliver Hartkopp 	so->opt.ext_address = CAN_ISOTP_DEFAULT_EXT_ADDRESS;
1612e057dd3fSOliver Hartkopp 	so->opt.rx_ext_address = CAN_ISOTP_DEFAULT_EXT_ADDRESS;
1613e057dd3fSOliver Hartkopp 	so->opt.rxpad_content = CAN_ISOTP_DEFAULT_PAD_CONTENT;
1614e057dd3fSOliver Hartkopp 	so->opt.txpad_content = CAN_ISOTP_DEFAULT_PAD_CONTENT;
1615e057dd3fSOliver Hartkopp 	so->opt.frame_txtime = CAN_ISOTP_DEFAULT_FRAME_TXTIME;
1616530e0d46SOliver Hartkopp 	so->frame_txtime = CAN_ISOTP_DEFAULT_FRAME_TXTIME;
1617e057dd3fSOliver Hartkopp 	so->rxfc.bs = CAN_ISOTP_DEFAULT_RECV_BS;
1618e057dd3fSOliver Hartkopp 	so->rxfc.stmin = CAN_ISOTP_DEFAULT_RECV_STMIN;
1619e057dd3fSOliver Hartkopp 	so->rxfc.wftmax = CAN_ISOTP_DEFAULT_RECV_WFTMAX;
1620e057dd3fSOliver Hartkopp 	so->ll.mtu = CAN_ISOTP_DEFAULT_LL_MTU;
1621e057dd3fSOliver Hartkopp 	so->ll.tx_dl = CAN_ISOTP_DEFAULT_LL_TX_DL;
1622e057dd3fSOliver Hartkopp 	so->ll.tx_flags = CAN_ISOTP_DEFAULT_LL_TX_FLAGS;
1623e057dd3fSOliver Hartkopp 
1624e057dd3fSOliver Hartkopp 	/* set ll_dl for tx path to similar place as for rx */
1625e057dd3fSOliver Hartkopp 	so->tx.ll_dl = so->ll.tx_dl;
1626e057dd3fSOliver Hartkopp 
1627e057dd3fSOliver Hartkopp 	so->rx.state = ISOTP_IDLE;
1628e057dd3fSOliver Hartkopp 	so->tx.state = ISOTP_IDLE;
1629e057dd3fSOliver Hartkopp 
163096d1c81eSOliver Hartkopp 	so->rx.buf = so->rx.sbuf;
163196d1c81eSOliver Hartkopp 	so->tx.buf = so->tx.sbuf;
163296d1c81eSOliver Hartkopp 	so->rx.buflen = ARRAY_SIZE(so->rx.sbuf);
163396d1c81eSOliver Hartkopp 	so->tx.buflen = ARRAY_SIZE(so->tx.sbuf);
163496d1c81eSOliver Hartkopp 
1635e057dd3fSOliver Hartkopp 	hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
1636e057dd3fSOliver Hartkopp 	so->rxtimer.function = isotp_rx_timer_handler;
1637e057dd3fSOliver Hartkopp 	hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
1638e057dd3fSOliver Hartkopp 	so->txtimer.function = isotp_tx_timer_handler;
16394f027cbaSOliver Hartkopp 	hrtimer_init(&so->txfrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
16404f027cbaSOliver Hartkopp 	so->txfrtimer.function = isotp_txfr_timer_handler;
1641e057dd3fSOliver Hartkopp 
1642e057dd3fSOliver Hartkopp 	init_waitqueue_head(&so->wait);
16437c759040SOliver Hartkopp 	spin_lock_init(&so->rx_lock);
1644e057dd3fSOliver Hartkopp 
16458d0caedbSTetsuo Handa 	spin_lock(&isotp_notifier_lock);
16468d0caedbSTetsuo Handa 	list_add_tail(&so->notifier, &isotp_notifier_list);
16478d0caedbSTetsuo Handa 	spin_unlock(&isotp_notifier_lock);
1648e057dd3fSOliver Hartkopp 
1649e057dd3fSOliver Hartkopp 	return 0;
1650e057dd3fSOliver Hartkopp }
1651e057dd3fSOliver Hartkopp 
isotp_poll(struct file * file,struct socket * sock,poll_table * wait)165279e19fa7SMichal Sojka static __poll_t isotp_poll(struct file *file, struct socket *sock, poll_table *wait)
165379e19fa7SMichal Sojka {
165479e19fa7SMichal Sojka 	struct sock *sk = sock->sk;
165579e19fa7SMichal Sojka 	struct isotp_sock *so = isotp_sk(sk);
165679e19fa7SMichal Sojka 
165779e19fa7SMichal Sojka 	__poll_t mask = datagram_poll(file, sock, wait);
165879e19fa7SMichal Sojka 	poll_wait(file, &so->wait, wait);
165979e19fa7SMichal Sojka 
166079e19fa7SMichal Sojka 	/* Check for false positives due to TX state */
166179e19fa7SMichal Sojka 	if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE))
166279e19fa7SMichal Sojka 		mask &= ~(EPOLLOUT | EPOLLWRNORM);
166379e19fa7SMichal Sojka 
166479e19fa7SMichal Sojka 	return mask;
166579e19fa7SMichal Sojka }
166679e19fa7SMichal Sojka 
isotp_sock_no_ioctlcmd(struct socket * sock,unsigned int cmd,unsigned long arg)1667e057dd3fSOliver Hartkopp static int isotp_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd,
1668e057dd3fSOliver Hartkopp 				  unsigned long arg)
1669e057dd3fSOliver Hartkopp {
1670e057dd3fSOliver Hartkopp 	/* no ioctls for socket layer -> hand it down to NIC layer */
1671e057dd3fSOliver Hartkopp 	return -ENOIOCTLCMD;
1672e057dd3fSOliver Hartkopp }
1673e057dd3fSOliver Hartkopp 
1674e057dd3fSOliver Hartkopp static const struct proto_ops isotp_ops = {
1675e057dd3fSOliver Hartkopp 	.family = PF_CAN,
1676e057dd3fSOliver Hartkopp 	.release = isotp_release,
1677e057dd3fSOliver Hartkopp 	.bind = isotp_bind,
1678e057dd3fSOliver Hartkopp 	.connect = sock_no_connect,
1679e057dd3fSOliver Hartkopp 	.socketpair = sock_no_socketpair,
1680e057dd3fSOliver Hartkopp 	.accept = sock_no_accept,
1681e057dd3fSOliver Hartkopp 	.getname = isotp_getname,
168279e19fa7SMichal Sojka 	.poll = isotp_poll,
1683e057dd3fSOliver Hartkopp 	.ioctl = isotp_sock_no_ioctlcmd,
1684e057dd3fSOliver Hartkopp 	.gettstamp = sock_gettstamp,
1685e057dd3fSOliver Hartkopp 	.listen = sock_no_listen,
1686e057dd3fSOliver Hartkopp 	.shutdown = sock_no_shutdown,
1687e057dd3fSOliver Hartkopp 	.setsockopt = isotp_setsockopt,
1688e057dd3fSOliver Hartkopp 	.getsockopt = isotp_getsockopt,
1689e057dd3fSOliver Hartkopp 	.sendmsg = isotp_sendmsg,
1690e057dd3fSOliver Hartkopp 	.recvmsg = isotp_recvmsg,
1691e057dd3fSOliver Hartkopp 	.mmap = sock_no_mmap,
1692e057dd3fSOliver Hartkopp };
1693e057dd3fSOliver Hartkopp 
1694e057dd3fSOliver Hartkopp static struct proto isotp_proto __read_mostly = {
1695e057dd3fSOliver Hartkopp 	.name = "CAN_ISOTP",
1696e057dd3fSOliver Hartkopp 	.owner = THIS_MODULE,
1697e057dd3fSOliver Hartkopp 	.obj_size = sizeof(struct isotp_sock),
1698e057dd3fSOliver Hartkopp 	.init = isotp_init,
1699e057dd3fSOliver Hartkopp };
1700e057dd3fSOliver Hartkopp 
1701e057dd3fSOliver Hartkopp static const struct can_proto isotp_can_proto = {
1702e057dd3fSOliver Hartkopp 	.type = SOCK_DGRAM,
1703e057dd3fSOliver Hartkopp 	.protocol = CAN_ISOTP,
1704e057dd3fSOliver Hartkopp 	.ops = &isotp_ops,
1705e057dd3fSOliver Hartkopp 	.prot = &isotp_proto,
1706e057dd3fSOliver Hartkopp };
1707e057dd3fSOliver Hartkopp 
17088d0caedbSTetsuo Handa static struct notifier_block canisotp_notifier = {
17098d0caedbSTetsuo Handa 	.notifier_call = isotp_notifier
17108d0caedbSTetsuo Handa };
17118d0caedbSTetsuo Handa 
isotp_module_init(void)1712e057dd3fSOliver Hartkopp static __init int isotp_module_init(void)
1713e057dd3fSOliver Hartkopp {
1714e057dd3fSOliver Hartkopp 	int err;
1715e057dd3fSOliver Hartkopp 
171696d1c81eSOliver Hartkopp 	max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE);
171796d1c81eSOliver Hartkopp 	max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE);
171896d1c81eSOliver Hartkopp 
171996d1c81eSOliver Hartkopp 	pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size);
1720e057dd3fSOliver Hartkopp 
1721e057dd3fSOliver Hartkopp 	err = can_proto_register(&isotp_can_proto);
1722e057dd3fSOliver Hartkopp 	if (err < 0)
17236a5ddae5SPatrick Menschel 		pr_err("can: registration of isotp protocol failed %pe\n", ERR_PTR(err));
17248d0caedbSTetsuo Handa 	else
17258d0caedbSTetsuo Handa 		register_netdevice_notifier(&canisotp_notifier);
1726e057dd3fSOliver Hartkopp 
1727e057dd3fSOliver Hartkopp 	return err;
1728e057dd3fSOliver Hartkopp }
1729e057dd3fSOliver Hartkopp 
isotp_module_exit(void)1730e057dd3fSOliver Hartkopp static __exit void isotp_module_exit(void)
1731e057dd3fSOliver Hartkopp {
1732e057dd3fSOliver Hartkopp 	can_proto_unregister(&isotp_can_proto);
17338d0caedbSTetsuo Handa 	unregister_netdevice_notifier(&canisotp_notifier);
1734e057dd3fSOliver Hartkopp }
1735e057dd3fSOliver Hartkopp 
1736e057dd3fSOliver Hartkopp module_init(isotp_module_init);
1737e057dd3fSOliver Hartkopp module_exit(isotp_module_exit);
1738