1 /****************************************************************************
2 ** File: display.c
3 **
4 ** Author: Mike Borella
5 **
6 ** Comments: Displaying functions
7 **
8 ** $Id: display.c,v 1.34 2007/06/25 10:12:37 farooq-i-azam Exp $
9 **
10 ** This program is free software; you can redistribute it and/or modify
11 ** it under the terms of the GNU General Public License as published by
12 ** the Free Software Foundation; either version 2 of the License, or
13 ** (at your option) any later version.
14 **
15 ** This program is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU Library General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with this program; if not, write to the Free Software
22 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 **
24 *****************************************************************************/
25
26 #include "display.h"
27
28 #define LABEL_LENGTH 22
29 #define MULTILINE_LENGTH 23
30 #define MULTILINE_STRING_LENGTH 48
31 #define BUF_SIZE 128
32 #define HOLDER_LEN 64
33
34 int packet_displayed;
35 int start_of_packet;
36
37 extern struct arg_t * my_args;
38
39 /*----------------------------------------------------------------------------
40 **
41 ** display_header_line()
42 **
43 ** Writes out a line of separators (separators defined in headerline_t)
44 **
45 **----------------------------------------------------------------------------
46 */
47
display_header_line(headerline_t hl)48 inline void display_header_line(headerline_t hl)
49 {
50 /* Check the layer */
51 if (check_layer())
52 return;
53
54 switch(hl)
55 {
56 case HEADERLINE_DASHES:
57 printf("--------------------------------------------------------------------------\n");
58 break;
59 case HEADERLINE_STARS:
60 printf("**************************************************************************\n");
61 break;
62 case HEADERLINE_EQUALS:
63 printf("==========================================================================\n");
64 break;
65 case HEADERLINE_DOTS:
66 printf("..........................................................................\n");
67 break;
68 default:
69 error_fatal("unknown header line type");
70 }
71 }
72
73 /*----------------------------------------------------------------------------
74 **
75 ** display_whitespace_pad()
76 **
77 ** Pad the output with a pre-determined number of spaces from the label to
78 ** the output. The input parameter is the length of the label.
79 **
80 **----------------------------------------------------------------------------
81 */
82
display_whitespace_pad(int length)83 inline void display_whitespace_pad(int length)
84 {
85 int i;
86
87 /* Check the layer */
88 if (check_layer())
89 return;
90
91 for (i=0; i < LABEL_LENGTH+1-length; i++)
92 putchar(' ');
93 }
94
95 /*----------------------------------------------------------------------------
96 **
97 ** display_header_banner_ts()
98 **
99 ** Writes out a generic header banner with timestamp for protocol headers.
100 **
101 ** ISSUE: Do we want to limit the length of the banner string so that it
102 ** doesn't run off the screen?
103 **
104 **----------------------------------------------------------------------------
105 */
106
display_header_banner_ts(char * banner,char * ts)107 inline void display_header_banner_ts(char *banner, char *ts)
108 {
109 /* Check the layer */
110 if (check_layer())
111 return;
112
113 if (start_of_packet)
114 {
115 display_header_line(HEADERLINE_STARS);
116 start_of_packet = 0;
117 }
118 else
119 display_header_line(HEADERLINE_DASHES);
120
121 printf(" %s", banner);
122 printf("\n");
123 if (ts != NULL)
124 {
125 display_whitespace_pad ( 0 );
126 printf ( " %s ", ts );
127 }
128
129 display_header_line(HEADERLINE_DASHES);
130 }
131
132 /*----------------------------------------------------------------------------
133 **
134 ** display_header_banner()
135 **
136 ** Writes out a generic header banner for protocol headers.
137 **
138 **----------------------------------------------------------------------------
139 */
140
display_header_banner(char * banner)141 inline void display_header_banner(char * banner)
142 {
143 display_header_banner_ts(banner, NULL);
144 }
145
146 /*----------------------------------------------------------------------------
147 **
148 ** display()
149 **
150 ** Display a protocol field or some other string according to our rules
151 **
152 ** Parameters:
153 ** label - always printed, must be null terminated string
154 ** content - the stuff to display, usually the value of the field
155 ** length - the number of bytes to display from the content parameter
156 ** format - the specific format to use when displaying
157 **
158 **----------------------------------------------------------------------------
159 */
160
display(char * label,u_int8_t * content,u_int32_t length,display_t format)161 inline void display(char * label, u_int8_t * content, u_int32_t length,
162 display_t format)
163 {
164 int label_len;
165 char label_truncated[LABEL_LENGTH+1];
166
167 /* Check the layer */
168 if (check_layer())
169 return;
170
171 /*
172 * Do sanity checks here
173 */
174
175 label_len = strlen(label);
176 if (label_len >= LABEL_LENGTH)
177 {
178 strncpy(label_truncated, label, LABEL_LENGTH);
179 label_truncated[LABEL_LENGTH] = '\0';
180 label_len = LABEL_LENGTH;
181 printf("%s:", label_truncated);
182 }
183 else
184 printf("%s:", label);
185
186 /*
187 * Do the actual displaying
188 */
189
190 display_whitespace_pad(label_len);
191 display_minimal(content, length, format);
192
193 /*
194 * Trailing printf()
195 */
196
197 printf("\n");
198
199 }
200
201 /*----------------------------------------------------------------------------
202 **
203 ** display_minimal()
204 **
205 ** Display a protocol field or some other string in minimal mode.
206 ** This means that there is no label, no padding, and no carriage return.
207 **
208 ** Parameters:
209 ** content - the stuff to display, usually the value of the field
210 ** length - the number of bytes to display from the content parameter
211 ** format - the specific format to use when displaying
212 **
213 **----------------------------------------------------------------------------
214 */
215
display_minimal(u_int8_t * content,u_int32_t length,display_t format)216 inline void display_minimal(u_int8_t * content, u_int32_t length,
217 display_t format)
218 {
219 int i,j;
220 int seen_a_one;
221 u_int8_t bit_holder;
222 struct in_addr * ip_holder;
223 u_int8_t * ptr;
224 u_int8_t * temp;
225 double sum;
226 u_int32_t multiplier;
227 int len;
228
229 /* Check the layer */
230 if (check_layer())
231 return;
232
233 /*
234 * We have displayed part of this packet, so we need a carriage return.
235 */
236
237 packet_displayed = 1;
238
239 /*
240 * Depending on the display format, we may do different things
241 */
242
243 switch(format)
244 {
245 case DISP_DEC:
246 temp = (u_int8_t *) my_malloc(length);
247 memcpy(temp, content, length);
248 #if !defined(WORDS_BIGENDIAN)
249 reverse_byte_order(temp, length);
250 #endif
251 sum = 0.0;
252 multiplier = 1;
253 for (i = length-1; i >= 0; i--)
254 {
255 ptr = temp+i;
256 sum += (double) (multiplier * *ptr);
257 multiplier = multiplier * 256;
258 }
259 printf("%.0f", sum);
260 my_free(temp);
261 break;
262
263 case DISP_DOTTEDDEC:
264 ip_holder = (struct in_addr *) content;
265 for (i=0; i<4; i++)
266 if (i==3)
267 printf("%d", content[i]);
268 else
269 printf("%d.", content[i]);
270 break;
271
272 case DISP_HEX:
273 printf("0x");
274 for (i=0; i < length; i++)
275 {
276 if (content[i] < 16)
277 printf("0%x", content[i]);
278 else
279 printf("%x", content[i]);
280 }
281 break;
282
283 case DISP_HEX_MULTILINE:
284 printf("0x");
285 for (i=0; i < length; i++)
286 {
287 if ((i > 0) && (i % MULTILINE_LENGTH == 0))
288 {
289 printf("\n");
290 display_whitespace_pad(-3);
291 }
292 if (content[i] < 16)
293 printf("0%x", content[i]);
294 else
295 printf("%x", content[i]);
296 }
297 break;
298
299 case DISP_HEXCOLONS:
300 for (i=0; i < length; i++)
301 {
302 if (content[i] < 16)
303 printf("0%x", content[i]);
304 else
305 printf("%x", content[i]);
306 if (i != length-1)
307 printf(":");
308 }
309 break;
310
311 case DISP_HEXCOLONS4:
312 for (i=0; i < length; i++)
313 {
314 if ( content [ i ] < 0x10 )
315 printf("0%x", content[i]);
316 else
317 printf("%x", content[i]);
318
319 if (i % 2 == 1 && i != length - 1)
320 printf(":");
321 }
322 break;
323
324 case DISP_BINNLZ:
325 seen_a_one = 0;
326 for (i=0; i < length; i++)
327 {
328 bit_holder = 128;
329 for (j=1; j<=8; j++)
330 {
331 if (content[i] & bit_holder)
332 {
333 seen_a_one = 1;
334 printf("1");
335 }
336 else
337 {
338 if (seen_a_one || (i == length -1 && j == 8))
339 printf("0");
340 }
341 bit_holder = bit_holder >> 1;
342 }
343 }
344 break;
345
346 case DISP_BIN:
347 for (i = 0; i < length; i++)
348 {
349 bit_holder = 0x80;
350 for (j = 1; j <= 8; j++)
351 {
352 if (content[i] & bit_holder)
353 printf ( "1" );
354 else
355 printf ( "0" );
356
357 bit_holder = bit_holder >> 1;
358 }
359 }
360 break;
361
362 case DISP_STRING:
363 /*
364 * Rather than just ass-u-ming that we've been handed a properly
365 * null terminated string, we created one of our own.
366 *
367 * Make sure that ONLY printable characters are sent in this call,
368 * Otherwise, very strnage bugs will occur! For example, send this
369 * code a \n and just try to figure out why your output is screwy...
370 *
371 */
372
373 ptr = (u_int8_t *) my_malloc(length+1);
374 memcpy(ptr, content, length);
375 ptr[length] = '\0';
376
377 /* Clean out extra control characters */
378 len = strlen(ptr);
379 while((ptr[len-1] == '\n' || ptr[len-1] == '\r') && len >= 1)
380 {
381 ptr[len-1] = '\0';
382 len--;
383 }
384
385 /*
386 * Let's make sure that the string contains only printable
387 * characters
388 */
389
390 if (!isprint_str(ptr, len))
391 {
392 my_free(ptr);
393 break;
394 }
395
396 /* print it then free it */
397 printf("%s", ptr);
398 my_free(ptr);
399 break;
400
401 case DISP_STRING_MULTILINE:
402 /* I'm sure that this could be made much more efficient... */
403 for (i=0; i < length; i++)
404 {
405 if ((i > 0) && (i % MULTILINE_STRING_LENGTH == 0))
406 {
407 printf("\n");
408 display_whitespace_pad(-3);
409 }
410 printf("%c", content[i]);
411 }
412 break;
413
414 default: /* oops, this shouldn't happen... */
415 break;
416 }
417 }
418
419 /*----------------------------------------------------------------------------
420 **
421 ** display_minimal_string()
422 **
423 ** Same as display_minimal() but we assume that the content argument is
424 ** a string.
425 **
426 **----------------------------------------------------------------------------
427 */
428
display_minimal_string(u_int8_t * content)429 inline void display_minimal_string(u_int8_t * content)
430 {
431 display_minimal(content, strlen(content), DISP_STRING);
432 }
433
434 /*----------------------------------------------------------------------------
435 **
436 ** display_string()
437 **
438 ** Same as display() but we assume that the content argument is
439 ** a string. We also assume multiline support is required.
440 **
441 **----------------------------------------------------------------------------
442 */
443
display_string(u_int8_t * label,u_int8_t * content)444 inline void display_string(u_int8_t * label, u_int8_t * content)
445 {
446 display(label, content, strlen(content), DISP_STRING_MULTILINE);
447 }
448
449 /*----------------------------------------------------------------------------
450 **
451 ** display_strmap()
452 **
453 ** Display an item from a strmap_t array, with proper expansion of its
454 ** textual representation.
455 **
456 **----------------------------------------------------------------------------
457 */
458
display_strmap(char * label,int content,strmap_t map[])459 inline void display_strmap(char * label, int content, strmap_t map[])
460 {
461 char holder[HOLDER_LEN];
462
463 snprintf(holder, HOLDER_LEN, "%d (%s)", content, map2str(map, content));
464 holder[HOLDER_LEN-1] = '\0';
465 display_string(label, holder);
466 }
467
468 /*----------------------------------------------------------------------------
469 **
470 ** display_strmap_hex()
471 **
472 ** Display an item from a strmap_t array, with proper expansion of its
473 ** textual representation. The number appears in hex format rather than
474 ** decimal.
475 **
476 **----------------------------------------------------------------------------
477 */
478
display_strmap_hex(char * label,int content,strmap_t map[])479 inline void display_strmap_hex(char * label, int content, strmap_t map[])
480 {
481 char holder[HOLDER_LEN];
482
483 snprintf(holder, HOLDER_LEN, "0x%x (%s)", content, map2str(map, content));
484 holder[HOLDER_LEN-1] = '\0';
485 display_string(label, holder);
486 }
487
488 /*----------------------------------------------------------------------------
489 **
490 ** display_ipv4()
491 **
492 ** Same as display() but we assume that the content argument is
493 ** a 4-byte IPv4 address.
494 **
495 **----------------------------------------------------------------------------
496 */
497
display_ipv4(u_int8_t * label,u_int8_t * addr)498 inline void display_ipv4(u_int8_t * label, u_int8_t * addr)
499 {
500 display(label, addr, 4, DISP_DOTTEDDEC);
501 }
502
503 /*----------------------------------------------------------------------------
504 **
505 ** display_ipv6()
506 **
507 ** Same as display() but we assume that the content argument is
508 ** a 16-byte IPv6 address.
509 **
510 **----------------------------------------------------------------------------
511 */
512
display_ipv6(u_int8_t * label,u_int8_t * addr)513 inline void display_ipv6(u_int8_t * label, u_int8_t * addr)
514 {
515 display(label, addr, 16, DISP_HEXCOLONS4);
516 }
517
518 /*----------------------------------------------------------------------------
519 **
520 ** display_minimal_ipv4()
521 **
522 ** Same as display_minimal() but we assume that the content argument is
523 ** a 4-byte IPv4 address.
524 **
525 **----------------------------------------------------------------------------
526 */
527
display_minimal_ipv4(u_int8_t * content)528 inline void display_minimal_ipv4(u_int8_t * content)
529 {
530 display_minimal(content, 4, DISP_DOTTEDDEC);
531 }
532
533 /*----------------------------------------------------------------------------
534 **
535 ** display_minimal_ipv6()
536 **
537 ** Same as display_minimal() but we assume that the content argument is
538 ** a 16-byte IPv6 address.
539 **
540 **----------------------------------------------------------------------------
541 */
542
display_minimal_ipv6(u_int8_t * content)543 inline void display_minimal_ipv6(u_int8_t * content)
544 {
545 display_minimal(content, 16, DISP_HEXCOLONS4);
546 }
547
548 /*----------------------------------------------------------------------------
549 **
550 ** display_minimal_cr()
551 **
552 ** Display a carriage return (actually, this will work for regular mode as
553 ** well).
554 **
555 **----------------------------------------------------------------------------
556 */
557
display_minimal_cr(void)558 inline void display_minimal_cr(void)
559 {
560 /* Check the layer */
561 if (check_layer())
562 return;
563
564 printf("\n");
565 }
566
567