cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dn_rules.c (5549B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 * DECnet       An implementation of the DECnet protocol suite for the LINUX
      5 *              operating system.  DECnet is implemented using the  BSD Socket
      6 *              interface as the means of communication with the user level.
      7 *
      8 *              DECnet Routing Forwarding Information Base (Rules)
      9 *
     10 * Author:      Steve Whitehouse <SteveW@ACM.org>
     11 *              Mostly copied from Alexey Kuznetsov's ipv4/fib_rules.c
     12 *
     13 *
     14 * Changes:
     15 *              Steve Whitehouse <steve@chygwyn.com>
     16 *              Updated for Thomas Graf's generic rules
     17 *
     18 */
     19#include <linux/net.h>
     20#include <linux/init.h>
     21#include <linux/netlink.h>
     22#include <linux/rtnetlink.h>
     23#include <linux/netdevice.h>
     24#include <linux/spinlock.h>
     25#include <linux/list.h>
     26#include <linux/rcupdate.h>
     27#include <linux/export.h>
     28#include <net/neighbour.h>
     29#include <net/dst.h>
     30#include <net/flow.h>
     31#include <net/fib_rules.h>
     32#include <net/dn.h>
     33#include <net/dn_fib.h>
     34#include <net/dn_neigh.h>
     35#include <net/dn_dev.h>
     36#include <net/dn_route.h>
     37
     38static struct fib_rules_ops *dn_fib_rules_ops;
     39
     40struct dn_fib_rule
     41{
     42	struct fib_rule		common;
     43	unsigned char		dst_len;
     44	unsigned char		src_len;
     45	__le16			src;
     46	__le16			srcmask;
     47	__le16			dst;
     48	__le16			dstmask;
     49	__le16			srcmap;
     50	u8			flags;
     51};
     52
     53
     54int dn_fib_lookup(struct flowidn *flp, struct dn_fib_res *res)
     55{
     56	struct fib_lookup_arg arg = {
     57		.result = res,
     58	};
     59	int err;
     60
     61	err = fib_rules_lookup(dn_fib_rules_ops,
     62			       flowidn_to_flowi(flp), 0, &arg);
     63	res->r = arg.rule;
     64
     65	return err;
     66}
     67
     68static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
     69			      int flags, struct fib_lookup_arg *arg)
     70{
     71	struct flowidn *fld = &flp->u.dn;
     72	int err = -EAGAIN;
     73	struct dn_fib_table *tbl;
     74
     75	switch(rule->action) {
     76	case FR_ACT_TO_TBL:
     77		break;
     78
     79	case FR_ACT_UNREACHABLE:
     80		err = -ENETUNREACH;
     81		goto errout;
     82
     83	case FR_ACT_PROHIBIT:
     84		err = -EACCES;
     85		goto errout;
     86
     87	case FR_ACT_BLACKHOLE:
     88	default:
     89		err = -EINVAL;
     90		goto errout;
     91	}
     92
     93	tbl = dn_fib_get_table(rule->table, 0);
     94	if (tbl == NULL)
     95		goto errout;
     96
     97	err = tbl->lookup(tbl, fld, (struct dn_fib_res *)arg->result);
     98	if (err > 0)
     99		err = -EAGAIN;
    100errout:
    101	return err;
    102}
    103
    104static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
    105{
    106	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
    107	struct flowidn *fld = &fl->u.dn;
    108	__le16 daddr = fld->daddr;
    109	__le16 saddr = fld->saddr;
    110
    111	if (((saddr ^ r->src) & r->srcmask) ||
    112	    ((daddr ^ r->dst) & r->dstmask))
    113		return 0;
    114
    115	return 1;
    116}
    117
    118static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
    119				 struct fib_rule_hdr *frh,
    120				 struct nlattr **tb,
    121				 struct netlink_ext_ack *extack)
    122{
    123	int err = -EINVAL;
    124	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
    125
    126	if (frh->tos) {
    127		NL_SET_ERR_MSG(extack, "Invalid tos value");
    128		goto  errout;
    129	}
    130
    131	if (rule->table == RT_TABLE_UNSPEC) {
    132		if (rule->action == FR_ACT_TO_TBL) {
    133			struct dn_fib_table *table;
    134
    135			table = dn_fib_empty_table();
    136			if (table == NULL) {
    137				err = -ENOBUFS;
    138				goto errout;
    139			}
    140
    141			rule->table = table->n;
    142		}
    143	}
    144
    145	if (frh->src_len)
    146		r->src = nla_get_le16(tb[FRA_SRC]);
    147
    148	if (frh->dst_len)
    149		r->dst = nla_get_le16(tb[FRA_DST]);
    150
    151	r->src_len = frh->src_len;
    152	r->srcmask = dnet_make_mask(r->src_len);
    153	r->dst_len = frh->dst_len;
    154	r->dstmask = dnet_make_mask(r->dst_len);
    155	err = 0;
    156errout:
    157	return err;
    158}
    159
    160static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
    161			       struct nlattr **tb)
    162{
    163	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
    164
    165	if (frh->src_len && (r->src_len != frh->src_len))
    166		return 0;
    167
    168	if (frh->dst_len && (r->dst_len != frh->dst_len))
    169		return 0;
    170
    171	if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC])))
    172		return 0;
    173
    174	if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST])))
    175		return 0;
    176
    177	return 1;
    178}
    179
    180unsigned int dnet_addr_type(__le16 addr)
    181{
    182	struct flowidn fld = { .daddr = addr };
    183	struct dn_fib_res res;
    184	unsigned int ret = RTN_UNICAST;
    185	struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
    186
    187	res.r = NULL;
    188
    189	if (tb) {
    190		if (!tb->lookup(tb, &fld, &res)) {
    191			ret = res.type;
    192			dn_fib_res_put(&res);
    193		}
    194	}
    195	return ret;
    196}
    197
    198static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
    199			    struct fib_rule_hdr *frh)
    200{
    201	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
    202
    203	frh->dst_len = r->dst_len;
    204	frh->src_len = r->src_len;
    205	frh->tos = 0;
    206
    207	if ((r->dst_len &&
    208	     nla_put_le16(skb, FRA_DST, r->dst)) ||
    209	    (r->src_len &&
    210	     nla_put_le16(skb, FRA_SRC, r->src)))
    211		goto nla_put_failure;
    212	return 0;
    213
    214nla_put_failure:
    215	return -ENOBUFS;
    216}
    217
    218static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
    219{
    220	dn_rt_cache_flush(-1);
    221}
    222
    223static const struct fib_rules_ops __net_initconst dn_fib_rules_ops_template = {
    224	.family		= AF_DECnet,
    225	.rule_size	= sizeof(struct dn_fib_rule),
    226	.addr_size	= sizeof(u16),
    227	.action		= dn_fib_rule_action,
    228	.match		= dn_fib_rule_match,
    229	.configure	= dn_fib_rule_configure,
    230	.compare	= dn_fib_rule_compare,
    231	.fill		= dn_fib_rule_fill,
    232	.flush_cache	= dn_fib_rule_flush_cache,
    233	.nlgroup	= RTNLGRP_DECnet_RULE,
    234	.owner		= THIS_MODULE,
    235	.fro_net	= &init_net,
    236};
    237
    238void __init dn_fib_rules_init(void)
    239{
    240	dn_fib_rules_ops =
    241		fib_rules_register(&dn_fib_rules_ops_template, &init_net);
    242	BUG_ON(IS_ERR(dn_fib_rules_ops));
    243	BUG_ON(fib_default_rule_add(dn_fib_rules_ops, 0x7fff,
    244			            RT_TABLE_MAIN, 0));
    245}
    246
    247void __exit dn_fib_rules_cleanup(void)
    248{
    249	rtnl_lock();
    250	fib_rules_unregister(dn_fib_rules_ops);
    251	rtnl_unlock();
    252	rcu_barrier();
    253}