diff options
author | truckman <truckman@FreeBSD.org> | 2001-03-04 01:39:19 +0000 |
---|---|---|
committer | truckman <truckman@FreeBSD.org> | 2001-03-04 01:39:19 +0000 |
commit | 3a29c2f4df782f7fddae75438b810805211a8ce8 (patch) | |
tree | c6852df143e5846e47169905c7943e91d734c513 /sys/netinet/ip_input.c | |
parent | 6a1cc9f79fb9e7eafdea1794998b46874779b495 (diff) | |
download | FreeBSD-src-3a29c2f4df782f7fddae75438b810805211a8ce8.zip FreeBSD-src-3a29c2f4df782f7fddae75438b810805211a8ce8.tar.gz |
Disable interface checking when IP forwarding is engaged so that packets
addressed to the interface on the other side of the box follow their
historical path.
Explicitly block packets sent to the loopback network sent from the outside,
which is consistent with the behavior of the forwarding path between
interfaces as implemented in in_canforward().
Always check the arrival interface when matching the packet destination
against the interface broadcast addresses. This bug allowed TCP
connections to be made to the broadcast address of an interface on the
far side of the system because the M_BCAST flag was not set because the
packet was unicast to the interface on the near side. This was broken
when the directed broadcast code was removed from revision 1.32. If
the directed broadcast code was stil present, the destination would not
have been recognized as local until the packet was forwarded to the output
interface and ether_output() looped a copy back to ip_input() with
M_BCAST set and the receive interface set to the output interface.
Optimize the order of the tests.
Reviewed by: jlemon
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r-- | sys/netinet/ip_input.c | 55 |
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; |