Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_subr.c
Show First 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | |||||
#include <netinet6/in6_fib.h> | #include <netinet6/in6_fib.h> | ||||
#include <netinet6/in6_pcb.h> | #include <netinet6/in6_pcb.h> | ||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#include <netinet6/scope6_var.h> | #include <netinet6/scope6_var.h> | ||||
#include <netinet6/nd6.h> | #include <netinet6/nd6.h> | ||||
#endif | #endif | ||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||
#ifdef INVARIANTS | |||||
#define TCPSTATES | |||||
#endif | |||||
#include <netinet/tcp_fsm.h> | #include <netinet/tcp_fsm.h> | ||||
#include <netinet/tcp_seq.h> | #include <netinet/tcp_seq.h> | ||||
#include <netinet/tcp_timer.h> | #include <netinet/tcp_timer.h> | ||||
#include <netinet/tcp_var.h> | #include <netinet/tcp_var.h> | ||||
#include <netinet/tcp_log_buf.h> | #include <netinet/tcp_log_buf.h> | ||||
#include <netinet/tcp_syncache.h> | #include <netinet/tcp_syncache.h> | ||||
#include <netinet/tcp_hpts.h> | #include <netinet/tcp_hpts.h> | ||||
#include <netinet/cc/cc.h> | #include <netinet/cc/cc.h> | ||||
▲ Show 20 Lines • Show All 1,638 Lines • ▼ Show 20 Lines | tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, | ||||
struct tcphdr *nth; | struct tcphdr *nth; | ||||
struct tcp_log_buffer *lgb; | struct tcp_log_buffer *lgb; | ||||
u_char *optp; | u_char *optp; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
int isipv6; | int isipv6; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
int optlen, tlen, win, ulen; | int optlen, tlen, win, ulen; | ||||
bool incl_opts, lock_upgraded; | bool incl_opts; | ||||
uint16_t port; | uint16_t port; | ||||
int output_ret; | int output_ret; | ||||
#ifdef INVARIANTS | |||||
int thflags = th->th_flags; | |||||
#endif | |||||
KASSERT(tp != NULL || m != NULL, ("tcp_respond: tp and m both NULL")); | KASSERT(tp != NULL || m != NULL, ("tcp_respond: tp and m both NULL")); | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
isipv6 = ((struct ip *)ipgen)->ip_v == (IPV6_VERSION >> 4); | isipv6 = ((struct ip *)ipgen)->ip_v == (IPV6_VERSION >> 4); | ||||
ip6 = ipgen; | ip6 = ipgen; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
▲ Show 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | |||||
#endif /* INET */ | #endif /* INET */ | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
if (tp == NULL || (inp->inp_socket->so_options & SO_DEBUG)) | if (tp == NULL || (inp->inp_socket->so_options & SO_DEBUG)) | ||||
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0); | tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0); | ||||
#endif | #endif | ||||
TCP_PROBE3(debug__output, tp, th, m); | TCP_PROBE3(debug__output, tp, th, m); | ||||
if (flags & TH_RST) | if (flags & TH_RST) | ||||
TCP_PROBE5(accept__refused, NULL, NULL, m, tp, nth); | TCP_PROBE5(accept__refused, NULL, NULL, m, tp, nth); | ||||
lock_upgraded = false; | |||||
lgb = NULL; | lgb = NULL; | ||||
if ((tp != NULL) && (tp->t_logstate != TCP_LOG_STATE_OFF)) { | if ((tp != NULL) && (tp->t_logstate != TCP_LOG_STATE_OFF)) { | ||||
union tcp_log_stackspecific log; | union tcp_log_stackspecific log; | ||||
struct timeval tv; | struct timeval tv; | ||||
lock_upgraded = !INP_WLOCKED(inp) && INP_TRY_UPGRADE(inp); | |||||
/* | |||||
*`If we don't already own the write lock and can't upgrade, | |||||
* just don't log the event, but still send the response. | |||||
*/ | |||||
if (INP_WLOCKED(inp)) { | if (INP_WLOCKED(inp)) { | ||||
memset(&log.u_bbr, 0, sizeof(log.u_bbr)); | memset(&log.u_bbr, 0, sizeof(log.u_bbr)); | ||||
log.u_bbr.inhpts = tp->t_inpcb->inp_in_hpts; | log.u_bbr.inhpts = tp->t_inpcb->inp_in_hpts; | ||||
log.u_bbr.ininput = tp->t_inpcb->inp_in_input; | log.u_bbr.ininput = tp->t_inpcb->inp_in_input; | ||||
log.u_bbr.flex8 = 4; | log.u_bbr.flex8 = 4; | ||||
log.u_bbr.pkts_out = tp->t_maxseg; | log.u_bbr.pkts_out = tp->t_maxseg; | ||||
log.u_bbr.timeStamp = tcp_get_usecs(&tv); | log.u_bbr.timeStamp = tcp_get_usecs(&tv); | ||||
log.u_bbr.delivered = 0; | log.u_bbr.delivered = 0; | ||||
lgb = tcp_log_event_(tp, nth, NULL, NULL, TCP_LOG_OUT, ERRNO_UNK, | lgb = tcp_log_event_(tp, nth, NULL, NULL, TCP_LOG_OUT, ERRNO_UNK, | ||||
0, &log, false, NULL, NULL, 0, &tv); | 0, &log, false, NULL, NULL, 0, &tv); | ||||
} else { | |||||
/* | |||||
* We can not log the packet, since we only own the | |||||
* read lock, but a write lock is needed. | |||||
* This happens only for pure SYN segments received in | |||||
* the initial CLOSED state or received in a state | |||||
* later then listen is the UDP encapsulation port is | |||||
lstewart: I'd suggest deleting `We can not log the packet, since we only own the read lock, but a write… | |||||
tuexenAuthorUnsubmitted Done Inline ActionsI kept the statement about the read/write lock and added an explanation, why we don't do the upgrade dance. I also added that the segments don't need to be logged since we don't consider them belonging to the connection. I also added a note, that the incoming SYN segments are also not logged. tuexen: I kept the statement about the read/write lock and added an explanation, why we don't do the… | |||||
* unexpected. | |||||
* Ensure that the above description is and stays | |||||
* correct. | |||||
*/ | |||||
KASSERT(((thflags & (TH_ACK|TH_SYN)) == TH_SYN) && | |||||
((tp->t_state == TCPS_CLOSED) || | |||||
((tp->t_state > TCPS_LISTEN) && (tp->t_port != port))), | |||||
("%s: Logging of TCP segment with flags 0x%b and UDP encapsulation port %u skipped in state %s", | |||||
__func__, thflags, PRINT_TH_FLAGS, | |||||
ntohs(port), tcpstates[tp->t_state])); | |||||
} | } | ||||
} | } | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (isipv6) { | if (isipv6) { | ||||
TCP_PROBE5(send, NULL, tp, ip6, tp, nth); | TCP_PROBE5(send, NULL, tp, ip6, tp, nth); | ||||
output_ret = ip6_output(m, NULL, NULL, 0, NULL, NULL, inp); | output_ret = ip6_output(m, NULL, NULL, 0, NULL, NULL, inp); | ||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#if defined(INET) && defined(INET6) | #if defined(INET) && defined(INET6) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
{ | { | ||||
TCP_PROBE5(send, NULL, tp, ip, tp, nth); | TCP_PROBE5(send, NULL, tp, ip, tp, nth); | ||||
output_ret = ip_output(m, NULL, NULL, 0, NULL, inp); | output_ret = ip_output(m, NULL, NULL, 0, NULL, inp); | ||||
} | } | ||||
#endif | #endif | ||||
if (lgb != NULL) | if (lgb != NULL) | ||||
lgb->tlb_errno = output_ret; | lgb->tlb_errno = output_ret; | ||||
if (lock_upgraded) | |||||
INP_DOWNGRADE(inp); | |||||
} | } | ||||
/* | /* | ||||
* Create a new TCP control block, making an | * Create a new TCP control block, making an | ||||
* empty reassembly queue and hooking it to the argument | * empty reassembly queue and hooking it to the argument | ||||
* protocol control block. The `inp' parameter must have | * protocol control block. The `inp' parameter must have | ||||
* come from the zone allocator set up in tcp_init(). | * come from the zone allocator set up in tcp_init(). | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 2,081 Lines • Show Last 20 Lines |
I'd suggest deleting We can not log the packet, since we only own the read lock, but a write lock is needed. as it's not very relevant even though true. Someone could read this comment later and wonder why not try the wlock upgrade approach or another method to ensure the log is generated.
What is more relevant and IMO should be captured in this comment block in place of the above sentence is that the 2 cases which pass through this block are considered to be events which are not appropriately associated with the tcpcb/connection, and therefore we are explicitly choosing not to log them.
Minor language/grammar nit:
... CLOSED state or received in a state later then listen is the UDP encapsulation port is unexpected.
->
... CLOSED state, or received in a more advanced state than LISTEN and the UDP encapsulation port does not match.