1bbeaf6c0SSean Eric Fagan /* 209d64da3SSean Eric Fagan * Copryight 1997 Sean Eric Fagan 309d64da3SSean Eric Fagan * 409d64da3SSean Eric Fagan * Redistribution and use in source and binary forms, with or without 509d64da3SSean Eric Fagan * modification, are permitted provided that the following conditions 609d64da3SSean Eric Fagan * are met: 709d64da3SSean Eric Fagan * 1. Redistributions of source code must retain the above copyright 809d64da3SSean Eric Fagan * notice, this list of conditions and the following disclaimer. 909d64da3SSean Eric Fagan * 2. Redistributions in binary form must reproduce the above copyright 1009d64da3SSean Eric Fagan * notice, this list of conditions and the following disclaimer in the 1109d64da3SSean Eric Fagan * documentation and/or other materials provided with the distribution. 1209d64da3SSean Eric Fagan * 3. All advertising materials mentioning features or use of this software 1309d64da3SSean Eric Fagan * must display the following acknowledgement: 1409d64da3SSean Eric Fagan * This product includes software developed by Sean Eric Fagan 1509d64da3SSean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote 1609d64da3SSean Eric Fagan * products derived from this software without specific prior written 1709d64da3SSean Eric Fagan * permission. 1809d64da3SSean Eric Fagan * 1909d64da3SSean Eric Fagan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2009d64da3SSean Eric Fagan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2109d64da3SSean Eric Fagan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2209d64da3SSean Eric Fagan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2309d64da3SSean Eric Fagan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2409d64da3SSean Eric Fagan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2509d64da3SSean Eric Fagan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2609d64da3SSean Eric Fagan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2709d64da3SSean Eric Fagan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2809d64da3SSean Eric Fagan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2909d64da3SSean Eric Fagan * SUCH DAMAGE. 3009d64da3SSean Eric Fagan */ 3109d64da3SSean Eric Fagan 323cf51049SPhilippe Charnier #ifndef lint 333cf51049SPhilippe Charnier static const char rcsid[] = 34c3aac50fSPeter Wemm "$FreeBSD$"; 353cf51049SPhilippe Charnier #endif /* not lint */ 363cf51049SPhilippe Charnier 3709d64da3SSean Eric Fagan /* 38bbeaf6c0SSean Eric Fagan * This file has routines used to print out system calls and their 39bbeaf6c0SSean Eric Fagan * arguments. 40bbeaf6c0SSean Eric Fagan */ 41bbeaf6c0SSean Eric Fagan 429ddd1412SDag-Erling Smørgrav #include <sys/types.h> 439ddd1412SDag-Erling Smørgrav #include <sys/socket.h> 449ddd1412SDag-Erling Smørgrav #include <sys/un.h> 459ddd1412SDag-Erling Smørgrav #include <netinet/in.h> 469ddd1412SDag-Erling Smørgrav #include <arpa/inet.h> 479ddd1412SDag-Erling Smørgrav 48dec17687SBrian Feldman #include <ctype.h> 493cf51049SPhilippe Charnier #include <err.h> 509ddd1412SDag-Erling Smørgrav #include <signal.h> 51bbeaf6c0SSean Eric Fagan #include <stdio.h> 52bbeaf6c0SSean Eric Fagan #include <stdlib.h> 53bbeaf6c0SSean Eric Fagan #include <string.h> 5437169f94SMatthew N. Dodd #include <time.h> 55bbeaf6c0SSean Eric Fagan #include <unistd.h> 569ddd1412SDag-Erling Smørgrav 57ec0bed25SMatthew N. Dodd #include "truss.h" 581be5d704SMark Murray #include "extern.h" 59bbeaf6c0SSean Eric Fagan #include "syscall.h" 60bbeaf6c0SSean Eric Fagan 61bbeaf6c0SSean Eric Fagan /* 62bbeaf6c0SSean Eric Fagan * This should probably be in its own file. 63bbeaf6c0SSean Eric Fagan */ 64bbeaf6c0SSean Eric Fagan 65bbeaf6c0SSean Eric Fagan struct syscall syscalls[] = { 66bbeaf6c0SSean Eric Fagan { "readlink", 1, 3, 67bbeaf6c0SSean Eric Fagan { { String, 0 } , { String | OUT, 1 }, { Int, 2 }}}, 68bbeaf6c0SSean Eric Fagan { "lseek", 2, 3, 69bbeaf6c0SSean Eric Fagan { { Int, 0 }, {Quad, 2 }, { Int, 4 }}}, 70bbeaf6c0SSean Eric Fagan { "mmap", 2, 6, 71bbeaf6c0SSean Eric Fagan { { Hex, 0 }, {Int, 1}, {Hex, 2}, {Hex, 3}, {Int, 4}, {Quad, 6}}}, 72bbeaf6c0SSean Eric Fagan { "open", 1, 3, 7309bf1169SAlfred Perlstein { { String | IN, 0} , { Hex, 1}, {Octal, 2}}}, 74bbeaf6c0SSean Eric Fagan { "linux_open", 1, 3, 7509bf1169SAlfred Perlstein { { String, 0 }, { Hex, 1}, { Octal, 2 }}}, 76bbeaf6c0SSean Eric Fagan { "close", 1, 1, { { Int, 0 } } }, 77bbeaf6c0SSean Eric Fagan { "fstat", 1, 2, 78bbeaf6c0SSean Eric Fagan { { Int, 0}, {Ptr | OUT , 1 }}}, 79bbeaf6c0SSean Eric Fagan { "stat", 1, 2, 80bbeaf6c0SSean Eric Fagan { { String | IN, 0 }, { Ptr | OUT, 1 }}}, 81a8f37218SSean Eric Fagan { "lstat", 1, 2, 82a8f37218SSean Eric Fagan { { String | IN, 0 }, { Ptr | OUT, 1 }}}, 83bbeaf6c0SSean Eric Fagan { "linux_newstat", 1, 2, 84bbeaf6c0SSean Eric Fagan { { String | IN, 0 }, { Ptr | OUT, 1 }}}, 85bbeaf6c0SSean Eric Fagan { "linux_newfstat", 1, 2, 86bbeaf6c0SSean Eric Fagan { { Int, 0 }, { Ptr | OUT, 1 }}}, 87bbeaf6c0SSean Eric Fagan { "write", 1, 3, 88bbeaf6c0SSean Eric Fagan { { Int, 0}, { Ptr | IN, 1 }, { Int, 2 }}}, 89970649f9SSean Eric Fagan { "ioctl", 1, 3, 90970649f9SSean Eric Fagan { { Int, 0}, { Ioctl, 1 }, { Hex, 2 }}}, 91bbeaf6c0SSean Eric Fagan { "break", 1, 1, { { Hex, 0 }}}, 92bbeaf6c0SSean Eric Fagan { "exit", 0, 1, { { Hex, 0 }}}, 9310714102SDag-Erling Smørgrav { "access", 1, 2, { { String | IN, 0 }, { Int, 1 }}}, 94f0ebbc29SDag-Erling Smørgrav { "sigaction", 1, 3, 95f0ebbc29SDag-Erling Smørgrav { { Signal, 0 }, { Ptr | IN, 1 }, { Ptr | OUT, 2 }}}, 969ddd1412SDag-Erling Smørgrav { "accept", 1, 3, 979ddd1412SDag-Erling Smørgrav { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, 989ddd1412SDag-Erling Smørgrav { "bind", 1, 3, 999ddd1412SDag-Erling Smørgrav { { Hex, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, 1009ddd1412SDag-Erling Smørgrav { "connect", 1, 3, 1019ddd1412SDag-Erling Smørgrav { { Hex, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, 1029ddd1412SDag-Erling Smørgrav { "getpeername", 1, 3, 1039ddd1412SDag-Erling Smørgrav { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, 1049ddd1412SDag-Erling Smørgrav { "getsockname", 1, 3, 1059ddd1412SDag-Erling Smørgrav { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, 1069897b203SMatthew N. Dodd { "execve", 1, 3, 1079897b203SMatthew N. Dodd { { String | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, 1089897b203SMatthew N. Dodd { "linux_execve", 1, 3, 1099897b203SMatthew N. Dodd { { String | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, 1103cf51049SPhilippe Charnier { 0, 0, 0, { { 0, 0 }}}, 111bbeaf6c0SSean Eric Fagan }; 112bbeaf6c0SSean Eric Fagan 113bbeaf6c0SSean Eric Fagan /* 114bbeaf6c0SSean Eric Fagan * If/when the list gets big, it might be desirable to do it 115bbeaf6c0SSean Eric Fagan * as a hash table or binary search. 116bbeaf6c0SSean Eric Fagan */ 117bbeaf6c0SSean Eric Fagan 118bbeaf6c0SSean Eric Fagan struct syscall * 119bbeaf6c0SSean Eric Fagan get_syscall(const char *name) { 120bbeaf6c0SSean Eric Fagan struct syscall *sc = syscalls; 121bbeaf6c0SSean Eric Fagan 122bbeaf6c0SSean Eric Fagan while (sc->name) { 123bbeaf6c0SSean Eric Fagan if (!strcmp(name, sc->name)) 124bbeaf6c0SSean Eric Fagan return sc; 125bbeaf6c0SSean Eric Fagan sc++; 126bbeaf6c0SSean Eric Fagan } 127bbeaf6c0SSean Eric Fagan return NULL; 128bbeaf6c0SSean Eric Fagan } 129bbeaf6c0SSean Eric Fagan 130bbeaf6c0SSean Eric Fagan /* 1319ddd1412SDag-Erling Smørgrav * get_struct 1329ddd1412SDag-Erling Smørgrav * 1339ddd1412SDag-Erling Smørgrav * Copy a fixed amount of bytes from the process. 1349ddd1412SDag-Erling Smørgrav */ 1359ddd1412SDag-Erling Smørgrav 1361be5d704SMark Murray static int 1379ddd1412SDag-Erling Smørgrav get_struct(int procfd, void *offset, void *buf, int len) { 1389ddd1412SDag-Erling Smørgrav char *pos; 1399ddd1412SDag-Erling Smørgrav FILE *p; 1409ddd1412SDag-Erling Smørgrav int c, fd; 1419ddd1412SDag-Erling Smørgrav 1429ddd1412SDag-Erling Smørgrav if ((fd = dup(procfd)) == -1) 1439ddd1412SDag-Erling Smørgrav err(1, "dup"); 1449ddd1412SDag-Erling Smørgrav if ((p = fdopen(fd, "r")) == NULL) 1459ddd1412SDag-Erling Smørgrav err(1, "fdopen"); 1467c8225caSDavid Malone fseeko(p, (uintptr_t)offset, SEEK_SET); 1479ddd1412SDag-Erling Smørgrav for (pos = (char *)buf; len--; pos++) { 1489ddd1412SDag-Erling Smørgrav if ((c = fgetc(p)) == EOF) 1499ddd1412SDag-Erling Smørgrav return -1; 1509ddd1412SDag-Erling Smørgrav *pos = c; 1519ddd1412SDag-Erling Smørgrav } 1529ddd1412SDag-Erling Smørgrav fclose(p); 1539ddd1412SDag-Erling Smørgrav return 0; 1549ddd1412SDag-Erling Smørgrav } 1559ddd1412SDag-Erling Smørgrav 1569ddd1412SDag-Erling Smørgrav /* 157bbeaf6c0SSean Eric Fagan * get_string 158bbeaf6c0SSean Eric Fagan * Copy a string from the process. Note that it is 159bbeaf6c0SSean Eric Fagan * expected to be a C string, but if max is set, it will 160bbeaf6c0SSean Eric Fagan * only get that much. 161bbeaf6c0SSean Eric Fagan */ 162bbeaf6c0SSean Eric Fagan 163bbeaf6c0SSean Eric Fagan char * 164bbeaf6c0SSean Eric Fagan get_string(int procfd, void *offset, int max) { 1653cf51049SPhilippe Charnier char *buf; 16605d5ca35SSean Eric Fagan int size, len, c, fd; 167bbeaf6c0SSean Eric Fagan FILE *p; 168bbeaf6c0SSean Eric Fagan 16905d5ca35SSean Eric Fagan if ((fd = dup(procfd)) == -1) 17005d5ca35SSean Eric Fagan err(1, "dup"); 17105d5ca35SSean Eric Fagan if ((p = fdopen(fd, "r")) == NULL) 1723cf51049SPhilippe Charnier err(1, "fdopen"); 173bbeaf6c0SSean Eric Fagan buf = malloc( size = (max ? max : 64 ) ); 174bbeaf6c0SSean Eric Fagan len = 0; 1758a2ecea9SJoerg Wunsch buf[0] = 0; 1767c8225caSDavid Malone fseeko(p, (uintptr_t)offset, SEEK_SET); 177bbeaf6c0SSean Eric Fagan while ((c = fgetc(p)) != EOF) { 178bbeaf6c0SSean Eric Fagan buf[len++] = c; 179bbeaf6c0SSean Eric Fagan if (c == 0 || len == max) { 180bbeaf6c0SSean Eric Fagan buf[len] = 0; 181bbeaf6c0SSean Eric Fagan break; 182bbeaf6c0SSean Eric Fagan } 183bbeaf6c0SSean Eric Fagan if (len == size) { 18405d5ca35SSean Eric Fagan char *tmp; 185bbeaf6c0SSean Eric Fagan tmp = realloc(buf, size+64); 186bbeaf6c0SSean Eric Fagan if (tmp == NULL) { 187bbeaf6c0SSean Eric Fagan buf[len] = 0; 18805d5ca35SSean Eric Fagan fclose(p); 189bbeaf6c0SSean Eric Fagan return buf; 190bbeaf6c0SSean Eric Fagan } 191bbeaf6c0SSean Eric Fagan size += 64; 19205d5ca35SSean Eric Fagan buf = tmp; 193bbeaf6c0SSean Eric Fagan } 194bbeaf6c0SSean Eric Fagan } 19505d5ca35SSean Eric Fagan fclose(p); 196bbeaf6c0SSean Eric Fagan return buf; 197bbeaf6c0SSean Eric Fagan } 198bbeaf6c0SSean Eric Fagan 199bbeaf6c0SSean Eric Fagan 200bbeaf6c0SSean Eric Fagan /* 201bbeaf6c0SSean Eric Fagan * Gag. This is really unportable. Multiplication is more portable. 202bbeaf6c0SSean Eric Fagan * But slower, from the code I saw. 203bbeaf6c0SSean Eric Fagan */ 204bbeaf6c0SSean Eric Fagan 205bbeaf6c0SSean Eric Fagan static long long 206bbeaf6c0SSean Eric Fagan make_quad(unsigned long p1, unsigned long p2) { 207bbeaf6c0SSean Eric Fagan union { 208bbeaf6c0SSean Eric Fagan long long ll; 209bbeaf6c0SSean Eric Fagan unsigned long l[2]; 210bbeaf6c0SSean Eric Fagan } t; 211bbeaf6c0SSean Eric Fagan t.l[0] = p1; 212bbeaf6c0SSean Eric Fagan t.l[1] = p2; 213bbeaf6c0SSean Eric Fagan return t.ll; 214bbeaf6c0SSean Eric Fagan } 215bbeaf6c0SSean Eric Fagan 216bbeaf6c0SSean Eric Fagan 217bbeaf6c0SSean Eric Fagan /* 218bbeaf6c0SSean Eric Fagan * print_arg 219bbeaf6c0SSean Eric Fagan * Converts a syscall argument into a string. Said string is 220bbeaf6c0SSean Eric Fagan * allocated via malloc(), so needs to be free()'d. The file 221bbeaf6c0SSean Eric Fagan * descriptor is for the process' memory (via /proc), and is used 222bbeaf6c0SSean Eric Fagan * to get any data (where the argument is a pointer). sc is 223bbeaf6c0SSean Eric Fagan * a pointer to the syscall description (see above); args is 224bbeaf6c0SSean Eric Fagan * an array of all of the system call arguments. 225bbeaf6c0SSean Eric Fagan */ 226bbeaf6c0SSean Eric Fagan 227bbeaf6c0SSean Eric Fagan char * 228bbeaf6c0SSean Eric Fagan print_arg(int fd, struct syscall_args *sc, unsigned long *args) { 2293cf51049SPhilippe Charnier char *tmp = NULL; 230bbeaf6c0SSean Eric Fagan switch (sc->type & ARG_MASK) { 231bbeaf6c0SSean Eric Fagan case Hex: 232bbeaf6c0SSean Eric Fagan tmp = malloc(12); 23322694ebaSBruce Evans sprintf(tmp, "0x%lx", args[sc->offset]); 234bbeaf6c0SSean Eric Fagan break; 235bbeaf6c0SSean Eric Fagan case Octal: 236bbeaf6c0SSean Eric Fagan tmp = malloc(13); 23722694ebaSBruce Evans sprintf(tmp, "0%lo", args[sc->offset]); 238bbeaf6c0SSean Eric Fagan break; 239bbeaf6c0SSean Eric Fagan case Int: 240bbeaf6c0SSean Eric Fagan tmp = malloc(12); 24122694ebaSBruce Evans sprintf(tmp, "%ld", args[sc->offset]); 242bbeaf6c0SSean Eric Fagan break; 243bbeaf6c0SSean Eric Fagan case String: 244bbeaf6c0SSean Eric Fagan { 245bbeaf6c0SSean Eric Fagan char *tmp2; 246bbeaf6c0SSean Eric Fagan tmp2 = get_string(fd, (void*)args[sc->offset], 0); 247bbeaf6c0SSean Eric Fagan tmp = malloc(strlen(tmp2) + 3); 248bbeaf6c0SSean Eric Fagan sprintf(tmp, "\"%s\"", tmp2); 249bbeaf6c0SSean Eric Fagan free(tmp2); 250bbeaf6c0SSean Eric Fagan } 251bbeaf6c0SSean Eric Fagan break; 2529897b203SMatthew N. Dodd case StringArray: 2539897b203SMatthew N. Dodd { 2549897b203SMatthew N. Dodd int num, size, i; 2559897b203SMatthew N. Dodd char *tmp2; 2569897b203SMatthew N. Dodd char *string; 2579897b203SMatthew N. Dodd char *strarray[100]; /* XXX This is ugly. */ 2589897b203SMatthew N. Dodd 2599897b203SMatthew N. Dodd if (get_struct(fd, (void *)args[sc->offset], (void *)&strarray, 2609897b203SMatthew N. Dodd sizeof(strarray)) == -1) { 2619897b203SMatthew N. Dodd err(1, "get_struct %p", (void *)args[sc->offset]); 2629897b203SMatthew N. Dodd } 2639897b203SMatthew N. Dodd num = 0; 2649897b203SMatthew N. Dodd size = 0; 2659897b203SMatthew N. Dodd 2669897b203SMatthew N. Dodd /* Find out how large of a buffer we'll need. */ 2679897b203SMatthew N. Dodd while (strarray[num] != NULL) { 2689897b203SMatthew N. Dodd string = get_string(fd, (void*)strarray[num], 0); 2699897b203SMatthew N. Dodd size += strlen(string); 2709897b203SMatthew N. Dodd free(string); 2719897b203SMatthew N. Dodd num++; 2729897b203SMatthew N. Dodd } 2739897b203SMatthew N. Dodd size += 4 + (num * 4); 2749897b203SMatthew N. Dodd tmp = (char *)malloc(size); 2759897b203SMatthew N. Dodd tmp2 = tmp; 2769897b203SMatthew N. Dodd 2779897b203SMatthew N. Dodd tmp2 += sprintf(tmp2, " ["); 2789897b203SMatthew N. Dodd for (i = 0; i < num; i++) { 2799897b203SMatthew N. Dodd string = get_string(fd, (void*)strarray[i], 0); 2809897b203SMatthew N. Dodd tmp2 += sprintf(tmp2, " \"%s\"%c", string, (i+1 == num) ? ' ' : ','); 2819897b203SMatthew N. Dodd free(string); 2829897b203SMatthew N. Dodd } 2839897b203SMatthew N. Dodd tmp2 += sprintf(tmp2, "]"); 2849897b203SMatthew N. Dodd } 2859897b203SMatthew N. Dodd break; 286bbeaf6c0SSean Eric Fagan case Quad: 287bbeaf6c0SSean Eric Fagan { 288bbeaf6c0SSean Eric Fagan unsigned long long t; 289bbeaf6c0SSean Eric Fagan unsigned long l1, l2; 290bbeaf6c0SSean Eric Fagan l1 = args[sc->offset]; 291bbeaf6c0SSean Eric Fagan l2 = args[sc->offset+1]; 292bbeaf6c0SSean Eric Fagan t = make_quad(l1, l2); 293bbeaf6c0SSean Eric Fagan tmp = malloc(24); 294bbeaf6c0SSean Eric Fagan sprintf(tmp, "0x%qx", t); 295bbeaf6c0SSean Eric Fagan break; 296bbeaf6c0SSean Eric Fagan } 297bbeaf6c0SSean Eric Fagan case Ptr: 298bbeaf6c0SSean Eric Fagan tmp = malloc(12); 29922694ebaSBruce Evans sprintf(tmp, "0x%lx", args[sc->offset]); 300bbeaf6c0SSean Eric Fagan break; 301970649f9SSean Eric Fagan case Ioctl: 302970649f9SSean Eric Fagan { 3031be5d704SMark Murray const char *temp = ioctlname(args[sc->offset]); 304970649f9SSean Eric Fagan if (temp) 305970649f9SSean Eric Fagan tmp = strdup(temp); 306970649f9SSean Eric Fagan else { 307970649f9SSean Eric Fagan tmp = malloc(12); 30822694ebaSBruce Evans sprintf(tmp, "0x%lx", args[sc->offset]); 309970649f9SSean Eric Fagan } 310970649f9SSean Eric Fagan } 311f0ebbc29SDag-Erling Smørgrav break; 312f0ebbc29SDag-Erling Smørgrav case Signal: 313f0ebbc29SDag-Erling Smørgrav { 314f0ebbc29SDag-Erling Smørgrav long sig; 315f0ebbc29SDag-Erling Smørgrav 316f0ebbc29SDag-Erling Smørgrav sig = args[sc->offset]; 317f0ebbc29SDag-Erling Smørgrav tmp = malloc(12); 318f0ebbc29SDag-Erling Smørgrav if (sig > 0 && sig < NSIG) { 319f0ebbc29SDag-Erling Smørgrav int i; 320f0ebbc29SDag-Erling Smørgrav sprintf(tmp, "sig%s", sys_signame[sig]); 321f0ebbc29SDag-Erling Smørgrav for (i = 0; tmp[i] != '\0'; ++i) 322f0ebbc29SDag-Erling Smørgrav tmp[i] = toupper(tmp[i]); 323f0ebbc29SDag-Erling Smørgrav } else { 324f0ebbc29SDag-Erling Smørgrav sprintf(tmp, "%ld", sig); 325f0ebbc29SDag-Erling Smørgrav } 326f0ebbc29SDag-Erling Smørgrav } 327f0ebbc29SDag-Erling Smørgrav break; 3289ddd1412SDag-Erling Smørgrav case Sockaddr: 3299ddd1412SDag-Erling Smørgrav { 330dec17687SBrian Feldman struct sockaddr_storage ss; 3319ddd1412SDag-Erling Smørgrav char addr[64]; 3321be5d704SMark Murray struct sockaddr_in *lsin; 3331be5d704SMark Murray struct sockaddr_in6 *lsin6; 334dec17687SBrian Feldman struct sockaddr_un *sun; 335dec17687SBrian Feldman struct sockaddr *sa; 336dec17687SBrian Feldman char *p; 337dec17687SBrian Feldman u_char *q; 338dec17687SBrian Feldman int i; 3399ddd1412SDag-Erling Smørgrav 340dec17687SBrian Feldman /* yuck: get ss_len */ 341dec17687SBrian Feldman if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, 342dec17687SBrian Feldman sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) 343dec17687SBrian Feldman err(1, "get_struct %p", (void *)args[sc->offset]); 344dec17687SBrian Feldman /* sockaddr_un never have the length filled in! */ 345dec17687SBrian Feldman if (ss.ss_family == AF_UNIX) { 346dec17687SBrian Feldman if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, 347dec17687SBrian Feldman sizeof(*sun)) 348dec17687SBrian Feldman == -1) 349dec17687SBrian Feldman err(2, "get_struct %p", (void *)args[sc->offset]); 3509ddd1412SDag-Erling Smørgrav } else { 351dec17687SBrian Feldman if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, ss.ss_len) 352dec17687SBrian Feldman == -1) 353dec17687SBrian Feldman err(2, "get_struct %p", (void *)args[sc->offset]); 3549ddd1412SDag-Erling Smørgrav } 355dec17687SBrian Feldman 356dec17687SBrian Feldman switch (ss.ss_family) { 357dec17687SBrian Feldman case AF_INET: 3581be5d704SMark Murray lsin = (struct sockaddr_in *)&ss; 3591be5d704SMark Murray inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr); 3601be5d704SMark Murray asprintf(&tmp, "{ AF_INET %s:%d }", addr, htons(lsin->sin_port)); 361dec17687SBrian Feldman break; 362dec17687SBrian Feldman case AF_INET6: 3631be5d704SMark Murray lsin6 = (struct sockaddr_in6 *)&ss; 3641be5d704SMark Murray inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, sizeof addr); 3651be5d704SMark Murray asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr, htons(lsin6->sin6_port)); 366dec17687SBrian Feldman break; 367dec17687SBrian Feldman case AF_UNIX: 368dec17687SBrian Feldman sun = (struct sockaddr_un *)&ss; 369dec17687SBrian Feldman asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path); 370dec17687SBrian Feldman break; 371dec17687SBrian Feldman default: 372dec17687SBrian Feldman sa = (struct sockaddr *)&ss; 373dec17687SBrian Feldman asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data = {%n%*s } }", 374dec17687SBrian Feldman (int)sa->sa_len, (int)sa->sa_family, &i, 375dec17687SBrian Feldman 6 * (int)(sa->sa_len - ((char *)&sa->sa_data - (char *)sa)), ""); 376dec17687SBrian Feldman if (tmp != NULL) { 377dec17687SBrian Feldman p = tmp + i; 378dec17687SBrian Feldman for (q = (u_char *)&sa->sa_data; q < (u_char *)sa + sa->sa_len; q++) 379dec17687SBrian Feldman p += sprintf(p, " %#02x,", *q); 380dec17687SBrian Feldman } 381dec17687SBrian Feldman } 3829ddd1412SDag-Erling Smørgrav } 3839ddd1412SDag-Erling Smørgrav break; 384bbeaf6c0SSean Eric Fagan } 385bbeaf6c0SSean Eric Fagan return tmp; 386bbeaf6c0SSean Eric Fagan } 387bbeaf6c0SSean Eric Fagan 388203098d8SMatthew N. Dodd #define timespecsubt(tvp, uvp, vvp) \ 389203098d8SMatthew N. Dodd do { \ 390203098d8SMatthew N. Dodd (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 391203098d8SMatthew N. Dodd (vvp)->tv_nsec = (tvp)->tv_nsec - (uvp)->tv_nsec; \ 392203098d8SMatthew N. Dodd if ((vvp)->tv_nsec < 0) { \ 393203098d8SMatthew N. Dodd (vvp)->tv_sec--; \ 394203098d8SMatthew N. Dodd (vvp)->tv_nsec += 1000000000; \ 395203098d8SMatthew N. Dodd } \ 396203098d8SMatthew N. Dodd } while (0) 397203098d8SMatthew N. Dodd 398bbeaf6c0SSean Eric Fagan /* 399bbeaf6c0SSean Eric Fagan * print_syscall 400bbeaf6c0SSean Eric Fagan * Print (to outfile) the system call and its arguments. Note that 401bbeaf6c0SSean Eric Fagan * nargs is the number of arguments (not the number of words; this is 402bbeaf6c0SSean Eric Fagan * potentially confusing, I know). 403bbeaf6c0SSean Eric Fagan */ 404bbeaf6c0SSean Eric Fagan 405bbeaf6c0SSean Eric Fagan void 406ec0bed25SMatthew N. Dodd print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args) { 407bbeaf6c0SSean Eric Fagan int i; 4086cb533feSSean Eric Fagan int len = 0; 409203098d8SMatthew N. Dodd struct timespec timediff; 4100d0bd00eSMatthew N. Dodd 411c03bfcc8SMatthew N. Dodd if (trussinfo->flags & FOLLOWFORKS) 412c03bfcc8SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid); 413c03bfcc8SMatthew N. Dodd 4140d0bd00eSMatthew N. Dodd if (!strcmp(name, "execve") || !strcmp(name, "exit")) { 415203098d8SMatthew N. Dodd clock_gettime(CLOCK_REALTIME, &trussinfo->after); 4160d0bd00eSMatthew N. Dodd } 4170d0bd00eSMatthew N. Dodd 4180d0bd00eSMatthew N. Dodd if (trussinfo->flags & ABSOLUTETIMESTAMPS) { 419203098d8SMatthew N. Dodd timespecsubt(&trussinfo->after, &trussinfo->start_time, &timediff); 42037169f94SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%ld.%09ld ", 421fb034d05SMatthew N. Dodd (long)timediff.tv_sec, timediff.tv_nsec); 4220d0bd00eSMatthew N. Dodd } 4230d0bd00eSMatthew N. Dodd 4240d0bd00eSMatthew N. Dodd if (trussinfo->flags & RELATIVETIMESTAMPS) { 425203098d8SMatthew N. Dodd timespecsubt(&trussinfo->after, &trussinfo->before, &timediff); 42637169f94SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%ld.%09ld ", 427fb034d05SMatthew N. Dodd (long)timediff.tv_sec, timediff.tv_nsec); 4280d0bd00eSMatthew N. Dodd } 4290d0bd00eSMatthew N. Dodd 430ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%s(", name); 431c03bfcc8SMatthew N. Dodd 432bbeaf6c0SSean Eric Fagan for (i = 0; i < nargs; i++) { 433bbeaf6c0SSean Eric Fagan if (s_args[i]) 434ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%s", s_args[i]); 435bbeaf6c0SSean Eric Fagan else 436ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, "<missing argument>"); 437ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : ""); 438bbeaf6c0SSean Eric Fagan } 439ec0bed25SMatthew N. Dodd len += fprintf(trussinfo->outfile, ")"); 4406cb533feSSean Eric Fagan for (i = 0; i < 6 - (len / 8); i++) 441ec0bed25SMatthew N. Dodd fprintf(trussinfo->outfile, "\t"); 4426cb533feSSean Eric Fagan } 4436cb533feSSean Eric Fagan 4446cb533feSSean Eric Fagan void 445ec0bed25SMatthew N. Dodd print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args, int errorp, int retval) { 446ec0bed25SMatthew N. Dodd print_syscall(trussinfo, name, nargs, s_args); 4476cb533feSSean Eric Fagan if (errorp) { 448ec0bed25SMatthew N. Dodd fprintf(trussinfo->outfile, " ERR#%d '%s'\n", retval, strerror(retval)); 4496cb533feSSean Eric Fagan } else { 450ec0bed25SMatthew N. Dodd fprintf(trussinfo->outfile, " = %d (0x%x)\n", retval, retval); 4516cb533feSSean Eric Fagan } 452bbeaf6c0SSean Eric Fagan } 453