]> The Tcpdump Group git mirrors - tcpdump/blobdiff - util-print.c
CVE-2017-13040/MPTCP: Clean up printing DSS suboption.
[tcpdump] / util-print.c
index b481e9e6d8d6396325038793157dcd5aafdf9ab6..90e11b9f3b80b02b6a42d62f001c6fcdc6070b0b 100644 (file)
@@ -21,7 +21,7 @@
 
 /*
  * txtproto_print() derived from original code by Hannes Gredler
- * (hannes@juniper.net):
+ * (hannes@gredler.at):
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that: (1) source code
@@ -57,6 +57,8 @@
 #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
@@ -66,6 +68,23 @@ int32_t thiszone;            /* seconds offset from gmt to local time */
 
 #define TOKBUFSIZE 128
 
+/*
+ * Print out a character, filtering out the non-printable ones
+ */
+void
+fn_print_char(netdissect_options *ndo, u_char c)
+{
+       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));
+}
+
 /*
  * Print out a null-terminated filename (or other ascii string).
  * If ep is NULL, assume no truncation check is needed.
@@ -99,6 +118,56 @@ fn_print(netdissect_options *ndo,
        return(ret);
 }
 
+/*
+ * 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.
+ * Return the number of bytes of string processed, including the
+ * terminating null, if not truncated.  Return 0 if truncated.
+ */
+u_int
+fn_printztn(netdissect_options *ndo,
+         register const u_char *s, register u_int n, register const u_char *ep)
+{
+       register u_int bytes;
+       register u_char c;
+
+       bytes = 0;
+       for (;;) {
+               if (n == 0 || (ep != NULL && s >= ep)) {
+                       /*
+                        * Truncated.  This includes "no null before we
+                        * got to the end of the fixed-length buffer".
+                        *
+                        * XXX - BOOTP says "null-terminated", which
+                        * means the maximum length of the string, in
+                        * bytes, is 1 less than the size of the buffer,
+                        * as there must always be a terminating null.
+                        */
+                       bytes = 0;
+                       break;
+               }
+
+               c = *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));
+       }
+       return(bytes);
+}
+
 /*
  * Print out a counted filename (or other ascii string).
  * If ep is NULL, assume no truncation check is needed.
@@ -318,27 +387,23 @@ ts_print(netdissect_options *ndo,
 }
 
 /*
- * Print a relative number of seconds (e.g. hold time, prune timer)
+ * Print an unsigned relative number of seconds (e.g. hold time, prune timer)
  * in the form 5m1s.  This does no truncation, so 32230861 seconds
  * is represented as 1y1w1d1h1m1s.
  */
 void
-relts_print(netdissect_options *ndo,
-            int secs)
+unsigned_relts_print(netdissect_options *ndo,
+                     uint32_t secs)
 {
        static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
-       static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
+       static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
        const char **l = lengths;
-       const int *s = seconds;
+       const u_int *s = seconds;
 
        if (secs == 0) {
                ND_PRINT((ndo, "0s"));
                return;
        }
-       if (secs < 0) {
-               ND_PRINT((ndo, "-"));
-               secs = -secs;
-       }
        while (secs > 0) {
                if (secs >= *s) {
                        ND_PRINT((ndo, "%d%s", secs / *s, *l));
@@ -349,6 +414,42 @@ relts_print(netdissect_options *ndo,
        }
 }
 
+/*
+ * Print a signed relative number of seconds (e.g. hold time, prune timer)
+ * in the form 5m1s.  This does no truncation, so 32230861 seconds
+ * is represented as 1y1w1d1h1m1s.
+ */
+void
+signed_relts_print(netdissect_options *ndo,
+                   int32_t secs)
+{
+       if (secs < 0) {
+               ND_PRINT((ndo, "-"));
+               if (secs == INT32_MIN) {
+                       /*
+                        * -2^31; you can't fit its absolute value into
+                        * a 32-bit signed integer.
+                        *
+                        * Just directly pass said absolute value to
+                        * unsigned_relts_print() directly.
+                        *
+                        * (XXX - does ISO C guarantee that -(-2^n),
+                        * when calculated and cast to an n-bit unsigned
+                        * integer type, will have the value 2^n?)
+                        */
+                       unsigned_relts_print(ndo, 2147483648U);
+               } else {
+                       /*
+                        * We now know -secs will fit into an int32_t;
+                        * negate it and pass that to unsigned_relts_print().
+                        */
+                       unsigned_relts_print(ndo, -secs);
+               }
+               return;
+       }
+       unsigned_relts_print(ndo, secs);
+}
+
 /*
  *  this is a generic routine for printing unknown data;
  *  we pass on the linefeed plus indentation string to
@@ -420,8 +521,9 @@ static char *
 bittok2str_internal(register const struct tok *lp, register const char *fmt,
           register u_int v, const char *sep)
 {
-        static char buf[256]; /* our stringbuffer */
-        int buflen=0;
+        static char buf[1024+1]; /* our string buffer */
+        char *bufp = buf;
+        size_t space_left = sizeof(buf), string_size;
         register u_int rotbit; /* this is the bit we rotate through all bitpositions */
         register u_int tokval;
         const char * sepstr = "";
@@ -436,8 +538,20 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt,
                  */
                if (tokval == (v&rotbit)) {
                     /* ok we have found something */
-                    buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
-                                     sepstr, lp->s);
+                    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;
                 }
@@ -446,7 +560,7 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt,
             lp++;
        }
 
-        if (buflen == 0)
+        if (bufp == buf)
             /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
             (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v);
         return (buf);
@@ -525,7 +639,6 @@ mask2plen(uint32_t mask)
        return (prefix_len);
 }
 
-#ifdef INET6
 int
 mask62plen(const u_char *mask)
 {
@@ -552,7 +665,6 @@ mask62plen(const u_char *mask)
        }
        return (cidr_len);
 }
-#endif /* INET6 */
 
 /*
  * Routine to print out information for text-based protocols such as FTP,
@@ -766,7 +878,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((ndo, "%c", toupper(*pnp)));
+               ND_PRINT((ndo, "%c", toupper((u_char)*pnp)));
 
        if (is_reqresp) {
                /*
@@ -803,7 +915,7 @@ safeputs(netdissect_options *ndo,
 {
        u_int idx = 0;
 
-       while (*s && idx < maxlen) {
+       while (idx < maxlen && *s) {
                safeputchar(ndo, *s);
                idx++;
                s++;