Convert connect address with address familiy AF_SYSTEM to human readable string

雨燕双飞 提交于 2019-12-25 15:52:30

问题


Background

I'm writing some dtrace program which tracks application socket file descriptors. Aim is to provide logs which help me spot leak of file descriptors in some very complex OS X application.

Here is my other question with very helpful answer.

Problem

I want that my program is logging address to which file descriptor has been connected to. In examples there is a code which partial do what I need: soconnect_mac.d, here is link to github.

soconnect_mac.d works great when applied on Firefox, but it completely fails in case of my application. Quick investigation shown that soconnect_mac.d is able to interpret only AF_INET (value 2) family address and som library used by my application is using AF_SYSTEM (value 32) family address.

I can't find anything which could help me convert received address to something what is human readable.

So far I've got this:

#!/usr/sbin/dtrace -s

inline int af_inet   = 2 ;  /* AF_INET   defined in Kernel/sys/socket.h */
inline int af_inet6  = 30;  /* AF_INET6  defined in Kernel/sys/socket.h */
inline int af_system = 32;  /* AF_SYSTEM defined in Kernel/sys/socket.h */

… // some stuff

syscall::connect:entry
/pid == $target && isOpened[pid, arg0] == 1/
{
    /* assume this is sockaddr_in until we can examine family */
    this->s = (struct sockaddr_in *)copyin(arg1, arg2);
    this->f = this->s->sin_family;
    self->fileDescriptor = arg0;
}

/* this section is copied with pride from "soconnect_mac.d" */
syscall::connect:entry
/this->f == af_inet/
{
    /* Convert port to host byte order without ntohs() being available. */
    self->port = (this->s->sin_port & 0xFF00) >> 8;
    self->port |= (this->s->sin_port & 0xFF) << 8;

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

    self->address = strjoin(this->addr1, this->addr2);
}

/* this section is my */
syscall::connect:entry
/this->f == af_system/
{
    /* TODO: Problem how to handle AF_SYSTEM address family */

    /* Convert port to host byte order without ntohs() being available. */
    self->port = (this->s->sin_port & 0xFF00) >> 8;
    self->port |= (this->s->sin_port & 0xFF) << 8; // this also doen't work as it should

    self->address = "system family address needed here";
}

// a fallback
syscall::connect:entry
/this->f && this->f != af_inet && this->f != af_system/
{
    /* Convert port to host byte order without ntohs() being available. */
    self->port = (this->s->sin_port & 0xFF00) >> 8;
    self->port |= (this->s->sin_port & 0xFF) << 8;

    self->address = strjoin("Can't handle family: ", lltostr(this->f));
}

syscall::connect:return
/self->fileDescriptor/
{
    this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
    printf("%Y.%03d FD:%d Status:%s Address:%s Port:%d",
           walltimestamp, walltimestamp % 1000000000 / 1000000,
           self->fileDescriptor, this->errstr, self->address, self->port);

    self->fileDescriptor = 0;
    self->address = 0;
    self->port = 0;
}

What is even more annoying my code has failed to read port number (I get 512 value instead one of this: 443, 8443, 5061).
IMO problem is first syscall::connect:entry where it is assumed that second argument can be treated as struct sockaddr_in. I'm guessing struct sockaddr_storage should be used in case of AF_SYSTEM address family, but I didn't found any documentation or source code which proves this in direct way.

My section with this->f == af_system condition properly catches events from application I'm investigating.

来源:https://stackoverflow.com/questions/47454393/convert-connect-address-with-address-familiy-af-system-to-human-readable-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!