1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
|
/*
* Oracle Linux DTrace.
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
#pragma D depends_on module vmlinux
#pragma D depends_on library net.d
#pragma D depends_on library procfs.d
#pragma D depends_on provider ip
inline int IPPROTO_IP = 0;
inline int IPPROTO_ICMP = 1;
inline int IPPROTO_IGMP = 2;
inline int IPPROTO_IPIP = 4;
inline int IPPROTO_TCP = 6;
inline int IPPROTO_EGP = 8;
inline int IPPROTO_PUP = 12;
inline int IPPROTO_UDP = 17;
inline int IPPROTO_IDP = 22;
inline int IPPROTO_TP = 29;
inline int IPPROTO_DCCP = 33;
inline int IPPROTO_IPV6 = 41;
inline int IPPROTO_RSVP = 46;
inline int IPPROTO_GRE = 47;
inline int IPPROTO_ESP = 50;
inline int IPPROTO_AH = 51;
inline int IPPROTO_OSPF = 89;
inline int IPPROTO_MTP = 92;
inline int IPPROTO_BEETPH = 94;
inline int IPPROTO_ENCAP = 98;
inline int IPPROTO_PIM = 103;
inline int IPPROTO_COMP = 108;
inline int IPPROTO_SCTP = 132;
inline int IPPROTO_UDPLITE = 136;
inline int IPPROTO_RAW = 255;
inline int IPPROTO_MAX = 256;
inline int IPPROTO_HOPOPTS = 0;
inline int IPPROTO_ROUTING = 43;
inline int IPPROTO_FRAGMENT = 44;
inline int IPPROTO_ICMPV6 = 58;
inline int IPPROTO_NONE = 59;
inline int IPPROTO_DSTOPTS = 60;
inline int IPPROTO_MH = 135;
inline int TCP_MIN_HEADER_LENGTH = 20;
/*
* ipinfo contains common IP info for both IPv4 and IPv6.
*/
typedef struct ipinfo {
uint8_t ip_ver; /* IP version (4, 6) */
uint32_t ip_plength; /* payload length */
string ip_saddr; /* source address */
string ip_daddr; /* destination address */
} ipinfo_t;
/*
* ifinfo contains network interface info.
*/
typedef struct ifinfo {
string if_name; /* interface name */
int8_t if_local; /* is delivered locally */
netstackid_t if_ipstack; /* netns pointer on Linux */
uintptr_t if_addr; /* pointer to raw struct net_device */
} ifinfo_t;
/*
* ipv4info is a translated version of the IPv4 header (with raw pointer).
* These values are NULL if the packet is not IPv4.
*/
typedef struct ipv4info {
uint8_t ipv4_ver; /* IP version (4) */
uint8_t ipv4_ihl; /* header length, bytes */
uint8_t ipv4_tos; /* type of service field */
uint16_t ipv4_length; /* length (header + payload) */
uint16_t ipv4_ident; /* identification */
uint8_t ipv4_flags; /* IP flags */
uint16_t ipv4_offset; /* fragment offset */
uint8_t ipv4_ttl; /* time to live */
uint8_t ipv4_protocol; /* next level protocol */
string ipv4_protostr; /* next level protocol, as string */
uint16_t ipv4_checksum; /* header checksum */
ipaddr_t ipv4_src; /* source address */
ipaddr_t ipv4_dst; /* destination address */
string ipv4_saddr; /* source address, string */
string ipv4_daddr; /* destination address, string */
struct iphdr *ipv4_hdr; /* pointer to raw header */
} ipv4info_t;
/*
* ipv6info is a translated version of the IPv6 header (with raw pointer).
* These values are NULL if the packet is not IPv6.
*/
typedef struct ipv6info {
uint8_t ipv6_ver; /* IP version (6) */
uint8_t ipv6_tclass; /* traffic class */
uint32_t ipv6_flow; /* flow label */
uint16_t ipv6_plen; /* payload length */
uint8_t ipv6_nexthdr; /* next header protocol */
string ipv6_nextstr; /* next header protocol, as string */
uint8_t ipv6_hlim; /* hop limit */
in6_addr_t *ipv6_src; /* source address */
in6_addr_t *ipv6_dst; /* destination address */
string ipv6_saddr; /* source address, string */
string ipv6_daddr; /* destination address, string */
struct ipv6hdr *ipv6_hdr; /* pointer to raw header */
} ipv6info_t;
/*
* void_ip_t is a void pointer to either an IPv4 or IPv6 header. It has
* its own type name so that a translator can be determined.
*/
typedef uintptr_t void_ip_t;
/*
* __dtrace_tcp_void_ip_t is used by the translator to take either the
* non-NULL void_ip_t * passed in or, if it is NULL, uses arg3 (struct tcp *)
* from the tcp:::send probe to translate to an ipinfo_t.
* This allows us to present the consumer with header data based on the
* struct tcp * when IP information is not yet present (for TCP send).
*/
typedef void * __dtrace_tcp_void_ip_t;
#pragma D binding "1.5" translator
translator pktinfo_t < struct sk_buff *s > {
pkt_addr = (uintptr_t)s;
};
#pragma D binding "1.5" translator
translator csinfo_t < struct sock *s > {
cs_addr = (uintptr_t)s;
};
#pragma D binding "1.5" translator
translator ipinfo_t < struct iphdr *I > {
ip_ver = 4;
ip_plength = I != NULL ? (ntohs(I->tot_len) - I->ihl << 2) : 0;
ip_saddr = I != NULL ? inet_ntoa(&I->saddr) : "<unknown>";
ip_daddr = I != NULL ? inet_ntoa(&I->daddr) : "<unknown>";
};
#pragma D binding "1.5" translator
translator ipinfo_t < struct ipv6hdr *I > {
ip_ver = 6;
ip_plength = I != NULL ? ntohs(I->payload_len) : 0;
ip_saddr = I != NULL ? inet_ntoa6(&I->saddr) : "<unknown>";
ip_daddr = I != NULL ? inet_ntoa6(&I->daddr) : "<unknown>";
};
#pragma D binding "1.5" translator
translator ipinfo_t < void_ip_t *I > {
ip_ver = I != NULL ? *(uint8_t *)I >> 4 : 0;
ip_plength = I != NULL ? (*(uint8_t *)I >> 4 == 4 ?
(ntohs(((struct iphdr *)I)->tot_len) - ((*(uint8_t *)I & 0xf) << 2)) :
*(uint8_t *)I >> 4 == 6 ?
ntohs(((struct ipv6hdr *)I)->payload_len) : 0) : 0;
ip_saddr = I != NULL ? (*(uint8_t *)I >> 4 == 4 ?
inet_ntoa(&((struct iphdr *)I)->saddr) : *(uint8_t *)I >> 4 == 6 ?
inet_ntoa6(&((struct ipv6hdr *)I)->saddr) : "<unknown>") :
"<unknown>";
ip_daddr = I != NULL ? (*(uint8_t *)I >> 4 == 4 ?
inet_ntoa(&((struct iphdr *)I)->daddr) : *(uint8_t *)I >> 4 == 6 ?
inet_ntoa6(&((struct ipv6hdr *)I)->daddr) : "<unknown>") :
"<unknown>";
};
/*
* In some cases where the ipinfo_t * is NULL we wish to construct IP info
* using the struct tcp_sock * (arg3). In order to map local IP to source
* or destination IP address appropriately we need to check if the associated
* data is inbound (NET_PROBE_INBOUND in arg6) or outbound (NET_PROBE_OUTBOUND);
* the value is stored in arg6. If inbound, we map the local IP address to
* ip_daddr (destination), and if outbound it is mapped to ip_saddr.
*/
#pragma D binding "1.5" translator
translator ipinfo_t < __dtrace_tcp_void_ip_t *I > {
/*
* General strategy used is to rely on the IP header I if it is
* non-null; otherwise we try to reconstruct IP values from arg3
* (a struct tcp_sock *).
*/
ip_ver = I != NULL ? *(uint8_t *)I >> 4 :
arg3 != NULL &&
((struct sock *)arg3)->__sk_common.skc_family == AF_INET ? 4 :
arg3 != NULL &&
((struct sock *)arg3)->__sk_common.skc_family== AF_INET6 ? 6 : 0;
/*
* For ip_plength we fall back to using TCP skb data from the tcp_skb_cb
* to determine payload length.
*/
ip_plength = I != NULL && *(uint8_t *)I >> 4 == 4 ?
ntohs(((struct iphdr *)I)->tot_len) - ((*(uint8_t *)I & 0xf) << 2) :
I != NULL && *(uint8_t *)I >> 4 == 6 ?
ntohs(((struct ipv6hdr *)I)->payload_len) :
arg0 != NULL ?
((struct tcp_skb_cb *)&(((struct sk_buff *)arg0)->cb[0]))->end_seq -
((struct tcp_skb_cb *)&(((struct sk_buff *)arg0)->cb[0]))->seq :
0;
/*
* For source/destination addresses, we again try to use the IP header I
* if available. If I is NULL, we utilize arg3 (struct tcp_sock *)
* but the problem here is that it stores local and remote IP addresses
* _not_ source and destination. So we need to know if traffic is
* inbound or outbound. If inbound, IP source address is remote
* socket address (skc_daddr) and destination IP address is local socket
* address (skc_rcv_saddr). If outbound, IP source address is local
* socket address and IP destination address is remote socket address.
*/
ip_saddr = I != NULL && *(uint8_t *)I >> 4 == 4 ?
inet_ntoa(&((struct iphdr *)I)->saddr) :
I != NULL && *(uint8_t *)I >> 4 == 6 ?
inet_ntoa6(&((struct ipv6hdr *)I)->saddr) :
arg3 != NULL &&
((struct sock *)arg3)->__sk_common.skc_family== AF_INET ?
inet_ntoa(arg6 == NET_PROBE_INBOUND ?
&((struct sock *)arg3)->__sk_common.skc_daddr :
&((struct sock *)arg3)->__sk_common.skc_rcv_saddr) :
arg3 != NULL &&
((struct sock *)arg3)->__sk_common.skc_family == AF_INET6 ?
inet_ntoa6(arg6 == NET_PROBE_INBOUND ?
&((struct sock *)arg3)->__sk_common.skc_v6_daddr :
&((struct sock *)arg3)->__sk_common.skc_v6_rcv_saddr) :
"<unknown>";
ip_daddr = I != NULL && *(uint8_t *)I >> 4 == 4 ?
inet_ntoa(&((struct iphdr *)I)->daddr) :
I != NULL && *(uint8_t *)I >> 4 == 6 ?
inet_ntoa6(&((struct ipv6hdr *)I)->daddr) :
arg3 != NULL &&
((struct sock *)arg3)->__sk_common.skc_family== AF_INET ?
inet_ntoa(arg6 == NET_PROBE_INBOUND ?
&((struct sock *)arg3)->__sk_common.skc_rcv_saddr :
&((struct sock *)arg3)->__sk_common.skc_daddr) :
arg3 != NULL &&
((struct sock *)arg3)->__sk_common.skc_family== AF_INET6 ?
inet_ntoa6(arg6 == NET_PROBE_INBOUND ?
&((struct sock *)arg3)->__sk_common.skc_v6_rcv_saddr :
&((struct sock *)arg3)->__sk_common.skc_v6_daddr) :
"<unknown>";
};
#pragma D binding "1.5" translator
translator ifinfo_t < struct net_device *N > {
if_name = N != NULL ? stringof(N->name) : "<unknown>";
if_ipstack = (N != NULL && sizeof(N->nd_net) > 0) ?
((uint64_t)N->nd_net.net) : 0;
if_local = (N == NULL); /* is delivered locally */
if_addr = (uintptr_t)N; /* pointer to raw struct net_device ptr */
};
#pragma D binding "1.5" translator
translator ipv4info_t < struct iphdr *I > {
ipv4_ver = I != NULL ? 4 : 0;
ipv4_ihl = I != NULL ? ((*(uint8_t *)I & 0xf) << 2) : 0;
ipv4_tos = I != NULL ? I->tos : 0;
ipv4_length = I != NULL ? ntohs(I->tot_len) : 0;
ipv4_ident = I != NULL ? ntohs(I->id) : 0;
ipv4_flags = I != NULL ? ntohs(I->frag_off) >> 12 : 0;
ipv4_offset = I != NULL ? ntohs(I->frag_off) & 0x0fff : 0;
ipv4_ttl = I != NULL ? I->ttl : 0;
ipv4_protocol = I != NULL ? I->protocol : 0;
ipv4_protostr = I == NULL ? "<null>" :
I->protocol == IPPROTO_TCP ? "TCP" :
I->protocol == IPPROTO_UDP ? "UDP" :
I->protocol == IPPROTO_IP ? "IP" :
I->protocol == IPPROTO_ICMP ? "ICMP" :
I->protocol == IPPROTO_IGMP ? "IGMP" :
I->protocol == IPPROTO_EGP ? "EGP" :
I->protocol == IPPROTO_IPV6 ? "IPv6" :
I->protocol == IPPROTO_ROUTING ? "ROUTE" :
I->protocol == IPPROTO_ESP ? "ESP" :
I->protocol == IPPROTO_AH ? "AH" :
I->protocol == IPPROTO_ICMPV6 ? "ICMPv6" :
I->protocol == IPPROTO_OSPF ? "OSPF" :
I->protocol == IPPROTO_SCTP ? "SCTP" :
I->protocol == IPPROTO_RAW ? "RAW" :
lltostr((uint64_t)I->protocol);
ipv4_checksum = I != NULL ? ntohs(I->check) : 0;
ipv4_src = I != NULL ? I->saddr : 0;
ipv4_dst = I != NULL ? I->daddr : 0;
ipv4_saddr = I != NULL ? inet_ntoa(&I->saddr) : "<null>";
ipv4_daddr = I != NULL ? inet_ntoa(&I->daddr) : "<null>";
ipv4_hdr = I;
};
#pragma D binding "1.5" translator
translator ipv6info_t < struct ipv6hdr *I > {
ipv6_ver = I != NULL ? ((*(uint8_t *)I) >> 4) : 0;
ipv6_tclass = I != NULL ? ((ntohl(*(uint32_t *)I) & 0x0fffffff) >> 20) : 0;
ipv6_flow = I != NULL ? (ntohl(*(uint32_t *)I) & 0x000fffff) : 0;
ipv6_plen = I != NULL ? ntohs(I->payload_len) : 0;
ipv6_nexthdr = I != NULL ? I->nexthdr : 0;
ipv6_nextstr = I == NULL ? "<null>" :
I->nexthdr == IPPROTO_TCP ? "TCP" :
I->nexthdr == IPPROTO_UDP ? "UDP" :
I->nexthdr == IPPROTO_IP ? "IP" :
I->nexthdr == IPPROTO_ICMP ? "ICMP" :
I->nexthdr == IPPROTO_IGMP ? "IGMP" :
I->nexthdr == IPPROTO_EGP ? "EGP" :
I->nexthdr == IPPROTO_IPV6 ? "IPv6" :
I->nexthdr == IPPROTO_ROUTING ? "ROUTE" :
I->nexthdr == IPPROTO_ESP ? "ESP" :
I->nexthdr == IPPROTO_AH ? "AH" :
I->nexthdr == IPPROTO_ICMPV6 ? "ICMPv6" :
I->nexthdr == IPPROTO_OSPF ? "OSPF" :
I->nexthdr == IPPROTO_SCTP ? "SCTP" :
I->nexthdr == IPPROTO_RAW ? "RAW" :
lltostr((uint64_t)I->nexthdr);
ipv6_hlim = I != NULL ? I->hop_limit : 0;
ipv6_src = I != NULL ? &I->saddr : NULL;
ipv6_dst = I != NULL ? &I->daddr : 0;
ipv6_saddr = I != NULL ? inet_ntoa6(&I->saddr) : "<null>";
ipv6_daddr = I != NULL ? inet_ntoa6(&I->daddr) : "<null>";
ipv6_hdr = I;
};
|