Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_input.c
Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
* Respond with an ICMP host redirect when we forward a packet out of | * Respond with an ICMP host redirect when we forward a packet out of | ||||
* the same interface on which it was received. See RFC 792. | * the same interface on which it was received. See RFC 792. | ||||
*/ | */ | ||||
VNET_DEFINE(int, ipsendredirects) = 1; | VNET_DEFINE(int, ipsendredirects) = 1; | ||||
SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(ipsendredirects), 0, | &VNET_NAME(ipsendredirects), 0, | ||||
"Enable sending IP redirects"); | "Enable sending IP redirects"); | ||||
/* | VNET_DEFINE_STATIC(bool, ip_strong_es) = false; | ||||
* XXX - Setting ip_checkinterface mostly implements the receive side of | #define V_ip_strong_es VNET(ip_strong_es) | ||||
* the Strong ES model described in RFC 1122, but since the routing table | SYSCTL_BOOL(_net_inet_ip, OID_AUTO, rfc1122_strong_es, | ||||
* and transmit implementation do not implement the Strong ES model, | CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_strong_es), false, | ||||
* setting this to 1 results in an odd hybrid. | "Packet's IP destination address must match address on arrival interface"); | ||||
* | |||||
* XXX - ip_checkinterface currently must be disabled if you use ipnat | |||||
* to translate the destination address to another local interface. | |||||
* | |||||
* XXX - ip_checkinterface must be disabled if you add IP aliases | |||||
* to the loopback interface instead of the interface where the | |||||
* packets for those addresses are received. | |||||
*/ | |||||
VNET_DEFINE_STATIC(int, ip_checkinterface); | |||||
#define V_ip_checkinterface VNET(ip_checkinterface) | |||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_VNET | CTLFLAG_RW, | |||||
&VNET_NAME(ip_checkinterface), 0, | |||||
"Verify packet arrives on correct interface"); | |||||
VNET_DEFINE(pfil_head_t, inet_pfil_head); /* Packet filter hooks */ | VNET_DEFINE(pfil_head_t, inet_pfil_head); /* Packet filter hooks */ | ||||
static struct netisr_handler ip_nh = { | static struct netisr_handler ip_nh = { | ||||
.nh_name = "ip", | .nh_name = "ip", | ||||
.nh_handler = ip_input, | .nh_handler = ip_input, | ||||
.nh_proto = NETISR_IP, | .nh_proto = NETISR_IP, | ||||
#ifdef RSS | #ifdef RSS | ||||
▲ Show 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
ip_input(struct mbuf *m) | ip_input(struct mbuf *m) | ||||
{ | { | ||||
MROUTER_RLOCK_TRACKER; | MROUTER_RLOCK_TRACKER; | ||||
struct ip *ip = NULL; | struct ip *ip = NULL; | ||||
struct in_ifaddr *ia = NULL; | struct in_ifaddr *ia = NULL; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int checkif, hlen = 0; | int hlen = 0; | ||||
uint16_t sum, ip_len; | uint16_t sum, ip_len; | ||||
int dchg = 0; /* dest changed after fw */ | int dchg = 0; /* dest changed after fw */ | ||||
struct in_addr odst; /* original dst address */ | struct in_addr odst; /* original dst address */ | ||||
bool strong_es; | |||||
M_ASSERTPKTHDR(m); | M_ASSERTPKTHDR(m); | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
if (m->m_flags & M_FASTFWD_OURS) { | if (m->m_flags & M_FASTFWD_OURS) { | ||||
m->m_flags &= ~M_FASTFWD_OURS; | m->m_flags &= ~M_FASTFWD_OURS; | ||||
/* Set up some basics that will be used later. */ | /* Set up some basics that will be used later. */ | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | passin: | ||||
*/ | */ | ||||
if (CK_STAILQ_EMPTY(&V_in_ifaddrhead) && | if (CK_STAILQ_EMPTY(&V_in_ifaddrhead) && | ||||
(m->m_flags & (M_MCAST|M_BCAST)) == 0) | (m->m_flags & (M_MCAST|M_BCAST)) == 0) | ||||
goto ours; | goto ours; | ||||
/* | /* | ||||
* Enable a consistency check between the destination address | * Enable a consistency check between the destination address | ||||
* and the arrival interface for a unicast packet (the RFC 1122 | * and the arrival interface for a unicast packet (the RFC 1122 | ||||
* strong ES model) if IP forwarding is disabled and the packet | * strong ES model) with a list of additional predicates: | ||||
* is not locally generated and the packet is not subject to | * - if IP forwarding is disabled | ||||
* 'ipfw fwd'. | * - the packet is not locally generated | ||||
* | * - the packet is not subject to 'ipfw fwd' | ||||
* XXX - Checking also should be disabled if the destination | * - Interface is not running CARP. If the packet got here, we already | ||||
* address is ipnat'ed to a different interface. | * checked it with carp_iamatch() and carp_forus(). | ||||
* | |||||
* XXX - Checking is incompatible with IP aliases added | |||||
* to the loopback interface instead of the interface where | |||||
* the packets are received. | |||||
* | |||||
* XXX - This is the case for carp vhost IPs as well so we | |||||
* insert a workaround. If the packet got here, we already | |||||
* checked with carp_iamatch() and carp_forus(). | |||||
*/ | */ | ||||
checkif = V_ip_checkinterface && (V_ipforwarding == 0) && | strong_es = V_ip_strong_es && (V_ipforwarding == 0) && | ||||
ifp != NULL && ((ifp->if_flags & IFF_LOOPBACK) == 0) && | ifp != NULL && ((ifp->if_flags & IFF_LOOPBACK) == 0) && | ||||
ifp->if_carp == NULL && (dchg == 0); | ifp->if_carp == NULL && (dchg == 0); | ||||
/* | /* | ||||
* Check for exact addresses in the hash bucket. | * Check for exact addresses in the hash bucket. | ||||
*/ | */ | ||||
CK_LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) { | CK_LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) { | ||||
if (IA_SIN(ia)->sin_addr.s_addr != ip->ip_dst.s_addr) | |||||
continue; | |||||
/* | /* | ||||
* If the address matches, verify that the packet | * net.inet.ip.rfc1122_strong_es: the address matches, verify | ||||
* arrived via the correct interface if checking is | * that the packet arrived via the correct interface. | ||||
* enabled. | |||||
*/ | */ | ||||
if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr && | if (__predict_false(strong_es && ia->ia_ifp != ifp)) { | ||||
(!checkif || ia->ia_ifp == ifp)) { | IPSTAT_INC(ips_badaddr); | ||||
goto bad; | |||||
} | |||||
counter_u64_add(ia->ia_ifa.ifa_ipackets, 1); | counter_u64_add(ia->ia_ifa.ifa_ipackets, 1); | ||||
counter_u64_add(ia->ia_ifa.ifa_ibytes, | counter_u64_add(ia->ia_ifa.ifa_ibytes, m->m_pkthdr.len); | ||||
m->m_pkthdr.len); | |||||
goto ours; | goto ours; | ||||
} | |||||
} | } | ||||
/* | /* | ||||
* Check for broadcast addresses. | * Check for broadcast addresses. | ||||
* | * | ||||
* Only accept broadcast packets that arrive via the matching | * Only accept broadcast packets that arrive via the matching | ||||
* interface. Reception of forwarded directed broadcasts would | * interface. Reception of forwarded directed broadcasts would | ||||
* be handled via ip_forward() and ether_output() with the loopback | * be handled via ip_forward() and ether_output() with the loopback | ||||
▲ Show 20 Lines • Show All 724 Lines • Show Last 20 Lines |