xref: /freebsd/contrib/tcpdump/extract.h (revision 0bff6a5af8cb6d8e5123f8b667df78cac885dbb7)
14edb46e9SPaul Traina /*
24edb46e9SPaul Traina  * Copyright (c) 1992, 1993, 1994, 1995, 1996
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
204edb46e9SPaul Traina  */
214edb46e9SPaul Traina 
221de50e9fSSam Leffler /*
23*0bff6a5aSEd Maste  * For 8-bit values; provided for the sake of completeness.  Byte order
24*0bff6a5aSEd Maste  * isn't relevant, and alignment isn't an issue.
251de50e9fSSam Leffler  */
26*0bff6a5aSEd Maste #define EXTRACT_8BITS(p)	(*(p))
27*0bff6a5aSEd Maste #define EXTRACT_LE_8BITS(p)	(*(p))
28*0bff6a5aSEd Maste 
29*0bff6a5aSEd Maste /*
30*0bff6a5aSEd Maste  * Inline functions or macros to extract possibly-unaligned big-endian
31*0bff6a5aSEd Maste  * integral values.
32*0bff6a5aSEd Maste  */
33*0bff6a5aSEd Maste #include "funcattrs.h"
34*0bff6a5aSEd Maste 
35*0bff6a5aSEd Maste /*
36*0bff6a5aSEd Maste  * If we have versions of GCC or Clang that support an __attribute__
37*0bff6a5aSEd Maste  * to say "if we're building with unsigned behavior sanitization,
38*0bff6a5aSEd Maste  * don't complain about undefined behavior in this function", we
39*0bff6a5aSEd Maste  * label these functions with that attribute - we *know* it's undefined
40*0bff6a5aSEd Maste  * in the C standard, but we *also* know it does what we want with
41*0bff6a5aSEd Maste  * the ISA we're targeting and the compiler we're using.
42*0bff6a5aSEd Maste  *
43*0bff6a5aSEd Maste  * For GCC 4.9.0 and later, we use __attribute__((no_sanitize_undefined));
44*0bff6a5aSEd Maste  * pre-5.0 GCC doesn't have __has_attribute, and I'm not sure whether
45*0bff6a5aSEd Maste  * GCC or Clang first had __attribute__((no_sanitize(XXX)).
46*0bff6a5aSEd Maste  *
47*0bff6a5aSEd Maste  * For Clang, we check for __attribute__((no_sanitize(XXX)) with
48*0bff6a5aSEd Maste  * __has_attribute, as there are versions of Clang that support
49*0bff6a5aSEd Maste  * __attribute__((no_sanitize("undefined")) but don't support
50*0bff6a5aSEd Maste  * __attribute__((no_sanitize_undefined)).
51*0bff6a5aSEd Maste  *
52*0bff6a5aSEd Maste  * We define this here, rather than in funcattrs.h, because we
53*0bff6a5aSEd Maste  * only want it used here, we don't want it to be broadly used.
54*0bff6a5aSEd Maste  * (Any printer will get this defined, but this should at least
55*0bff6a5aSEd Maste  * make it harder for people to find.)
56*0bff6a5aSEd Maste  */
57*0bff6a5aSEd Maste #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
58*0bff6a5aSEd Maste #define UNALIGNED_OK	__attribute__((no_sanitize_undefined))
59*0bff6a5aSEd Maste #elif __has_attribute(no_sanitize)
60*0bff6a5aSEd Maste #define UNALIGNED_OK	__attribute__((no_sanitize("undefined")))
61*0bff6a5aSEd Maste #else
62*0bff6a5aSEd Maste #define UNALIGNED_OK
63*0bff6a5aSEd Maste #endif
64*0bff6a5aSEd Maste 
654edb46e9SPaul Traina #ifdef LBL_ALIGN
665b0fe478SBruce M Simpson /*
675b0fe478SBruce M Simpson  * The processor doesn't natively handle unaligned loads.
685b0fe478SBruce M Simpson  */
693c602fabSXin LI #if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
703c602fabSXin LI     (defined(__alpha) || defined(__alpha__) || \
713c602fabSXin LI      defined(__mips) || defined(__mips__))
723c602fabSXin LI 
735b0fe478SBruce M Simpson /*
743c602fabSXin LI * This is a GCC-compatible compiler and we have __attribute__, which
753c602fabSXin LI  * we assume that mean we have __attribute__((packed)), and this is
763c602fabSXin LI  * MIPS or Alpha, which has instructions that can help when doing
773c602fabSXin LI  * unaligned loads.
783c602fabSXin LI  *
793c602fabSXin LI  * Declare packed structures containing a uint16_t and a uint32_t,
805b0fe478SBruce M Simpson  * cast the pointer to point to one of those, and fetch through it;
815b0fe478SBruce M Simpson  * the GCC manual doesn't appear to explicitly say that
825b0fe478SBruce M Simpson  * __attribute__((packed)) causes the compiler to generate unaligned-safe
835b0fe478SBruce M Simpson  * code, but it apppears to do so.
845b0fe478SBruce M Simpson  *
853c602fabSXin LI  * We do this in case the compiler can generate code using those
863c602fabSXin LI  * instructions to do an unaligned load and pass stuff to "ntohs()" or
873c602fabSXin LI  * "ntohl()", which might be better than than the code to fetch the
883c602fabSXin LI  * bytes one at a time and assemble them.  (That might not be the
893c602fabSXin LI  * case on a little-endian platform, such as DEC's MIPS machines and
903c602fabSXin LI  * Alpha machines, where "ntohs()" and "ntohl()" might not be done
913c602fabSXin LI  * inline.)
923c602fabSXin LI  *
933c602fabSXin LI  * We do this only for specific architectures because, for example,
943c602fabSXin LI  * at least some versions of GCC, when compiling for 64-bit SPARC,
953c602fabSXin LI  * generate code that assumes alignment if we do this.
963c602fabSXin LI  *
973c602fabSXin LI  * XXX - add other architectures and compilers as possible and
983c602fabSXin LI  * appropriate.
993c602fabSXin LI  *
1003c602fabSXin LI  * HP's C compiler, indicated by __HP_cc being defined, supports
1013c602fabSXin LI  * "#pragma unaligned N" in version A.05.50 and later, where "N"
1023c602fabSXin LI  * specifies a number of bytes at which the typedef on the next
1033c602fabSXin LI  * line is aligned, e.g.
1043c602fabSXin LI  *
1053c602fabSXin LI  *	#pragma unalign 1
1063c602fabSXin LI  *	typedef uint16_t unaligned_uint16_t;
1073c602fabSXin LI  *
1083c602fabSXin LI  * to define unaligned_uint16_t as a 16-bit unaligned data type.
1093c602fabSXin LI  * This could be presumably used, in sufficiently recent versions of
1103c602fabSXin LI  * the compiler, with macros similar to those below.  This would be
1113c602fabSXin LI  * useful only if that compiler could generate better code for PA-RISC
1123c602fabSXin LI  * or Itanium than would be generated by a bunch of shifts-and-ORs.
1133c602fabSXin LI  *
1143c602fabSXin LI  * DEC C, indicated by __DECC being defined, has, at least on Alpha,
1153c602fabSXin LI  * an __unaligned qualifier that can be applied to pointers to get the
1163c602fabSXin LI  * compiler to generate code that does unaligned loads and stores when
1173c602fabSXin LI  * dereferencing the pointer in question.
1183c602fabSXin LI  *
1193c602fabSXin LI  * XXX - what if the native C compiler doesn't support
1203c602fabSXin LI  * __attribute__((packed))?  How can we get it to generate unaligned
1213c602fabSXin LI  * accesses for *specific* items?
1225b0fe478SBruce M Simpson  */
1235b0fe478SBruce M Simpson typedef struct {
1243c602fabSXin LI 	uint16_t	val;
1253c602fabSXin LI } __attribute__((packed)) unaligned_uint16_t;
1265b0fe478SBruce M Simpson 
1275b0fe478SBruce M Simpson typedef struct {
1283c602fabSXin LI 	uint32_t	val;
1293c602fabSXin LI } __attribute__((packed)) unaligned_uint32_t;
1305b0fe478SBruce M Simpson 
131*0bff6a5aSEd Maste UNALIGNED_OK static inline uint16_t
132340b3427SPedro F. Giffuni EXTRACT_16BITS(const void *p)
133340b3427SPedro F. Giffuni {
1343c602fabSXin LI 	return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
135340b3427SPedro F. Giffuni }
136340b3427SPedro F. Giffuni 
137*0bff6a5aSEd Maste UNALIGNED_OK static inline uint32_t
138340b3427SPedro F. Giffuni EXTRACT_32BITS(const void *p)
139340b3427SPedro F. Giffuni {
1403c602fabSXin LI 	return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
141340b3427SPedro F. Giffuni }
142340b3427SPedro F. Giffuni 
143*0bff6a5aSEd Maste UNALIGNED_OK static inline uint64_t
144340b3427SPedro F. Giffuni EXTRACT_64BITS(const void *p)
145340b3427SPedro F. Giffuni {
1463340d773SGleb Smirnoff 	return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
1473c602fabSXin LI 		((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
148340b3427SPedro F. Giffuni }
1491de50e9fSSam Leffler 
1503c602fabSXin LI #else /* have to do it a byte at a time */
1515b0fe478SBruce M Simpson /*
1523c602fabSXin LI  * This isn't a GCC-compatible compiler, we don't have __attribute__,
1533c602fabSXin LI  * or we do but we don't know of any better way with this instruction
1543c602fabSXin LI  * set to do unaligned loads, so do unaligned loads of big-endian
1555b0fe478SBruce M Simpson  * quantities the hard way - fetch the bytes one at a time and
1565b0fe478SBruce M Simpson  * assemble them.
1575b0fe478SBruce M Simpson  */
1585b0fe478SBruce M Simpson #define EXTRACT_16BITS(p) \
1598bdc5a62SPatrick Kelsey 	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
1608bdc5a62SPatrick Kelsey 	            ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
1615b0fe478SBruce M Simpson #define EXTRACT_32BITS(p) \
1628bdc5a62SPatrick Kelsey 	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
1638bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
1648bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
1658bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
1661de50e9fSSam Leffler #define EXTRACT_64BITS(p) \
1678bdc5a62SPatrick Kelsey 	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
1688bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
1698bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
1708bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
1718bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
1728bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
1738bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
1748bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
1753c602fabSXin LI #endif /* must special-case unaligned accesses */
1765b0fe478SBruce M Simpson #else /* LBL_ALIGN */
1775b0fe478SBruce M Simpson /*
1785b0fe478SBruce M Simpson  * The processor natively handles unaligned loads, so we can just
1795b0fe478SBruce M Simpson  * cast the pointer and fetch through it.
1805b0fe478SBruce M Simpson  */
181*0bff6a5aSEd Maste static inline uint16_t UNALIGNED_OK
182340b3427SPedro F. Giffuni EXTRACT_16BITS(const void *p)
183340b3427SPedro F. Giffuni {
1843c602fabSXin LI 	return ((uint16_t)ntohs(*(const uint16_t *)(p)));
185340b3427SPedro F. Giffuni }
186340b3427SPedro F. Giffuni 
187*0bff6a5aSEd Maste static inline uint32_t UNALIGNED_OK
188340b3427SPedro F. Giffuni EXTRACT_32BITS(const void *p)
189340b3427SPedro F. Giffuni {
1903c602fabSXin LI 	return ((uint32_t)ntohl(*(const uint32_t *)(p)));
191340b3427SPedro F. Giffuni }
192340b3427SPedro F. Giffuni 
193*0bff6a5aSEd Maste static inline uint64_t UNALIGNED_OK
194340b3427SPedro F. Giffuni EXTRACT_64BITS(const void *p)
195340b3427SPedro F. Giffuni {
1963340d773SGleb Smirnoff 	return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
1973c602fabSXin LI 		((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
198340b3427SPedro F. Giffuni 
199340b3427SPedro F. Giffuni }
200340b3427SPedro F. Giffuni 
2015b0fe478SBruce M Simpson #endif /* LBL_ALIGN */
2024edb46e9SPaul Traina 
2034edb46e9SPaul Traina #define EXTRACT_24BITS(p) \
2048bdc5a62SPatrick Kelsey 	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
2058bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
2068bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
2073c602fabSXin LI 
2083c602fabSXin LI #define EXTRACT_40BITS(p) \
2098bdc5a62SPatrick Kelsey 	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
2108bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
2118bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
2128bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
2138bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
2143c602fabSXin LI 
2153c602fabSXin LI #define EXTRACT_48BITS(p) \
2168bdc5a62SPatrick Kelsey 	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
2178bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
2188bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
2198bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
2208bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
2218bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
2223c602fabSXin LI 
2233c602fabSXin LI #define EXTRACT_56BITS(p) \
2248bdc5a62SPatrick Kelsey 	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
2258bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
2268bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
2278bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
2288bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
2298bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
2308bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
2314edb46e9SPaul Traina 
2321de50e9fSSam Leffler /*
2331de50e9fSSam Leffler  * Macros to extract possibly-unaligned little-endian integral values.
2341de50e9fSSam Leffler  * XXX - do loads on little-endian machines that support unaligned loads?
2351de50e9fSSam Leffler  */
2364edb46e9SPaul Traina #define EXTRACT_LE_16BITS(p) \
2378bdc5a62SPatrick Kelsey 	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
2388bdc5a62SPatrick Kelsey 	            ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
2394edb46e9SPaul Traina #define EXTRACT_LE_32BITS(p) \
2408bdc5a62SPatrick Kelsey 	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
2418bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
2428bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
2438bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
244a5779b6eSRui Paulo #define EXTRACT_LE_24BITS(p) \
2458bdc5a62SPatrick Kelsey 	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
2468bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
2478bdc5a62SPatrick Kelsey 	            ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
2481de50e9fSSam Leffler #define EXTRACT_LE_64BITS(p) \
2498bdc5a62SPatrick Kelsey 	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
2508bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
2518bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
2528bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
2538bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
2548bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
2558bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
2568bdc5a62SPatrick Kelsey 	            ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
2573340d773SGleb Smirnoff 
2583340d773SGleb Smirnoff /*
2593340d773SGleb Smirnoff  * Macros to check the presence of the values in question.
2603340d773SGleb Smirnoff  */
2613340d773SGleb Smirnoff #define ND_TTEST_8BITS(p) ND_TTEST2(*(p), 1)
2623340d773SGleb Smirnoff #define ND_TCHECK_8BITS(p) ND_TCHECK2(*(p), 1)
2633340d773SGleb Smirnoff 
2643340d773SGleb Smirnoff #define ND_TTEST_16BITS(p) ND_TTEST2(*(p), 2)
2653340d773SGleb Smirnoff #define ND_TCHECK_16BITS(p) ND_TCHECK2(*(p), 2)
2663340d773SGleb Smirnoff 
2673340d773SGleb Smirnoff #define ND_TTEST_24BITS(p) ND_TTEST2(*(p), 3)
2683340d773SGleb Smirnoff #define ND_TCHECK_24BITS(p) ND_TCHECK2(*(p), 3)
2693340d773SGleb Smirnoff 
2703340d773SGleb Smirnoff #define ND_TTEST_32BITS(p) ND_TTEST2(*(p), 4)
2713340d773SGleb Smirnoff #define ND_TCHECK_32BITS(p) ND_TCHECK2(*(p), 4)
2723340d773SGleb Smirnoff 
2733340d773SGleb Smirnoff #define ND_TTEST_40BITS(p) ND_TTEST2(*(p), 5)
2743340d773SGleb Smirnoff #define ND_TCHECK_40BITS(p) ND_TCHECK2(*(p), 5)
2753340d773SGleb Smirnoff 
2763340d773SGleb Smirnoff #define ND_TTEST_48BITS(p) ND_TTEST2(*(p), 6)
2773340d773SGleb Smirnoff #define ND_TCHECK_48BITS(p) ND_TCHECK2(*(p), 6)
2783340d773SGleb Smirnoff 
2793340d773SGleb Smirnoff #define ND_TTEST_56BITS(p) ND_TTEST2(*(p), 7)
2803340d773SGleb Smirnoff #define ND_TCHECK_56BITS(p) ND_TCHECK2(*(p), 7)
2813340d773SGleb Smirnoff 
2823340d773SGleb Smirnoff #define ND_TTEST_64BITS(p) ND_TTEST2(*(p), 8)
2833340d773SGleb Smirnoff #define ND_TCHECK_64BITS(p) ND_TCHECK2(*(p), 8)
284*0bff6a5aSEd Maste 
285*0bff6a5aSEd Maste #define ND_TTEST_128BITS(p) ND_TTEST2(*(p), 16)
286*0bff6a5aSEd Maste #define ND_TCHECK_128BITS(p) ND_TCHECK2(*(p), 16)
287