[dtrace-discuss] values from a struct

goinsane
2010-09-24T09:19:25Z

This becomes interesting. truss shows an ipv6 address for some processes, like
sshd (ipv4 encapsulated in ipv6), although there is no configured ipv6
interface.

909:    accept(3, 0x08047A10, 0x08047E78, SOV_DEFAULT)  = 4
909:            AF_INET6  name = ::ffff:172.31.70.6  port = 64625


When the probe fbt:sockfs:accept:return is fired , af_family is set to 26
(INET6) instead of 2 (INET). The return of an ipv6 address seems to be the
reason for the value of 0 of (uint_t)self->sockcont->sin_addr.s_addr . I
still have no glue how the struct sin_addr for ipv6 does look like, if and how
it differs from the original ipv4 one.

Is there a way to find out the structs getting accessed when a probe is fired?



I''ve create created a perlscript, which uses IO::Socket::INET to create
a listening socket. truss return the address family AF_INET and the ipv4
address.

23523:  accept(4, 0x080475E8, 0x08047A00, SOV_DEFAULT)  = 5
23523:          AF_INET  name = 172.31.70.6  port = 64622

With the following D I could catch the source ip and port. You''re
right, I''ve to distinguish the endianness. So it won''t work on
sparc.

What predicate could be used to differentiate between little and big endian?
Do you see a simpler way of the bit operations I''m doing to get the
port and ip?


#!/usr/sbin/dtrace -qCs

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

fbt:sockfs:accept:entry
/ execname == "tcps.pl" /
{
    self->sockaddr = arg1;
    self->socklenp = arg2;
}


fbt:sockfs:accept:return
/ self->socklenp && execname == "tcps.pl" /
{
   self->socklen = *(int *)copyin(self->socklenp, 4);
   self->sockcont = (struct sockaddr_in *)copyin(self->sockaddr,
self->socklen);
   self->sockcont_nofamily = (struct sockaddr *)copyin(self->sockaddr,
self->socklen);

   self->port = self->sockcont->sin_port;
   self->portB1 = self->port & 0xFF00;
   self->portB1 >>= 8;
   self->portB2 = self->port & 0xFF;
   self->portB2 <<= 8;

   self->portOk = self->portB2 | self->portB1;
   self->ip   = (uint_t)self->sockcont->sin_addr.s_addr;
   oct4 = self->ip >> 24;
   oct3 = self->ip >> 16;
   oct2 = self->ip >>  8;
   oct1 = self->ip;
   oct1 &= 255;
   oct2 &= 255;
   oct3 &= 255;
   oct4 &= 255;

  printf("Process %s , Pid: %d got request from %d.%d.%d.%d (src Port
%d)\n", execname, pid, oct1, oct2, oct3, oct4, self->portOk);

/*
  printf("address family const got : %d\n",
self->sockcont_nofamily->sa_family);
  printf("address family const of ipv6: %d\n", AF_INET6);

  printf("len %d\n",  self->socklen);
  printf("struct size: %d\n", sizeof( self->sockcont));
  printf("port: %d ip: %d    port1: %d     port2:  %d     portall:
%d\n", self->port, self->ip, self->portB1, self->portB2,
self->portOk);
  printf("socklen: %d \n",  self->socklen);
  printf("struct addrr: %x \n", self->sockaddr);
  printf("struct len: %x\n", self->socklenp);
 */

}