Subject: bin/1205: hex/ascii dump for tcpdump
To: None <gnats-admin@sun-lamp.pc.cs.cmu.edu>
From: Simon J. Gerraty <sjg@zen.void.oz.au>
List: netbsd-bugs
Date: 07/10/1995 18:50:05
>Number:         1205
>Category:       bin
>Synopsis:       add print_telnet and hex_dump to tcpdump
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Jul 10 18:50:02 1995
>Originator:     Simon J. Gerraty
>Organization:
Zen Programming...
>Release:        NetBSD-950508
>Environment:
	
System: NetBSD zen.void.oz.au 1.0A NetBSD 1.0A (ZEN) #3: Fri Jun 16 09:36:33 EST 1995 root@zen.void.oz.au:/f1/usr.src/sys/arch/i386/compile/ZEN i386


>Description:
	
The patch below adds the ability to hex/ascii dump packets at the
frame, packet or data level.   It also adds printing of telent
options.

The diffs while against NetBSD-950508, apply cleanly to 950627 as
well.

For example:

tcpdump -s1024 -n -X1 port 23
tcpdump: listening on ed0

22:27:43.578467 203.12.250.1.1546 > 203.12.250.2.23: P 1:28(27) ack 1 win 16384
Telnet:
0x0000  fffd 03                 DO SUPPRESS GO AHEAD
0x0003  fffb 18                 WILL TERMINAL TYPE
0x0006  fffb 1f                 WILL NAWS
0x0009  fffb 20                 WILL TSPEED
0x000c  fffb 21                 WILL LFLOW
0x000f  fffb 22                 WILL LINEMODE
0x0012  fffb 27                 WILL NEW-ENVIRON
0x0015  fffd 05                 DO STATUS
0x0018  fffb 23                 WILL XDISPLOC
 [tos 0x10]
Data: 67 bytes
Offset  Hex                                              ASCII
0x0000  4510 0043 2443 0000 4006 cc44 cb0c fa01         |E..C$C..@..D....|
0x0010  cb0c fa02 060a 0017 37ef 5601 4f84 7201         |........7.V.O.r.|
0x0020  5018 4000 10af 0000 fffd 03ff fb18 fffb         |P.@.............|
0x0030  1fff fb20 fffb 21ff fb22 fffb 27ff fd05         |... ..!.."..'...|
0x0040  fffb 23                                         |..#             |


>How-To-Repeat:
	
Apply the patch below and use -Xn 
-X0	dumps at the frame (eg ether) level
-X1	dumps at the packet (ip) level
-X2	dumps at the data level (after tcp or udp header)

-q	dissables telnet option printing.

>Fix:
	
cvs diff: Diffing .
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/Makefile,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 Makefile
*** Makefile	1995/04/13 04:16:13	1.1.1.1
--- Makefile	1995/07/07 13:02:53
***************
*** 36,43 ****
  	print-snmp.c print-ntp.c print-null.c print-egp.c print-ospf.c \
  	print-fddi.c print-llc.c print-sunrpc.c \
  	print-wb.c print-decnet.c print-isoclns.c print-ipx.c \
! 	util.c bpf_dump.c parsenfsfh.c version.c
  
  AWKS =	atime.awk packetdat.awk send-ack.awk stime.awk
  
  .include <bsd.prog.mk>
--- 36,48 ----
  	print-snmp.c print-ntp.c print-null.c print-egp.c print-ospf.c \
  	print-fddi.c print-llc.c print-sunrpc.c \
  	print-wb.c print-decnet.c print-isoclns.c print-ipx.c \
! 	util.c bpf_dump.c parsenfsfh.c version.c print-telnet.c
  
  AWKS =	atime.awk packetdat.awk send-ack.awk stime.awk
+ 
+ .if exists(hexdump.c)
+ SRCS+= hexdump.c
+ CFLAGS+= -DHEX_DUMP
+ .endif
  
  .include <bsd.prog.mk>
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/interface.h,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 interface.h
*** interface.h	1995/04/13 04:16:08	1.1.1.1
--- interface.h	1995/07/07 12:51:09
***************
*** 54,59 ****
--- 54,60 ----
  extern int tflag;		/* print packet arrival time */
  extern int vflag;		/* verbose */
  extern int xflag;		/* print packet in hex */
+ extern int Xflag;		/* print packet/data in hex/ascii */
  
  extern char *program_name;	/* used to generate self-identifying messages */
  
***************
*** 61,66 ****
--- 62,69 ----
  /* global pointers to beginning and end of current packet (during printing) */
  extern const u_char *packetp;
  extern const u_char *snapend;
+ extern const u_char *packetdata;		/* packet data! */
+ extern const u_char *penddata;			/* end of data */
  
  extern int fddipad;	/* alignment offset for FDDI headers, in bytes */
  
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-arp.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-arp.c
*** print-arp.c	1995/04/13 04:16:09	1.1.1.1
--- print-arp.c	1995/07/07 12:51:09
***************
*** 54,59 ****
--- 54,61 ----
  	if ((u_char *)(ap + 1) > snapend) {
  		printf("[|arp]");
  		return;
+ 	}  else {
+ 		packetdata = (u_char *) ap + sizeof(struct ether_arp);
  	}
  	if (length < sizeof(struct ether_arp)) {
  		(void)printf("truncated-arp");
***************
*** 120,123 ****
--- 122,137 ----
  	}
  	if (hrd != ARPHRD_ETHER)
  		printf(" hardware #%d", ap->arp_hrd);
+ #ifdef HEX_DUMP
+ 	if (Xflag) {
+ 		switch (Xflag) {
+ 		case -1:				/* everything! */
+ 			hex_dump((u_char *)ap, penddata - (u_char *)ap);
+ 			break;
+ 		default:
+ 			hex_dump(packetdata, penddata - packetdata);
+ 			break;
+ 		}
+ 	}
+ #endif
  }
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-ether.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-ether.c
*** print-ether.c	1995/04/13 04:16:10	1.1.1.1
--- print-ether.c	1995/07/09 10:38:21
***************
*** 51,56 ****
--- 51,58 ----
  
  const u_char *packetp;
  const u_char *snapend;
+ const u_char *packetdata;
+ const u_char *penddata;
  
  static inline void
  ether_print(register const u_char *bp, int length)
***************
*** 101,108 ****
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetp = p;
! 	snapend = p + caplen;
  
  	length -= sizeof(struct ether_header);
  	caplen -= sizeof(struct ether_header);
--- 103,110 ----
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetdata = packetp = p;
! 	penddata = snapend = p + caplen;
  
  	length -= sizeof(struct ether_header);
  	caplen -= sizeof(struct ether_header);
***************
*** 125,142 ****
  				printf("(LLC %s) ",
  			       etherproto_string(htons(extracted_ethertype)));
  			}
! 			if (!xflag && !qflag)
  				default_print(p, caplen);
  		}
  	} else if (ether_encap_print(ether_type, p, length, caplen) == 0) {
  		/* ether_type not known, print raw packet */
  		if (!eflag)
  			ether_print((u_char *)ep, length + sizeof(*ep));
! 		if (!xflag && !qflag)
  			default_print(p, caplen);
  	}
  	if (xflag)
  		default_print(p, caplen);
   out:
  	putchar('\n');
  }
--- 127,158 ----
  				printf("(LLC %s) ",
  			       etherproto_string(htons(extracted_ethertype)));
  			}
! 			if (!Xflag && !xflag && !qflag)
  				default_print(p, caplen);
  		}
  	} else if (ether_encap_print(ether_type, p, length, caplen) == 0) {
  		/* ether_type not known, print raw packet */
  		if (!eflag)
  			ether_print((u_char *)ep, length + sizeof(*ep));
! 		if (!Xflag && !xflag && !qflag)
  			default_print(p, caplen);
  	}
  	if (xflag)
  		default_print(p, caplen);
+ #ifdef HEX_DUMP
+ 	if (Xflag) {
+ 		switch (Xflag) {
+ 		case -1:				/* everything! */
+ 			hex_dump((u_char *)ep, penddata - (u_char *)ep);
+ 			break;
+ 		case 1:
+ 			hex_dump(p, penddata - p);
+ 		default:
+ 			hex_dump(packetdata, penddata - packetdata);
+ 			break;
+ 		}
+ 	} else					/* avoid \n */
+ #endif
   out:
  	putchar('\n');
  }
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-fddi.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-fddi.c
*** print-fddi.c	1995/04/13 04:16:10	1.1.1.1
--- print-fddi.c	1995/07/09 10:39:26
***************
*** 285,298 ****
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	snapend = p + caplen;
  	/*
  	 * Actually, the only printer that uses packetp is print-bootp.c,
  	 * and it assumes that packetp points to an Ethernet header.  The
  	 * right thing to do is to fix print-bootp.c to know which link
  	 * type is in use when it excavates. XXX
  	 */
! 	packetp = (u_char *)&ehdr;
  
  	if (eflag)
  		fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
--- 285,298 ----
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	penddata = snapend = p + caplen;
  	/*
  	 * Actually, the only printer that uses packetp is print-bootp.c,
  	 * and it assumes that packetp points to an Ethernet header.  The
  	 * right thing to do is to fix print-bootp.c to know which link
  	 * type is in use when it excavates. XXX
  	 */
! 	packetdata = packetp = (u_char *)&ehdr;
  
  	if (eflag)
  		fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
***************
*** 319,325 ****
  				printf("(LLC %s) ",
  			etherproto_string(htons(extracted_ethertype)));
  			}
! 			if (!xflag && !qflag)
  				default_print(p, caplen);
  		}
  	} else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
--- 319,325 ----
  				printf("(LLC %s) ",
  			etherproto_string(htons(extracted_ethertype)));
  			}
! 			if (!Xflag && !xflag && !qflag)
  				default_print(p, caplen);
  		}
  	} else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
***************
*** 328,338 ****
  		/* Some kinds of FDDI packet we cannot handle intelligently */
  		if (!eflag)
  			fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
! 		if (!xflag && !qflag)
  			default_print(p, caplen);
  	}
  	if (xflag)
  		default_print(p, caplen);
  out:
  	putchar('\n');
  }
--- 328,353 ----
  		/* Some kinds of FDDI packet we cannot handle intelligently */
  		if (!eflag)
  			fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
! 		if (!Xflag && !xflag && !qflag)
  			default_print(p, caplen);
  	}
  	if (xflag)
  		default_print(p, caplen);
+ #ifdef HEX_DUMP
+ 	if (Xflag) {
+ 		switch (Xflag) {
+ 		case -1:				/* everything! */
+ 			hex_dump((u_char *)&ehdr, penddata - (u_char *)&ehdr);
+ 			break;
+ 		case 1:
+ 			hex_dump(p, penddata - p);
+ 			break;
+ 		default:
+ 			hex_dump(packetdata, penddata - packetdata);
+ 			break;
+ 		}
+ 	} else					/* avoid \n */
+ #endif
  out:
  	putchar('\n');
  }
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-ip.c,v
retrieving revision 1.1.1.2
diff -c -b -r1.1.1.2 print-ip.c
*** print-ip.c	1995/05/08 15:07:49	1.1.1.2
--- print-ip.c	1995/07/10 08:20:43
***************
*** 232,238 ****
  			abuf = (u_char *)malloc(snaplen);
  		bcopy((char *)ip, (char *)abuf, min(length, snaplen));
  		snapend += abuf - (u_char *)ip;
! 		packetp = abuf;
  		ip = (struct ip *)abuf;
  	}
  #endif
--- 232,239 ----
  			abuf = (u_char *)malloc(snaplen);
  		bcopy((char *)ip, (char *)abuf, min(length, snaplen));
  		snapend += abuf - (u_char *)ip;
! 		packetdata = packetp = abuf;
! 		penddata = snapend;
  		ip = (struct ip *)abuf;
  	}
  #endif
***************
*** 243,255 ****
--- 244,263 ----
  	if (length < sizeof (struct ip)) {
  		(void)printf("truncated-ip %d", length);
  		return;
+ 	} else {
+ 		packetdata = (u_char *) ip + sizeof (struct ip);
  	}
+ 	
  	hlen = ip->ip_hl * 4;
  
  	len = ntohs(ip->ip_len);
  	if (length < len)
  		(void)printf("truncated-ip - %d bytes missing!",
  			len - length);
+ 	else {
+  		packetdata = (u_char *) ip + hlen;
+  		penddata = (u_char *) ip + len;
+  	}
  	len -= hlen;
  
  	/*
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-null.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-null.c
*** print-null.c	1995/04/13 04:16:11	1.1.1.1
--- print-null.c	1995/07/09 10:45:25
***************
*** 94,101 ****
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetp = p;
! 	snapend = p + caplen;
  
  	length -= NULL_HDRLEN;
  
--- 94,101 ----
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetdata = packetp = p;
! 	penddata = snapend = p + caplen;
  
  	length -= NULL_HDRLEN;
  
***************
*** 108,113 ****
--- 108,128 ----
  
  	if (xflag)
  		default_print((const u_char *)ip, caplen - NULL_HDRLEN);
+ #ifdef HEX_DUMP
+ 	if (Xflag) {
+ 		switch (Xflag) {
+ 		case -1:				/* everything! */
+ 			hex_dump((u_char *)p, penddata - p);
+ 			break;
+ 		case 1:
+ 			hex_dump((const u_char *)ip, penddata - (const u_char *)ip);
+ 			break;
+ 		default:
+ 			hex_dump(packetdata, penddata - packetdata);
+ 			break;
+ 		}
+ 	} else					/* avoid \n */
+ #endif
  	putchar('\n');
  }
  
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-ppp.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-ppp.c
*** print-ppp.c	1995/04/13 04:16:06	1.1.1.1
--- print-ppp.c	1995/07/09 10:46:39
***************
*** 72,79 ****
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetp = p;
! 	snapend = p + caplen;
  
  	if (eflag)
  		printf("%c %4d %02x %04x: ", p[0] ? 'O' : 'I', length,
--- 72,79 ----
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetdata = packetp = p;
! 	penddata = snapend = p + caplen;
  
  	if (eflag)
  		printf("%c %4d %02x %04x: ", p[0] ? 'O' : 'I', length,
***************
*** 85,90 ****
--- 85,105 ----
  
  	if (xflag)
  		default_print((const u_char *)ip, caplen - PPP_HDRLEN);
+ #ifdef HEX_DUMP
+ 	if (Xflag) {
+ 		switch (Xflag) {
+ 		case -1:			/* everything! */
+ 			hex_dump((u_char *)p, penddata - p);
+ 			break;
+ 		case 1:
+ 			hex_dump((const u_char *)ip, penddata - (const u_char *)ip);
+ 			break;
+ 		default:
+ 			hex_dump(packetdata, penddata - packetdata);
+ 			break;
+ 		}
+ 	} else
+ #endif
  out:
  	putchar('\n');
  }
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-sl.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-sl.c
*** print-sl.c	1995/04/13 04:16:06	1.1.1.1
--- print-sl.c	1995/07/09 10:47:09
***************
*** 83,90 ****
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetp = p;
! 	snapend = p + caplen;
  
  	length -= SLIP_HDRLEN;
  
--- 83,90 ----
  	 * and/or check that they're not walking off the end of the packet.
  	 * Rather than pass them all the way down, we set these globals.
  	 */
! 	packetdata = packetp = p;
! 	penddata = snapend = p + caplen;
  
  	length -= SLIP_HDRLEN;
  
***************
*** 97,102 ****
--- 97,117 ----
  
  	if (xflag)
  		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
+ #ifdef HEX_DUMP
+ 	if (Xflag) {
+ 		switch (Xflag) {
+ 		case -1:				/* everything! */
+ 			hex_dump((u_char *)p, penddata - p);
+ 			break;
+ 		case 1:
+ 			hex_dump((const u_char *)ip, penddata - (const u_char *)ip);
+ 		default:
+ 			hex_dump(packetdata, penddata - packetdata);
+ 			break;
+ 			break;
+ 		}
+ 	} else					/* avoid \n */
+ #endif
   out:
  	putchar('\n');
  }
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-tcp.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-tcp.c
*** print-tcp.c	1995/04/13 04:16:06	1.1.1.1
--- print-tcp.c	1995/07/10 22:33:39
***************
*** 37,42 ****
--- 37,43 ----
  #include <netinet/tcp.h>
  #include <netinet/tcpip.h>
  
+ 
  #include <stdio.h>
  #ifdef __STDC__
  #include <stdlib.h>
***************
*** 82,88 ****
  
  static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
  
- 
  void
  tcp_print(register const u_char *bp, register int length,
  	  register const u_char *bp2)
--- 83,88 ----
***************
*** 93,98 ****
--- 93,99 ----
  	register int hlen;
  	u_short sport, dport, win, urp;
  	tcp_seq seq, ack;
+ 	int tnport = htons(23);
  
  	tp = (struct tcphdr *)bp;
  	ip = (struct ip *)bp2;
***************
*** 103,108 ****
--- 104,111 ----
  	if (length < sizeof(struct tcphdr)) {
  		(void)printf("truncated-tcp %d", length);
  		return;
+ 	} else {
+ 		packetdata = (u_char *) tp + sizeof(struct tcphdr);
  	}
  
  	sport = ntohs(tp->th_sport);
***************
*** 181,186 ****
--- 184,191 ----
  	length -= hlen;
  	if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
  		(void)printf(" %lu:%lu(%d)", seq, seq + length, length);
+ 	packetdata = (u_char *) tp + hlen;
+ 	
  	if (flags & TH_ACK)
  		(void)printf(" ack %u", ack);
  
***************
*** 274,278 ****
--- 279,285 ----
  		}
  		putchar('>');
  	}
+ 	if (!qflag && (tp->th_dport == tnport || tp->th_sport == tnport))
+ 		print_telnet(packetdata, penddata - packetdata);
  }
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/print-udp.c,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 print-udp.c
*** print-udp.c	1995/04/13 04:16:12	1.1.1.1
--- print-udp.c	1995/07/07 12:51:11
***************
*** 148,153 ****
--- 148,155 ----
  	if (length < sizeof(struct udphdr)) {
  		(void)printf(" truncated-udp %d", length);
  		return;
+ 	} else {
+ 		packetdata = (u_char *) up + sizeof(struct udphdr);
  	}
  	length -= sizeof(struct udphdr);
  
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/tcpdump.8,v
retrieving revision 1.1.1.1
diff -c -b -r1.1.1.1 tcpdump.8
*** tcpdump.8	1995/04/13 04:16:05	1.1.1.1
--- tcpdump.8	1995/07/09 23:30:01
***************
*** 31,36 ****
--- 31,39 ----
  [
  .B \-deflnNOpqStvx
  ] [
+ .B \-X
+ .I level
+ ] [
  .B \-c
  .I count
  ] [
***************
*** 175,180 ****
--- 178,194 ----
  The smaller of the entire packet or
  .I snaplen
  bytes will be printed.
+ .TP
+ .B \-X
+ Print data part of each packet in hex and ASCII up to the end of 
+ the packet or to the end of available data.
+ The data start pointer is updated by various protocol print modules
+ (currently ip,tcp,arp,udp) otherwise it defaults to the start of the packet.
+ If \fIlevel\fR is 0, then the entire packet (including say ethernet
+ header) is dumped.   
+ If \fIlevel\fR is 1, then the packet is dumped from say the ip header on.
+ Any other value of \fIlevel\fR causes just the data portion of the
+ packet to be dumped.
  .IP "\fI expression\fP"
  .RS
  selects which packets will be dumped.  If no \fIexpression\fP
===================================================================
RCS file: /local/src/master/usr.src/usr.sbin/tcpdump/tcpdump.c,v
retrieving revision 1.1.1.2
diff -c -b -r1.1.1.2 tcpdump.c
*** tcpdump.c	1995/05/08 15:08:08	1.1.1.2
--- tcpdump.c	1995/07/07 12:51:11
***************
*** 61,66 ****
--- 61,67 ----
  int eflag;			/* print ethernet header */
  int vflag;			/* verbose */
  int xflag;			/* print packet in hex */
+ int Xflag = 0;			/* print packet in hex */
  int Oflag = 1;			/* run filter code optimizer */
  int Sflag;			/* print raw TCP sequence numbers */
  int packettype;
***************
*** 153,159 ****
  		program_name = argv[0];
  
  	opterr = 0;
! 	while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:StT:vw:xY")) != EOF)
  		switch (op) {
  		case 'c':
  			cnt = atoi(optarg);
--- 154,160 ----
  		program_name = argv[0];
  
  	opterr = 0;
! 	while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:StT:vw:xYX:")) != EOF)
  		switch (op) {
  		case 'c':
  			cnt = atoi(optarg);
***************
*** 249,254 ****
--- 250,261 ----
  #endif
  		case 'x':
  			++xflag;
+ 			break;
+ 
+ 		case 'X':
+ 			Xflag = atoi(optarg);
+ 			if (Xflag <= 0)
+ 				Xflag = -1;	/* print everything */
  			break;
  
  		default:
*** /dev/null	Tue Jul 11 07:40:01 1995
--- print-telnet.c	Mon Jul 10 23:24:31 1995
***************
*** 0 ****
--- 1,128 ----
+ /*
+  *      @(#)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 and that due credit be given 
+  *      to the author.  
+  *      2/ that any changes to this code are clearly commented 
+  *      as such so that the author does not get blamed for bugs 
+  *      other than his own.
+  */
+ 
+ #ifndef lint
+ static char rcsid[] = "$Id: print-telnet.c,v 1.1 1995/07/10 13:24:31 sjg Exp $";
+ #endif
+ 
+ #include <sys/param.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ 
+ #include <netinet/in.h>
+ #include <netinet/in_systm.h>
+ #include <netinet/ip.h>
+ #include <netinet/ip_var.h>
+ #include <netinet/tcp.h>
+ #include <netinet/tcpip.h>
+ 
+ #define TELCMDS
+ #define TELOPTS
+ #include <arpa/telnet.h>
+ 
+ #include <stdio.h>
+ #ifdef __STDC__
+ #include <stdlib.h>
+ #endif
+ #include <unistd.h>
+ 
+ #include "interface.h"
+ #include "addrtoname.h"
+ 
+ 
+ #ifndef TELCMD_FIRST
+ # define TELCMD_FIRST SE
+ #endif
+ 
+ void
+ print_telnet(sp, length)
+ 	register u_char *sp;
+ 	register int length;
+ {
+ 	static char tnet[128];
+ 	register int i, c;
+ 	register u_char *rcp;
+ 	int off, first = 1;
+ 	u_char	*osp = sp;
+ 
+ 	off = 0;
+ 	
+ 	while (length > 0 && *sp == IAC) {
+ 		osp = sp;
+ 		tnet[0] = '\0';
+ 		
+ 		c = *sp++;
+ 		length--;
+ 		switch (*sp) {
+ 		case IAC:			/* <IAC><IAC>! */
+ 			length = 0;
+ 			break;
+ 		default:
+ 			if (first) {
+ 				if (Xflag)
+ 					printf("\nTelnet:\n");
+ 				else
+ 					printf(" telnet");
+ 			}
+ 			c = *sp++;
+ 			length--;
+ 			if ((i = c - TELCMD_FIRST) >= 0 &&
+ 			    i <= IAC - TELCMD_FIRST) {
+ 				(void)strcat(strcpy(tnet, telcmds[i]), " ");
+ 			} else {
+ 				(void)printf("unknown: ff%02x\n", c);
+ 				return;
+ 			}
+ 			i = *sp++;		/* option */
+ 			length--;
+ 			if (i >= 0 && i < NTELOPTS) {
+ 				(void)strcat(tnet, telopts[i]);
+ 			}
+ 			if (c == SB) {
+ 				c = *sp++;
+ 				(void)strcat(tnet, c ? " SEND" : " IS '");
+ 				rcp = sp;
+ 				i = strlen(tnet);
+ 				while (*sp++ != IAC) ;
+ 				if (i + 16 + sp - rcp < sizeof(tnet)) {
+ 					(void)strncpy(&tnet[i], rcp, sp - rcp);
+ 					i += (sp - rcp);
+ 					tnet[i] = '\0';
+ 				} else if (i + 16 < sizeof(tnet)) {
+ 					(void)strcat(&tnet[i], "data...");
+ 				}
+ 				if (*sp++ == SE)
+ 					(void)strcat(tnet, c ? " SE" : "' SE");
+ 			}
+ 			/*
+ 			 * now print it
+ 			 */
+ 			if (Xflag) {
+ 				i = sp - osp;
+ 				print_hex(osp, i, off);
+ 				off += i;
+ 				if (i > 8)
+ 					printf("\n\t\t\t\t%s\n", tnet);
+ 				else
+ 					printf("%*s\t%s\n", (8 - i) * 3, "", tnet);
+ 			} else {
+ 				printf("%s%s", (first) ? " " : ", ", tnet);
+ 			}
+ 			first = 0;
+ 			break;
+ 		}
+ 	}
+ 	if (length >= 0)
+ 		packetdata = sp;
+ }
*** /dev/null	Tue Jul 11 07:40:01 1995
--- hexdump.c	Mon Jul 10 23:22:45 1995
***************
*** 0 ****
--- 1,176 ----
+ /* NAME:
+  *	hex_dump - print data in hex and ASCII.
+  *
+  * DESCRIPTION:
+  *	The above says it all :-)
+  *	
+  */
+ /*
+  *      @(#)Copyright (c) 1993, Simon J. Gerraty.
+  *      
+  *      This code is presented AS IS.  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 and that due credit be given 
+  *      to the author.  
+  *      2/ that any changes to this code are clearly commented 
+  *      as such so that the author does not get blamed for bugs 
+  *      other than his own.
+  *      
+  *      Please send copies of changes and bug-fixes to:
+  *      sjg@zen.void.oz.au
+  */
+ #ifndef lint
+ static char RCSid[] = "$Id: hexdump.c,v 1.2 1995/07/10 13:22:45 sjg Exp $";
+ #endif
+ 
+ #include <stdio.h>
+ 
+ int HexOffset = 1;
+ 
+ 
+ char *
+ sprint_hex(dest, buf, nbytes, off)
+ 	char *dest;
+ 	unsigned char *buf;
+ 	int nbytes;
+ 	int off;
+ {
+ 	register char *rcp = dest;
+ 	register int i;
+ 
+ 	if (off && (off % 128) == 0) {
+ 		(void) sprintf(rcp, "\n");
+ 		rcp++;
+ 	}
+ 	if (HexOffset) 
+ 		(void) sprintf(rcp, "0x%04x  ", off);
+ 	else
+ 		(void) sprintf(rcp, "%4d  ", off);
+ 	rcp += strlen(rcp);
+ 
+ 	for (i = 0; i < 16 && i < nbytes; i++) {
+ 		(void) sprintf(rcp, "%02x%s", buf[i], (i % 2) ? " " : "");
+ 		rcp += strlen(rcp);
+ 	}
+ 	return dest;
+ }
+ 
+ char *
+ shex_dump(dest, buf, nbytes)
+ 	char *dest;
+ 	unsigned char *buf;
+ 	int nbytes;
+ {
+ 	register unsigned int i, j, off, c;
+ 	unsigned char *endp = buf + nbytes;
+ 	register char *rcp, *cp = dest;
+ 	
+ 	dest[0] = '\0';
+ 	for (i = 0, off = 0; buf < endp; buf += i, off += i) {
+ 		rcp = sprint_hex(cp, buf, endp - buf, off);
+ 		rcp += strlen(rcp);
+ 		while ((rcp - cp) < 56)
+ 			*rcp++ = ' ';
+ 		*rcp++ = '|';
+ 
+ 		for (i = 0; i < 16 && buf + i < endp; i++) {
+ 			if ((c = (unsigned int) buf[i]) < ' ' || c >= 0x7f)
+ 				*rcp++ = '.';
+ 			else {
+ 				(void) sprintf(rcp, "%c", c);
+ 				rcp++;
+ 			}
+ 		}
+ 		for (j = i; j < 16; j++)
+ 			*rcp++ = ' ';
+ 		*rcp++ = '|';
+ 		*rcp++ = '\n';
+ 		cp = rcp;
+ 	}
+ 	return dest;
+ }
+ 
+ int
+ fprint_hex(fh, buf, nbytes, off)
+ 	FILE *fh;
+ 	register unsigned char *buf;
+ 	register int nbytes;
+ 	int off;
+ {
+ 	register int i;
+ 
+ 	if (off && (off % 128) == 0)
+ 		(void) fprintf(fh, "\n");
+ 	if (HexOffset)
+ 		(void) fprintf(fh, "0x%04x\t", off);
+ 	else
+ 		(void) fprintf(fh, "%4d\t", off);
+ 
+ 	for (i = 0; i < 16 && i < nbytes; i++)
+ 		(void) fprintf(fh, "%02x%s", buf[i], (i % 2) ? " " : "");
+ 	return i;
+ }
+ 
+ void
+ fhex_dump(fh, buf, nbytes)
+ 	FILE *fh;
+ 	register unsigned char *buf;
+ 	register int nbytes;
+ {
+ 	register unsigned int i, off, c;
+ 	unsigned char *endp = buf + nbytes;
+ 
+ 	if (nbytes > 0)
+ 		(void) fprintf(fh, "\nData: %d bytes\nOffset\tHex\t\t\t\t\t\t ASCII\n",
+ 			      nbytes);
+ 		
+ 	for (i = 0, off = 0; buf < endp; buf += i, off += i) {
+ 		i = fprint_hex(fh, buf, endp - buf, off);
+ 		(void) fprintf(fh, "%*s\t|", (16 - i) * 3, "");
+ 		for (i = 0; i < 16 && buf + i < endp; i++) {
+ 			if ((c = (unsigned int) buf[i]) < ' ' || c >= 0x7f)
+ 				c = '.';
+ 			(void) fprintf(fh, "%c", c);
+ 		}
+ 		(void) fprintf(fh, "%*s|\n", 16 - i, "");
+ 	}
+ 	(void) fprintf(fh, "\n");
+ 	(void) fflush(fh);
+ }
+ 
+ print_hex(buf, nbytes, off)
+ 	register unsigned char *buf;
+ 	register int nbytes;
+ 	int off;
+ {
+ 	return fprint_hex(stdout, buf, nbytes, off);
+ }
+ 
+ void
+ hex_dump(buf, nbytes)
+ 		register unsigned char *buf;
+ 	register int nbytes;
+ {
+ 	fhex_dump(stdout, buf, nbytes);
+ }
+ 	 
+ #ifdef MAIN
+ int
+ main(argc, argv)
+ 	int argc;
+ 	char **argv;
+ {
+ 	int c;
+ 	char buf[1024+1];
+ 	char buf2[1024+1];
+ 	
+ 	while ((c = read(0, buf, 1024)) > 0) {
+ 		hex_dump(buf, c);
+ 		shex_dump(buf2, buf, c);
+ 		printf("%s", buf2);
+ 	}
+ 	return 0;
+ }
+ #endif
>Audit-Trail:
>Unformatted: