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 */ 24 25 #pragma D depends_on module unix 26 #pragma D depends_on provider dccp 27 28 inline int32_t DCCP_STATE_CLOSED = @DCCPS_CLOSED@; 29 #pragma D binding "1.10" DCCP_STATE_CLOSED 30 inline int32_t DCCP_STATE_BOUND = @DCCPS_BOUND@; 31 #pragma D binding "1.10" DCCP_STATE_BOUND 32 inline int32_t DCCP_STATE_REQUEST = @DCCPS_REQUEST@; 33 #pragma D binding "1.10" DCCP_STATE_REQUEST 34 inline int32_t DCCP_STATE_LISTEN = @DCCPS_LISTEN@; 35 #pragma D binding "1.10" DCCP_STATE_LISTEN 36 inline int32_t DCCP_STATE_PARTOPEN = @DCCPS_PARTOPEN@; 37 #pragma D binding "1.10" DCCP_STATE_PARTOPEN 38 inline int32_t DCCP_STATE_RESPOND = @DCCPS_RESPOND@; 39 #pragma D binding "1.10" DCCP_STATE_RESPOND 40 inline int32_t DCCP_STATE_OPEN = @DCCPS_OPEN@; 41 #pragma D binding "1.10" DCCP_STATE_OPEN 42 inline int32_t DCCP_STATE_CLOSING = @DCCPS_CLOSING@; 43 #pragma D binding "1.10" DCCP_STATE_CLOSING 44 inline int32_t DCCP_STATE_CLOSEREQ = @DCCPS_CLOSEREQ@; 45 #pragma D binding "1.10" DCCP_STATE_CLOSEREQ 46 inline int32_t DCCP_STATE_TIMEWAIT = @DCCPS_TIMEWAIT@; 47 #pragma D binding "1.10" DCCP_STATE_TIMEWAIT 48 49 /* 50 * Convert a DCCP state value to a string. 51 */ 52 inline string dccp_state_string[int32_t state] = 53 state == DCCP_STATE_CLOSED ? "state-closed" : 54 state == DCCP_STATE_BOUND ? "state-bound" : 55 state == DCCP_STATE_REQUEST ? "state-request" : 56 state == DCCP_STATE_LISTEN ? "state-listen" : 57 state == DCCP_STATE_PARTOPEN ? "state-partopen" : 58 state == DCCP_STATE_RESPOND ? "state-respond" : 59 state == DCCP_STATE_OPEN ? "state-open" : 60 state == DCCP_STATE_CLOSING ? "state-closing" : 61 state == DCCP_STATE_CLOSEREQ ? "state-closereq" : 62 state == DCCP_STATE_TIMEWAIT ? "state-timewait" : 63 "<unknown>"; 64 #pragma D binding "1.10" dccp_state_string 65 66 /* 67 * dccpinfo is the DCCP header fields. 68 */ 69 typedef struct dccpinfo { 70 uint16_t dccp_sport; /* source port */ 71 uint16_t dccp_dport; /* destination port */ 72 uint32_t dccp_seq; /* sequence number */ 73 uint8_t dccp_offset; /* data offset, in bytes */ 74 uint16_t dccp_checksum; /* checksum */ 75 dccph_t *dccp_hdr; /* raw DCCP header */ 76 } dccpinfo_t; 77 78 /* 79 * dccpsinfo contains stable DCCP details from dccp_t. 80 */ 81 typedef struct dccpsinfo { 82 uintptr_t dccps_addr; 83 int dccps_local; /* Is delivered locally, boolean */ 84 int dccps_active; /* Active open (from here), boolean */ 85 uint16_t dccps_lport; /* Local port */ 86 uint16_t dccps_rport; /* Remote port */ 87 string dccps_laddr; /* Local address, as a string */ 88 string dccps_raddr; /* Remote address, as a string */ 89 int32_t dccps_state; /* DCCP state */ 90 uint32_t dccps_iss; /* Initial sequence # sent */ 91 } dccpsinfo_t; 92 93 /* 94 * dccplsinfo provides the old dccp state for state changes. 95 */ 96 typedef struct dccplsinfo { 97 int32_t dccps_state; /* Previous DCCP state */ 98 } dccplsinfo_t; 99 100 /* 101 * __dtrace_tcp_tcph_t is used by the tcpinfo_t * translator to take either 102 * the non-NULL tcph_t * passed in or, if it is NULL, uses arg3 (tcp_t *) 103 * from the tcp:::send and tcp:::recieve probes and translates the tcp_t * 104 * into the tcpinfo_t. When no headers are available - as is the case for 105 * TCP fusion tcp:::send and tcp:::receive - this allows us to present the 106 * consumer with header data based on tcp_t * content and hide TCP fusion 107 * implementation details. 108 */ 109 typedef dccph_t * __dtrace_dccp_dccph_t; 110 111 #pragma D binding "1.10" translator 112 translator dccpinfo_t < dccph_t *T > { 113 dccp_sport = ntohs(*(uint16_t *)T->dh_lport); 114 dccp_dport = ntohs(*(uint16_t *)T->dh_fport); 115 dccp_seq = ntohl(*(uint32_t *)T->dh_seq); /* XXX */ 116 dccp_offset = (*(uint8_t *)T->dh_offset & 0xf0) >> 2; 117 dccp_checksum = ntohs(*(uint16_t *)T->dh_sum); 118 dccp_hdr = T; 119 }; 120 121 #pragma D binding "1.10" translator 122 translator dccpinfo_t < __dtrace_dccp_dccph_t *T > { 123 dccp_sport = 124 T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_lport) : 125 arg3 != NULL && probename == "send" ? 126 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_lport) : 127 arg3 != NULL && probename == "receive" ? 128 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_fport) : 129 0; 130 dccp_dport = 131 T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_fport) : 132 arg3 != NULL && probename == "send" ? 133 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_fport) : 134 arg3 != NULL && probename == "receive" ? 135 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_lport) : 136 0; 137 dccp_seq = 138 T != NULL ? ntohl(*(uint32_t *)((dccph_t *)T)->dh_seq) : 139 0; 140 dccp_offset = T != NULL ? 141 (*(uint8_t *)((dccph_t *)T)->dh_offset & 0xf0) >> 2 : 142 @DCCP_MIN_HEADER_LENGTH@; 143 dccp_checksum = T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_sum) : 144 0; 145 dccp_hdr = NULL; 146 }; 147 148 #pragma D binding "1.10" translator 149 translator dccpsinfo_t < dccp_t *T > { 150 dccps_addr = (uintptr_t)T; 151 /* 152 * The following two members should just use tcp_t->tcp_loopback 153 * and tcp_t->tcp_active_open, however these are bit fields and 154 * can't be used until CR 6876830 is fixed. Meanwhile we source 155 * them a different way. 156 */ 157 dccps_local = T ? T->dccp_ipha ? 158 T->dccp_ipha->ipha_src == T->dccp_ipha->ipha_dst : 1 : 0; 159 dccps_active = T ? !T->dccp_saved_listener : 0; 160 dccps_lport = T ? 161 ntohs(T->dccp_connp->u_port.connu_ports.connu_lport) : 0; 162 dccps_rport = T ? 163 ntohs(T->dccp_connp->u_port.connu_ports.connu_fport) : 0; 164 dccps_laddr = T ? 165 inet_ntoa6(&T->dccp_connp->connua_v6addr.connua_laddr) : "<unknown>"; 166 dccps_raddr = T ? 167 inet_ntoa6(&T->dccp_connp->connua_v6addr.connua_faddr) : "<unknown>"; 168 dccps_state = T ? T->dccp_state : DCCP_STATE_CLOSED; 169 dccps_iss = T ? T->dccp_iss : 0; 170 }; 171 172 /* 173 * Note: although we specify that the old state argument used as the 174 * input to the tcplsinfo_t translator is an int32_t, it reaches us as an 175 * int64_t (since it is a probe argument) so explicitly cast it back to 176 * interpret the negatively-valued states correctly. 177 */ 178 #pragma D binding "1.10" translator 179 translator dccplsinfo_t < int64_t I > { 180 dccps_state = (int32_t) I; 181 };