linux/net/can/gw.c

// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/* gw.c - CAN frame Gateway/Router/Bridge with netlink interface
 *
 * Copyright (c) 2019 Volkswagen Group Electronic Research
 * 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>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/rculist.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
#include <linux/can/skb.h>
#include <linux/can/gw.h>
#include <net/rtnetlink.h>
#include <net/net_namespace.h>
#include <net/sock.h>

#define CAN_GW_NAME

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_ALIAS();

#define CGW_MIN_HOPS
#define CGW_MAX_HOPS
#define CGW_DEFAULT_HOPS

static unsigned int max_hops __read_mostly =;
module_param(max_hops, uint, 0444);
MODULE_PARM_DESC();

static struct notifier_block notifier;
static struct kmem_cache *cgw_cache __read_mostly;

/* structure that contains the (on-the-fly) CAN frame modifications */
struct cf_mod {};

/* So far we just support CAN -> CAN routing and frame modifications.
 *
 * The internal can_can_gw structure contains data and attributes for
 * a CAN -> CAN gateway job.
 */
struct can_can_gw {};

/* list entry for CAN gateways jobs */
struct cgw_job {};

/* modification functions that are invoked in the hot path in can_can_gw_rcv */

#define MODFUNC(func, op)

MODFUNC(mod_and_id, cf->can_id &= mod->modframe.and.can_id)
MODFUNC(mod_and_len, cf->len &= mod->modframe.and.len)
MODFUNC(mod_and_flags, cf->flags &= mod->modframe.and.flags)
MODFUNC(mod_and_data, *(u64 *)cf->data &= *(u64 *)mod->modframe.and.data)
MODFUNC(mod_or_id, cf->can_id |= mod->modframe.or.can_id)
MODFUNC(mod_or_len, cf->len |= mod->modframe.or.len)
MODFUNC(mod_or_flags, cf->flags |= mod->modframe.or.flags)
MODFUNC(mod_or_data, *(u64 *)cf->data |= *(u64 *)mod->modframe.or.data)
MODFUNC(mod_xor_id, cf->can_id ^= mod->modframe.xor.can_id)
MODFUNC(mod_xor_len, cf->len ^= mod->modframe.xor.len)
MODFUNC(mod_xor_flags, cf->flags ^= mod->modframe.xor.flags)
MODFUNC(mod_xor_data, *(u64 *)cf->data ^= *(u64 *)mod->modframe.xor.data)
MODFUNC(mod_set_id, cf->can_id = mod->modframe.set.can_id)
MODFUNC(mod_set_len, cf->len = mod->modframe.set.len)
MODFUNC(mod_set_flags, cf->flags = mod->modframe.set.flags)
MODFUNC(mod_set_data, *(u64 *)cf->data = *(u64 *)mod->modframe.set.data)

static void mod_and_fddata(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void mod_or_fddata(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void mod_xor_fddata(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void mod_set_fddata(struct canfd_frame *cf, struct cf_mod *mod)
{}

/* retrieve valid CC DLC value and store it into 'len' */
static void mod_retrieve_ccdlc(struct canfd_frame *cf)
{}

/* convert valid CC DLC value in 'len' into struct can_frame elements */
static void mod_store_ccdlc(struct canfd_frame *cf)
{}

static void mod_and_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void mod_or_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void mod_xor_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void mod_set_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
{}

static void canframecpy(struct canfd_frame *dst, struct can_frame *src)
{}

static void canfdframecpy(struct canfd_frame *dst, struct canfd_frame *src)
{}

static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re, struct rtcanmsg *r)
{}

static inline int calc_idx(int idx, int rx_len)
{}

static void cgw_csum_xor_rel(struct canfd_frame *cf, struct cgw_csum_xor *xor)
{}

static void cgw_csum_xor_pos(struct canfd_frame *cf, struct cgw_csum_xor *xor)
{}

static void cgw_csum_xor_neg(struct canfd_frame *cf, struct cgw_csum_xor *xor)
{}

static void cgw_csum_crc8_rel(struct canfd_frame *cf,
			      struct cgw_csum_crc8 *crc8)
{}

static void cgw_csum_crc8_pos(struct canfd_frame *cf,
			      struct cgw_csum_crc8 *crc8)
{}

static void cgw_csum_crc8_neg(struct canfd_frame *cf,
			      struct cgw_csum_crc8 *crc8)
{}

/* the receive & process & send function */
static void can_can_gw_rcv(struct sk_buff *skb, void *data)
{}

static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
{}

static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)
{}

static void cgw_job_free_rcu(struct rcu_head *rcu_head)
{}

static int cgw_notifier(struct notifier_block *nb,
			unsigned long msg, void *ptr)
{}

static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
		       u32 pid, u32 seq, int flags)
{}

/* Dump information about all CAN gateway jobs, in response to RTM_GETROUTE */
static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb)
{}

static const struct nla_policy cgw_policy[CGW_MAX + 1] =;

/* check for common and gwtype specific attributes */
static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
			  u8 gwtype, void *gwtypeattr, u8 *limhops)
{}

static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
			  struct netlink_ext_ack *extack)
{}

static void cgw_remove_all_jobs(struct net *net)
{}

static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
			  struct netlink_ext_ack *extack)
{}

static int __net_init cangw_pernet_init(struct net *net)
{}

static void __net_exit cangw_pernet_exit_batch(struct list_head *net_list)
{}

static struct pernet_operations cangw_pernet_ops =;

static __init int cgw_module_init(void)
{}

static __exit void cgw_module_exit(void)
{}

module_init();
module_exit(cgw_module_exit);