diff options
author | des <des@FreeBSD.org> | 2001-10-21 21:57:10 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2001-10-21 21:57:10 +0000 |
commit | 90be41ff5d2f1e88a4cf1d9a36a241a2dc159e7a (patch) | |
tree | 0ee86c2b6e560fa1bfad07553d5be4d19fc31603 /usr.bin/truss | |
parent | 359955a1956383c238da1fab2a6b379f9ce90dd7 (diff) | |
download | FreeBSD-src-90be41ff5d2f1e88a4cf1d9a36a241a2dc159e7a.zip FreeBSD-src-90be41ff5d2f1e88a4cf1d9a36a241a2dc159e7a.tar.gz |
Teach truss(1) to display sockaddrs. It currently knows about AF_INET,
AF_INET6 and AF_UNIX sockaddrs, and will recognize accept(), bind(),
connect(), getpeername() and getsockname() as syscalls taking sockaddr
arguments. Some enterprising soul might want to add (and test) support
for the send() / recv() family of syscalls as well.
MFC after: 1 week
Diffstat (limited to 'usr.bin/truss')
-rw-r--r-- | usr.bin/truss/syscall.h | 2 | ||||
-rw-r--r-- | usr.bin/truss/syscalls.c | 83 |
2 files changed, 82 insertions, 3 deletions
diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h index 5e556e1..a663573 100644 --- a/usr.bin/truss/syscall.h +++ b/usr.bin/truss/syscall.h @@ -22,7 +22,7 @@ */ enum Argtype { None = 1, Hex, Octal, Int, String, Ptr, Stat, Ioctl, Quad, - Signal }; + Signal, Sockaddr }; #define ARG_MASK 0xff #define OUT 0x100 diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index cd92deb..2512225 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -39,13 +39,19 @@ static const char rcsid[] = * arguments. */ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> + #include <err.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <sys/types.h> -#include <signal.h> + #include "syscall.h" /* @@ -83,6 +89,16 @@ struct syscall syscalls[] = { { "access", 1, 2, { { String | IN, 0 }, { Int, 1 }}}, { "sigaction", 1, 3, { { Signal, 0 }, { Ptr | IN, 1 }, { Ptr | OUT, 2 }}}, + { "accept", 1, 3, + { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, + { "bind", 1, 3, + { { Hex, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, + { "connect", 1, 3, + { { Hex, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, + { "getpeername", 1, 3, + { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, + { "getsockname", 1, 3, + { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { 0, 0, 0, { { 0, 0 }}}, }; @@ -106,6 +122,32 @@ get_syscall(const char *name) { } /* + * get_struct + * + * Copy a fixed amount of bytes from the process. + */ + +int +get_struct(int procfd, void *offset, void *buf, int len) { + char *pos; + FILE *p; + int c, fd; + + if ((fd = dup(procfd)) == -1) + err(1, "dup"); + if ((p = fdopen(fd, "r")) == NULL) + err(1, "fdopen"); + fseek(p, (long)offset, SEEK_SET); + for (pos = (char *)buf; len--; pos++) { + if ((c = fgetc(p)) == EOF) + return -1; + *pos = c; + } + fclose(p); + return 0; +} + +/* * get_string * Copy a string from the process. Note that it is * expected to be a C string, but if max is set, it will @@ -243,6 +285,43 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args) { } } break; + case Sockaddr: + { + struct sockaddr *sa; + char addr[64]; + u_char sa_len; + char *p, *q; + int i, len; + + /* yuck: get sa_len */ + get_struct(fd, (void *)args[sc->offset], (void *)&sa_len, sizeof sa_len); + sa = malloc(sa_len); + get_struct(fd, (void *)args[sc->offset], (void *)sa, sa_len); + + tmp = malloc(100); + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + inet_ntop(AF_INET, &sin->sin_addr, addr, sizeof addr); + sprintf(tmp, "{ AF_INET %s:%d }", addr, htons(sin->sin_port)); + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + inet_ntop(AF_INET6, &sin6->sin6_addr, addr, sizeof addr); + sprintf(tmp, "{ AF_INET6 [%s]:%d }", addr, htons(sin6->sin6_port)); + } else if (sa->sa_family == AF_UNIX) { + struct sockaddr_un *sun = (struct sockaddr_un *)sa; + sprintf(tmp, "{ AF_UNIX \"%s\" }", sun->sun_path); + } else { + p = tmp; + p += sprintf(p, "{ sa_len = %d, sa_family = %d, sa_data = {", + sa->sa_len, sa->sa_family); + for (q = sa->sa_data; q < ((char *)sa) + sa_len; q++) + p += sprintf(p, " 0x%02x,", *q); + p--; + p += sprintf(p, "} }"); + } + free(sa); + } + break; } return tmp; } |