summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/ip_input.c55
1 files changed, 45 insertions, 10 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 85c1b96..985d34c 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -124,6 +124,12 @@ SYSCTL_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
&ip_keepfaith, 0,
"Enable packet capture for FAITH IPv4->IPv6 translater daemon");
+/*
+ * XXX - Setting ip_checkinterface mostly implements the receive side of
+ * the Strong ES model described in RFC 1122, but since the routing table
+ * and transmit implementation do not implement the Strong ES model, so
+ * setting this to 1 results in an odd hybrid.
+ */
static int ip_checkinterface = 1;
SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW,
&ip_checkinterface, 0, "Verify packet arrives on correct interface");
@@ -257,7 +263,7 @@ ip_input(struct mbuf *m)
struct ip *ip;
struct ipq *fp;
struct in_ifaddr *ia = NULL;
- int i, hlen;
+ int i, hlen, checkif;
u_short sum;
u_int16_t divert_cookie; /* firewall cookie */
struct in_addr pkt_dst;
@@ -506,6 +512,30 @@ pass:
pkt_dst = ip_fw_fwd_addr == NULL ?
ip->ip_dst : ip_fw_fwd_addr->sin_addr;
+ /*
+ * Don't accept packets with a loopback destination address
+ * unless they arrived via the loopback interface.
+ * XXX - should ip->ip_dst.s_addr be pkt_dst.s_addr?
+ */
+ if ((ntohl(ip->ip_dst.s_addr) & IN_CLASSA_NET) ==
+ (IN_LOOPBACKNET << IN_CLASSA_NSHIFT) &&
+ (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
+ m_freem(m);
+#ifdef IPFIREWALL_FORWARD
+ ip_fw_fwd_addr = NULL;
+#endif
+ return;
+ }
+
+ /*
+ * Enable a consistency check between the destination address
+ * and the arrival interface for a unicast packet (the RFC 1122
+ * strong ES model) if IP forwarding is disabled and the packet
+ * is not locally generated.
+ */
+ checkif = ip_checkinterface && (ipforwarding == 0) &&
+ ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0);
+
TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
#define satosin(sa) ((struct sockaddr_in *)(sa))
@@ -514,17 +544,22 @@ pass:
goto ours;
#endif
/*
- * check that the packet is either arriving from the
- * correct interface or is locally generated.
+ * If the address matches, verify that the packet
+ * arrived via the correct interface if checking is
+ * enabled.
*/
- if (ia->ia_ifp != m->m_pkthdr.rcvif && ip_checkinterface &&
- (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0)
- continue;
-
- if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr)
+ if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr &&
+ (!checkif || ia->ia_ifp == m->m_pkthdr.rcvif))
goto ours;
-
- if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
+ /*
+ * Only accept broadcast packets that arrive via the
+ * matching interface. Reception of forwarded directed
+ * broadcasts would be handled via ip_forward() and
+ * ether_output() with the loopback into the stack for
+ * SIMPLEX interfaces handled by ether_output().
+ */
+ if (ia->ia_ifp == m->m_pkthdr.rcvif &&
+ ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
pkt_dst.s_addr)
goto ours;
OpenPOWER on IntegriCloud