函数fib_check_nh检测下一跳的合法性。

int fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope, struct netlink_ext_ack *extack)
{int err;if (nh->fib_nh_gw_family == AF_INET)err = fib_check_nh_v4_gw(net, nh, table, scope, extack);else if (nh->fib_nh_gw_family == AF_INET6)err = fib_check_nh_v6_gw(net, nh, table, extack);elseerr = fib_check_nh_nongw(net, nh, extack);

IPv4下一跳检查

内核代码中注释内容显示了下一跳网关检查的4种情况:

* a) gateway can be actually local interface address, so that gatewayed route is direct.网关可以是本地接口上的地址,所以目的网络是直连的。
* b) gateway must be on-link address, possibly described not by an ifaddr, but also by a direct route.网关必须是链路可达地址,可以不是和接口地址同网段,或是直连路由可达。
* c) If both gateway and interface are specified, they should not contradict.如果同时指定了网关和出接口,两者不能冲突。
* d) If we use tunnel routes, gateway could be not on-link.如果使用隧道路由,网关可以不是链路可达地址(需指定onlink命令字)。

如下路由配置:

# /a/
# ip address
4: ens35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:ea:2e:3b brd ff:ff:ff:ff:ff:ffinet 192.168.10.2/32 scope global ens35valid_lft forever preferred_lft forever
#
# ip route add 192.168.10.0/24 via 192.168.10.2
# ip route add 192.168.5.0/24 via 192.168.10.2
#
# ip route list
192.168.5.0/24 via 192.168.10.2 dev ens35
192.168.10.0/24 via 192.168.10.2 dev ens35
#
# /c/
# ip route add 192.168.7.0/24 via 192.168.10.2 dev ens35
#
# /d/
# ip route add 10.10.1.0/24 via 192.168.10.1 dev ens35 onlink

先看一下onlink路由的配置,由于指定了错误scope值,IP命令配置路由时返回以下错误:

# ip route add 10.10.1.0/24 via 192.168.10.1 scope 255 onlink
Error: Invalid scope.
#
# ip route add 10.10.1.0/24 via 192.168.10.1 scope host onlink
Error: Route with host scope can not have a gateway.

如下在fib_create_info中的代码,如果scope值大于RT_SCOPE_HOST(254),就认为是不合法的scope值,即到达目的网络最近的就是RT_SCOPE_HOST。另外,如果scope值等于RT_SCOPE_HOST,不能指定路由网关。

struct fib_info *fib_create_info(struct fib_config *cfg, struct netlink_ext_ack *extack)
{if (cfg->fc_scope > RT_SCOPE_HOST) {     /* RT_SCOPE_HOST */NL_SET_ERR_MSG(extack, "Invalid scope");goto err_inval;}if (fi->nh) {...} else if (cfg->fc_scope == RT_SCOPE_HOST) {struct fib_nh *nh = fi->fib_nh;/* Local address is added. */if (nhs != 1) {NL_SET_ERR_MSG(extack, "Route with host scope can not have multiple nexthops");goto err_inval;}if (nh->fib_nh_gw_family) {NL_SET_ERR_MSG(extack, "Route with host scope can not have a gateway");goto err_inval;}

以下IP命令将触发内核函数fib_check_nh_v4_gw中的错误检查,对于当前链路路由(RTNH_F_ONLINK),如下所示:

# ip addr add 192.168.10.2/32 dev ens35
#
# ip route add 10.10.1.0/24 via 192.168.10.1 scope 253 onlink
Error: Nexthop has invalid scope.
#
# ip route add 10.10.1.0/24 via 192.168.10.1 onlink
Error: Nexthop device required for onlink.
#
# ip route add 10.10.1.0/24 via 192.168.10.1 dev ens35 onlink
Error: Nexthop device is not up.
#
# ip route add 10.10.1.0/24 via 192.168.10.1 dev ens35
Error: Nexthop has invalid gateway.

IP命令的onlink关键字对于与内核代码中的标志位RTNH_F_ONLINK,那么scope值不应大于等于RT_SCOPE_LINK。如果scope值等于RT_SCOPE_LINK,或者更大的值RT_SCOPE_HOST,就没有必要指定onlink命令字。

static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table, u8 scope, struct netlink_ext_ack *extack)
{if (nh->fib_nh_flags & RTNH_F_ONLINK) {unsigned int addr_type;if (scope >= RT_SCOPE_LINK) {NL_SET_ERR_MSG(extack, "Nexthop has invalid scope");return -EINVAL;}dev = __dev_get_by_index(net, nh->fib_nh_oif);if (!dev) {NL_SET_ERR_MSG(extack, "Nexthop device required for onlink");return -ENODEV;}if (!(dev->flags & IFF_UP)) {NL_SET_ERR_MSG(extack, "Nexthop device is not up");return -ENETDOWN;}addr_type = inet_addr_type_dev_table(net, dev, nh->fib_nh_gw4);if (addr_type != RTN_UNICAST) {NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");return -EINVAL;}if (!netif_carrier_ok(dev))nh->fib_nh_flags |= RTNH_F_LINKDOWN;nh->fib_nh_dev = dev;dev_hold(dev);nh->fib_nh_scope = RT_SCOPE_LINK;return 0;}

以下为没有指定onlink关键字的情况(通常情况不指定),需要验证网关的可达性。对于可达网关,其scope应当等于RT_SCOPE_LINK或者RT_SCOPE_HOST,以下路由查询获取到达网关的路由,将scope的最小值限定在RT_SCOPE_LINK值。

如果指定了路由表(非主路由表),在其中进行路由查询;否则,未指定路由表,或者以上查询失败的情况下,在主路由表和本地路由表中(RT_TABLE_MAIN/RT_TABLE_LOCAL)进行查询。

    {struct fib_table *tbl = NULL;struct flowi4 fl4 = {.daddr = nh->fib_nh_gw4,.flowi4_scope = scope + 1,.flowi4_oif = nh->fib_nh_oif,.flowi4_iif = LOOPBACK_IFINDEX,};/* It is not necessary, but requires a bit of thinking */if (fl4.flowi4_scope < RT_SCOPE_LINK)fl4.flowi4_scope = RT_SCOPE_LINK;if (table && table != RT_TABLE_MAIN)tbl = fib_get_table(net, table);if (tbl)err = fib_table_lookup(tbl, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE | FIB_LOOKUP_NOREF);/* on error or if no table given do full lookup. This* is needed for example when nexthops are in the local* table rather than the given table*/if (!tbl || err) {err = fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE);}if (err) {NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");goto out;}}

合法的网关路由类型需要是单播类型(RTN_UNICAST)或者本地类型(RTN_LOCAL),否则为无效网关。如果路由查询结果的出接口为空,返回错误。最后,根据出口设备的链路状态设置下一跳结构的状态位。

    err = -EINVAL;if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) {NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");goto out;}nh->fib_nh_scope = res.scope;nh->fib_nh_oif = FIB_RES_OIF(res);nh->fib_nh_dev = dev = FIB_RES_DEV(res);if (!dev) {NL_SET_ERR_MSG(extack, "No egress device for nexthop gateway");goto out;}dev_hold(dev);if (!netif_carrier_ok(dev))nh->fib_nh_flags |= RTNH_F_LINKDOWN;err = (dev->flags & IFF_UP) ? 0 : -ENETDOWN;

另外,fl4结构成员flowi4_scope的值等于参数scope+1,例如scope值为RT_SCOPE_LINK,增加1之后变成RT_SCOPE_HOST。即对于RT_SCOPE_LINK类型的路由网关,要求查询到的到网关的路由的scope值小于大于等于RT_SCOPE_HOST。参见在路由查询函数fib_table_lookup中,对flowi4_scope的判断。

对于scope为RT_SCOPE_HOST的情况,不需要网关。对于scope为RT_SCOPE_NOWHERE(255)的情况,增加1之后为0,对于小于RT_SCOPE_LINK的scope,都按照RT_SCOPE_NOWHERE进行路由查询。

int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, struct fib_result *res, int fib_flags)
{/* Step 3: Process the leaf, if that fails fall back to backtracing */hlist_for_each_entry_rcu(fa, &n->leaf, fa_list) {struct fib_info *fi = fa->fa_info;if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)continue;if (fi->fib_dead)continue;if (fa->fa_info->fib_scope < flp->flowi4_scope)continue;

未设置网关下一跳检查

以下IP命令配置无网关的路由项:

# ip route add 192.168.30.0/24 dev ens35 onlink
Error: Invalid flags for nexthop - PERVASIVE and ONLINK can not be set.
#
# ip route add 192.168.30.0/24 dev ens35
Error: Device for nexthop is not up.

对于未配置网关的路由,不能设置RTNH_F_PERVASIVE或者RTNH_F_ONLINK标志,前者用于递归查找网关,或者用于指定网关在本地链路上。未配置网关的路由项需要指定出口设备,如果出口设备没有启用,返回错误。

static int fib_check_nh_nongw(struct net *net, struct fib_nh *nh, struct netlink_ext_ack *extack)
{struct in_device *in_dev;int err;if (nh->fib_nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK)) {NL_SET_ERR_MSG(extack, "Invalid flags for nexthop - PERVASIVE and ONLINK can not be set");return -EINVAL;}rcu_read_lock();err = -ENODEV;in_dev = inetdev_by_index(net, nh->fib_nh_oif);if (!in_dev)goto out;err = -ENETDOWN;if (!(in_dev->dev->flags & IFF_UP)) {NL_SET_ERR_MSG(extack, "Device for nexthop is not up");goto out;}nh->fib_nh_dev = in_dev->dev;dev_hold(nh->fib_nh_dev);nh->fib_nh_scope = RT_SCOPE_HOST;if (!netif_carrier_ok(nh->fib_nh_dev))nh->fib_nh_flags |= RTNH_F_LINKDOWN;

内核版本 5.10

IPv4路由下一跳合法性检测相关推荐

  1. 配置静态路由下一跳为本地出战接口和IP地址的区别

    配置静态路由下一跳为本地出战接口和IP地址的区别 在配置静态路由时,下一跳可以使用下一路由器的IP地址,也可以使用本路由器的出站接口.在点对点的网络中,两者可能没有什么差别,但在以太网中或者NBMA网 ...

  2. 【数通网络交换基础梳理2】三层设备、网关、ARP表、VLAN、路由表及跨网段路由下一跳转发原理

    一.不同网段如何通讯 同网段可以依靠二层交换机通讯,网络中存在多个网段192.168.1.1/24 172.16.1.1/24 173.73.1.1/24情况下如何互相通讯?上节留一下的问题,这节继续 ...

  3. h3c 虚拟服务器 下一跳,H3CNE 312题和313题 直连路由静态路由的下一跳问题

    321.在MSR 路由器上看到路由表里有如下显示: Destination/Mask Proto Pre Cost NextHop Interface 127.0.0.0/8 Direct 0 0 1 ...

  4. BGP邻居特性及下一跳如何建立 学习笔记

    两台路由器运行bgp建立任何邻居之前,会先交互tcp的三个报文 ,三次握手做完之后建成一个基于tcp的 信道,基于信道就开始邻居关系建立,只用交互一个open报文 .主要包括路由信的身份标识 ,rou ...

  5. IPv4路由cache统计信息

    内核定义如下的每处理器结构rt_cache_stat记录路由缓存信息. struct rt_cache_stat {unsigned int in_slow_tot;unsigned int in_s ...

  6. CCNP精粹系列之三十二--BGP下一跳问题,推荐

                       Bgp的下一跳 R1:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:off ...

  7. 路由器下一跳地址怎么判断_CCNP-路由器工作原理

    好物要写,我们的文章也不能断更,赚钱重要,学习新知识更重要,今天就是进入NP阶段的内容了,我们会深入理解每个动态路由协议的工作原理,以及一些策略方面的配置,至此你就能随心所欲控制路由的走向,让他走你所 ...

  8. 路由nexthop下一跳blackhole属性

    以下添加blackhole属性的nexthop及相关路由. # ip -6 nexthop add id 1 blackhole # # ip nexthop id 1 blackhole # # i ...

  9. 配置静态路由使用出站接口和下一跳IP的差别

    在配置静态路由时,下一跳可以使用下一路由器的IP地址,也可以使用本路由器的出站接口.在点对点的网络中,两者可能没有什么差别,但在以太网中,两者有很大差别.         在以太网中,两个相邻接口之间 ...

最新文章

  1. HTML5中常见的列表标签包括,介绍几个常用的HTML5标签
  2. WordPress电子商务博客源码
  3. 2019 年最好用的 7 款数据库监控工具
  4. Maven学习总结(39)——Maven私服的搭建及使用deploy命令部署构建问题汇总
  5. Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
  6. HDX RealTime 避免回音
  7. 解决从PDF复制到Word中的英文字母变成宋体格式的问题
  8. html+css+js实现小游戏flybird(完整版)
  9. m个苹果放在n个盘子里面有多少种放法?(动态规划)
  10. matlab怎么画函数线,请问matlab怎么画常数函数,比如同时画x=300和x=400这两条线...
  11. Arthas线上问题定位神器
  12. 西瓜中视频是如何赚钱的?教你提高视频收益的3个方法!
  13. 获取android模拟器的IP地址
  14. 三位数求最大公因数c语言,求最大公因数的三种算法
  15. 开关柜绝缘状态检测与故障诊断
  16. Julia实现GCC-PHAT算法
  17. MAC盗版软件下载网站黑名单
  18. 拨乱反正!关于LoRaWAN的7个常见误解
  19. 免费算力平台——九天毕昇
  20. 服务器npc修改,梦幻古龙服务端NPC对话修改工具与教程

热门文章

  1. 松柏先生·每日一例:卖的不止是面包,而是一种生活方式
  2. css自适应屏幕教程,WordPress主题css适配屏幕尺寸大小自适应教程
  3. 前端实现纯css文本显示省略号
  4. 查看linux时间和时区,Linux查看时区和时间
  5. 剑灵力士卡刀ahk_用AutoHotkey帮朋友写一份卡刀软件,不清楚力士卡刀数据,帮个忙....
  6. 中兴PON设备通过MEF认证
  7. 【python日用】for表达式[列表推导式]
  8. 国内券商转型迎来新风口——港股市场的火热「微观篇」
  9. 新理念计算机英语,《新理念英语》English For You
  10. 互联网时代即时通讯软件的利与弊