@@ -103,6 +103,7 @@ MODULE_ALIAS("can-proto-6");
103103#define FC_CONTENT_SZ 3 /* flow control content size in byte (FS/BS/STmin) */
104104
105105#define ISOTP_CHECK_PADDING (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA)
106+ #define ISOTP_ALL_BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
106107
107108/* Flow Status given in FC frame */
108109#define ISOTP_FC_CTS 0 /* clear to send */
@@ -157,6 +158,23 @@ static inline struct isotp_sock *isotp_sk(const struct sock *sk)
157158 return (struct isotp_sock * )sk ;
158159}
159160
161+ static u32 isotp_bc_flags (struct isotp_sock * so )
162+ {
163+ return so -> opt .flags & ISOTP_ALL_BC_FLAGS ;
164+ }
165+
166+ static bool isotp_register_rxid (struct isotp_sock * so )
167+ {
168+ /* no broadcast modes => register rx_id for FC frame reception */
169+ return (isotp_bc_flags (so ) == 0 );
170+ }
171+
172+ static bool isotp_register_txecho (struct isotp_sock * so )
173+ {
174+ /* all modes but SF_BROADCAST register for tx echo skbs */
175+ return (isotp_bc_flags (so ) != CAN_ISOTP_SF_BROADCAST );
176+ }
177+
160178static enum hrtimer_restart isotp_rx_timer_handler (struct hrtimer * hrtimer )
161179{
162180 struct isotp_sock * so = container_of (hrtimer , struct isotp_sock ,
@@ -792,7 +810,6 @@ static void isotp_create_fframe(struct canfd_frame *cf, struct isotp_sock *so,
792810 cf -> data [i ] = so -> tx .buf [so -> tx .idx ++ ];
793811
794812 so -> tx .sn = 1 ;
795- so -> tx .state = ISOTP_WAIT_FIRST_FC ;
796813}
797814
798815static void isotp_rcv_echo (struct sk_buff * skb , void * data )
@@ -925,7 +942,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
925942 off = (so -> tx .ll_dl > CAN_MAX_DLEN ) ? 1 : 0 ;
926943
927944 /* does the given data fit into a single frame for SF_BROADCAST? */
928- if ((so -> opt . flags & CAN_ISOTP_SF_BROADCAST ) &&
945+ if ((isotp_bc_flags ( so ) == CAN_ISOTP_SF_BROADCAST ) &&
929946 (size > so -> tx .ll_dl - SF_PCI_SZ4 - ae - off )) {
930947 err = - EINVAL ;
931948 goto err_out_drop ;
@@ -989,12 +1006,41 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
9891006 /* don't enable wait queue for a single frame transmission */
9901007 wait_tx_done = 0 ;
9911008 } else {
992- /* send first frame and wait for FC */
1009+ /* send first frame */
9931010
9941011 isotp_create_fframe (cf , so , ae );
9951012
996- /* start timeout for FC */
997- hrtimer_sec = 1 ;
1013+ if (isotp_bc_flags (so ) == CAN_ISOTP_CF_BROADCAST ) {
1014+ /* set timer for FC-less operation (STmin = 0) */
1015+ if (so -> opt .flags & CAN_ISOTP_FORCE_TXSTMIN )
1016+ so -> tx_gap = ktime_set (0 , so -> force_tx_stmin );
1017+ else
1018+ so -> tx_gap = ktime_set (0 , so -> frame_txtime );
1019+
1020+ /* disable wait for FCs due to activated block size */
1021+ so -> txfc .bs = 0 ;
1022+
1023+ /* cfecho should have been zero'ed by init */
1024+ if (so -> cfecho )
1025+ pr_notice_once ("can-isotp: no fc cfecho %08X\n" ,
1026+ so -> cfecho );
1027+
1028+ /* set consecutive frame echo tag */
1029+ so -> cfecho = * (u32 * )cf -> data ;
1030+
1031+ /* switch directly to ISOTP_SENDING state */
1032+ so -> tx .state = ISOTP_SENDING ;
1033+
1034+ /* start timeout for unlikely lost echo skb */
1035+ hrtimer_sec = 2 ;
1036+ } else {
1037+ /* standard flow control check */
1038+ so -> tx .state = ISOTP_WAIT_FIRST_FC ;
1039+
1040+ /* start timeout for FC */
1041+ hrtimer_sec = 1 ;
1042+ }
1043+
9981044 hrtimer_start (& so -> txtimer , ktime_set (hrtimer_sec , 0 ),
9991045 HRTIMER_MODE_REL_SOFT );
10001046 }
@@ -1014,6 +1060,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
10141060 if (hrtimer_sec )
10151061 hrtimer_cancel (& so -> txtimer );
10161062
1063+ /* reset consecutive frame echo tag */
1064+ so -> cfecho = 0 ;
1065+
10171066 goto err_out_drop ;
10181067 }
10191068
@@ -1110,15 +1159,17 @@ static int isotp_release(struct socket *sock)
11101159 lock_sock (sk );
11111160
11121161 /* remove current filters & unregister */
1113- if (so -> bound && (!( so -> opt . flags & CAN_ISOTP_SF_BROADCAST ) )) {
1162+ if (so -> bound && isotp_register_txecho ( so )) {
11141163 if (so -> ifindex ) {
11151164 struct net_device * dev ;
11161165
11171166 dev = dev_get_by_index (net , so -> ifindex );
11181167 if (dev ) {
1119- can_rx_unregister (net , dev , so -> rxid ,
1120- SINGLE_MASK (so -> rxid ),
1121- isotp_rcv , sk );
1168+ if (isotp_register_rxid (so ))
1169+ can_rx_unregister (net , dev , so -> rxid ,
1170+ SINGLE_MASK (so -> rxid ),
1171+ isotp_rcv , sk );
1172+
11221173 can_rx_unregister (net , dev , so -> txid ,
11231174 SINGLE_MASK (so -> txid ),
11241175 isotp_rcv_echo , sk );
@@ -1154,7 +1205,6 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
11541205 canid_t tx_id , rx_id ;
11551206 int err = 0 ;
11561207 int notify_enetdown = 0 ;
1157- int do_rx_reg = 1 ;
11581208
11591209 if (len < ISOTP_MIN_NAMELEN )
11601210 return - EINVAL ;
@@ -1187,12 +1237,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
11871237 goto out ;
11881238 }
11891239
1190- /* do not register frame reception for functional addressing */
1191- if (so -> opt .flags & CAN_ISOTP_SF_BROADCAST )
1192- do_rx_reg = 0 ;
1193-
1194- /* do not validate rx address for functional addressing */
1195- if (do_rx_reg && rx_id == tx_id ) {
1240+ /* ensure different CAN IDs when the rx_id is to be registered */
1241+ if (isotp_register_rxid (so ) && rx_id == tx_id ) {
11961242 err = - EADDRNOTAVAIL ;
11971243 goto out ;
11981244 }
@@ -1217,10 +1263,11 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
12171263
12181264 ifindex = dev -> ifindex ;
12191265
1220- if (do_rx_reg ) {
1266+ if (isotp_register_rxid ( so ))
12211267 can_rx_register (net , dev , rx_id , SINGLE_MASK (rx_id ),
12221268 isotp_rcv , sk , "isotp" , sk );
12231269
1270+ if (isotp_register_txecho (so )) {
12241271 /* no consecutive frame echo skb in flight */
12251272 so -> cfecho = 0 ;
12261273
@@ -1289,6 +1336,15 @@ static int isotp_setsockopt_locked(struct socket *sock, int level, int optname,
12891336 if (!(so -> opt .flags & CAN_ISOTP_RX_EXT_ADDR ))
12901337 so -> opt .rx_ext_address = so -> opt .ext_address ;
12911338
1339+ /* these broadcast flags are not allowed together */
1340+ if (isotp_bc_flags (so ) == ISOTP_ALL_BC_FLAGS ) {
1341+ /* CAN_ISOTP_SF_BROADCAST is prioritized */
1342+ so -> opt .flags &= ~CAN_ISOTP_CF_BROADCAST ;
1343+
1344+ /* give user feedback on wrong config attempt */
1345+ ret = - EINVAL ;
1346+ }
1347+
12921348 /* check for frame_txtime changes (0 => no changes) */
12931349 if (so -> opt .frame_txtime ) {
12941350 if (so -> opt .frame_txtime == CAN_ISOTP_FRAME_TXTIME_ZERO )
@@ -1439,10 +1495,12 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
14391495 case NETDEV_UNREGISTER :
14401496 lock_sock (sk );
14411497 /* remove current filters & unregister */
1442- if (so -> bound && (!(so -> opt .flags & CAN_ISOTP_SF_BROADCAST ))) {
1443- can_rx_unregister (dev_net (dev ), dev , so -> rxid ,
1444- SINGLE_MASK (so -> rxid ),
1445- isotp_rcv , sk );
1498+ if (so -> bound && isotp_register_txecho (so )) {
1499+ if (isotp_register_rxid (so ))
1500+ can_rx_unregister (dev_net (dev ), dev , so -> rxid ,
1501+ SINGLE_MASK (so -> rxid ),
1502+ isotp_rcv , sk );
1503+
14461504 can_rx_unregister (dev_net (dev ), dev , so -> txid ,
14471505 SINGLE_MASK (so -> txid ),
14481506 isotp_rcv_echo , sk );
0 commit comments