Provavelmente, a abordagem mais versátil e personalizada para concluir sua missão é analisar dtrace
.
Use um soquete genérico ou um provedor tcp e execute o script no modo destrutivo para chamar system()
do kernel ou use o Rastreamento de Limite de Função (FBT) como seu provedor. Este último fará com que o seu script dependa da versão do OSX.
Brincando um pouco, eu criei algo que deveria lhe dar força suficiente para a sua solução final usando um provedor de soquete (por isso deve funcionar em ambas as suas máquinas MacOSX):
#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option switchrate=10hz
#pragma D option destructive
/* AF_INET{6} are unknown to dtrace, so replace with numbers */
inline int af_inet = 2; /* AF_INET */
inline int af_inet6 = 30; /* AF_INET6 */
inline const string procname = "nc";
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[EACCES] = "Permission denied";
err[ENETDOWN] = "Network is down";
err[ENETUNREACH] = "Network unreachable";
err[ECONNRESET] = "Connection reset";
err[ECONNREFUSED] = "Connection refused";
err[ETIMEDOUT] = "Timed out";
err[EHOSTDOWN] = "Host down";
err[EHOSTUNREACH] = "No route to host";
err[EINPROGRESS] = "In progress";
err[EADDRNOTAVAIL] = "Can't assign requested address";
printf("%-6s %-20s %-8s %-21s %-21s %-8s %s\n",
"PID", "PROCNAME", "FAMILY", "S_ADDR:S_PORT", "D_ADDR:D_PORT",
"LAT(us)", "RESULT");
}
/* MacOSX connectx() syscall:
connectx(arg0:int s, arg1:struct sockaddr *src, arg2:socklen_t srclen,
arg3:struct sockaddr *dsts, arg4:socklen_t dstlen,
arg5:uint32_t ifscope, arg6: associd_t aid,
arg7:connid_t *cid);
*/
syscall::connectx:entry
{
this->s = (struct sockaddr_in *) copyin(arg3, sizeof(struct sockaddr));
this->f = this->s->sin_family;
}
syscall::connectx:entry
/ this->f == af_inet && execname == procname /
{
this->s = (struct sockaddr_in *) copyin(arg1, sizeof(struct sockaddr));
self->address = inet_ntop(this->f, (void *) &this->s->sin_addr);
self->port = ntohs(this->s->sin_port);
self->s_addr = strjoin(strjoin(self->address, ":"), lltostr(self->port));
this->d = (struct sockaddr_in *) copyin(arg3, sizeof(struct sockaddr));
self->address = inet_ntop(this->f, (void *) &this->d->sin_addr);
self->port = ntohs(this->d->sin_port);
self->d_addr = strjoin(strjoin(self->address, ":"), lltostr(self->port));
self->ts = timestamp;
}
syscall::connectx:entry
/ this->f == af_inet6 && execname == procname /
{
this->s6 = (struct sockaddr_in6 *) copyin(arg1, sizeof(struct sockaddr_in6));
self->port = ntohs(this->s6->sin6_port);
self->address = inet_ntop(this->f, (void *) &this->s6->sin6_addr);
self->s_addr = strjoin(strjoin(self->address, ":"), lltostr(self->port));
this->d6 = (struct sockaddr_in6 *) copyin(arg3, sizeof(struct sockaddr_in6));
self->port = ntohs(this->d6->sin6_port);
self->address = inet_ntop(this->f, (void *) &this->d6->sin6_addr);
self->d_addr = strjoin(strjoin(self->address, ":"), lltostr(self->port));
self->ts = timestamp;
}
syscall::connectx:return
/ self->ts /
{
this->delta = (timestamp - self->ts) / 1000;
this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
/* Basically anything can be called here */
system("date");
printf("%-6d %-20s %-8d %-21s %-21s %-8d %s\n",
pid, execname, this->f, self->s_addr, self->d_addr,
this->delta, this->errstr);
self->family = 0;
self->ts = 0;
}
Salve-o em um arquivo (digamos ./socket_connect_mac_simple.d
) e, em seguida, chame o código da seguinte forma:
$ sudo ./socket_connect_mac_simple.d
Abra outro terminal e inicie nc
como um servidor:
$ nc -4 -k -l 127.0.0.1 6472 > /dev/null
E em outro terminal, conecte-se a ele:
$ while :; do nc -4 -s 192.168.0.19 127.0.0.1 6472 < /usr/bin/true; sleep 0.5; done
Sua saída deve parecer algo nos seguintes termos:
$ sudo ./socket_connect_mac_simple.d
PID PROCNAME FAMILY S_ADDR:S_PORT D_ADDR:D_PORT LAT(us) RESULT
45823 nc 2 192.168.0.19:0 127.0.0.1:6472 240 Success
45825 nc 2 192.168.0.19:0 127.0.0.1:6472 234 Success
45827 nc 2 192.168.0.19:0 127.0.0.1:6472 236 Success
45829 nc 2 192.168.0.19:0 127.0.0.1:6472 240 Success
45831 nc 2 192.168.0.19:0 127.0.0.1:6472 241 Success
45833 nc 2 192.168.0.19:0 127.0.0.1:6472 238 Success
45835 nc 2 192.168.0.19:0 127.0.0.1:6472 234 Success
45837 nc 2 192.168.0.19:0 127.0.0.1:6472 241 Success
45839 nc 2 192.168.0.19:0 127.0.0.1:6472 236 Success
45841 nc 2 192.168.0.19:0 127.0.0.1:6472 237 Success
Obviamente, você estará substituindo nc
com sua lista de daemon na porta 6472 e também terá que chamar seu script bash onde eu coloquei o fragmento de código system("date")
. Além disso, deve funcionar apenas como você descreveu.
Assegure-se de ler a documentação sobre o modo destrutivo chamada dtrace system()
: Chamadas no Modo Destrutivo dentro do DTrace