Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Oct 2004 00:38:58 -0700
From:      Bruce M Simpson <bms@spc.org>
To:        freebsd-net@freebsd.org
Subject:   Implementing IP_SENDIF (like SO_BINDTODEVICE)
Message-ID:  <20041027073858.GC719@empiric.icir.org>

next in thread | raw e-mail | index | archive | help

--mojUlQ0s9EVzWg2t
Content-Type: multipart/mixed; boundary="RnlQjJ0d97Da+TV1"
Content-Disposition: inline


--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

It annoys me that we have to resort to BPF to send IP datagrams on
unnumbered interfaces. Here is a half baked idea. Please look and
tell me what you think.

--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ip_sendif_rev1.patch"
Content-Transfer-Encoding: quoted-printable

Adding IP_SENDIF (like Linux's SO_BINDTODEVICE) support to FreeBSD.
Clean up the RFC 1724 hack in ip_output.c

TODO:

Add IP_SENDIF processing to ip_ctloutput.
Move inp_depend6.inp6_ifindex into general inpcb structure.
Update #define.
Pass IP_ROUTETOIF flag to ip_output() from udp and rawip.
Pass inp_ifindex to ip_output() as destination from udp and rawip.

Index: src/sys/netinet/ip_output.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.225.2.4
diff -u -p -r1.225.2.4 ip_output.c
--- src/sys/netinet/ip_output.c	22 Sep 2004 19:23:38 -0000	1.225.2.4
+++ src/sys/netinet/ip_output.c	27 Oct 2004 07:27:24 -0000
@@ -93,7 +93,7 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_
 #endif
=20
 static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *);
-static struct ifnet *ip_multicast_if(struct in_addr *, int *);
+static struct ifnet *ina_to_rfc1724_if(struct in_addr *, int *);
 static void	ip_mloopback
 	(struct ifnet *, struct mbuf *, struct sockaddr_in *, int);
 static int	ip_getmoptions
@@ -206,19 +206,30 @@ again:
 		dst->sin_addr =3D ip->ip_dst;
 	}
 	/*
-	 * If routing to interface only,
-	 * short circuit routing lookup.
+	 * If routing to interface only, short circuit routing lookup.
+	 *
+	 * Assume the destination is either the destination end of a
+	 * point-to-point interface, the network address of an interface,
+	 * or the address of an interface itself. In the last case, an
+	 * interface may be specified by index as per RFC 1724.
+	 *=20
 	 */
 	if (flags & IP_ROUTETOIF) {
-		if ((ia =3D ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) =3D=3D NULL &&
-		    (ia =3D ifatoia(ifa_ifwithnet(sintosa(dst)))) =3D=3D NULL) {
+		ia =3D ifatoia(ifa_ifwithdstaddr(sintosa(dst)));
+		if (ia =3D=3D NULL)
+			ia =3D ifatoia(ifa_ifwithnet(sintosa(dst)));
+		if (ia !=3D NULL)
+			ifp =3D ia->ia_ifp;
+		else
+			ifp =3D ina_to_rfc1724_if(&dst->sin_addr, NULL);
+		if (ifp =3D=3D NULL) {
 			ipstat.ips_noroute++;
 			error =3D ENETUNREACH;
 			goto bad;
 		}
-		ifp =3D ia->ia_ifp;
 		ip->ip_ttl =3D 1;
-		isbroadcast =3D in_broadcast(dst->sin_addr, ifp);
+		isbroadcast =3D (flags & IP_SENDONES) |
+			      in_broadcast(dst->sin_addr, ifp);
 	} else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
 	    imo !=3D NULL && imo->imo_multicast_ifp !=3D NULL) {
 		/*
@@ -1531,11 +1542,15 @@ bad:
  * standard option (IP_TTL).
  */
=20
+#define	INADDR_IFINDEX_MASK	0x00FFFFFF		/* 0.0.0.0/8 */
+
 /*
- * following RFC1724 section 3.3, 0.0.0.0/8 is interpreted as interface in=
dex.
+ * Look up the ifnet corresponding to a given IPv4 host address, taking the
+ * RFC1724 hack into account. If the address given has the network prefix
+ * 0.0.0.0/8, interpret the host portion as an interface index.
  */
 static struct ifnet *
-ip_multicast_if(a, ifindexp)
+ina_to_rfc1724_if(a, ifindexp)
 	struct in_addr *a;
 	int *ifindexp;
 {
@@ -1544,8 +1559,8 @@ ip_multicast_if(a, ifindexp)
=20
 	if (ifindexp)
 		*ifindexp =3D 0;
-	if (ntohl(a->s_addr) >> 24 =3D=3D 0) {
-		ifindex =3D ntohl(a->s_addr) & 0xffffff;
+	if ((ntohl(a->s_addr) & ~INADDR_IFINDEX_MASK) =3D=3D 0) {
+		ifindex =3D ntohl(a->s_addr) & 0x00FFFFFF;
 		if (ifindex < 0 || if_index < ifindex)
 			return NULL;
 		ifp =3D ifnet_byindex(ifindex);
@@ -1554,7 +1569,7 @@ ip_multicast_if(a, ifindexp)
 	} else {
 		INADDR_TO_IFP(*a, ifp);
 	}
-	return ifp;
+	return (ifp);
 }
=20
 /*
@@ -1634,7 +1649,7 @@ ip_setmoptions(sopt, imop)
 		 * it supports multicasting.
 		 */
 		s =3D splimp();
-		ifp =3D ip_multicast_if(&addr, &ifindex);
+		ifp =3D ina_to_rfc1724_if(&addr, &ifindex);
 		if (ifp =3D=3D NULL || (ifp->if_flags & IFF_MULTICAST) =3D=3D 0) {
 			splx(s);
 			error =3D EADDRNOTAVAIL;
@@ -1731,7 +1746,7 @@ ip_setmoptions(sopt, imop)
 			RTFREE(ro.ro_rt);
 		}
 		else {
-			ifp =3D ip_multicast_if(&mreq.imr_interface, NULL);
+			ifp =3D ina_to_rfc1724_if(&mreq.imr_interface, NULL);
 		}
=20
 		/*
@@ -1799,7 +1814,7 @@ ip_setmoptions(sopt, imop)
 		if (mreq.imr_interface.s_addr =3D=3D INADDR_ANY)
 			ifp =3D NULL;
 		else {
-			ifp =3D ip_multicast_if(&mreq.imr_interface, NULL);
+			ifp =3D ina_to_rfc1724_if(&mreq.imr_interface, NULL);
 			if (ifp =3D=3D NULL) {
 				error =3D EADDRNOTAVAIL;
 				splx(s);

--RnlQjJ0d97Da+TV1--

--mojUlQ0s9EVzWg2t
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Comment: ''

iD8DBQFBf1CRueUpAYYNtTsRAq2ZAJsEpxqxKF2l20jgnztRsZhElDNZHQCeLb7l
bPPlc+nBc/B3muPtA0NpVdU=
=V3uW
-----END PGP SIGNATURE-----

--mojUlQ0s9EVzWg2t--



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