root/net/ipv4/fib_rules.c

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

DEFINITIONS

This source file includes following definitions.
  1. fib4_rule_matchall
  2. fib4_rule_default
  3. fib4_rules_dump
  4. fib4_rules_seq_read
  5. __fib_lookup
  6. fib4_rule_action
  7. fib4_rule_suppress
  8. fib4_rule_match
  9. fib_empty_table
  10. fib4_rule_configure
  11. fib4_rule_delete
  12. fib4_rule_compare
  13. fib4_rule_fill
  14. fib4_rule_nlmsg_payload
  15. fib4_rule_flush_cache
  16. fib_default_rules_init
  17. fib4_rules_init
  18. fib4_rules_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   4  *              operating system.  INET is implemented using the  BSD Socket
   5  *              interface as the means of communication with the user level.
   6  *
   7  *              IPv4 Forwarding Information Base: policy rules.
   8  *
   9  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  10  *              Thomas Graf <tgraf@suug.ch>
  11  *
  12  * Fixes:
  13  *              Rani Assaf      :       local_rule cannot be deleted
  14  *              Marc Boucher    :       routing by fwmark
  15  */
  16 
  17 #include <linux/types.h>
  18 #include <linux/kernel.h>
  19 #include <linux/netdevice.h>
  20 #include <linux/netlink.h>
  21 #include <linux/inetdevice.h>
  22 #include <linux/init.h>
  23 #include <linux/list.h>
  24 #include <linux/rcupdate.h>
  25 #include <linux/export.h>
  26 #include <net/ip.h>
  27 #include <net/route.h>
  28 #include <net/tcp.h>
  29 #include <net/ip_fib.h>
  30 #include <net/nexthop.h>
  31 #include <net/fib_rules.h>
  32 
  33 struct fib4_rule {
  34         struct fib_rule         common;
  35         u8                      dst_len;
  36         u8                      src_len;
  37         u8                      tos;
  38         __be32                  src;
  39         __be32                  srcmask;
  40         __be32                  dst;
  41         __be32                  dstmask;
  42 #ifdef CONFIG_IP_ROUTE_CLASSID
  43         u32                     tclassid;
  44 #endif
  45 };
  46 
  47 static bool fib4_rule_matchall(const struct fib_rule *rule)
  48 {
  49         struct fib4_rule *r = container_of(rule, struct fib4_rule, common);
  50 
  51         if (r->dst_len || r->src_len || r->tos)
  52                 return false;
  53         return fib_rule_matchall(rule);
  54 }
  55 
  56 bool fib4_rule_default(const struct fib_rule *rule)
  57 {
  58         if (!fib4_rule_matchall(rule) || rule->action != FR_ACT_TO_TBL ||
  59             rule->l3mdev)
  60                 return false;
  61         if (rule->table != RT_TABLE_LOCAL && rule->table != RT_TABLE_MAIN &&
  62             rule->table != RT_TABLE_DEFAULT)
  63                 return false;
  64         return true;
  65 }
  66 EXPORT_SYMBOL_GPL(fib4_rule_default);
  67 
  68 int fib4_rules_dump(struct net *net, struct notifier_block *nb)
  69 {
  70         return fib_rules_dump(net, nb, AF_INET);
  71 }
  72 
  73 unsigned int fib4_rules_seq_read(struct net *net)
  74 {
  75         return fib_rules_seq_read(net, AF_INET);
  76 }
  77 
  78 int __fib_lookup(struct net *net, struct flowi4 *flp,
  79                  struct fib_result *res, unsigned int flags)
  80 {
  81         struct fib_lookup_arg arg = {
  82                 .result = res,
  83                 .flags = flags,
  84         };
  85         int err;
  86 
  87         /* update flow if oif or iif point to device enslaved to l3mdev */
  88         l3mdev_update_flow(net, flowi4_to_flowi(flp));
  89 
  90         err = fib_rules_lookup(net->ipv4.rules_ops, flowi4_to_flowi(flp), 0, &arg);
  91 #ifdef CONFIG_IP_ROUTE_CLASSID
  92         if (arg.rule)
  93                 res->tclassid = ((struct fib4_rule *)arg.rule)->tclassid;
  94         else
  95                 res->tclassid = 0;
  96 #endif
  97 
  98         if (err == -ESRCH)
  99                 err = -ENETUNREACH;
 100 
 101         return err;
 102 }
 103 EXPORT_SYMBOL_GPL(__fib_lookup);
 104 
 105 static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
 106                             int flags, struct fib_lookup_arg *arg)
 107 {
 108         int err = -EAGAIN;
 109         struct fib_table *tbl;
 110         u32 tb_id;
 111 
 112         switch (rule->action) {
 113         case FR_ACT_TO_TBL:
 114                 break;
 115 
 116         case FR_ACT_UNREACHABLE:
 117                 return -ENETUNREACH;
 118 
 119         case FR_ACT_PROHIBIT:
 120                 return -EACCES;
 121 
 122         case FR_ACT_BLACKHOLE:
 123         default:
 124                 return -EINVAL;
 125         }
 126 
 127         rcu_read_lock();
 128 
 129         tb_id = fib_rule_get_table(rule, arg);
 130         tbl = fib_get_table(rule->fr_net, tb_id);
 131         if (tbl)
 132                 err = fib_table_lookup(tbl, &flp->u.ip4,
 133                                        (struct fib_result *)arg->result,
 134                                        arg->flags);
 135 
 136         rcu_read_unlock();
 137         return err;
 138 }
 139 
 140 static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 141 {
 142         struct fib_result *result = (struct fib_result *) arg->result;
 143         struct net_device *dev = NULL;
 144 
 145         if (result->fi) {
 146                 struct fib_nh_common *nhc = fib_info_nhc(result->fi, 0);
 147 
 148                 dev = nhc->nhc_dev;
 149         }
 150 
 151         /* do not accept result if the route does
 152          * not meet the required prefix length
 153          */
 154         if (result->prefixlen <= rule->suppress_prefixlen)
 155                 goto suppress_route;
 156 
 157         /* do not accept result if the route uses a device
 158          * belonging to a forbidden interface group
 159          */
 160         if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
 161                 goto suppress_route;
 162 
 163         return false;
 164 
 165 suppress_route:
 166         if (!(arg->flags & FIB_LOOKUP_NOREF))
 167                 fib_info_put(result->fi);
 168         return true;
 169 }
 170 
 171 static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 172 {
 173         struct fib4_rule *r = (struct fib4_rule *) rule;
 174         struct flowi4 *fl4 = &fl->u.ip4;
 175         __be32 daddr = fl4->daddr;
 176         __be32 saddr = fl4->saddr;
 177 
 178         if (((saddr ^ r->src) & r->srcmask) ||
 179             ((daddr ^ r->dst) & r->dstmask))
 180                 return 0;
 181 
 182         if (r->tos && (r->tos != fl4->flowi4_tos))
 183                 return 0;
 184 
 185         if (rule->ip_proto && (rule->ip_proto != fl4->flowi4_proto))
 186                 return 0;
 187 
 188         if (fib_rule_port_range_set(&rule->sport_range) &&
 189             !fib_rule_port_inrange(&rule->sport_range, fl4->fl4_sport))
 190                 return 0;
 191 
 192         if (fib_rule_port_range_set(&rule->dport_range) &&
 193             !fib_rule_port_inrange(&rule->dport_range, fl4->fl4_dport))
 194                 return 0;
 195 
 196         return 1;
 197 }
 198 
 199 static struct fib_table *fib_empty_table(struct net *net)
 200 {
 201         u32 id = 1;
 202 
 203         while (1) {
 204                 if (!fib_get_table(net, id))
 205                         return fib_new_table(net, id);
 206 
 207                 if (id++ == RT_TABLE_MAX)
 208                         break;
 209         }
 210         return NULL;
 211 }
 212 
 213 static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
 214         FRA_GENERIC_POLICY,
 215         [FRA_FLOW]      = { .type = NLA_U32 },
 216 };
 217 
 218 static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
 219                                struct fib_rule_hdr *frh,
 220                                struct nlattr **tb,
 221                                struct netlink_ext_ack *extack)
 222 {
 223         struct net *net = sock_net(skb->sk);
 224         int err = -EINVAL;
 225         struct fib4_rule *rule4 = (struct fib4_rule *) rule;
 226 
 227         if (frh->tos & ~IPTOS_TOS_MASK) {
 228                 NL_SET_ERR_MSG(extack, "Invalid tos");
 229                 goto errout;
 230         }
 231 
 232         /* split local/main if they are not already split */
 233         err = fib_unmerge(net);
 234         if (err)
 235                 goto errout;
 236 
 237         if (rule->table == RT_TABLE_UNSPEC && !rule->l3mdev) {
 238                 if (rule->action == FR_ACT_TO_TBL) {
 239                         struct fib_table *table;
 240 
 241                         table = fib_empty_table(net);
 242                         if (!table) {
 243                                 err = -ENOBUFS;
 244                                 goto errout;
 245                         }
 246 
 247                         rule->table = table->tb_id;
 248                 }
 249         }
 250 
 251         if (frh->src_len)
 252                 rule4->src = nla_get_in_addr(tb[FRA_SRC]);
 253 
 254         if (frh->dst_len)
 255                 rule4->dst = nla_get_in_addr(tb[FRA_DST]);
 256 
 257 #ifdef CONFIG_IP_ROUTE_CLASSID
 258         if (tb[FRA_FLOW]) {
 259                 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
 260                 if (rule4->tclassid)
 261                         net->ipv4.fib_num_tclassid_users++;
 262         }
 263 #endif
 264 
 265         if (fib_rule_requires_fldissect(rule))
 266                 net->ipv4.fib_rules_require_fldissect++;
 267 
 268         rule4->src_len = frh->src_len;
 269         rule4->srcmask = inet_make_mask(rule4->src_len);
 270         rule4->dst_len = frh->dst_len;
 271         rule4->dstmask = inet_make_mask(rule4->dst_len);
 272         rule4->tos = frh->tos;
 273 
 274         net->ipv4.fib_has_custom_rules = true;
 275 
 276         err = 0;
 277 errout:
 278         return err;
 279 }
 280 
 281 static int fib4_rule_delete(struct fib_rule *rule)
 282 {
 283         struct net *net = rule->fr_net;
 284         int err;
 285 
 286         /* split local/main if they are not already split */
 287         err = fib_unmerge(net);
 288         if (err)
 289                 goto errout;
 290 
 291 #ifdef CONFIG_IP_ROUTE_CLASSID
 292         if (((struct fib4_rule *)rule)->tclassid)
 293                 net->ipv4.fib_num_tclassid_users--;
 294 #endif
 295         net->ipv4.fib_has_custom_rules = true;
 296 
 297         if (net->ipv4.fib_rules_require_fldissect &&
 298             fib_rule_requires_fldissect(rule))
 299                 net->ipv4.fib_rules_require_fldissect--;
 300 errout:
 301         return err;
 302 }
 303 
 304 static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
 305                              struct nlattr **tb)
 306 {
 307         struct fib4_rule *rule4 = (struct fib4_rule *) rule;
 308 
 309         if (frh->src_len && (rule4->src_len != frh->src_len))
 310                 return 0;
 311 
 312         if (frh->dst_len && (rule4->dst_len != frh->dst_len))
 313                 return 0;
 314 
 315         if (frh->tos && (rule4->tos != frh->tos))
 316                 return 0;
 317 
 318 #ifdef CONFIG_IP_ROUTE_CLASSID
 319         if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
 320                 return 0;
 321 #endif
 322 
 323         if (frh->src_len && (rule4->src != nla_get_in_addr(tb[FRA_SRC])))
 324                 return 0;
 325 
 326         if (frh->dst_len && (rule4->dst != nla_get_in_addr(tb[FRA_DST])))
 327                 return 0;
 328 
 329         return 1;
 330 }
 331 
 332 static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
 333                           struct fib_rule_hdr *frh)
 334 {
 335         struct fib4_rule *rule4 = (struct fib4_rule *) rule;
 336 
 337         frh->dst_len = rule4->dst_len;
 338         frh->src_len = rule4->src_len;
 339         frh->tos = rule4->tos;
 340 
 341         if ((rule4->dst_len &&
 342              nla_put_in_addr(skb, FRA_DST, rule4->dst)) ||
 343             (rule4->src_len &&
 344              nla_put_in_addr(skb, FRA_SRC, rule4->src)))
 345                 goto nla_put_failure;
 346 #ifdef CONFIG_IP_ROUTE_CLASSID
 347         if (rule4->tclassid &&
 348             nla_put_u32(skb, FRA_FLOW, rule4->tclassid))
 349                 goto nla_put_failure;
 350 #endif
 351         return 0;
 352 
 353 nla_put_failure:
 354         return -ENOBUFS;
 355 }
 356 
 357 static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
 358 {
 359         return nla_total_size(4) /* dst */
 360                + nla_total_size(4) /* src */
 361                + nla_total_size(4); /* flow */
 362 }
 363 
 364 static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
 365 {
 366         rt_cache_flush(ops->fro_net);
 367 }
 368 
 369 static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
 370         .family         = AF_INET,
 371         .rule_size      = sizeof(struct fib4_rule),
 372         .addr_size      = sizeof(u32),
 373         .action         = fib4_rule_action,
 374         .suppress       = fib4_rule_suppress,
 375         .match          = fib4_rule_match,
 376         .configure      = fib4_rule_configure,
 377         .delete         = fib4_rule_delete,
 378         .compare        = fib4_rule_compare,
 379         .fill           = fib4_rule_fill,
 380         .nlmsg_payload  = fib4_rule_nlmsg_payload,
 381         .flush_cache    = fib4_rule_flush_cache,
 382         .nlgroup        = RTNLGRP_IPV4_RULE,
 383         .policy         = fib4_rule_policy,
 384         .owner          = THIS_MODULE,
 385 };
 386 
 387 static int fib_default_rules_init(struct fib_rules_ops *ops)
 388 {
 389         int err;
 390 
 391         err = fib_default_rule_add(ops, 0, RT_TABLE_LOCAL, 0);
 392         if (err < 0)
 393                 return err;
 394         err = fib_default_rule_add(ops, 0x7FFE, RT_TABLE_MAIN, 0);
 395         if (err < 0)
 396                 return err;
 397         err = fib_default_rule_add(ops, 0x7FFF, RT_TABLE_DEFAULT, 0);
 398         if (err < 0)
 399                 return err;
 400         return 0;
 401 }
 402 
 403 int __net_init fib4_rules_init(struct net *net)
 404 {
 405         int err;
 406         struct fib_rules_ops *ops;
 407 
 408         ops = fib_rules_register(&fib4_rules_ops_template, net);
 409         if (IS_ERR(ops))
 410                 return PTR_ERR(ops);
 411 
 412         err = fib_default_rules_init(ops);
 413         if (err < 0)
 414                 goto fail;
 415         net->ipv4.rules_ops = ops;
 416         net->ipv4.fib_has_custom_rules = false;
 417         net->ipv4.fib_rules_require_fldissect = 0;
 418         return 0;
 419 
 420 fail:
 421         /* also cleans all rules already added */
 422         fib_rules_unregister(ops);
 423         return err;
 424 }
 425 
 426 void __net_exit fib4_rules_exit(struct net *net)
 427 {
 428         fib_rules_unregister(net->ipv4.rules_ops);
 429 }

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