/src/libpcap-1.9.1/extract.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 1992, 1993, 1994, 1995, 1996 |
3 | | * The Regents of the University of California. All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that: (1) source code distributions |
7 | | * retain the above copyright notice and this paragraph in its entirety, (2) |
8 | | * distributions including binary code include the above copyright notice and |
9 | | * this paragraph in its entirety in the documentation or other materials |
10 | | * provided with the distribution, and (3) all advertising materials mentioning |
11 | | * features or use of this software display the following acknowledgement: |
12 | | * ``This product includes software developed by the University of California, |
13 | | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
14 | | * the University nor the names of its contributors may be used to endorse |
15 | | * or promote products derived from this software without specific prior |
16 | | * written permission. |
17 | | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
18 | | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
19 | | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
20 | | */ |
21 | | |
22 | | #ifndef _WIN32 |
23 | | #include <arpa/inet.h> |
24 | | #endif |
25 | | |
26 | | #include <pcap/pcap-inttypes.h> |
27 | | #include <pcap/compiler-tests.h> |
28 | | |
29 | | /* |
30 | | * Macros to extract possibly-unaligned big-endian integral values. |
31 | | */ |
32 | | #ifdef LBL_ALIGN |
33 | | /* |
34 | | * The processor doesn't natively handle unaligned loads. |
35 | | */ |
36 | | #if PCAP_IS_AT_LEAST_GNUC_VERSION(2,0) && \ |
37 | | (defined(__alpha) || defined(__alpha__) || \ |
38 | | defined(__mips) || defined(__mips__)) |
39 | | /* |
40 | | * This is MIPS or Alpha, which don't natively handle unaligned loads, |
41 | | * but which have instructions that can help when doing unaligned |
42 | | * loads, and this is GCC 2.0 or later or a compiler that claims to |
43 | | * be GCC 2.0 or later, which we assume that mean we have |
44 | | * __attribute__((packed)), which we can use to convince the compiler |
45 | | * to generate those instructions. |
46 | | * |
47 | | * Declare packed structures containing a uint16_t and a uint32_t, |
48 | | * cast the pointer to point to one of those, and fetch through it; |
49 | | * the GCC manual doesn't appear to explicitly say that |
50 | | * __attribute__((packed)) causes the compiler to generate unaligned-safe |
51 | | * code, but it apppears to do so. |
52 | | * |
53 | | * We do this in case the compiler can generate code using those |
54 | | * instructions to do an unaligned load and pass stuff to "ntohs()" or |
55 | | * "ntohl()", which might be better than than the code to fetch the |
56 | | * bytes one at a time and assemble them. (That might not be the |
57 | | * case on a little-endian platform, such as DEC's MIPS machines and |
58 | | * Alpha machines, where "ntohs()" and "ntohl()" might not be done |
59 | | * inline.) |
60 | | * |
61 | | * We do this only for specific architectures because, for example, |
62 | | * at least some versions of GCC, when compiling for 64-bit SPARC, |
63 | | * generate code that assumes alignment if we do this. |
64 | | * |
65 | | * XXX - add other architectures and compilers as possible and |
66 | | * appropriate. |
67 | | * |
68 | | * HP's C compiler, indicated by __HP_cc being defined, supports |
69 | | * "#pragma unaligned N" in version A.05.50 and later, where "N" |
70 | | * specifies a number of bytes at which the typedef on the next |
71 | | * line is aligned, e.g. |
72 | | * |
73 | | * #pragma unalign 1 |
74 | | * typedef uint16_t unaligned_uint16_t; |
75 | | * |
76 | | * to define unaligned_uint16_t as a 16-bit unaligned data type. |
77 | | * This could be presumably used, in sufficiently recent versions of |
78 | | * the compiler, with macros similar to those below. This would be |
79 | | * useful only if that compiler could generate better code for PA-RISC |
80 | | * or Itanium than would be generated by a bunch of shifts-and-ORs. |
81 | | * |
82 | | * DEC C, indicated by __DECC being defined, has, at least on Alpha, |
83 | | * an __unaligned qualifier that can be applied to pointers to get the |
84 | | * compiler to generate code that does unaligned loads and stores when |
85 | | * dereferencing the pointer in question. |
86 | | * |
87 | | * XXX - what if the native C compiler doesn't support |
88 | | * __attribute__((packed))? How can we get it to generate unaligned |
89 | | * accesses for *specific* items? |
90 | | */ |
91 | | typedef struct { |
92 | | uint16_t val; |
93 | | } __attribute__((packed)) unaligned_uint16_t; |
94 | | |
95 | | typedef struct { |
96 | | uint32_t val; |
97 | | } __attribute__((packed)) unaligned_uint32_t; |
98 | | |
99 | | static inline uint16_t |
100 | | EXTRACT_16BITS(const void *p) |
101 | | { |
102 | | return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val)); |
103 | | } |
104 | | |
105 | | static inline uint32_t |
106 | | EXTRACT_32BITS(const void *p) |
107 | | { |
108 | | return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val)); |
109 | | } |
110 | | |
111 | | static inline uint64_t |
112 | | EXTRACT_64BITS(const void *p) |
113 | | { |
114 | | return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \ |
115 | | ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0)); |
116 | | } |
117 | | |
118 | | #else /* have to do it a byte at a time */ |
119 | | /* |
120 | | * This isn't a GCC-compatible compiler, we don't have __attribute__, |
121 | | * or we do but we don't know of any better way with this instruction |
122 | | * set to do unaligned loads, so do unaligned loads of big-endian |
123 | | * quantities the hard way - fetch the bytes one at a time and |
124 | | * assemble them. |
125 | | */ |
126 | | #define EXTRACT_16BITS(p) \ |
127 | | ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \ |
128 | | ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0))) |
129 | | #define EXTRACT_32BITS(p) \ |
130 | | ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \ |
131 | | ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \ |
132 | | ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \ |
133 | | ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0))) |
134 | | #define EXTRACT_64BITS(p) \ |
135 | | ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \ |
136 | | ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \ |
137 | | ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \ |
138 | | ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \ |
139 | | ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \ |
140 | | ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \ |
141 | | ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \ |
142 | | ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0))) |
143 | | #endif /* must special-case unaligned accesses */ |
144 | | #else /* LBL_ALIGN */ |
145 | | /* |
146 | | * The processor natively handles unaligned loads, so we can just |
147 | | * cast the pointer and fetch through it. |
148 | | */ |
149 | | static inline uint16_t |
150 | | EXTRACT_16BITS(const void *p) |
151 | 852 | { |
152 | 852 | return ((uint16_t)ntohs(*(const uint16_t *)(p))); |
153 | 852 | } Unexecuted instantiation: gencode.c:EXTRACT_16BITS pcap-common.c:EXTRACT_16BITS Line | Count | Source | 151 | 852 | { | 152 | 852 | return ((uint16_t)ntohs(*(const uint16_t *)(p))); | 153 | 852 | } |
|
154 | | |
155 | | static inline uint32_t |
156 | | EXTRACT_32BITS(const void *p) |
157 | 0 | { |
158 | 0 | return ((uint32_t)ntohl(*(const uint32_t *)(p))); |
159 | 0 | } Unexecuted instantiation: gencode.c:EXTRACT_32BITS Unexecuted instantiation: pcap-common.c:EXTRACT_32BITS |
160 | | |
161 | | static inline uint64_t |
162 | | EXTRACT_64BITS(const void *p) |
163 | 0 | { |
164 | 0 | return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \ |
165 | 0 | ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0)); |
166 | 0 |
|
167 | 0 | } Unexecuted instantiation: gencode.c:EXTRACT_64BITS Unexecuted instantiation: pcap-common.c:EXTRACT_64BITS |
168 | | |
169 | | #endif /* LBL_ALIGN */ |
170 | | |
171 | | #define EXTRACT_24BITS(p) \ |
172 | | ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \ |
173 | | ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \ |
174 | | ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0))) |
175 | | |
176 | | #define EXTRACT_40BITS(p) \ |
177 | | ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \ |
178 | | ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \ |
179 | | ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \ |
180 | | ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \ |
181 | | ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0))) |
182 | | |
183 | | #define EXTRACT_48BITS(p) \ |
184 | | ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \ |
185 | | ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \ |
186 | | ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \ |
187 | | ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \ |
188 | | ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \ |
189 | | ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0))) |
190 | | |
191 | | #define EXTRACT_56BITS(p) \ |
192 | | ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \ |
193 | | ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \ |
194 | | ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \ |
195 | | ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \ |
196 | | ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \ |
197 | | ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \ |
198 | | ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0))) |
199 | | |
200 | | /* |
201 | | * Macros to extract possibly-unaligned little-endian integral values. |
202 | | * XXX - do loads on little-endian machines that support unaligned loads? |
203 | | */ |
204 | | #define EXTRACT_LE_8BITS(p) (*(p)) |
205 | | #define EXTRACT_LE_16BITS(p) \ |
206 | | ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \ |
207 | | ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0))) |
208 | | #define EXTRACT_LE_32BITS(p) \ |
209 | | ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \ |
210 | | ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \ |
211 | | ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \ |
212 | | ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0))) |
213 | | #define EXTRACT_LE_24BITS(p) \ |
214 | | ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \ |
215 | | ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \ |
216 | | ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0))) |
217 | | #define EXTRACT_LE_64BITS(p) \ |
218 | | ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \ |
219 | | ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \ |
220 | | ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \ |
221 | | ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \ |
222 | | ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \ |
223 | | ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \ |
224 | | ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \ |
225 | | ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0))) |