Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/tcp_syncache.c
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
#include <vm/uma.h> | #include <vm/uma.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/route.h> | #include <net/route.h> | ||||
#include <net/vnet.h> | #include <net/vnet.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_kdtrace.h> | |||||
#include <netinet/in_systm.h> | #include <netinet/in_systm.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/ip_options.h> | #include <netinet/ip_options.h> | ||||
#ifdef INET6 | #ifdef INET6 | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
▲ Show 20 Lines • Show All 1,315 Lines • ▼ Show 20 Lines | |||||
#ifdef MAC | #ifdef MAC | ||||
/* | /* | ||||
* Since we have already unconditionally allocated label | * Since we have already unconditionally allocated label | ||||
* storage, free it up. The syncache entry will already | * storage, free it up. The syncache entry will already | ||||
* have an initialized label we can use. | * have an initialized label we can use. | ||||
*/ | */ | ||||
mac_syncache_destroy(&maclabel); | mac_syncache_destroy(&maclabel); | ||||
#endif | #endif | ||||
TCP_PROBE5(receive, NULL, NULL, m, NULL, th); | |||||
/* Retransmit SYN|ACK and reset retransmit count. */ | /* Retransmit SYN|ACK and reset retransmit count. */ | ||||
if ((s = tcp_log_addrs(&sc->sc_inc, th, NULL, NULL))) { | if ((s = tcp_log_addrs(&sc->sc_inc, th, NULL, NULL))) { | ||||
log(LOG_DEBUG, "%s; %s: Received duplicate SYN, " | log(LOG_DEBUG, "%s; %s: Received duplicate SYN, " | ||||
"resetting timer and retransmitting SYN|ACK\n", | "resetting timer and retransmitting SYN|ACK\n", | ||||
s, __func__); | s, __func__); | ||||
free(s, M_TCPLOG); | free(s, M_TCPLOG); | ||||
} | } | ||||
if (syncache_respond(sc, sch, 1, m) == 0) { | if (syncache_respond(sc, sch, 1, m) == 0) { | ||||
sc->sc_rxmits = 0; | sc->sc_rxmits = 0; | ||||
syncache_timeout(sc, sch, 1); | syncache_timeout(sc, sch, 1); | ||||
TCPSTAT_INC(tcps_sndacks); | TCPSTAT_INC(tcps_sndacks); | ||||
TCPSTAT_INC(tcps_sndtotal); | TCPSTAT_INC(tcps_sndtotal); | ||||
} | } | ||||
SCH_UNLOCK(sch); | SCH_UNLOCK(sch); | ||||
goto done; | goto donenoprobe; | ||||
} | } | ||||
if (tfo_cookie_valid) { | if (tfo_cookie_valid) { | ||||
bzero(&scs, sizeof(scs)); | bzero(&scs, sizeof(scs)); | ||||
sc = &scs; | sc = &scs; | ||||
goto skip_alloc; | goto skip_alloc; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | #endif | ||||
if (tfo_cookie_valid) { | if (tfo_cookie_valid) { | ||||
syncache_tfo_expand(sc, lsop, m, tfo_response_cookie); | syncache_tfo_expand(sc, lsop, m, tfo_response_cookie); | ||||
/* INP_WUNLOCK(inp) will be performed by the caller */ | /* INP_WUNLOCK(inp) will be performed by the caller */ | ||||
rv = 1; | rv = 1; | ||||
goto tfo_expanded; | goto tfo_expanded; | ||||
} | } | ||||
TCP_PROBE5(receive, NULL, NULL, m, NULL, th); | |||||
/* | /* | ||||
* Do a standard 3-way handshake. | * Do a standard 3-way handshake. | ||||
*/ | */ | ||||
if (syncache_respond(sc, sch, 0, m) == 0) { | if (syncache_respond(sc, sch, 0, m) == 0) { | ||||
if (V_tcp_syncookies && V_tcp_syncookiesonly && sc != &scs) | if (V_tcp_syncookies && V_tcp_syncookiesonly && sc != &scs) | ||||
syncache_free(sc); | syncache_free(sc); | ||||
else if (sc != &scs) | else if (sc != &scs) | ||||
syncache_insert(sc, sch); /* locks and unlocks sch */ | syncache_insert(sc, sch); /* locks and unlocks sch */ | ||||
TCPSTAT_INC(tcps_sndacks); | TCPSTAT_INC(tcps_sndacks); | ||||
TCPSTAT_INC(tcps_sndtotal); | TCPSTAT_INC(tcps_sndtotal); | ||||
} else { | } else { | ||||
if (sc != &scs) | if (sc != &scs) | ||||
syncache_free(sc); | syncache_free(sc); | ||||
TCPSTAT_INC(tcps_sc_dropped); | TCPSTAT_INC(tcps_sc_dropped); | ||||
} | } | ||||
goto donenoprobe; | |||||
done: | done: | ||||
TCP_PROBE5(receive, NULL, NULL, m, NULL, th); | |||||
donenoprobe: | |||||
if (m) { | if (m) { | ||||
*lsop = NULL; | *lsop = NULL; | ||||
m_freem(m); | m_freem(m); | ||||
} | } | ||||
/* | /* | ||||
* If tfo_pending is not NULL here, then a TFO SYN that did not | * If tfo_pending is not NULL here, then a TFO SYN that did not | ||||
* result in a new socket was processed and the associated pending | * result in a new socket was processed and the associated pending | ||||
* counter has not yet been decremented. All such TFO processing paths | * counter has not yet been decremented. All such TFO processing paths | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | #ifdef TCP_OFFLOAD | ||||
if (ADDED_BY_TOE(sc)) { | if (ADDED_BY_TOE(sc)) { | ||||
struct toedev *tod = sc->sc_tod; | struct toedev *tod = sc->sc_tod; | ||||
error = tod->tod_syncache_respond(tod, sc->sc_todctx, m); | error = tod->tod_syncache_respond(tod, sc->sc_todctx, m); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif | ||||
TCP_PROBE5(send, NULL, NULL, ip6, NULL, th); | |||||
error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); | error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); | ||||
} | } | ||||
#endif | #endif | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
{ | { | ||||
m->m_pkthdr.csum_flags = CSUM_TCP; | m->m_pkthdr.csum_flags = CSUM_TCP; | ||||
th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, | th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, | ||||
htons(tlen + optlen - hlen + IPPROTO_TCP)); | htons(tlen + optlen - hlen + IPPROTO_TCP)); | ||||
#ifdef TCP_OFFLOAD | #ifdef TCP_OFFLOAD | ||||
if (ADDED_BY_TOE(sc)) { | if (ADDED_BY_TOE(sc)) { | ||||
struct toedev *tod = sc->sc_tod; | struct toedev *tod = sc->sc_tod; | ||||
error = tod->tod_syncache_respond(tod, sc->sc_todctx, m); | error = tod->tod_syncache_respond(tod, sc->sc_todctx, m); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif | ||||
TCP_PROBE5(send, NULL, NULL, ip, NULL, th); | |||||
error = ip_output(m, sc->sc_ipopts, NULL, 0, NULL, NULL); | error = ip_output(m, sc->sc_ipopts, NULL, 0, NULL, NULL); | ||||
} | } | ||||
#endif | #endif | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* The purpose of syncookies is to handle spoofed SYN flooding DoS attacks | * The purpose of syncookies is to handle spoofed SYN flooding DoS attacks | ||||
▲ Show 20 Lines • Show All 424 Lines • Show Last 20 Lines |