xref: /freebsd/contrib/tcpdump/print-ascii.c (revision 3340d77368116708ab5b5b95acf6c9c710528300)
1b0453382SBill Fenner /*	$NetBSD: print-ascii.c,v 1.1 1999/09/30 14:49:12 sjg Exp $ 	*/
2b0453382SBill Fenner 
3b0453382SBill Fenner /*-
4b0453382SBill Fenner  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5b0453382SBill Fenner  * All rights reserved.
6b0453382SBill Fenner  *
7b0453382SBill Fenner  * This code is derived from software contributed to The NetBSD Foundation
8b0453382SBill Fenner  * by Alan Barrett and Simon J. Gerraty.
9b0453382SBill Fenner  *
10b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
11b0453382SBill Fenner  * modification, are permitted provided that the following conditions
12b0453382SBill Fenner  * are met:
13b0453382SBill Fenner  * 1. Redistributions of source code must retain the above copyright
14b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer.
15b0453382SBill Fenner  * 2. Redistributions in binary form must reproduce the above copyright
16b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer in the
17b0453382SBill Fenner  *    documentation and/or other materials provided with the distribution.
18b0453382SBill Fenner  * 3. All advertising materials mentioning features or use of this software
19b0453382SBill Fenner  *    must display the following acknowledgement:
20b0453382SBill Fenner  *        This product includes software developed by the NetBSD
21b0453382SBill Fenner  *        Foundation, Inc. and its contributors.
22b0453382SBill Fenner  * 4. Neither the name of The NetBSD Foundation nor the names of its
23b0453382SBill Fenner  *    contributors may be used to endorse or promote products derived
24b0453382SBill Fenner  *    from this software without specific prior written permission.
25b0453382SBill Fenner  *
26b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27b0453382SBill Fenner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28b0453382SBill Fenner  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29b0453382SBill Fenner  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30b0453382SBill Fenner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31b0453382SBill Fenner  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32b0453382SBill Fenner  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33b0453382SBill Fenner  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34b0453382SBill Fenner  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35b0453382SBill Fenner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36b0453382SBill Fenner  * POSSIBILITY OF SUCH DAMAGE.
37b0453382SBill Fenner  */
38b0453382SBill Fenner 
39*3340d773SGleb Smirnoff /* \summary: ASCII packet dump printer */
40*3340d773SGleb Smirnoff 
41b0453382SBill Fenner #ifdef HAVE_CONFIG_H
42b0453382SBill Fenner #include "config.h"
43b0453382SBill Fenner #endif
44b0453382SBill Fenner 
45*3340d773SGleb Smirnoff #include <netdissect-stdinc.h>
46b0453382SBill Fenner #include <stdio.h>
47b0453382SBill Fenner 
48*3340d773SGleb Smirnoff #include "netdissect.h"
49b0453382SBill Fenner 
505b0fe478SBruce M Simpson #define ASCII_LINELENGTH 300
51b0453382SBill Fenner #define HEXDUMP_BYTES_PER_LINE 16
52b0453382SBill Fenner #define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
53b0453382SBill Fenner #define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
54b0453382SBill Fenner #define HEXDUMP_HEXSTUFF_PER_LINE \
55b0453382SBill Fenner 		(HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
56b0453382SBill Fenner 
57b0453382SBill Fenner void
583c602fabSXin LI ascii_print(netdissect_options *ndo,
593c602fabSXin LI             const u_char *cp, u_int length)
602ebc47dbSSam Leffler {
618bdc5a62SPatrick Kelsey 	u_int caplength;
623c602fabSXin LI 	register u_char s;
632ebc47dbSSam Leffler 
648bdc5a62SPatrick Kelsey 	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
658bdc5a62SPatrick Kelsey 	if (length > caplength)
668bdc5a62SPatrick Kelsey 		length = caplength;
673c602fabSXin LI 	ND_PRINT((ndo, "\n"));
682ebc47dbSSam Leffler 	while (length > 0) {
692ebc47dbSSam Leffler 		s = *cp++;
702ebc47dbSSam Leffler 		length--;
713c602fabSXin LI 		if (s == '\r') {
723c602fabSXin LI 			/*
733c602fabSXin LI 			 * Don't print CRs at the end of the line; they
743c602fabSXin LI 			 * don't belong at the ends of lines on UN*X,
753c602fabSXin LI 			 * and the standard I/O library will give us one
763c602fabSXin LI 			 * on Windows so we don't need to print one
773c602fabSXin LI 			 * ourselves.
783c602fabSXin LI 			 *
793c602fabSXin LI 			 * In the middle of a line, just print a '.'.
803c602fabSXin LI 			 */
813c602fabSXin LI 			if (length > 1 && *cp != '\n')
823c602fabSXin LI 				ND_PRINT((ndo, "."));
833c602fabSXin LI 		} else {
843c602fabSXin LI 			if (!ND_ISGRAPH(s) &&
853c602fabSXin LI 			    (s != '\t' && s != ' ' && s != '\n'))
863c602fabSXin LI 				ND_PRINT((ndo, "."));
872ebc47dbSSam Leffler 			else
883c602fabSXin LI 				ND_PRINT((ndo, "%c", s));
893c602fabSXin LI 		}
902ebc47dbSSam Leffler 	}
912ebc47dbSSam Leffler }
922ebc47dbSSam Leffler 
932ebc47dbSSam Leffler void
943c602fabSXin LI hex_and_ascii_print_with_offset(netdissect_options *ndo, register const char *ident,
952ebc47dbSSam Leffler     register const u_char *cp, register u_int length, register u_int oset)
96b0453382SBill Fenner {
978bdc5a62SPatrick Kelsey 	u_int caplength;
98b0453382SBill Fenner 	register u_int i;
99b0453382SBill Fenner 	register int s1, s2;
100b0453382SBill Fenner 	register int nshorts;
101b0453382SBill Fenner 	char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
1025b0fe478SBruce M Simpson 	char asciistuff[ASCII_LINELENGTH+1], *asp;
103b0453382SBill Fenner 
1048bdc5a62SPatrick Kelsey 	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
1058bdc5a62SPatrick Kelsey 	if (length > caplength)
1068bdc5a62SPatrick Kelsey 		length = caplength;
107b0453382SBill Fenner 	nshorts = length / sizeof(u_short);
108b0453382SBill Fenner 	i = 0;
109b0453382SBill Fenner 	hsp = hexstuff; asp = asciistuff;
110b0453382SBill Fenner 	while (--nshorts >= 0) {
111b0453382SBill Fenner 		s1 = *cp++;
112b0453382SBill Fenner 		s2 = *cp++;
113685295f4SBill Fenner 		(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
114685295f4SBill Fenner 		    " %02x%02x", s1, s2);
115b0453382SBill Fenner 		hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
1163c602fabSXin LI 		*(asp++) = (ND_ISGRAPH(s1) ? s1 : '.');
1173c602fabSXin LI 		*(asp++) = (ND_ISGRAPH(s2) ? s2 : '.');
1185b0fe478SBruce M Simpson 		i++;
1192ebc47dbSSam Leffler 		if (i >= HEXDUMP_SHORTS_PER_LINE) {
120b0453382SBill Fenner 			*hsp = *asp = '\0';
1213c602fabSXin LI 			ND_PRINT((ndo, "%s0x%04x: %-*s  %s",
1225b0fe478SBruce M Simpson 			    ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
1233c602fabSXin LI 			    hexstuff, asciistuff));
124b0453382SBill Fenner 			i = 0; hsp = hexstuff; asp = asciistuff;
125b0453382SBill Fenner 			oset += HEXDUMP_BYTES_PER_LINE;
126b0453382SBill Fenner 		}
127b0453382SBill Fenner 	}
128b0453382SBill Fenner 	if (length & 1) {
129b0453382SBill Fenner 		s1 = *cp++;
130685295f4SBill Fenner 		(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
131685295f4SBill Fenner 		    " %02x", s1);
132b0453382SBill Fenner 		hsp += 3;
1333c602fabSXin LI 		*(asp++) = (ND_ISGRAPH(s1) ? s1 : '.');
134b0453382SBill Fenner 		++i;
135b0453382SBill Fenner 	}
136b0453382SBill Fenner 	if (i > 0) {
137b0453382SBill Fenner 		*hsp = *asp = '\0';
1383c602fabSXin LI 		ND_PRINT((ndo, "%s0x%04x: %-*s  %s",
1395b0fe478SBruce M Simpson 		     ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
1403c602fabSXin LI 		     hexstuff, asciistuff));
141b0453382SBill Fenner 	}
142b0453382SBill Fenner }
143b0453382SBill Fenner 
144b0453382SBill Fenner void
1453c602fabSXin LI hex_and_ascii_print(netdissect_options *ndo, register const char *ident,
1463c602fabSXin LI     register const u_char *cp, register u_int length)
147b0453382SBill Fenner {
1483c602fabSXin LI 	hex_and_ascii_print_with_offset(ndo, ident, cp, length, 0);
149b0453382SBill Fenner }
150b0453382SBill Fenner 
151b0453382SBill Fenner /*
152b0453382SBill Fenner  * telnet_print() wants this.  It is essentially default_print_unaligned()
153b0453382SBill Fenner  */
154b0453382SBill Fenner void
1553c602fabSXin LI hex_print_with_offset(netdissect_options *ndo,
1563c602fabSXin LI                       const char *ident, const u_char *cp, u_int length,
1573c602fabSXin LI 		      u_int oset)
158b0453382SBill Fenner {
1598bdc5a62SPatrick Kelsey 	u_int caplength;
160b0453382SBill Fenner 	register u_int i, s;
161b0453382SBill Fenner 	register int nshorts;
162b0453382SBill Fenner 
1638bdc5a62SPatrick Kelsey 	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
1648bdc5a62SPatrick Kelsey 	if (length > caplength)
1658bdc5a62SPatrick Kelsey 		length = caplength;
166b0453382SBill Fenner 	nshorts = (u_int) length / sizeof(u_short);
167b0453382SBill Fenner 	i = 0;
168b0453382SBill Fenner 	while (--nshorts >= 0) {
169b0453382SBill Fenner 		if ((i++ % 8) == 0) {
1703c602fabSXin LI 			ND_PRINT((ndo,"%s0x%04x: ", ident, oset));
171b0453382SBill Fenner 			oset += HEXDUMP_BYTES_PER_LINE;
172b0453382SBill Fenner 		}
173b0453382SBill Fenner 		s = *cp++;
1743c602fabSXin LI 		ND_PRINT((ndo," %02x%02x", s, *cp++));
175b0453382SBill Fenner 	}
176b0453382SBill Fenner 	if (length & 1) {
177b0453382SBill Fenner 		if ((i % 8) == 0)
1783c602fabSXin LI 			ND_PRINT((ndo,"%s0x%04x: ", ident, oset));
1793c602fabSXin LI 		ND_PRINT((ndo," %02x", *cp));
180b0453382SBill Fenner 	}
181b0453382SBill Fenner }
182b0453382SBill Fenner 
183b0453382SBill Fenner /*
184b0453382SBill Fenner  * just for completeness
185b0453382SBill Fenner  */
186b0453382SBill Fenner void
1873c602fabSXin LI hex_print(netdissect_options *ndo,const char *ident, const u_char *cp, u_int length)
188b0453382SBill Fenner {
1893c602fabSXin LI   hex_print_with_offset(ndo, ident, cp, length, 0);
190b0453382SBill Fenner }
191b0453382SBill Fenner 
192b0453382SBill Fenner #ifdef MAIN
193b0453382SBill Fenner int
194b0453382SBill Fenner main(int argc, char *argv[])
195b0453382SBill Fenner {
1962ebc47dbSSam Leffler 	hex_print("\n\t", "Hello, World!\n", 14);
1972ebc47dbSSam Leffler 	printf("\n");
1982ebc47dbSSam Leffler 	hex_and_ascii_print("\n\t", "Hello, World!\n", 14);
199b0453382SBill Fenner 	printf("\n");
200b0453382SBill Fenner 	ascii_print("Hello, World!\n", 14);
201b0453382SBill Fenner 	printf("\n");
202b0453382SBill Fenner #define TMSG "Now is the winter of our discontent...\n"
2032ebc47dbSSam Leffler 	hex_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
2042ebc47dbSSam Leffler 	printf("\n");
2052ebc47dbSSam Leffler 	hex_and_ascii_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
206b0453382SBill Fenner 	printf("\n");
207b0453382SBill Fenner 	exit(0);
208b0453382SBill Fenner }
209b0453382SBill Fenner #endif /* MAIN */
210