Home | History | Annotate | Download | only in tcpdump
      1 /*	$NetBSD: print-ascii.c,v 1.1 1999/09/30 14:49:12 sjg Exp $ 	*/
      2 
      3 /*-
      4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Alan Barrett and Simon J. Gerraty.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /* \summary: ASCII packet dump printer */
     40 
     41 #ifdef HAVE_CONFIG_H
     42 #include "config.h"
     43 #endif
     44 
     45 #include <netdissect-stdinc.h>
     46 #include <stdio.h>
     47 
     48 #include "netdissect.h"
     49 
     50 #define ASCII_LINELENGTH 300
     51 #define HEXDUMP_BYTES_PER_LINE 16
     52 #define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
     53 #define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
     54 #define HEXDUMP_HEXSTUFF_PER_LINE \
     55 		(HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
     56 
     57 void
     58 ascii_print(netdissect_options *ndo,
     59             const u_char *cp, u_int length)
     60 {
     61 	u_int caplength;
     62 	register u_char s;
     63 
     64 	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
     65 	if (length > caplength)
     66 		length = caplength;
     67 	ND_PRINT((ndo, "\n"));
     68 	while (length > 0) {
     69 		s = *cp++;
     70 		length--;
     71 		if (s == '\r') {
     72 			/*
     73 			 * Don't print CRs at the end of the line; they
     74 			 * don't belong at the ends of lines on UN*X,
     75 			 * and the standard I/O library will give us one
     76 			 * on Windows so we don't need to print one
     77 			 * ourselves.
     78 			 *
     79 			 * In the middle of a line, just print a '.'.
     80 			 */
     81 			if (length > 1 && *cp != '\n')
     82 				ND_PRINT((ndo, "."));
     83 		} else {
     84 			if (!ND_ISGRAPH(s) &&
     85 			    (s != '\t' && s != ' ' && s != '\n'))
     86 				ND_PRINT((ndo, "."));
     87 			else
     88 				ND_PRINT((ndo, "%c", s));
     89 		}
     90 	}
     91 }
     92 
     93 void
     94 hex_and_ascii_print_with_offset(netdissect_options *ndo, register const char *ident,
     95     register const u_char *cp, register u_int length, register u_int oset)
     96 {
     97 	u_int caplength;
     98 	register u_int i;
     99 	register int s1, s2;
    100 	register int nshorts;
    101 	char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
    102 	char asciistuff[ASCII_LINELENGTH+1], *asp;
    103 
    104 	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
    105 	if (length > caplength)
    106 		length = caplength;
    107 	nshorts = length / sizeof(u_short);
    108 	i = 0;
    109 	hsp = hexstuff; asp = asciistuff;
    110 	while (--nshorts >= 0) {
    111 		s1 = *cp++;
    112 		s2 = *cp++;
    113 		(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
    114 		    " %02x%02x", s1, s2);
    115 		hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
    116 		*(asp++) = (ND_ISGRAPH(s1) ? s1 : '.');
    117 		*(asp++) = (ND_ISGRAPH(s2) ? s2 : '.');
    118 		i++;
    119 		if (i >= HEXDUMP_SHORTS_PER_LINE) {
    120 			*hsp = *asp = '\0';
    121 			ND_PRINT((ndo, "%s0x%04x: %-*s  %s",
    122 			    ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
    123 			    hexstuff, asciistuff));
    124 			i = 0; hsp = hexstuff; asp = asciistuff;
    125 			oset += HEXDUMP_BYTES_PER_LINE;
    126 		}
    127 	}
    128 	if (length & 1) {
    129 		s1 = *cp++;
    130 		(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
    131 		    " %02x", s1);
    132 		hsp += 3;
    133 		*(asp++) = (ND_ISGRAPH(s1) ? s1 : '.');
    134 		++i;
    135 	}
    136 	if (i > 0) {
    137 		*hsp = *asp = '\0';
    138 		ND_PRINT((ndo, "%s0x%04x: %-*s  %s",
    139 		     ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
    140 		     hexstuff, asciistuff));
    141 	}
    142 }
    143 
    144 void
    145 hex_and_ascii_print(netdissect_options *ndo, register const char *ident,
    146     register const u_char *cp, register u_int length)
    147 {
    148 	hex_and_ascii_print_with_offset(ndo, ident, cp, length, 0);
    149 }
    150 
    151 /*
    152  * telnet_print() wants this.  It is essentially default_print_unaligned()
    153  */
    154 void
    155 hex_print_with_offset(netdissect_options *ndo,
    156                       const char *ident, const u_char *cp, u_int length,
    157 		      u_int oset)
    158 {
    159 	u_int caplength;
    160 	register u_int i, s;
    161 	register int nshorts;
    162 
    163 	caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0;
    164 	if (length > caplength)
    165 		length = caplength;
    166 	nshorts = (u_int) length / sizeof(u_short);
    167 	i = 0;
    168 	while (--nshorts >= 0) {
    169 		if ((i++ % 8) == 0) {
    170 			ND_PRINT((ndo,"%s0x%04x: ", ident, oset));
    171 			oset += HEXDUMP_BYTES_PER_LINE;
    172 		}
    173 		s = *cp++;
    174 		ND_PRINT((ndo," %02x%02x", s, *cp++));
    175 	}
    176 	if (length & 1) {
    177 		if ((i % 8) == 0)
    178 			ND_PRINT((ndo,"%s0x%04x: ", ident, oset));
    179 		ND_PRINT((ndo," %02x", *cp));
    180 	}
    181 }
    182 
    183 /*
    184  * just for completeness
    185  */
    186 void
    187 hex_print(netdissect_options *ndo,const char *ident, const u_char *cp, u_int length)
    188 {
    189   hex_print_with_offset(ndo, ident, cp, length, 0);
    190 }
    191 
    192 #ifdef MAIN
    193 int
    194 main(int argc, char *argv[])
    195 {
    196 	hex_print("\n\t", "Hello, World!\n", 14);
    197 	printf("\n");
    198 	hex_and_ascii_print("\n\t", "Hello, World!\n", 14);
    199 	printf("\n");
    200 	ascii_print("Hello, World!\n", 14);
    201 	printf("\n");
    202 #define TMSG "Now is the winter of our discontent...\n"
    203 	hex_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
    204 	printf("\n");
    205 	hex_and_ascii_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
    206 	printf("\n");
    207 	exit(0);
    208 }
    209 #endif /* MAIN */
    210