summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2014-03-28 08:33:52 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2014-03-28 08:33:52 +0000
commit0a90147190d373b5095c738f1ca6b109b7f20e9c (patch)
tree7340b37510a26dad27eb4511e3a67b14033a1771 /sys/netinet
parente2859ce1d1ec8b4a84b0441c6013497cc514ac6e (diff)
revert "Retire kernel support for SO_DONTROUTE" diff, which does bad things
for localhost connections. discussed with deraadt@
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in_pcb.c25
-rw-r--r--sys/netinet/ip_divert.c8
-rw-r--r--sys/netinet/ip_output.c40
-rw-r--r--sys/netinet/ip_var.h3
-rw-r--r--sys/netinet/raw_ip.c4
-rw-r--r--sys/netinet/tcp_output.c9
-rw-r--r--sys/netinet/udp_usrreq.c6
7 files changed, 73 insertions, 22 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 28012438f98..db67fbaa95c 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.148 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.149 2014/03/28 08:33:51 sthen Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -817,12 +817,14 @@ in_selectsrc(struct sockaddr_in *sin, struct route *ro, int soopts,
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
*/
- if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- (satosin(&ro->ro_dst)->sin_addr.s_addr != sin->sin_addr.s_addr))) {
+ if (ro->ro_rt && (!(ro->ro_rt->rt_flags & RTF_UP) ||
+ (satosin(&ro->ro_dst)->sin_addr.s_addr != sin->sin_addr.s_addr ||
+ soopts & SO_DONTROUTE))) {
RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
- if ((ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL)) {
+ if ((soopts & SO_DONTROUTE) == 0 && /*XXX*/
+ (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL)) {
/* No route yet, so try to acquire one */
ro->ro_dst.sa_family = AF_INET;
ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
@@ -847,8 +849,19 @@ in_selectsrc(struct sockaddr_in *sin, struct route *ro, int soopts,
!(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
ia = ifatoia(ro->ro_rt->rt_ifa);
if (ia == 0) {
- *errorp = EADDRNOTAVAIL;
- return (NULL);
+ u_int16_t fport = sin->sin_port;
+
+ sin->sin_port = 0;
+ ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin), rtableid));
+ if (ia == 0)
+ ia = ifatoia(ifa_ifwithnet(sintosa(sin), rtableid));
+ sin->sin_port = fport;
+ if (ia == 0)
+ ia = TAILQ_FIRST(&in_ifaddr);
+ if (ia == 0) {
+ *errorp = EADDRNOTAVAIL;
+ return NULL;
+ }
}
return (&ia->ia_addr);
}
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 947f5205b2e..6ac2f0688e2 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_divert.c,v 1.17 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: ip_divert.c,v 1.18 2014/03/28 08:33:51 sthen Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -180,8 +180,10 @@ divert_output(struct mbuf *m, ...)
schednetisr(NETISR_IP);
splx(s);
} else {
- error = ip_output(m, NULL, &inp->inp_route,
- IP_ALLOWBROADCAST | IP_RAWOUTPUT, NULL, NULL);
+ error = ip_output(m, (void *)NULL, &inp->inp_route,
+ ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0)
+ | IP_ALLOWBROADCAST | IP_RAWOUTPUT, (void *)NULL,
+ (void *)NULL);
if (error == EACCES) /* translate pf(4) error for userland */
error = EHOSTUNREACH;
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 6d490bc5700..03a6a782028 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.258 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: ip_output.c,v 1.259 2014/03/28 08:33:51 sthen Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -194,7 +194,23 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
ro->ro_tableid = m->m_pkthdr.rdomain;
}
- if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
+ /*
+ * If routing to interface only, short-circuit routing lookup.
+ */
+ if (flags & IP_ROUTETOIF) {
+ if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst),
+ m->m_pkthdr.rdomain))) == 0 &&
+ (ia = ifatoia(ifa_ifwithnet(sintosa(dst),
+ m->m_pkthdr.rdomain))) == 0) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+
+ ifp = ia->ia_ifp;
+ mtu = ifp->if_mtu;
+ ip->ip_ttl = 1;
+ } else if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
(ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
imo != NULL && imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
@@ -344,7 +360,23 @@ reroute:
ro->ro_tableid = m->m_pkthdr.rdomain;
}
- if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
+ /*
+ * If routing to interface only, short-circuit routing lookup.
+ */
+ if (flags & IP_ROUTETOIF) {
+ if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst),
+ m->m_pkthdr.rdomain))) == 0 &&
+ (ia = ifatoia(ifa_ifwithnet(sintosa(dst),
+ m->m_pkthdr.rdomain))) == 0) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+
+ ifp = ia->ia_ifp;
+ mtu = ifp->if_mtu;
+ ip->ip_ttl = 1;
+ } else if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
(ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
imo != NULL && imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
@@ -720,7 +752,7 @@ sendit:
ipstat.ips_fragmented++;
done:
- if (ro == &iproute && ro->ro_rt)
+ if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
RTFREE(ro->ro_rt);
return (error);
bad:
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 8abdd451a27..0d90a82969c 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.53 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: ip_var.h,v 1.54 2014/03/28 08:33:51 sthen Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -140,6 +140,7 @@ struct ipq {
/* flags passed to ip_output as last parameter */
#define IP_FORWARDING 0x1 /* most of ip header exists */
#define IP_RAWOUTPUT 0x2 /* raw ip header exists */
+#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
#define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */
#define IP_ROUTETOETHER 0x1000 /* ether addresses given */
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 3b6cbe590f7..91d22a49987 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip.c,v 1.68 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: raw_ip.c,v 1.69 2014/03/28 08:33:51 sthen Exp $ */
/* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */
/*
@@ -218,7 +218,7 @@ rip_output(struct mbuf *m, ...)
va_end(ap);
inp = sotoinpcb(so);
- flags = IP_ALLOWBROADCAST;
+ flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
/*
* If the user handed us a complete IP packet, use it.
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index d0633905556..7eec9e2d4c6 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.102 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.103 2014/03/28 08:33:51 sthen Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -1076,7 +1076,9 @@ send:
}
error = ip_output(m, tp->t_inpcb->inp_options,
&tp->t_inpcb->inp_route,
- (ip_mtudisc ? IP_MTUDISC : 0), NULL, tp->t_inpcb);
+ (ip_mtudisc ? IP_MTUDISC : 0) |
+ (so->so_options & SO_DONTROUTE),
+ (void *)NULL, tp->t_inpcb);
break;
#endif /* INET */
#ifdef INET6
@@ -1097,7 +1099,8 @@ send:
}
error = ip6_output(m, tp->t_inpcb->inp_outputopts6,
&tp->t_inpcb->inp_route6,
- 0, NULL, NULL, tp->t_inpcb);
+ (so->so_options & SO_DONTROUTE), NULL, NULL,
+ tp->t_inpcb);
break;
#endif /* INET6 */
}
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index b85330eeec0..17f69795b40 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.175 2014/03/27 13:27:28 mpi Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.176 2014/03/28 08:33:51 sthen Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -1090,8 +1090,8 @@ udp_output(struct mbuf *m, ...)
m->m_pkthdr.rdomain = inp->inp_rtableid;
error = ip_output(m, inp->inp_options, &inp->inp_route,
- (inp->inp_socket->so_options & SO_BROADCAST) | IP_IPSECFLOW,
- inp->inp_moptions, inp, ipsecflowinfo);
+ (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST))
+ |IP_IPSECFLOW, inp->inp_moptions, inp, ipsecflowinfo);
if (error == EACCES) /* translate pf(4) error for userland */
error = EHOSTUNREACH;