#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;
struct cf_mod { … };
struct can_can_gw { … };
struct cgw_job { … };
#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)
{ … }
static void mod_retrieve_ccdlc(struct canfd_frame *cf)
{ … }
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)
{ … }
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)
{ … }
static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb)
{ … }
static const struct nla_policy cgw_policy[CGW_MAX + 1] = …;
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);