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.1
 
  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