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         <carls...@workingcode.com>
_______________________________________________
dtrace-discuss mailing list
dtrace-discuss@opensolaris.org

Reply via email to