1 1.1 christos #!/usr/sbin/dtrace -Cs 2 1.1 christos /* 3 1.1 christos * tcpsnoop_snv.d - snoop TCP network packets by process. 4 1.1 christos * Written using DTrace (Solaris Nevada) 5 1.1 christos * 6 1.1 christos * This analyses TCP network packets and prints the responsible PID and UID, 7 1.1 christos * plus standard details such as IP address and port. This captures traffic 8 1.1 christos * of newly created TCP connections that were established while this program 9 1.1 christos * was running. It can help identify which processes is causing TCP traffic. 10 1.1 christos * 11 1.1 christos * WARNING: This script may only work on Solaris Nevada and OpenSolaris 12 1.1 christos * of the late 2007 vintage, since it uses the fbt provider to trace the raw 13 1.1 christos * operation of a specific version of the kernel. In the future, a 'stable' 14 1.1 christos * network provider should exist which will allow this to be written for that 15 1.1 christos * and subsequent versions of the kernel. In the meantime, check for other 16 1.1 christos * versions of this script in the /Net directory, and read the 17 1.1 christos * Notes/ALLfbt_notes.txt for more background on fbt. 18 1.1 christos * 19 1.1 christos * $Id: tcpsnoop_snv.d,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $ 20 1.1 christos * 21 1.1 christos * USAGE: tcpsnoop.d 22 1.1 christos * 23 1.1 christos * FIELDS: 24 1.1 christos * UID user ID 25 1.1 christos * PID process ID 26 1.1 christos * CMD command 27 1.1 christos * LADDR local IP address 28 1.1 christos * RADDR remote IP address 29 1.1 christos * LPORT local port number 30 1.1 christos * RPORT remote port number 31 1.1 christos * DR direction 32 1.1 christos * SIZE packet size, bytes 33 1.1 christos * 34 1.1 christos * SEE ALSO: snoop -rS 35 1.1 christos * 36 1.1 christos * COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg. 37 1.1 christos * 38 1.1 christos * CDDL HEADER START 39 1.1 christos * 40 1.1 christos * The contents of this file are subject to the terms of the 41 1.1 christos * Common Development and Distribution License, Version 1.0 only 42 1.1 christos * (the "License"). You may not use this file except in compliance 43 1.1 christos * with the License. 44 1.1 christos * 45 1.1 christos * You can obtain a copy of the license at Docs/cddl1.txt 46 1.1 christos * or http://www.opensolaris.org/os/licensing. 47 1.1 christos * See the License for the specific language governing permissions 48 1.1 christos * and limitations under the License. 49 1.1 christos * 50 1.1 christos * CDDL HEADER END 51 1.1 christos * 52 1.1 christos * Author: Brendan Gregg [Sydney, Australia] 53 1.1 christos * 54 1.1 christos * TODO: IPv6 55 1.1 christos * 56 1.1 christos * 09-Jul-2004 Brendan Gregg Created this. 57 1.1 christos * 12-Mar-2005 " " Changed probes, size info now printed. 58 1.1 christos * 02-Jul-2005 " " Many more probes. Renamed "tcpsnoop.d". 59 1.1 christos * 03-Dec-2005 " " Fixed tcp_accept_finish bug, now 100% correct 60 1.1 christos * execname. Thanks Kias Belgaied for expertise. 61 1.1 christos * 20-Apr-2006 " " Fixed SS_TCP_FAST_ACCEPT bug in build 31+. 62 1.1 christos * 20-Apr-2006 " " Last update. 63 1.1 christos * 30-Sep-2007 " " Bumped this for recent OpenSolaris/Nevada. 64 1.1 christos */ 65 1.1 christos 66 1.1 christos #pragma D option quiet 67 1.1 christos #pragma D option switchrate=10hz 68 1.1 christos 69 1.1 christos #include <sys/file.h> 70 1.1 christos #include <inet/common.h> 71 1.1 christos #include <sys/byteorder.h> 72 1.1 christos 73 1.1 christos /* 74 1.1 christos * Print header 75 1.1 christos */ 76 1.1 christos dtrace:::BEGIN 77 1.1 christos { 78 1.1 christos /* print main headers */ 79 1.1 christos printf("%5s %6s %-15s %5s %2s %-15s %5s %5s %s\n", 80 1.1 christos "UID", "PID", "LADDR", "LPORT", "DR", "RADDR", "RPORT", 81 1.1 christos "SIZE", "CMD"); 82 1.1 christos } 83 1.1 christos 84 1.1 christos /* 85 1.1 christos * TCP Process inbound connections 86 1.1 christos * 87 1.1 christos * 0x00200000 has been hardcoded. It was SS_TCP_FAST_ACCEPT, but was 88 1.1 christos * renamed to SS_DIRECT around build 31. 89 1.1 christos */ 90 1.1 christos fbt:sockfs:sotpi_accept:entry 91 1.1 christos /(arg1 & FREAD) && (arg1 & FWRITE) && (args[0]->so_state & 0x00200000)/ 92 1.1 christos { 93 1.1 christos self->sop = args[0]; 94 1.1 christos } 95 1.1 christos 96 1.1 christos fbt:sockfs:sotpi_create:return 97 1.1 christos /self->sop/ 98 1.1 christos { 99 1.1 christos self->nsop = (struct sonode *)arg1; 100 1.1 christos } 101 1.1 christos 102 1.1 christos fbt:sockfs:sotpi_accept:return 103 1.1 christos /self->nsop/ 104 1.1 christos { 105 1.1 christos this->tcpp = (tcp_t *)self->nsop->so_priv; 106 1.1 christos self->connp = (conn_t *)this->tcpp->tcp_connp; 107 1.1 christos tname[(int)self->connp] = execname; 108 1.1 christos tpid[(int)self->connp] = pid; 109 1.1 christos tuid[(int)self->connp] = uid; 110 1.1 christos } 111 1.1 christos 112 1.1 christos fbt:sockfs:sotpi_accept:return 113 1.1 christos { 114 1.1 christos self->nsop = 0; 115 1.1 christos self->sop = 0; 116 1.1 christos } 117 1.1 christos 118 1.1 christos /* 119 1.1 christos * TCP Process outbound connections 120 1.1 christos */ 121 1.1 christos fbt:ip:tcp_connect:entry 122 1.1 christos { 123 1.1 christos this->tcpp = (tcp_t *)arg0; 124 1.1 christos self->connp = (conn_t *)this->tcpp->tcp_connp; 125 1.1 christos tname[(int)self->connp] = execname; 126 1.1 christos tpid[(int)self->connp] = pid; 127 1.1 christos tuid[(int)self->connp] = uid; 128 1.1 christos } 129 1.1 christos 130 1.1 christos /* 131 1.1 christos * TCP Data translations 132 1.1 christos */ 133 1.1 christos fbt:sockfs:sotpi_accept:return, 134 1.1 christos fbt:ip:tcp_connect:return 135 1.1 christos /self->connp/ 136 1.1 christos { 137 1.1 christos /* fetch ports */ 138 1.1 christos #if defined(_BIG_ENDIAN) 139 1.1 christos self->lport = self->connp->u_port.tcpu_ports.tcpu_lport; 140 1.1 christos self->fport = self->connp->u_port.tcpu_ports.tcpu_fport; 141 1.1 christos #else 142 1.1 christos self->lport = BSWAP_16(self->connp->u_port.tcpu_ports.tcpu_lport); 143 1.1 christos self->fport = BSWAP_16(self->connp->u_port.tcpu_ports.tcpu_fport); 144 1.1 christos #endif 145 1.1 christos 146 1.1 christos /* fetch IPv4 addresses */ 147 1.1 christos this->fad12 = 148 1.1 christos (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[12]; 149 1.1 christos this->fad13 = 150 1.1 christos (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[13]; 151 1.1 christos this->fad14 = 152 1.1 christos (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[14]; 153 1.1 christos this->fad15 = 154 1.1 christos (int)self->connp->connua_v6addr.connua_faddr._S6_un._S6_u8[15]; 155 1.1 christos this->lad12 = 156 1.1 christos (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[12]; 157 1.1 christos this->lad13 = 158 1.1 christos (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[13]; 159 1.1 christos this->lad14 = 160 1.1 christos (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[14]; 161 1.1 christos this->lad15 = 162 1.1 christos (int)self->connp->connua_v6addr.connua_laddr._S6_un._S6_u8[15]; 163 1.1 christos 164 1.1 christos /* convert type for use with lltostr() */ 165 1.1 christos this->fad12 = this->fad12 < 0 ? 256 + this->fad12 : this->fad12; 166 1.1 christos this->fad13 = this->fad13 < 0 ? 256 + this->fad13 : this->fad13; 167 1.1 christos this->fad14 = this->fad14 < 0 ? 256 + this->fad14 : this->fad14; 168 1.1 christos this->fad15 = this->fad15 < 0 ? 256 + this->fad15 : this->fad15; 169 1.1 christos this->lad12 = this->lad12 < 0 ? 256 + this->lad12 : this->lad12; 170 1.1 christos this->lad13 = this->lad13 < 0 ? 256 + this->lad13 : this->lad13; 171 1.1 christos this->lad14 = this->lad14 < 0 ? 256 + this->lad14 : this->lad14; 172 1.1 christos this->lad15 = this->lad15 < 0 ? 256 + this->lad15 : this->lad15; 173 1.1 christos 174 1.1 christos /* stringify addresses */ 175 1.1 christos self->faddr = strjoin(lltostr(this->fad12), "."); 176 1.1 christos self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad13), ".")); 177 1.1 christos self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad14), ".")); 178 1.1 christos self->faddr = strjoin(self->faddr, lltostr(this->fad15 + 0)); 179 1.1 christos self->laddr = strjoin(lltostr(this->lad12), "."); 180 1.1 christos self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad13), ".")); 181 1.1 christos self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad14), ".")); 182 1.1 christos self->laddr = strjoin(self->laddr, lltostr(this->lad15 + 0)); 183 1.1 christos 184 1.1 christos /* fix direction and save values */ 185 1.1 christos tladdr[(int)self->connp] = self->laddr; 186 1.1 christos tfaddr[(int)self->connp] = self->faddr; 187 1.1 christos tlport[(int)self->connp] = self->lport; 188 1.1 christos tfport[(int)self->connp] = self->fport; 189 1.1 christos 190 1.1 christos /* all systems go */ 191 1.1 christos tok[(int)self->connp] = 1; 192 1.1 christos } 193 1.1 christos 194 1.1 christos /* 195 1.1 christos * TCP Clear connp 196 1.1 christos */ 197 1.1 christos fbt:ip:tcp_get_conn:return 198 1.1 christos { 199 1.1 christos /* Q_TO_CONN */ 200 1.1 christos this->connp = (conn_t *)arg1; 201 1.1 christos tok[(int)this->connp] = 0; 202 1.1 christos tpid[(int)this->connp] = 0; 203 1.1 christos tuid[(int)this->connp] = 0; 204 1.1 christos tname[(int)this->connp] = 0; 205 1.1 christos } 206 1.1 christos 207 1.1 christos /* 208 1.1 christos * TCP Process "port closed" 209 1.1 christos */ 210 1.1 christos fbt:ip:tcp_xmit_early_reset:entry 211 1.1 christos { 212 1.1 christos this->queuep = args[7]->tcps_g_q; 213 1.1 christos this->connp = (conn_t *)this->queuep->q_ptr; 214 1.1 christos this->tcpp = (tcp_t *)this->connp->conn_tcp; 215 1.1 christos 216 1.1 christos /* split addresses */ 217 1.1 christos this->ipha = (ipha_t *)args[1]->b_rptr; 218 1.1 christos this->fad15 = (this->ipha->ipha_src & 0xff000000) >> 24; 219 1.1 christos this->fad14 = (this->ipha->ipha_src & 0x00ff0000) >> 16; 220 1.1 christos this->fad13 = (this->ipha->ipha_src & 0x0000ff00) >> 8; 221 1.1 christos this->fad12 = (this->ipha->ipha_src & 0x000000ff); 222 1.1 christos this->lad15 = (this->ipha->ipha_dst & 0xff000000) >> 24; 223 1.1 christos this->lad14 = (this->ipha->ipha_dst & 0x00ff0000) >> 16; 224 1.1 christos this->lad13 = (this->ipha->ipha_dst & 0x0000ff00) >> 8; 225 1.1 christos this->lad12 = (this->ipha->ipha_dst & 0x000000ff); 226 1.1 christos 227 1.1 christos /* stringify addresses */ 228 1.1 christos self->faddr = strjoin(lltostr(this->fad12), "."); 229 1.1 christos self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad13), ".")); 230 1.1 christos self->faddr = strjoin(self->faddr, strjoin(lltostr(this->fad14), ".")); 231 1.1 christos self->faddr = strjoin(self->faddr, lltostr(this->fad15 + 0)); 232 1.1 christos self->laddr = strjoin(lltostr(this->lad12), "."); 233 1.1 christos self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad13), ".")); 234 1.1 christos self->laddr = strjoin(self->laddr, strjoin(lltostr(this->lad14), ".")); 235 1.1 christos self->laddr = strjoin(self->laddr, lltostr(this->lad15 + 0)); 236 1.1 christos 237 1.1 christos self->reset = 1; 238 1.1 christos } 239 1.1 christos 240 1.1 christos /* 241 1.1 christos * TCP Fetch "port closed" ports 242 1.1 christos */ 243 1.1 christos fbt:ip:tcp_xchg:entry 244 1.1 christos /self->reset/ 245 1.1 christos { 246 1.1 christos #if defined(_BIG_ENDIAN) 247 1.1 christos self->lport = (uint16_t)arg0; 248 1.1 christos self->fport = (uint16_t)arg1; 249 1.1 christos #else 250 1.1 christos self->lport = BSWAP_16((uint16_t)arg0); 251 1.1 christos self->fport = BSWAP_16((uint16_t)arg1); 252 1.1 christos #endif 253 1.1 christos self->lport = BE16_TO_U16(arg0); 254 1.1 christos self->fport = BE16_TO_U16(arg1); 255 1.1 christos } 256 1.1 christos 257 1.1 christos /* 258 1.1 christos * TCP Print "port closed" 259 1.1 christos */ 260 1.1 christos fbt:ip:tcp_xmit_early_reset:return 261 1.1 christos { 262 1.1 christos self->name = "<closed>"; 263 1.1 christos self->pid = 0; 264 1.1 christos self->uid = 0; 265 1.1 christos self->size = 54; /* should check trailers */ 266 1.1 christos self->dir = "<-"; 267 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 268 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 269 1.1 christos self->faddr, self->fport, self->size, self->name); 270 1.1 christos self->dir = "->"; 271 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 272 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 273 1.1 christos self->faddr, self->fport, self->size, self->name); 274 1.1 christos self->reset = 0; 275 1.1 christos self->size = 0; 276 1.1 christos self->name = 0; 277 1.1 christos } 278 1.1 christos 279 1.1 christos /* 280 1.1 christos * TCP Process Write 281 1.1 christos */ 282 1.1 christos fbt:ip:tcp_send_data:entry 283 1.1 christos { 284 1.1 christos self->conn_p = (conn_t *)args[0]->tcp_connp; 285 1.1 christos } 286 1.1 christos 287 1.1 christos fbt:ip:tcp_send_data:entry 288 1.1 christos /tok[(int)self->conn_p]/ 289 1.1 christos { 290 1.1 christos self->dir = "->"; 291 1.1 christos self->size = msgdsize(args[2]) + 14; /* should check trailers */ 292 1.1 christos self->uid = tuid[(int)self->conn_p]; 293 1.1 christos self->laddr = tladdr[(int)self->conn_p]; 294 1.1 christos self->faddr = tfaddr[(int)self->conn_p]; 295 1.1 christos self->lport = tlport[(int)self->conn_p]; 296 1.1 christos self->fport = tfport[(int)self->conn_p]; 297 1.1 christos self->ok = 2; 298 1.1 christos 299 1.1 christos /* follow inetd -> in.* transitions */ 300 1.1 christos self->name = pid && (tname[(int)self->conn_p] == "inetd") ? 301 1.1 christos execname : tname[(int)self->conn_p]; 302 1.1 christos self->pid = pid && (tname[(int)self->conn_p] == "inetd") ? 303 1.1 christos pid : tpid[(int)self->conn_p]; 304 1.1 christos tname[(int)self->conn_p] = self->name; 305 1.1 christos tpid[(int)self->conn_p] = self->pid; 306 1.1 christos } 307 1.1 christos 308 1.1 christos /* 309 1.1 christos * TCP Process Read 310 1.1 christos */ 311 1.1 christos fbt:ip:tcp_rput_data:entry 312 1.1 christos { 313 1.1 christos self->conn_p = (conn_t *)arg0; 314 1.1 christos self->size = msgdsize(args[1]) + 14; /* should check trailers */ 315 1.1 christos } 316 1.1 christos 317 1.1 christos fbt:ip:tcp_rput_data:entry 318 1.1 christos /tok[(int)self->conn_p]/ 319 1.1 christos { 320 1.1 christos self->dir = "<-"; 321 1.1 christos self->uid = tuid[(int)self->conn_p]; 322 1.1 christos self->laddr = tladdr[(int)self->conn_p]; 323 1.1 christos self->faddr = tfaddr[(int)self->conn_p]; 324 1.1 christos self->lport = tlport[(int)self->conn_p]; 325 1.1 christos self->fport = tfport[(int)self->conn_p]; 326 1.1 christos self->ok = 2; 327 1.1 christos 328 1.1 christos /* follow inetd -> in.* transitions */ 329 1.1 christos self->name = pid && (tname[(int)self->conn_p] == "inetd") ? 330 1.1 christos execname : tname[(int)self->conn_p]; 331 1.1 christos self->pid = pid && (tname[(int)self->conn_p] == "inetd") ? 332 1.1 christos pid : tpid[(int)self->conn_p]; 333 1.1 christos tname[(int)self->conn_p] = self->name; 334 1.1 christos tpid[(int)self->conn_p] = self->pid; 335 1.1 christos } 336 1.1 christos 337 1.1 christos /* 338 1.1 christos * TCP Complete printing outbound handshake 339 1.1 christos */ 340 1.1 christos fbt:ip:tcp_connect:return 341 1.1 christos /self->connp/ 342 1.1 christos { 343 1.1 christos self->name = tname[(int)self->connp]; 344 1.1 christos self->pid = tpid[(int)self->connp]; 345 1.1 christos self->uid = tuid[(int)self->connp]; 346 1.1 christos self->size = 54; /* should check trailers */ 347 1.1 christos self->dir = "->"; 348 1.1 christos /* this packet occured before connp was fully established */ 349 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 350 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 351 1.1 christos self->faddr, self->fport, self->size, self->name); 352 1.1 christos } 353 1.1 christos 354 1.1 christos /* 355 1.1 christos * TCP Complete printing inbound handshake 356 1.1 christos */ 357 1.1 christos fbt:sockfs:sotpi_accept:return 358 1.1 christos /self->connp/ 359 1.1 christos { 360 1.1 christos self->name = tname[(int)self->connp]; 361 1.1 christos self->pid = tpid[(int)self->connp]; 362 1.1 christos self->uid = tuid[(int)self->connp]; 363 1.1 christos self->size = 54; /* should check trailers */ 364 1.1 christos /* these packets occured before connp was fully established */ 365 1.1 christos self->dir = "<-"; 366 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 367 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 368 1.1 christos self->faddr, self->fport, self->size, self->name); 369 1.1 christos self->dir = "->"; 370 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 371 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 372 1.1 christos self->faddr, self->fport, self->size, self->name); 373 1.1 christos self->dir = "<-"; 374 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 375 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 376 1.1 christos self->faddr, self->fport, self->size, self->name); 377 1.1 christos } 378 1.1 christos 379 1.1 christos /* 380 1.1 christos * Print output 381 1.1 christos */ 382 1.1 christos fbt:ip:tcp_send_data:entry, 383 1.1 christos fbt:ip:tcp_rput_data:entry 384 1.1 christos /self->ok == 2/ 385 1.1 christos { 386 1.1 christos /* print output line */ 387 1.1 christos printf("%5d %6d %-15s %5d %2s %-15s %5d %5d %s\n", 388 1.1 christos self->uid, self->pid, self->laddr, self->lport, self->dir, 389 1.1 christos self->faddr, self->fport, self->size, self->name); 390 1.1 christos } 391 1.1 christos 392 1.1 christos /* 393 1.1 christos * TCP Clear connect variables 394 1.1 christos */ 395 1.1 christos fbt:sockfs:sotpi_accept:return, 396 1.1 christos fbt:ip:tcp_connect:return 397 1.1 christos /self->connp/ 398 1.1 christos { 399 1.1 christos self->faddr = 0; 400 1.1 christos self->laddr = 0; 401 1.1 christos self->fport = 0; 402 1.1 christos self->lport = 0; 403 1.1 christos self->connp = 0; 404 1.1 christos self->name = 0; 405 1.1 christos self->pid = 0; 406 1.1 christos self->uid = 0; 407 1.1 christos } 408 1.1 christos 409 1.1 christos /* 410 1.1 christos * TCP Clear r/w variables 411 1.1 christos */ 412 1.1 christos fbt:ip:tcp_send_data:entry, 413 1.1 christos fbt:ip:tcp_rput_data:entry 414 1.1 christos { 415 1.1 christos self->ok = 0; 416 1.1 christos self->dir = 0; 417 1.1 christos self->uid = 0; 418 1.1 christos self->pid = 0; 419 1.1 christos self->size = 0; 420 1.1 christos self->name = 0; 421 1.1 christos self->lport = 0; 422 1.1 christos self->fport = 0; 423 1.1 christos self->laddr = 0; 424 1.1 christos self->faddr = 0; 425 1.1 christos self->conn_p = 0; 426 1.1 christos } 427