Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Sep 2004 03:19:58 +0200
From:      Max Laier <max@love2party.net>
To:        freebsd-net@freebsd.org
Subject:   Re: route to host on same network
Message-ID:  <200409140319.58203.max@love2party.net>
In-Reply-To: <m2r7p5bqyr.wl@minion.local.neville-neil.com>
References:  <20040913171931.GA5368@zibbi.icomtek.csir.co.za> <m2r7p5bqyr.wl@minion.local.neville-neil.com>

next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_+ckRB4GdcGWp4fa
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Tuesday 14 September 2004 03:05, George V. Neville-Neil wrote:
> At Mon, 13 Sep 2004 19:19:31 +0200,
>
> John Hay wrote:
> > Hi,
> >
> > I'm busy trying to port mobilemesh
> > (www.mitre.org/tech_transfer/mobilemesh) to FreeBSD and run into a
> > problem.
> >
> > The way mobilemesh works is that you use a subnet for the wireless
> > network and then it use host routes to route packets to hosts that are
> > not directly visible. Say for instance that you have hosts 1, 2 and 3
> > on the 10.0.0.0/24 subnet and machines 1 and 3 can't directly see each
> > other, but both can see host 2, then the mobilemesh routing protocol
> > will try to add a host route to the other machine through host 2. On
> > host 1 it will do something like "route add 10.0.0.3 10.0.0.2" and
> > on host 3 it will do "route add 10.0.0.1 10.0.0.2". This seems to work
> > on Linux (where mobilemesh was developed), but I have been unable to
> > get it to work on FreeBSD. I have also tried various ways with and
> > without -interface and -iface, but none works. Is it supposed to be
> > possible in FreeBSD and if so does someone know how?
>
> What "doesn't work" as in what error, if any, do you get?  Or does it
> just silently fail?  Also, what does your routing table look like
> before and after the commands (netstat -rn).

I assume you get: 17 EEXIST "File exists" ...

... if that's the case, can you try the attached patch (originally done for 
the CARP import) and tell me if it works for this? I have yet to check all 
the side-effects of this, but it might help.

[ http://people.freebsd.org/~mlaier/in.c.patch ]

Thank you for reporting back!

-- 
/"\  Best regards,                      | mlaier@freebsd.org
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | mlaier@EFnet
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News

--Boundary-00=_+ckRB4GdcGWp4fa
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="in.c.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="in.c.patch"

Index: in.c
===================================================================
RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/in.c,v
retrieving revision 1.77
diff -u -r1.77 in.c
--- in.c	16 Aug 2004 18:32:07 -0000	1.77
+++ in.c	14 Sep 2004 01:16:12 -0000
@@ -1,4 +1,32 @@
 /*
+ * Copyright (C) 2001 WIDE Project.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
  * Copyright (c) 1982, 1986, 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -55,6 +83,8 @@
 static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
 	struct ifnet *, struct thread *);
 
+static int	in_addprefix(struct in_ifaddr *, int);
+static int	in_scrubprefix(struct in_ifaddr *);
 static void	in_socktrim(struct sockaddr_in *);
 static int	in_ifinit(struct ifnet *,
 	    struct in_ifaddr *, struct sockaddr_in *, int);
@@ -654,14 +684,7 @@
 	register struct ifnet *ifp;
 	register struct in_ifaddr *ia;
 {
-
-	if ((ia->ia_flags & IFA_ROUTE) == 0)
-		return;
-	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
-		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
-	else
-		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
-	ia->ia_flags &= ~IFA_ROUTE;
+	in_scrubprefix(ia);
 }
 
 /*
@@ -743,26 +766,7 @@
 			return (0);
 		flags |= RTF_HOST;
 	}
-
-	/*-
-	 * Don't add host routes for interface addresses of
-	 * 0.0.0.0 --> 0.255.255.255 netmask 255.0.0.0.  This makes it
-	 * possible to assign several such address pairs with consistent
-	 * results (no host route) and is required by BOOTP.
-	 *
-	 * XXX: This is ugly !  There should be a way for the caller to
-	 *      say that they don't want a host route.
-	 */
-	if (ia->ia_addr.sin_addr.s_addr != INADDR_ANY ||
-	    ia->ia_netmask != IN_CLASSA_NET ||
-	    ia->ia_dstaddr.sin_addr.s_addr != htonl(IN_CLASSA_HOST)) {
-		if ((error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags)) != 0) {
-			ia->ia_addr = oldaddr;
-			return (error);
-		}
-		ia->ia_flags |= IFA_ROUTE;
-	}
-
+	error = in_addprefix(ia, flags);
 	/*
 	 * If the interface supports multicast, join the "all hosts"
 	 * multicast group on that interface.
@@ -776,6 +780,120 @@
 	return (error);
 }
 
+#define rtinitflags(x) \
+	((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
+	    ? RTF_HOST : 0)
+/*
+ * add a route to prefix ("connected route" in cisco terminology).
+ * does nothing if there's some interface address with the same prefix already.
+ */
+static int
+in_addprefix(target, flags)
+	struct in_ifaddr *target;
+	int flags;
+{
+	struct in_ifaddr *ia;
+	struct in_addr prefix, mask, p;
+	int error;
+
+	if ((flags & RTF_HOST) != 0)
+		prefix = target->ia_dstaddr.sin_addr;
+	else {
+		prefix = target->ia_addr.sin_addr;
+		mask = target->ia_sockmask.sin_addr;
+		prefix.s_addr &= mask.s_addr;
+	}
+
+/*	for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { */
+	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
+			if (rtinitflags(ia))
+			p = ia->ia_dstaddr.sin_addr;
+		else {
+			p = ia->ia_addr.sin_addr;
+			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
+		}
+
+		if (prefix.s_addr != p.s_addr)
+			continue;
+
+		/*
+		 * if we got a matching prefix route inserted by other
+		 * interface adderss, we don't need to bother
+		 */
+		if (ia->ia_flags & IFA_ROUTE)
+			return 0;
+	}
+
+	/*
+	 * noone seem to have prefix route.  insert it.
+	 */
+	error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
+	if (!error)
+		target->ia_flags |= IFA_ROUTE;
+	return error;
+}
+
+/*
+ * remove a route to prefix ("connected route" in cisco terminology).
+ * re-installs the route by using another interface address, if there's one
+ * with the same prefix (otherwise we lose the route mistakenly).
+ */
+static int
+in_scrubprefix(target)
+	struct in_ifaddr *target;
+{
+	struct in_ifaddr *ia;
+	struct in_addr prefix, mask, p;
+	int error;
+
+	if ((target->ia_flags & IFA_ROUTE) == 0)
+		return 0;
+
+	if (rtinitflags(target))
+		prefix = target->ia_dstaddr.sin_addr;
+	else {
+		prefix = target->ia_addr.sin_addr;
+		mask = target->ia_sockmask.sin_addr;
+		prefix.s_addr &= mask.s_addr;
+	}
+
+/*	for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { */
+	TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
+		if (rtinitflags(ia))
+			p = ia->ia_dstaddr.sin_addr;
+		else {
+			p = ia->ia_addr.sin_addr;
+			p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
+		}
+
+		if (prefix.s_addr != p.s_addr)
+			continue;
+
+		/*
+		 * if we got a matching prefix route, move IFA_ROUTE to him
+		 */
+		if ((ia->ia_flags & IFA_ROUTE) == 0) {
+			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
+			    rtinitflags(target));
+			target->ia_flags &= ~IFA_ROUTE;
+
+			error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
+			    rtinitflags(ia) | RTF_UP);
+			if (error == 0)
+				ia->ia_flags |= IFA_ROUTE;
+			return error;
+		}
+	}
+
+	/*
+	 * noone seem to have prefix route.  remove it.
+	 */
+	rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
+	target->ia_flags &= ~IFA_ROUTE;
+	return 0;
+}
+
+#undef rtinitflags
 
 /*
  * Return 1 if the address might be a local broadcast address.

--Boundary-00=_+ckRB4GdcGWp4fa--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200409140319.58203.max>