Skip to contentSkip to conversation

Updating the dead-gateway detection patch...

PATCH Philip A. Prindeville 1 participant 1 message Dec 16, 2008 2 messages not in the archive

Subsystems (5)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#2 lore raw

I've revised this patch for 2.6.26.8. Can someone please check it for correctness? (I have no easy way to test it.)

Thanks.

-Philip

include/linux/rtnetlink.h renamed from linux/include/linux/rtnetlink.h +2 -0
diff -urp v2.6.25/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
@@ -303,6 +303,8 @@ struct rtnexthop
 #define RTNH_F_DEAD		1	/* Nexthop is dead (used by multipath)	*/
 #define RTNH_F_PERVASIVE	2	/* Do recursive gateway lookup	*/
 #define RTNH_F_ONLINK		4	/* Gateway is forced on link	*/
+#define RTNH_F_SUSPECT		8	/* We don't know the real state	*/
+#define RTNH_F_BADSTATE		(RTNH_F_DEAD | RTNH_F_SUSPECT)
 
 /* Macros to handle hexthops */
 
include/net/flow.h renamed from linux/include/net/flow.h +4 -0
diff -urp v2.6.25/linux/include/net/flow.h linux/include/net/flow.h
@@ -19,6 +19,8 @@ struct flowi {
 		struct {
 			__be32			daddr;
 			__be32			saddr;
+			__be32			lsrc;
+			__be32			gw;
 			__u8			tos;
 			__u8			scope;
 		} ip4_u;
@@ -43,6 +45,8 @@ struct flowi {
 #define fl6_flowlabel	nl_u.ip6_u.flowlabel
 #define fl4_dst		nl_u.ip4_u.daddr
 #define fl4_src		nl_u.ip4_u.saddr
+#define fl4_lsrc	nl_u.ip4_u.lsrc
+#define fl4_gw		nl_u.ip4_u.gw
 #define fl4_tos		nl_u.ip4_u.tos
 #define fl4_scope	nl_u.ip4_u.scope
 
include/net/ip_fib.h renamed from linux/include/net/ip_fib.h +4 -0
diff -urp v2.6.25/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
@@ -207,6 +207,8 @@ extern int fib_lookup(struct net *n, str
 extern struct fib_table *fib_new_table(struct net *net, u32 id);
 extern struct fib_table *fib_get_table(struct net *net, u32 id);
 
+extern int fib_result_table(struct fib_result *res);
+
 #endif /* CONFIG_IP_MULTIPLE_TABLES */
 
 /* Exported by fib_frontend.c */
@@ -276,4 +278,6 @@ static inline void fib_proc_exit(struct 
 }
 #endif
 
+extern rwlock_t fib_nhflags_lock;
+
 #endif  /* _NET_FIB_H */
include/net/netfilter/nf_nat.h renamed from linux/include/net/netfilter/nf_nat.h +7 -0
diff -urp v2.6.25/linux/include/net/netfilter/nf_nat.h linux/include/net/netfilter/nf_nat.h
@@ -77,6 +77,13 @@ struct nf_conn_nat
 #endif
 };
 
+/* Call input routing for SNAT-ed traffic */
+extern unsigned int ip_nat_route_input(unsigned int hooknum,
+				       struct sk_buff *skb,
+				       const struct net_device *in,
+				       const struct net_device *out,
+				       int (*okfn)(struct sk_buff *));
+
 /* Set up the info structure to map into this range. */
 extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
 				      const struct nf_nat_range *range,
include/net/route.h renamed from linux/include/net/route.h +1 -0
diff -urp v2.6.25/linux/include/net/route.h linux/include/net/route.h
@@ -116,6 +116,7 @@
 extern int		ip_route_output_key(struct net *, struct rtable **, struct flowi *flp);
 extern int		ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
 extern int		ip_route_input(struct sk_buff*, __be32 dst, __be32 src, u8 tos, struct net_device *devin);
+extern int		ip_route_input_lookup(struct sk_buff*, __be32 dst, __be32 src, u8 tos, struct net_device *devin, __be32 lsrc);
 extern unsigned short	ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu, struct net_device *dev);
 extern void		ip_rt_send_redirect(struct sk_buff *skb);
 
net/bridge/br_netfilter.c renamed from linux/net/bridge/br_netfilter.c +4 -0
diff -urp v2.6.25/linux/net/bridge/br_netfilter.c linux/net/bridge/br_netfilter.c
@@ -325,6 +325,10 @@ static int br_nf_pre_routing_finish(stru
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 	int err;
 
+	/* Old skb->dst is not expected, it is lost in all cases */
+	dst_release(skb->dst);
+	skb->dst = NULL;
+
 	if (nf_bridge->mask & BRNF_PKT_TYPE) {
 		skb->pkt_type = PACKET_OTHERHOST;
 		nf_bridge->mask ^= BRNF_PKT_TYPE;
net/ipv4/fib_frontend.c renamed from linux/net/ipv4/fib_frontend.c +2 -0
diff -urp v2.6.25/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
@@ -49,6 +49,8 @@
 
 #ifndef CONFIG_IP_MULTIPLE_TABLES
 
+#define FIB_RES_TABLE(r) (RT_TABLE_MAIN)
 
+
 static int __net_init fib4_rules_init(struct net *net)
 {

struct fib_table *local_table, *main_table;
@@ -73,6 +75,8 @@ fail:
}
#else

+#define FIB_RES_TABLE(r) (fib_result_table(r))
+
struct fib_table *fib_new_table(struct net *net, u32 id) {
struct fib_table *tb;
@@ -127,7 +131,8 @@ void fib_select_default(struct net *net,
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)
+ if ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
+ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)
tb->tb_select_default(tb, flp, res);
}

@@ -241,6 +246,9 @@ int fib_validate_source(__be32 src, __be
.tos = tos } },
.iif = oif };
struct fib_result res;
+ int table;
+ unsigned char prefixlen;
+ unsigned char scope;
int no_addr, rpf;
int ret;
struct net *net;
@@ -264,31 +272,35 @@ int fib_validate_source(__be32 src, __be
goto e_inval_res;
*spec_dst = FIB_RES_PREFSRC(res); fib_combine_itag(itag, &res);
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
-#else
if (FIB_RES_DEV(res) == dev)
-#endif
{
ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; fib_res_put(&res);
return ret;
}
+ table = FIB_RES_TABLE(&res);
+ prefixlen = res.prefixlen;
+ scope = res.scope;
fib_res_put(&res);
if (no_addr)
goto last_resort;
- if (rpf)
- goto e_inval;
fl.oif = dev->ifindex;

ret = 0;
if (fib_lookup(net, &fl, &res) == 0) {
- if (res.type == RTN_UNICAST) {
+ if (res.type == RTN_UNICAST &&
+ ((table == FIB_RES_TABLE(&res) &&
+ res.prefixlen >= prefixlen && res.scope >= scope) ||
+ !rpf)) {
*spec_dst = FIB_RES_PREFSRC(res); ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+ fib_res_put(&res);
+ return ret;
}
fib_res_put(&res);
}
+ if (rpf)
+ goto e_inval;
return ret;

last_resort:
@@ -911,9 +923,7 @@ static int fib_inetaddr_event(struct not
switch (event) {
case NETDEV_UP:
fib_add_ifaddr(ifa);
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
fib_sync_up(ifa->ifa_dev->dev);
-#endif
rt_cache_flush(-1);
break;
case NETDEV_DOWN:
@@ -949,9 +959,7 @@ static int fib_netdev_event(struct notif
for_ifa(in_dev) {
fib_add_ifaddr(ifa);
} endfor_ifa(in_dev);
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
fib_sync_up(dev);
-#endif
rt_cache_flush(-1);
break;
case NETDEV_DOWN:

net/ipv4/fib_hash.c renamed from linux/net/ipv4/fib_hash.c +43 -17

122 lines not on this page · raw message

net/ipv4/fib_lookup.h renamed from linux/net/ipv4/fib_lookup.h +3 -1
diff -urp v2.6.25/linux/net/ipv4/fib_lookup.h linux/net/ipv4/fib_lookup.h
@@ -8,6 +8,7 @@
 struct fib_alias {
 	struct list_head	fa_list;
 	struct fib_info		*fa_info;
+	int			fa_last_dflt;
 	u8			fa_tos;
 	u8			fa_type;
 	u8			fa_scope;
@@ -38,7 +39,8 @@ extern struct fib_alias *fib_find_alias(
 					u8 tos, u32 prio);
 extern int fib_detect_death(struct fib_info *fi, int order,
 			    struct fib_info **last_resort,
-			    int *last_idx, int dflt);
+			    int *last_idx, int *dflt, int *last_nhsel,
+			    const struct flowi *flp);
 
 static inline void fib_result_assign(struct fib_result *res,
 				     struct fib_info *fi)
net/ipv4/fib_rules.c renamed from linux/net/ipv4/fib_rules.c +5 -0
diff -urp v2.6.25/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
@@ -54,6 +54,11 @@ u32 fib_rules_tclass(struct fib_result *
 }
 #endif
 
+int fib_result_table(struct fib_result *res)
+{
+	return res->r->table;
+}
+
 int fib_lookup(struct net *net, struct flowi *flp, struct fib_result *res)
 {
 	struct fib_lookup_arg arg = {
net/ipv4/fib_semantics.c renamed from linux/net/ipv4/fib_semantics.c +226 -67

436 lines not on this page · raw message

net/ipv4/netfilter/ipt_MASQUERADE.c renamed from linux/net/ipv4/netfilter/ipt_MASQUERADE.c +25 -6
diff -urp v2.6.25/linux/net/ipv4/netfilter/ipt_MASQUERADE.c linux/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -59,7 +59,7 @@ masquerade_tg(struct sk_buff *skb, const
 	enum ip_conntrack_info ctinfo;
 	struct nf_nat_range newrange;
 	const struct nf_nat_multi_range_compat *mr;
-	const struct rtable *rt;
+	struct rtable *rt;
 	__be32 newsrc;
 
 	NF_CT_ASSERT(hooknum == NF_INET_POST_ROUTING);
@@ -77,13 +77,32 @@ masquerade_tg(struct sk_buff *skb, const
 		return NF_ACCEPT;
 
 	mr = targinfo;
-	rt = skb->rtable;
-	newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
-	if (!newsrc) {
-		printk("MASQUERADE: %s ate my IP address\n", out->name);
-		return NF_DROP;
+
+	{
+		struct flowi fl = { .nl_u = { .ip4_u =
+					      { .daddr = ip_hdr(skb)->daddr,
+						.tos = (RT_TOS(ip_hdr(skb)->tos) |
+							RTO_CONN),
+						.gw = ((struct rtable *) skb->dst)->rt_gateway,
+					      } },
+				    .mark = skb->mark,
+				    .oif = out->ifindex };
+ #ifdef CONFIG_NET_NS
+		if (ip_route_output_key(out->nd_net, &rt, &fl) != 0) {
+ #else
+		if (ip_route_output_key(&init_net, &rt, &fl) != 0) {
+ #endif
+			/* Funky routing can do this. */
+			if (net_ratelimit())
+				printk("MASQUERADE:"
+				       " No route: Rusty's brain broke!\n");
+			return NF_DROP;
+		}
 	}
 
+	newsrc = rt->rt_src;
+	ip_rt_put(rt);
+
 	write_lock_bh(&masq_lock);
 	nat->masq_index = out->ifindex;
 	write_unlock_bh(&masq_lock);
net/ipv4/netfilter/nf_nat_core.c renamed from linux/net/ipv4/netfilter/nf_nat_core.c +46 -0

52 lines not on this page · raw message

net/ipv4/netfilter/nf_nat_standalone.c renamed from linux/net/ipv4/netfilter/nf_nat_standalone.c +8 -0
diff -urp v2.6.25/linux/net/ipv4/netfilter/nf_nat_standalone.c linux/net/ipv4/netfilter/nf_nat_standalone.c
@@ -282,6 +282,14 @@ static struct nf_hook_ops nf_nat_ops[] _
 		.hooknum	= NF_INET_PRE_ROUTING,
 		.priority	= NF_IP_PRI_NAT_DST,
 	},
+	/* Before routing, route before mangling */
+	{
+		.hook		= ip_nat_route_input,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_INET_PRE_ROUTING,
+		.priority	= NF_IP_PRI_LAST-1,
+	},
 	/* After packet filtering, change source */
 	{
 		.hook		= nf_nat_out,
net/ipv4/route.c renamed from linux/net/ipv4/route.c +55 -16

242 lines not on this page · raw message