]> The Tcpdump Group git mirrors - tcpdump/blobdiff - extract.h
Add program_name field in the netdissect_options structure
[tcpdump] / extract.h
index f0479638b4f14d5cbf66222e3e15a5afe3ff443d..cb62ebddb61e9a7f0c85a5af782f1afd20b1dd1d 100644 (file)
--- a/extract.h
+++ b/extract.h
@@ -17,8 +17,6 @@
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * @(#) $Header: /tcpdump/master/tcpdump/extract.h,v 1.24 2005-01-15 02:06:50 guy Exp $ (LBL)
  */
 
 /*
 /*
  * The processor doesn't natively handle unaligned loads.
  */
-#ifdef HAVE___ATTRIBUTE__
+#if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
+    (defined(__alpha) || defined(__alpha__) || \
+     defined(__mips) || defined(__mips__))
+
 /*
- * We have __attribute__; we assume that means we have __attribute__((packed)).
- * Declare packed structures containing a u_int16_t and a u_int32_t,
+ * This is a GCC-compatible compiler and we have __attribute__, which
+ * we assume that mean we have __attribute__((packed)), and this is
+ * MIPS or Alpha, which has instructions that can help when doing
+ * unaligned loads.
+ *
+ * Declare packed structures containing a uint16_t and a uint32_t,
  * cast the pointer to point to one of those, and fetch through it;
  * the GCC manual doesn't appear to explicitly say that
  * __attribute__((packed)) causes the compiler to generate unaligned-safe
  * code, but it apppears to do so.
  *
- * We do this in case the compiler can generate, for this instruction set,
- * better code to do an unaligned load and pass stuff to "ntohs()" or
- * "ntohl()" than the code to fetch the bytes one at a time and
- * assemble them.  (That might not be the case on a little-endian platform,
- * where "ntohs()" and "ntohl()" might not be done inline.)
+ * We do this in case the compiler can generate code using those
+ * instructions to do an unaligned load and pass stuff to "ntohs()" or
+ * "ntohl()", which might be better than than the code to fetch the
+ * bytes one at a time and assemble them.  (That might not be the
+ * case on a little-endian platform, such as DEC's MIPS machines and
+ * Alpha machines, where "ntohs()" and "ntohl()" might not be done
+ * inline.)
+ *
+ * We do this only for specific architectures because, for example,
+ * at least some versions of GCC, when compiling for 64-bit SPARC,
+ * generate code that assumes alignment if we do this.
+ *
+ * XXX - add other architectures and compilers as possible and
+ * appropriate.
+ *
+ * HP's C compiler, indicated by __HP_cc being defined, supports
+ * "#pragma unaligned N" in version A.05.50 and later, where "N"
+ * specifies a number of bytes at which the typedef on the next
+ * line is aligned, e.g.
+ *
+ *     #pragma unalign 1
+ *     typedef uint16_t unaligned_uint16_t;
+ *
+ * to define unaligned_uint16_t as a 16-bit unaligned data type.
+ * This could be presumably used, in sufficiently recent versions of
+ * the compiler, with macros similar to those below.  This would be
+ * useful only if that compiler could generate better code for PA-RISC
+ * or Itanium than would be generated by a bunch of shifts-and-ORs.
+ *
+ * DEC C, indicated by __DECC being defined, has, at least on Alpha,
+ * an __unaligned qualifier that can be applied to pointers to get the
+ * compiler to generate code that does unaligned loads and stores when
+ * dereferencing the pointer in question.
+ *
+ * XXX - what if the native C compiler doesn't support
+ * __attribute__((packed))?  How can we get it to generate unaligned
+ * accesses for *specific* items?
  */
 typedef struct {
-       u_int16_t       val;
-} __attribute__((packed)) unaligned_u_int16_t;
+       uint16_t        val;
+} __attribute__((packed)) unaligned_uint16_t;
 
 typedef struct {
-       u_int32_t       val;
-} __attribute__((packed)) unaligned_u_int32_t;
+       uint32_t        val;
+} __attribute__((packed)) unaligned_uint32_t;
 
-#define EXTRACT_16BITS(p) \
-       ((u_int16_t)ntohs(((const unaligned_u_int16_t *)(p))->val))
-#define EXTRACT_32BITS(p) \
-       ((u_int32_t)ntohl(((const unaligned_u_int32_t *)(p))->val))
-#define EXTRACT_64BITS(p) \
-       ((u_int64_t)(((u_int64_t)ntohl(((const unaligned_u_int32_t *)(p) + 0)->val)) << 32 | \
-                    ((u_int64_t)ntohl(((const unaligned_u_int32_t *)(p) + 1)->val)) << 0))
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+       return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
+}
 
-#else /* HAVE___ATTRIBUTE__ */
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+       return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+       return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \
+               ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
+}
+
+#else /* have to do it a byte at a time */
 /*
- * We don't have __attribute__, so do unaligned loads of big-endian
+ * This isn't a GCC-compatible compiler, we don't have __attribute__,
+ * or we do but we don't know of any better way with this instruction
+ * set to do unaligned loads, so do unaligned loads of big-endian
  * quantities the hard way - fetch the bytes one at a time and
  * assemble them.
  */
 #define EXTRACT_16BITS(p) \
-       ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \
-                    (u_int16_t)*((const u_int8_t *)(p) + 1)))
+       ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
+                   ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
 #define EXTRACT_32BITS(p) \
-       ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 3)))
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
 #define EXTRACT_64BITS(p) \
-       ((u_int64_t)((u_int64_t)*((const u_int8_t *)(p) + 0) << 56 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 1) << 48 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 2) << 40 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 3) << 32 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 4) << 24 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 5) << 16 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 6) << 8 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 7)))
-#endif /* HAVE___ATTRIBUTE__ */
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
+#endif /* must special-case unaligned accesses */
 #else /* LBL_ALIGN */
 /*
  * The processor natively handles unaligned loads, so we can just
  * cast the pointer and fetch through it.
  */
-#define EXTRACT_16BITS(p) \
-       ((u_int16_t)ntohs(*(const u_int16_t *)(p)))
-#define EXTRACT_32BITS(p) \
-       ((u_int32_t)ntohl(*(const u_int32_t *)(p)))
-#define EXTRACT_64BITS(p) \
-       ((u_int64_t)(((u_int64_t)ntohl(*((const u_int32_t *)(p) + 0))) << 32 | \
-                    ((u_int64_t)ntohl(*((const u_int32_t *)(p) + 1))) << 0))
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+       return ((uint16_t)ntohs(*(const uint16_t *)(p)));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+       return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+       return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \
+               ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+
 #endif /* LBL_ALIGN */
 
 #define EXTRACT_24BITS(p) \
-       ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 2)))
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
+
+#define EXTRACT_40BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
+
+#define EXTRACT_48BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
+
+#define EXTRACT_56BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
 
 /*
  * Macros to extract possibly-unaligned little-endian integral values.
@@ -108,19 +195,23 @@ typedef struct {
  */
 #define EXTRACT_LE_8BITS(p) (*(p))
 #define EXTRACT_LE_16BITS(p) \
-       ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \
-                    (u_int16_t)*((const u_int8_t *)(p) + 0)))
+       ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
 #define EXTRACT_LE_32BITS(p) \
-       ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
-                    (u_int32_t)*((const u_int8_t *)(p) + 0)))
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_24BITS(p) \
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
 #define EXTRACT_LE_64BITS(p) \
-       ((u_int64_t)((u_int64_t)*((const u_int8_t *)(p) + 7) << 56 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 6) << 48 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 5) << 40 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 4) << 32 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 3) << 24 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 2) << 16 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 1) << 8 | \
-                    (u_int64_t)*((const u_int8_t *)(p) + 0)))
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))