From: itojun Date: Wed, 22 Dec 1999 15:44:09 +0000 (+0000) Subject: add print-ascii.c and print-telnet.c from netbsd. X-Git-Tag: tcpdump-3.5.1~447 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/2813c22cf1ab58ee309749eae16f6211cea59952 add print-ascii.c and print-telnet.c from netbsd. - add -X option for ascii printing. - telnet command sequences (ff xx xx) will be dumped with -vvv -X. --- diff --git a/Makefile.in b/Makefile.in index 12ff18e5..26b5e6cc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,7 +17,7 @@ # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # -# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.218 1999-12-14 16:49:02 fenner Exp $ (LBL) +# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.219 1999-12-22 15:44:09 itojun Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) @@ -76,7 +76,7 @@ CSRC = tcpdump.c \ print-esp.c print-ah.c print-vjc.c print-isakmp.c print-chdlc.c \ print-ipcomp.c print-mobile.c print-l2tp.c print-bgp.c print-rx.c \ print-lane.c print-cip.c print-pppoe.c print-lcp.c \ - print-smb.c smbutil.c + print-smb.c smbutil.c print-ascii.c print-telnet.c LOCALSRC = @LOCALSRC@ GENSRC = version.c LIBOBJS = @LIBOBJS@ diff --git a/interface.h b/interface.h index 52316132..bc4dc596 100644 --- a/interface.h +++ b/interface.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.117 1999-12-22 06:27:20 itojun Exp $ (LBL) + * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.118 1999-12-22 15:44:09 itojun Exp $ (LBL) */ #ifndef tcpdump_interface_h @@ -47,6 +47,7 @@ extern int Sflag; /* print raw TCP sequence numbers */ extern int tflag; /* print packet arrival time */ extern int vflag; /* verbose */ extern int xflag; /* print packet in hex */ +extern int Xflag; /* print packet in hex/ascii */ extern char *ahsecret; extern char *espsecret; @@ -172,6 +173,11 @@ extern char *dnnum_string(u_short); struct pcap_pkthdr; #endif +extern void ascii_print_with_offset(const u_char *, u_int, u_int); +extern void ascii_print(const u_char *, u_int); +extern void hex_print_with_offset(const u_char *, u_int, u_int); +extern void telnet_print(const u_char *, u_int); +extern void hex_print(const u_char *, u_int); extern int ether_encap_print(u_short, const u_char *, u_int, u_int); extern int llc_print(const u_char *, u_int, u_int, const u_char *, const u_char *); diff --git a/print-ascii.c b/print-ascii.c new file mode 100644 index 00000000..8483c47b --- /dev/null +++ b/print-ascii.c @@ -0,0 +1,158 @@ +/* $NetBSD: print-ascii.c,v 1.1 1999/09/30 14:49:12 sjg Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Alan Barrett and Simon J. Gerraty. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#ifndef lint +__RCSID("$NetBSD: print-ascii.c,v 1.1 1999/09/30 14:49:12 sjg Exp $"); +#endif +#include +#include +#include + +#include "interface.h" + +#define HEXDUMP_BYTES_PER_LINE 16 +#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2) +#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */ +#define HEXDUMP_HEXSTUFF_PER_LINE \ + (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE) + +void +ascii_print_with_offset(register const u_char *cp, register u_int length, + register u_int oset) +{ + register u_int i; + register int s1, s2; + register int nshorts; + char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp; + char asciistuff[HEXDUMP_BYTES_PER_LINE+1], *asp; + + nshorts = length / sizeof(u_short); + i = 0; + hsp = hexstuff; asp = asciistuff; + while (--nshorts >= 0) { + s1 = *cp++; + s2 = *cp++; + (void)sprintf(hsp, " %02x%02x", s1, s2); + hsp += HEXDUMP_HEXSTUFF_PER_SHORT; + *(asp++) = (isgraph(s1) ? s1 : '.'); + *(asp++) = (isgraph(s2) ? s2 : '.'); + if (++i >= HEXDUMP_SHORTS_PER_LINE) { + *hsp = *asp = '\0'; + (void)printf("\n0x%04x\t%-*s\t%s", + oset, HEXDUMP_HEXSTUFF_PER_LINE, + hexstuff, asciistuff); + i = 0; hsp = hexstuff; asp = asciistuff; + oset += HEXDUMP_BYTES_PER_LINE; + } + } + if (length & 1) { + s1 = *cp++; + (void)sprintf(hsp, " %02x", s1); + hsp += 3; + *(asp++) = (isgraph(s1) ? s1 : '.'); + ++i; + } + if (i > 0) { + *hsp = *asp = '\0'; + (void)printf("\n0x%04x\t%-*s\t%s", + oset, HEXDUMP_HEXSTUFF_PER_LINE, + hexstuff, asciistuff); + } +} + +void +ascii_print(register const u_char *cp, register u_int length) +{ + ascii_print_with_offset(cp, length, 0); +} + +/* + * telnet_print() wants this. It is essentially default_print_unaligned() + */ +void +hex_print_with_offset(register const u_char *cp, register u_int length, + register u_int oset) +{ + register u_int i, s; + register int nshorts; + + nshorts = (u_int) length / sizeof(u_short); + i = 0; + while (--nshorts >= 0) { + if ((i++ % 8) == 0) { + (void)printf("\n0x%04x\t", oset); + oset += HEXDUMP_BYTES_PER_LINE; + } + s = *cp++; + (void)printf(" %02x%02x", s, *cp++); + } + if (length & 1) { + if ((i % 8) == 0) + (void)printf("\n0x%04x\t", oset); + (void)printf(" %02x", *cp); + } +} + +/* + * just for completeness + */ +void +hex_print(register const u_char *cp, register u_int length) +{ + hex_print_with_offset(cp, length, 0); +} + +#ifdef MAIN +int +main(int argc, char *argv[]) +{ + hex_print("Hello, World!\n", 14); + printf("\n"); + ascii_print("Hello, World!\n", 14); + printf("\n"); +#define TMSG "Now is the winter of our discontent...\n" + ascii_print_with_offset(TMSG, sizeof(TMSG) - 1, 0x100); + printf("\n"); + exit(0); +} +#endif /* MAIN */ diff --git a/print-tcp.c b/print-tcp.c index 1561cdc3..4cb88861 100644 --- a/print-tcp.c +++ b/print-tcp.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.62 1999-12-22 06:27:23 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.63 1999-12-22 15:44:10 itojun Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -108,6 +108,9 @@ struct tcp_seq_hash { static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE]; +#ifndef TELNET_PORT +#define TELNET_PORT 23 +#endif #ifndef BGP_PORT #define BGP_PORT 179 #endif @@ -491,9 +494,12 @@ tcp_print(register const u_char *bp, register u_int length, * Decode payload if necessary. */ bp += (tp->th_off * 4); - if (sport == BGP_PORT || dport == BGP_PORT) + if (!qflag && vflag && length > 0 + && (sport == TELNET_PORT || dport == TELNET_PORT)) + telnet_print(bp, length); + else if (sport == BGP_PORT || dport == BGP_PORT) bgp_print(bp, length); - if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) + else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) nbt_tcp_print(bp, length); return; bad: diff --git a/print-telnet.c b/print-telnet.c new file mode 100644 index 00000000..6df1a230 --- /dev/null +++ b/print-telnet.c @@ -0,0 +1,191 @@ +/* $NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Simon J. Gerraty. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * @(#)Copyright (c) 1994, Simon J. Gerraty. + * + * This is free software. It comes with NO WARRANTY. + * Permission to use, modify and distribute this source code + * is granted subject to the following conditions. + * 1/ that the above copyright notice and this notice + * are preserved in all copies. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#ifndef lint +__RCSID("$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $"); +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define TELCMDS +#define TELOPTS +#include + +#include +#ifdef __STDC__ +#include +#endif +#include +#include + +#include "interface.h" +#include "addrtoname.h" + + +#ifndef TELCMD_FIRST +# define TELCMD_FIRST SE +#endif + +void +telnet_print(register const u_char *sp, u_int length) +{ + static char tnet[128]; + register int i, c, x; + register u_char *rcp; + int off, first = 1; + u_char *osp; + + off = 0; + x = 0; + + while (length > 0 && *sp == IAC) { + osp = (u_char *) sp; + tnet[0] = '\0'; + + c = *sp++; + length--; + switch (*sp) { + case IAC: /* ! */ + if (length > 1 && sp[1] == IAC) { + (void)strcpy(tnet, "IAC IAC"); + } else { + length = 0; + continue; + } + break; + default: + c = *sp++; + length--; + if ((i = c - TELCMD_FIRST) < 0 + || i > IAC - TELCMD_FIRST) { + (void)printf("unknown: ff%02x\n", c); + return; + } + switch (c) { + case DONT: + case DO: + case WONT: + case WILL: + case SB: + x = *sp++; /* option */ + length--; + if (x >= 0 && x < NTELOPTS) { + (void)sprintf(tnet, "%s %s", + telcmds[i], telopts[x]); + } else { + (void)sprintf(tnet, "%s %#x", + telcmds[i], x); + } + break; + default: + (void)strcpy(tnet, telcmds[i]); + } + if (c == SB) { + c = *sp++; + length--; + (void)strcat(tnet, c ? " SEND" : " IS '"); + rcp = (u_char *) sp; + i = strlen(tnet); + while (length > 0 && (x = *sp++) != IAC) + --length; + if (x == IAC) { + if (2 < vflag + && i + 16 + sp - rcp < sizeof(tnet)) { + (void)strncpy(&tnet[i], rcp, sp - rcp); + i += (sp - rcp) - 1; + tnet[i] = '\0'; + } else if (i + 8 < sizeof(tnet)) { + (void)strcat(&tnet[i], "..."); + } + if (*sp++ == SE + && i + 4 < sizeof(tnet)) + (void)strcat(tnet, c ? " SE" : "' SE"); + } else if (i + 16 < sizeof(tnet)) { + (void)strcat(tnet, " truncated!"); + } + } + break; + } + /* + * now print it + */ + if (Xflag && 2 < vflag) { + if (first) + printf("\nTelnet:\n"); + i = sp - osp; + hex_print_with_offset(osp, i, off); + off += i; + if (i > 8) + printf("\n\t\t\t\t%s", tnet); + else + printf("%*s\t%s", (8 - i) * 3, "", tnet); + } else { + printf("%s%s", (first) ? " [telnet " : ", ", tnet); + } + first = 0; + } + if (!first) { + if (Xflag && 2 < vflag) + printf("\n"); + else + printf("]"); + } +} diff --git a/tcpdump.1 b/tcpdump.1 index 7170a935..f94553e7 100644 --- a/tcpdump.1 +++ b/tcpdump.1 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.71 1999-12-13 18:06:15 mcr Exp $ (LBL) +.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.72 1999-12-22 15:44:10 itojun Exp $ (LBL) .\" .\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -27,7 +27,7 @@ tcpdump \- dump traffic on a network .na .B tcpdump [ -.B \-adeflnNOpqRStvx +.B \-adeflnNOpqRStvxX ] [ .B \-c .I count @@ -223,6 +223,13 @@ and type of service information in an IP packet is printed. Even more verbose output. For example, additional fields are printed from NFS reply packets. .TP +.B \-vvv +Even more verbose output. For example, +telnet \fBSB\fP ... \fBSE\fP options +are printed in full. With +.B \-X +telnet options are printed in hex as well. +.TP .B \-w Write the raw packets to \fIfile\fR rather than parsing and printing them out. They can later be printed with the \-r option. @@ -233,6 +240,16 @@ Print each packet (minus its link level header) in hex. The smaller of the entire packet or .I snaplen bytes will be printed. +.TP +.B \-X +When printing hex, print ascii too. Thus if +.B \-x +is also set, the packet is printed in hex/ascii. +This is very handy for analysing new protocols. +Even if +.B \-x +is not also set, some parts of some packets may be printed +in hex/ascii. .IP "\fI expression\fP" .RS selects which packets will be dumped. If no \fIexpression\fP diff --git a/tcpdump.c b/tcpdump.c index 714b19ee..71e7c7ea 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -24,7 +24,7 @@ static const char copyright[] = "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\ The Regents of the University of California. All rights reserved.\n"; static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.137 1999-12-22 06:27:24 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.138 1999-12-22 15:44:11 itojun Exp $ (LBL)"; #endif /* @@ -76,6 +76,7 @@ int Sflag; /* print raw TCP sequence numbers */ int tflag = 1; /* print packet arrival time */ int vflag; /* verbose */ int xflag; /* print packet in hex */ +int Xflag; /* print packet in ascii as well as hex */ char *ahsecret = NULL; /* AH secret key */ char *espsecret = NULL; /* ESP secret key */ @@ -175,7 +176,7 @@ main(int argc, char **argv) opterr = 0; while ( - (op = getopt(argc, argv, "ac:deE:fF:i:lnNm:Opqr:Rs:StT:vw:xY")) != EOF) + (op = getopt(argc, argv, "ac:deE:fF:i:lnNm:Opqr:Rs:StT:vw:xXY")) != EOF) switch (op) { case 'a': @@ -310,6 +311,15 @@ main(int argc, char **argv) case 'w': WFileName = optarg; break; + + case 'x': + ++xflag; + break; + + case 'X': + ++Xflag; + break; + #ifdef YYDEBUG case 'Y': { @@ -319,10 +329,6 @@ main(int argc, char **argv) } break; #endif - case 'x': - ++xflag; - break; - default: usage(); /* NOTREACHED */ @@ -445,10 +451,13 @@ cleanup(int signo) void default_print_unaligned(register const u_char *cp, register u_int length) { -#if 1 register u_int i, s; register int nshorts; + if (Xflag) { + ascii_print(cp, length); + return; + } nshorts = (u_int) length / sizeof(u_short); i = 0; while (--nshorts >= 0) { @@ -462,44 +471,6 @@ default_print_unaligned(register const u_char *cp, register u_int length) (void)printf("\n\t\t\t"); (void)printf(" %02x", *cp); } -#else - register u_int i; - register int nshorts; - - char line[81]; - - nshorts = (u_int) length / sizeof(u_short); - i = 0; - memset(line, ' ', 80); - line[81]='\0'; - - putchar('\n'); - while (nshorts >= 0) { - - sprintf(line+20+i*5, "%02x%02x ", cp[0], cp[1]); - - if(isprint(cp[0])) { - line[62+i*2]=cp[0]; - } else { - line[62+i*2]='.'; - } - if(isprint(cp[1])) { - line[62+i*2+1]=cp[1]; - } else { - line[62+i*2+1]='.'; - } - i++; - if (i == 8) { - line[60]=' '; - line[61]=' '; - line[62+16]='\0'; - puts(line); - i=0; - } - cp += 2; - nshorts--; - } -#endif } /* @@ -522,7 +493,7 @@ usage(void) (void)fprintf(stderr, "%s version %s\n", program_name, version); (void)fprintf(stderr, "libpcap version %s\n", pcap_version); (void)fprintf(stderr, -"Usage: %s [-adeflnNOpqStvx] [-c count] [ -F file ]\n", program_name); +"Usage: %s [-adeflnNOpqStvxX] [-c count] [ -F file ]\n", program_name); (void)fprintf(stderr, "\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n"); (void)fprintf(stderr,