/****************************************************************************
** File: display.c
**
** Author: Mike Borella
**
** Comments: Displaying functions
**
** $Id: display.c,v 1.27 2002/01/03 00:04:01 mborella Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#include "display.h"
#define LABEL_LENGTH 22
#define MULTILINE_LENGTH 23
#define MULTILINE_STRING_LENGTH 48
#define BUF_SIZE 128
#define HOLDER_LEN 64
int packet_displayed;
int start_of_packet;
extern struct arg_t * my_args;
/*----------------------------------------------------------------------------
**
** display_header_line()
**
** Writes out a line of separators (separators defined in headerline_t)
**
**----------------------------------------------------------------------------
*/
inline void display_header_line(headerline_t hl)
{
/* Check the layer */
if (check_layer())
return;
switch(hl)
{
case HEADERLINE_DASHES:
printf("--------------------------------------------------------------------------\n");
break;
case HEADERLINE_STARS:
printf("**************************************************************************\n");
break;
case HEADERLINE_EQUALS:
printf("==========================================================================\n");
break;
case HEADERLINE_DOTS:
printf("..........................................................................\n");
break;
default:
error_fatal("unknown header line type");
}
}
/*----------------------------------------------------------------------------
**
** display_header_banner_ts()
**
** Writes out a generic header banner with timestamp for protocol headers.
**
** ISSUE: Do we want to limit the length of the banner string so that it
** doesn't run off the screen?
**
**----------------------------------------------------------------------------
*/
inline void display_header_banner_ts(char *banner, char *ts)
{
/* Check the layer */
if (check_layer())
return;
if (start_of_packet)
{
display_header_line(HEADERLINE_STARS);
start_of_packet = 0;
}
else
display_header_line(HEADERLINE_DASHES);
printf(" %s", banner);
if (ts == NULL)
printf("\n");
else
printf(" (%s)\n", ts);
display_header_line(HEADERLINE_DASHES);
}
/*----------------------------------------------------------------------------
**
** display_header_banner()
**
** Writes out a generic header banner for protocol headers.
**
**----------------------------------------------------------------------------
*/
inline void display_header_banner(char * banner)
{
display_header_banner_ts(banner, NULL);
}
/*----------------------------------------------------------------------------
**
** display_whitespace_pad()
**
** Pad the output with a pre-determined number of spaces from the label to
** the output. The input parameter is the length of the label.
**
**----------------------------------------------------------------------------
*/
inline void display_whitespace_pad(int length)
{
int i;
/* Check the layer */
if (check_layer())
return;
for (i=0; i < LABEL_LENGTH+1-length; i++)
putchar(' ');
}
/*----------------------------------------------------------------------------
**
** display()
**
** Display a protocol field or some other string according to our rules
**
** Parameters:
** label - always printed, must be null terminated string
** content - the stuff to display, usually the value of the field
** length - the number of bytes to display from the content parameter
** format - the specific format to use when displaying
**
**----------------------------------------------------------------------------
*/
inline void display(char * label, u_int8_t * content, u_int32_t length,
display_t format)
{
int label_len;
char label_truncated[LABEL_LENGTH+1];
/* Check the layer */
if (check_layer())
return;
/*
* Do sanity checks here
*/
label_len = strlen(label);
if (label_len >= LABEL_LENGTH)
{
strncpy(label_truncated, label, LABEL_LENGTH);
label_truncated[LABEL_LENGTH] = '\0';
label_len = LABEL_LENGTH;
printf("%s:", label_truncated);
}
else
printf("%s:", label);
/*
* Do the actual displaying
*/
display_whitespace_pad(label_len);
display_minimal(content, length, format);
/*
* Trailing printf()
*/
printf("\n");
}
/*----------------------------------------------------------------------------
**
** display_minimal()
**
** Display a protocol field or some other string in minimal mode.
** This means that there is no label, no padding, and no carriage return.
**
** Parameters:
** content - the stuff to display, usually the value of the field
** length - the number of bytes to display from the content parameter
** format - the specific format to use when displaying
**
**----------------------------------------------------------------------------
*/
inline void display_minimal(u_int8_t * content, u_int32_t length,
display_t format)
{
int i,j;
int seen_a_one;
u_int8_t bit_holder;
struct in_addr * ip_holder;
u_int8_t * ptr;
u_int8_t * temp;
double sum;
u_int32_t multiplier;
int len;
/* Check the layer */
if (check_layer())
return;
/*
* We have displayed part of this packet, so we need a carriage return.
*/
packet_displayed = 1;
/*
* Depending on the display format, we may do different things
*/
switch(format)
{
case DISP_DEC:
temp = (u_int8_t *) my_malloc(length);
memcpy(temp, content, length);
#if !defined(WORDS_BIGENDIAN)
reverse_byte_order(temp, length);
#endif
sum = 0.0;
multiplier = 1;
for (i = length-1; i >= 0; i--)
{
ptr = temp+i;
sum += (double) (multiplier * *ptr);
multiplier = multiplier * 256;
}
printf("%.0f", sum);
my_free(temp);
break;
case DISP_DOTTEDDEC:
ip_holder = (struct in_addr *) content;
for (i=0; i<4; i++)
if (i==3)
printf("%d", content[i]);
else
printf("%d.", content[i]);
break;
case DISP_HEX:
printf("0x");
for (i=0; i < length; i++)
{
if (content[i] < 16)
printf("0%x", content[i]);
else
printf("%x", content[i]);
}
break;
case DISP_HEX_MULTILINE:
printf("0x");
for (i=0; i < length; i++)
{
if ((i > 0) && (i % MULTILINE_LENGTH == 0))
{
printf("\n");
display_whitespace_pad(-3);
}
if (content[i] < 16)
printf("0%x", content[i]);
else
printf("%x", content[i]);
}
break;
case DISP_HEXCOLONS:
for (i=0; i < length; i++)
{
if (content[i] < 16)
printf("0%x", content[i]);
else
printf("%x", content[i]);
if (i != length-1)
printf(":");
}
break;
case DISP_HEXCOLONS4:
for (i=0; i < length; i++)
{
printf("%x", content[i]);
if (i % 2 == 1 && i != length - 1)
printf(":");
}
break;
case DISP_BINNLZ:
seen_a_one = 0;
for (i=0; i < length; i++)
{
bit_holder = 128;
for (j=1; j<=8; j++)
{
if (content[i] & bit_holder)
{
seen_a_one = 1;
printf("1");
}
else
{
if (seen_a_one || (i == length -1 && j == 8))
printf("0");
}
bit_holder = bit_holder >> 1;
}
}
break;
case DISP_STRING:
/*
* Rather than just ass-u-ming that we've been handed a properly
* null terminated string, we created one of our own.
*
* Make sure that ONLY printable characters are sent in this call,
* Otherwise, very strnage bugs will occur! For example, send this
* code a \n and just try to figure out why your output is screwy...
*
*/
ptr = (u_int8_t *) my_malloc(length+1);
memcpy(ptr, content, length);
ptr[length] = '\0';
/* Clean out extra control characters */
len = strlen(ptr);
while((ptr[len-1] == '\n' || ptr[len-1] == '\r') && len >= 1)
{
ptr[len-1] = '\0';
len--;
}
/*
* Let's make sure that the string contains only printable
* characters
*/
if (!isprint_str(ptr, len))
{
my_free(ptr);
break;
}
/* print it then free it */
printf("%s", ptr);
my_free(ptr);
break;
case DISP_STRING_MULTILINE:
/* I'm sure that this could be made much more efficient... */
for (i=0; i < length; i++)
{
if ((i > 0) && (i % MULTILINE_STRING_LENGTH == 0))
{
printf("\n");
display_whitespace_pad(-3);
}
printf("%c", content[i]);
}
break;
default: /* oops, this shouldn't happen... */
break;
}
}
/*----------------------------------------------------------------------------
**
** display_minimal_string()
**
** Same as display_minimal() but we assume that the content argument is
** a string.
**
**----------------------------------------------------------------------------
*/
inline void display_minimal_string(u_int8_t * content)
{
display_minimal(content, strlen(content), DISP_STRING);
}
/*----------------------------------------------------------------------------
**
** display_string()
**
** Same as display() but we assume that the content argument is
** a string. We also assume multiline support is required.
**
**----------------------------------------------------------------------------
*/
inline void display_string(u_int8_t * label, u_int8_t * content)
{
display(label, content, strlen(content), DISP_STRING_MULTILINE);
}
/*----------------------------------------------------------------------------
**
** display_strmap()
**
** Display an item from a strmap_t array, with proper expansion of its
** textual representation.
**
**----------------------------------------------------------------------------
*/
inline void display_strmap(char * label, int content, strmap_t map[])
{
char holder[HOLDER_LEN];
snprintf(holder, HOLDER_LEN, "%d (%s)", content, map2str(map, content));
holder[HOLDER_LEN-1] = '\0';
display_string(label, holder);
}
/*----------------------------------------------------------------------------
**
** display_strmap_hex()
**
** Display an item from a strmap_t array, with proper expansion of its
** textual representation. The number appears in hex format rather than
** decimal.
**
**----------------------------------------------------------------------------
*/
inline void display_strmap_hex(char * label, int content, strmap_t map[])
{
char holder[HOLDER_LEN];
snprintf(holder, HOLDER_LEN, "0x%x (%s)", content, map2str(map, content));
holder[HOLDER_LEN-1] = '\0';
display_string(label, holder);
}
/*----------------------------------------------------------------------------
**
** display_ipv4()
**
** Same as display() but we assume that the content argument is
** a 4-byte IPv4 address.
**
**----------------------------------------------------------------------------
*/
inline void display_ipv4(u_int8_t * label, u_int8_t * addr)
{
display(label, addr, 4, DISP_DOTTEDDEC);
}
/*----------------------------------------------------------------------------
**
** display_ipv6()
**
** Same as display() but we assume that the content argument is
** a 16-byte IPv6 address.
**
**----------------------------------------------------------------------------
*/
inline void display_ipv6(u_int8_t * label, u_int8_t * addr)
{
display(label, addr, 16, DISP_HEXCOLONS4);
}
/*----------------------------------------------------------------------------
**
** display_minimal_ipv4()
**
** Same as display_minimal() but we assume that the content argument is
** a 4-byte IPv4 address.
**
**----------------------------------------------------------------------------
*/
inline void display_minimal_ipv4(u_int8_t * content)
{
display_minimal(content, 4, DISP_DOTTEDDEC);
}
/*----------------------------------------------------------------------------
**
** display_minimal_ipv6()
**
** Same as display_minimal() but we assume that the content argument is
** a 16-byte IPv6 address.
**
**----------------------------------------------------------------------------
*/
inline void display_minimal_ipv6(u_int8_t * content)
{
display_minimal(content, 16, DISP_HEXCOLONS4);
}
/*----------------------------------------------------------------------------
**
** display_minimal_cr()
**
** Display a carriage return (actually, this will work for regular mode as
** well).
**
**----------------------------------------------------------------------------
*/
inline void display_minimal_cr(void)
{
/* Check the layer */
if (check_layer())
return;
printf("\n");
}
syntax highlighted by Code2HTML, v. 0.9.1