Implementing IP_SENDIF (like SO_BINDTODEVICE)
Bruce M Simpson
bms at spc.org
Wed Oct 27 00:39:11 PDT 2004
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.
-------------- next part --------------
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
===================================================================
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
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 = 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.
+ *
*/
if (flags & IP_ROUTETOIF) {
- if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
- (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) {
+ ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)));
+ if (ia == NULL)
+ ia = ifatoia(ifa_ifwithnet(sintosa(dst)));
+ if (ia != NULL)
+ ifp = ia->ia_ifp;
+ else
+ ifp = ina_to_rfc1724_if(&dst->sin_addr, NULL);
+ if (ifp == NULL) {
ipstat.ips_noroute++;
error = ENETUNREACH;
goto bad;
}
- ifp = ia->ia_ifp;
ip->ip_ttl = 1;
- isbroadcast = in_broadcast(dst->sin_addr, ifp);
+ isbroadcast = (flags & IP_SENDONES) |
+ in_broadcast(dst->sin_addr, ifp);
} else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
imo != NULL && imo->imo_multicast_ifp != NULL) {
/*
@@ -1531,11 +1542,15 @@ bad:
* standard option (IP_TTL).
*/
+#define INADDR_IFINDEX_MASK 0x00FFFFFF /* 0.0.0.0/8 */
+
/*
- * following RFC1724 section 3.3, 0.0.0.0/8 is interpreted as interface index.
+ * 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)
if (ifindexp)
*ifindexp = 0;
- if (ntohl(a->s_addr) >> 24 == 0) {
- ifindex = ntohl(a->s_addr) & 0xffffff;
+ if ((ntohl(a->s_addr) & ~INADDR_IFINDEX_MASK) == 0) {
+ ifindex = ntohl(a->s_addr) & 0x00FFFFFF;
if (ifindex < 0 || if_index < ifindex)
return NULL;
ifp = ifnet_byindex(ifindex);
@@ -1554,7 +1569,7 @@ ip_multicast_if(a, ifindexp)
} else {
INADDR_TO_IFP(*a, ifp);
}
- return ifp;
+ return (ifp);
}
/*
@@ -1634,7 +1649,7 @@ ip_setmoptions(sopt, imop)
* it supports multicasting.
*/
s = splimp();
- ifp = ip_multicast_if(&addr, &ifindex);
+ ifp = ina_to_rfc1724_if(&addr, &ifindex);
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
splx(s);
error = EADDRNOTAVAIL;
@@ -1731,7 +1746,7 @@ ip_setmoptions(sopt, imop)
RTFREE(ro.ro_rt);
}
else {
- ifp = ip_multicast_if(&mreq.imr_interface, NULL);
+ ifp = ina_to_rfc1724_if(&mreq.imr_interface, NULL);
}
/*
@@ -1799,7 +1814,7 @@ ip_setmoptions(sopt, imop)
if (mreq.imr_interface.s_addr == INADDR_ANY)
ifp = NULL;
else {
- ifp = ip_multicast_if(&mreq.imr_interface, NULL);
+ ifp = ina_to_rfc1724_if(&mreq.imr_interface, NULL);
if (ifp == NULL) {
error = EADDRNOTAVAIL;
splx(s);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 167 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20041027/77fd0480/attachment.bin
More information about the freebsd-net
mailing list