]> The Tcpdump Group git mirrors - tcpdump/blobdiff - util-print.c
Merge pull request #703 from nmap/update-gitignore
[tcpdump] / util-print.c
index 84c10107451489e82ff43820c1a93ad945eb213e..a982e86da4deb95ec4ca2e76ec632e1a4a085b1f 100644 (file)
 #include "ascii_strcasecmp.h"
 #include "timeval-operations.h"
 
-int32_t thiszone;              /* seconds offset from gmt to local time */
-/* invalid string to print '(invalid)' for malformed or corrupted packets */
-const char istr[] = " (invalid)";
-
-/*
- * timestamp display buffer size, the biggest size of both formats is needed
- * sizeof("0000000000.000000000") > sizeof("00:00:00.000000000")
- */
-#define TS_BUF_SIZE sizeof("0000000000.000000000")
-
 #define TOKBUFSIZE 128
 
+enum date_flag { WITHOUT_DATE = 0, WITH_DATE = 1 };
+enum time_flag { UTC_TIME = 0, LOCAL_TIME = 1 };
+
 /*
  * Print out a character, filtering out the non-printable ones
  */
@@ -129,10 +122,21 @@ nd_print(netdissect_options *ndo,
 
 /*
  * Print out a null-terminated filename (or other ASCII string) from
- * a fixed-length buffer, part of the packet buffer.
- * If ep is NULL, assume no truncation check is needed.
+ * a fixed-length field in the packet buffer, or from what remains of
+ * the packet.
+ *
+ * n is the length of the fixed-length field, or the number of bytes
+ * remaining in the packet based on its on-the-network length.
+ *
+ * If ep is non-null, it should point just past the last captured byte
+ * of the packet, e.g. ndo->ndo_snapend.  If ep is NULL, we assume no
+ * truncation check, other than the checks of the field length/remaining
+ * packet data length, is needed.
+ *
  * Return the number of bytes of string processed, including the
- * terminating null, if not truncated.  Return 0 if truncated.
+ * terminating null, if not truncated; as the terminating null is
+ * included in the count, and as there must be a terminating null,
+ * this will always be non-zero.  Return 0 if truncated.
  */
 u_int
 nd_printztn(netdissect_options *ndo,
@@ -146,7 +150,8 @@ nd_printztn(netdissect_options *ndo,
                if (n == 0 || (ep != NULL && s >= ep)) {
                        /*
                         * Truncated.  This includes "no null before we
-                        * got to the end of the fixed-length buffer".
+                        * got to the end of the fixed-length buffer or
+                        * the end of the packet".
                         *
                         * XXX - BOOTP says "null-terminated", which
                         * means the maximum length of the string, in
@@ -223,77 +228,80 @@ nd_printzp(netdissect_options *ndo,
 }
 
 /*
- * Format the timestamp
+ * Print the timestamp .FRAC part (Microseconds/nanoseconds)
  */
-static char *
-ts_format(netdissect_options *ndo
-#ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
-_U_
-#endif
-, int sec, int usec, char *buf)
+static void
+ts_frac_print(netdissect_options *ndo, int usec)
 {
-       const char *format;
-
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
        switch (ndo->ndo_tstamp_precision) {
 
        case PCAP_TSTAMP_PRECISION_MICRO:
-               format = "%02d:%02d:%02d.%06u";
+               ND_PRINT(".%06u", (unsigned)usec);
                break;
 
        case PCAP_TSTAMP_PRECISION_NANO:
-               format = "%02d:%02d:%02d.%09u";
+               ND_PRINT(".%09u", (unsigned)usec);
                break;
 
        default:
-               format = "%02d:%02d:%02d.{unknown}";
+               ND_PRINT(".{unknown}");
                break;
        }
 #else
-       format = "%02d:%02d:%02d.%06u";
+       ND_PRINT(".%06u", (unsigned)usec);
 #endif
-
-       nd_snprintf(buf, TS_BUF_SIZE, format,
-                 sec / 3600, (sec % 3600) / 60, sec % 60, usec);
-
-        return buf;
 }
 
 /*
- * Format the timestamp - Unix timeval style
+ * Print the timestamp as [YY:MM:DD] HH:MM:SS.FRAC.
+ *   if time_flag == LOCAL_TIME print local time else UTC/GMT time
+ *   if date_flag == WITH_DATE print YY:MM:DD before HH:MM:SS.FRAC
  */
-static char *
-ts_unix_format(netdissect_options *ndo
-#ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
-_U_
-#endif
-, int sec, int usec, char *buf)
+static void
+ts_date_hmsfrac_print(netdissect_options *ndo, int sec, int usec,
+                     enum date_flag date_flag, enum time_flag time_flag)
 {
-       const char *format;
-
-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
-       switch (ndo->ndo_tstamp_precision) {
+       time_t Time = sec;
+       struct tm *tm;
+       char timestr[32];
 
-       case PCAP_TSTAMP_PRECISION_MICRO:
-               format = "%u.%06u";
-               break;
+       if ((unsigned)sec & 0x80000000) {
+               ND_PRINT("[Error converting time]");
+               return;
+       }
 
-       case PCAP_TSTAMP_PRECISION_NANO:
-               format = "%u.%09u";
-               break;
+       if (time_flag == LOCAL_TIME)
+               tm = localtime(&Time);
+       else
+               tm = gmtime(&Time);
 
-       default:
-               format = "%u.{unknown}";
-               break;
+       if (!tm) {
+               ND_PRINT("[Error converting time]");
+               return;
        }
-#else
-       format = "%u.%06u";
-#endif
+       if (date_flag == WITH_DATE)
+               strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
+       else
+               strftime(timestr, sizeof(timestr), "%H:%M:%S", tm);
+       ND_PRINT("%s", timestr);
+
+       ts_frac_print(ndo, usec);
+}
 
-       nd_snprintf(buf, TS_BUF_SIZE, format,
-                (unsigned)sec, (unsigned)usec);
+/*
+ * Print the timestamp - Unix timeval style, as SECS.FRAC.
+ */
+static void
+ts_unix_print(netdissect_options *ndo, int sec, int usec)
+{
+       if ((unsigned)sec & 0x80000000) {
+               ND_PRINT("[Error converting time]");
+               return;
+       }
 
-       return buf;
+       ND_PRINT("%u", (unsigned)sec);
+       ts_frac_print(ndo, usec);
 }
 
 /*
@@ -303,10 +311,6 @@ void
 ts_print(netdissect_options *ndo,
          const struct timeval *tvp)
 {
-       int s;
-       struct tm *tm;
-       time_t Time;
-       char buf[TS_BUF_SIZE];
        static struct timeval tv_ref;
        struct timeval tv_result;
        int negative_offset;
@@ -315,16 +319,17 @@ ts_print(netdissect_options *ndo,
        switch (ndo->ndo_tflag) {
 
        case 0: /* Default */
-               s = (tvp->tv_sec + thiszone) % 86400;
-               ND_PRINT("%s ", ts_format(ndo, s, tvp->tv_usec, buf));
+               ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
+                                     WITHOUT_DATE, LOCAL_TIME);
+               ND_PRINT(" ");
                break;
 
        case 1: /* No time stamp */
                break;
 
        case 2: /* Unix timeval style */
-               ND_PRINT("%s ", ts_unix_format(ndo,
-                         tvp->tv_sec, tvp->tv_usec, buf));
+               ts_unix_print(ndo, tvp->tv_sec, tvp->tv_usec);
+               ND_PRINT(" ");
                break;
 
        case 3: /* Microseconds/nanoseconds since previous packet */
@@ -354,24 +359,18 @@ ts_print(netdissect_options *ndo,
                        netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
 
                ND_PRINT((negative_offset ? "-" : " "));
-
-               ND_PRINT("%s ", ts_format(ndo,
-                         tv_result.tv_sec, tv_result.tv_usec, buf));
+               ts_date_hmsfrac_print(ndo, tv_result.tv_sec, tv_result.tv_usec,
+                                     WITHOUT_DATE, UTC_TIME);
+               ND_PRINT(" ");
 
                 if (ndo->ndo_tflag == 3)
                        tv_ref = *tvp; /* set timestamp for previous packet */
                break;
 
-       case 4: /* Default + Date */
-               s = (tvp->tv_sec + thiszone) % 86400;
-               Time = (tvp->tv_sec + thiszone) - s;
-               tm = gmtime (&Time);
-               if (!tm)
-                       ND_PRINT("Date fail  ");
-               else
-                       ND_PRINT("%04d-%02d-%02d %s ",
-                               tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
-                               ts_format(ndo, s, tvp->tv_usec, buf));
+       case 4: /* Date + Default */
+               ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
+                                     WITH_DATE, LOCAL_TIME);
+               ND_PRINT(" ");
                break;
        }
 }
@@ -446,6 +445,12 @@ void nd_print_trunc(netdissect_options *ndo)
        ND_PRINT(" [|%s]", ndo->ndo_protocol);
 }
 
+/* Print the invalid string */
+void nd_print_invalid(netdissect_options *ndo)
+{
+       ND_PRINT(" (invalid)");
+}
+
 /*
  *  this is a generic routine for printing unknown data;
  *  we pass on the linefeed plus indentation string to
@@ -512,7 +517,7 @@ tok2str(const struct tok *lp, const char *fmt,
 
 /*
  * Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are seperated
+ * this is useful for parsing bitfields, the output strings are separated
  * if the s field is positive.
  */
 static char *
@@ -566,7 +571,7 @@ bittok2str_internal(const struct tok *lp, const char *fmt,
 
 /*
  * Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are not seperated.
+ * this is useful for parsing bitfields, the output strings are not separated.
  */
 char *
 bittok2str_nosep(const struct tok *lp, const char *fmt,
@@ -577,7 +582,7 @@ bittok2str_nosep(const struct tok *lp, const char *fmt,
 
 /*
  * Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are comma seperated.
+ * this is useful for parsing bitfields, the output strings are comma separated.
  */
 char *
 bittok2str(const struct tok *lp, const char *fmt,
@@ -892,7 +897,7 @@ txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
 
        /* Capitalize the protocol name */
        for (pnp = protoname; *pnp != '\0'; pnp++)
-               ND_PRINT("%c", toupper((u_char)*pnp));
+               ND_PRINT("%c", ND_TOUPPER((u_char)*pnp));
 
        if (print_this) {
                /*