Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * INET     An implementation of the TCP/IP protocol suite for the LINUX
0004  *      operating system.  INET is implemented using the  BSD Socket
0005  *      interface as the means of communication with the user level.
0006  *
0007  *      IPv4 Forwarding Information Base: policy rules.
0008  *
0009  * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
0010  *      Thomas Graf <tgraf@suug.ch>
0011  *
0012  * Fixes:
0013  *      Rani Assaf  :   local_rule cannot be deleted
0014  *      Marc Boucher    :   routing by fwmark
0015  */
0016 
0017 #include <linux/types.h>
0018 #include <linux/kernel.h>
0019 #include <linux/netdevice.h>
0020 #include <linux/netlink.h>
0021 #include <linux/inetdevice.h>
0022 #include <linux/init.h>
0023 #include <linux/list.h>
0024 #include <linux/rcupdate.h>
0025 #include <linux/export.h>
0026 #include <net/inet_dscp.h>
0027 #include <net/ip.h>
0028 #include <net/route.h>
0029 #include <net/tcp.h>
0030 #include <net/ip_fib.h>
0031 #include <net/nexthop.h>
0032 #include <net/fib_rules.h>
0033 #include <linux/indirect_call_wrapper.h>
0034 
0035 struct fib4_rule {
0036     struct fib_rule     common;
0037     u8          dst_len;
0038     u8          src_len;
0039     dscp_t          dscp;
0040     __be32          src;
0041     __be32          srcmask;
0042     __be32          dst;
0043     __be32          dstmask;
0044 #ifdef CONFIG_IP_ROUTE_CLASSID
0045     u32         tclassid;
0046 #endif
0047 };
0048 
0049 static bool fib4_rule_matchall(const struct fib_rule *rule)
0050 {
0051     struct fib4_rule *r = container_of(rule, struct fib4_rule, common);
0052 
0053     if (r->dst_len || r->src_len || r->dscp)
0054         return false;
0055     return fib_rule_matchall(rule);
0056 }
0057 
0058 bool fib4_rule_default(const struct fib_rule *rule)
0059 {
0060     if (!fib4_rule_matchall(rule) || rule->action != FR_ACT_TO_TBL ||
0061         rule->l3mdev)
0062         return false;
0063     if (rule->table != RT_TABLE_LOCAL && rule->table != RT_TABLE_MAIN &&
0064         rule->table != RT_TABLE_DEFAULT)
0065         return false;
0066     return true;
0067 }
0068 EXPORT_SYMBOL_GPL(fib4_rule_default);
0069 
0070 int fib4_rules_dump(struct net *net, struct notifier_block *nb,
0071             struct netlink_ext_ack *extack)
0072 {
0073     return fib_rules_dump(net, nb, AF_INET, extack);
0074 }
0075 
0076 unsigned int fib4_rules_seq_read(struct net *net)
0077 {
0078     return fib_rules_seq_read(net, AF_INET);
0079 }
0080 
0081 int __fib_lookup(struct net *net, struct flowi4 *flp,
0082          struct fib_result *res, unsigned int flags)
0083 {
0084     struct fib_lookup_arg arg = {
0085         .result = res,
0086         .flags = flags,
0087     };
0088     int err;
0089 
0090     /* update flow if oif or iif point to device enslaved to l3mdev */
0091     l3mdev_update_flow(net, flowi4_to_flowi(flp));
0092 
0093     err = fib_rules_lookup(net->ipv4.rules_ops, flowi4_to_flowi(flp), 0, &arg);
0094 #ifdef CONFIG_IP_ROUTE_CLASSID
0095     if (arg.rule)
0096         res->tclassid = ((struct fib4_rule *)arg.rule)->tclassid;
0097     else
0098         res->tclassid = 0;
0099 #endif
0100 
0101     if (err == -ESRCH)
0102         err = -ENETUNREACH;
0103 
0104     return err;
0105 }
0106 EXPORT_SYMBOL_GPL(__fib_lookup);
0107 
0108 INDIRECT_CALLABLE_SCOPE int fib4_rule_action(struct fib_rule *rule,
0109                          struct flowi *flp, int flags,
0110                          struct fib_lookup_arg *arg)
0111 {
0112     int err = -EAGAIN;
0113     struct fib_table *tbl;
0114     u32 tb_id;
0115 
0116     switch (rule->action) {
0117     case FR_ACT_TO_TBL:
0118         break;
0119 
0120     case FR_ACT_UNREACHABLE:
0121         return -ENETUNREACH;
0122 
0123     case FR_ACT_PROHIBIT:
0124         return -EACCES;
0125 
0126     case FR_ACT_BLACKHOLE:
0127     default:
0128         return -EINVAL;
0129     }
0130 
0131     rcu_read_lock();
0132 
0133     tb_id = fib_rule_get_table(rule, arg);
0134     tbl = fib_get_table(rule->fr_net, tb_id);
0135     if (tbl)
0136         err = fib_table_lookup(tbl, &flp->u.ip4,
0137                        (struct fib_result *)arg->result,
0138                        arg->flags);
0139 
0140     rcu_read_unlock();
0141     return err;
0142 }
0143 
0144 INDIRECT_CALLABLE_SCOPE bool fib4_rule_suppress(struct fib_rule *rule,
0145                         int flags,
0146                         struct fib_lookup_arg *arg)
0147 {
0148     struct fib_result *result = arg->result;
0149     struct net_device *dev = NULL;
0150 
0151     if (result->fi) {
0152         struct fib_nh_common *nhc = fib_info_nhc(result->fi, 0);
0153 
0154         dev = nhc->nhc_dev;
0155     }
0156 
0157     /* do not accept result if the route does
0158      * not meet the required prefix length
0159      */
0160     if (result->prefixlen <= rule->suppress_prefixlen)
0161         goto suppress_route;
0162 
0163     /* do not accept result if the route uses a device
0164      * belonging to a forbidden interface group
0165      */
0166     if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
0167         goto suppress_route;
0168 
0169     return false;
0170 
0171 suppress_route:
0172     if (!(arg->flags & FIB_LOOKUP_NOREF))
0173         fib_info_put(result->fi);
0174     return true;
0175 }
0176 
0177 INDIRECT_CALLABLE_SCOPE int fib4_rule_match(struct fib_rule *rule,
0178                         struct flowi *fl, int flags)
0179 {
0180     struct fib4_rule *r = (struct fib4_rule *) rule;
0181     struct flowi4 *fl4 = &fl->u.ip4;
0182     __be32 daddr = fl4->daddr;
0183     __be32 saddr = fl4->saddr;
0184 
0185     if (((saddr ^ r->src) & r->srcmask) ||
0186         ((daddr ^ r->dst) & r->dstmask))
0187         return 0;
0188 
0189     if (r->dscp && r->dscp != inet_dsfield_to_dscp(fl4->flowi4_tos))
0190         return 0;
0191 
0192     if (rule->ip_proto && (rule->ip_proto != fl4->flowi4_proto))
0193         return 0;
0194 
0195     if (fib_rule_port_range_set(&rule->sport_range) &&
0196         !fib_rule_port_inrange(&rule->sport_range, fl4->fl4_sport))
0197         return 0;
0198 
0199     if (fib_rule_port_range_set(&rule->dport_range) &&
0200         !fib_rule_port_inrange(&rule->dport_range, fl4->fl4_dport))
0201         return 0;
0202 
0203     return 1;
0204 }
0205 
0206 static struct fib_table *fib_empty_table(struct net *net)
0207 {
0208     u32 id = 1;
0209 
0210     while (1) {
0211         if (!fib_get_table(net, id))
0212             return fib_new_table(net, id);
0213 
0214         if (id++ == RT_TABLE_MAX)
0215             break;
0216     }
0217     return NULL;
0218 }
0219 
0220 static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
0221                    struct fib_rule_hdr *frh,
0222                    struct nlattr **tb,
0223                    struct netlink_ext_ack *extack)
0224 {
0225     struct net *net = sock_net(skb->sk);
0226     int err = -EINVAL;
0227     struct fib4_rule *rule4 = (struct fib4_rule *) rule;
0228 
0229     if (!inet_validate_dscp(frh->tos)) {
0230         NL_SET_ERR_MSG(extack,
0231                    "Invalid dsfield (tos): ECN bits must be 0");
0232         goto errout;
0233     }
0234     /* IPv4 currently doesn't handle high order DSCP bits correctly */
0235     if (frh->tos & ~IPTOS_TOS_MASK) {
0236         NL_SET_ERR_MSG(extack, "Invalid tos");
0237         goto errout;
0238     }
0239     rule4->dscp = inet_dsfield_to_dscp(frh->tos);
0240 
0241     /* split local/main if they are not already split */
0242     err = fib_unmerge(net);
0243     if (err)
0244         goto errout;
0245 
0246     if (rule->table == RT_TABLE_UNSPEC && !rule->l3mdev) {
0247         if (rule->action == FR_ACT_TO_TBL) {
0248             struct fib_table *table;
0249 
0250             table = fib_empty_table(net);
0251             if (!table) {
0252                 err = -ENOBUFS;
0253                 goto errout;
0254             }
0255 
0256             rule->table = table->tb_id;
0257         }
0258     }
0259 
0260     if (frh->src_len)
0261         rule4->src = nla_get_in_addr(tb[FRA_SRC]);
0262 
0263     if (frh->dst_len)
0264         rule4->dst = nla_get_in_addr(tb[FRA_DST]);
0265 
0266 #ifdef CONFIG_IP_ROUTE_CLASSID
0267     if (tb[FRA_FLOW]) {
0268         rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
0269         if (rule4->tclassid)
0270             atomic_inc(&net->ipv4.fib_num_tclassid_users);
0271     }
0272 #endif
0273 
0274     if (fib_rule_requires_fldissect(rule))
0275         net->ipv4.fib_rules_require_fldissect++;
0276 
0277     rule4->src_len = frh->src_len;
0278     rule4->srcmask = inet_make_mask(rule4->src_len);
0279     rule4->dst_len = frh->dst_len;
0280     rule4->dstmask = inet_make_mask(rule4->dst_len);
0281 
0282     net->ipv4.fib_has_custom_rules = true;
0283 
0284     err = 0;
0285 errout:
0286     return err;
0287 }
0288 
0289 static int fib4_rule_delete(struct fib_rule *rule)
0290 {
0291     struct net *net = rule->fr_net;
0292     int err;
0293 
0294     /* split local/main if they are not already split */
0295     err = fib_unmerge(net);
0296     if (err)
0297         goto errout;
0298 
0299 #ifdef CONFIG_IP_ROUTE_CLASSID
0300     if (((struct fib4_rule *)rule)->tclassid)
0301         atomic_dec(&net->ipv4.fib_num_tclassid_users);
0302 #endif
0303     net->ipv4.fib_has_custom_rules = true;
0304 
0305     if (net->ipv4.fib_rules_require_fldissect &&
0306         fib_rule_requires_fldissect(rule))
0307         net->ipv4.fib_rules_require_fldissect--;
0308 errout:
0309     return err;
0310 }
0311 
0312 static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
0313                  struct nlattr **tb)
0314 {
0315     struct fib4_rule *rule4 = (struct fib4_rule *) rule;
0316 
0317     if (frh->src_len && (rule4->src_len != frh->src_len))
0318         return 0;
0319 
0320     if (frh->dst_len && (rule4->dst_len != frh->dst_len))
0321         return 0;
0322 
0323     if (frh->tos && inet_dscp_to_dsfield(rule4->dscp) != frh->tos)
0324         return 0;
0325 
0326 #ifdef CONFIG_IP_ROUTE_CLASSID
0327     if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
0328         return 0;
0329 #endif
0330 
0331     if (frh->src_len && (rule4->src != nla_get_in_addr(tb[FRA_SRC])))
0332         return 0;
0333 
0334     if (frh->dst_len && (rule4->dst != nla_get_in_addr(tb[FRA_DST])))
0335         return 0;
0336 
0337     return 1;
0338 }
0339 
0340 static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
0341               struct fib_rule_hdr *frh)
0342 {
0343     struct fib4_rule *rule4 = (struct fib4_rule *) rule;
0344 
0345     frh->dst_len = rule4->dst_len;
0346     frh->src_len = rule4->src_len;
0347     frh->tos = inet_dscp_to_dsfield(rule4->dscp);
0348 
0349     if ((rule4->dst_len &&
0350          nla_put_in_addr(skb, FRA_DST, rule4->dst)) ||
0351         (rule4->src_len &&
0352          nla_put_in_addr(skb, FRA_SRC, rule4->src)))
0353         goto nla_put_failure;
0354 #ifdef CONFIG_IP_ROUTE_CLASSID
0355     if (rule4->tclassid &&
0356         nla_put_u32(skb, FRA_FLOW, rule4->tclassid))
0357         goto nla_put_failure;
0358 #endif
0359     return 0;
0360 
0361 nla_put_failure:
0362     return -ENOBUFS;
0363 }
0364 
0365 static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
0366 {
0367     return nla_total_size(4) /* dst */
0368            + nla_total_size(4) /* src */
0369            + nla_total_size(4); /* flow */
0370 }
0371 
0372 static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
0373 {
0374     rt_cache_flush(ops->fro_net);
0375 }
0376 
0377 static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
0378     .family     = AF_INET,
0379     .rule_size  = sizeof(struct fib4_rule),
0380     .addr_size  = sizeof(u32),
0381     .action     = fib4_rule_action,
0382     .suppress   = fib4_rule_suppress,
0383     .match      = fib4_rule_match,
0384     .configure  = fib4_rule_configure,
0385     .delete     = fib4_rule_delete,
0386     .compare    = fib4_rule_compare,
0387     .fill       = fib4_rule_fill,
0388     .nlmsg_payload  = fib4_rule_nlmsg_payload,
0389     .flush_cache    = fib4_rule_flush_cache,
0390     .nlgroup    = RTNLGRP_IPV4_RULE,
0391     .owner      = THIS_MODULE,
0392 };
0393 
0394 static int fib_default_rules_init(struct fib_rules_ops *ops)
0395 {
0396     int err;
0397 
0398     err = fib_default_rule_add(ops, 0, RT_TABLE_LOCAL, 0);
0399     if (err < 0)
0400         return err;
0401     err = fib_default_rule_add(ops, 0x7FFE, RT_TABLE_MAIN, 0);
0402     if (err < 0)
0403         return err;
0404     err = fib_default_rule_add(ops, 0x7FFF, RT_TABLE_DEFAULT, 0);
0405     if (err < 0)
0406         return err;
0407     return 0;
0408 }
0409 
0410 int __net_init fib4_rules_init(struct net *net)
0411 {
0412     int err;
0413     struct fib_rules_ops *ops;
0414 
0415     ops = fib_rules_register(&fib4_rules_ops_template, net);
0416     if (IS_ERR(ops))
0417         return PTR_ERR(ops);
0418 
0419     err = fib_default_rules_init(ops);
0420     if (err < 0)
0421         goto fail;
0422     net->ipv4.rules_ops = ops;
0423     net->ipv4.fib_has_custom_rules = false;
0424     net->ipv4.fib_rules_require_fldissect = 0;
0425     return 0;
0426 
0427 fail:
0428     /* also cleans all rules already added */
0429     fib_rules_unregister(ops);
0430     return err;
0431 }
0432 
0433 void __net_exit fib4_rules_exit(struct net *net)
0434 {
0435     fib_rules_unregister(net->ipv4.rules_ops);
0436 }