new "fromarp" route flag
Subsystems (2)
PATCH 1/1 new "fromarp" route flag
The following patch implements a new route flag, "fromarp".
Problem description:
--------------------
Zeroconf hardware automatically assigns an ip address from the link local range (169.254.1.0 - 169.254.254.255). This ip addresses don't get routed and are local to the interfaces. To address such a component, one can add a link local route:
ip route add 169.254.0.0/16 dev eth0
Things get ugly if a host is multihomed and zeroconf hardware is conected to more than one interface. It is not possible to add a route in that case.
Solution:
---------
My patch adds a new route flag, "fromarp", to the kernel. Example:
ip route add 169.254.0.0/16 fromarp nexthop dev eth0 nexthop dev eth1
If a packet is to be send with such a route, the kernel checks the arp cache of the interfaces specified in the route. If a match is found, the packet is send to the matching interface. Otherwise an arp request is sent from all of the interfaces.
Comments anyone?
include/linux/in_route.h renamed from include/linux/in_route.h.orig +1 -0
@@ -18,6 +18,7 @@#define RTCF_MASQ 0x00400000#define RTCF_SNAT 0x00800000#define RTCF_DOREDIRECT 0x01000000 +#define RTCF_FROMARP 0x02000000#define RTCF_DIRECTSRC 0x04000000#define RTCF_DNAT 0x08000000#define RTCF_BROADCAST 0x10000000
include/linux/rtnetlink.h renamed from include/linux/rtnetlink.h.orig +1 -0
@@ -170,6 +170,7 @@#define RTM_F_CLONED 0x200/* This route is cloned */ #define RTM_F_EQUALIZE 0x400/* Multipath equalizer: NI */ #define RTM_F_PREFIX 0x800/* Prefix addresses */ +#define RTM_F_FROMARP 0x1000/* Select if from arpcache */ /* Reserved table identifiers */
net/ipv4/arp.c renamed from net/ipv4/arp.c.orig +6 -0
@@ -952,6 +952,12 @@return 0 ; } +struct neighbour *arp_lookup (u32 ip,struct net_device *dev,int creat) +{ +return __neigh_lookup (&arp_tbl, &ip, dev, creat); +} + +/* * User level interface (ioctl) */
net/ipv4/fib_semantics.c renamed from net/ipv4/fib_semantics.c.orig +48 -0
52 lines not on this page · raw message
net/ipv4/route.c renamed from net/ipv4/route.c.orig +22 -6
@@ -1332,7 +1332,9 @@ {struct rtable *rt; -icmp_send (skb,ICMP_DEST_UNREACH ,ICMP_HOST_UNREACH ,0 ); + rt = (struct rtable *) skb->dst; +if (!rt || !(rt->rt_flags &RTCF_FROMARP )) +icmp_send (skb,ICMP_DEST_UNREACH ,ICMP_HOST_UNREACH ,0 ); rt = (struct rtable *) skb->dst;if (rt)
@@ -2077,9 +2079,13 @@ }#ifdef CONFIG_IP_ROUTE_MULTIPATH -if (res.fi->fib_nhs >1 && fl.oif ==0 ) -fib_select_multipath (&fl, &res); - else +if (res.fi->fib_nhs >1 && fl.oif ==0 ) { +if (res.fi->fib_flags &RTM_F_FROMARP ) { +if (!fib_select_fromarp (&fl, &res)) + flags |=RTCF_FROMARP ; + }else +fib_select_multipath (&fl, &res); + }#endif if (!res.prefixlen && res.type ==RTN_UNICAST && !fl.oif)fib_select_default (&fl, &res);
@@ -2190,8 +2196,18 @@ rth->rt_flags = flags; - hash =rt_hash_code (oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif <<5 ), tos); - err =rt_intern_hash (hash, rth, rp); +if (flags &RTCF_FROMARP ) { + err =0 ; +if (rth->rt_type ==RTN_UNICAST || rth->fl.iif ==0 ) { +if ((err =arp_bind_neighbour (&rth->u.dst)) !=0 ) +rt_drop (rth); + } +if (!err) + *rp = rth; + }else { + hash =rt_hash_code (oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif <<5 ), tos); + err =rt_intern_hash (hash, rth, rp); + } done:if (free_res)fib_res_put (&res);
Cheers,
Michael.
Signature · 2 lines
Michael Schroeder [email protected] main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}