static bool rpfilter_lookup_reverse(struct flowi4 *fl4, const struct net_device *dev, u8 flags) { struct fib_result res; bool dev_match; struct net *net = dev_net(dev); int ret __maybe_unused; if (fib_lookup(net, fl4, &res)) return false; if (res.type != RTN_UNICAST) { if (res.type != RTN_LOCAL || !(flags & XT_RPFILTER_ACCEPT_LOCAL)) return false; } dev_match = false; #ifdef CONFIG_IP_ROUTE_MULTIPATH for (ret = 0; ret < res.fi->fib_nhs; ret++) { struct fib_nh *nh = &res.fi->fib_nh[ret]; if (nh->nh_dev == dev) { dev_match = true; break; } } #else if (FIB_RES_DEV(res) == dev) dev_match = true; #endif if (dev_match || flags & XT_RPFILTER_LOOSE) return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST; return dev_match; }
void fib_select_default(struct net *net, const struct flowi *flp, struct fib_result *res) { struct fib_table *tb; int table = RT_TABLE_MAIN; #ifdef CONFIG_IP_MULTIPLE_TABLES if (res->r == NULL || res->r->action != FR_ACT_TO_TBL) return; table = res->r->table; #endif tb = fib_get_table(net, table); if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) tb->tb_select_default(tb, flp, res); }