162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 262306a36Sopenharmony_ci/* af_can.c - Protocol family CAN core module 362306a36Sopenharmony_ci * (used by different CAN protocol modules) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2002-2017 Volkswagen Group Electronic Research 662306a36Sopenharmony_ci * All rights reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 962306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1062306a36Sopenharmony_ci * are met: 1162306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1262306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1362306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 1462306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 1562306a36Sopenharmony_ci * documentation and/or other materials provided with the distribution. 1662306a36Sopenharmony_ci * 3. Neither the name of Volkswagen nor the names of its contributors 1762306a36Sopenharmony_ci * may be used to endorse or promote products derived from this software 1862306a36Sopenharmony_ci * without specific prior written permission. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Alternatively, provided that this notice is retained in full, this 2162306a36Sopenharmony_ci * software may be distributed under the terms of the GNU General 2262306a36Sopenharmony_ci * Public License ("GPL") version 2, in which case the provisions of the 2362306a36Sopenharmony_ci * GPL apply INSTEAD OF those given above. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * The provided data structures and external interfaces from this code 2662306a36Sopenharmony_ci * are not restricted to be used by modules with a GPL compatible license. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2962306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3062306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3162306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3262306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3362306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3462306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3562306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3662306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3762306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3862306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 3962306a36Sopenharmony_ci * DAMAGE. 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#include <linux/module.h> 4462306a36Sopenharmony_ci#include <linux/stddef.h> 4562306a36Sopenharmony_ci#include <linux/init.h> 4662306a36Sopenharmony_ci#include <linux/kmod.h> 4762306a36Sopenharmony_ci#include <linux/slab.h> 4862306a36Sopenharmony_ci#include <linux/list.h> 4962306a36Sopenharmony_ci#include <linux/spinlock.h> 5062306a36Sopenharmony_ci#include <linux/rcupdate.h> 5162306a36Sopenharmony_ci#include <linux/uaccess.h> 5262306a36Sopenharmony_ci#include <linux/net.h> 5362306a36Sopenharmony_ci#include <linux/netdevice.h> 5462306a36Sopenharmony_ci#include <linux/socket.h> 5562306a36Sopenharmony_ci#include <linux/if_ether.h> 5662306a36Sopenharmony_ci#include <linux/if_arp.h> 5762306a36Sopenharmony_ci#include <linux/skbuff.h> 5862306a36Sopenharmony_ci#include <linux/can.h> 5962306a36Sopenharmony_ci#include <linux/can/core.h> 6062306a36Sopenharmony_ci#include <linux/can/skb.h> 6162306a36Sopenharmony_ci#include <linux/can/can-ml.h> 6262306a36Sopenharmony_ci#include <linux/ratelimit.h> 6362306a36Sopenharmony_ci#include <net/net_namespace.h> 6462306a36Sopenharmony_ci#include <net/sock.h> 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#include "af_can.h" 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ciMODULE_DESCRIPTION("Controller Area Network PF_CAN core"); 6962306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 7062306a36Sopenharmony_ciMODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>, " 7162306a36Sopenharmony_ci "Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciMODULE_ALIAS_NETPROTO(PF_CAN); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic int stats_timer __read_mostly = 1; 7662306a36Sopenharmony_cimodule_param(stats_timer, int, 0444); 7762306a36Sopenharmony_ciMODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)"); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic struct kmem_cache *rcv_cache __read_mostly; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* table of registered CAN protocols */ 8262306a36Sopenharmony_cistatic const struct can_proto __rcu *proto_tab[CAN_NPROTO] __read_mostly; 8362306a36Sopenharmony_cistatic DEFINE_MUTEX(proto_tab_lock); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic atomic_t skbcounter = ATOMIC_INIT(0); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* af_can socket functions */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_civoid can_sock_destruct(struct sock *sk) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci skb_queue_purge(&sk->sk_receive_queue); 9262306a36Sopenharmony_ci skb_queue_purge(&sk->sk_error_queue); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ciEXPORT_SYMBOL(can_sock_destruct); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic const struct can_proto *can_get_proto(int protocol) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci const struct can_proto *cp; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci rcu_read_lock(); 10162306a36Sopenharmony_ci cp = rcu_dereference(proto_tab[protocol]); 10262306a36Sopenharmony_ci if (cp && !try_module_get(cp->prot->owner)) 10362306a36Sopenharmony_ci cp = NULL; 10462306a36Sopenharmony_ci rcu_read_unlock(); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return cp; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic inline void can_put_proto(const struct can_proto *cp) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci module_put(cp->prot->owner); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic int can_create(struct net *net, struct socket *sock, int protocol, 11562306a36Sopenharmony_ci int kern) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct sock *sk; 11862306a36Sopenharmony_ci const struct can_proto *cp; 11962306a36Sopenharmony_ci int err = 0; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci sock->state = SS_UNCONNECTED; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (protocol < 0 || protocol >= CAN_NPROTO) 12462306a36Sopenharmony_ci return -EINVAL; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci cp = can_get_proto(protocol); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#ifdef CONFIG_MODULES 12962306a36Sopenharmony_ci if (!cp) { 13062306a36Sopenharmony_ci /* try to load protocol module if kernel is modular */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci err = request_module("can-proto-%d", protocol); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* In case of error we only print a message but don't 13562306a36Sopenharmony_ci * return the error code immediately. Below we will 13662306a36Sopenharmony_ci * return -EPROTONOSUPPORT 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_ci if (err) 13962306a36Sopenharmony_ci pr_err_ratelimited("can: request_module (can-proto-%d) failed.\n", 14062306a36Sopenharmony_ci protocol); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci cp = can_get_proto(protocol); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci#endif 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* check for available protocol and correct usage */ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (!cp) 14962306a36Sopenharmony_ci return -EPROTONOSUPPORT; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (cp->type != sock->type) { 15262306a36Sopenharmony_ci err = -EPROTOTYPE; 15362306a36Sopenharmony_ci goto errout; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci sock->ops = cp->ops; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot, kern); 15962306a36Sopenharmony_ci if (!sk) { 16062306a36Sopenharmony_ci err = -ENOMEM; 16162306a36Sopenharmony_ci goto errout; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci sock_init_data(sock, sk); 16562306a36Sopenharmony_ci sk->sk_destruct = can_sock_destruct; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (sk->sk_prot->init) 16862306a36Sopenharmony_ci err = sk->sk_prot->init(sk); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (err) { 17162306a36Sopenharmony_ci /* release sk on errors */ 17262306a36Sopenharmony_ci sock_orphan(sk); 17362306a36Sopenharmony_ci sock_put(sk); 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci errout: 17762306a36Sopenharmony_ci can_put_proto(cp); 17862306a36Sopenharmony_ci return err; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci/* af_can tx path */ 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/** 18462306a36Sopenharmony_ci * can_send - transmit a CAN frame (optional with local loopback) 18562306a36Sopenharmony_ci * @skb: pointer to socket buffer with CAN frame in data section 18662306a36Sopenharmony_ci * @loop: loopback for listeners on local CAN sockets (recommended default!) 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * Due to the loopback this routine must not be called from hardirq context. 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * Return: 19162306a36Sopenharmony_ci * 0 on success 19262306a36Sopenharmony_ci * -ENETDOWN when the selected interface is down 19362306a36Sopenharmony_ci * -ENOBUFS on full driver queue (see net_xmit_errno()) 19462306a36Sopenharmony_ci * -ENOMEM when local loopback failed at calling skb_clone() 19562306a36Sopenharmony_ci * -EPERM when trying to send on a non-CAN interface 19662306a36Sopenharmony_ci * -EMSGSIZE CAN frame size is bigger than CAN interface MTU 19762306a36Sopenharmony_ci * -EINVAL when the skb->data does not contain a valid CAN frame 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ciint can_send(struct sk_buff *skb, int loop) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct sk_buff *newskb = NULL; 20262306a36Sopenharmony_ci struct can_pkg_stats *pkg_stats = dev_net(skb->dev)->can.pkg_stats; 20362306a36Sopenharmony_ci int err = -EINVAL; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (can_is_canxl_skb(skb)) { 20662306a36Sopenharmony_ci skb->protocol = htons(ETH_P_CANXL); 20762306a36Sopenharmony_ci } else if (can_is_can_skb(skb)) { 20862306a36Sopenharmony_ci skb->protocol = htons(ETH_P_CAN); 20962306a36Sopenharmony_ci } else if (can_is_canfd_skb(skb)) { 21062306a36Sopenharmony_ci struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci skb->protocol = htons(ETH_P_CANFD); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* set CAN FD flag for CAN FD frames by default */ 21562306a36Sopenharmony_ci cfd->flags |= CANFD_FDF; 21662306a36Sopenharmony_ci } else { 21762306a36Sopenharmony_ci goto inval_skb; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Make sure the CAN frame can pass the selected CAN netdevice. */ 22162306a36Sopenharmony_ci if (unlikely(skb->len > skb->dev->mtu)) { 22262306a36Sopenharmony_ci err = -EMSGSIZE; 22362306a36Sopenharmony_ci goto inval_skb; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (unlikely(skb->dev->type != ARPHRD_CAN)) { 22762306a36Sopenharmony_ci err = -EPERM; 22862306a36Sopenharmony_ci goto inval_skb; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (unlikely(!(skb->dev->flags & IFF_UP))) { 23262306a36Sopenharmony_ci err = -ENETDOWN; 23362306a36Sopenharmony_ci goto inval_skb; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci skb->ip_summed = CHECKSUM_UNNECESSARY; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci skb_reset_mac_header(skb); 23962306a36Sopenharmony_ci skb_reset_network_header(skb); 24062306a36Sopenharmony_ci skb_reset_transport_header(skb); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci if (loop) { 24362306a36Sopenharmony_ci /* local loopback of sent CAN frames */ 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* indication for the CAN driver: do loopback */ 24662306a36Sopenharmony_ci skb->pkt_type = PACKET_LOOPBACK; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* The reference to the originating sock may be required 24962306a36Sopenharmony_ci * by the receiving socket to check whether the frame is 25062306a36Sopenharmony_ci * its own. Example: can_raw sockopt CAN_RAW_RECV_OWN_MSGS 25162306a36Sopenharmony_ci * Therefore we have to ensure that skb->sk remains the 25262306a36Sopenharmony_ci * reference to the originating sock by restoring skb->sk 25362306a36Sopenharmony_ci * after each skb_clone() or skb_orphan() usage. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (!(skb->dev->flags & IFF_ECHO)) { 25762306a36Sopenharmony_ci /* If the interface is not capable to do loopback 25862306a36Sopenharmony_ci * itself, we do it here. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci newskb = skb_clone(skb, GFP_ATOMIC); 26162306a36Sopenharmony_ci if (!newskb) { 26262306a36Sopenharmony_ci kfree_skb(skb); 26362306a36Sopenharmony_ci return -ENOMEM; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci can_skb_set_owner(newskb, skb->sk); 26762306a36Sopenharmony_ci newskb->ip_summed = CHECKSUM_UNNECESSARY; 26862306a36Sopenharmony_ci newskb->pkt_type = PACKET_BROADCAST; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci } else { 27162306a36Sopenharmony_ci /* indication for the CAN driver: no loopback required */ 27262306a36Sopenharmony_ci skb->pkt_type = PACKET_HOST; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* send to netdevice */ 27662306a36Sopenharmony_ci err = dev_queue_xmit(skb); 27762306a36Sopenharmony_ci if (err > 0) 27862306a36Sopenharmony_ci err = net_xmit_errno(err); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci if (err) { 28162306a36Sopenharmony_ci kfree_skb(newskb); 28262306a36Sopenharmony_ci return err; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci if (newskb) 28662306a36Sopenharmony_ci netif_rx(newskb); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* update statistics */ 28962306a36Sopenharmony_ci pkg_stats->tx_frames++; 29062306a36Sopenharmony_ci pkg_stats->tx_frames_delta++; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci return 0; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciinval_skb: 29562306a36Sopenharmony_ci kfree_skb(skb); 29662306a36Sopenharmony_ci return err; 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ciEXPORT_SYMBOL(can_send); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci/* af_can rx path */ 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net, 30362306a36Sopenharmony_ci struct net_device *dev) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci if (dev) { 30662306a36Sopenharmony_ci struct can_ml_priv *can_ml = can_get_ml_priv(dev); 30762306a36Sopenharmony_ci return &can_ml->dev_rcv_lists; 30862306a36Sopenharmony_ci } else { 30962306a36Sopenharmony_ci return net->can.rx_alldev_list; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/** 31462306a36Sopenharmony_ci * effhash - hash function for 29 bit CAN identifier reduction 31562306a36Sopenharmony_ci * @can_id: 29 bit CAN identifier 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * Description: 31862306a36Sopenharmony_ci * To reduce the linear traversal in one linked list of _single_ EFF CAN 31962306a36Sopenharmony_ci * frame subscriptions the 29 bit identifier is mapped to 10 bits. 32062306a36Sopenharmony_ci * (see CAN_EFF_RCV_HASH_BITS definition) 32162306a36Sopenharmony_ci * 32262306a36Sopenharmony_ci * Return: 32362306a36Sopenharmony_ci * Hash value from 0x000 - 0x3FF ( enforced by CAN_EFF_RCV_HASH_BITS mask ) 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_cistatic unsigned int effhash(canid_t can_id) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci unsigned int hash; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci hash = can_id; 33062306a36Sopenharmony_ci hash ^= can_id >> CAN_EFF_RCV_HASH_BITS; 33162306a36Sopenharmony_ci hash ^= can_id >> (2 * CAN_EFF_RCV_HASH_BITS); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return hash & ((1 << CAN_EFF_RCV_HASH_BITS) - 1); 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/** 33762306a36Sopenharmony_ci * can_rcv_list_find - determine optimal filterlist inside device filter struct 33862306a36Sopenharmony_ci * @can_id: pointer to CAN identifier of a given can_filter 33962306a36Sopenharmony_ci * @mask: pointer to CAN mask of a given can_filter 34062306a36Sopenharmony_ci * @dev_rcv_lists: pointer to the device filter struct 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci * Description: 34362306a36Sopenharmony_ci * Returns the optimal filterlist to reduce the filter handling in the 34462306a36Sopenharmony_ci * receive path. This function is called by service functions that need 34562306a36Sopenharmony_ci * to register or unregister a can_filter in the filter lists. 34662306a36Sopenharmony_ci * 34762306a36Sopenharmony_ci * A filter matches in general, when 34862306a36Sopenharmony_ci * 34962306a36Sopenharmony_ci * <received_can_id> & mask == can_id & mask 35062306a36Sopenharmony_ci * 35162306a36Sopenharmony_ci * so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe 35262306a36Sopenharmony_ci * relevant bits for the filter. 35362306a36Sopenharmony_ci * 35462306a36Sopenharmony_ci * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can 35562306a36Sopenharmony_ci * filter for error messages (CAN_ERR_FLAG bit set in mask). For error msg 35662306a36Sopenharmony_ci * frames there is a special filterlist and a special rx path filter handling. 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci * Return: 35962306a36Sopenharmony_ci * Pointer to optimal filterlist for the given can_id/mask pair. 36062306a36Sopenharmony_ci * Consistency checked mask. 36162306a36Sopenharmony_ci * Reduced can_id to have a preprocessed filter compare value. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_cistatic struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask, 36462306a36Sopenharmony_ci struct can_dev_rcv_lists *dev_rcv_lists) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */ 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* filter for error message frames in extra filterlist */ 36962306a36Sopenharmony_ci if (*mask & CAN_ERR_FLAG) { 37062306a36Sopenharmony_ci /* clear CAN_ERR_FLAG in filter entry */ 37162306a36Sopenharmony_ci *mask &= CAN_ERR_MASK; 37262306a36Sopenharmony_ci return &dev_rcv_lists->rx[RX_ERR]; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */ 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci#define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG) 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* ensure valid values in can_mask for 'SFF only' frame filtering */ 38062306a36Sopenharmony_ci if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG)) 38162306a36Sopenharmony_ci *mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* reduce condition testing at receive time */ 38462306a36Sopenharmony_ci *can_id &= *mask; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* inverse can_id/can_mask filter */ 38762306a36Sopenharmony_ci if (inv) 38862306a36Sopenharmony_ci return &dev_rcv_lists->rx[RX_INV]; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* mask == 0 => no condition testing at receive time */ 39162306a36Sopenharmony_ci if (!(*mask)) 39262306a36Sopenharmony_ci return &dev_rcv_lists->rx[RX_ALL]; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* extra filterlists for the subscription of a single non-RTR can_id */ 39562306a36Sopenharmony_ci if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) && 39662306a36Sopenharmony_ci !(*can_id & CAN_RTR_FLAG)) { 39762306a36Sopenharmony_ci if (*can_id & CAN_EFF_FLAG) { 39862306a36Sopenharmony_ci if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) 39962306a36Sopenharmony_ci return &dev_rcv_lists->rx_eff[effhash(*can_id)]; 40062306a36Sopenharmony_ci } else { 40162306a36Sopenharmony_ci if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS)) 40262306a36Sopenharmony_ci return &dev_rcv_lists->rx_sff[*can_id]; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* default: filter via can_id/can_mask */ 40762306a36Sopenharmony_ci return &dev_rcv_lists->rx[RX_FIL]; 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci/** 41162306a36Sopenharmony_ci * can_rx_register - subscribe CAN frames from a specific interface 41262306a36Sopenharmony_ci * @net: the applicable net namespace 41362306a36Sopenharmony_ci * @dev: pointer to netdevice (NULL => subscribe from 'all' CAN devices list) 41462306a36Sopenharmony_ci * @can_id: CAN identifier (see description) 41562306a36Sopenharmony_ci * @mask: CAN mask (see description) 41662306a36Sopenharmony_ci * @func: callback function on filter match 41762306a36Sopenharmony_ci * @data: returned parameter for callback function 41862306a36Sopenharmony_ci * @ident: string for calling module identification 41962306a36Sopenharmony_ci * @sk: socket pointer (might be NULL) 42062306a36Sopenharmony_ci * 42162306a36Sopenharmony_ci * Description: 42262306a36Sopenharmony_ci * Invokes the callback function with the received sk_buff and the given 42362306a36Sopenharmony_ci * parameter 'data' on a matching receive filter. A filter matches, when 42462306a36Sopenharmony_ci * 42562306a36Sopenharmony_ci * <received_can_id> & mask == can_id & mask 42662306a36Sopenharmony_ci * 42762306a36Sopenharmony_ci * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can 42862306a36Sopenharmony_ci * filter for error message frames (CAN_ERR_FLAG bit set in mask). 42962306a36Sopenharmony_ci * 43062306a36Sopenharmony_ci * The provided pointer to the sk_buff is guaranteed to be valid as long as 43162306a36Sopenharmony_ci * the callback function is running. The callback function must *not* free 43262306a36Sopenharmony_ci * the given sk_buff while processing it's task. When the given sk_buff is 43362306a36Sopenharmony_ci * needed after the end of the callback function it must be cloned inside 43462306a36Sopenharmony_ci * the callback function with skb_clone(). 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * Return: 43762306a36Sopenharmony_ci * 0 on success 43862306a36Sopenharmony_ci * -ENOMEM on missing cache mem to create subscription entry 43962306a36Sopenharmony_ci * -ENODEV unknown device 44062306a36Sopenharmony_ci */ 44162306a36Sopenharmony_ciint can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, 44262306a36Sopenharmony_ci canid_t mask, void (*func)(struct sk_buff *, void *), 44362306a36Sopenharmony_ci void *data, char *ident, struct sock *sk) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci struct receiver *rcv; 44662306a36Sopenharmony_ci struct hlist_head *rcv_list; 44762306a36Sopenharmony_ci struct can_dev_rcv_lists *dev_rcv_lists; 44862306a36Sopenharmony_ci struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci /* insert new receiver (dev,canid,mask) -> (func,data) */ 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev))) 45362306a36Sopenharmony_ci return -ENODEV; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (dev && !net_eq(net, dev_net(dev))) 45662306a36Sopenharmony_ci return -ENODEV; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci rcv = kmem_cache_alloc(rcv_cache, GFP_KERNEL); 45962306a36Sopenharmony_ci if (!rcv) 46062306a36Sopenharmony_ci return -ENOMEM; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci spin_lock_bh(&net->can.rcvlists_lock); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci dev_rcv_lists = can_dev_rcv_lists_find(net, dev); 46562306a36Sopenharmony_ci rcv_list = can_rcv_list_find(&can_id, &mask, dev_rcv_lists); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci rcv->can_id = can_id; 46862306a36Sopenharmony_ci rcv->mask = mask; 46962306a36Sopenharmony_ci rcv->matches = 0; 47062306a36Sopenharmony_ci rcv->func = func; 47162306a36Sopenharmony_ci rcv->data = data; 47262306a36Sopenharmony_ci rcv->ident = ident; 47362306a36Sopenharmony_ci rcv->sk = sk; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci hlist_add_head_rcu(&rcv->list, rcv_list); 47662306a36Sopenharmony_ci dev_rcv_lists->entries++; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci rcv_lists_stats->rcv_entries++; 47962306a36Sopenharmony_ci rcv_lists_stats->rcv_entries_max = max(rcv_lists_stats->rcv_entries_max, 48062306a36Sopenharmony_ci rcv_lists_stats->rcv_entries); 48162306a36Sopenharmony_ci spin_unlock_bh(&net->can.rcvlists_lock); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return 0; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ciEXPORT_SYMBOL(can_rx_register); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/* can_rx_delete_receiver - rcu callback for single receiver entry removal */ 48862306a36Sopenharmony_cistatic void can_rx_delete_receiver(struct rcu_head *rp) 48962306a36Sopenharmony_ci{ 49062306a36Sopenharmony_ci struct receiver *rcv = container_of(rp, struct receiver, rcu); 49162306a36Sopenharmony_ci struct sock *sk = rcv->sk; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci kmem_cache_free(rcv_cache, rcv); 49462306a36Sopenharmony_ci if (sk) 49562306a36Sopenharmony_ci sock_put(sk); 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci/** 49962306a36Sopenharmony_ci * can_rx_unregister - unsubscribe CAN frames from a specific interface 50062306a36Sopenharmony_ci * @net: the applicable net namespace 50162306a36Sopenharmony_ci * @dev: pointer to netdevice (NULL => unsubscribe from 'all' CAN devices list) 50262306a36Sopenharmony_ci * @can_id: CAN identifier 50362306a36Sopenharmony_ci * @mask: CAN mask 50462306a36Sopenharmony_ci * @func: callback function on filter match 50562306a36Sopenharmony_ci * @data: returned parameter for callback function 50662306a36Sopenharmony_ci * 50762306a36Sopenharmony_ci * Description: 50862306a36Sopenharmony_ci * Removes subscription entry depending on given (subscription) values. 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_civoid can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, 51162306a36Sopenharmony_ci canid_t mask, void (*func)(struct sk_buff *, void *), 51262306a36Sopenharmony_ci void *data) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci struct receiver *rcv = NULL; 51562306a36Sopenharmony_ci struct hlist_head *rcv_list; 51662306a36Sopenharmony_ci struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats; 51762306a36Sopenharmony_ci struct can_dev_rcv_lists *dev_rcv_lists; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (dev && dev->type != ARPHRD_CAN) 52062306a36Sopenharmony_ci return; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (dev && !net_eq(net, dev_net(dev))) 52362306a36Sopenharmony_ci return; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci spin_lock_bh(&net->can.rcvlists_lock); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci dev_rcv_lists = can_dev_rcv_lists_find(net, dev); 52862306a36Sopenharmony_ci rcv_list = can_rcv_list_find(&can_id, &mask, dev_rcv_lists); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /* Search the receiver list for the item to delete. This should 53162306a36Sopenharmony_ci * exist, since no receiver may be unregistered that hasn't 53262306a36Sopenharmony_ci * been registered before. 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, rcv_list, list) { 53562306a36Sopenharmony_ci if (rcv->can_id == can_id && rcv->mask == mask && 53662306a36Sopenharmony_ci rcv->func == func && rcv->data == data) 53762306a36Sopenharmony_ci break; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci /* Check for bugs in CAN protocol implementations using af_can.c: 54162306a36Sopenharmony_ci * 'rcv' will be NULL if no matching list item was found for removal. 54262306a36Sopenharmony_ci * As this case may potentially happen when closing a socket while 54362306a36Sopenharmony_ci * the notifier for removing the CAN netdev is running we just print 54462306a36Sopenharmony_ci * a warning here. 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_ci if (!rcv) { 54762306a36Sopenharmony_ci pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n", 54862306a36Sopenharmony_ci DNAME(dev), can_id, mask); 54962306a36Sopenharmony_ci goto out; 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci hlist_del_rcu(&rcv->list); 55362306a36Sopenharmony_ci dev_rcv_lists->entries--; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (rcv_lists_stats->rcv_entries > 0) 55662306a36Sopenharmony_ci rcv_lists_stats->rcv_entries--; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci out: 55962306a36Sopenharmony_ci spin_unlock_bh(&net->can.rcvlists_lock); 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci /* schedule the receiver item for deletion */ 56262306a36Sopenharmony_ci if (rcv) { 56362306a36Sopenharmony_ci if (rcv->sk) 56462306a36Sopenharmony_ci sock_hold(rcv->sk); 56562306a36Sopenharmony_ci call_rcu(&rcv->rcu, can_rx_delete_receiver); 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci} 56862306a36Sopenharmony_ciEXPORT_SYMBOL(can_rx_unregister); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic inline void deliver(struct sk_buff *skb, struct receiver *rcv) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci rcv->func(skb, rcv->data); 57362306a36Sopenharmony_ci rcv->matches++; 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct receiver *rcv; 57962306a36Sopenharmony_ci int matches = 0; 58062306a36Sopenharmony_ci struct can_frame *cf = (struct can_frame *)skb->data; 58162306a36Sopenharmony_ci canid_t can_id = cf->can_id; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (dev_rcv_lists->entries == 0) 58462306a36Sopenharmony_ci return 0; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (can_id & CAN_ERR_FLAG) { 58762306a36Sopenharmony_ci /* check for error message frame entries only */ 58862306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ERR], list) { 58962306a36Sopenharmony_ci if (can_id & rcv->mask) { 59062306a36Sopenharmony_ci deliver(skb, rcv); 59162306a36Sopenharmony_ci matches++; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci return matches; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* check for unfiltered entries */ 59862306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ALL], list) { 59962306a36Sopenharmony_ci deliver(skb, rcv); 60062306a36Sopenharmony_ci matches++; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* check for can_id/mask entries */ 60462306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_FIL], list) { 60562306a36Sopenharmony_ci if ((can_id & rcv->mask) == rcv->can_id) { 60662306a36Sopenharmony_ci deliver(skb, rcv); 60762306a36Sopenharmony_ci matches++; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* check for inverted can_id/mask entries */ 61262306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_INV], list) { 61362306a36Sopenharmony_ci if ((can_id & rcv->mask) != rcv->can_id) { 61462306a36Sopenharmony_ci deliver(skb, rcv); 61562306a36Sopenharmony_ci matches++; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* check filterlists for single non-RTR can_ids */ 62062306a36Sopenharmony_ci if (can_id & CAN_RTR_FLAG) 62162306a36Sopenharmony_ci return matches; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (can_id & CAN_EFF_FLAG) { 62462306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_eff[effhash(can_id)], list) { 62562306a36Sopenharmony_ci if (rcv->can_id == can_id) { 62662306a36Sopenharmony_ci deliver(skb, rcv); 62762306a36Sopenharmony_ci matches++; 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci } else { 63162306a36Sopenharmony_ci can_id &= CAN_SFF_MASK; 63262306a36Sopenharmony_ci hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_sff[can_id], list) { 63362306a36Sopenharmony_ci deliver(skb, rcv); 63462306a36Sopenharmony_ci matches++; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci return matches; 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic void can_receive(struct sk_buff *skb, struct net_device *dev) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci struct can_dev_rcv_lists *dev_rcv_lists; 64462306a36Sopenharmony_ci struct net *net = dev_net(dev); 64562306a36Sopenharmony_ci struct can_pkg_stats *pkg_stats = net->can.pkg_stats; 64662306a36Sopenharmony_ci int matches; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci /* update statistics */ 64962306a36Sopenharmony_ci pkg_stats->rx_frames++; 65062306a36Sopenharmony_ci pkg_stats->rx_frames_delta++; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci /* create non-zero unique skb identifier together with *skb */ 65362306a36Sopenharmony_ci while (!(can_skb_prv(skb)->skbcnt)) 65462306a36Sopenharmony_ci can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci rcu_read_lock(); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci /* deliver the packet to sockets listening on all devices */ 65962306a36Sopenharmony_ci matches = can_rcv_filter(net->can.rx_alldev_list, skb); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* find receive list for this device */ 66262306a36Sopenharmony_ci dev_rcv_lists = can_dev_rcv_lists_find(net, dev); 66362306a36Sopenharmony_ci matches += can_rcv_filter(dev_rcv_lists, skb); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci rcu_read_unlock(); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /* consume the skbuff allocated by the netdevice driver */ 66862306a36Sopenharmony_ci consume_skb(skb); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci if (matches > 0) { 67162306a36Sopenharmony_ci pkg_stats->matches++; 67262306a36Sopenharmony_ci pkg_stats->matches_delta++; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_cistatic int can_rcv(struct sk_buff *skb, struct net_device *dev, 67762306a36Sopenharmony_ci struct packet_type *pt, struct net_device *orig_dev) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_can_skb(skb))) { 68062306a36Sopenharmony_ci pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n", 68162306a36Sopenharmony_ci dev->type, skb->len); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci kfree_skb(skb); 68462306a36Sopenharmony_ci return NET_RX_DROP; 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci can_receive(skb, dev); 68862306a36Sopenharmony_ci return NET_RX_SUCCESS; 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_cistatic int canfd_rcv(struct sk_buff *skb, struct net_device *dev, 69262306a36Sopenharmony_ci struct packet_type *pt, struct net_device *orig_dev) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canfd_skb(skb))) { 69562306a36Sopenharmony_ci pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n", 69662306a36Sopenharmony_ci dev->type, skb->len); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci kfree_skb(skb); 69962306a36Sopenharmony_ci return NET_RX_DROP; 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci can_receive(skb, dev); 70362306a36Sopenharmony_ci return NET_RX_SUCCESS; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic int canxl_rcv(struct sk_buff *skb, struct net_device *dev, 70762306a36Sopenharmony_ci struct packet_type *pt, struct net_device *orig_dev) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canxl_skb(skb))) { 71062306a36Sopenharmony_ci pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n", 71162306a36Sopenharmony_ci dev->type, skb->len); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci kfree_skb(skb); 71462306a36Sopenharmony_ci return NET_RX_DROP; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci can_receive(skb, dev); 71862306a36Sopenharmony_ci return NET_RX_SUCCESS; 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci/* af_can protocol functions */ 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci/** 72462306a36Sopenharmony_ci * can_proto_register - register CAN transport protocol 72562306a36Sopenharmony_ci * @cp: pointer to CAN protocol structure 72662306a36Sopenharmony_ci * 72762306a36Sopenharmony_ci * Return: 72862306a36Sopenharmony_ci * 0 on success 72962306a36Sopenharmony_ci * -EINVAL invalid (out of range) protocol number 73062306a36Sopenharmony_ci * -EBUSY protocol already in use 73162306a36Sopenharmony_ci * -ENOBUF if proto_register() fails 73262306a36Sopenharmony_ci */ 73362306a36Sopenharmony_ciint can_proto_register(const struct can_proto *cp) 73462306a36Sopenharmony_ci{ 73562306a36Sopenharmony_ci int proto = cp->protocol; 73662306a36Sopenharmony_ci int err = 0; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci if (proto < 0 || proto >= CAN_NPROTO) { 73962306a36Sopenharmony_ci pr_err("can: protocol number %d out of range\n", proto); 74062306a36Sopenharmony_ci return -EINVAL; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci err = proto_register(cp->prot, 0); 74462306a36Sopenharmony_ci if (err < 0) 74562306a36Sopenharmony_ci return err; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci mutex_lock(&proto_tab_lock); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci if (rcu_access_pointer(proto_tab[proto])) { 75062306a36Sopenharmony_ci pr_err("can: protocol %d already registered\n", proto); 75162306a36Sopenharmony_ci err = -EBUSY; 75262306a36Sopenharmony_ci } else { 75362306a36Sopenharmony_ci RCU_INIT_POINTER(proto_tab[proto], cp); 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci mutex_unlock(&proto_tab_lock); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci if (err < 0) 75962306a36Sopenharmony_ci proto_unregister(cp->prot); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return err; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ciEXPORT_SYMBOL(can_proto_register); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci/** 76662306a36Sopenharmony_ci * can_proto_unregister - unregister CAN transport protocol 76762306a36Sopenharmony_ci * @cp: pointer to CAN protocol structure 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_civoid can_proto_unregister(const struct can_proto *cp) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci int proto = cp->protocol; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci mutex_lock(&proto_tab_lock); 77462306a36Sopenharmony_ci BUG_ON(rcu_access_pointer(proto_tab[proto]) != cp); 77562306a36Sopenharmony_ci RCU_INIT_POINTER(proto_tab[proto], NULL); 77662306a36Sopenharmony_ci mutex_unlock(&proto_tab_lock); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci synchronize_rcu(); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci proto_unregister(cp->prot); 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ciEXPORT_SYMBOL(can_proto_unregister); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic int can_pernet_init(struct net *net) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci spin_lock_init(&net->can.rcvlists_lock); 78762306a36Sopenharmony_ci net->can.rx_alldev_list = 78862306a36Sopenharmony_ci kzalloc(sizeof(*net->can.rx_alldev_list), GFP_KERNEL); 78962306a36Sopenharmony_ci if (!net->can.rx_alldev_list) 79062306a36Sopenharmony_ci goto out; 79162306a36Sopenharmony_ci net->can.pkg_stats = kzalloc(sizeof(*net->can.pkg_stats), GFP_KERNEL); 79262306a36Sopenharmony_ci if (!net->can.pkg_stats) 79362306a36Sopenharmony_ci goto out_free_rx_alldev_list; 79462306a36Sopenharmony_ci net->can.rcv_lists_stats = kzalloc(sizeof(*net->can.rcv_lists_stats), GFP_KERNEL); 79562306a36Sopenharmony_ci if (!net->can.rcv_lists_stats) 79662306a36Sopenharmony_ci goto out_free_pkg_stats; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PROC_FS)) { 79962306a36Sopenharmony_ci /* the statistics are updated every second (timer triggered) */ 80062306a36Sopenharmony_ci if (stats_timer) { 80162306a36Sopenharmony_ci timer_setup(&net->can.stattimer, can_stat_update, 80262306a36Sopenharmony_ci 0); 80362306a36Sopenharmony_ci mod_timer(&net->can.stattimer, 80462306a36Sopenharmony_ci round_jiffies(jiffies + HZ)); 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci net->can.pkg_stats->jiffies_init = jiffies; 80762306a36Sopenharmony_ci can_init_proc(net); 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci return 0; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci out_free_pkg_stats: 81362306a36Sopenharmony_ci kfree(net->can.pkg_stats); 81462306a36Sopenharmony_ci out_free_rx_alldev_list: 81562306a36Sopenharmony_ci kfree(net->can.rx_alldev_list); 81662306a36Sopenharmony_ci out: 81762306a36Sopenharmony_ci return -ENOMEM; 81862306a36Sopenharmony_ci} 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic void can_pernet_exit(struct net *net) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PROC_FS)) { 82362306a36Sopenharmony_ci can_remove_proc(net); 82462306a36Sopenharmony_ci if (stats_timer) 82562306a36Sopenharmony_ci del_timer_sync(&net->can.stattimer); 82662306a36Sopenharmony_ci } 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci kfree(net->can.rx_alldev_list); 82962306a36Sopenharmony_ci kfree(net->can.pkg_stats); 83062306a36Sopenharmony_ci kfree(net->can.rcv_lists_stats); 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci/* af_can module init/exit functions */ 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_cistatic struct packet_type can_packet __read_mostly = { 83662306a36Sopenharmony_ci .type = cpu_to_be16(ETH_P_CAN), 83762306a36Sopenharmony_ci .func = can_rcv, 83862306a36Sopenharmony_ci}; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_cistatic struct packet_type canfd_packet __read_mostly = { 84162306a36Sopenharmony_ci .type = cpu_to_be16(ETH_P_CANFD), 84262306a36Sopenharmony_ci .func = canfd_rcv, 84362306a36Sopenharmony_ci}; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_cistatic struct packet_type canxl_packet __read_mostly = { 84662306a36Sopenharmony_ci .type = cpu_to_be16(ETH_P_CANXL), 84762306a36Sopenharmony_ci .func = canxl_rcv, 84862306a36Sopenharmony_ci}; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_cistatic const struct net_proto_family can_family_ops = { 85162306a36Sopenharmony_ci .family = PF_CAN, 85262306a36Sopenharmony_ci .create = can_create, 85362306a36Sopenharmony_ci .owner = THIS_MODULE, 85462306a36Sopenharmony_ci}; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cistatic struct pernet_operations can_pernet_ops __read_mostly = { 85762306a36Sopenharmony_ci .init = can_pernet_init, 85862306a36Sopenharmony_ci .exit = can_pernet_exit, 85962306a36Sopenharmony_ci}; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_cistatic __init int can_init(void) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci int err; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* check for correct padding to be able to use the structs similarly */ 86662306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct can_frame, len) != 86762306a36Sopenharmony_ci offsetof(struct canfd_frame, len) || 86862306a36Sopenharmony_ci offsetof(struct can_frame, data) != 86962306a36Sopenharmony_ci offsetof(struct canfd_frame, data)); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci pr_info("can: controller area network core\n"); 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver), 87462306a36Sopenharmony_ci 0, 0, NULL); 87562306a36Sopenharmony_ci if (!rcv_cache) 87662306a36Sopenharmony_ci return -ENOMEM; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci err = register_pernet_subsys(&can_pernet_ops); 87962306a36Sopenharmony_ci if (err) 88062306a36Sopenharmony_ci goto out_pernet; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci /* protocol register */ 88362306a36Sopenharmony_ci err = sock_register(&can_family_ops); 88462306a36Sopenharmony_ci if (err) 88562306a36Sopenharmony_ci goto out_sock; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci dev_add_pack(&can_packet); 88862306a36Sopenharmony_ci dev_add_pack(&canfd_packet); 88962306a36Sopenharmony_ci dev_add_pack(&canxl_packet); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return 0; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ciout_sock: 89462306a36Sopenharmony_ci unregister_pernet_subsys(&can_pernet_ops); 89562306a36Sopenharmony_ciout_pernet: 89662306a36Sopenharmony_ci kmem_cache_destroy(rcv_cache); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci return err; 89962306a36Sopenharmony_ci} 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_cistatic __exit void can_exit(void) 90262306a36Sopenharmony_ci{ 90362306a36Sopenharmony_ci /* protocol unregister */ 90462306a36Sopenharmony_ci dev_remove_pack(&canxl_packet); 90562306a36Sopenharmony_ci dev_remove_pack(&canfd_packet); 90662306a36Sopenharmony_ci dev_remove_pack(&can_packet); 90762306a36Sopenharmony_ci sock_unregister(PF_CAN); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci unregister_pernet_subsys(&can_pernet_ops); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci rcu_barrier(); /* Wait for completion of call_rcu()'s */ 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci kmem_cache_destroy(rcv_cache); 91462306a36Sopenharmony_ci} 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_cimodule_init(can_init); 91762306a36Sopenharmony_cimodule_exit(can_exit); 918