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 47 #include <stdio.h> 48 49 #include "netdissect-ctype.h" 50 51 #include "netdissect.h" 52 #include "extract.h" 53 54 #define ASCII_LINELENGTH 300 55 #define HEXDUMP_BYTES_PER_LINE 16 56 #define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2) 57 #define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */ 58 #define HEXDUMP_HEXSTUFF_PER_LINE \ 59 (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE) 60 61 void 62 ascii_print(netdissect_options *ndo, 63 const u_char *cp, u_int length) 64 { 65 u_int caplength; 66 u_char s; 67 int truncated = FALSE; 68 69 ndo->ndo_protocol = "ascii"; 70 caplength = (ndo->ndo_snapend > cp) ? ND_BYTES_AVAILABLE_AFTER(cp) : 0; 71 if (length > caplength) { 72 length = caplength; 73 truncated = TRUE; 74 } 75 ND_PRINT("\n"); 76 while (length > 0) { 77 s = GET_U_1(cp); 78 cp++; 79 length--; 80 if (s == '\r') { 81 /* 82 * Don't print CRs at the end of the line; they 83 * don't belong at the ends of lines on UN*X, 84 * and the standard I/O library will give us one 85 * on Windows so we don't need to print one 86 * ourselves. 87 * 88 * In the middle of a line, just print a '.'. 89 */ 90 if (length > 1 && GET_U_1(cp) != '\n') 91 ND_PRINT("."); 92 } else { 93 if (!ND_ASCII_ISGRAPH(s) && 94 (s != '\t' && s != ' ' && s != '\n')) 95 ND_PRINT("."); 96 else 97 ND_PRINT("%c", s); 98 } 99 } 100 if (truncated) 101 nd_trunc_longjmp(ndo); 102 } 103 104 static void 105 hex_and_ascii_print_with_offset(netdissect_options *ndo, const char *ident, 106 const u_char *cp, u_int length, u_int oset) 107 { 108 u_int caplength; 109 u_int i; 110 u_int s1, s2; 111 u_int nshorts; 112 int truncated = FALSE; 113 char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp; 114 char asciistuff[ASCII_LINELENGTH+1], *asp; 115 116 caplength = (ndo->ndo_snapend > cp) ? ND_BYTES_AVAILABLE_AFTER(cp) : 0; 117 if (length > caplength) { 118 length = caplength; 119 truncated = TRUE; 120 } 121 nshorts = length / sizeof(u_short); 122 i = 0; 123 hsp = hexstuff; asp = asciistuff; 124 while (nshorts != 0) { 125 s1 = GET_U_1(cp); 126 cp++; 127 s2 = GET_U_1(cp); 128 cp++; 129 (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff), 130 " %02x%02x", s1, s2); 131 hsp += HEXDUMP_HEXSTUFF_PER_SHORT; 132 *(asp++) = (char)(ND_ASCII_ISGRAPH(s1) ? s1 : '.'); 133 *(asp++) = (char)(ND_ASCII_ISGRAPH(s2) ? s2 : '.'); 134 i++; 135 if (i >= HEXDUMP_SHORTS_PER_LINE) { 136 *hsp = *asp = '\0'; 137 ND_PRINT("%s0x%04x: %-*s %s", 138 ident, oset, HEXDUMP_HEXSTUFF_PER_LINE, 139 hexstuff, asciistuff); 140 i = 0; hsp = hexstuff; asp = asciistuff; 141 oset += HEXDUMP_BYTES_PER_LINE; 142 } 143 nshorts--; 144 } 145 if (length & 1) { 146 s1 = GET_U_1(cp); 147 cp++; 148 (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff), 149 " %02x", s1); 150 hsp += 3; 151 *(asp++) = (char)(ND_ASCII_ISGRAPH(s1) ? s1 : '.'); 152 ++i; 153 } 154 if (i > 0) { 155 *hsp = *asp = '\0'; 156 ND_PRINT("%s0x%04x: %-*s %s", 157 ident, oset, HEXDUMP_HEXSTUFF_PER_LINE, 158 hexstuff, asciistuff); 159 } 160 if (truncated) 161 nd_trunc_longjmp(ndo); 162 } 163 164 void 165 hex_and_ascii_print(netdissect_options *ndo, const char *ident, 166 const u_char *cp, u_int length) 167 { 168 hex_and_ascii_print_with_offset(ndo, ident, cp, length, 0); 169 } 170 171 /* 172 * telnet_print() wants this. It is essentially default_print_unaligned() 173 */ 174 void 175 hex_print_with_offset(netdissect_options *ndo, 176 const char *ident, const u_char *cp, u_int length, 177 u_int oset) 178 { 179 u_int caplength; 180 u_int i, s; 181 u_int nshorts; 182 int truncated = FALSE; 183 184 caplength = (ndo->ndo_snapend > cp) ? ND_BYTES_AVAILABLE_AFTER(cp) : 0; 185 if (length > caplength) { 186 length = caplength; 187 truncated = TRUE; 188 } 189 nshorts = length / sizeof(u_short); 190 i = 0; 191 while (nshorts != 0) { 192 if ((i++ % 8) == 0) { 193 ND_PRINT("%s0x%04x: ", ident, oset); 194 oset += HEXDUMP_BYTES_PER_LINE; 195 } 196 s = GET_U_1(cp); 197 cp++; 198 ND_PRINT(" %02x%02x", s, GET_U_1(cp)); 199 cp++; 200 nshorts--; 201 } 202 if (length & 1) { 203 if ((i % 8) == 0) 204 ND_PRINT("%s0x%04x: ", ident, oset); 205 ND_PRINT(" %02x", GET_U_1(cp)); 206 } 207 if (truncated) 208 nd_trunc_longjmp(ndo); 209 } 210 211 void 212 hex_print(netdissect_options *ndo, 213 const char *ident, const u_char *cp, u_int length) 214 { 215 hex_print_with_offset(ndo, ident, cp, length, 0); 216 } 217 218 #ifdef MAIN 219 int 220 main(int argc, char *argv[]) 221 { 222 hex_print("\n\t", "Hello, World!\n", 14); 223 printf("\n"); 224 hex_and_ascii_print("\n\t", "Hello, World!\n", 14); 225 printf("\n"); 226 ascii_print("Hello, World!\n", 14); 227 printf("\n"); 228 #define TMSG "Now is the winter of our discontent...\n" 229 hex_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100); 230 printf("\n"); 231 hex_and_ascii_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100); 232 printf("\n"); 233 exit(0); 234 } 235 #endif /* MAIN */ 236