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