patricia, trie: minor: do some cleanups
[netsniff-ng.git] / pcap.h
blobe1cd5b3bab759922ea8ba68d58393cce9309f1df
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009 - 2013 Daniel Borkmann.
5 * Copyright 2010 Emmanuel Roullit.
6 * Subject to the GPL, version 2.
7 */
9 #ifndef PCAP_H
10 #define PCAP_H
12 #include <unistd.h>
13 #include <stdint.h>
14 #include <stdbool.h>
15 #include <errno.h>
16 #include <sys/time.h>
17 #include <linux/if_packet.h>
19 #include "built_in.h"
20 #include "die.h"
21 #include "xio.h"
23 #define TCPDUMP_MAGIC 0xa1b2c3d4
24 #define ORIGINAL_TCPDUMP_MAGIC TCPDUMP_MAGIC
25 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
26 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
27 #define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
29 #define PCAP_VERSION_MAJOR 2
30 #define PCAP_VERSION_MINOR 4
31 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535
33 #define LINKTYPE_EN10MB 1 /* Ethernet (10Mb) */
34 #define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 wireless */
36 struct pcap_filehdr {
37 uint32_t magic;
38 uint16_t version_major;
39 uint16_t version_minor;
40 int32_t thiszone;
41 uint32_t sigfigs;
42 uint32_t snaplen;
43 uint32_t linktype;
46 struct pcap_timeval {
47 int32_t tv_sec;
48 int32_t tv_usec;
51 struct pcap_timeval_ns {
52 int32_t tv_sec;
53 int32_t tv_nsec;
56 struct pcap_pkthdr {
57 struct pcap_timeval ts;
58 uint32_t caplen;
59 uint32_t len;
62 struct pcap_pkthdr_ns {
63 struct pcap_timeval_ns ts;
64 uint32_t caplen;
65 uint32_t len;
68 struct pcap_pkthdr_kuz {
69 struct pcap_timeval ts;
70 uint32_t caplen;
71 uint32_t len;
72 int ifindex;
73 uint16_t protocol;
74 uint8_t pkttype;
77 struct pcap_pkthdr_bkm {
78 struct pcap_timeval_ns ts;
79 uint32_t caplen;
80 uint32_t len;
81 uint32_t ifindex;
82 uint16_t protocol;
83 uint8_t hatype;
84 uint8_t pkttype;
87 typedef union {
88 struct pcap_pkthdr ppo;
89 struct pcap_pkthdr_ns ppn;
90 struct pcap_pkthdr_kuz ppk;
91 struct pcap_pkthdr_bkm ppb;
92 } pcap_pkthdr_t;
94 enum pcap_type {
95 DEFAULT = ORIGINAL_TCPDUMP_MAGIC,
96 NSEC = NSEC_TCPDUMP_MAGIC,
97 KUZNETZOV = KUZNETZOV_TCPDUMP_MAGIC,
98 BORKMANN = BORKMANN_TCPDUMP_MAGIC,
101 enum pcap_ops_groups {
102 PCAP_OPS_RW = 0,
103 PCAP_OPS_SG,
104 PCAP_OPS_MM,
107 enum pcap_mode {
108 PCAP_MODE_RD = 0,
109 PCAP_MODE_WR,
112 struct pcap_file_ops {
113 int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
114 int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
115 int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
116 ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
117 const uint8_t *packet, size_t len);
118 ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
119 uint8_t *packet, size_t len);
120 void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
121 void (*fsync_pcap)(int fd);
124 extern const struct pcap_file_ops pcap_rw_ops;
125 extern const struct pcap_file_ops pcap_sg_ops;
126 extern const struct pcap_file_ops pcap_mm_ops;
128 static inline void pcap_check_magic(uint32_t magic)
130 switch (magic) {
131 case DEFAULT:
132 case NSEC:
133 case KUZNETZOV:
134 case BORKMANN:
135 break;
136 default:
137 panic("This file has not a valid pcap header\n");
141 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
143 switch (type) {
144 #define CASE_RET_CAPLEN(what, member) \
145 case (what): \
146 return phdr->member.caplen
147 CASE_RET_CAPLEN(DEFAULT, ppo);
148 CASE_RET_CAPLEN(NSEC, ppn);
149 CASE_RET_CAPLEN(KUZNETZOV, ppk);
150 CASE_RET_CAPLEN(BORKMANN, ppb);
151 default:
152 bug();
156 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
158 switch (type) {
159 #define CASE_SET_CAPLEN(what, member) \
160 case (what): \
161 phdr->member.caplen = len; \
162 break
163 CASE_SET_CAPLEN(DEFAULT, ppo);
164 CASE_SET_CAPLEN(NSEC, ppn);
165 CASE_SET_CAPLEN(KUZNETZOV, ppk);
166 CASE_SET_CAPLEN(BORKMANN, ppb);
167 default:
168 bug();
172 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
174 switch (type) {
175 #define CASE_RET_HDRLEN(what, member) \
176 case (what): \
177 return sizeof(phdr->member)
178 CASE_RET_HDRLEN(DEFAULT, ppo);
179 CASE_RET_HDRLEN(NSEC, ppn);
180 CASE_RET_HDRLEN(KUZNETZOV, ppk);
181 CASE_RET_HDRLEN(BORKMANN, ppb);
182 default:
183 bug();
187 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
189 switch (type) {
190 #define CASE_RET_TOTLEN(what, member) \
191 case (what): \
192 return phdr->member.caplen + sizeof(phdr->member)
193 CASE_RET_TOTLEN(DEFAULT, ppo);
194 CASE_RET_TOTLEN(NSEC, ppn);
195 CASE_RET_TOTLEN(KUZNETZOV, ppk);
196 CASE_RET_TOTLEN(BORKMANN, ppb);
197 default:
198 bug();
202 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
203 struct sockaddr_ll *sll,
204 pcap_pkthdr_t *phdr,
205 enum pcap_type type)
207 switch (type) {
208 case DEFAULT:
209 phdr->ppo.ts.tv_sec = thdr->tp_sec;
210 phdr->ppo.ts.tv_usec = thdr->tp_nsec / 1000;
211 phdr->ppo.caplen = thdr->tp_snaplen;
212 phdr->ppo.len = thdr->tp_len;
213 break;
215 case NSEC:
216 phdr->ppn.ts.tv_sec = thdr->tp_sec;
217 phdr->ppn.ts.tv_nsec = thdr->tp_nsec;
218 phdr->ppn.caplen = thdr->tp_snaplen;
219 phdr->ppn.len = thdr->tp_len;
220 break;
222 case KUZNETZOV:
223 phdr->ppk.ts.tv_sec = thdr->tp_sec;
224 phdr->ppk.ts.tv_usec = thdr->tp_nsec / 1000;
225 phdr->ppk.caplen = thdr->tp_snaplen;
226 phdr->ppk.len = thdr->tp_len;
227 phdr->ppk.ifindex = sll->sll_ifindex;
228 phdr->ppk.protocol = sll->sll_protocol;
229 phdr->ppk.pkttype = sll->sll_pkttype;
230 break;
232 case BORKMANN:
233 phdr->ppb.ts.tv_sec = thdr->tp_sec;
234 phdr->ppb.ts.tv_nsec = thdr->tp_nsec;
235 phdr->ppb.caplen = thdr->tp_snaplen;
236 phdr->ppb.len = thdr->tp_len;
237 phdr->ppb.ifindex = (u32) sll->sll_ifindex;
238 phdr->ppb.protocol = sll->sll_protocol;
239 phdr->ppb.hatype = sll->sll_hatype;
240 phdr->ppb.pkttype = sll->sll_pkttype;
241 break;
243 default:
244 bug();
248 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
249 enum pcap_type type,
250 struct tpacket2_hdr *thdr,
251 struct sockaddr_ll *sll)
253 switch (type) {
254 case DEFAULT:
255 thdr->tp_sec = phdr->ppo.ts.tv_sec;
256 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
257 thdr->tp_snaplen = phdr->ppo.caplen;
258 thdr->tp_len = phdr->ppo.len;
259 break;
261 case NSEC:
262 thdr->tp_sec = phdr->ppn.ts.tv_sec;
263 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
264 thdr->tp_snaplen = phdr->ppn.caplen;
265 thdr->tp_len = phdr->ppn.len;
266 break;
268 case KUZNETZOV:
269 thdr->tp_sec = phdr->ppk.ts.tv_sec;
270 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
271 thdr->tp_snaplen = phdr->ppk.caplen;
272 thdr->tp_len = phdr->ppk.len;
273 break;
275 case BORKMANN:
276 thdr->tp_sec = phdr->ppb.ts.tv_sec;
277 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
278 thdr->tp_snaplen = phdr->ppb.caplen;
279 thdr->tp_len = phdr->ppb.len;
280 break;
282 default:
283 bug();
287 #define FEATURE_UNKNOWN (0 << 0)
288 #define FEATURE_TIMEVAL_MS (1 << 0)
289 #define FEATURE_TIMEVAL_NS (1 << 1)
290 #define FEATURE_LEN (1 << 2)
291 #define FEATURE_CAPLEN (1 << 3)
292 #define FEATURE_IFINDEX (1 << 4)
293 #define FEATURE_PROTO (1 << 5)
294 #define FEATURE_HATYPE (1 << 6)
295 #define FEATURE_PKTTYPE (1 << 7)
297 struct pcap_magic_type {
298 uint32_t magic;
299 char *desc;
300 uint16_t features;
303 static const struct pcap_magic_type const pcap_magic_types[] __maybe_unused = {
305 .magic = ORIGINAL_TCPDUMP_MAGIC,
306 .desc = "tcpdump-capable pcap",
307 .features = FEATURE_TIMEVAL_MS |
308 FEATURE_LEN |
309 FEATURE_CAPLEN,
310 }, {
311 .magic = NSEC_TCPDUMP_MAGIC,
312 .desc = "tcpdump-capable pcap with ns resolution",
313 .features = FEATURE_TIMEVAL_NS |
314 FEATURE_LEN |
315 FEATURE_CAPLEN,
316 }, {
317 .magic = KUZNETZOV_TCPDUMP_MAGIC,
318 .desc = "Alexey Kuznetzov's pcap",
319 .features = FEATURE_TIMEVAL_MS |
320 FEATURE_LEN |
321 FEATURE_CAPLEN |
322 FEATURE_IFINDEX |
323 FEATURE_PROTO |
324 FEATURE_PKTTYPE,
325 }, {
326 .magic = BORKMANN_TCPDUMP_MAGIC,
327 .desc = "netsniff-ng pcap",
328 .features = FEATURE_TIMEVAL_NS |
329 FEATURE_LEN |
330 FEATURE_CAPLEN |
331 FEATURE_IFINDEX |
332 FEATURE_PROTO |
333 FEATURE_HATYPE |
334 FEATURE_PKTTYPE,
338 static inline void pcap_dump_type_features(void)
340 int i;
342 for (i = 0; i < array_size(pcap_magic_types); ++i) {
343 printf("%s:\n", pcap_magic_types[i].desc);
344 printf(" magic: 0x%x\n", pcap_magic_types[i].magic);
345 printf(" features:\n");
347 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
348 printf(" unknown\n");
349 continue;
352 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
353 printf(" timeval in us\n");
354 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
355 printf(" timeval in ns\n");
356 if (pcap_magic_types[i].features & FEATURE_LEN)
357 printf(" packet length\n");
358 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
359 printf(" packet cap-length\n");
360 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
361 printf(" packet ifindex\n");
362 if (pcap_magic_types[i].features & FEATURE_PROTO)
363 printf(" packet protocol\n");
364 if (pcap_magic_types[i].features & FEATURE_HATYPE)
365 printf(" hardware type\n");
366 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
367 printf(" packet type\n");
371 static const char *pcap_ops_group_to_str[] __maybe_unused = {
372 [PCAP_OPS_RW] = "rw",
373 [PCAP_OPS_SG] = "sg",
374 [PCAP_OPS_MM] = "mm",
377 static const struct pcap_file_ops const *pcap_ops[] __maybe_unused = {
378 [PCAP_OPS_RW] = &pcap_rw_ops,
379 [PCAP_OPS_SG] = &pcap_sg_ops,
380 [PCAP_OPS_MM] = &pcap_mm_ops,
383 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
384 uint32_t linktype, int32_t thiszone,
385 uint32_t snaplen)
387 hdr->magic = magic;
388 hdr->version_major = PCAP_VERSION_MAJOR;
389 hdr->version_minor = PCAP_VERSION_MINOR;
390 hdr->thiszone = thiszone;
391 hdr->sigfigs = 0;
392 hdr->snaplen = snaplen;
393 hdr->linktype = linktype;
396 static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
398 pcap_check_magic(hdr->magic);
400 switch (hdr->linktype) {
401 case LINKTYPE_EN10MB:
402 case LINKTYPE_IEEE802_11:
403 break;
404 default:
405 panic("This file has not a valid pcap header\n");
408 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR))
409 panic("This file has not a valid pcap header\n");
410 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR))
411 panic("This file has not a valid pcap header\n");
414 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
415 uint32_t *linktype) __maybe_unused;
417 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
419 ssize_t ret;
420 struct pcap_filehdr hdr;
422 ret = read(fd, &hdr, sizeof(hdr));
423 if (unlikely(ret != sizeof(hdr)))
424 return -EIO;
426 pcap_validate_header(&hdr);
428 *magic = hdr.magic;
429 *linktype = hdr.linktype;
431 return 0;
434 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
435 uint32_t linktype) __maybe_unused;
437 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
439 ssize_t ret;
440 struct pcap_filehdr hdr;
442 memset(&hdr, 0, sizeof(hdr));
444 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
446 ret = write_or_die(fd, &hdr, sizeof(hdr));
447 if (unlikely(ret != sizeof(hdr)))
448 panic("Failed to write pkt file header!\n");
450 return 0;
453 #endif /* PCAP_H */