我想调试我正在增强的程序的TCP/IP交互。我没有根访问权限(因此没有tcpdump等),但应用程序是以我自己的ID运行的。我可以使用strace来拦截系统调用,但是是否有值得推荐的替代方法?如果是,为什么-他们提供什么?命令行首选(目前我的电脑上没有安装X服务器:-(),但对GUI也很好奇。
理想情况下,它会说:
app listening on port <portA>
app listening on port <portB>
client connection #1 accepted on listening port <portA> to local port <portC>
from remote <hostX:portXA>
app sent #1 <number> bytes "<data dump...>"
app received from client #1 <number> bytes "<data dump...>"
client #1 closed connection
我自己也会刮伤一个轮子,但太多的轮子无法重新改造……
事先谢谢。
更新:保卢贝尔和伊诺斯都提出了非常有益的建议…(希望我能接受这两个答案,因为它们都是明确的,而且同样好)。实现Paul建议的ld_预载拦截的代码如下:
// TCP comms trace library
// as per http://www.jayconrod.com/cgi/view_post.py?23
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <dlfcn.h>
typedef ssize_t (*Recv)(int s, void* buf, size_t len, int flags);
ssize_t recv(int s, void* buf, size_t len, int flags)
{
static Recv real = NULL;
if (!real)
real = (Recv)dlsym(RTLD_NEXT, "recv");
fprintf(stderr, "> recv(s '%d', buf %p, len %lld, flags %d)...\n",
s, buf, len, flags);
ssize_t result = real(s, buf, len, flags);
fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
s, buf, len, flags, result);
return result;
}
typedef ssize_t (*Send)(int s, const void* buf, size_t len, int flags);
ssize_t send(int s, const void* buf, size_t len, int flags)
{
static Send real = NULL;
if (!real)
real = (Send)dlsym(RTLD_NEXT, "send");
fprintf(stderr, "> send(s '%d', buf %p, len %lld, flags %d)...\n",
s, buf, len, flags);
ssize_t result = real(s, buf, len, flags);
fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
s, buf, len, flags, result);
return result;
}
typedef int (*Connect)(int s, const struct sockaddr* serv_addr, socklen_t addrlen);
int connect(int s, const struct sockaddr* serv_addr, socklen_t addrlen)
{
static Connect real = NULL;
if (!real)
real = (Connect)dlsym(RTLD_NEXT, "connect");
fprintf(stderr, "> connect(s %d, sockaddr %p, addrlen %d)\n",
s, (void*)serv_addr, addrlen);
int result = real(s, serv_addr, addrlen);
fprintf(stderr, "< connect(s %d, sockaddr %p, addrlen %d) return %d\n",
s, (void*)serv_addr, addrlen, result);
return result;
}
typedef int (*Accept)(int s, const struct sockaddr* serv_addr, socklen_t* addrlen);
int accept(int s, struct sockaddr* serv_addr, socklen_t* addrlen)
{
static Accept real = NULL;
if (!real)
real = (Accept)dlsym(RTLD_NEXT, "accept");
fprintf(stderr, "> accept(s %d, sockaddr %p, addrlen %p)\n",
s, (void*)serv_addr, addrlen);
int result = real(s, serv_addr, addrlen);
fprintf(stderr, "< accept(s %d, sockaddr %p, addrlen %p -> %d) return %d\n",
s, (void*)serv_addr, addrlen, *addrlen, result);
return result;
}