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 | |||||