tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

RTF_LOCAL support



Hi List

FreeBSD and OpenBSD have added the routing flag RTF_LOCAL to indicate
the route represents a local address. They also create a local route for
each IPv4 address in a similar way to IPv6. dhcpcd and dhclient-script
do this for NetBSD as well, but it makes sense to move this into the
kernel for statically added addresses as well.

I have created a patch to do this for NetBSD which also moves the bulk
of the in6_if{add,rem}loop() functions into more generic
rt_ifa_{add,rem}local() functions and also renamed to
in6_if{add,rem}local(). in_if{add,rem}local() functions have also been
added to achieve the same functionality for IPv4.

One question though - sys/netinet/ip_carp.c has a large block of code
which looks like it handles this for IPv4. the IPv6 segment just calls
in6_{add,rem}loop(). Can this large block of code be changed to call
in_if{add,rem}local() for IPv4 or have I missed something? I don't know
anything about carp(4), hence asking.

Thanks
Roy
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.134
diff -u -p -r1.134 route.c
--- sys/net/route.c	2 Dec 2014 19:57:11 -0000	1.134
+++ sys/net/route.c	24 Feb 2015 14:00:09 -0000
@@ -986,6 +986,117 @@ rtinit(struct ifaddr *ifa, int cmd, int 
 	return error;
 }
 
+static const struct in_addr inmask32 = {.s_addr = INADDR_BROADCAST};
+/* Subrotine for rt_ifa_addlocal() and rt_ifa_remlocal() */
+static int
+rt_ifa_localrequest(int cmd, struct ifaddr *ifa)
+{
+	struct sockaddr *all1_sa;
+	struct sockaddr_in all1_sin;
+#ifdef INET6
+	struct sockaddr_in6 all1_sin6;
+#endif
+	struct rtentry *nrt = NULL;
+	int flags, e, af_add;
+
+	switch(ifa->ifa_addr->sa_family) {
+	case AF_INET:
+		sockaddr_in_init(&all1_sin, &inmask32, 0);
+		all1_sa = (struct sockaddr *)&all1_sin;
+		af_add = 1;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sockaddr_in6_init(&all1_sin6, &in6mask128, 0, 0, 0);
+		all1_sa = (struct sockaddr *)&all1_sin6;
+		/* The address will be announced when DAD completes */
+		af_add =
+		    !(((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE);
+#endif
+	default:
+		return 0;
+	}
+
+	flags = RTF_UP | RTF_HOST | RTF_LOCAL;
+	if (!(ifa->ifa_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
+		flags |= RTF_LLINFO;
+	e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr, all1_sa, flags, &nrt);
+
+	/* Make sure rt_ifa be equal to IFA, the second argument of the
+	 * function. */
+	if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa)
+		rt_replace_ifa(nrt, ifa);
+	if (nrt) {
+		if (cmd != RTM_ADD || af_add)
+			rt_newaddrmsg(cmd, ifa, e, nrt);
+		if (cmd == RTM_DELETE) {
+			if (nrt->rt_refcnt <= 0) {
+				/* XXX: we should free the entry ourselves. */
+				nrt->rt_refcnt++;
+				rtfree(nrt);
+			}
+		} else {
+			/* the cmd must be RTM_ADD here */
+			nrt->rt_refcnt--;
+		}
+	}
+	return e;
+}
+
+/* Add ownaddr as loopback rtentry. */
+int
+rt_ifa_addlocal(struct ifaddr *ifa)
+{
+	struct in_ifaddr *ia;
+	int e = 0;
+
+	ia = (struct in_ifaddr *)ifa;
+	if ((ifa->ifa_ifp->if_flags & IFF_LOOPBACK) == 0) {
+		struct rtentry *rt;
+
+		/* If there is no loopback entry, allocate one. */
+		rt = rtalloc1(ifa->ifa_addr, 0);
+		if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
+		    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
+			e = rt_ifa_localrequest(RTM_ADD, ifa);
+		if (rt != NULL)
+			rt->rt_refcnt--;
+	}
+	return e;
+}
+
+/* Rempve loopback entry of ownaddr */
+int
+rt_ifa_remlocal(struct ifaddr *ifa, struct ifaddr *alt_ifa)
+{
+	struct rtentry *rt;
+
+	if ((rt = rtalloc1(ifa->ifa_addr, 0)) == NULL)
+		return -1;
+	rt->rt_refcnt--;
+
+	/*
+	 * Before deleting, check if a corresponding loopbacked
+	 * host route surely exists.  With this check, we can avoid
+	 * deleting an interface direct route whose destination is
+	 * the same as the address being removed.  This can happen
+	 * when removing a subnet-router anycast address on an
+	 * interface attached to a shared medium.
+	 */
+	if ((rt->rt_flags & RTF_HOST) == 0 ||
+	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
+		return 0;
+
+	/* If we cannot replace the route's ifaddr with the equivalent
+	 * ifaddr of another interface, I believe it is safest to
+	 * delete the route.
+	 */
+	if (alt_ifa == NULL)
+		return rt_ifa_localrequest(RTM_DELETE, ifa);
+	rt_replace_ifa(rt, alt_ifa);
+	return 0;
+}
+
 /*
  * Route timer routines.  These routes allow functions to be called
  * for various routes at any time.  This is useful in supporting
Index: sys/net/route.h
===================================================================
RCS file: /cvsroot/src/sys/net/route.h,v
retrieving revision 1.84
diff -u -p -r1.84 route.h
--- sys/net/route.h	6 Jun 2014 01:02:47 -0000	1.84
+++ sys/net/route.h	24 Feb 2015 14:00:10 -0000
@@ -155,7 +155,7 @@ struct ortentry {
 #define RTF_PROTO1	0x8000		/* protocol specific routing flag */
 #define RTF_SRC		0x10000		/* route has fixed source address */
 #define	RTF_ANNOUNCE	0x20000		/* announce new arp or ndp entry */
-
+#define RTF_LOCAL	0x200000	/* route represents a local address */
 
 /*
  * Routing statistics.
@@ -504,6 +504,8 @@ struct rtentry *rt_lookup(rtbl_t *, cons
 struct rtentry *rt_deladdr(rtbl_t *, const struct sockaddr *,
     const struct sockaddr *);
 void rtbl_init(void);
+int rt_ifa_addlocal(struct ifaddr *);
+int rt_ifa_remlocal(struct ifaddr *, struct ifaddr *);
 rtbl_t *rt_gettable(sa_family_t);
 void rt_assert_inactive(const struct rtentry *);
 
Index: sys/netinet/if_arp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/if_arp.c,v
retrieving revision 1.160
diff -u -p -r1.160 if_arp.c
--- sys/netinet/if_arp.c	13 Nov 2014 16:11:18 -0000	1.160
+++ sys/netinet/if_arp.c	24 Feb 2015 14:00:10 -0000
@@ -453,7 +453,9 @@ arp_setgate(struct rtentry *rt, struct s
 	if ((rt->rt_flags & RTF_HOST) == 0 && netmask != NULL &&
 	    satocsin(netmask)->sin_addr.s_addr != 0xffffffff)
 		rt->rt_flags |= RTF_CLONING;
-	if (rt->rt_flags & RTF_CLONING) {
+	if (rt->rt_flags & RTF_CLONING ||
+	    ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !rt->rt_llinfo))
+	{
 		union {
 			struct sockaddr sa;
 			struct sockaddr_storage ss;
@@ -554,7 +556,9 @@ arp_rtrequest(int req, struct rtentry *r
 		break;
 	case RTM_ADD:
 		gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]);
-		if (rt->rt_flags & RTF_CLONING) {
+		if (rt->rt_flags & RTF_CLONING ||
+		    ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la))
+		{
 			/*
 			 * Give this route an expiration time, even though
 			 * it's a "permanent" route, so that routes cloned
@@ -592,7 +596,8 @@ arp_rtrequest(int req, struct rtentry *r
 			    }
 #endif
 			}
-			break;
+			if (rt->rt_flags & RTF_CLONING)
+				break;
 		}
 		/* Announce a new entry if requested. */
 		if (rt->rt_flags & RTF_ANNOUNCE) {
Index: sys/netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.149
diff -u -p -r1.149 in.c
--- sys/netinet/in.c	1 Dec 2014 17:07:43 -0000	1.149
+++ sys/netinet/in.c	24 Feb 2015 14:00:10 -0000
@@ -602,6 +602,45 @@ in_control(struct socket *so, u_long cmd
 	return error;
 }
 
+/* Add ownaddr as loopback rtentry. */
+static void
+in_ifaddlocal(struct ifaddr *ifa)
+{
+	struct in_ifaddr *ia;
+
+	ia = (struct in_ifaddr *)ifa;
+	if (ia->ia_addr.sin_addr.s_addr != INADDR_ANY &&
+	    !((ifa->ifa_ifp->if_flags & IFF_POINTOPOINT) &&
+	    ia->ia_dstaddr.sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr))
+		rt_ifa_addlocal(ifa);
+}
+
+/* Rempve loopback entry of ownaddr */
+static void
+in_ifremlocal(struct ifaddr *ifa)
+{
+	struct in_ifaddr *ia, *p;
+	struct ifaddr *alt_ifa = NULL;
+	int ia_count = 0;
+
+	ia = (struct in_ifaddr *)ifa;
+	/* Delete the entry if exactly one ifaddr matches the
+	 * address, ifa->ifa_addr. */
+	TAILQ_FOREACH(p, &in_ifaddrhead, ia_list) {
+		if (!in_hosteq(p->ia_addr.sin_addr, ia->ia_addr.sin_addr))
+			continue;
+		if (p->ia_ifp != ia->ia_ifp)
+			alt_ifa = &p->ia_ifa;
+		if (++ia_count > 1 && alt_ifa != NULL)
+			break;
+	}
+
+	if (ia_count == 0)
+		return;
+
+	rt_ifa_remlocal(ifa, ia_count == 1 ? NULL : alt_ifa);
+}
+
 void
 in_purgeaddr(struct ifaddr *ifa)
 {
@@ -609,6 +648,7 @@ in_purgeaddr(struct ifaddr *ifa)
 	struct in_ifaddr *ia = (void *) ifa;
 
 	in_ifscrub(ifp, ia);
+	in_ifremlocal(ifa);
 	LIST_REMOVE(ia, ia_hash);
 	ifa_remove(ifp, &ia->ia_ifa);
 	TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
@@ -857,6 +897,9 @@ in_ifinit(struct ifnet *ifp, struct in_i
 		ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
 	}
 
+	/* Add the local route to the address */
+	in_ifaddlocal(&ia->ia_ifa);
+
 	i = ia->ia_addr.sin_addr.s_addr;
 	if (IN_CLASSA(i))
 		ia->ia_netmask = IN_CLASSA_NET;
Index: sys/netinet/ip_carp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_carp.c,v
retrieving revision 1.59
diff -u -p -r1.59 ip_carp.c
--- sys/netinet/ip_carp.c	31 Jul 2014 02:37:25 -0000	1.59
+++ sys/netinet/ip_carp.c	24 Feb 2015 14:00:10 -0000
@@ -446,9 +446,9 @@ carp_setroute(struct carp_softc *sc, int
 #ifdef INET6
 		case AF_INET6:
 			if (cmd == RTM_ADD)
-				in6_ifaddloop(ifa);
+				in6_ifaddlocal(ifa);
 			else
-				in6_ifremloop(ifa);
+				in6_ifremlocal(ifa);
 			break;
 #endif /* INET6 */
 		default:
Index: sys/netinet6/in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.180
diff -u -p -r1.180 in6.c
--- sys/netinet6/in6.c	2 Dec 2014 19:36:58 -0000	1.180
+++ sys/netinet6/in6.c	24 Feb 2015 14:00:11 -0000
@@ -145,84 +145,6 @@ static int in6_ifinit(struct ifnet *, st
 static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
 
 /*
- * Subroutine for in6_ifaddloop() and in6_ifremloop().
- * This routine does actual work.
- */
-static void
-in6_ifloop_request(int cmd, struct ifaddr *ifa)
-{
-	struct sockaddr_in6 all1_sa;
-	struct rtentry *nrt = NULL;
-	int e;
-
-	sockaddr_in6_init(&all1_sa, &in6mask128, 0, 0, 0);
-
-	/*
-	 * We specify the address itself as the gateway, and set the
-	 * RTF_LLINFO flag, so that the corresponding host route would have
-	 * the flag, and thus applications that assume traditional behavior
-	 * would be happy.  Note that we assume the caller of the function
-	 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
-	 * which changes the outgoing interface to the loopback interface.
-	 */
-	e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
-	    (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
-	if (e != 0) {
-		log(LOG_ERR, "in6_ifloop_request: "
-		    "%s operation failed for %s (errno=%d)\n",
-		    cmd == RTM_ADD ? "ADD" : "DELETE",
-		    ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
-		    e);
-	}
-
-	/*
-	 * Make sure rt_ifa be equal to IFA, the second argument of the
-	 * function.
-	 * We need this because when we refer to rt_ifa->ia6_flags in
-	 * ip6_input, we assume that the rt_ifa points to the address instead
-	 * of the loopback address.
-	 */
-	if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa)
-		rt_replace_ifa(nrt, ifa);
-
-	/*
-	 * Report the addition/removal of the address to the routing socket
-	 * unless the address is marked tentative, where it will be reported
-	 * once DAD completes.
-	 * XXX: since we called rtinit for a p2p interface with a destination,
-	 *      we end up reporting twice in such a case.  Should we rather
-	 *      omit the second report?
-	 */
-	if (nrt) {
-		if (cmd != RTM_ADD ||
-		    !(((struct in6_ifaddr *)ifa)->ia6_flags &IN6_IFF_TENTATIVE))
-		{
-#if 0
-			struct in6_ifaddr *ia;
-
-			ia = (struct in6_ifaddr *)ifa;
-			log(LOG_DEBUG,
-			    "in6_ifloop_request: announced %s (%s %d)\n",
-			    ip6_sprintf(&ia->ia_addr.sin6_addr),
-			    cmd == RTM_ADD ? "RTM_ADD" : "RTM_DELETE",
-			    ia->ia6_flags);
-#endif
-			rt_newaddrmsg(cmd, ifa, e, nrt);
-		}
-		if (cmd == RTM_DELETE) {
-			if (nrt->rt_refcnt <= 0) {
-				/* XXX: we should free the entry ourselves. */
-				nrt->rt_refcnt++;
-				rtfree(nrt);
-			}
-		} else {
-			/* the cmd must be RTM_ADD here */
-			nrt->rt_refcnt--;
-		}
-	}
-}
-
-/*
  * Add ownaddr as loopback rtentry.  We previously add the route only if
  * necessary (ex. on a p2p link).  However, since we now manage addresses
  * separately from prefixes, we should always add the route.  We can't
@@ -230,28 +152,26 @@ in6_ifloop_request(int cmd, struct ifadd
  * any more.
  */
 void
-in6_ifaddloop(struct ifaddr *ifa)
+in6_ifaddlocal(struct ifaddr *ifa)
 {
-	struct rtentry *rt;
+	struct in6_ifaddr *ia;
 
-	/* If there is no loopback entry, allocate one. */
-	rt = rtalloc1(ifa->ifa_addr, 0);
-	if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
-	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
-		in6_ifloop_request(RTM_ADD, ifa);
-	if (rt != NULL)
-		rt->rt_refcnt--;
+	ia = (struct in6_ifaddr *)ifa;
+	if (!IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &in6addr_any) &&
+	    !((ifa->ifa_ifp->if_flags & IFF_POINTOPOINT) &&
+	    IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_dstaddr.sin6_addr)))
+		rt_ifa_addlocal(ifa);
 }
 
 /*
- * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
+ * Remove loopback rtentry of ownaddr generated by in6_ifaddlocal(),
  * if it exists.
  */
 void
-in6_ifremloop(struct ifaddr *ifa)
+in6_ifremlocal(struct ifaddr *ifa)
 {
-	struct in6_ifaddr *alt_ia = NULL, *ia;
-	struct rtentry *rt;
+	struct in6_ifaddr *ia;
+	struct ifaddr *alt_ifa = NULL;
 	int ia_count = 0;
 
 	/*
@@ -286,38 +206,14 @@ in6_ifremloop(struct ifaddr *ifa)
 		if (!IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr))
 			continue;
 		if (ia->ia_ifp != ifa->ifa_ifp)
-			alt_ia = ia;
-		if (++ia_count > 1 && alt_ia != NULL)
+			alt_ifa = &ia->ia_ifa;
+		if (++ia_count > 1 && alt_ifa != NULL)
 			break;
 	}
 
 	if (ia_count == 0)
 		return;
-
-	if ((rt = rtalloc1(ifa->ifa_addr, 0)) == NULL)
-		return;
-	rt->rt_refcnt--;
-
-	/*
-	 * Before deleting, check if a corresponding loopbacked
-	 * host route surely exists.  With this check, we can avoid
-	 * deleting an interface direct route whose destination is
-	 * the same as the address being removed.  This can happen
-	 * when removing a subnet-router anycast address on an
-	 * interface attached to a shared medium.
-	 */
-	if ((rt->rt_flags & RTF_HOST) == 0 ||
-	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
-		return;
-
-	/* If we cannot replace the route's ifaddr with the equivalent
-	 * ifaddr of another interface, I believe it is safest to
-	 * delete the route.
-	 */
-	if (ia_count == 1 || alt_ia == NULL)
-		in6_ifloop_request(RTM_DELETE, ifa);
-	else
-		rt_replace_ifa(rt, &alt_ia->ia_ifa);
+	rt_ifa_remlocal(ifa, ia_count == 1 ? NULL : alt_ifa);
 }
 
 int
@@ -1397,7 +1293,7 @@ in6_purgeaddr(struct ifaddr *ifa)
 	}
 
 	/* Remove ownaddr's loopback rtentry, if it exists. */
-	in6_ifremloop(&(ia->ia_ifa));
+	in6_ifremlocal(&(ia->ia_ifa));
 
 	/*
 	 * leave from multicast groups we have joined for the interface
@@ -1796,7 +1692,7 @@ in6_ifinit(struct ifnet *ifp, struct in6
 	if (newhost) {
 		/* set the rtrequest function to create llinfo */
 		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
-		in6_ifaddloop(&ia->ia_ifa);
+		in6_ifaddlocal(&ia->ia_ifa);
 	} else {
 		/* Inform the routing socket of new flags/timings */
 		nd6_newaddrmsg(&ia->ia_ifa);
Index: sys/netinet6/in6_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_var.h,v
retrieving revision 1.71
diff -u -p -r1.71 in6_var.h
--- sys/netinet6/in6_var.h	5 Sep 2014 06:06:31 -0000	1.71
+++ sys/netinet6/in6_var.h	24 Feb 2015 14:00:11 -0000
@@ -693,8 +693,8 @@ int	in6_if2idlen  (struct ifnet *);
 void	*in6_domifattach(struct ifnet *);
 void	in6_domifdetach(struct ifnet *, void *);
 void	in6_restoremkludge(struct in6_ifaddr *, struct ifnet *);
-void	in6_ifremloop(struct ifaddr *);
-void	in6_ifaddloop(struct ifaddr *);
+void	in6_ifremlocal(struct ifaddr *);
+void	in6_ifaddlocal(struct ifaddr *);
 void	in6_createmkludge(struct ifnet *);
 void	in6_purgemkludge(struct ifnet *);
 struct in6_ifaddr *in6ifa_ifpforlinklocal(const struct ifnet *, int);
Index: share/man/man4/route.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/route.4,v
retrieving revision 1.22
diff -u -p -r1.22 route.4
--- share/man/man4/route.4	24 May 2013 14:40:18 -0000	1.22
+++ share/man/man4/route.4	24 Feb 2015 14:00:11 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)route.4	8.6 (Berkeley) 4/19/94
 .\"
-.Dd May 21, 2013
+.Dd February 24, 2015
 .Dt ROUTE 4
 .Os
 .Sh NAME
@@ -292,22 +292,23 @@ struct rt_metrics {
 .Pp
 Flags include the values:
 .Bd -literal
-#define	RTF_UP        0x1      /* route usable */
-#define	RTF_GATEWAY   0x2      /* destination is a gateway */
-#define	RTF_HOST      0x4      /* host entry (net otherwise) */
-#define	RTF_REJECT    0x8      /* host or net unreachable */
-#define	RTF_DYNAMIC   0x10     /* created dynamically (by redirect) */
-#define	RTF_MODIFIED  0x20     /* modified dynamically (by redirect) */
-#define	RTF_DONE      0x40     /* message confirmed */
-#define	RTF_MASK      0x80     /* subnet mask present */
-#define	RTF_CLONING   0x100    /* generate new routes on use */
-#define	RTF_XRESOLVE  0x200    /* external daemon resolves name */
-#define	RTF_LLINFO    0x400    /* generated by ARP or ESIS */
-#define	RTF_STATIC    0x800    /* manually added */
-#define	RTF_BLACKHOLE 0x1000   /* just discard pkts (during updates) */
-#define	RTF_CLONED    0x2000   /* this is a cloned route */
-#define	RTF_PROTO2    0x4000   /* protocol specific routing flag */
-#define	RTF_PROTO1    0x8000   /* protocol specific routing flag */
+#define	RTF_UP        0x1       /* route usable */
+#define	RTF_GATEWAY   0x2       /* destination is a gateway */
+#define	RTF_HOST      0x4       /* host entry (net otherwise) */
+#define	RTF_REJECT    0x8       /* host or net unreachable */
+#define	RTF_DYNAMIC   0x10      /* created dynamically (by redirect) */
+#define	RTF_MODIFIED  0x20      /* modified dynamically (by redirect) */
+#define	RTF_DONE      0x40      /* message confirmed */
+#define	RTF_MASK      0x80      /* subnet mask present */
+#define	RTF_CLONING   0x100     /* generate new routes on use */
+#define	RTF_XRESOLVE  0x200     /* external daemon resolves name */
+#define	RTF_LLINFO    0x400     /* generated by ARP or ESIS */
+#define	RTF_STATIC    0x800     /* manually added */
+#define	RTF_BLACKHOLE 0x1000    /* just discard pkts (during updates) */
+#define	RTF_CLONED    0x2000    /* this is a cloned route */
+#define	RTF_PROTO2    0x4000    /* protocol specific routing flag */
+#define	RTF_PROTO1    0x8000    /* protocol specific routing flag */
+#define	RTF_LOCAL     0x200000	/* route represents a local address */
 .Ed
 .Pp
 Specifiers for metric values in rmx_locks and rtm_inits are:
Index: sbin/route/route.8
===================================================================
RCS file: /cvsroot/src/sbin/route/route.8,v
retrieving revision 1.53
diff -u -p -r1.53 route.8
--- sbin/route/route.8	1 Dec 2014 20:30:27 -0000	1.53
+++ sbin/route/route.8	24 Feb 2015 14:00:11 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)route.8	8.4 (Berkeley) 6/1/94
 .\"
-.Dd December 1, 2014
+.Dd February 24, 2015
 .Dt ROUTE 8
 .Os
 .Sh NAME
@@ -304,6 +304,7 @@ by indicating the following correspondin
 .It Li G Ta "" Ta " RTF_GATEWAY" Ta forwarded to dest by intermediary
 .It Li H Ta "" Ta " RTF_HOST" Ta host entry (net otherwise)
 .It Li L Ta -llinfo Ta " RTF_LLINFO" Ta translate proto to link addr
+.It Li l Ta "" Ta " RTF_LOCAL" Ta Route represents a local address
 .It Li M Ta "" Ta " RTF_MODIFIED" Ta modified dynamically (redirect)
 .It Li p Ta -proxy Ta " RTF_ANNOUNCE" Ta make entry a link level proxy
 .It Li R Ta -reject Ta " RTF_REJECT" Ta send ICMP unreachable on match
Index: sbin/route/rtutil.c
===================================================================
RCS file: /cvsroot/src/sbin/route/rtutil.c,v
retrieving revision 1.4
diff -u -p -r1.4 rtutil.c
--- sbin/route/rtutil.c	7 Jan 2015 22:38:32 -0000	1.4
+++ sbin/route/rtutil.c	24 Feb 2015 14:00:11 -0000
@@ -92,6 +92,7 @@ static const struct bits bits[] = {
 	{ RTF_CLONED,	'c' },
 	/* { RTF_JUMBO,	'J' }, */
 	{ RTF_ANNOUNCE,	'p' },
+	{ RTF_LOCAL, 'l'},
 	{ 0, 0 }
 };
 
Index: sbin/route/show.c
===================================================================
RCS file: /cvsroot/src/sbin/route/show.c,v
retrieving revision 1.46
diff -u -p -r1.46 show.c
--- sbin/route/show.c	6 Nov 2014 21:29:32 -0000	1.46
+++ sbin/route/show.c	24 Feb 2015 14:00:11 -0000
@@ -137,7 +137,7 @@ show(int argc, char *const *argv, int fl
 {
 	int af, rflags;
 	static int interesting = RTF_UP | RTF_GATEWAY | RTF_HOST |
-	    RTF_REJECT | RTF_LLINFO;
+	    RTF_REJECT | RTF_LLINFO | RTF_LOCAL;
 
 	parse_show_opts(argc, argv, &af, &rflags, NULL, true);
 	p_rttables(af, flags, rflags, interesting);
Index: usr.bin/netstat/netstat.1
===================================================================
RCS file: /cvsroot/src/usr.bin/netstat/netstat.1,v
retrieving revision 1.70
diff -u -p -r1.70 netstat.1
--- usr.bin/netstat/netstat.1	11 Oct 2014 09:23:32 -0000	1.70
+++ usr.bin/netstat/netstat.1	24 Feb 2015 14:00:11 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"	@(#)netstat.1	8.8 (Berkeley) 4/18/94
 .\"
-.Dd October 19, 2013
+.Dd February 24, 2015
 .Dt NETSTAT 1
 .Os
 .Sh NAME
@@ -378,6 +378,7 @@ The mapping between letters and flags is
 .It G	RTF_GATEWAY	Destination requires forwarding by intermediary
 .It H	RTF_HOST	Host entry (net otherwise)
 .It L	RTF_LLINFO	Valid protocol to link address translation.
+.It l	RTF_LOCAL	Route represents a local address
 .It M	RTF_MODIFIED	Modified dynamically (by redirect)
 .It p	RTF_ANNOUNCE	Link level proxy
 .It R	RTF_REJECT	Host or net unreachable


Home | Main Index | Thread Index | Old Index