[dtrace-discuss] values from a struct

James Carlson
2010-09-24T12:44:03Z

goinsane wrote:
> 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?

No.  The program itself doesn''t even know that.  That''s why
sa_family
exists.  You''re supposed to switch out based on that value.

In a D script, you "switch out" by having multiple probes with
different
conditions.

> 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?

There are two distinct endian issues here.

On SPARC, the network values (port numbers and addresses) will all be in
the right order, but you have to pay attention to 32/64.  I''ve
forgotten
how to do that, but I''m sure there''s someone on this list who
knows.

On x86, the network values will all be in reverse order, because network
data is big-endian.  That means you have to swap it yourself.

I''d recommend having this clause first:

fbt:sockfs:accept:entry
{
	self->socklenp = 0;
}

That way, all tests after the first one can be "/self->socklenp/"
rather
than doing a string compare on execname.  It should be a little better
performing.

> 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);

That''s where I think you''re going wrong.  You need to copy in
the family
first, so something like this:

	self->family = *(short *)copyin(self->sockaddr, sizeof (short));

Then just end that clause and start a new one:

fbt:sockfs:accept:return
/self->socklenp && self->family == 2/
{
	/* this is the AF_INET case */

You can then copy in the full sockaddr_in and drive on.

For AF_INET6, you have to use sockaddr_in6 and sin6_addr.  See the
netinet/in.h header file and the inet6(7P) man page.

D trace clauses are like ''if'' statements in other languages.
You can
have multiple, and they''re executed in the order they appear in the
file.

--
James Carlson         42.703N 71.076W         <carlsonj at
workingcode.com>