Linux Audio

Check our new training course

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