* FOR A PARTICULAR PURPOSE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <sys/stat.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
void
nd_printjn(netdissect_options *ndo, const u_char *s, u_int n)
{
- while (n > 0) {
+ while (n != 0) {
fn_print_char(ndo, GET_U_1(s));
n--;
s++;
{
u_char c;
- while (n > 0) {
+ while (n != 0) {
c = GET_U_1(s);
if (c == '\0')
break;
* Print the timestamp .FRAC part (Microseconds/nanoseconds)
*/
static void
-ts_frac_print(netdissect_options *ndo, long usec)
+ts_frac_print(netdissect_options *ndo, const struct timeval *tv)
{
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
switch (ndo->ndo_tstamp_precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
- ND_PRINT(".%06u", (unsigned)usec);
+ ND_PRINT(".%06u", (unsigned)tv->tv_usec);
+ if ((unsigned)tv->tv_usec > ND_MICRO_PER_SEC - 1)
+ ND_PRINT(" " ND_INVALID_MICRO_SEC_STR);
break;
case PCAP_TSTAMP_PRECISION_NANO:
- ND_PRINT(".%09u", (unsigned)usec);
+ ND_PRINT(".%09u", (unsigned)tv->tv_usec);
+ if ((unsigned)tv->tv_usec > ND_NANO_PER_SEC - 1)
+ ND_PRINT(" " ND_INVALID_NANO_SEC_STR);
break;
default:
break;
}
#else
- ND_PRINT(".%06u", (unsigned)usec);
+ ND_PRINT(".%06u", (unsigned)tv->tv_usec);
+ if ((unsigned)tv->tv_usec > ND_MICRO_PER_SEC - 1)
+ ND_PRINT(" " ND_INVALID_MICRO_SEC_STR);
#endif
}
* if date_flag == WITH_DATE print YY:MM:DD before HH:MM:SS.FRAC
*/
static void
-ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec,
+ts_date_hmsfrac_print(netdissect_options *ndo, const struct timeval *tv,
enum date_flag date_flag, enum time_flag time_flag)
{
- time_t Time = sec;
struct tm *tm;
- char timestr[32];
+ char timebuf[32];
+ const char *timestr;
+#ifdef _WIN32
+ time_t sec;
+#endif
- if ((unsigned)sec & 0x80000000) {
- ND_PRINT("[Error converting time]");
+ if (tv->tv_sec < 0) {
+ ND_PRINT("[timestamp overflow]");
return;
}
+#ifdef _WIN32
+ /* on Windows tv->tv_sec is a long not a 64-bit time_t. */
+ sec = tv->tv_sec;
+#endif
+
if (time_flag == LOCAL_TIME)
- tm = localtime(&Time);
+#ifdef _WIN32
+ tm = localtime(&sec);
+#else
+ tm = localtime(&tv->tv_sec);
+#endif
else
- tm = gmtime(&Time);
+#ifdef _WIN32
+ tm = gmtime(&sec);
+#else
+ tm = gmtime(&tv->tv_sec);
+#endif
- if (!tm) {
- ND_PRINT("[Error converting time]");
- return;
+ if (date_flag == WITH_DATE) {
+ timestr = nd_format_time(timebuf, sizeof(timebuf),
+ "%Y-%m-%d %H:%M:%S", tm);
+ } else {
+ timestr = nd_format_time(timebuf, sizeof(timebuf),
+ "%H:%M:%S", tm);
}
- 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);
+ ts_frac_print(ndo, tv);
}
/*
* Print the timestamp - Unix timeval style, as SECS.FRAC.
*/
static void
-ts_unix_print(netdissect_options *ndo, long sec, long usec)
+ts_unix_print(netdissect_options *ndo, const struct timeval *tv)
{
- if ((unsigned)sec & 0x80000000) {
- ND_PRINT("[Error converting time]");
+ if (tv->tv_sec < 0) {
+ ND_PRINT("[timestamp overflow]");
return;
}
- ND_PRINT("%u", (unsigned)sec);
- ts_frac_print(ndo, usec);
+ ND_PRINT("%" PRId64, (int64_t)tv->tv_sec);
+ ts_frac_print(ndo, tv);
}
/*
switch (ndo->ndo_tflag) {
case 0: /* Default */
- ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
- WITHOUT_DATE, LOCAL_TIME);
+ ts_date_hmsfrac_print(ndo, tvp, WITHOUT_DATE, LOCAL_TIME);
ND_PRINT(" ");
break;
break;
case 2: /* Unix timeval style */
- ts_unix_print(ndo, tvp->tv_sec, tvp->tv_usec);
+ ts_unix_print(ndo, tvp);
ND_PRINT(" ");
break;
netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
ND_PRINT((negative_offset ? "-" : " "));
- ts_date_hmsfrac_print(ndo, tv_result.tv_sec, tv_result.tv_usec,
- WITHOUT_DATE, UTC_TIME);
+ ts_date_hmsfrac_print(ndo, &tv_result, WITHOUT_DATE, UTC_TIME);
ND_PRINT(" ");
if (ndo->ndo_tflag == 3)
break;
case 4: /* Date + Default */
- ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
- WITH_DATE, LOCAL_TIME);
+ ts_date_hmsfrac_print(ndo, tvp, WITH_DATE, LOCAL_TIME);
ND_PRINT(" ");
break;
}
ND_PRINT("0s");
return;
}
- while (secs > 0) {
+ while (secs != 0) {
if (secs >= *s) {
ND_PRINT("%u%s", secs / *s, *l);
secs -= (secs / *s) * *s;
unsigned_relts_print(ndo, secs);
}
+/*
+ * Format a struct tm with strftime().
+ * If the pointer to the struct tm is null, that means that the
+ * routine to convert a time_t to a struct tm failed; the localtime()
+ * and gmtime() in the Microsoft Visual Studio C library will fail,
+ * returning null, if the value is before the UNIX Epoch.
+ */
+const char *
+nd_format_time(char *buf, size_t bufsize, const char *format,
+ const struct tm *timeptr)
+{
+ if (timeptr != NULL) {
+ if (strftime(buf, bufsize, format, timeptr) != 0)
+ return (buf);
+ else
+ return ("[nd_format_time() buffer is too small]");
+ } else
+ return ("[localtime() or gmtime() couldn't convert the date and time]");
+}
+
/* Print the truncated string */
void nd_print_trunc(netdissect_options *ndo)
{
ND_PRINT(" (invalid)");
}
+/*
+ * Print a sequence of bytes, separated by a single space.
+ * Stop if truncated (via GET_U_1/longjmp) or after n bytes,
+ * whichever is first.
+ */
+void
+nd_print_bytes_hex(netdissect_options *ndo, const u_char *cp, u_int n)
+{
+ while (n > 0) {
+ ND_PRINT("%02x", GET_U_1(cp));
+ n--;
+ cp++;
+ if (n > 0)
+ ND_PRINT(" ");
+ }
+}
+
/*
* this is a generic routine for printing unknown data;
* we pass on the linefeed plus indentation string to
* either a space character at the beginning of the line (this
* includes a blank line) or no more tokens remaining on the line.
*/
-static int
+static u_int
fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
u_char *tbuf, size_t tbuflen)
{
/*
* All printable ASCII, but no line ending after that point
- * in the buffer; treat this as if it were truncated.
+ * in the buffer.
*/
linelen = idx - startidx;
ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
- nd_print_trunc(ndo);
return (0);
print: