root/net/decnet/dn_rules.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dn_fib_lookup
  2. dn_fib_rule_action
  3. dn_fib_rule_match
  4. dn_fib_rule_configure
  5. dn_fib_rule_compare
  6. dnet_addr_type
  7. dn_fib_rule_fill
  8. dn_fib_rule_flush_cache
  9. dn_fib_rules_init
  10. dn_fib_rules_cleanup

   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 
  38 static struct fib_rules_ops *dn_fib_rules_ops;
  39 
  40 struct 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 
  54 int 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 
  68 static 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;
 100 errout:
 101         return err;
 102 }
 103 
 104 static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
 105         FRA_GENERIC_POLICY,
 106 };
 107 
 108 static 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 
 122 static 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;
 160 errout:
 161         return err;
 162 }
 163 
 164 static 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 
 184 unsigned 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 
 202 static 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 
 218 nla_put_failure:
 219         return -ENOBUFS;
 220 }
 221 
 222 static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
 223 {
 224         dn_rt_cache_flush(-1);
 225 }
 226 
 227 static 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 
 243 void __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 
 252 void __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 }

/* [<][>][^][v][top][bottom][index][help] */