]> The Tcpdump Group git mirrors - tcpdump/blobdiff - extract.h
Add a cast to the EXTRACT_U_1() macro
[tcpdump] / extract.h
index 28c828ebfc09727be99c6f99d0a571b6b65a4df0..0ea84e925b4ba5a78b21fbb9f367c9ec74b4201f 100644 (file)
--- a/extract.h
+++ b/extract.h
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include <string.h>
+
 /*
  * For 8-bit values; needed to fetch a one-byte value.  Byte order
  * isn't relevant, and alignment isn't an issue.
  */
-#define EXTRACT_U_1(p) (*(p))
+#define EXTRACT_U_1(p) ((uint8_t)(*(p)))
 #define EXTRACT_S_1(p) ((int8_t)(*(p)))
 
 /*
  * XXX - do we need to test for both 32-bit and 64-bit versions of those
  * architectures in all cases?
  */
-static inline uint16_t UNALIGNED_OK
+UNALIGNED_OK static inline uint16_t
 EXTRACT_BE_U_2(const void *p)
 {
        return ((uint16_t)ntohs(*(const uint16_t *)(p)));
 }
 
-static inline int16_t UNALIGNED_OK
+UNALIGNED_OK static inline int16_t
 EXTRACT_BE_S_2(const void *p)
 {
        return ((int16_t)ntohs(*(const int16_t *)(p)));
 }
 
-static inline uint32_t UNALIGNED_OK
+UNALIGNED_OK static inline uint32_t
 EXTRACT_BE_U_4(const void *p)
 {
        return ((uint32_t)ntohl(*(const uint32_t *)(p)));
 }
 
-static inline int32_t UNALIGNED_OK
+UNALIGNED_OK static inline int32_t
 EXTRACT_BE_S_4(const void *p)
 {
        return ((int32_t)ntohl(*(const int32_t *)(p)));
 }
 
-static inline uint64_t UNALIGNED_OK
+UNALIGNED_OK static inline uint64_t
 EXTRACT_BE_U_8(const void *p)
 {
        return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
@@ -114,22 +116,33 @@ EXTRACT_BE_U_8(const void *p)
 
 }
 
-static inline int64_t UNALIGNED_OK
+UNALIGNED_OK static inline int64_t
 EXTRACT_BE_S_8(const void *p)
 {
        return ((int64_t)(((int64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
                ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
 
 }
-#elif defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
+
+/*
+ * Extract an IPv4 address, which is in network byte order, and not
+ * necessarily aligned, and provide the result in host byte order.
+ */
+UNALIGNED_OK static inline uint32_t
+EXTRACT_IPV4_TO_HOST_ORDER(const void *p)
+{
+       return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+#elif ND_IS_AT_LEAST_GNUC_VERSION(2,0) && \
     (defined(__alpha) || defined(__alpha__) || \
      defined(__mips) || defined(__mips__))
 /*
  * This is MIPS or Alpha, which don't natively handle unaligned loads,
  * but which have instructions that can help when doing unaligned
- * loads, and this is a GCC-compatible compiler and we have __attribute__,
- * which we assume that mean we have __attribute__((packed)), which
- * we can use to convince the compiler to generate those instructions.
+ * loads, and this is GCC 2.0 or later or a compiler that claims to
+ * be GCC 2.0 or later, which we assume that mean we have
+ * __attribute__((packed)), which we can use to convince the compiler
+ * to generate those instructions.
  *
  * Declare packed structures containing a uint16_t and a uint32_t,
  * cast the pointer to point to one of those, and fetch through it;
@@ -228,6 +241,16 @@ EXTRACT_BE_S_8(const void *p)
        return ((int64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
                ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
 }
+
+/*
+ * Extract an IPv4 address, which is in network byte order, and not
+ * necessarily aligned, and provide the result in host byte order.
+ */
+UNALIGNED_OK static inline uint32_t
+EXTRACT_IPV4_TO_HOST_ORDER(const void *p)
+{
+       return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
+}
 #else
 /*
  * This architecture doesn't natively support unaligned loads, and either
@@ -271,8 +294,87 @@ EXTRACT_BE_S_8(const void *p)
                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
                   ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
+
+/*
+ * Extract an IPv4 address, which is in network byte order, and not
+ * necessarily aligned, and provide the result in host byte order.
+ */
+#define EXTRACT_IPV4_TO_HOST_ORDER(p) \
+       ((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)))
 #endif /* unaligned access checks */
 
+/*
+ * Extract numerical values in *host* byte order.  (Some metadata
+ * headers are in the byte order of the host that wrote the file,
+ * and libpcap translate them to the byte order of the host
+ * reading the file.  This means that if a program on that host
+ * reads with libpcap and writes to a new file, the new file will
+ * be written in the byte order of the host writing the file.  Thus,
+ * the magic number in pcap files and byte-order magic in pcapng
+ * files can be used to determine the byte order in those metadata
+ * headers.)
+ *
+ * XXX - on platforms that can do unaligned accesses, just cast and
+ * dereference the pointer.
+ */
+static inline uint16_t
+EXTRACT_HE_U_2(const void *p)
+{
+       uint16_t val;
+
+       UNALIGNED_MEMCPY(&val, p, sizeof(uint16_t));
+       return val;
+}
+
+static inline int16_t
+EXTRACT_HE_S_2(const void *p)
+{
+       int16_t val;
+
+       UNALIGNED_MEMCPY(&val, p, sizeof(int16_t));
+       return val;
+}
+
+static inline uint32_t
+EXTRACT_HE_U_4(const void *p)
+{
+       uint32_t val;
+
+       UNALIGNED_MEMCPY(&val, p, sizeof(uint32_t));
+       return val;
+}
+
+static inline int32_t
+EXTRACT_HE_S_4(const void *p)
+{
+       int32_t val;
+
+       UNALIGNED_MEMCPY(&val, p, sizeof(int32_t));
+       return val;
+}
+
+/*
+ * Extract an IPv4 address, which is in network byte order, and which
+ * is not necessarily aligned on a 4-byte boundary, and provide the
+ * result in network byte order.
+ *
+ * This works the same way regardless of the host's byte order.
+ */
+static inline uint32_t
+EXTRACT_IPV4_TO_NETWORK_ORDER(const void *p)
+{
+       uint32_t addr;
+
+       UNALIGNED_MEMCPY(&addr, p, sizeof(uint32_t));
+       return addr;
+}
+
+/*
+ * Non-power-of-2 sizes.
+ */
 #define EXTRACT_BE_U_3(p) \
        ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
                    ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \