Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
Show First 20 Lines • Show All 599 Lines • ▼ Show 20 Lines | tcp_input(struct mbuf **mp, int *offp, int proto) | ||||
struct ip *ip = NULL; | struct ip *ip = NULL; | ||||
struct inpcb *inp = NULL; | struct inpcb *inp = NULL; | ||||
struct tcpcb *tp = NULL; | struct tcpcb *tp = NULL; | ||||
struct socket *so = NULL; | struct socket *so = NULL; | ||||
u_char *optp = NULL; | u_char *optp = NULL; | ||||
int off0; | int off0; | ||||
int optlen = 0; | int optlen = 0; | ||||
#ifdef INET | #ifdef INET | ||||
struct sockaddr_in next_hop; | |||||
int len; | int len; | ||||
#endif | #endif | ||||
int tlen = 0, off; | int tlen = 0, off; | ||||
int drop_hdrlen; | int drop_hdrlen; | ||||
int thflags; | int thflags; | ||||
int rstreason = 0; /* For badport_bandlim accounting purposes */ | int rstreason = 0; /* For badport_bandlim accounting purposes */ | ||||
#ifdef TCP_SIGNATURE | #ifdef TCP_SIGNATURE | ||||
uint8_t sig_checked = 0; | uint8_t sig_checked = 0; | ||||
#endif | #endif | ||||
uint8_t iptos; | uint8_t iptos; | ||||
struct m_tag *fwd_tag = NULL; | |||||
#ifdef INET6 | #ifdef INET6 | ||||
struct sockaddr_in6 next_hop6; | |||||
struct ip6_hdr *ip6 = NULL; | struct ip6_hdr *ip6 = NULL; | ||||
int isipv6; | int isipv6; | ||||
#else | #else | ||||
const void *ip6 = NULL; | const void *ip6 = NULL; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
struct tcpopt to; /* options in this segment */ | struct tcpopt to; /* options in this segment */ | ||||
char *s = NULL; /* address and port logging */ | char *s = NULL; /* address and port logging */ | ||||
int ti_locked; | int ti_locked; | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | #endif | ||||
* connection in TIMEWAIT and SYNs not targeting a listening socket. | * connection in TIMEWAIT and SYNs not targeting a listening socket. | ||||
*/ | */ | ||||
if ((thflags & (TH_FIN | TH_RST)) != 0) { | if ((thflags & (TH_FIN | TH_RST)) != 0) { | ||||
INP_INFO_RLOCK(&V_tcbinfo); | INP_INFO_RLOCK(&V_tcbinfo); | ||||
ti_locked = TI_RLOCKED; | ti_locked = TI_RLOCKED; | ||||
} else | } else | ||||
ti_locked = TI_UNLOCKED; | ti_locked = TI_UNLOCKED; | ||||
/* | |||||
* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. | |||||
*/ | |||||
if ( | |||||
#ifdef INET6 | |||||
(isipv6 && (m->m_flags & M_IP6_NEXTHOP)) | |||||
#ifdef INET | |||||
|| (!isipv6 && (m->m_flags & M_IP_NEXTHOP)) | |||||
#endif | |||||
#endif | |||||
#if defined(INET) && !defined(INET6) | |||||
(m->m_flags & M_IP_NEXTHOP) | |||||
#endif | |||||
) | |||||
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); | |||||
findpcb: | findpcb: | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (ti_locked == TI_RLOCKED) { | if (ti_locked == TI_RLOCKED) { | ||||
INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | ||||
} else { | } else { | ||||
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (isipv6 && fwd_tag != NULL) { | |||||
struct sockaddr_in6 *next_hop6; | |||||
next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1); | |||||
/* | /* | ||||
* Grab info from IP forward tag prepended to the chain. | |||||
*/ | |||||
if (isipv6 && IP6_HAS_NEXTHOP(m) && | |||||
!ip6_get_fwdtag(m, &next_hop6, NULL)) { | |||||
/* | |||||
* Transparently forwarded. Pretend to be the destination. | * Transparently forwarded. Pretend to be the destination. | ||||
* Already got one like this? | * Already got one like this? | ||||
*/ | */ | ||||
inp = in6_pcblookup_mbuf(&V_tcbinfo, | inp = in6_pcblookup_mbuf(&V_tcbinfo, | ||||
&ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport, | &ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport, | ||||
INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif, m); | INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif, m); | ||||
if (!inp) { | if (!inp) { | ||||
/* | /* | ||||
* It's new. Try to find the ambushing socket. | * It's new. Try to find the ambushing socket. | ||||
* Because we've rewritten the destination address, | * Because we've rewritten the destination address, | ||||
* any hardware-generated hash is ignored. | * any hardware-generated hash is ignored. | ||||
*/ | */ | ||||
inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src, | inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src, | ||||
th->th_sport, &next_hop6->sin6_addr, | th->th_sport, &next_hop6.sin6_addr, | ||||
next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) : | next_hop6.sin6_port ? ntohs(next_hop6.sin6_port) : | ||||
th->th_dport, INPLOOKUP_WILDCARD | | th->th_dport, INPLOOKUP_WILDCARD | | ||||
INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif); | INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif); | ||||
} | } | ||||
/* Remove the tag from the packet. We don't need it anymore. */ | |||||
ip6_flush_fwdtag(m); | |||||
} else if (isipv6) { | } else if (isipv6) { | ||||
inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src, | inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src, | ||||
th->th_sport, &ip6->ip6_dst, th->th_dport, | th->th_sport, &ip6->ip6_dst, th->th_dport, | ||||
INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB, | INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB, | ||||
m->m_pkthdr.rcvif, m); | m->m_pkthdr.rcvif, m); | ||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
if (fwd_tag != NULL) { | |||||
struct sockaddr_in *next_hop; | |||||
next_hop = (struct sockaddr_in *)(fwd_tag+1); | |||||
/* | /* | ||||
* Grab info from IP forward tag prepended to the chain. | |||||
*/ | |||||
if (IP_HAS_NEXTHOP(m) && !ip_get_fwdtag(m, &next_hop, NULL)) { | |||||
/* | |||||
* Transparently forwarded. Pretend to be the destination. | * Transparently forwarded. Pretend to be the destination. | ||||
* already got one like this? | * already got one like this? | ||||
*/ | */ | ||||
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, th->th_sport, | inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, th->th_sport, | ||||
ip->ip_dst, th->th_dport, INPLOOKUP_WLOCKPCB, | ip->ip_dst, th->th_dport, INPLOOKUP_WLOCKPCB, | ||||
m->m_pkthdr.rcvif, m); | m->m_pkthdr.rcvif, m); | ||||
if (!inp) { | if (!inp) { | ||||
/* | /* | ||||
* It's new. Try to find the ambushing socket. | * It's new. Try to find the ambushing socket. | ||||
* Because we've rewritten the destination address, | * Because we've rewritten the destination address, | ||||
* any hardware-generated hash is ignored. | * any hardware-generated hash is ignored. | ||||
*/ | */ | ||||
inp = in_pcblookup(&V_tcbinfo, ip->ip_src, | inp = in_pcblookup(&V_tcbinfo, ip->ip_src, | ||||
th->th_sport, next_hop->sin_addr, | th->th_sport, next_hop.sin_addr, | ||||
next_hop->sin_port ? ntohs(next_hop->sin_port) : | next_hop.sin_port ? ntohs(next_hop.sin_port) : | ||||
th->th_dport, INPLOOKUP_WILDCARD | | th->th_dport, INPLOOKUP_WILDCARD | | ||||
INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif); | INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif); | ||||
} | } | ||||
/* Remove the tag from the packet. We don't need it anymore. */ | |||||
ip_flush_fwdtag(m); | |||||
} else | } else | ||||
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, | inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, | ||||
th->th_sport, ip->ip_dst, th->th_dport, | th->th_sport, ip->ip_dst, th->th_dport, | ||||
INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB, | INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB, | ||||
m->m_pkthdr.rcvif, m); | m->m_pkthdr.rcvif, m); | ||||
#endif /* INET */ | #endif /* INET */ | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 3,020 Lines • Show Last 20 Lines |