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