Network Lower Level Protocols:soaccept.d
From DTraceBook
soaccept.d, page 453
#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option switchrate=10hz
/* If AF_INET and AF_INET6 are "Unknown" to DTrace, replace with numbers: */
inline int af_inet = AF_INET;
inline int af_inet6 = AF_INET6;
dtrace:::BEGIN
{
/* Add translations as desired from /usr/include/sys/errno.h */
err[0] = "Success";
err[EINTR] = "Interrupted syscall";
err[EIO] = "I/O error";
err[EAGAIN] = "Resource temp unavail";
err[EACCES] = "Permission denied";
err[ECONNABORTED] = "Connection aborted";
err[ECONNRESET] = "Connection reset";
err[ETIMEDOUT] = "Timed out";
err[EINPROGRESS] = "In progress";
printf("%-6s %-16s %-3s %-16s %-5s %8s %s\n", "PID", "PROCESS", "FAM",
"ADDRESS", "PORT", "LAT(us)", "RESULT");
}
syscall::accept*:entry
{
self->sa = arg1;
self->start = timestamp;
}
syscall::accept*:return
/self->sa/
{
this->delta = (timestamp - self->start) / 1000;
/* assume this is sockaddr_in until we can examine family */
this->s = (struct sockaddr_in *)copyin(self->sa,
sizeof (struct sockaddr_in));
this->f = this->s->sin_family;
}
syscall::accept*:return
/this->f == af_inet/
{
this->port = ntohs(this->s->sin_port);
this->address = inet_ntoa((ipaddr_t *)&this->s->sin_addr);
this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
printf("%-6d %-16s %-3d %-16s %-5d %8d %s\n", pid, execname,
this->f, this->address, this->port, this->delta, this->errstr);
}
syscall::accept*:return
/this->f == af_inet6/
{
/* refetch for sockaddr_in6 */
this->s6 = (struct sockaddr_in6 *)copyin(self->sa,
sizeof (struct sockaddr_in6));
this->port = ntohs(this->s6->sin6_port);
this->address = inet_ntoa6((in6_addr_t *)&this->s6->sin6_addr);
this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
printf("%-6d %-16s %-3d %-16s %-5d %8d %s\n", pid, execname,
this->f, this->address, this->port, this->delta, this->errstr);
}
syscall::accept*:return
/self->start/
{
self->sa = 0; self->start = 0;
}
Mac OS X
#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option switchrate=10hz
/* If AF_INET and AF_INET6 are "Unknown" to DTrace, replace with numbers: */
inline int af_inet = 2; /* AF_INET defined in bsd/sys/socket.h */
inline int af_inet6 = 30; /* AF_INET6 defined in bsd/sys/socket.h */
dtrace:::BEGIN
{
/* Add translations as desired from /usr/include/sys/errno.h */
err[0] = "Success";
err[EINTR] = "Interrupted syscall";
err[EIO] = "I/O error";
err[EAGAIN] = "Resource temp unavail";
err[EACCES] = "Permission denied";
err[ECONNABORTED] = "Connection aborted";
err[ECONNRESET] = "Connection reset";
err[ETIMEDOUT] = "Timed out";
err[EINPROGRESS] = "In progress";
printf("%-6s %-16s %-3s %-16s %-5s %8s %s\n", "PID", "PROCESS", "FAM",
"ADDRESS", "PORT", "LAT(us)", "RESULT");
}
syscall::accept*:entry
{
self->sa = arg1;
self->start = timestamp;
}
syscall::accept*:return
/self->sa/
{
this->delta = (timestamp - self->start) / 1000;
/* assume this is sockaddr_in until we can examine family */
this->s = (struct sockaddr_in *)copyin(self->sa,
sizeof (struct sockaddr_in));
this->f = this->s->sin_family;
}
syscall::accept*:return
/this->f == af_inet/
{
this->port = ntohs(this->s->sin_port);
/*
* Convert an IPv4 address into a dotted quad decimal string.
* Until the inet_ntoa() functions are available from DTrace, this is
* converted using the existing strjoin() and lltostr(). It's done in
* two parts to avoid exhausting DTrace registers in one line of code.
*/
this->a = (uint8_t *)&this->s->sin_addr;
this->addr1 = strjoin(lltostr(this->a[0] + 0ULL), strjoin(".",
strjoin(lltostr(this->a[1] + 0ULL), ".")));
this->addr2 = strjoin(lltostr(this->a[2] + 0ULL), strjoin(".",
lltostr(this->a[3] + 0ULL)));
this->address = strjoin(this->addr1, this->addr2);
this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
printf("%-6d %-16s %-3d %-16s %-5d %8d %s\n", pid, execname,
this->f, this->address, this->port, this->delta, this->errstr);
}
syscall::accept*:return
/self->start/
{
self->sa = 0; self->start = 0;
}
This version does IPv4 only. IPv6 can be traced: you'll need to add a clause for /this->f == af_inet6/ and write some code to stringify the address (or just hexdump). Also, the port number was "0" (when it should be something else) during testing; need to investigate more.