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