2019-07-23 16:17:55 +03:00
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2019-07-24 15:16:29 +03:00
/* af_can.c - Protocol family CAN core module
2007-11-17 02:52:17 +03:00
* ( used by different CAN protocol modules )
*
2017-04-25 09:19:41 +03:00
* Copyright ( c ) 2002 - 2017 Volkswagen Group Electronic Research
2007-11-17 02:52:17 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the name of Volkswagen nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* Alternatively , provided that this notice is retained in full , this
* software may be distributed under the terms of the GNU General
* Public License ( " GPL " ) version 2 , in which case the provisions of the
* GPL apply INSTEAD OF those given above .
*
* The provided data structures and external interfaces from this code
* are not restricted to be used by modules with a GPL compatible license .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE .
*
*/
# include <linux/module.h>
2012-06-13 22:04:33 +04:00
# include <linux/stddef.h>
2007-11-17 02:52:17 +03:00
# include <linux/init.h>
# include <linux/kmod.h>
# include <linux/slab.h>
# include <linux/list.h>
# include <linux/spinlock.h>
# include <linux/rcupdate.h>
# include <linux/uaccess.h>
# include <linux/net.h>
# include <linux/netdevice.h>
# include <linux/socket.h>
# include <linux/if_ether.h>
# include <linux/if_arp.h>
# include <linux/skbuff.h>
# include <linux/can.h>
# include <linux/can/core.h>
2014-01-30 13:11:28 +04:00
# include <linux/can/skb.h>
2018-10-08 10:02:38 +03:00
# include <linux/can/can-ml.h>
2011-06-16 06:08:01 +04:00
# include <linux/ratelimit.h>
2007-11-17 02:52:17 +03:00
# include <net/net_namespace.h>
# include <net/sock.h>
# include "af_can.h"
MODULE_DESCRIPTION ( " Controller Area Network PF_CAN core " ) ;
MODULE_LICENSE ( " Dual BSD/GPL " ) ;
MODULE_AUTHOR ( " Urs Thuermann <urs.thuermann@volkswagen.de>, "
" Oliver Hartkopp <oliver.hartkopp@volkswagen.de> " ) ;
MODULE_ALIAS_NETPROTO ( PF_CAN ) ;
static int stats_timer __read_mostly = 1 ;
2018-03-24 01:54:38 +03:00
module_param ( stats_timer , int , 0444 ) ;
2007-11-17 02:52:17 +03:00
MODULE_PARM_DESC ( stats_timer , " enable timer for statistics (default:on) " ) ;
static struct kmem_cache * rcv_cache __read_mostly ;
/* table of registered CAN protocols */
2017-10-17 08:18:35 +03:00
static const struct can_proto __rcu * proto_tab [ CAN_NPROTO ] __read_mostly ;
2011-04-05 12:01:16 +04:00
static DEFINE_MUTEX ( proto_tab_lock ) ;
2007-11-17 02:52:17 +03:00
2015-06-26 12:58:19 +03:00
static atomic_t skbcounter = ATOMIC_INIT ( 0 ) ;
2019-07-24 15:16:29 +03:00
/* af_can socket functions */
2007-11-17 02:52:17 +03:00
2019-11-07 13:55:42 +03:00
void can_sock_destruct ( struct sock * sk )
2007-11-17 02:52:17 +03:00
{
skb_queue_purge ( & sk - > sk_receive_queue ) ;
2019-06-07 23:46:07 +03:00
skb_queue_purge ( & sk - > sk_error_queue ) ;
2007-11-17 02:52:17 +03:00
}
2019-11-07 13:55:42 +03:00
EXPORT_SYMBOL ( can_sock_destruct ) ;
2007-11-17 02:52:17 +03:00
2011-05-03 22:42:04 +04:00
static const struct can_proto * can_get_proto ( int protocol )
2011-04-05 12:01:16 +04:00
{
2011-05-03 22:40:57 +04:00
const struct can_proto * cp ;
2011-04-05 12:01:16 +04:00
rcu_read_lock ( ) ;
cp = rcu_dereference ( proto_tab [ protocol ] ) ;
if ( cp & & ! try_module_get ( cp - > prot - > owner ) )
cp = NULL ;
rcu_read_unlock ( ) ;
return cp ;
}
2011-05-03 22:42:04 +04:00
static inline void can_put_proto ( const struct can_proto * cp )
{
module_put ( cp - > prot - > owner ) ;
}
2009-11-06 09:18:14 +03:00
static int can_create ( struct net * net , struct socket * sock , int protocol ,
int kern )
2007-11-17 02:52:17 +03:00
{
struct sock * sk ;
2011-05-03 22:40:57 +04:00
const struct can_proto * cp ;
2007-11-17 02:52:17 +03:00
int err = 0 ;
sock - > state = SS_UNCONNECTED ;
if ( protocol < 0 | | protocol > = CAN_NPROTO )
return - EINVAL ;
2011-05-03 22:42:04 +04:00
cp = can_get_proto ( protocol ) ;
2011-04-05 12:01:16 +04:00
2008-10-17 02:24:51 +04:00
# ifdef CONFIG_MODULES
2011-04-05 12:01:16 +04:00
if ( ! cp ) {
/* try to load protocol module if kernel is modular */
2008-02-08 05:04:21 +03:00
err = request_module ( " can-proto-%d " , protocol ) ;
2007-11-17 02:52:17 +03:00
2019-07-24 15:16:29 +03:00
/* In case of error we only print a message but don't
2007-11-17 02:52:17 +03:00
* return the error code immediately . Below we will
* return - EPROTONOSUPPORT
*/
2011-06-16 06:08:01 +04:00
if ( err )
2019-08-13 10:29:10 +03:00
pr_err_ratelimited ( " can: request_module (can-proto-%d) failed. \n " ,
protocol ) ;
2011-04-05 12:01:16 +04:00
2011-05-03 22:42:04 +04:00
cp = can_get_proto ( protocol ) ;
2007-11-17 02:52:17 +03:00
}
2008-02-08 05:04:21 +03:00
# endif
2007-11-17 02:52:17 +03:00
/* check for available protocol and correct usage */
if ( ! cp )
return - EPROTONOSUPPORT ;
if ( cp - > type ! = sock - > type ) {
2011-04-05 12:01:16 +04:00
err = - EPROTOTYPE ;
2007-11-17 02:52:17 +03:00
goto errout ;
}
sock - > ops = cp - > ops ;
2015-05-09 05:09:13 +03:00
sk = sk_alloc ( net , PF_CAN , GFP_KERNEL , cp - > prot , kern ) ;
2007-11-17 02:52:17 +03:00
if ( ! sk ) {
err = - ENOMEM ;
goto errout ;
}
sock_init_data ( sock , sk ) ;
sk - > sk_destruct = can_sock_destruct ;
if ( sk - > sk_prot - > init )
err = sk - > sk_prot - > init ( sk ) ;
if ( err ) {
/* release sk on errors */
sock_orphan ( sk ) ;
sock_put ( sk ) ;
}
errout :
2011-05-03 22:42:04 +04:00
can_put_proto ( cp ) ;
2007-11-17 02:52:17 +03:00
return err ;
}
2019-07-24 15:16:29 +03:00
/* af_can tx path */
2007-11-17 02:52:17 +03:00
/**
* can_send - transmit a CAN frame ( optional with local loopback )
* @ skb : pointer to socket buffer with CAN frame in data section
* @ loop : loopback for listeners on local CAN sockets ( recommended default ! )
*
2009-09-15 12:31:34 +04:00
* Due to the loopback this routine must not be called from hardirq context .
*
2007-11-17 02:52:17 +03:00
* Return :
* 0 on success
* - ENETDOWN when the selected interface is down
* - ENOBUFS on full driver queue ( see net_xmit_errno ( ) )
* - ENOMEM when local loopback failed at calling skb_clone ( )
* - EPERM when trying to send on a non - CAN interface
2012-06-13 22:33:02 +04:00
* - EMSGSIZE CAN frame size is bigger than CAN interface MTU
2008-07-06 10:38:43 +04:00
* - EINVAL when the skb - > data does not contain a valid CAN frame
2007-11-17 02:52:17 +03:00
*/
int can_send ( struct sk_buff * skb , int loop )
{
2008-05-08 13:49:55 +04:00
struct sk_buff * newskb = NULL ;
2018-10-08 10:02:28 +03:00
struct can_pkg_stats * pkg_stats = dev_net ( skb - > dev ) - > can . pkg_stats ;
2012-06-13 22:33:02 +04:00
int err = - EINVAL ;
2022-09-12 20:07:23 +03:00
if ( can_is_canxl_skb ( skb ) ) {
skb - > protocol = htons ( ETH_P_CANXL ) ;
} else if ( can_is_can_skb ( skb ) ) {
2012-06-13 22:33:02 +04:00
skb - > protocol = htons ( ETH_P_CAN ) ;
2022-09-12 20:07:19 +03:00
} else if ( can_is_canfd_skb ( skb ) ) {
2022-09-12 20:07:21 +03:00
struct canfd_frame * cfd = ( struct canfd_frame * ) skb - > data ;
2012-06-13 22:33:02 +04:00
skb - > protocol = htons ( ETH_P_CANFD ) ;
2022-09-12 20:07:21 +03:00
/* set CAN FD flag for CAN FD frames by default */
cfd - > flags | = CANFD_FDF ;
2019-08-13 10:03:55 +03:00
} else {
2012-06-13 22:33:02 +04:00
goto inval_skb ;
2019-08-13 10:03:55 +03:00
}
2007-11-17 02:52:17 +03:00
2022-09-12 20:07:19 +03:00
/* Make sure the CAN frame can pass the selected CAN netdevice. */
if ( unlikely ( skb - > len > skb - > dev - > mtu ) ) {
2012-06-13 22:33:02 +04:00
err = - EMSGSIZE ;
goto inval_skb ;
2008-07-06 10:38:43 +04:00
}
2012-06-13 22:33:02 +04:00
if ( unlikely ( skb - > dev - > type ! = ARPHRD_CAN ) ) {
err = - EPERM ;
goto inval_skb ;
2007-11-17 02:52:17 +03:00
}
2012-06-13 22:33:02 +04:00
if ( unlikely ( ! ( skb - > dev - > flags & IFF_UP ) ) ) {
err = - ENETDOWN ;
goto inval_skb ;
2007-11-17 02:52:17 +03:00
}
2015-02-23 22:37:54 +03:00
skb - > ip_summed = CHECKSUM_UNNECESSARY ;
skb_reset_mac_header ( skb ) ;
2007-11-17 02:52:17 +03:00
skb_reset_network_header ( skb ) ;
skb_reset_transport_header ( skb ) ;
if ( loop ) {
/* local loopback of sent CAN frames */
/* indication for the CAN driver: do loopback */
skb - > pkt_type = PACKET_LOOPBACK ;
2019-07-24 15:16:29 +03:00
/* The reference to the originating sock may be required
2007-11-17 02:52:17 +03:00
* by the receiving socket to check whether the frame is
* its own . Example : can_raw sockopt CAN_RAW_RECV_OWN_MSGS
* Therefore we have to ensure that skb - > sk remains the
* reference to the originating sock by restoring skb - > sk
* after each skb_clone ( ) or skb_orphan ( ) usage .
*/
if ( ! ( skb - > dev - > flags & IFF_ECHO ) ) {
2019-07-24 15:16:29 +03:00
/* If the interface is not capable to do loopback
2007-11-17 02:52:17 +03:00
* itself , we do it here .
*/
2008-05-08 13:49:55 +04:00
newskb = skb_clone ( skb , GFP_ATOMIC ) ;
2007-11-17 02:52:17 +03:00
if ( ! newskb ) {
kfree_skb ( skb ) ;
return - ENOMEM ;
}
2014-01-30 13:11:28 +04:00
can_skb_set_owner ( newskb , skb - > sk ) ;
2007-11-17 02:52:17 +03:00
newskb - > ip_summed = CHECKSUM_UNNECESSARY ;
newskb - > pkt_type = PACKET_BROADCAST ;
}
} else {
/* indication for the CAN driver: no loopback required */
skb - > pkt_type = PACKET_HOST ;
}
/* send to netdevice */
err = dev_queue_xmit ( skb ) ;
if ( err > 0 )
err = net_xmit_errno ( err ) ;
2008-05-08 13:49:55 +04:00
if ( err ) {
2009-02-25 03:35:44 +03:00
kfree_skb ( newskb ) ;
2008-05-08 13:49:55 +04:00
return err ;
}
2015-06-26 12:58:19 +03:00
if ( newskb )
2022-03-06 01:12:46 +03:00
netif_rx ( newskb ) ;
2008-05-08 13:49:55 +04:00
2007-11-17 02:52:17 +03:00
/* update statistics */
2018-10-08 10:02:28 +03:00
pkg_stats - > tx_frames + + ;
pkg_stats - > tx_frames_delta + + ;
2007-11-17 02:52:17 +03:00
2008-05-08 13:49:55 +04:00
return 0 ;
2012-06-13 22:33:02 +04:00
inval_skb :
kfree_skb ( skb ) ;
return err ;
2007-11-17 02:52:17 +03:00
}
EXPORT_SYMBOL ( can_send ) ;
2019-07-24 15:16:29 +03:00
/* af_can rx path */
2007-11-17 02:52:17 +03:00
2018-10-08 10:02:34 +03:00
static struct can_dev_rcv_lists * can_dev_rcv_lists_find ( struct net * net ,
struct net_device * dev )
2007-11-17 02:52:17 +03:00
{
2018-10-08 10:02:39 +03:00
if ( dev ) {
2021-02-23 10:01:26 +03:00
struct can_ml_priv * can_ml = can_get_ml_priv ( dev ) ;
return & can_ml - > dev_rcv_lists ;
2018-10-08 10:02:39 +03:00
} else {
2018-10-08 10:02:30 +03:00
return net - > can . rx_alldev_list ;
2018-10-08 10:02:39 +03:00
}
2007-11-17 02:52:17 +03:00
}
2014-04-02 22:25:26 +04:00
/**
* effhash - hash function for 29 bit CAN identifier reduction
* @ can_id : 29 bit CAN identifier
*
* Description :
* To reduce the linear traversal in one linked list of _single_ EFF CAN
* frame subscriptions the 29 bit identifier is mapped to 10 bits .
* ( see CAN_EFF_RCV_HASH_BITS definition )
*
* Return :
* Hash value from 0x000 - 0x3FF ( enforced by CAN_EFF_RCV_HASH_BITS mask )
*/
static unsigned int effhash ( canid_t can_id )
{
unsigned int hash ;
hash = can_id ;
hash ^ = can_id > > CAN_EFF_RCV_HASH_BITS ;
hash ^ = can_id > > ( 2 * CAN_EFF_RCV_HASH_BITS ) ;
return hash & ( ( 1 < < CAN_EFF_RCV_HASH_BITS ) - 1 ) ;
}
2008-12-04 02:52:35 +03:00
/**
2018-10-08 10:02:33 +03:00
* can_rcv_list_find - determine optimal filterlist inside device filter struct
2008-12-04 02:52:35 +03:00
* @ can_id : pointer to CAN identifier of a given can_filter
* @ mask : pointer to CAN mask of a given can_filter
2020-10-04 15:09:48 +03:00
* @ dev_rcv_lists : pointer to the device filter struct
2008-12-04 02:52:35 +03:00
*
* Description :
* Returns the optimal filterlist to reduce the filter handling in the
* receive path . This function is called by service functions that need
* to register or unregister a can_filter in the filter lists .
*
* A filter matches in general , when
*
* < received_can_id > & mask = = can_id & mask
*
* so every bit set in the mask ( even CAN_EFF_FLAG , CAN_RTR_FLAG ) describe
* relevant bits for the filter .
*
* The filter can be inverted ( CAN_INV_FILTER bit set in can_id ) or it can
2012-05-09 00:20:33 +04:00
* filter for error messages ( CAN_ERR_FLAG bit set in mask ) . For error msg
* frames there is a special filterlist and a special rx path filter handling .
2008-12-04 02:52:35 +03:00
*
* Return :
* Pointer to optimal filterlist for the given can_id / mask pair .
2020-09-16 01:34:54 +03:00
* Consistency checked mask .
2008-12-04 02:52:35 +03:00
* Reduced can_id to have a preprocessed filter compare value .
*/
2018-10-08 10:02:33 +03:00
static struct hlist_head * can_rcv_list_find ( canid_t * can_id , canid_t * mask ,
struct can_dev_rcv_lists * dev_rcv_lists )
2007-11-17 02:52:17 +03:00
{
canid_t inv = * can_id & CAN_INV_FILTER ; /* save flag before masking */
2012-05-09 00:20:33 +04:00
/* filter for error message frames in extra filterlist */
2007-11-17 02:52:17 +03:00
if ( * mask & CAN_ERR_FLAG ) {
2008-12-04 02:52:35 +03:00
/* clear CAN_ERR_FLAG in filter entry */
2007-11-17 02:52:17 +03:00
* mask & = CAN_ERR_MASK ;
2018-10-08 10:02:31 +03:00
return & dev_rcv_lists - > rx [ RX_ERR ] ;
2007-11-17 02:52:17 +03:00
}
2008-12-04 02:52:35 +03:00
/* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */
# define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG)
/* ensure valid values in can_mask for 'SFF only' frame filtering */
if ( ( * mask & CAN_EFF_FLAG ) & & ! ( * can_id & CAN_EFF_FLAG ) )
* mask & = ( CAN_SFF_MASK | CAN_EFF_RTR_FLAGS ) ;
2007-11-17 02:52:17 +03:00
/* reduce condition testing at receive time */
* can_id & = * mask ;
/* inverse can_id/can_mask filter */
if ( inv )
2018-10-08 10:02:31 +03:00
return & dev_rcv_lists - > rx [ RX_INV ] ;
2007-11-17 02:52:17 +03:00
/* mask == 0 => no condition testing at receive time */
if ( ! ( * mask ) )
2018-10-08 10:02:31 +03:00
return & dev_rcv_lists - > rx [ RX_ALL ] ;
2007-11-17 02:52:17 +03:00
2008-12-04 02:52:35 +03:00
/* extra filterlists for the subscription of a single non-RTR can_id */
2009-11-30 03:55:45 +03:00
if ( ( ( * mask & CAN_EFF_RTR_FLAGS ) = = CAN_EFF_RTR_FLAGS ) & &
! ( * can_id & CAN_RTR_FLAG ) ) {
2008-12-04 02:52:35 +03:00
if ( * can_id & CAN_EFF_FLAG ) {
2014-04-02 22:25:26 +04:00
if ( * mask = = ( CAN_EFF_MASK | CAN_EFF_RTR_FLAGS ) )
2018-10-08 10:02:31 +03:00
return & dev_rcv_lists - > rx_eff [ effhash ( * can_id ) ] ;
2008-12-04 02:52:35 +03:00
} else {
if ( * mask = = ( CAN_SFF_MASK | CAN_EFF_RTR_FLAGS ) )
2018-10-08 10:02:31 +03:00
return & dev_rcv_lists - > rx_sff [ * can_id ] ;
2007-11-17 02:52:17 +03:00
}
}
/* default: filter via can_id/can_mask */
2018-10-08 10:02:31 +03:00
return & dev_rcv_lists - > rx [ RX_FIL ] ;
2007-11-17 02:52:17 +03:00
}
/**
* can_rx_register - subscribe CAN frames from a specific interface
2020-07-13 02:14:58 +03:00
* @ net : the applicable net namespace
2020-09-16 01:34:54 +03:00
* @ dev : pointer to netdevice ( NULL = > subscribe from ' all ' CAN devices list )
2007-11-17 02:52:17 +03:00
* @ can_id : CAN identifier ( see description )
* @ mask : CAN mask ( see description )
* @ func : callback function on filter match
* @ data : returned parameter for callback function
2013-10-12 03:29:46 +04:00
* @ ident : string for calling module identification
2017-01-27 19:11:44 +03:00
* @ sk : socket pointer ( might be NULL )
2007-11-17 02:52:17 +03:00
*
* Description :
* Invokes the callback function with the received sk_buff and the given
* parameter ' data ' on a matching receive filter . A filter matches , when
*
* < received_can_id > & mask = = can_id & mask
*
* The filter can be inverted ( CAN_INV_FILTER bit set in can_id ) or it can
2012-05-09 00:20:33 +04:00
* filter for error message frames ( CAN_ERR_FLAG bit set in mask ) .
2007-11-17 02:52:17 +03:00
*
2009-01-06 22:07:54 +03:00
* The provided pointer to the sk_buff is guaranteed to be valid as long as
* the callback function is running . The callback function must * not * free
* the given sk_buff while processing it ' s task . When the given sk_buff is
* needed after the end of the callback function it must be cloned inside
* the callback function with skb_clone ( ) .
*
2007-11-17 02:52:17 +03:00
* Return :
* 0 on success
* - ENOMEM on missing cache mem to create subscription entry
* - ENODEV unknown device
*/
2017-02-21 14:19:47 +03:00
int can_rx_register ( struct net * net , struct net_device * dev , canid_t can_id ,
canid_t mask , void ( * func ) ( struct sk_buff * , void * ) ,
void * data , char * ident , struct sock * sk )
2007-11-17 02:52:17 +03:00
{
2018-10-08 10:02:35 +03:00
struct receiver * rcv ;
struct hlist_head * rcv_list ;
2018-10-08 10:02:31 +03:00
struct can_dev_rcv_lists * dev_rcv_lists ;
2018-10-08 10:02:28 +03:00
struct can_rcv_lists_stats * rcv_lists_stats = net - > can . rcv_lists_stats ;
2007-11-17 02:52:17 +03:00
/* insert new receiver (dev,canid,mask) -> (func,data) */
can: af_can: fix NULL pointer dereference in can_rx_register()
It causes NULL pointer dereference when testing as following:
(a) use syscall(__NR_socket, 0x10ul, 3ul, 0) to create netlink socket.
(b) use syscall(__NR_sendmsg, ...) to create bond link device and vxcan
link device, and bind vxcan device to bond device (can also use
ifenslave command to bind vxcan device to bond device).
(c) use syscall(__NR_socket, 0x1dul, 3ul, 1) to create CAN socket.
(d) use syscall(__NR_bind, ...) to bind the bond device to CAN socket.
The bond device invokes the can-raw protocol registration interface to
receive CAN packets. However, ml_priv is not allocated to the dev,
dev_rcv_lists is assigned to NULL in can_rx_register(). In this case,
it will occur the NULL pointer dereference issue.
The following is the stack information:
BUG: kernel NULL pointer dereference, address: 0000000000000008
PGD 122a4067 P4D 122a4067 PUD 1223c067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
RIP: 0010:can_rx_register+0x12d/0x1e0
Call Trace:
<TASK>
raw_enable_filters+0x8d/0x120
raw_enable_allfilters+0x3b/0x130
raw_bind+0x118/0x4f0
__sys_bind+0x163/0x1a0
__x64_sys_bind+0x1e/0x30
do_syscall_64+0x35/0x80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
</TASK>
Fixes: 4e096a18867a ("net: introduce CAN specific pointer in the struct net_device")
Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
Reviewed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Link: https://lore.kernel.org/all/20221028085650.170470-1-shaozhengchao@huawei.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-10-28 11:56:50 +03:00
if ( dev & & ( dev - > type ! = ARPHRD_CAN | | ! can_get_ml_priv ( dev ) ) )
2010-02-02 18:21:34 +03:00
return - ENODEV ;
2017-02-21 14:19:47 +03:00
if ( dev & & ! net_eq ( net , dev_net ( dev ) ) )
return - ENODEV ;
2018-10-08 10:02:35 +03:00
rcv = kmem_cache_alloc ( rcv_cache , GFP_KERNEL ) ;
if ( ! rcv )
2007-11-17 02:52:17 +03:00
return - ENOMEM ;
2018-10-30 11:00:34 +03:00
spin_lock_bh ( & net - > can . rcvlists_lock ) ;
2007-11-17 02:52:17 +03:00
2018-10-08 10:02:34 +03:00
dev_rcv_lists = can_dev_rcv_lists_find ( net , dev ) ;
2018-10-08 10:02:40 +03:00
rcv_list = can_rcv_list_find ( & can_id , & mask , dev_rcv_lists ) ;
rcv - > can_id = can_id ;
rcv - > mask = mask ;
rcv - > matches = 0 ;
rcv - > func = func ;
rcv - > data = data ;
rcv - > ident = ident ;
rcv - > sk = sk ;
2007-11-17 02:52:17 +03:00
2018-10-08 10:02:40 +03:00
hlist_add_head_rcu ( & rcv - > list , rcv_list ) ;
dev_rcv_lists - > entries + + ;
rcv_lists_stats - > rcv_entries + + ;
rcv_lists_stats - > rcv_entries_max = max ( rcv_lists_stats - > rcv_entries_max ,
rcv_lists_stats - > rcv_entries ) ;
2018-10-30 11:00:34 +03:00
spin_unlock_bh ( & net - > can . rcvlists_lock ) ;
2007-11-17 02:52:17 +03:00
2022-12-08 12:09:40 +03:00
return 0 ;
2007-11-17 02:52:17 +03:00
}
EXPORT_SYMBOL ( can_rx_register ) ;
2019-07-24 15:16:29 +03:00
/* can_rx_delete_receiver - rcu callback for single receiver entry removal */
2007-11-17 02:52:17 +03:00
static void can_rx_delete_receiver ( struct rcu_head * rp )
{
2018-10-08 10:02:35 +03:00
struct receiver * rcv = container_of ( rp , struct receiver , rcu ) ;
struct sock * sk = rcv - > sk ;
2007-11-17 02:52:17 +03:00
2018-10-08 10:02:35 +03:00
kmem_cache_free ( rcv_cache , rcv ) ;
2017-01-27 19:11:44 +03:00
if ( sk )
sock_put ( sk ) ;
2007-11-17 02:52:17 +03:00
}
/**
* can_rx_unregister - unsubscribe CAN frames from a specific interface
2020-07-13 02:14:58 +03:00
* @ net : the applicable net namespace
2014-12-05 20:54:38 +03:00
* @ dev : pointer to netdevice ( NULL = > unsubscribe from ' all ' CAN devices list )
2007-11-17 02:52:17 +03:00
* @ can_id : CAN identifier
* @ mask : CAN mask
* @ func : callback function on filter match
* @ data : returned parameter for callback function
*
* Description :
* Removes subscription entry depending on given ( subscription ) values .
*/
2017-02-21 14:19:47 +03:00
void can_rx_unregister ( struct net * net , struct net_device * dev , canid_t can_id ,
canid_t mask , void ( * func ) ( struct sk_buff * , void * ) ,
void * data )
2007-11-17 02:52:17 +03:00
{
2018-10-08 10:02:35 +03:00
struct receiver * rcv = NULL ;
struct hlist_head * rcv_list ;
2018-10-08 10:02:28 +03:00
struct can_rcv_lists_stats * rcv_lists_stats = net - > can . rcv_lists_stats ;
2018-10-08 10:02:31 +03:00
struct can_dev_rcv_lists * dev_rcv_lists ;
2007-11-17 02:52:17 +03:00
2010-02-02 18:21:34 +03:00
if ( dev & & dev - > type ! = ARPHRD_CAN )
return ;
2017-02-21 14:19:47 +03:00
if ( dev & & ! net_eq ( net , dev_net ( dev ) ) )
return ;
2007-11-17 02:52:17 +03:00
2018-10-30 11:00:34 +03:00
spin_lock_bh ( & net - > can . rcvlists_lock ) ;
2017-02-21 14:19:47 +03:00
2018-10-08 10:02:34 +03:00
dev_rcv_lists = can_dev_rcv_lists_find ( net , dev ) ;
2018-10-08 10:02:35 +03:00
rcv_list = can_rcv_list_find ( & can_id , & mask , dev_rcv_lists ) ;
2007-11-17 02:52:17 +03:00
2019-07-24 15:16:29 +03:00
/* Search the receiver list for the item to delete. This should
2007-11-17 02:52:17 +03:00
* exist , since no receiver may be unregistered that hasn ' t
* been registered before .
*/
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , rcv_list , list ) {
if ( rcv - > can_id = = can_id & & rcv - > mask = = mask & &
rcv - > func = = func & & rcv - > data = = data )
2007-11-17 02:52:17 +03:00
break ;
}
2019-07-24 15:16:29 +03:00
/* Check for bugs in CAN protocol implementations using af_can.c:
2018-10-08 10:02:35 +03:00
* ' rcv ' will be NULL if no matching list item was found for removal .
2020-11-26 22:21:40 +03:00
* As this case may potentially happen when closing a socket while
* the notifier for removing the CAN netdev is running we just print
* a warning here .
2007-11-17 02:52:17 +03:00
*/
2018-10-08 10:02:35 +03:00
if ( ! rcv ) {
2020-11-26 22:21:40 +03:00
pr_warn ( " can: receive list entry not found for dev %s, id %03X, mask %03X \n " ,
DNAME ( dev ) , can_id , mask ) ;
2007-11-17 02:52:17 +03:00
goto out ;
}
2018-10-08 10:02:35 +03:00
hlist_del_rcu ( & rcv - > list ) ;
2018-10-08 10:02:31 +03:00
dev_rcv_lists - > entries - - ;
2007-11-17 02:52:17 +03:00
2018-10-08 10:02:28 +03:00
if ( rcv_lists_stats - > rcv_entries > 0 )
rcv_lists_stats - > rcv_entries - - ;
2007-11-17 02:52:17 +03:00
out :
2018-10-30 11:00:34 +03:00
spin_unlock_bh ( & net - > can . rcvlists_lock ) ;
2007-11-17 02:52:17 +03:00
/* schedule the receiver item for deletion */
2018-10-08 10:02:35 +03:00
if ( rcv ) {
if ( rcv - > sk )
sock_hold ( rcv - > sk ) ;
call_rcu ( & rcv - > rcu , can_rx_delete_receiver ) ;
2017-01-27 19:11:44 +03:00
}
2007-11-17 02:52:17 +03:00
}
EXPORT_SYMBOL ( can_rx_unregister ) ;
2018-10-08 10:02:35 +03:00
static inline void deliver ( struct sk_buff * skb , struct receiver * rcv )
2007-11-17 02:52:17 +03:00
{
2018-10-08 10:02:35 +03:00
rcv - > func ( skb , rcv - > data ) ;
rcv - > matches + + ;
2007-11-17 02:52:17 +03:00
}
2018-10-08 10:02:31 +03:00
static int can_rcv_filter ( struct can_dev_rcv_lists * dev_rcv_lists , struct sk_buff * skb )
2007-11-17 02:52:17 +03:00
{
2018-10-08 10:02:35 +03:00
struct receiver * rcv ;
2007-11-17 02:52:17 +03:00
int matches = 0 ;
struct can_frame * cf = ( struct can_frame * ) skb - > data ;
canid_t can_id = cf - > can_id ;
2018-10-08 10:02:31 +03:00
if ( dev_rcv_lists - > entries = = 0 )
2007-11-17 02:52:17 +03:00
return 0 ;
if ( can_id & CAN_ERR_FLAG ) {
2012-05-09 00:20:33 +04:00
/* check for error message frame entries only */
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , & dev_rcv_lists - > rx [ RX_ERR ] , list ) {
if ( can_id & rcv - > mask ) {
deliver ( skb , rcv ) ;
2007-11-17 02:52:17 +03:00
matches + + ;
}
}
return matches ;
}
/* check for unfiltered entries */
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , & dev_rcv_lists - > rx [ RX_ALL ] , list ) {
deliver ( skb , rcv ) ;
2007-11-17 02:52:17 +03:00
matches + + ;
}
/* check for can_id/mask entries */
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , & dev_rcv_lists - > rx [ RX_FIL ] , list ) {
if ( ( can_id & rcv - > mask ) = = rcv - > can_id ) {
deliver ( skb , rcv ) ;
2007-11-17 02:52:17 +03:00
matches + + ;
}
}
/* check for inverted can_id/mask entries */
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , & dev_rcv_lists - > rx [ RX_INV ] , list ) {
if ( ( can_id & rcv - > mask ) ! = rcv - > can_id ) {
deliver ( skb , rcv ) ;
2007-11-17 02:52:17 +03:00
matches + + ;
}
}
2008-12-05 02:01:08 +03:00
/* check filterlists for single non-RTR can_ids */
if ( can_id & CAN_RTR_FLAG )
return matches ;
2007-11-17 02:52:17 +03:00
if ( can_id & CAN_EFF_FLAG ) {
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , & dev_rcv_lists - > rx_eff [ effhash ( can_id ) ] , list ) {
if ( rcv - > can_id = = can_id ) {
deliver ( skb , rcv ) ;
2007-11-17 02:52:17 +03:00
matches + + ;
}
}
} else {
can_id & = CAN_SFF_MASK ;
2018-10-08 10:02:35 +03:00
hlist_for_each_entry_rcu ( rcv , & dev_rcv_lists - > rx_sff [ can_id ] , list ) {
deliver ( skb , rcv ) ;
2007-11-17 02:52:17 +03:00
matches + + ;
}
}
return matches ;
}
2012-06-13 22:33:02 +04:00
static void can_receive ( struct sk_buff * skb , struct net_device * dev )
2007-11-17 02:52:17 +03:00
{
2018-10-08 10:02:31 +03:00
struct can_dev_rcv_lists * dev_rcv_lists ;
2017-04-25 09:19:41 +03:00
struct net * net = dev_net ( dev ) ;
2018-10-08 10:02:28 +03:00
struct can_pkg_stats * pkg_stats = net - > can . pkg_stats ;
2007-11-17 02:52:17 +03:00
int matches ;
/* update statistics */
2018-10-08 10:02:28 +03:00
pkg_stats - > rx_frames + + ;
pkg_stats - > rx_frames_delta + + ;
2007-11-17 02:52:17 +03:00
2015-06-26 12:58:19 +03:00
/* create non-zero unique skb identifier together with *skb */
while ( ! ( can_skb_prv ( skb ) - > skbcnt ) )
can_skb_prv ( skb ) - > skbcnt = atomic_inc_return ( & skbcounter ) ;
2007-11-17 02:52:17 +03:00
rcu_read_lock ( ) ;
/* deliver the packet to sockets listening on all devices */
2018-10-08 10:02:30 +03:00
matches = can_rcv_filter ( net - > can . rx_alldev_list , skb ) ;
2007-11-17 02:52:17 +03:00
/* find receive list for this device */
2018-10-08 10:02:34 +03:00
dev_rcv_lists = can_dev_rcv_lists_find ( net , dev ) ;
2018-10-08 10:02:40 +03:00
matches + = can_rcv_filter ( dev_rcv_lists , skb ) ;
2007-11-17 02:52:17 +03:00
rcu_read_unlock ( ) ;
2009-04-17 12:38:46 +04:00
/* consume the skbuff allocated by the netdevice driver */
consume_skb ( skb ) ;
2007-11-17 02:52:17 +03:00
if ( matches > 0 ) {
2018-10-08 10:02:28 +03:00
pkg_stats - > matches + + ;
pkg_stats - > matches_delta + + ;
2007-11-17 02:52:17 +03:00
}
2012-06-13 22:33:02 +04:00
}
static int can_rcv ( struct sk_buff * skb , struct net_device * dev ,
struct packet_type * pt , struct net_device * orig_dev )
{
2022-12-06 23:12:59 +03:00
if ( unlikely ( dev - > type ! = ARPHRD_CAN | | ! can_get_ml_priv ( dev ) | | ! can_is_can_skb ( skb ) ) ) {
2020-11-04 00:39:05 +03:00
pr_warn_once ( " PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d \n " ,
dev - > type , skb - > len ) ;
2022-09-12 20:07:19 +03:00
kfree_skb ( skb ) ;
return NET_RX_DROP ;
2018-01-16 21:30:14 +03:00
}
2012-06-13 22:33:02 +04:00
can_receive ( skb , dev ) ;
return NET_RX_SUCCESS ;
}
static int canfd_rcv ( struct sk_buff * skb , struct net_device * dev ,
2019-08-13 10:06:17 +03:00
struct packet_type * pt , struct net_device * orig_dev )
2012-06-13 22:33:02 +04:00
{
2022-12-06 23:12:59 +03:00
if ( unlikely ( dev - > type ! = ARPHRD_CAN | | ! can_get_ml_priv ( dev ) | | ! can_is_canfd_skb ( skb ) ) ) {
2020-11-04 00:39:06 +03:00
pr_warn_once ( " PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d \n " ,
dev - > type , skb - > len ) ;
2022-09-12 20:07:19 +03:00
kfree_skb ( skb ) ;
return NET_RX_DROP ;
2018-01-16 21:30:14 +03:00
}
2012-06-13 22:33:02 +04:00
can_receive ( skb , dev ) ;
2009-08-29 10:45:09 +04:00
return NET_RX_SUCCESS ;
2007-11-17 02:52:17 +03:00
}
2022-09-12 20:07:23 +03:00
static int canxl_rcv ( struct sk_buff * skb , struct net_device * dev ,
struct packet_type * pt , struct net_device * orig_dev )
{
2022-12-06 23:12:59 +03:00
if ( unlikely ( dev - > type ! = ARPHRD_CAN | | ! can_get_ml_priv ( dev ) | | ! can_is_canxl_skb ( skb ) ) ) {
2022-09-12 20:07:23 +03:00
pr_warn_once ( " PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d \n " ,
dev - > type , skb - > len ) ;
kfree_skb ( skb ) ;
return NET_RX_DROP ;
}
can_receive ( skb , dev ) ;
return NET_RX_SUCCESS ;
}
2019-07-24 15:16:29 +03:00
/* af_can protocol functions */
2007-11-17 02:52:17 +03:00
/**
* can_proto_register - register CAN transport protocol
* @ cp : pointer to CAN protocol structure
*
* Return :
* 0 on success
* - EINVAL invalid ( out of range ) protocol number
* - EBUSY protocol already in use
* - ENOBUF if proto_register ( ) fails
*/
2011-05-03 22:40:57 +04:00
int can_proto_register ( const struct can_proto * cp )
2007-11-17 02:52:17 +03:00
{
int proto = cp - > protocol ;
int err = 0 ;
if ( proto < 0 | | proto > = CAN_NPROTO ) {
2013-03-10 15:15:13 +04:00
pr_err ( " can: protocol number %d out of range \n " , proto ) ;
2007-11-17 02:52:17 +03:00
return - EINVAL ;
}
2008-02-08 05:04:45 +03:00
err = proto_register ( cp - > prot , 0 ) ;
if ( err < 0 )
return err ;
2011-04-05 12:01:16 +04:00
mutex_lock ( & proto_tab_lock ) ;
2017-10-17 08:18:35 +03:00
if ( rcu_access_pointer ( proto_tab [ proto ] ) ) {
2013-03-10 15:15:13 +04:00
pr_err ( " can: protocol %d already registered \n " , proto ) ;
2007-11-17 02:52:17 +03:00
err = - EBUSY ;
2019-08-13 10:03:55 +03:00
} else {
2011-08-01 20:19:00 +04:00
RCU_INIT_POINTER ( proto_tab [ proto ] , cp ) ;
2019-08-13 10:03:55 +03:00
}
2008-02-08 05:04:45 +03:00
2011-04-05 12:01:16 +04:00
mutex_unlock ( & proto_tab_lock ) ;
2007-11-17 02:52:17 +03:00
if ( err < 0 )
2008-02-08 05:04:45 +03:00
proto_unregister ( cp - > prot ) ;
2007-11-17 02:52:17 +03:00
return err ;
}
EXPORT_SYMBOL ( can_proto_register ) ;
/**
* can_proto_unregister - unregister CAN transport protocol
* @ cp : pointer to CAN protocol structure
*/
2011-05-03 22:40:57 +04:00
void can_proto_unregister ( const struct can_proto * cp )
2007-11-17 02:52:17 +03:00
{
int proto = cp - > protocol ;
2011-04-05 12:01:16 +04:00
mutex_lock ( & proto_tab_lock ) ;
2017-10-17 08:18:35 +03:00
BUG_ON ( rcu_access_pointer ( proto_tab [ proto ] ) ! = cp ) ;
2011-08-01 20:19:00 +04:00
RCU_INIT_POINTER ( proto_tab [ proto ] , NULL ) ;
2011-04-05 12:01:16 +04:00
mutex_unlock ( & proto_tab_lock ) ;
synchronize_rcu ( ) ;
2008-02-08 05:04:45 +03:00
proto_unregister ( cp - > prot ) ;
2007-11-17 02:52:17 +03:00
}
EXPORT_SYMBOL ( can_proto_unregister ) ;
2017-02-21 14:19:47 +03:00
static int can_pernet_init ( struct net * net )
{
2018-10-08 10:02:30 +03:00
spin_lock_init ( & net - > can . rcvlists_lock ) ;
net - > can . rx_alldev_list =
kzalloc ( sizeof ( * net - > can . rx_alldev_list ) , GFP_KERNEL ) ;
if ( ! net - > can . rx_alldev_list )
2017-07-29 12:51:01 +03:00
goto out ;
2018-10-08 10:02:27 +03:00
net - > can . pkg_stats = kzalloc ( sizeof ( * net - > can . pkg_stats ) , GFP_KERNEL ) ;
if ( ! net - > can . pkg_stats )
goto out_free_rx_alldev_list ;
net - > can . rcv_lists_stats = kzalloc ( sizeof ( * net - > can . rcv_lists_stats ) , GFP_KERNEL ) ;
if ( ! net - > can . rcv_lists_stats )
goto out_free_pkg_stats ;
2017-04-25 09:19:41 +03:00
if ( IS_ENABLED ( CONFIG_PROC_FS ) ) {
/* the statistics are updated every second (timer triggered) */
if ( stats_timer ) {
2018-10-08 10:02:30 +03:00
timer_setup ( & net - > can . stattimer , can_stat_update ,
2017-10-17 03:29:06 +03:00
0 ) ;
2018-10-08 10:02:30 +03:00
mod_timer ( & net - > can . stattimer ,
2017-04-25 09:19:41 +03:00
round_jiffies ( jiffies + HZ ) ) ;
}
2018-10-08 10:02:27 +03:00
net - > can . pkg_stats - > jiffies_init = jiffies ;
2017-02-21 14:19:47 +03:00
can_init_proc ( net ) ;
2017-04-25 09:19:41 +03:00
}
2017-02-21 14:19:47 +03:00
return 0 ;
2017-07-29 12:51:01 +03:00
2018-10-08 10:02:27 +03:00
out_free_pkg_stats :
kfree ( net - > can . pkg_stats ) ;
out_free_rx_alldev_list :
2018-10-08 10:02:30 +03:00
kfree ( net - > can . rx_alldev_list ) ;
2017-07-29 12:51:01 +03:00
out :
return - ENOMEM ;
2017-02-21 14:19:47 +03:00
}
static void can_pernet_exit ( struct net * net )
{
2017-04-25 09:19:41 +03:00
if ( IS_ENABLED ( CONFIG_PROC_FS ) ) {
2017-02-21 14:19:47 +03:00
can_remove_proc ( net ) ;
2017-04-25 09:19:41 +03:00
if ( stats_timer )
2018-10-08 10:02:30 +03:00
del_timer_sync ( & net - > can . stattimer ) ;
2017-04-25 09:19:41 +03:00
}
2017-02-21 14:19:47 +03:00
2018-10-08 10:02:30 +03:00
kfree ( net - > can . rx_alldev_list ) ;
2018-10-08 10:02:27 +03:00
kfree ( net - > can . pkg_stats ) ;
kfree ( net - > can . rcv_lists_stats ) ;
2017-02-21 14:19:47 +03:00
}
2019-07-24 15:16:29 +03:00
/* af_can module init/exit functions */
2007-11-17 02:52:17 +03:00
static struct packet_type can_packet __read_mostly = {
2009-02-01 11:45:17 +03:00
. type = cpu_to_be16 ( ETH_P_CAN ) ,
2007-11-17 02:52:17 +03:00
. func = can_rcv ,
} ;
2012-06-13 22:33:02 +04:00
static struct packet_type canfd_packet __read_mostly = {
. type = cpu_to_be16 ( ETH_P_CANFD ) ,
. func = canfd_rcv ,
} ;
2022-09-12 20:07:23 +03:00
static struct packet_type canxl_packet __read_mostly = {
. type = cpu_to_be16 ( ETH_P_CANXL ) ,
. func = canxl_rcv ,
} ;
2009-10-05 09:58:39 +04:00
static const struct net_proto_family can_family_ops = {
2007-11-17 02:52:17 +03:00
. family = PF_CAN ,
. create = can_create ,
. owner = THIS_MODULE ,
} ;
2017-02-21 14:19:47 +03:00
static struct pernet_operations can_pernet_ops __read_mostly = {
. init = can_pernet_init ,
. exit = can_pernet_exit ,
} ;
2007-11-17 02:52:17 +03:00
static __init int can_init ( void )
{
2019-05-16 17:36:26 +03:00
int err ;
2012-06-13 22:04:33 +04:00
/* check for correct padding to be able to use the structs similarly */
2020-11-20 13:04:44 +03:00
BUILD_BUG_ON ( offsetof ( struct can_frame , len ) ! =
2012-06-13 22:04:33 +04:00
offsetof ( struct canfd_frame , len ) | |
offsetof ( struct can_frame , data ) ! =
offsetof ( struct canfd_frame , data ) ) ;
2020-10-12 10:43:54 +03:00
pr_info ( " can: controller area network core \n " ) ;
2007-11-17 02:52:17 +03:00
rcv_cache = kmem_cache_create ( " can_receiver " , sizeof ( struct receiver ) ,
0 , 0 , NULL ) ;
if ( ! rcv_cache )
return - ENOMEM ;
2019-05-16 17:36:26 +03:00
err = register_pernet_subsys ( & can_pernet_ops ) ;
if ( err )
goto out_pernet ;
2017-02-21 14:19:47 +03:00
2007-11-17 02:52:17 +03:00
/* protocol register */
2019-05-16 17:36:26 +03:00
err = sock_register ( & can_family_ops ) ;
if ( err )
goto out_sock ;
2007-11-17 02:52:17 +03:00
dev_add_pack ( & can_packet ) ;
2012-06-13 22:33:02 +04:00
dev_add_pack ( & canfd_packet ) ;
2022-09-12 20:07:23 +03:00
dev_add_pack ( & canxl_packet ) ;
2007-11-17 02:52:17 +03:00
return 0 ;
2019-05-16 17:36:26 +03:00
out_sock :
unregister_pernet_subsys ( & can_pernet_ops ) ;
out_pernet :
kmem_cache_destroy ( rcv_cache ) ;
return err ;
2007-11-17 02:52:17 +03:00
}
static __exit void can_exit ( void )
{
/* protocol unregister */
2022-10-31 06:30:53 +03:00
dev_remove_pack ( & canxl_packet ) ;
2012-06-13 22:33:02 +04:00
dev_remove_pack ( & canfd_packet ) ;
2007-11-17 02:52:17 +03:00
dev_remove_pack ( & can_packet ) ;
sock_unregister ( PF_CAN ) ;
2017-02-21 14:19:47 +03:00
unregister_pernet_subsys ( & can_pernet_ops ) ;
2007-11-17 02:52:17 +03:00
2009-06-08 07:11:38 +04:00
rcu_barrier ( ) ; /* Wait for completion of call_rcu()'s */
2007-11-17 02:52:17 +03:00
kmem_cache_destroy ( rcv_cache ) ;
}
module_init ( can_init ) ;
module_exit ( can_exit ) ;