Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145652051
D55338.id172106.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D55338.id172106.diff
View Options
diff --git a/sys/netinet/in_kdtrace.h b/sys/netinet/in_kdtrace.h
--- a/sys/netinet/in_kdtrace.h
+++ b/sys/netinet/in_kdtrace.h
@@ -336,6 +336,10 @@
SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvghostack);
SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcvacktooold);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcv_rst_payload);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_rcv_rst_diag_payload);
+SDT_PROBE_DECLARE(mib, tcp, count, tcps_snd_rst_diag_payload);
+
SDT_PROBE_DECLARE(mib, ipsec, count, ips_in_polvio);
SDT_PROBE_DECLARE(mib, ipsec, count, ips_in_nomem);
SDT_PROBE_DECLARE(mib, ipsec, count, ips_in_inval);
diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c
--- a/sys/netinet/in_kdtrace.c
+++ b/sys/netinet/in_kdtrace.c
@@ -344,6 +344,10 @@
MIB_PROBE_TCP(tcps_rcvghostack);
MIB_PROBE_TCP(tcps_rcvacktooold);
+MIB_PROBE_TCP(tcps_rcv_rst_payload);
+MIB_PROBE_TCP(tcps_rcv_rst_diag_payload);
+MIB_PROBE_TCP(tcps_snd_rst_diag_payload);
+
#define MIB_PROBE_IPSEC(name) SDT_PROBE_DEFINE1(mib, ipsec, count, name, "int")
MIB_PROBE_IPSEC(ips_in_polvio);
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -219,6 +219,7 @@
#define TCP_PROC_ACCOUNTING 76 /* Do accounting on tcp cpu usage and counts */
#define TCP_USE_CMP_ACKS 77 /* The transport can handle the Compressed mbuf acks */
#define TCP_PERF_INFO 78 /* retrieve accounting counters */
+#define TCP_RST_REASON_CODE 79 /* Diagnostic Payload in RST segments */
#define TCP_KEEPINIT 128 /* N, time to establish connection */
#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */
#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */
@@ -572,5 +573,11 @@
#define TCP_REUSPORT_LB_NUMA_NODOM (-2) /* remove numa binding */
#define TCP_REUSPORT_LB_NUMA_CURDOM (-1) /* bind to current domain */
+struct tcp_rst_reason {
+ uint16_t rst_reason_code;
+ uint16_t rst_reason_unused;
+ uint32_t rst_reason_pen;
+};
+
#endif /* __BSD_VISIBLE */
#endif /* !_NETINET_TCP_H_ */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1382,6 +1382,8 @@
if (inp != NULL)
INP_UNLOCK(inp);
+ if ((thflags & TH_RST) != 0 && tlen > 0)
+ TCPSTAT_INC(tcps_rcv_rst_payload);
drop:
if (s != NULL)
@@ -1984,6 +1986,9 @@
*/
case TCPS_SYN_SENT:
if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) {
+ if (tlen > 0)
+ TCPSTAT_INC(tcps_rcv_rst_payload);
+ tcp_handle_diag_payload(tp, m, tlen, drop_hdrlen);
TCP_PROBE5(connect__refused, NULL, tp,
m, tp, th);
tcp_log_end_status(tp, TCP_EI_STATUS_RST_IN_FRONT);
@@ -2150,6 +2155,10 @@
close:
/* FALLTHROUGH */
default:
+ if (tlen > 0)
+ TCPSTAT_INC(tcps_rcv_rst_payload);
+ tcp_handle_diag_payload(tp, m, tlen,
+ drop_hdrlen);
tcp_log_end_status(tp, TCP_EI_STATUS_CLIENT_RST);
tp = tcp_close(tp);
}
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -196,7 +196,7 @@
struct ip *ip = NULL;
struct tcphdr *th;
u_char opt[TCP_MAXOLEN];
- unsigned ipoptlen, optlen, hdrlen, ulen;
+ unsigned ipoptlen, optlen, hdrlen, ulen, dplen;
unsigned ipsec_optlen = 0;
int idle, sendalot, curticks;
int sack_bytes_rxmt;
@@ -204,6 +204,7 @@
int tso, mtu;
struct tcpopt to;
struct udphdr *udp = NULL;
+ struct tcp_rst_diagnostic_payload *dp;
struct tcp_log_buffer *lgb;
unsigned int wanted_cookie = 0;
unsigned int dont_sendalot = 0;
@@ -274,6 +275,11 @@
sendwin = min(tp->snd_wnd, tp->snd_cwnd + sendwin);
flags = tcp_outflags[tp->t_state];
+ if (((flags & TH_RST) != 0) &&
+ (tp->snd_rst_pen != 0 || tp->snd_rst_code != 0))
+ dplen = sizeof(struct tcp_rst_diagnostic_payload);
+ else
+ dplen = 0;
/*
* Send any SACK-generated retransmissions. If we're explicitly trying
* to send out new data (when sendalot is 1), bypass this function.
@@ -1146,7 +1152,7 @@
} else
#endif
m->m_data += max_linkhdr;
- m->m_len = hdrlen;
+ m->m_len = hdrlen + dplen;
}
SOCK_SENDBUF_UNLOCK_ASSERT(so);
m->m_pkthdr.rcvif = (struct ifnet *)0;
@@ -1325,7 +1331,13 @@
* Put TCP length in extended header, and then
* checksum extended header and data.
*/
- m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */
+ m->m_pkthdr.len = hdrlen + len + dplen; /* in6_cksum() need this */
+ if (dplen > 0) {
+ dp = (struct tcp_rst_diagnostic_payload *)((caddr_t)(th + 1) + optlen);
+ dp->magic_nr = htons(TCP_RST_DIAGNOSTIC_PAYLOAD_MAGIC_NUMBER);
+ dp->rst_code = htons(tp->snd_rst_code);
+ dp->rst_pen = htonl(tp->snd_rst_pen);
+ }
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (to.to_flags & TOF_SIGNATURE) {
@@ -1404,9 +1416,9 @@
m->m_pkthdr.tso_segsz = tp->t_maxseg - optlen - ipsec_optlen;
}
- KASSERT(len + hdrlen == m_length(m, NULL),
- ("%s: mbuf chain shorter than expected: %d + %u != %u",
- __func__, len, hdrlen, m_length(m, NULL)));
+ KASSERT(len + hdrlen + dplen == m_length(m, NULL),
+ ("%s: mbuf chain shorter than expected: %d + %u +%u != %u",
+ __func__, len, hdrlen, dplen, m_length(m, NULL)));
#ifdef TCP_HHOOK
/* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */
diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c
--- a/sys/netinet/tcp_stacks/bbr.c
+++ b/sys/netinet/tcp_stacks/bbr.c
@@ -8760,6 +8760,9 @@
return (1);
}
if ((thflags & (TH_ACK | TH_RST)) == (TH_ACK | TH_RST)) {
+ if (tlen > 0)
+ KMOD_TCPSTAT_INC(tcps_rcv_rst_payload);
+ tcp_handle_diag_payload(tp, m, tlen, th->th_off << 2);
TCP_PROBE5(connect__refused, NULL, tp,
mtod(m, const char *), tp, th);
tp = tcp_drop(tp, ECONNREFUSED);
@@ -8953,7 +8956,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
if ((thflags & TH_ACK) &&
(SEQ_LEQ(th->th_ack, tp->snd_una) ||
SEQ_GT(th->th_ack, tp->snd_max))) {
@@ -9212,7 +9216,8 @@
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -9309,7 +9314,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -9431,7 +9437,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -9556,7 +9563,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -9658,7 +9666,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -9761,7 +9770,8 @@
/* Reset receive buffer auto scaling when not in bulk receive mode. */
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
@@ -11825,7 +11835,7 @@
struct tcphdr *th;
struct udphdr *udp = NULL;
u_char opt[TCP_MAXOLEN];
- unsigned ipoptlen, optlen, hdrlen;
+ unsigned ipoptlen, optlen, hdrlen, dplen;
unsigned ulen;
uint32_t bbr_seq;
uint32_t delay_calc=0;
@@ -11854,6 +11864,7 @@
int32_t pacing_delay = 0;
struct inpcb *inp;
struct sockbuf *sb;
+ struct tcp_rst_diagnostic_payload *dp;
bool hpts_calling;
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
@@ -12103,6 +12114,11 @@
sendwin = min(tp->snd_wnd, tp->snd_cwnd);
sb_offset = tp->snd_max - tp->snd_una;
flags = tcp_outflags[tp->t_state];
+ if (((flags & TH_RST) != 0) &&
+ (tp->snd_rst_pen != 0 || tp->snd_rst_code != 0))
+ dplen = sizeof(struct tcp_rst_diagnostic_payload);
+ else
+ dplen = 0;
sack_rxmit = 0;
len = 0;
rsm = NULL;
@@ -13237,7 +13253,7 @@
} else
#endif
m->m_data += max_linkhdr;
- m->m_len = hdrlen;
+ m->m_len = hdrlen + dplen;
}
SOCK_SENDBUF_UNLOCK_ASSERT(so);
m->m_pkthdr.rcvif = (struct ifnet *)0;
@@ -13387,7 +13403,13 @@
* Put TCP length in extended header, and then checksum extended
* header and data.
*/
- m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */
+ m->m_pkthdr.len = hdrlen + len + dplen; /* in6_cksum() need this */
+ if (dplen > 0) {
+ dp = (struct tcp_rst_diagnostic_payload *)((caddr_t)(th + 1) + optlen);
+ dp->magic_nr = htons(TCP_RST_DIAGNOSTIC_PAYLOAD_MAGIC_NUMBER);
+ dp->rst_code = htons(tp->snd_rst_code);
+ dp->rst_pen = htonl(tp->snd_rst_pen);
+ }
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (to.to_flags & TOF_SIGNATURE) {
@@ -13464,9 +13486,9 @@
csum_flags |= CSUM_TSO;
m->m_pkthdr.tso_segsz = maxseg;
}
- KASSERT(len + hdrlen == m_length(m, NULL),
- ("%s: mbuf chain different than expected: %d + %u != %u",
- __func__, len, hdrlen, m_length(m, NULL)));
+ KASSERT(len + hdrlen + dplen == m_length(m, NULL),
+ ("%s: mbuf chain different than expected: %d + %u + %u != %u",
+ __func__, len, hdrlen, dplen, m_length(m, NULL)));
#ifdef TCP_HHOOK
/* Run HHOOK_TC_ESTABLISHED_OUT helper hooks. */
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -12751,6 +12751,9 @@
return (1);
}
if ((thflags & (TH_ACK | TH_RST)) == (TH_ACK | TH_RST)) {
+ if (tlen > 0)
+ KMOD_TCPSTAT_INC(tcps_rcv_rst_payload);
+ tcp_handle_diag_payload(tp, m, tlen, th->th_off << 2);
TCP_PROBE5(connect__refused, NULL, tp,
mtod(m, const char *), tp, th);
tp = tcp_drop(tp, ECONNREFUSED);
@@ -12956,7 +12959,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
if ((thflags & TH_ACK) &&
(SEQ_LEQ(th->th_ack, tp->snd_una) ||
SEQ_GT(th->th_ack, tp->snd_max))) {
@@ -13200,7 +13204,8 @@
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
@@ -13296,7 +13301,8 @@
ctf_calc_rwin(so, tp);
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -13421,7 +13427,8 @@
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -13543,7 +13550,8 @@
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -13644,7 +13652,8 @@
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -13747,7 +13756,8 @@
/* Reset receive buffer auto scaling when not in bulk receive mode. */
if ((thflags & TH_RST) ||
(tp->t_fin_is_rst && (thflags & TH_FIN)))
- return (ctf_process_rst(m, th, so, tp));
+ return (ctf_process_rst(m, th, so, tp, tlen, drop_hdrlen,
+ (thflags & TH_RST) != 0));
/*
* RFC5961 Section 4.2 Send challenge ACK for any SYN in
* synchronized state.
@@ -19563,7 +19573,7 @@
uint8_t check_done = 0;
uint8_t wanted_cookie = 0;
u_char opt[TCP_MAXOLEN];
- unsigned ipoptlen, optlen, hdrlen, ulen=0;
+ unsigned ipoptlen, optlen, hdrlen, ulen=0, dplen;
uint32_t rack_seq;
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
@@ -19589,6 +19599,7 @@
int32_t orig_len = 0;
struct timeval tv;
int32_t prefetch_so_done = 0;
+ struct tcp_rst_diagnostic_payload *dp;
struct tcp_log_buffer *lgb;
struct inpcb *inp = tptoinpcb(tp);
struct sockbuf *sb;
@@ -19935,6 +19946,11 @@
sb_offset = tp->snd_max - tp->snd_una;
cwnd_to_use = rack->r_ctl.cwnd_to_use = tp->snd_cwnd;
flags = tcp_outflags[tp->t_state];
+ if (((flags & TH_RST) != 0) &&
+ (tp->snd_rst_pen != 0 || tp->snd_rst_code != 0))
+ dplen = sizeof(struct tcp_rst_diagnostic_payload);
+ else
+ dplen = 0;
while (rack->rc_free_cnt < rack_free_cache) {
rsm = rack_alloc(rack);
if (rsm == NULL) {
@@ -21498,7 +21514,7 @@
} else
#endif
m->m_data += max_linkhdr;
- m->m_len = hdrlen;
+ m->m_len = hdrlen + dplen;
}
SOCK_SENDBUF_UNLOCK_ASSERT(so);
m->m_pkthdr.rcvif = (struct ifnet *)0;
@@ -21671,7 +21687,13 @@
* Put TCP length in extended header, and then checksum extended
* header and data.
*/
- m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */
+ m->m_pkthdr.len = hdrlen + len + dplen; /* in6_cksum() need this */
+ if (dplen > 0) {
+ dp = (struct tcp_rst_diagnostic_payload *)((caddr_t)(th + 1) + optlen);
+ dp->magic_nr = htons(TCP_RST_DIAGNOSTIC_PAYLOAD_MAGIC_NUMBER);
+ dp->rst_code = htons(tp->snd_rst_code);
+ dp->rst_pen = htonl(tp->snd_rst_pen);
+ }
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if (to.to_flags & TOF_SIGNATURE) {
/*
@@ -21750,9 +21772,9 @@
m->m_pkthdr.csum_flags |= CSUM_TSO;
m->m_pkthdr.tso_segsz = tp->t_maxseg - optlen;
}
- KASSERT(len + hdrlen == m_length(m, NULL),
- ("%s: mbuf chain different than expected: %d + %u != %u",
- __func__, len, hdrlen, m_length(m, NULL)));
+ KASSERT(len + hdrlen + dplen == m_length(m, NULL),
+ ("%s: mbuf chain different than expected: %d + %u +%u != %u",
+ __func__, len, hdrlen, dplen, m_length(m, NULL)));
#ifdef TCP_HHOOK
/* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */
diff --git a/sys/netinet/tcp_stacks/rack_bbr_common.h b/sys/netinet/tcp_stacks/rack_bbr_common.h
--- a/sys/netinet/tcp_stacks/rack_bbr_common.h
+++ b/sys/netinet/tcp_stacks/rack_bbr_common.h
@@ -106,8 +106,8 @@
ctf_do_drop(struct mbuf *m, struct tcpcb *tp);
int
-ctf_process_rst(struct mbuf *m, struct tcphdr *th,
- struct socket *so, struct tcpcb *tp);
+ctf_process_rst(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, int tlen, int offset, bool process_rst);
void
ctf_challenge_ack(struct mbuf *m, struct tcphdr *th,
diff --git a/sys/netinet/tcp_stacks/rack_bbr_common.c b/sys/netinet/tcp_stacks/rack_bbr_common.c
--- a/sys/netinet/tcp_stacks/rack_bbr_common.c
+++ b/sys/netinet/tcp_stacks/rack_bbr_common.c
@@ -692,7 +692,7 @@
int
ctf_process_rst(struct mbuf *m, struct tcphdr *th, struct socket *so,
- struct tcpcb *tp)
+ struct tcpcb *tp, int tlen, int offset, bool process_rst)
{
/*
* RFC5961 Section 3.2
@@ -733,6 +733,11 @@
tcp_state_change(tp, TCPS_CLOSED);
/* FALLTHROUGH */
default:
+ if (process_rst) {
+ if (tlen > 0)
+ KMOD_TCPSTAT_INC(tcps_rcv_rst_payload);
+ tcp_handle_diag_payload(tp, m, tlen, offset);
+ }
tcp_log_end_status(tp, TCP_EI_STATUS_CLIENT_RST);
tp = tcp_close(tp);
}
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -5036,3 +5036,19 @@
}
#endif
}
+
+void
+tcp_handle_diag_payload(struct tcpcb *tp, struct mbuf *m, int tlen, int offset)
+{
+ struct tcp_rst_diagnostic_payload dp;
+
+ if (tlen != sizeof(struct tcp_rst_diagnostic_payload))
+ return;
+ m_copydata(m, offset, sizeof(struct tcp_rst_diagnostic_payload),
+ (caddr_t)&dp);
+ if (dp.magic_nr == htons(TCP_RST_DIAGNOSTIC_PAYLOAD_MAGIC_NUMBER)) {
+ TCPSTAT_INC(tcps_rcv_rst_diag_payload);
+ tp->rcv_rst_code = ntohs(dp.rst_code);
+ tp->rcv_rst_pen = ntohl(dp.rst_pen);
+ }
+}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1003,6 +1003,8 @@
tcp_log_state_change(tp, tcp_get_bblog_state(sototcpcb(lso)));
}
#endif
+ tp->snd_rst_code = sototcpcb(lso)->snd_rst_code;
+ tp->snd_rst_pen = sototcpcb(lso)->snd_rst_pen;
/*
* Copy and activate timers.
*/
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1839,8 +1839,10 @@
MPASS(sopt->sopt_dir == SOPT_GET);
INP_WLOCK_ASSERT(inp);
+#if 0
KASSERT((inp->inp_flags & INP_DROPPED) == 0,
("inp_flags == %x", inp->inp_flags));
+#endif
KASSERT(so != NULL, ("inp_socket == NULL"));
if (sopt->sopt_level != IPPROTO_TCP) {
@@ -1889,7 +1891,7 @@
KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_flags & INP_DROPPED) {
+ if ((inp->inp_flags & INP_DROPPED) && (sopt->sopt_dir == SOPT_SET)) {
INP_WUNLOCK(inp);
return (ECONNRESET);
}
@@ -2040,11 +2042,14 @@
#ifdef STATS
struct statsblob *sbp;
#endif
+ struct tcp_rst_reason rst_reason;
size_t len;
INP_WLOCK_ASSERT(inp);
+#if 0
KASSERT((inp->inp_flags & INP_DROPPED) == 0,
("inp_flags == %x", inp->inp_flags));
+#endif
KASSERT(inp->inp_socket != NULL, ("inp_socket == NULL"));
switch (sopt->sopt_level) {
@@ -2457,6 +2462,23 @@
break;
#endif
+ case TCP_RST_REASON_CODE:
+ INP_WUNLOCK(inp);
+ error = sooptcopyin(sopt, &rst_reason,
+ sizeof(struct tcp_rst_reason),
+ sizeof(struct tcp_rst_reason));
+ if (error)
+ break;
+ INP_WLOCK_RECHECK(inp);
+ if (rst_reason.rst_reason_pen != 0 ||
+ rst_reason.rst_reason_code == 0) {
+ tp->snd_rst_code = rst_reason.rst_reason_code;
+ tp->snd_rst_pen = rst_reason.rst_reason_pen;
+ } else
+ error = EINVAL;
+ INP_WUNLOCK(inp);
+ break;
+
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -2627,6 +2649,14 @@
sizeof(optval));
break;
#endif
+ case TCP_RST_REASON_CODE:
+ rst_reason.rst_reason_code = tp->rcv_rst_code;
+ rst_reason.rst_reason_unused = 0;
+ rst_reason.rst_reason_pen = tp->rcv_rst_pen;
+ INP_WUNLOCK(inp);
+ error = sooptcopyout(sopt, &rst_reason,
+ sizeof(struct tcp_rst_reason));
+ break;
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -2970,6 +3000,13 @@
db_printf("t_lognum: %d t_loglimit: %d t_logsn: %u\n",
tp->t_lognum, tp->t_loglimit, tp->t_logsn);
+ db_print_indent(indent);
+ db_printf("snd_rst_code: %u snd_rst_pen: %u\n",
+ tp->snd_rst_code, tp->snd_rst_pen);
+ db_print_indent(indent);
+ db_printf("rcv_rst_code: %u rcv_rst_pen: %u\n",
+ tp->rcv_rst_code, tp->rcv_rst_pen);
+
if (show_bblog) {
#ifdef TCP_BLACKBOX
db_print_bblog_entries(&tp->t_logs, indent);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -480,6 +480,11 @@
};
struct osd t_osd; /* storage for Khelp module data */
uint8_t _t_logpoint; /* Used when a BB log points is enabled */
+ /* Support for Diagnostic Payload in RST segments */
+ uint16_t snd_rst_code; /* Reason code to be sent in RST */
+ uint16_t rcv_rst_code; /* Reason code received in RST */
+ uint32_t snd_rst_pen; /* PEN to be sent in RST */
+ uint32_t rcv_rst_pen; /* PEN received in RST */
/*
* Keep all #ifdef'ed components at the end of the structure!
* This is important to minimize problems when compiling modules
@@ -1120,6 +1125,10 @@
uint64_t tcps_rcvghostack; /* received ACK for data never sent */
uint64_t tcps_rcvacktooold; /* received ACK for data too long ago */
+ uint64_t tcps_rcv_rst_payload; /* received RST with payload */
+ uint64_t tcps_rcv_rst_diag_payload; /* received RST with diag payload */
+ uint64_t tcps_snd_rst_diag_payload; /* sent RST with diag payload */
+
uint64_t _pad[1]; /* 1 TBD placeholder for STABLE */
};
@@ -1429,6 +1438,7 @@
int tcp_input_with_port(struct mbuf **, int *, int, uint16_t);
void tcp_do_segment(struct tcpcb *, struct mbuf *, struct tcphdr *, int,
int, uint8_t);
+void tcp_handle_diag_payload(struct tcpcb *, struct mbuf *, int, int);
int register_tcp_functions(struct tcp_function_block *blk, int wait);
int register_tcp_functions_as_names(struct tcp_function_block *blk,
@@ -1615,6 +1625,13 @@
th->th_win = htons(th->th_win);
th->th_urp = htons(th->th_urp);
}
+
+struct tcp_rst_diagnostic_payload {
+ uint16_t magic_nr;
+ uint16_t rst_code;
+ uint32_t rst_pen;
+};
+#define TCP_RST_DIAGNOSTIC_PAYLOAD_MAGIC_NUMBER 0x33AA
#endif /* _KERNEL */
#endif /* _NETINET_TCP_VAR_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 23, 4:35 PM (13 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28941625
Default Alt Text
D55338.id172106.diff (21 KB)
Attached To
Mode
D55338: tcp: add support for TCP_RST_REASON_CODE socket option
Attached
Detach File
Event Timeline
Log In to Comment