]> The Tcpdump Group git mirrors - tcpdump/blobdiff - util.c
PIM: refresh and use tok2str()
[tcpdump] / util.c
diff --git a/util.c b/util.c
index d4882d72cc9a7311389c721d359fc9244949c234..f71f0e8acfbf179ffc1ab63fcdacdef937f22147 100644 (file)
--- a/util.c
+++ b/util.c
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.98 2005-05-06 07:56:54 guy Exp $ (LBL)";
-#endif
-
+#define NETDISSECT_REWORKED
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -36,7 +32,6 @@ static const char rcsid[] _U_ =
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
-#include <pcap.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -62,12 +57,12 @@ fn_print(register const u_char *s, register const u_char *ep)
                        ret = 0;
                        break;
                }
-               if (!isascii(c)) {
-                       c = toascii(c);
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
                        putchar('M');
                        putchar('-');
                }
-               if (!isprint(c)) {
+               if (!ND_ISPRINT(c)) {
                        c ^= 0x40;      /* DEL to ?, others to alpha */
                        putchar('^');
                }
@@ -90,12 +85,12 @@ fn_printn(register const u_char *s, register u_int n,
        while (n > 0 && (ep == NULL || s < ep)) {
                n--;
                c = *s++;
-               if (!isascii(c)) {
-                       c = toascii(c);
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
                        putchar('M');
                        putchar('-');
                }
-               if (!isprint(c)) {
+               if (!ND_ISPRINT(c)) {
                        c ^= 0x40;      /* DEL to ?, others to alpha */
                        putchar('^');
                }
@@ -124,67 +119,86 @@ fn_printzp(register const u_char *s, register u_int n,
                        ret = 0;
                        break;
                }
-               if (!isascii(c)) {
-                       c = toascii(c);
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
                        putchar('M');
                        putchar('-');
                }
-               if (!isprint(c)) {
+               if (!ND_ISPRINT(c)) {
                        c ^= 0x40;      /* DEL to ?, others to alpha */
                        putchar('^');
                }
                putchar(c);
        }
-       return (n == 0) ? 0 : 1;
+       return (n == 0) ? 0 : ret;
+}
+
+/*
+ * Format the timestamp
+ */
+static char *
+ts_format(register int sec, register int usec)
+{
+        static char buf[sizeof("00:00:00.000000")];
+        (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u",
+               sec / 3600, (sec % 3600) / 60, sec % 60, usec);
+
+        return buf;
 }
 
 /*
  * Print the timestamp
  */
 void
-ts_print(register const struct timeval *tvp)
+ts_print(netdissect_options *ndo,
+         register const struct timeval *tvp)
 {
        register int s;
        struct tm *tm;
        time_t Time;
        static unsigned b_sec;
        static unsigned b_usec;
+       int d_usec;
+       int d_sec;
 
-       switch (tflag) {
+       switch (ndo->ndo_tflag) {
 
        case 0: /* Default */
                s = (tvp->tv_sec + thiszone) % 86400;
-               (void)printf("%02d:%02d:%02d.%06u ",
-                            s / 3600, (s % 3600) / 60, s % 60,
-                            (unsigned)tvp->tv_usec);
+               ND_PRINT((ndo, "%s ", ts_format(s, tvp->tv_usec)));
                break;
 
        case 1: /* No time stamp */
                break;
 
        case 2: /* Unix timeval style */
-               (void)printf("%u.%06u ",
+               ND_PRINT((ndo, "%u.%06u ",
                             (unsigned)tvp->tv_sec,
-                            (unsigned)tvp->tv_usec);
+                            (unsigned)tvp->tv_usec));
                break;
 
        case 3: /* Microseconds since previous packet */
+        case 5: /* Microseconds since first packet */
                if (b_sec == 0) {
-                       printf("000000 ");
-               } else {
-                       int d_usec = tvp->tv_usec - b_usec;
-                       int d_sec = tvp->tv_sec - b_sec;
-
-                       while (d_usec < 0) {
-                               d_usec += 1000000;
-                               d_sec--;
-                       }
-                       if (d_sec)
-                               printf("%d. ", d_sec);
-                       printf("%06d ", d_usec);
-               }
-               b_sec = tvp->tv_sec;
-               b_usec = tvp->tv_usec;
+                        /* init timestamp for first packet */
+                        b_usec = tvp->tv_usec;
+                        b_sec = tvp->tv_sec;
+                }
+
+                d_usec = tvp->tv_usec - b_usec;
+                d_sec = tvp->tv_sec - b_sec;
+
+                while (d_usec < 0) {
+                    d_usec += 1000000;
+                    d_sec--;
+                }
+
+                ND_PRINT((ndo, "%s ", ts_format(d_sec, d_usec)));
+
+                if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */
+                    b_sec = tvp->tv_sec;
+                    b_usec = tvp->tv_usec;
+                }
                break;
 
        case 4: /* Default + Date*/
@@ -192,12 +206,11 @@ ts_print(register const struct timeval *tvp)
                Time = (tvp->tv_sec + thiszone) - s;
                tm = gmtime (&Time);
                if (!tm)
-                       printf("Date fail  ");
+                       ND_PRINT((ndo, "Date fail  "));
                else
-                       printf("%04d-%02d-%02d ",
-                                  tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
-               printf("%02d:%02d:%02d.%06u ",
-                          s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
+                       ND_PRINT((ndo, "%04d-%02d-%02d %s ",
+                               tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+                               ts_format(s, tvp->tv_usec)));
                break;
        }
 }
@@ -208,7 +221,8 @@ ts_print(register const struct timeval *tvp)
  * is represented as 1y1w1d1h1m1s.
  */
 void
-relts_print(int secs)
+relts_print(netdissect_options *ndo,
+            int secs)
 {
        static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
        static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
@@ -216,16 +230,16 @@ relts_print(int secs)
        const int *s = seconds;
 
        if (secs == 0) {
-               (void)printf("0s");
+               ND_PRINT((ndo, "0s"));
                return;
        }
        if (secs < 0) {
-               (void)printf("-");
+               ND_PRINT((ndo, "-"));
                secs = -secs;
        }
        while (secs > 0) {
                if (secs >= *s) {
-                       (void)printf("%d%s", secs / *s, *l);
+                       ND_PRINT((ndo, "%d%s", secs / *s, *l));
                        secs -= (secs / *s) * *s;
                }
                s++;
@@ -240,11 +254,21 @@ relts_print(int secs)
  */
 
 int
-print_unknown_data(const u_char *cp,const char *ident,int len)
+print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len)
 {
-       if (snapend - cp < len)
-               len = snapend - cp;
-        hex_print(ident,cp,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));
+               return(0);
+       }
+        hex_print(ndo, ident,cp,len);
        return(1); /* everything is ok */
 }
 
@@ -253,7 +277,7 @@ print_unknown_data(const u_char *cp,const char *ident,int len)
  */
 const char *
 tok2strbuf(register const struct tok *lp, register const char *fmt,
-          register int v, char *buf, size_t bufsize)
+          register u_int v, char *buf, size_t bufsize)
 {
        if (lp != NULL) {
                while (lp->s != NULL) {
@@ -287,18 +311,19 @@ tok2str(register const struct tok *lp, register 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 seperated
+ * if the s field is positive.
  */
-char *
-bittok2str(register const struct tok *lp, register const char *fmt,
-          register int v)
+static char *
+bittok2str_internal(register const struct tok *lp, register const char *fmt,
+          register int v, register int sep)
 {
         static char buf[256]; /* our stringbuffer */
         int buflen=0;
         register int rotbit; /* this is the bit we rotate through all bitpositions */
         register int tokval;
 
-       while (lp->s != NULL && lp != NULL) {
+       while (lp != NULL && lp->s != NULL) {
             tokval=lp->v;   /* load our first value */
             rotbit=1;
             while (rotbit != 0) {
@@ -308,7 +333,8 @@ bittok2str(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, ",lp->s);
+                    buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
+                                     lp->s, sep ? ", " : "");
                     break;
                 }
                 rotbit=rotbit<<1; /* no match - lets shift and try again */
@@ -316,8 +342,13 @@ bittok2str(register const struct tok *lp, register const char *fmt,
             lp++;
        }
 
+        /* user didn't want string seperation - no need to cut off trailing seperators */
+        if (!sep) {
+            return (buf);
+        }
+
         if (buflen != 0) { /* did we find anything */
-            /* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
+            /* yep, set the trailing zero 2 bytes before to eliminate the last comma & whitespace */
             buf[buflen-2] = '\0';
             return (buf);
         }
@@ -330,6 +361,28 @@ bittok2str(register const struct tok *lp, register 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 not seperated.
+ */
+char *
+bittok2str_nosep(register const struct tok *lp, register const char *fmt,
+          register int v)
+{
+    return (bittok2str_internal(lp, fmt, v, 0));
+}
+
+/*
+ * 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.
+ */
+char *
+bittok2str(register const struct tok *lp, register const char *fmt,
+          register int v)
+{
+    return (bittok2str_internal(lp, fmt, v, 1));
+}
+
 /*
  * Convert a value to a string using an array; the macro
  * tok2strary() in <interface.h> is the public interface to
@@ -357,7 +410,7 @@ tok2strary_internal(register const char **lp, int n, register const char *fmt,
  */
 
 int
-mask2plen (u_int32_t mask)
+mask2plen(u_int32_t mask)
 {
        u_int32_t bitmasks[33] = {
                0x00000000,
@@ -381,6 +434,35 @@ mask2plen (u_int32_t mask)
        return (prefix_len);
 }
 
+#ifdef INET6
+int
+mask62plen(const u_char *mask)
+{
+       u_char bitmasks[9] = {
+               0x00,
+               0x80, 0xc0, 0xe0, 0xf0,
+               0xf8, 0xfc, 0xfe, 0xff
+       };
+       int byte;
+       int cidr_len = 0;
+
+       for (byte = 0; byte < 16; byte++) {
+               u_int bits;
+
+               for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
+                       if (mask[byte] == bitmasks[bits]) {
+                               cidr_len += bits;
+                               break;
+                       }
+               }
+
+               if (mask[byte] != 0xff)
+                       break;
+       }
+       return (cidr_len);
+}
+#endif /* INET6 */
+
 /* VARARGS */
 void
 error(const char *fmt, ...)
@@ -497,22 +579,41 @@ read_infile(char *fname)
 }
 
 void
-safeputs(const char *s)
+safeputs(netdissect_options *ndo,
+         const u_char *s, const u_int maxlen)
 {
-       while (*s) {
-               safeputchar(*s);
+       u_int idx = 0;
+
+       while (*s && idx < maxlen) {
+               safeputchar(ndo, *s);
+               idx++;
                s++;
        }
 }
 
 void
-safeputchar(int c)
+safeputchar(netdissect_options *ndo,
+            const u_char c)
+{
+       ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
+}
+
+#ifdef LBL_ALIGN
+/*
+ * Some compilers try to optimize memcpy(), using the alignment constraint
+ * on the argument pointer type.  by using this function, we try to avoid the
+ * optimization.
+ */
+void
+unaligned_memcpy(void *p, const void *q, size_t l)
 {
-       unsigned char ch;
+       memcpy(p, q, l);
+}
 
-       ch = (unsigned char)(c & 0xff);
-       if (ch < 0x80 && isprint(ch))
-               printf("%c", ch);
-       else
-               printf("\\%03o", ch);
+/* As with memcpy(), so with memcmp(). */
+int
+unaligned_memcmp(const void *p, const void *q, size_t l)
+{
+       return (memcmp(p, q, l));
 }
+#endif