Linux Audio

Check our new training course

Loading...
v5.4
  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 const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
105	FRA_GENERIC_POLICY,
106};
107
108static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
109{
110	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
111	struct flowidn *fld = &fl->u.dn;
112	__le16 daddr = fld->daddr;
113	__le16 saddr = fld->saddr;
114
115	if (((saddr ^ r->src) & r->srcmask) ||
116	    ((daddr ^ r->dst) & r->dstmask))
117		return 0;
118
119	return 1;
120}
121
122static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
123				 struct fib_rule_hdr *frh,
124				 struct nlattr **tb,
125				 struct netlink_ext_ack *extack)
126{
127	int err = -EINVAL;
128	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
129
130	if (frh->tos) {
131		NL_SET_ERR_MSG(extack, "Invalid tos value");
132		goto  errout;
133	}
134
135	if (rule->table == RT_TABLE_UNSPEC) {
136		if (rule->action == FR_ACT_TO_TBL) {
137			struct dn_fib_table *table;
138
139			table = dn_fib_empty_table();
140			if (table == NULL) {
141				err = -ENOBUFS;
142				goto errout;
143			}
144
145			rule->table = table->n;
146		}
147	}
148
149	if (frh->src_len)
150		r->src = nla_get_le16(tb[FRA_SRC]);
151
152	if (frh->dst_len)
153		r->dst = nla_get_le16(tb[FRA_DST]);
154
155	r->src_len = frh->src_len;
156	r->srcmask = dnet_make_mask(r->src_len);
157	r->dst_len = frh->dst_len;
158	r->dstmask = dnet_make_mask(r->dst_len);
159	err = 0;
160errout:
161	return err;
162}
163
164static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
165			       struct nlattr **tb)
166{
167	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
168
169	if (frh->src_len && (r->src_len != frh->src_len))
170		return 0;
171
172	if (frh->dst_len && (r->dst_len != frh->dst_len))
173		return 0;
174
175	if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC])))
176		return 0;
177
178	if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST])))
179		return 0;
180
181	return 1;
182}
183
184unsigned int dnet_addr_type(__le16 addr)
185{
186	struct flowidn fld = { .daddr = addr };
187	struct dn_fib_res res;
188	unsigned int ret = RTN_UNICAST;
189	struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
190
191	res.r = NULL;
192
193	if (tb) {
194		if (!tb->lookup(tb, &fld, &res)) {
195			ret = res.type;
196			dn_fib_res_put(&res);
197		}
198	}
199	return ret;
200}
201
202static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
203			    struct fib_rule_hdr *frh)
204{
205	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
206
207	frh->dst_len = r->dst_len;
208	frh->src_len = r->src_len;
209	frh->tos = 0;
210
211	if ((r->dst_len &&
212	     nla_put_le16(skb, FRA_DST, r->dst)) ||
213	    (r->src_len &&
214	     nla_put_le16(skb, FRA_SRC, r->src)))
215		goto nla_put_failure;
216	return 0;
217
218nla_put_failure:
219	return -ENOBUFS;
220}
221
222static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
223{
224	dn_rt_cache_flush(-1);
225}
226
227static const struct fib_rules_ops __net_initconst dn_fib_rules_ops_template = {
228	.family		= AF_DECnet,
229	.rule_size	= sizeof(struct dn_fib_rule),
230	.addr_size	= sizeof(u16),
231	.action		= dn_fib_rule_action,
232	.match		= dn_fib_rule_match,
233	.configure	= dn_fib_rule_configure,
234	.compare	= dn_fib_rule_compare,
235	.fill		= dn_fib_rule_fill,
 
236	.flush_cache	= dn_fib_rule_flush_cache,
237	.nlgroup	= RTNLGRP_DECnet_RULE,
238	.policy		= dn_fib_rule_policy,
239	.owner		= THIS_MODULE,
240	.fro_net	= &init_net,
241};
242
243void __init dn_fib_rules_init(void)
244{
245	dn_fib_rules_ops =
246		fib_rules_register(&dn_fib_rules_ops_template, &init_net);
247	BUG_ON(IS_ERR(dn_fib_rules_ops));
248	BUG_ON(fib_default_rule_add(dn_fib_rules_ops, 0x7fff,
249			            RT_TABLE_MAIN, 0));
250}
251
252void __exit dn_fib_rules_cleanup(void)
253{
254	rtnl_lock();
255	fib_rules_unregister(dn_fib_rules_ops);
256	rtnl_unlock();
257	rcu_barrier();
258}
v3.15
 
  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 <linux/export.h>
 27#include <net/neighbour.h>
 28#include <net/dst.h>
 29#include <net/flow.h>
 30#include <net/fib_rules.h>
 31#include <net/dn.h>
 32#include <net/dn_fib.h>
 33#include <net/dn_neigh.h>
 34#include <net/dn_dev.h>
 35#include <net/dn_route.h>
 36
 37static struct fib_rules_ops *dn_fib_rules_ops;
 38
 39struct dn_fib_rule
 40{
 41	struct fib_rule		common;
 42	unsigned char		dst_len;
 43	unsigned char		src_len;
 44	__le16			src;
 45	__le16			srcmask;
 46	__le16			dst;
 47	__le16			dstmask;
 48	__le16			srcmap;
 49	u8			flags;
 50};
 51
 52
 53int dn_fib_lookup(struct flowidn *flp, struct dn_fib_res *res)
 54{
 55	struct fib_lookup_arg arg = {
 56		.result = res,
 57	};
 58	int err;
 59
 60	err = fib_rules_lookup(dn_fib_rules_ops,
 61			       flowidn_to_flowi(flp), 0, &arg);
 62	res->r = arg.rule;
 63
 64	return err;
 65}
 66
 67static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
 68			      int flags, struct fib_lookup_arg *arg)
 69{
 70	struct flowidn *fld = &flp->u.dn;
 71	int err = -EAGAIN;
 72	struct dn_fib_table *tbl;
 73
 74	switch(rule->action) {
 75	case FR_ACT_TO_TBL:
 76		break;
 77
 78	case FR_ACT_UNREACHABLE:
 79		err = -ENETUNREACH;
 80		goto errout;
 81
 82	case FR_ACT_PROHIBIT:
 83		err = -EACCES;
 84		goto errout;
 85
 86	case FR_ACT_BLACKHOLE:
 87	default:
 88		err = -EINVAL;
 89		goto errout;
 90	}
 91
 92	tbl = dn_fib_get_table(rule->table, 0);
 93	if (tbl == NULL)
 94		goto errout;
 95
 96	err = tbl->lookup(tbl, fld, (struct dn_fib_res *)arg->result);
 97	if (err > 0)
 98		err = -EAGAIN;
 99errout:
100	return err;
101}
102
103static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
104	FRA_GENERIC_POLICY,
105};
106
107static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
108{
109	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
110	struct flowidn *fld = &fl->u.dn;
111	__le16 daddr = fld->daddr;
112	__le16 saddr = fld->saddr;
113
114	if (((saddr ^ r->src) & r->srcmask) ||
115	    ((daddr ^ r->dst) & r->dstmask))
116		return 0;
117
118	return 1;
119}
120
121static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
122				 struct fib_rule_hdr *frh,
123				 struct nlattr **tb)
 
124{
125	int err = -EINVAL;
126	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
127
128	if (frh->tos)
 
129		goto  errout;
 
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	.default_pref	= fib_default_rule_pref,
233	.flush_cache	= dn_fib_rule_flush_cache,
234	.nlgroup	= RTNLGRP_DECnet_RULE,
235	.policy		= dn_fib_rule_policy,
236	.owner		= THIS_MODULE,
237	.fro_net	= &init_net,
238};
239
240void __init dn_fib_rules_init(void)
241{
242	dn_fib_rules_ops =
243		fib_rules_register(&dn_fib_rules_ops_template, &init_net);
244	BUG_ON(IS_ERR(dn_fib_rules_ops));
245	BUG_ON(fib_default_rule_add(dn_fib_rules_ops, 0x7fff,
246			            RT_TABLE_MAIN, 0));
247}
248
249void __exit dn_fib_rules_cleanup(void)
250{
 
251	fib_rules_unregister(dn_fib_rules_ops);
 
252	rcu_barrier();
253}
254
255