* FOR A PARTICULAR PURPOSE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <config.h>
-#include <netdissect-stdinc.h>
+#include "netdissect-stdinc.h"
#include <sys/stat.h>
-#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)";
-
-/*
- * 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
*/
{
if (!ND_ISASCII(c)) {
c = ND_TOASCII(c);
- ND_PRINT((ndo, "M-"));
+ ND_PRINT("M-");
}
- if (!ND_ISPRINT(c)) {
+ if (!ND_ASCII_ISPRINT(c)) {
c ^= 0x40; /* DEL to ?, others to alpha */
- ND_PRINT((ndo, "^"));
+ ND_PRINT("^");
}
- ND_PRINT((ndo, "%c", c));
+ ND_PRINT("%c", c);
}
/*
- * Print out a null-terminated filename (or other ASCII string).
- * If ep is NULL, assume no truncation check is needed.
- * Return true if truncated.
- * Stop at ep (if given) or before the null char, whichever is first.
+ * Print a null-terminated string, filtering out non-printable characters.
+ * DON'T USE IT with a pointer on the packet buffer because there is no
+ * truncation check. For this use, see the nd_printX() functions below.
*/
-int
-fn_print(netdissect_options *ndo,
- const u_char *s, const u_char *ep)
+void
+fn_print_str(netdissect_options *ndo, const u_char *s)
{
- int ret;
- u_char c;
-
- ret = 1; /* assume truncated */
- while (ep == NULL || s < ep) {
- c = *s++;
- if (c == '\0') {
- ret = 0;
- break;
- }
- if (!ND_ISASCII(c)) {
- c = ND_TOASCII(c);
- ND_PRINT((ndo, "M-"));
- }
- if (!ND_ISPRINT(c)) {
- c ^= 0x40; /* DEL to ?, others to alpha */
- ND_PRINT((ndo, "^"));
- }
- ND_PRINT((ndo, "%c", c));
- }
- return(ret);
+ while (*s != '\0') {
+ fn_print_char(ndo, *s);
+ s++;
+ }
}
/*
* Print out a null-terminated filename (or other ASCII string) from
- * a fixed-length 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
-fn_printztn(netdissect_options *ndo,
+nd_printztn(netdissect_options *ndo,
const u_char *s, u_int n, const u_char *ep)
{
u_int bytes;
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
break;
}
- c = *s++;
+ c = GET_U_1(s);
+ s++;
bytes++;
n--;
if (c == '\0') {
/* End of string */
break;
}
- if (!ND_ISASCII(c)) {
- c = ND_TOASCII(c);
- ND_PRINT((ndo, "M-"));
- }
- if (!ND_ISPRINT(c)) {
- c ^= 0x40; /* DEL to ?, others to alpha */
- ND_PRINT((ndo, "^"));
- }
- ND_PRINT((ndo, "%c", c));
+ fn_print_char(ndo, c);
}
return(bytes);
}
/*
- * Print out a counted filename (or other ASCII string).
+ * Print out a counted filename (or other ASCII string), part of
+ * the packet buffer.
* If ep is NULL, assume no truncation check is needed.
* Return true if truncated.
* Stop at ep (if given) or after n bytes, whichever is first.
*/
int
-fn_printn(netdissect_options *ndo,
+nd_printn(netdissect_options *ndo,
const u_char *s, u_int n, const u_char *ep)
{
u_char c;
while (n > 0 && (ep == NULL || s < ep)) {
n--;
- c = *s++;
- if (!ND_ISASCII(c)) {
- c = ND_TOASCII(c);
- ND_PRINT((ndo, "M-"));
- }
- if (!ND_ISPRINT(c)) {
- c ^= 0x40; /* DEL to ?, others to alpha */
- ND_PRINT((ndo, "^"));
- }
- ND_PRINT((ndo, "%c", c));
+ c = GET_U_1(s);
+ s++;
+ fn_print_char(ndo, c);
}
return (n == 0) ? 0 : 1;
}
/*
- * Print out a null-padded filename (or other ASCII string).
- * If ep is NULL, assume no truncation check is needed.
- * Return true if truncated.
- * Stop at ep (if given) or after n bytes or before the null char,
+ * Print a counted filename (or other ASCII string), part of
+ * the packet buffer, filtering out non-printable characters.
+ * Stop if truncated (via GET_U_1/longjmp) or after n bytes,
* whichever is first.
+ * The suffix comes from: j:longJmp, n:after N bytes.
*/
-int
-fn_printzp(netdissect_options *ndo,
- const u_char *s, u_int n,
- const u_char *ep)
+void
+nd_printjn(netdissect_options *ndo, const u_char *s, u_int n)
+{
+ while (n != 0) {
+ fn_print_char(ndo, GET_U_1(s));
+ n--;
+ s++;
+ }
+}
+
+/*
+ * Print a null-padded filename (or other ASCII string), part of
+ * the packet buffer, filtering out non-printable characters.
+ * Stop if truncated (via GET_U_1/longjmp) or after n bytes or before
+ * the null char, whichever occurs first.
+ * The suffix comes from: j:longJmp, n:after N bytes, p:null-Padded.
+ */
+void
+nd_printjnp(netdissect_options *ndo, const u_char *s, u_int n)
{
- int ret;
u_char c;
- ret = 1; /* assume truncated */
- while (n > 0 && (ep == NULL || s < ep)) {
- n--;
- c = *s++;
- if (c == '\0') {
- ret = 0;
+ while (n != 0) {
+ c = GET_U_1(s);
+ if (c == '\0')
break;
- }
- if (!ND_ISASCII(c)) {
- c = ND_TOASCII(c);
- ND_PRINT((ndo, "M-"));
- }
- if (!ND_ISPRINT(c)) {
- c ^= 0x40; /* DEL to ?, others to alpha */
- ND_PRINT((ndo, "^"));
- }
- ND_PRINT((ndo, "%c", c));
+ fn_print_char(ndo, c);
+ n--;
+ s++;
}
- return (n == 0) ? 0 : ret;
}
/*
- * 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, const struct timeval *tv)
{
- 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)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:
- format = "%02d:%02d:%02d.%09u";
+ 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:
- format = "%02d:%02d:%02d.{unknown}";
+ ND_PRINT(".{unknown}");
break;
}
#else
- format = "%02d:%02d:%02d.%06u";
+ 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
-
- 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, const struct timeval *tv,
+ enum date_flag date_flag, enum time_flag time_flag)
{
- const char *format;
-
-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
- switch (ndo->ndo_tstamp_precision) {
+ struct tm *tm;
+ char timebuf[32];
+ const char *timestr;
+#ifdef _WIN32
+ time_t sec;
+#endif
- case PCAP_TSTAMP_PRECISION_MICRO:
- format = "%u.%06u";
- break;
+ if (tv->tv_sec < 0) {
+ ND_PRINT("[timestamp overflow]");
+ return;
+ }
- case PCAP_TSTAMP_PRECISION_NANO:
- format = "%u.%09u";
- break;
+#ifdef _WIN32
+ /* on Windows tv->tv_sec is a long not a 64-bit time_t. */
+ sec = tv->tv_sec;
+#endif
- default:
- format = "%u.{unknown}";
- break;
- }
+ if (time_flag == LOCAL_TIME)
+#ifdef _WIN32
+ tm = localtime(&sec);
#else
- format = "%u.%06u";
+ tm = localtime(&tv->tv_sec);
#endif
+ else
+#ifdef _WIN32
+ tm = gmtime(&sec);
+#else
+ tm = gmtime(&tv->tv_sec);
+#endif
+
+ 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);
+ }
+ ND_PRINT("%s", timestr);
- snprintf(buf, TS_BUF_SIZE, format,
- (unsigned)sec, (unsigned)usec);
+ ts_frac_print(ndo, tv);
+}
- return buf;
+/*
+ * Print the timestamp - Unix timeval style, as SECS.FRAC.
+ */
+static void
+ts_unix_print(netdissect_options *ndo, const struct timeval *tv)
+{
+ if (tv->tv_sec < 0) {
+ ND_PRINT("[timestamp overflow]");
+ return;
+ }
+
+ ND_PRINT("%" PRId64, (int64_t)tv->tv_sec);
+ ts_frac_print(ndo, tv);
}
/*
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;
switch (ndo->ndo_tflag) {
case 0: /* Default */
- s = (tvp->tv_sec + thiszone) % 86400;
- ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec, buf)));
+ ts_date_hmsfrac_print(ndo, tvp, WITHOUT_DATE, LOCAL_TIME);
+ ND_PRINT(" ");
break;
case 1: /* No time stamp */
break;
case 2: /* Unix timeval style */
- ND_PRINT((ndo, "%s ", ts_unix_format(ndo,
- tvp->tv_sec, tvp->tv_usec, buf)));
+ ts_unix_print(ndo, tvp);
+ ND_PRINT(" ");
break;
case 3: /* Microseconds/nanoseconds since previous packet */
else
netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
- ND_PRINT((ndo, (negative_offset ? "-" : " ")));
-
- ND_PRINT((ndo, "%s ", ts_format(ndo,
- tv_result.tv_sec, tv_result.tv_usec, buf)));
+ ND_PRINT((negative_offset ? "-" : " "));
+ ts_date_hmsfrac_print(ndo, &tv_result, 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((ndo, "Date fail "));
- else
- ND_PRINT((ndo, "%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, WITH_DATE, LOCAL_TIME);
+ ND_PRINT(" ");
break;
}
}
const u_int *s = seconds;
if (secs == 0) {
- ND_PRINT((ndo, "0s"));
+ ND_PRINT("0s");
return;
}
- while (secs > 0) {
+ while (secs != 0) {
if (secs >= *s) {
- ND_PRINT((ndo, "%d%s", secs / *s, *l));
+ ND_PRINT("%u%s", secs / *s, *l);
secs -= (secs / *s) * *s;
}
s++;
int32_t secs)
{
if (secs < 0) {
- ND_PRINT((ndo, "-"));
+ ND_PRINT("-");
if (secs == INT32_MIN) {
/*
* -2^31; you can't fit its absolute value into
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(" [|%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)");
+}
+
+/*
+ * 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
*/
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 *indent, u_int len)
{
- if (len < 0) {
- ND_PRINT((ndo,"%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((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet",
- ident));
+ if (!ND_TTEST_LEN(cp, 0)) {
+ ND_PRINT("%sDissector error: %s() called with pointer past end of packet",
+ indent, __func__);
return(0);
}
- hex_print(ndo, ident,cp,len);
+ hex_print(ndo, indent, cp, ND_MIN(len, ND_BYTES_AVAILABLE_AFTER(cp)));
return(1); /* everything is ok */
}
/*
* Convert a token value to a string; use "fmt" if not found.
*/
-const char *
+static const char *
tok2strbuf(const struct tok *lp, const char *fmt,
- u_int v, char *buf, size_t bufsize)
+ const u_int v, char *buf, const size_t bufsize)
{
if (lp != NULL) {
while (lp->s != NULL) {
* in round-robin fashion.
*/
const char *
-tok2str(const struct tok *lp, const char *fmt,
- u_int v)
+tok2str(const struct tok *lp, const char *fmt, const u_int v)
{
static char buf[4][TOKBUFSIZE];
static int idx = 0;
/*
* 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.
+ *
+ * A token matches iff it has one or more bits set and every bit that is set
+ * in the token is set in v. Consequently, a 0 token never matches.
*/
static char *
bittok2str_internal(const struct tok *lp, const char *fmt,
- u_int v, const char *sep)
+ const u_int v, const char *sep)
{
static char buf[1024+1]; /* our string buffer */
char *bufp = buf;
size_t space_left = sizeof(buf), string_size;
- u_int rotbit; /* this is the bit we rotate through all bitpositions */
- u_int tokval;
const char * sepstr = "";
- while (lp != NULL && lp->s != NULL) {
- tokval=lp->v; /* load our first value */
- rotbit=1;
- while (rotbit != 0) {
- /*
- * lets AND the rotating bit with our token value
- * and see if we have got a match
- */
- if (tokval == (v&rotbit)) {
- /* ok we have found something */
- if (space_left <= 1)
- return (buf); /* only enough room left for NUL, if that */
- string_size = strlcpy(bufp, sepstr, space_left);
- if (string_size >= space_left)
- return (buf); /* we ran out of room */
- bufp += string_size;
- space_left -= string_size;
- if (space_left <= 1)
- return (buf); /* only enough room left for NUL, if that */
- string_size = strlcpy(bufp, lp->s, space_left);
- if (string_size >= space_left)
- return (buf); /* we ran out of room */
- bufp += string_size;
- space_left -= string_size;
- sepstr = sep;
- break;
- }
- rotbit=rotbit<<1; /* no match - lets shift and try again */
+ while (lp != NULL && lp->s != NULL) {
+ if (lp->v && (v & lp->v) == lp->v) {
+ /* ok we have found something */
+ if (space_left <= 1)
+ return (buf); /* only enough room left for NUL, if that */
+ string_size = strlcpy(bufp, sepstr, space_left);
+ if (string_size >= space_left)
+ return (buf); /* we ran out of room */
+ bufp += string_size;
+ space_left -= string_size;
+ if (space_left <= 1)
+ return (buf); /* only enough room left for NUL, if that */
+ string_size = strlcpy(bufp, lp->s, space_left);
+ if (string_size >= space_left)
+ return (buf); /* we ran out of room */
+ bufp += string_size;
+ space_left -= string_size;
+ sepstr = sep;
}
lp++;
- }
+ }
if (bufp == buf)
/* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
/*
* 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,
- u_int v)
+bittok2str_nosep(const struct tok *lp, const char *fmt, const u_int v)
{
return (bittok2str_internal(lp, fmt, v, ""));
}
/*
* 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,
- u_int v)
+bittok2str(const struct tok *lp, const char *fmt, const u_int v)
{
return (bittok2str_internal(lp, fmt, v, ", "));
}
* correct for bounds-checking.
*/
const char *
-tok2strary_internal(const char **lp, int n, const char *fmt,
- int v)
+tok2strary_internal(const char **lp, int n, const char *fmt, const int v)
{
static char buf[TOKBUFSIZE];
return (buf);
}
+const struct tok *
+uint2tokary_internal(const struct uint_tokary dict[], const size_t size,
+ const u_int val)
+{
+ size_t i;
+ /* Try a direct lookup before the full scan. */
+ if (val < size && dict[val].uintval == val)
+ return dict[val].tokary; /* OK if NULL */
+ for (i = 0; i < size; i++)
+ if (dict[i].uintval == val)
+ return dict[i].tokary; /* OK if NULL */
+ return NULL;
+}
+
/*
* Convert a 32-bit netmask to prefixlen if possible
* the function returns the prefix-len; if plen == -1
*/
int
-mask2plen(uint32_t mask)
+mask2plen(const uint32_t mask)
{
- uint32_t bitmasks[33] = {
+ const uint32_t bitmasks[33] = {
0x00000000,
0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
* 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)
+ 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(*(pptr + idx))) {
+ c = GET_U_1(pptr + idx);
+ if (!ND_ISASCII(c)) {
/* not an ASCII character */
return (0);
}
- if (isspace(*(pptr + idx))) {
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
/* end of token */
break;
}
- if (!isprint(*(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] = *(pptr + idx);
+ tbuf[toklen] = c;
toklen++;
}
if (toklen == 0) {
/* ran past end of captured data */
break;
}
- if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') {
+ c = GET_U_1(pptr + idx);
+ if (c == '\r' || c == '\n') {
/* end of line */
break;
}
- if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) {
+ if (!ND_ASCII_ISPRINT(c)) {
/* not a printable ASCII character */
break;
}
- if (!isspace(*(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 (*(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 (*(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 (*(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(*(pptr+idx)) ||
- (!isprint(*(pptr+idx)) && *(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.
+ * in the buffer.
*/
-trunc:
linelen = idx - startidx;
- ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
- protoname));
+ ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
return (0);
print:
- ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx));
+ ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
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((ndo, "%c", toupper((u_char)*pnp)));
+ nd_print_protocol_caps(ndo);
if (print_this) {
/*
* request or response; just print the length
* on the first line of the output.
*/
- ND_PRINT((ndo, ", length: %u", len));
+ 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);
}
}
}
-void
-safeputs(netdissect_options *ndo,
- const u_char *s, const u_int maxlen)
-{
- u_int idx = 0;
-
- while (idx < maxlen && *s) {
- safeputchar(ndo, *s);
- idx++;
- s++;
- }
-}
-
-void
-safeputchar(netdissect_options *ndo,
- const u_char c)
-{
- ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
-}
-
#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
(defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
(defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \
defined(__vax__)
/*
- * The procesor natively handles unaligned loads, so just use memcpy()
+ * The processor natively handles unaligned loads, so just use memcpy()
* and memcmp(), to enable those optimizations.
*
* XXX - are those all the x86 tests we need?