156893Sfenner/*	$NetBSD: print-ascii.c,v 1.1 1999/09/30 14:49:12 sjg Exp $ 	*/
256893Sfenner
356893Sfenner/*-
456893Sfenner * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
556893Sfenner * All rights reserved.
656893Sfenner *
756893Sfenner * This code is derived from software contributed to The NetBSD Foundation
856893Sfenner * by Alan Barrett and Simon J. Gerraty.
956893Sfenner *
1056893Sfenner * Redistribution and use in source and binary forms, with or without
1156893Sfenner * modification, are permitted provided that the following conditions
1256893Sfenner * are met:
1356893Sfenner * 1. Redistributions of source code must retain the above copyright
1456893Sfenner *    notice, this list of conditions and the following disclaimer.
1556893Sfenner * 2. Redistributions in binary form must reproduce the above copyright
1656893Sfenner *    notice, this list of conditions and the following disclaimer in the
1756893Sfenner *    documentation and/or other materials provided with the distribution.
1856893Sfenner * 3. All advertising materials mentioning features or use of this software
1956893Sfenner *    must display the following acknowledgement:
2056893Sfenner *        This product includes software developed by the NetBSD
2156893Sfenner *        Foundation, Inc. and its contributors.
2256893Sfenner * 4. Neither the name of The NetBSD Foundation nor the names of its
2356893Sfenner *    contributors may be used to endorse or promote products derived
2456893Sfenner *    from this software without specific prior written permission.
2556893Sfenner *
2656893Sfenner * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2756893Sfenner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2856893Sfenner * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2956893Sfenner * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3056893Sfenner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3156893Sfenner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3256893Sfenner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3356893Sfenner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3456893Sfenner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3556893Sfenner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3656893Sfenner * POSSIBILITY OF SUCH DAMAGE.
3756893Sfenner */
3856893Sfenner
39276788Sdelphij#define NETDISSECT_REWORKED
4056893Sfenner#ifdef HAVE_CONFIG_H
4156893Sfenner#include "config.h"
4256893Sfenner#endif
4356893Sfenner
44127668Sbms#include <tcpdump-stdinc.h>
4556893Sfenner#include <stdio.h>
4656893Sfenner
4756893Sfenner#include "interface.h"
4856893Sfenner
49127668Sbms#define ASCII_LINELENGTH 300
5056893Sfenner#define HEXDUMP_BYTES_PER_LINE 16
5156893Sfenner#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
5256893Sfenner#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
5356893Sfenner#define HEXDUMP_HEXSTUFF_PER_LINE \
5456893Sfenner		(HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
55127668Sbms
5656893Sfennervoid
57276788Sdelphijascii_print(netdissect_options *ndo,
58276788Sdelphij            const u_char *cp, u_int length)
5956893Sfenner{
60285275Spkelsey	u_int caplength;
61276788Sdelphij	register u_char s;
62162017Ssam
63285275Spkelsey	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
64285275Spkelsey	if (length > caplength)
65285275Spkelsey		length = caplength;
66276788Sdelphij	ND_PRINT((ndo, "\n"));
67162017Ssam	while (length > 0) {
68162017Ssam		s = *cp++;
69162017Ssam		length--;
70276788Sdelphij		if (s == '\r') {
71276788Sdelphij			/*
72276788Sdelphij			 * Don't print CRs at the end of the line; they
73276788Sdelphij			 * don't belong at the ends of lines on UN*X,
74276788Sdelphij			 * and the standard I/O library will give us one
75276788Sdelphij			 * on Windows so we don't need to print one
76276788Sdelphij			 * ourselves.
77276788Sdelphij			 *
78276788Sdelphij			 * In the middle of a line, just print a '.'.
79276788Sdelphij			 */
80276788Sdelphij			if (length > 1 && *cp != '\n')
81276788Sdelphij				ND_PRINT((ndo, "."));
82276788Sdelphij		} else {
83276788Sdelphij			if (!ND_ISGRAPH(s) &&
84276788Sdelphij			    (s != '\t' && s != ' ' && s != '\n'))
85276788Sdelphij				ND_PRINT((ndo, "."));
86276788Sdelphij			else
87276788Sdelphij				ND_PRINT((ndo, "%c", s));
88276788Sdelphij		}
89162017Ssam	}
90162017Ssam}
91162017Ssam
92162017Ssamvoid
93276788Sdelphijhex_and_ascii_print_with_offset(netdissect_options *ndo, register const char *ident,
94162017Ssam    register const u_char *cp, register u_int length, register u_int oset)
95162017Ssam{
96285275Spkelsey	u_int caplength;
9756893Sfenner	register u_int i;
9856893Sfenner	register int s1, s2;
9956893Sfenner	register int nshorts;
10056893Sfenner	char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
101127668Sbms	char asciistuff[ASCII_LINELENGTH+1], *asp;
10256893Sfenner
103285275Spkelsey	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
104285275Spkelsey	if (length > caplength)
105285275Spkelsey		length = caplength;
10656893Sfenner	nshorts = length / sizeof(u_short);
10756893Sfenner	i = 0;
10856893Sfenner	hsp = hexstuff; asp = asciistuff;
10956893Sfenner	while (--nshorts >= 0) {
11056893Sfenner		s1 = *cp++;
11156893Sfenner		s2 = *cp++;
112162017Ssam		(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
113162017Ssam		    " %02x%02x", s1, s2);
114162017Ssam		hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
115276788Sdelphij		*(asp++) = (ND_ISGRAPH(s1) ? s1 : '.');
116276788Sdelphij		*(asp++) = (ND_ISGRAPH(s2) ? s2 : '.');
117162017Ssam		i++;
118162017Ssam		if (i >= HEXDUMP_SHORTS_PER_LINE) {
119127668Sbms			*hsp = *asp = '\0';
120276788Sdelphij			ND_PRINT((ndo, "%s0x%04x: %-*s  %s",
121162017Ssam			    ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
122276788Sdelphij			    hexstuff, asciistuff));
123127668Sbms			i = 0; hsp = hexstuff; asp = asciistuff;
124127668Sbms			oset += HEXDUMP_BYTES_PER_LINE;
125127668Sbms		}
12656893Sfenner	}
12756893Sfenner	if (length & 1) {
12856893Sfenner		s1 = *cp++;
129162017Ssam		(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
130162017Ssam		    " %02x", s1);
131162017Ssam		hsp += 3;
132276788Sdelphij		*(asp++) = (ND_ISGRAPH(s1) ? s1 : '.');
13356893Sfenner		++i;
13456893Sfenner	}
13556893Sfenner	if (i > 0) {
13656893Sfenner		*hsp = *asp = '\0';
137276788Sdelphij		ND_PRINT((ndo, "%s0x%04x: %-*s  %s",
138162017Ssam		     ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
139276788Sdelphij		     hexstuff, asciistuff));
14056893Sfenner	}
14156893Sfenner}
14256893Sfenner
14356893Sfennervoid
144276788Sdelphijhex_and_ascii_print(netdissect_options *ndo, register const char *ident,
145276788Sdelphij    register const u_char *cp, register u_int length)
14656893Sfenner{
147276788Sdelphij	hex_and_ascii_print_with_offset(ndo, ident, cp, length, 0);
14856893Sfenner}
149127668Sbms
15056893Sfenner/*
15156893Sfenner * telnet_print() wants this.  It is essentially default_print_unaligned()
15256893Sfenner */
15356893Sfennervoid
154276788Sdelphijhex_print_with_offset(netdissect_options *ndo,
155276788Sdelphij                      const char *ident, const u_char *cp, u_int length,
156276788Sdelphij		      u_int oset)
15756893Sfenner{
158285275Spkelsey	u_int caplength;
15956893Sfenner	register u_int i, s;
16056893Sfenner	register int nshorts;
16156893Sfenner
162285275Spkelsey	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
163285275Spkelsey	if (length > caplength)
164285275Spkelsey		length = caplength;
16556893Sfenner	nshorts = (u_int) length / sizeof(u_short);
16656893Sfenner	i = 0;
16756893Sfenner	while (--nshorts >= 0) {
16856893Sfenner		if ((i++ % 8) == 0) {
169276788Sdelphij			ND_PRINT((ndo,"%s0x%04x: ", ident, oset));
17056893Sfenner			oset += HEXDUMP_BYTES_PER_LINE;
17156893Sfenner		}
17256893Sfenner		s = *cp++;
173276788Sdelphij		ND_PRINT((ndo," %02x%02x", s, *cp++));
17456893Sfenner	}
17556893Sfenner	if (length & 1) {
17656893Sfenner		if ((i % 8) == 0)
177276788Sdelphij			ND_PRINT((ndo,"%s0x%04x: ", ident, oset));
178276788Sdelphij		ND_PRINT((ndo," %02x", *cp));
17956893Sfenner	}
18056893Sfenner}
18156893Sfenner
18256893Sfenner/*
18356893Sfenner * just for completeness
18456893Sfenner */
18556893Sfennervoid
186276788Sdelphijhex_print(netdissect_options *ndo,const char *ident, const u_char *cp, u_int length)
18756893Sfenner{
188276788Sdelphij  hex_print_with_offset(ndo, ident, cp, length, 0);
18956893Sfenner}
19056893Sfenner
19156893Sfenner#ifdef MAIN
19256893Sfennerint
19356893Sfennermain(int argc, char *argv[])
19456893Sfenner{
195162017Ssam	hex_print("\n\t", "Hello, World!\n", 14);
19656893Sfenner	printf("\n");
197162017Ssam	hex_and_ascii_print("\n\t", "Hello, World!\n", 14);
198162017Ssam	printf("\n");
19956893Sfenner	ascii_print("Hello, World!\n", 14);
20056893Sfenner	printf("\n");
20156893Sfenner#define TMSG "Now is the winter of our discontent...\n"
202162017Ssam	hex_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
20356893Sfenner	printf("\n");
204162017Ssam	hex_and_ascii_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
205162017Ssam	printf("\n");
20656893Sfenner	exit(0);
20756893Sfenner}
20856893Sfenner#endif /* MAIN */
209