#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+#include "netdissect-ctype.h"
+
#include "netdissect.h"
#include "extract.h"
#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)";
-
#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
*/
c = ND_TOASCII(c);
ND_PRINT("M-");
}
- if (!ND_ISPRINT(c)) {
+ if (!ND_ASCII_ISPRINT(c)) {
c ^= 0x40; /* DEL to ?, others to alpha */
ND_PRINT("^");
}
ret = 1; /* assume truncated */
while (ep == NULL || s < ep) {
- c = EXTRACT_U_1(s);
+ c = GET_U_1(s);
s++;
if (c == '\0') {
ret = 0;
break;
}
- c = EXTRACT_U_1(s);
+ c = GET_U_1(s);
s++;
bytes++;
n--;
while (n > 0 && (ep == NULL || s < ep)) {
n--;
- c = EXTRACT_U_1(s);
+ c = GET_U_1(s);
s++;
fn_print_char(ndo, c);
}
ret = 1; /* assume truncated */
while (n > 0 && (ep == NULL || s < ep)) {
n--;
- c = EXTRACT_U_1(s);
+ c = GET_U_1(s);
s++;
if (c == '\0') {
ret = 0;
}
/*
- * Print the timestamp as HH:MM:SS.FRAC.
+ * Print the timestamp .FRAC part (Microseconds/nanoseconds)
*/
static void
-ts_hmsfrac_print(netdissect_options *ndo, int sec, int usec)
+ts_frac_print(netdissect_options *ndo, long usec)
{
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
switch (ndo->ndo_tstamp_precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
- ND_PRINT("%02d:%02d:%02d.%06u", sec / 3600, (sec % 3600) / 60,
- sec % 60, usec);
+ ND_PRINT(".%06u", (unsigned)usec);
break;
case PCAP_TSTAMP_PRECISION_NANO:
- ND_PRINT("%02d:%02d:%02d.%09u", sec / 3600, (sec % 3600) / 60,
- sec % 60, usec);
+ ND_PRINT(".%09u", (unsigned)usec);
break;
default:
- ND_PRINT("%02d:%02d:%02d.{unknown}", sec / 3600, (sec % 3600) / 60,
- sec % 60);
+ ND_PRINT(".{unknown}");
break;
}
#else
- ND_PRINT("%02d:%02d:%02d.%06u", sec / 3600, (sec % 3600) / 60,
- sec % 60, usec);
+ ND_PRINT(".%06u", (unsigned)usec);
#endif
}
/*
- * Print the timestamp - Unix timeval style, as SECS.FRAC.
+ * 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 void
-ts_unix_print(netdissect_options *ndo, int sec, int usec)
+ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec,
+ enum date_flag date_flag, enum time_flag time_flag)
{
-#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:
- ND_PRINT("%u.%06u", (unsigned)sec, (unsigned)usec);
- break;
+ if ((unsigned)sec & 0x80000000) {
+ ND_PRINT("[Error converting time]");
+ return;
+ }
- case PCAP_TSTAMP_PRECISION_NANO:
- ND_PRINT("%u.%09u", (unsigned)sec, (unsigned)usec);
- break;
+ if (time_flag == LOCAL_TIME)
+ tm = localtime(&Time);
+ else
+ tm = gmtime(&Time);
- default:
- ND_PRINT("%u.{unknown}", (unsigned)sec);
- break;
+ if (!tm) {
+ ND_PRINT("[Error converting time]");
+ return;
}
-#else
- ND_PRINT("%u.%06u", (unsigned)sec, (unsigned)usec);
-#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);
+}
+
+/*
+ * Print the timestamp - Unix timeval style, as SECS.FRAC.
+ */
+static void
+ts_unix_print(netdissect_options *ndo, long sec, long usec)
+{
+ if ((unsigned)sec & 0x80000000) {
+ ND_PRINT("[Error converting time]");
+ return;
+ }
+
+ ND_PRINT("%u", (unsigned)sec);
+ ts_frac_print(ndo, usec);
}
/*
ts_print(netdissect_options *ndo,
const struct timeval *tvp)
{
- int s;
- struct tm *tm;
- time_t Time;
static struct timeval tv_ref;
struct timeval tv_result;
int negative_offset;
switch (ndo->ndo_tflag) {
case 0: /* Default */
- s = (tvp->tv_sec + thiszone) % 86400;
- ts_hmsfrac_print(ndo, s, tvp->tv_usec);
+ ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
+ WITHOUT_DATE, LOCAL_TIME);
ND_PRINT(" ");
break;
netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
ND_PRINT((negative_offset ? "-" : " "));
- ts_hmsfrac_print(ndo, tv_result.tv_sec, tv_result.tv_usec);
+ 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 ",
- tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
- ts_hmsfrac_print(ndo, s, tvp->tv_usec);
- ND_PRINT(" ");
- }
+ case 4: /* Date + Default */
+ ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
+ WITH_DATE, LOCAL_TIME);
+ ND_PRINT(" ");
break;
}
}
ND_PRINT(" [|%s]", ndo->ndo_protocol);
}
+/* Print the protocol name */
+void nd_print_protocol(netdissect_options *ndo)
+{
+ ND_PRINT("%s", ndo->ndo_protocol);
+}
+
+/* Print the protocol name in caps (uppercases) */
+void nd_print_protocol_caps(netdissect_options *ndo)
+{
+ const char *p;
+ for (p = ndo->ndo_protocol; *p != '\0'; p++)
+ ND_PRINT("%c", ND_ASCII_TOUPPER(*p));
+}
+
+/* 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
*/
int
-print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len)
+print_unknown_data(netdissect_options *ndo, const u_char *cp,
+ const char *ident, u_int len)
{
- if (len < 0) {
- ND_PRINT("%sDissector error: print_unknown_data called with negative length",
- ident);
- return(0);
- }
- if (ndo->ndo_snapend - cp < len)
- len = ndo->ndo_snapend - cp;
- if (len < 0) {
- ND_PRINT("%sDissector error: print_unknown_data called with pointer past end of packet",
+ u_int len_to_print;
+
+ len_to_print = len;
+ if (!ND_TTEST_LEN(cp, 0)) {
+ ND_PRINT("%sDissector error: print_unknown_data called with pointer past end of packet",
ident);
return(0);
}
- hex_print(ndo, ident,cp,len);
+ if (ND_BYTES_AVAILABLE_AFTER(cp) < len_to_print)
+ len_to_print = ND_BYTES_AVAILABLE_AFTER(cp);
+ hex_print(ndo, ident, cp, len_to_print);
return(1); /* everything is ok */
}
if (fmt == NULL)
fmt = "#%d";
- (void)nd_snprintf(buf, bufsize, fmt, v);
+ (void)snprintf(buf, bufsize, fmt, v);
return (const char *)buf;
}
/*
* 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 *
if (bufp == buf)
/* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
- (void)nd_snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v);
+ (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v);
return (buf);
}
/*
* 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,
/*
* 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,
return lp[v];
if (fmt == NULL)
fmt = "#%d";
- (void)nd_snprintf(buf, sizeof(buf), fmt, v);
+ (void)snprintf(buf, sizeof(buf), fmt, v);
return (buf);
}
u_char *tbuf, size_t tbuflen)
{
size_t toklen = 0;
+ u_char c;
for (; idx < len; idx++) {
if (!ND_TTEST_1(pptr + idx)) {
/* ran past end of captured data */
return (0);
}
- if (!isascii(EXTRACT_U_1(pptr + idx))) {
+ c = GET_U_1(pptr + idx);
+ if (!ND_ISASCII(c)) {
/* not an ASCII character */
return (0);
}
- if (isspace(EXTRACT_U_1(pptr + idx))) {
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
/* end of token */
break;
}
- if (!isprint(EXTRACT_U_1(pptr + idx))) {
+ if (!ND_ASCII_ISPRINT(c)) {
/* not part of a command token or response code */
return (0);
}
/* no room for this character and terminating '\0' */
return (0);
}
- tbuf[toklen] = EXTRACT_U_1(pptr + idx);
+ tbuf[toklen] = c;
toklen++;
}
if (toklen == 0) {
/* ran past end of captured data */
break;
}
- if (EXTRACT_U_1(pptr + idx) == '\r' || EXTRACT_U_1(pptr + idx) == '\n') {
+ c = GET_U_1(pptr + idx);
+ if (c == '\r' || c == '\n') {
/* end of line */
break;
}
- if (!isascii(EXTRACT_U_1(pptr + idx)) || !isprint(EXTRACT_U_1(pptr + idx))) {
+ if (!ND_ASCII_ISPRINT(c)) {
/* not a printable ASCII character */
break;
}
- if (!isspace(EXTRACT_U_1(pptr + idx))) {
+ if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
/* beginning of next token */
break;
}
* the line ending.
*/
static u_int
-print_txt_line(netdissect_options *ndo, const char *protoname,
- const char *prefix, const u_char *pptr, u_int idx, u_int len)
+print_txt_line(netdissect_options *ndo, const char *prefix,
+ const u_char *pptr, u_int idx, u_int len)
{
u_int startidx;
u_int linelen;
+ u_char c;
startidx = idx;
while (idx < len) {
- ND_TCHECK_1(pptr + idx);
- if (EXTRACT_U_1(pptr + idx) == '\n') {
+ c = GET_U_1(pptr + idx);
+ if (c == '\n') {
/*
* LF without CR; end of line.
* Skip the LF and print the line, with the
linelen = idx - startidx;
idx++;
goto print;
- } else if (EXTRACT_U_1(pptr + idx) == '\r') {
+ } else if (c == '\r') {
/* CR - any LF? */
if ((idx+1) >= len) {
/* not in this packet */
return (0);
}
- ND_TCHECK_1(pptr + idx + 1);
- if (EXTRACT_U_1(pptr + idx + 1) == '\n') {
+ if (GET_U_1(pptr + idx + 1) == '\n') {
/*
* CR-LF; end of line.
* Skip the CR-LF and print the line, with
* it.
*/
return (0);
- } else if (!isascii(EXTRACT_U_1(pptr + idx)) ||
- (!isprint(EXTRACT_U_1(pptr + idx)) &&
- EXTRACT_U_1(pptr + idx) != '\t')) {
+ } else if (!ND_ASCII_ISPRINT(c) && c != '\t') {
/*
* Not a printable ASCII character and not a tab;
* treat this as if it were binary data, and
* All printable ASCII, but no line ending after that point
* in the buffer; treat this as if it were truncated.
*/
-trunc:
linelen = idx - startidx;
- ND_PRINT("%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
- protoname);
+ ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
+ nd_print_trunc(ndo);
return (0);
print:
return (idx);
}
+/* Assign needed before calling txtproto_print(): ndo->ndo_protocol = "proto" */
void
txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
- const char *protoname, const char **cmds, u_int flags)
+ const char **cmds, u_int flags)
{
u_int idx, eol;
u_char token[MAX_TOKEN+1];
const char *cmd;
int print_this = 0;
- const char *pnp;
if (cmds != NULL) {
/*
sizeof(token));
}
if (idx != 0) {
- if (isdigit(token[0]) && isdigit(token[1]) &&
- isdigit(token[2]) && token[3] == '\0') {
+ if (ND_ASCII_ISDIGIT(token[0]) && ND_ASCII_ISDIGIT(token[1]) &&
+ ND_ASCII_ISDIGIT(token[2]) && token[3] == '\0') {
/* Yes. */
print_this = 1;
}
print_this = 1;
}
- /* Capitalize the protocol name */
- for (pnp = protoname; *pnp != '\0'; pnp++)
- ND_PRINT("%c", toupper((u_char)*pnp));
+ nd_print_protocol_caps(ndo);
if (print_this) {
/*
*/
ND_PRINT(", length: %u", len);
for (idx = 0;
- idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0;
+ idx < len && (eol = print_txt_line(ndo, "\n\t", pptr, idx, len)) != 0;
idx = eol)
;
} else {
/*
* Just print the first text line.
*/
- print_txt_line(ndo, protoname, ": ", pptr, 0, len);
+ print_txt_line(ndo, ": ", pptr, 0, len);
}
}
}