extern void signed_relts_print(netdissect_options *, int32_t);
extern void unsigned_relts_print(netdissect_options *, uint32_t);
+extern const char *nd_format_time(char *buf, size_t bufsize,
+ const char *format, const struct tm *timeptr);
+
extern void fn_print_char(netdissect_options *, u_char);
extern void fn_print_str(netdissect_options *, const u_char *);
extern u_int nd_printztn(netdissect_options *, const u_char *, u_int, const u_char *);
if (i) {
int64_t seconds_64bit = (int64_t)i - JAN_1970;
time_t seconds;
- struct tm *tm;
char time_buf[128];
+ const char *time_string;
seconds = (time_t)seconds_64bit;
if (seconds != seconds_64bit) {
* It doesn't fit into a time_t, so we can't hand it
* to gmtime.
*/
- ND_PRINT(" (unrepresentable)");
+ time_string = "[Time is too large to fit into a time_t]";
} else {
- tm = gmtime(&seconds);
- if (tm == NULL) {
- /*
- * gmtime() can't handle it.
- * (Yes, that might happen with some version of
- * Microsoft's C library.)
- */
- ND_PRINT(" (unrepresentable)");
- } else {
- /* use ISO 8601 (RFC3339) format */
- strftime(time_buf, sizeof (time_buf), "%Y-%m-%dT%H:%M:%SZ", tm);
- ND_PRINT(" (%s)", time_buf);
- }
+ /* use ISO 8601 (RFC3339) format */
+ time_string = nd_format_time(time_buf, sizeof (time_buf),
+ "%Y-%m-%dT%H:%M:%SZ", gmtime(&seconds));
}
+ ND_PRINT(" (%s)", time_string);
}
}
const u_char *cp, uint8_t len)
{
time_t t;
- struct tm *tm;
- char buf[BUFSIZE];
+ char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")];
if (len != 4)
goto invalid;
t = GET_BE_U_4(cp);
- if (NULL == (tm = gmtime(&t)))
- ND_PRINT(": gmtime() error");
- else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm))
- ND_PRINT(": strftime() error");
- else
- ND_PRINT(": %s UTC", buf);
+ ND_PRINT(": %s",
+ nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC",
+ gmtime(&t)));
return;
invalid:
#include "netdissect.h"
#include "extract.h"
-#include "addrtoname.h"
/*
uint32_t nanoseconds)
{
time_t ts;
- struct tm *tm;
- char buf[BUFSIZE];
+ char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss")];
ts = seconds + (nanoseconds / 1000000000);
nanoseconds %= 1000000000;
- if (NULL == (tm = gmtime(&ts)))
- ND_PRINT("gmtime() error");
- else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm))
- ND_PRINT("strftime() error");
- else
- ND_PRINT("%s.%09u", buf, nanoseconds);
+ ND_PRINT("%s.%09u",
+ nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
+ gmtime(&ts)), nanoseconds);
}
int
ND_PRINT(" %" PRIu64, _i); \
}
-#define DATEOUT() { time_t _t; struct tm *tm; char str[256]; \
+#define DATEOUT() { time_t _t; char str[256]; \
_t = (time_t) GET_BE_S_4(bp); \
bp += sizeof(int32_t); \
- tm = localtime(&_t); \
- strftime(str, 256, "%Y/%m/%d %H:%M:%S", tm); \
- ND_PRINT(" %s", str); \
+ ND_PRINT(" %s", \
+ nd_format_time(str, sizeof(str), \
+ "%Y/%m/%d %H:%M:%S", localtime(&_t))); \
}
#define STOREATTROUT() { uint32_t mask, _i; \
*/
if (i) {
time_t seconds = i - JAN_1970;
- struct tm *tm;
char time_buf[128];
- tm = localtime(&seconds);
- strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm);
- ND_PRINT(" (%s)", time_buf);
+ ND_PRINT(" (%s)",
+ nd_format_time(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S",
+ localtime(&seconds)));
}
}
case 'T':
{
time_t t;
- struct tm *lt;
const char *tstring;
- char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy\n")];
+ char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy")];
uint32_t x;
switch (atoi(fmt + 1)) {
break;
}
if (t != 0) {
- lt = localtime(&t);
- if (lt != NULL) {
- strftime(buffer, sizeof(buffer), "%a %b %e %T %Y%n", lt);
- tstring = buffer;
- }
- else
- tstring = "(Can't convert time)\n";
+ tstring = nd_format_time(buffer, sizeof(buffer), "%a %b %e %T %Y",
+ localtime(&t));
} else
- tstring = "NULL\n";
- ND_PRINT("%s", tstring);
+ tstring = "NULL";
+ ND_PRINT("%s\n", tstring);
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
char *filename = malloc(PATH_MAX + 1);
if (filename == NULL)
error("%s: malloc", __func__);
+ if (strlen(orig_name) == 0)
+ error("an empty string is not a valid file name");
/* Process with strftime if Gflag is set. */
if (Gflag != 0) {
}
/* There's no good way to detect an error in strftime since a return
- * value of 0 isn't necessarily failure.
+ * value of 0 isn't necessarily failure; if orig_name is an empty
+ * string, the formatted string will be empty.
+ *
+ * However, the C90 standard says that, if there *is* a
+ * buffer overflow, the content of the buffer is undefined,
+ * so we must check for a buffer overflow.
+ *
+ * So we check above for an empty orig_name, and only call
+ * strftime() if it's non-empty, in which case the return
+ * value will only be 0 if the formatted date doesn't fit
+ * in the buffer.
+ *
+ * (We check above because, even if we don't use -G, we
+ * want a better error message than "tcpdump: : No such
+ * file or directory" for this case.)
*/
- strftime(filename, PATH_MAX, orig_name, local_tm);
+ if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) {
+ error("%s: strftime", __func__);
+ }
} else {
strncpy(filename, orig_name, PATH_MAX);
}
{
time_t Time = sec;
struct tm *tm;
- char timestr[32];
+ char timebuf[32];
+ const char *timestr;
if ((unsigned)sec & 0x80000000) {
ND_PRINT("[Error converting time]");
else
tm = gmtime(&Time);
- 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);
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)
{