Page MenuHomeFreeBSD

D55338.id172106.diff
No OneTemporary

D55338.id172106.diff

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

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)

Event Timeline