/* * An ASCII filter for tcpdump. * * "tcpdump -x" prints the content of network packets in hex. Read * this data and format it in ASCII. Non-printable chars are output * as NON_PRINTABLE_CHAR, defined below. * * The terminal window size is used for displayed lines length. * * Typical usage: * tcpdump -lx -s 512 | tcpdump2ascii * * NOTE * Newish versions of tcpdump implement a "-X" flag that does just this. * * Renaud Waldura * Tue Jul 25 15:24:75 PDT 2000 * */ #include #include #include #include #include /* for struct winsize */ #define DEFAULT_LINE_LENGTH 80 #define MAX_LINE_LENGTH 256 #define NON_PRINTABLE_CHAR ' ' #define hex(c) ((isdigit(c)) ? (c) - '0' : tolower(c) - 'a' + 10) int line_length = -1; int get_window_columns (int fd) { struct winsize ws; int e = ioctl(fd, TIOCGWINSZ, &ws); return (e == 0) ? ws.ws_col : 0; } void get_options (int argc, const char* argv[]) { int columns; if (argc > 1) line_length = atoi(argv[1]); if (line_length < 1 && (columns = get_window_columns(1))) line_length = columns; if (line_length < 1 || line_length > MAX_LINE_LENGTH) line_length = DEFAULT_LINE_LENGTH; } void winch_handler (int sig) { int columns = get_window_columns(1); if (columns) line_length = columns; } main (int argc, const char* argv[]) { char inbuf[MAX_LINE_LENGTH], outbuf[MAX_LINE_LENGTH]; char *s; int n = 0; /* get options */ get_options(argc, argv); /* install signal handler for window size change */ signal(SIGWINCH, winch_handler); while (s = fgets(inbuf, MAX_LINE_LENGTH, stdin)) { /* look for lines starting with whitespace */ if (!isspace(*s++)) continue; while (*s) { char c; if (!isxdigit(*s)) /* skip junk */ { s++; continue; } /* convert pair of hex digits to char */ c = 16 * hex(s[0]) + hex(s[1]); s += 2; /* store in buffer */ outbuf[n++] = (isprint(c)) ? c : NON_PRINTABLE_CHAR; if (n > line_length - 1) /* print buffer if full */ { outbuf[n] = '\0'; puts(outbuf); n = 0; } } } /* flush output buffer */ outbuf[n] = '\0'; puts(outbuf); return 0; }