1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2013 Mark Johnston <markj@freebsd.org> 24 */ 25 26 #pragma D depends_on library ip.d 27 #pragma D depends_on module kernel 28 #pragma D depends_on provider tcp 29 30 /* 31 * Convert a TCP state value to a string. 32 */ 33 #pragma D binding "1.6.3" TCPS_CLOSED 34 inline int TCPS_CLOSED = 0; 35 #pragma D binding "1.6.3" TCPS_LISTEN 36 inline int TCPS_LISTEN = 1; 37 #pragma D binding "1.6.3" TCPS_SYN_SENT 38 inline int TCPS_SYN_SENT = 2; 39 #pragma D binding "1.6.3" TCPS_SYN_RECEIVED 40 inline int TCPS_SYN_RECEIVED = 3; 41 #pragma D binding "1.6.3" TCPS_ESTABLISHED 42 inline int TCPS_ESTABLISHED = 4; 43 #pragma D binding "1.6.3" TCPS_CLOSE_WAIT 44 inline int TCPS_CLOSE_WAIT = 5; 45 #pragma D binding "1.6.3" TCPS_FIN_WAIT_1 46 inline int TCPS_FIN_WAIT_1 = 6; 47 #pragma D binding "1.6.3" TCPS_CLOSING 48 inline int TCPS_CLOSING = 7; 49 #pragma D binding "1.6.3" TCPS_LAST_ACK 50 inline int TCPS_LAST_ACK = 8; 51 #pragma D binding "1.6.3" TCPS_FIN_WAIT_2 52 inline int TCPS_FIN_WAIT_2 = 9; 53 #pragma D binding "1.6.3" TCPS_TIME_WAIT 54 inline int TCPS_TIME_WAIT = 10; 55 56 /* 57 * For compatibility also provide the names used by Solaris. 58 */ 59 #pragma D binding "1.13" TCP_STATE_CLOSED 60 inline int TCP_STATE_CLOSED = TCPS_CLOSED; 61 #pragma D binding "1.13" TCP_STATE_LISTEN 62 inline int TCP_STATE_LISTEN = TCPS_LISTEN; 63 #pragma D binding "1.13" TCP_STATE_SYN_SENT 64 inline int TCP_STATE_SYN_SENT = TCPS_SYN_SENT; 65 #pragma D binding "1.13" TCP_STATE_SYN_RECEIVED 66 inline int TCP_STATE_SYN_RECEIVED = TCPS_SYN_RECEIVED; 67 #pragma D binding "1.13" TCP_STATE_ESTABLISHED 68 inline int TCP_STATE_ESTABLISHED = TCPS_ESTABLISHED; 69 #pragma D binding "1.13" TCP_STATE_CLOSE_WAIT 70 inline int TCP_STATE_CLOSE_WAIT = TCPS_CLOSE_WAIT; 71 #pragma D binding "1.13" TCP_STATE_FIN_WAIT_1 72 inline int TCP_STATE_FIN_WAIT_1 = TCPS_FIN_WAIT_1; 73 #pragma D binding "1.13" TCP_STATE_CLOSING 74 inline int TCP_STATE_CLOSING = TCPS_CLOSING; 75 #pragma D binding "1.13" TCP_STATE_LAST_ACK 76 inline int TCP_STATE_LAST_ACK = TCPS_LAST_ACK; 77 #pragma D binding "1.13" TCP_STATE_FIN_WAIT_2 78 inline int TCP_STATE_FIN_WAIT_2 = TCPS_FIN_WAIT_2; 79 #pragma D binding "1.13" TCP_STATE_TIME_WAIT 80 inline int TCP_STATE_TIME_WAIT = TCPS_TIME_WAIT; 81 82 /* TCP segment flags. */ 83 #pragma D binding "1.6.3" TH_FIN 84 inline uint8_t TH_FIN = 0x01; 85 #pragma D binding "1.6.3" TH_SYN 86 inline uint8_t TH_SYN = 0x02; 87 #pragma D binding "1.6.3" TH_RST 88 inline uint8_t TH_RST = 0x04; 89 #pragma D binding "1.6.3" TH_PUSH 90 inline uint8_t TH_PUSH = 0x08; 91 #pragma D binding "1.6.3" TH_ACK 92 inline uint8_t TH_ACK = 0x10; 93 #pragma D binding "1.6.3" TH_URG 94 inline uint8_t TH_URG = 0x20; 95 #pragma D binding "1.6.3" TH_ECE 96 inline uint8_t TH_ECE = 0x40; 97 #pragma D binding "1.6.3" TH_CWR 98 inline uint8_t TH_CWR = 0x80; 99 100 /* TCP connection state strings. */ 101 #pragma D binding "1.6.3" tcp_state_string 102 inline string tcp_state_string[int32_t state] = 103 state == TCPS_CLOSED ? "state-closed" : 104 state == TCPS_LISTEN ? "state-listen" : 105 state == TCPS_SYN_SENT ? "state-syn-sent" : 106 state == TCPS_SYN_RECEIVED ? "state-syn-received" : 107 state == TCPS_ESTABLISHED ? "state-established" : 108 state == TCPS_CLOSE_WAIT ? "state-close-wait" : 109 state == TCPS_FIN_WAIT_1 ? "state-fin-wait-1" : 110 state == TCPS_CLOSING ? "state-closing" : 111 state == TCPS_LAST_ACK ? "state-last-ack" : 112 state == TCPS_FIN_WAIT_2 ? "state-fin-wait-2" : 113 state == TCPS_TIME_WAIT ? "state-time-wait" : 114 "<unknown>"; 115 116 /* 117 * tcpsinfo contains stable TCP details from tcp_t. 118 */ 119 typedef struct tcpsinfo { 120 uintptr_t tcps_addr; 121 int tcps_local; /* is delivered locally, boolean */ 122 int tcps_active; /* active open (from here), boolean */ 123 uint16_t tcps_lport; /* local port */ 124 uint16_t tcps_rport; /* remote port */ 125 string tcps_laddr; /* local address, as a string */ 126 string tcps_raddr; /* remote address, as a string */ 127 int32_t tcps_state; /* TCP state */ 128 uint32_t tcps_iss; /* Initial sequence # sent */ 129 uint32_t tcps_irs; /* Initial sequence # received */ 130 uint32_t tcps_suna; /* sequence # sent but unacked */ 131 uint32_t tcps_smax; /* highest sequence number sent */ 132 uint32_t tcps_snxt; /* next sequence # to send */ 133 uint32_t tcps_rack; /* sequence # we have acked */ 134 uint32_t tcps_rnxt; /* next sequence # expected */ 135 u_long tcps_swnd; /* send window size */ 136 int32_t tcps_snd_ws; /* send window scaling */ 137 uint32_t tcps_swl1; /* window update seg seq number */ 138 uint32_t tcps_swl2; /* window update seg ack number */ 139 uint32_t tcps_rup; /* receive urgent pointer */ 140 uint32_t tcps_radv; /* advertised window */ 141 u_long tcps_rwnd; /* receive window size */ 142 int32_t tcps_rcv_ws; /* receive window scaling */ 143 u_long tcps_cwnd; /* congestion window */ 144 u_long tcps_cwnd_ssthresh; /* threshold for congestion avoidance */ 145 uint32_t tcps_srecover; /* for use in NewReno Fast Recovery */ 146 uint32_t tcps_sack_fack; /* SACK sequence # we have acked */ 147 uint32_t tcps_sack_snxt; /* next SACK seq # for retransmission */ 148 uint32_t tcps_rto; /* round-trip timeout, msec */ 149 uint32_t tcps_mss; /* max segment size */ 150 int tcps_retransmit; /* retransmit send event, boolean */ 151 int tcps_srtt; /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */ 152 int tcps_debug; /* socket has SO_DEBUG set */ 153 int tcps_cookie; /* expose the socket's SO_USER_COOKIE */ 154 int32_t tcps_dupacks; /* consecutive dup acks received */ 155 uint32_t tcps_rtttime; /* RTT measurement start time */ 156 uint32_t tcps_rtseq; /* sequence # being timed */ 157 uint32_t tcps_ts_recent; /* timestamp echo data */ 158 } tcpsinfo_t; 159 160 /* 161 * tcplsinfo provides the old tcp state for state changes. 162 */ 163 typedef struct tcplsinfo { 164 int32_t tcps_state; /* previous TCP state */ 165 } tcplsinfo_t; 166 167 /* 168 * tcpinfo is the TCP header fields. 169 */ 170 typedef struct tcpinfo { 171 uint16_t tcp_sport; /* source port */ 172 uint16_t tcp_dport; /* destination port */ 173 uint32_t tcp_seq; /* sequence number */ 174 uint32_t tcp_ack; /* acknowledgment number */ 175 uint8_t tcp_offset; /* data offset, in bytes */ 176 uint8_t tcp_flags; /* flags */ 177 uint16_t tcp_window; /* window size */ 178 uint16_t tcp_checksum; /* checksum */ 179 uint16_t tcp_urgent; /* urgent data pointer */ 180 struct tcphdr *tcp_hdr; /* raw TCP header */ 181 } tcpinfo_t; 182 183 /* 184 * A clone of tcpinfo_t used to handle the fact that the TCP input path 185 * overwrites some fields of the TCP header with their host-order equivalents. 186 * Unfortunately, DTrace doesn't let us simply typedef a new name for struct 187 * tcpinfo and define a separate translator for it. 188 */ 189 typedef struct tcpinfoh { 190 uint16_t tcp_sport; /* source port */ 191 uint16_t tcp_dport; /* destination port */ 192 uint32_t tcp_seq; /* sequence number */ 193 uint32_t tcp_ack; /* acknowledgment number */ 194 uint8_t tcp_offset; /* data offset, in bytes */ 195 uint8_t tcp_flags; /* flags */ 196 uint16_t tcp_window; /* window size */ 197 uint16_t tcp_checksum; /* checksum */ 198 uint16_t tcp_urgent; /* urgent data pointer */ 199 struct tcphdr *tcp_hdr; /* raw TCP header */ 200 } tcpinfoh_t; 201 202 #pragma D binding "1.6.3" translator 203 translator csinfo_t < struct tcpcb *p > { 204 cs_addr = NULL; 205 cs_cid = (uint64_t)(p == NULL ? 0 : &p->t_inpcb); 206 cs_pid = 0; 207 cs_zoneid = 0; 208 }; 209 210 #pragma D binding "1.6.3" translator 211 translator tcpsinfo_t < struct tcpcb *p > { 212 tcps_addr = (uintptr_t)p; 213 tcps_local = -1; /* XXX */ 214 tcps_active = -1; /* XXX */ 215 tcps_lport = p == NULL ? 0 : ntohs(p->t_inpcb.inp_inc.inc_ie.ie_lport); 216 tcps_rport = p == NULL ? 0 : ntohs(p->t_inpcb.inp_inc.inc_ie.ie_fport); 217 tcps_laddr = p == NULL ? "<unknown>" : 218 p->t_inpcb.inp_vflag == INP_IPV4 ? 219 inet_ntoa(&p->t_inpcb.inp_inc.inc_ie.ie_dependladdr.id46_addr.ia46_addr4.s_addr) : 220 inet_ntoa6(&p->t_inpcb.inp_inc.inc_ie.ie_dependladdr.id6_addr); 221 tcps_raddr = p == NULL ? "<unknown>" : 222 p->t_inpcb.inp_vflag == INP_IPV4 ? 223 inet_ntoa(&p->t_inpcb.inp_inc.inc_ie.ie_dependfaddr.id46_addr.ia46_addr4.s_addr) : 224 inet_ntoa6(&p->t_inpcb.inp_inc.inc_ie.ie_dependfaddr.id6_addr); 225 tcps_state = p == NULL ? -1 : p->t_state; 226 tcps_iss = p == NULL ? 0 : p->iss; 227 tcps_irs = p == NULL ? 0 : p->irs; 228 tcps_suna = p == NULL ? 0 : p->snd_una; 229 tcps_smax = p == NULL ? 0 : p->snd_max; 230 tcps_snxt = p == NULL ? 0 : p->snd_nxt; 231 tcps_rack = p == NULL ? 0 : p->last_ack_sent; 232 tcps_rnxt = p == NULL ? 0 : p->rcv_nxt; 233 tcps_swnd = p == NULL ? -1 : p->snd_wnd; 234 tcps_snd_ws = p == NULL ? -1 : p->snd_scale; 235 tcps_swl1 = p == NULL ? -1 : p->snd_wl1; 236 tcps_swl2 = p == NULL ? -1 : p->snd_wl2; 237 tcps_radv = p == NULL ? -1 : p->rcv_adv; 238 tcps_rwnd = p == NULL ? -1 : p->rcv_wnd; 239 tcps_rup = p == NULL ? -1 : p->rcv_up; 240 tcps_rcv_ws = p == NULL ? -1 : p->rcv_scale; 241 tcps_cwnd = p == NULL ? -1 : p->snd_cwnd; 242 tcps_cwnd_ssthresh = p == NULL ? -1 : p->snd_ssthresh; 243 tcps_srecover = p == NULL ? -1 : p->snd_recover; 244 tcps_sack_fack = p == NULL ? 0 : p->snd_fack; 245 tcps_sack_snxt = p == NULL ? 0 : p->snd_recover; 246 tcps_rto = p == NULL ? -1 : (p->t_rxtcur * 1000) / `hz; 247 tcps_mss = p == NULL ? -1 : p->t_maxseg; 248 tcps_retransmit = p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0; 249 tcps_srtt = p == NULL ? -1 : p->t_srtt; /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */ 250 tcps_debug = p == NULL ? 0 : 251 p->t_inpcb.inp_socket->so_options & 1; 252 tcps_cookie = p == NULL ? -1 : 253 p->t_inpcb.inp_socket->so_user_cookie; 254 tcps_dupacks = p == NULL ? -1 : p->t_dupacks; 255 tcps_rtttime = p == NULL ? -1 : p->t_rtttime; 256 tcps_rtseq = p == NULL ? -1 : p->t_rtseq; 257 tcps_ts_recent = p == NULL ? -1 : p->ts_recent; 258 }; 259 260 #pragma D binding "1.6.3" translator 261 translator tcpinfo_t < struct tcphdr *p > { 262 tcp_sport = p == NULL ? 0 : ntohs(p->th_sport); 263 tcp_dport = p == NULL ? 0 : ntohs(p->th_dport); 264 tcp_seq = p == NULL ? -1 : ntohl(p->th_seq); 265 tcp_ack = p == NULL ? -1 : ntohl(p->th_ack); 266 tcp_offset = p == NULL ? -1 : (p->th_off >> 2); 267 tcp_flags = p == NULL ? 0 : p->th_flags; 268 tcp_window = p == NULL ? 0 : ntohs(p->th_win); 269 tcp_checksum = p == NULL ? 0 : ntohs(p->th_sum); 270 tcp_urgent = p == NULL ? 0 : ntohs(p->th_urp); 271 tcp_hdr = (struct tcphdr *)p; 272 }; 273 274 /* 275 * This translator differs from the one for tcpinfo_t in that the sequence 276 * number, acknowledgement number, window size and urgent pointer are already 277 * in host order and thus don't need to be converted. 278 */ 279 #pragma D binding "1.6.3" translator 280 translator tcpinfoh_t < struct tcphdr *p > { 281 tcp_sport = p == NULL ? 0 : ntohs(p->th_sport); 282 tcp_dport = p == NULL ? 0 : ntohs(p->th_dport); 283 tcp_seq = p == NULL ? -1 : p->th_seq; 284 tcp_ack = p == NULL ? -1 : p->th_ack; 285 tcp_offset = p == NULL ? -1 : (p->th_off >> 2); 286 tcp_flags = p == NULL ? 0 : p->th_flags; 287 tcp_window = p == NULL ? 0 : p->th_win; 288 tcp_checksum = p == NULL ? 0 : ntohs(p->th_sum); 289 tcp_urgent = p == NULL ? 0 : p->th_urp; 290 tcp_hdr = (struct tcphdr *)p; 291 }; 292 293 #pragma D binding "1.6.3" translator 294 translator tcplsinfo_t < int s > { 295 tcps_state = s; 296 }; 297 298 299 /* Support for TCP debug */ 300 301 #pragma D binding "1.12.1" TA_INPUT 302 inline int TA_INPUT = 0; 303 #pragma D binding "1.12.1" TA_OUTPUT 304 inline int TA_OUTPUT = 1; 305 #pragma D binding "1.12.1" TA_USER 306 inline int TA_USER = 2; 307 #pragma D binding "1.12.1" TA_RESPOND 308 inline int TA_RESPOND = 3; 309 #pragma D binding "1.12.1" TA_DROP 310 inline int TA_DROP = 4; 311 312 /* direction strings. */ 313 314 #pragma D binding "1.12.1" tcpdebug_dir_string 315 inline string tcpdebug_dir_string[uint8_t direction] = 316 direction == TA_INPUT ? "input" : 317 direction == TA_OUTPUT ? "output" : 318 direction == TA_USER ? "user" : 319 direction == TA_RESPOND ? "respond" : 320 direction == TA_OUTPUT ? "drop" : 321 "unknown" ; 322 323 #pragma D binding "1.12.1" tcpflag_string 324 inline string tcpflag_string[uint8_t flags] = 325 flags & TH_FIN ? "FIN" : 326 flags & TH_SYN ? "SYN" : 327 flags & TH_RST ? "RST" : 328 flags & TH_PUSH ? "PUSH" : 329 flags & TH_ACK ? "ACK" : 330 flags & TH_URG ? "URG" : 331 flags & TH_ECE ? "ECE" : 332 flags & TH_CWR ? "CWR" : 333 "unknown" ; 334 335 #pragma D binding "1.12.1" PRU_ATTACH 336 inline int PRU_ATTACH = 0; 337 #pragma D binding "1.12.1" PRU_DETACH 338 inline int PRU_DETACH = 1; 339 #pragma D binding "1.12.1" PRU_BIND 340 inline int PRU_BIND = 2; 341 #pragma D binding "1.12.1" PRU_LISTEN 342 inline int PRU_LISTEN = 3; 343 #pragma D binding "1.12.1" PRU_CONNECT 344 inline int PRU_CONNECT = 4; 345 #pragma D binding "1.12.1" PRU_ACCEPT 346 inline int PRU_ACCEPT = 5 ; 347 #pragma D binding "1.12.1" PRU_DISCONNECT 348 inline int PRU_DISCONNECT = 6; 349 #pragma D binding "1.12.1" PRU_SHUTDOWN 350 inline int PRU_SHUTDOWN = 7; 351 #pragma D binding "1.12.1" PRU_RCVD 352 inline int PRU_RCVD = 8; 353 #pragma D binding "1.12.1" PRU_SEND 354 inline int PRU_SEND = 9; 355 #pragma D binding "1.12.1" PRU_ABORT 356 inline int PRU_ABORT = 10; 357 #pragma D binding "1.12.1" PRU_CONTROL 358 inline int PRU_CONTROL = 11; 359 #pragma D binding "1.12.1" PRU_SENSE 360 inline int PRU_SENSE = 12; 361 #pragma D binding "1.12.1" PRU_RCVOOB 362 inline int PRU_RCVOOB = 13; 363 #pragma D binding "1.12.1" PRU_SENDOOB 364 inline int PRU_SENDOOB = 14; 365 #pragma D binding "1.12.1" PRU_SOCKADDR 366 inline int PRU_SOCKADDR = 15; 367 #pragma D binding "1.12.1" PRU_PEERADDR 368 inline int PRU_PEERADDR = 16; 369 #pragma D binding "1.12.1" PRU_CONNECT2 370 inline int PRU_CONNECT2 = 17; 371 #pragma D binding "1.12.1" PRU_FASTTIMO 372 inline int PRU_FASTTIMO = 18; 373 #pragma D binding "1.12.1" PRU_SLOWTIMO 374 inline int PRU_SLOWTIMO = 19; 375 #pragma D binding "1.12.1" PRU_PROTORCV 376 inline int PRU_PROTORCV = 20; 377 #pragma D binding "1.12.1" PRU_PROTOSEND 378 inline int PRU_PROTOSEND = 21; 379 #pragma D binding "1.12.1" PRU_SEND_EOF 380 inline int PRU_SEND_EOF = 22; 381 #pragma D binding "1.12.1" PRU_SOSETLABEL 382 inline int PRU_SOSETLABEL = 23; 383 #pragma D binding "1.12.1" PRU_CLOSE 384 inline int PRU_CLOSE = 24; 385 #pragma D binding "1.12.1" PRU_FLUSH 386 inline int PRU_FLUSH = 25; 387 388 #pragma D binding "1.12.1" prureq_string 389 inline string prureq_string[uint8_t req] = 390 req == PRU_ATTACH ? "ATTACH" : 391 req == PRU_DETACH ? "DETACH" : 392 req == PRU_BIND ? "BIND" : 393 req == PRU_LISTEN ? "LISTEN" : 394 req == PRU_CONNECT ? "CONNECT" : 395 req == PRU_ACCEPT ? "ACCEPT" : 396 req == PRU_DISCONNECT ? "DISCONNECT" : 397 req == PRU_SHUTDOWN ? "SHUTDOWN" : 398 req == PRU_RCVD ? "RCVD" : 399 req == PRU_SEND ? "SEND" : 400 req == PRU_ABORT ? "ABORT" : 401 req == PRU_CONTROL ? "CONTROL" : 402 req == PRU_SENSE ? "SENSE" : 403 req == PRU_RCVOOB ? "RCVOOB" : 404 req == PRU_SENDOOB ? "SENDOOB" : 405 req == PRU_SOCKADDR ? "SOCKADDR" : 406 req == PRU_PEERADDR ? "PEERADDR" : 407 req == PRU_CONNECT2 ? "CONNECT2" : 408 req == PRU_FASTTIMO ? "FASTTIMO" : 409 req == PRU_SLOWTIMO ? "SLOWTIMO" : 410 req == PRU_PROTORCV ? "PROTORCV" : 411 req == PRU_PROTOSEND ? "PROTOSEND" : 412 req == PRU_SEND ? "SEND_EOF" : 413 req == PRU_SOSETLABEL ? "SOSETLABEL" : 414 req == PRU_CLOSE ? "CLOSE" : 415 req == PRU_FLUSH ? "FLUSE" : 416 "unknown" ; 417