1235368Sgnn#!/usr/sbin/dtrace -Cs 2235368Sgnn/* 3235368Sgnn * tcpsnoop.d - snoop TCP network packets by process. 4235368Sgnn * Written using DTrace (Solaris 10 3/05) 5235368Sgnn * 6235368Sgnn * This analyses TCP network packets and prints the responsible PID and UID, 7235368Sgnn * plus standard details such as IP address and port. This captures traffic 8235368Sgnn * of newly created TCP connections that were established while this program 9235368Sgnn * was running. It can help identify which processes is causing TCP traffic. 10235368Sgnn * 11235368Sgnn * WARNING: This script may only work on Solaris 10 3/05, since it uses the 12235368Sgnn * fbt provider to trace the raw operation of a specific version of the kernel. 13235368Sgnn * In the future, a 'stable' network provider should exist which will allow 14235368Sgnn * this to be written for that and subsequent versions of the kernel. In the 15235368Sgnn * meantime, check for other versions of this script in the /Net directory, 16235368Sgnn * and read the Notes/ALLfbt_notes.txt for more background on fbt. 17235368Sgnn * 18235368Sgnn * $Id: tcpsnoop.d 69 2007-10-04 13:40:00Z brendan $ 19235368Sgnn * 20235368Sgnn * USAGE: tcpsnoop.d 21235368Sgnn * 22235368Sgnn * FIELDS: 23235368Sgnn * UID user ID 24235368Sgnn * PID process ID 25235368Sgnn * CMD command 26235368Sgnn * LADDR local IP address 27235368Sgnn * RADDR remote IP address 28235368Sgnn * LPORT local port number 29235368Sgnn * RPORT remote port number 30235368Sgnn * DR direction 31235368Sgnn * SIZE packet size, bytes 32235368Sgnn * 33235368Sgnn * SEE ALSO: snoop -rS 34235368Sgnn * 35235368Sgnn * COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg. 36235368Sgnn * 37235368Sgnn * CDDL HEADER START 38235368Sgnn * 39235368Sgnn * The contents of this file are subject to the terms of the 40235368Sgnn * Common Development and Distribution License, Version 1.0 only 41235368Sgnn * (the "License"). You may not use this file except in compliance 42235368Sgnn * with the License. 43235368Sgnn * 44235368Sgnn * You can obtain a copy of the license at Docs/cddl1.txt 45235368Sgnn * or http://www.opensolaris.org/os/licensing. 46235368Sgnn * See the License for the specific language governing permissions 47235368Sgnn * and limitations under the License. 48235368Sgnn * 49235368Sgnn * CDDL HEADER END 50235368Sgnn * 51235368Sgnn * Author: Brendan Gregg [Sydney, Australia] 52235368Sgnn * 53235368Sgnn * TODO: IPv6 54235368Sgnn * 55235368Sgnn * 09-Jul-2004 Brendan Gregg Created this. 56235368Sgnn * 12-Mar-2005 " " Changed probes, size info now printed. 57235368Sgnn * 02-Jul-2005 " " Many more probes. Renamed "tcpsnoop.d". 58235368Sgnn * 03-Dec-2005 " " Fixed tcp_accept_finish bug, now 100% correct 59235368Sgnn * execname. Thanks Kias Belgaied for expertise. 60235368Sgnn * 20-Apr-2006 " " Fixed SS_TCP_FAST_ACCEPT bug in build 31+. 61235368Sgnn * 20-Apr-2006 " " Last update. 62235368Sgnn */ 63235368Sgnn 64235368Sgnn#pragma D option quiet 65235368Sgnn#pragma D option switchrate=10hz 66235368Sgnn 67235368Sgnn#include <sys/file.h> 68235368Sgnn#include <inet/common.h> 69235368Sgnn#include <sys/byteorder.h> 70235368Sgnn 71235368Sgnn/* 72235368Sgnn * Print header 73235368Sgnn */ 74235368Sgnndtrace:::BEGIN 75235368Sgnn{ 76235368Sgnn /* print main headers */ 77235368Sgnn printf("%5s %6s %-15s %5s %2s %-15s %5s %5s %s\n", 78235368Sgnn "UID", "PID", "LADDR", "LPORT", "DR", "RADDR", "RPORT", 79235368Sgnn "SIZE", "CMD"); 80235368Sgnn} 81235368Sgnn 82235368Sgnn/* 83235368Sgnn * TCP Process inbound connections 84235368Sgnn * 85235368Sgnn * 0x00200000 has been hardcoded. It was SS_TCP_FAST_ACCEPT, but was 86235368Sgnn * renamed to SS_DIRECT around build 31. 87235368Sgnn */ 88235368Sgnnfbt:sockfs:sotpi_accept:entry 89235368Sgnn/(arg1 & FREAD) && (arg1 & FWRITE) && (args[0]->so_state & 0x00200000)/ 90235368Sgnn{ 91235368Sgnn self->sop = args[0]; 92235368Sgnn} 93235368Sgnn 94235368Sgnnfbt:sockfs:sotpi_create:return 95235368Sgnn/self->sop/ 96235368Sgnn{ 97235368Sgnn self->nsop = (struct sonode *)arg1; 98235368Sgnn} 99235368Sgnn 100235368Sgnnfbt:sockfs:sotpi_accept:return 101235368Sgnn/self->nsop/ 102235368Sgnn{ 103235368Sgnn this->tcpp = (tcp_t *)self->nsop->so_priv; 104235368Sgnn self->connp = (conn_t *)this->tcpp->tcp_connp; 105235368Sgnn tname[(int)self->connp] = execname; 106235368Sgnn tpid[(int)self->connp] = pid; 107235368Sgnn tuid[(int)self->connp] = uid; 108235368Sgnn} 109235368Sgnn 110235368Sgnnfbt:sockfs:sotpi_accept:return 111235368Sgnn{ 112235368Sgnn self->nsop = 0; 113235368Sgnn self->sop = 0; 114235368Sgnn} 115235368Sgnn 116235368Sgnn/* 117235368Sgnn * TCP Process outbound connections 118235368Sgnn */ 119235368Sgnnfbt:ip:tcp_connect:entry 120235368Sgnn{ 121235368Sgnn this->tcpp = (tcp_t *)arg0; 122235368Sgnn self->connp = (conn_t *)this->tcpp->tcp_connp; 123235368Sgnn tname[(int)self->connp] = execname; 124235368Sgnn tpid[(int)self->connp] = pid; 125235368Sgnn tuid[(int)self->connp] = uid; 126235368Sgnn} 127235368Sgnn 128235368Sgnn/* 129235368Sgnn * TCP Data translations 130235368Sgnn */ 131235368Sgnnfbt:sockfs:sotpi_accept:return, 132235368Sgnnfbt:ip:tcp_connect:return 133235368Sgnn/self->connp/ 134235368Sgnn{ 135235368Sgnn /* fetch ports */ 136235368Sgnn#if defined(_BIG_ENDIAN) 137235368Sgnn self->lport = self->connp->u_port.tcpu_ports.tcpu_lport; 138235368Sgnn self->fport = self->connp->u_port.tcpu_ports.tcpu_fport; 139235368Sgnn#else 140235368Sgnn self->lport = BSWAP_16(self->connp->u_port.tcpu_ports.tcpu_lport); 141235368Sgnn self->fport = BSWAP_16(self->connp->u_port.tcpu_ports.tcpu_fport); 142235368Sgnn#endif 143235368Sgnn 144235368Sgnn /* fetch IPv4 addresses */ 145235368Sgnn this->fad12 = 146235368Sgnn (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[12]; 147235368Sgnn this->fad13 = 148235368Sgnn (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[13]; 149235368Sgnn this->fad14 = 150235368Sgnn (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[14]; 151235368Sgnn this->fad15 = 152235368Sgnn (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[15]; 153235368Sgnn this->lad12 = 154235368Sgnn (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[12]; 155235368Sgnn this->lad13 = 156235368Sgnn (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[13]; 157235368Sgnn this->lad14 = 158235368Sgnn (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[14]; 159235368Sgnn this->lad15 = 160235368Sgnn (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[15]; 161235368Sgnn 162235368Sgnn /* convert type for use with lltostr() */ 163235368Sgnn this->fad12 = this->fad12 < 0 ? 256 + this->fad12 : this->fad12; 164235368Sgnn this->fad13 = this->fad13 < 0 ? 256 + this->fad13 : this->fad13; 165235368Sgnn this->fad14 = this->fad14 < 0 ? 256 + this->fad14 : this->fad14; 166235368Sgnn this->fad15 = this->fad15 < 0 ? 256 + this->fad15 : this->fad15; 167235368Sgnn this->lad12 = this->lad12 < 0 ? 256 + this->lad12 : this->lad12; 168235368Sgnn this->lad13 = this->lad13 < 0 ? 256 + this->lad13 : this->lad13; 169235368Sgnn this->lad14 = this->lad14 < 0 ? 256 + this->lad14 : this->lad14; 170235368Sgnn this->lad15 = this->lad15 < 0 ? 256 + this->lad15 : this->lad15; 171235368Sgnn 172235368Sgnn /* stringify addresses */ 173235368Sgnn self->faddr = strjoin(lltostr(this->fad12), "."); 174235368Sgnn self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad13), ".")); 175235368Sgnn self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad14), ".")); 176235368Sgnn self->faddr = strjoin(self->faddr, lltostr(this->fad15 + 0)); 177235368Sgnn self->laddr = strjoin(lltostr(this->lad12), "."); 178235368Sgnn self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad13), ".")); 179235368Sgnn self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad14), ".")); 180235368Sgnn self->laddr = strjoin(self->laddr, lltostr(this->lad15 + 0)); 181235368Sgnn 182235368Sgnn /* fix direction and save values */ 183235368Sgnn tladdr[(int)self->connp] = self->laddr; 184235368Sgnn tfaddr[(int)self->connp] = self->faddr; 185235368Sgnn tlport[(int)self->connp] = self->lport; 186235368Sgnn tfport[(int)self->connp] = self->fport; 187235368Sgnn 188235368Sgnn /* all systems go */ 189235368Sgnn tok[(int)self->connp] = 1; 190235368Sgnn} 191235368Sgnn 192235368Sgnn/* 193235368Sgnn * TCP Clear connp 194235368Sgnn */ 195235368Sgnnfbt:ip:tcp_get_conn:return 196235368Sgnn{ 197235368Sgnn /* Q_TO_CONN */ 198235368Sgnn this->connp = (conn_t *)arg1; 199235368Sgnn tok[(int)this->connp] = 0; 200235368Sgnn tpid[(int)this->connp] = 0; 201235368Sgnn tuid[(int)this->connp] = 0; 202235368Sgnn tname[(int)this->connp] = 0; 203235368Sgnn} 204235368Sgnn 205235368Sgnn/* 206235368Sgnn * TCP Process "port closed" 207235368Sgnn */ 208235368Sgnnfbt:ip:tcp_xmit_early_reset:entry 209235368Sgnn{ 210235368Sgnn this->queuep = (queue_t *)`tcp_g_q; /* ` */ 211235368Sgnn this->connp = (conn_t *)this->queuep->q_ptr; 212235368Sgnn this->tcpp = (tcp_t *)this->connp->conn_tcp; 213235368Sgnn 214235368Sgnn /* split addresses */ 215235368Sgnn this->ipha = (ipha_t *)args[1]->b_rptr; 216235368Sgnn this->fad15 = (this->ipha->ipha_src & 0xff000000) >> 24; 217235368Sgnn this->fad14 = (this->ipha->ipha_src & 0x00ff0000) >> 16; 218235368Sgnn this->fad13 = (this->ipha->ipha_src & 0x0000ff00) >> 8; 219235368Sgnn this->fad12 = (this->ipha->ipha_src & 0x000000ff); 220235368Sgnn this->lad15 = (this->ipha->ipha_dst & 0xff000000) >> 24; 221235368Sgnn this->lad14 = (this->ipha->ipha_dst & 0x00ff0000) >> 16; 222235368Sgnn this->lad13 = (this->ipha->ipha_dst & 0x0000ff00) >> 8; 223235368Sgnn this->lad12 = (this->ipha->ipha_dst & 0x000000ff); 224235368Sgnn 225235368Sgnn /* stringify addresses */ 226235368Sgnn self->faddr = strjoin(lltostr(this->fad12), "."); 227235368Sgnn self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad13), ".")); 228235368Sgnn self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad14), ".")); 229235368Sgnn self->faddr = strjoin(self->faddr, lltostr(this->fad15 + 0)); 230235368Sgnn self->laddr = strjoin(lltostr(this->lad12), "."); 231235368Sgnn self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad13), ".")); 232235368Sgnn self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad14), ".")); 233235368Sgnn self->laddr = strjoin(self->laddr, lltostr(this->lad15 + 0)); 234235368Sgnn 235235368Sgnn self->reset = 1; 236235368Sgnn} 237235368Sgnn 238235368Sgnn/* 239235368Sgnn * TCP Fetch "port closed" ports 240235368Sgnn */ 241235368Sgnnfbt:ip:tcp_xchg:entry 242235368Sgnn/self->reset/ 243235368Sgnn{ 244235368Sgnn#if defined(_BIG_ENDIAN) 245235368Sgnn self->lport = (uint16_t)arg0; 246235368Sgnn self->fport = (uint16_t)arg1; 247235368Sgnn#else 248235368Sgnn self->lport = BSWAP_16((uint16_t)arg0); 249235368Sgnn self->fport = BSWAP_16((uint16_t)arg1); 250235368Sgnn#endif 251235368Sgnn self->lport = BE16_TO_U16(arg0); 252235368Sgnn self->fport = BE16_TO_U16(arg1); 253235368Sgnn} 254235368Sgnn 255235368Sgnn/* 256235368Sgnn * TCP Print "port closed" 257235368Sgnn */ 258235368Sgnnfbt:ip:tcp_xmit_early_reset:return 259235368Sgnn{ 260235368Sgnn self->name = "<closed>"; 261235368Sgnn self->pid = 0; 262235368Sgnn self->uid = 0; 263235368Sgnn self->size = 54; /* should check trailers */ 264235368Sgnn self->dir = "<-"; 265235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 266235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 267235368Sgnn self->faddr, self->fport, self->size, self->name); 268235368Sgnn self->dir = "->"; 269235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 270235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 271235368Sgnn self->faddr, self->fport, self->size, self->name); 272235368Sgnn self->reset = 0; 273235368Sgnn self->size = 0; 274235368Sgnn self->name = 0; 275235368Sgnn} 276235368Sgnn 277235368Sgnn/* 278235368Sgnn * TCP Process Write 279235368Sgnn */ 280235368Sgnnfbt:ip:tcp_send_data:entry 281235368Sgnn{ 282235368Sgnn self->conn_p = (conn_t *)args[0]->tcp_connp; 283235368Sgnn} 284235368Sgnn 285235368Sgnnfbt:ip:tcp_send_data:entry 286235368Sgnn/tok[(int)self->conn_p]/ 287235368Sgnn{ 288235368Sgnn self->dir = "->"; 289235368Sgnn self->size = msgdsize(args[2]) + 14; /* should check trailers */ 290235368Sgnn self->uid = tuid[(int)self->conn_p]; 291235368Sgnn self->laddr = tladdr[(int)self->conn_p]; 292235368Sgnn self->faddr = tfaddr[(int)self->conn_p]; 293235368Sgnn self->lport = tlport[(int)self->conn_p]; 294235368Sgnn self->fport = tfport[(int)self->conn_p]; 295235368Sgnn self->ok = 2; 296235368Sgnn 297235368Sgnn /* follow inetd -> in.* transitions */ 298235368Sgnn self->name = pid && (tname[(int)self->conn_p] == "inetd") ? 299235368Sgnn execname : tname[(int)self->conn_p]; 300235368Sgnn self->pid = pid && (tname[(int)self->conn_p] == "inetd") ? 301235368Sgnn pid : tpid[(int)self->conn_p]; 302235368Sgnn tname[(int)self->conn_p] = self->name; 303235368Sgnn tpid[(int)self->conn_p] = self->pid; 304235368Sgnn} 305235368Sgnn 306235368Sgnn/* 307235368Sgnn * TCP Process Read 308235368Sgnn */ 309235368Sgnnfbt:ip:tcp_rput_data:entry 310235368Sgnn{ 311235368Sgnn self->conn_p = (conn_t *)arg0; 312235368Sgnn self->size = msgdsize(args[1]) + 14; /* should check trailers */ 313235368Sgnn} 314235368Sgnn 315235368Sgnnfbt:ip:tcp_rput_data:entry 316235368Sgnn/tok[(int)self->conn_p]/ 317235368Sgnn{ 318235368Sgnn self->dir = "<-"; 319235368Sgnn self->uid = tuid[(int)self->conn_p]; 320235368Sgnn self->laddr = tladdr[(int)self->conn_p]; 321235368Sgnn self->faddr = tfaddr[(int)self->conn_p]; 322235368Sgnn self->lport = tlport[(int)self->conn_p]; 323235368Sgnn self->fport = tfport[(int)self->conn_p]; 324235368Sgnn self->ok = 2; 325235368Sgnn 326235368Sgnn /* follow inetd -> in.* transitions */ 327235368Sgnn self->name = pid && (tname[(int)self->conn_p] == "inetd") ? 328235368Sgnn execname : tname[(int)self->conn_p]; 329235368Sgnn self->pid = pid && (tname[(int)self->conn_p] == "inetd") ? 330235368Sgnn pid : tpid[(int)self->conn_p]; 331235368Sgnn tname[(int)self->conn_p] = self->name; 332235368Sgnn tpid[(int)self->conn_p] = self->pid; 333235368Sgnn} 334235368Sgnn 335235368Sgnn/* 336235368Sgnn * TCP Complete printing outbound handshake 337235368Sgnn */ 338235368Sgnnfbt:ip:tcp_connect:return 339235368Sgnn/self->connp/ 340235368Sgnn{ 341235368Sgnn self->name = tname[(int)self->connp]; 342235368Sgnn self->pid = tpid[(int)self->connp]; 343235368Sgnn self->uid = tuid[(int)self->connp]; 344235368Sgnn self->size = 54; /* should check trailers */ 345235368Sgnn self->dir = "->"; 346235368Sgnn /* this packet occured before connp was fully established */ 347235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 348235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 349235368Sgnn self->faddr, self->fport, self->size, self->name); 350235368Sgnn} 351235368Sgnn 352235368Sgnn/* 353235368Sgnn * TCP Complete printing inbound handshake 354235368Sgnn */ 355235368Sgnnfbt:sockfs:sotpi_accept:return 356235368Sgnn/self->connp/ 357235368Sgnn{ 358235368Sgnn self->name = tname[(int)self->connp]; 359235368Sgnn self->pid = tpid[(int)self->connp]; 360235368Sgnn self->uid = tuid[(int)self->connp]; 361235368Sgnn self->size = 54; /* should check trailers */ 362235368Sgnn /* these packets occured before connp was fully established */ 363235368Sgnn self->dir = "<-"; 364235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 365235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 366235368Sgnn self->faddr, self->fport, self->size, self->name); 367235368Sgnn self->dir = "->"; 368235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 369235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 370235368Sgnn self->faddr, self->fport, self->size, self->name); 371235368Sgnn self->dir = "<-"; 372235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 373235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 374235368Sgnn self->faddr, self->fport, self->size, self->name); 375235368Sgnn} 376235368Sgnn 377235368Sgnn/* 378235368Sgnn * Print output 379235368Sgnn */ 380235368Sgnnfbt:ip:tcp_send_data:entry, 381235368Sgnnfbt:ip:tcp_rput_data:entry 382235368Sgnn/self->ok == 2/ 383235368Sgnn{ 384235368Sgnn /* print output line */ 385235368Sgnn printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 386235368Sgnn self->uid, self->pid, self->laddr, self->lport, self->dir, 387235368Sgnn self->faddr, self->fport, self->size, self->name); 388235368Sgnn} 389235368Sgnn 390235368Sgnn/* 391235368Sgnn * TCP Clear connect variables 392235368Sgnn */ 393235368Sgnnfbt:sockfs:sotpi_accept:return, 394235368Sgnnfbt:ip:tcp_connect:return 395235368Sgnn/self->connp/ 396235368Sgnn{ 397235368Sgnn self->faddr = 0; 398235368Sgnn self->laddr = 0; 399235368Sgnn self->fport = 0; 400235368Sgnn self->lport = 0; 401235368Sgnn self->connp = 0; 402235368Sgnn self->name = 0; 403235368Sgnn self->pid = 0; 404235368Sgnn self->uid = 0; 405235368Sgnn} 406235368Sgnn 407235368Sgnn/* 408235368Sgnn * TCP Clear r/w variables 409235368Sgnn */ 410235368Sgnnfbt:ip:tcp_send_data:entry, 411235368Sgnnfbt:ip:tcp_rput_data:entry 412235368Sgnn{ 413235368Sgnn self->ok = 0; 414235368Sgnn self->dir = 0; 415235368Sgnn self->uid = 0; 416235368Sgnn self->pid = 0; 417235368Sgnn self->size = 0; 418235368Sgnn self->name = 0; 419235368Sgnn self->lport = 0; 420235368Sgnn self->fport = 0; 421235368Sgnn self->laddr = 0; 422235368Sgnn self->faddr = 0; 423235368Sgnn self->conn_p = 0; 424235368Sgnn} 425