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 };