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