can: Fix CAN_(EFF|RTR)_FLAG handling in can_filter

Due to a wrong safety check in af_can.c it was not possible to filter
for SFF frames with a specific CAN identifier without getting the
same selected CAN identifier from a received EFF frame also.

This fix has a minimum (but user visible) impact on the CAN filter
API and therefore the CAN version is set to a new date.

Indeed the 'old' API is still working as-is. But when now setting
CAN_(EFF|RTR)_FLAG in can_filter.can_mask you might get less traffic
than before - but still the stuff that you expected to get for your
defined filter ...

Thanks to Kurt Van Dijck for pointing at this issue and for the review.

Signed-off-by: Oliver Hartkopp <oliver@hartkopp.net>
Acked-by: Kurt Van Dijck <kurt.van.dijck@eia.be>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oliver Hartkopp and committed by
David S. Miller
d253eee2 bd7df219

+53 -19
+1 -1
include/linux/can/core.h
··· 19 #include <linux/skbuff.h> 20 #include <linux/netdevice.h> 21 22 - #define CAN_VERSION "20071116" 23 24 /* increment this number each time you change some user-space interface */ 25 #define CAN_ABI_VERSION "8"
··· 19 #include <linux/skbuff.h> 20 #include <linux/netdevice.h> 21 22 + #define CAN_VERSION "20081130" 23 24 /* increment this number each time you change some user-space interface */ 25 #define CAN_ABI_VERSION "8"
+48 -15
net/can/af_can.c
··· 319 return n ? d : NULL; 320 } 321 322 static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, 323 struct dev_rcv_lists *d) 324 { 325 canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */ 326 327 - /* filter error frames */ 328 if (*mask & CAN_ERR_FLAG) { 329 - /* clear CAN_ERR_FLAG in list entry */ 330 *mask &= CAN_ERR_MASK; 331 return &d->rx[RX_ERR]; 332 } 333 334 - /* ensure valid values in can_mask */ 335 - if (*mask & CAN_EFF_FLAG) 336 - *mask &= (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG); 337 - else 338 - *mask &= (CAN_SFF_MASK | CAN_RTR_FLAG); 339 340 /* reduce condition testing at receive time */ 341 *can_id &= *mask; ··· 377 if (!(*mask)) 378 return &d->rx[RX_ALL]; 379 380 - /* use extra filterset for the subscription of exactly *ONE* can_id */ 381 - if (*can_id & CAN_EFF_FLAG) { 382 - if (*mask == (CAN_EFF_MASK | CAN_EFF_FLAG)) { 383 - /* RFC: a use-case for hash-tables in the future? */ 384 - return &d->rx[RX_EFF]; 385 } 386 - } else { 387 - if (*mask == CAN_SFF_MASK) 388 - return &d->rx_sff[*can_id]; 389 } 390 391 /* default: filter via can_id/can_mask */
··· 319 return n ? d : NULL; 320 } 321 322 + /** 323 + * find_rcv_list - determine optimal filterlist inside device filter struct 324 + * @can_id: pointer to CAN identifier of a given can_filter 325 + * @mask: pointer to CAN mask of a given can_filter 326 + * @d: pointer to the device filter struct 327 + * 328 + * Description: 329 + * Returns the optimal filterlist to reduce the filter handling in the 330 + * receive path. This function is called by service functions that need 331 + * to register or unregister a can_filter in the filter lists. 332 + * 333 + * A filter matches in general, when 334 + * 335 + * <received_can_id> & mask == can_id & mask 336 + * 337 + * so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe 338 + * relevant bits for the filter. 339 + * 340 + * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can 341 + * filter for error frames (CAN_ERR_FLAG bit set in mask). For error frames 342 + * there is a special filterlist and a special rx path filter handling. 343 + * 344 + * Return: 345 + * Pointer to optimal filterlist for the given can_id/mask pair. 346 + * Constistency checked mask. 347 + * Reduced can_id to have a preprocessed filter compare value. 348 + */ 349 static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, 350 struct dev_rcv_lists *d) 351 { 352 canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */ 353 354 + /* filter for error frames in extra filterlist */ 355 if (*mask & CAN_ERR_FLAG) { 356 + /* clear CAN_ERR_FLAG in filter entry */ 357 *mask &= CAN_ERR_MASK; 358 return &d->rx[RX_ERR]; 359 } 360 361 + /* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */ 362 + 363 + #define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG) 364 + 365 + /* ensure valid values in can_mask for 'SFF only' frame filtering */ 366 + if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG)) 367 + *mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS); 368 369 /* reduce condition testing at receive time */ 370 *can_id &= *mask; ··· 348 if (!(*mask)) 349 return &d->rx[RX_ALL]; 350 351 + /* extra filterlists for the subscription of a single non-RTR can_id */ 352 + if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) 353 + && !(*can_id & CAN_RTR_FLAG)) { 354 + 355 + if (*can_id & CAN_EFF_FLAG) { 356 + if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) { 357 + /* RFC: a future use-case for hash-tables? */ 358 + return &d->rx[RX_EFF]; 359 + } 360 + } else { 361 + if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS)) 362 + return &d->rx_sff[*can_id]; 363 } 364 } 365 366 /* default: filter via can_id/can_mask */
+4 -3
net/can/bcm.c
··· 64 #define BCM_CAN_DLC_MASK 0x0F /* clean private flags in can_dlc by masking */ 65 66 /* get best masking value for can_rx_register() for a given single can_id */ 67 - #define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \ 68 - (CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK)) 69 70 - #define CAN_BCM_VERSION "20080415" 71 static __initdata const char banner[] = KERN_INFO 72 "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n"; 73
··· 64 #define BCM_CAN_DLC_MASK 0x0F /* clean private flags in can_dlc by masking */ 65 66 /* get best masking value for can_rx_register() for a given single can_id */ 67 + #define REGMASK(id) ((id & CAN_EFF_FLAG) ? \ 68 + (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \ 69 + (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG)) 70 71 + #define CAN_BCM_VERSION CAN_VERSION 72 static __initdata const char banner[] = KERN_INFO 73 "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n"; 74