/**************************************************************************** ** 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"); }