Corrected spinning loop potential in getrandombytes
[netsniff-ng-old.git] / pcap_io.h
blobb2e6f03b60498d774da59d213ac768e595c4422f
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009 - 2013 Daniel Borkmann.
4 * Copyright 2010 Emmanuel Roullit.
5 * Subject to the GPL, version 2.
6 */
8 #ifndef PCAP_IO_H
9 #define PCAP_IO_H
11 #include <unistd.h>
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include <errno.h>
15 #include <sys/time.h>
16 #include <linux/if_packet.h>
18 #include "built_in.h"
19 #include "die.h"
20 #include "xio.h"
22 #define TCPDUMP_MAGIC 0xa1b2c3d4
23 #define ORIGINAL_TCPDUMP_MAGIC TCPDUMP_MAGIC
24 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
25 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
26 #define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
28 #define PCAP_VERSION_MAJOR 2
29 #define PCAP_VERSION_MINOR 4
30 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535
32 #define LINKTYPE_EN10MB 1 /* Ethernet (10Mb) */
33 #define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 wireless */
35 struct pcap_filehdr {
36 uint32_t magic;
37 uint16_t version_major;
38 uint16_t version_minor;
39 int32_t thiszone;
40 uint32_t sigfigs;
41 uint32_t snaplen;
42 uint32_t linktype;
45 struct pcap_timeval {
46 int32_t tv_sec;
47 int32_t tv_usec;
50 struct pcap_timeval_ns {
51 int32_t tv_sec;
52 int32_t tv_nsec;
55 struct pcap_pkthdr {
56 struct pcap_timeval ts;
57 uint32_t caplen;
58 uint32_t len;
61 struct pcap_pkthdr_ns {
62 struct pcap_timeval_ns ts;
63 uint32_t caplen;
64 uint32_t len;
67 struct pcap_pkthdr_kuz {
68 struct pcap_timeval ts;
69 uint32_t caplen;
70 uint32_t len;
71 int ifindex;
72 uint16_t protocol;
73 uint8_t pkttype;
76 struct pcap_pkthdr_bkm {
77 struct pcap_timeval_ns ts;
78 uint32_t caplen;
79 uint32_t len;
80 uint32_t ifindex;
81 uint16_t protocol;
82 uint8_t hatype;
83 uint8_t pkttype;
86 typedef union {
87 struct pcap_pkthdr ppo;
88 struct pcap_pkthdr_ns ppn;
89 struct pcap_pkthdr_kuz ppk;
90 struct pcap_pkthdr_bkm ppb;
91 uint8_t raw;
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,
100 DEFAULT_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
101 NSEC_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC),
102 KUZNETZOV_SWAPPED = ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
103 BORKMANN_SWAPPED = ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
106 enum pcap_ops_groups {
107 PCAP_OPS_RW = 0,
108 PCAP_OPS_SG,
109 PCAP_OPS_MM,
112 enum pcap_mode {
113 PCAP_MODE_RD = 0,
114 PCAP_MODE_WR,
117 struct pcap_file_ops {
118 int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
119 int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
120 int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
121 ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
122 const uint8_t *packet, size_t len);
123 ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
124 uint8_t *packet, size_t len);
125 void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
126 void (*fsync_pcap)(int fd);
129 extern const struct pcap_file_ops pcap_rw_ops;
130 extern const struct pcap_file_ops pcap_sg_ops;
131 extern const struct pcap_file_ops pcap_mm_ops;
133 static inline void pcap_check_magic(uint32_t magic)
135 switch (magic) {
137 case ORIGINAL_TCPDUMP_MAGIC:
138 case NSEC_TCPDUMP_MAGIC:
139 case KUZNETZOV_TCPDUMP_MAGIC:
140 case BORKMANN_TCPDUMP_MAGIC:
142 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
143 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
144 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
145 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
146 break;
148 default:
149 panic("This file has not a valid pcap header\n");
153 static inline bool pcap_magic_is_swapped(uint32_t magic)
155 bool swapped = false;
157 switch (magic) {
158 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
159 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
160 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
161 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
162 swapped = true;
165 return swapped;
168 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
170 switch (type) {
171 #define CASE_RET_CAPLEN(what, member, swap) \
172 case (what): \
173 return (swap ? ___constant_swab32(phdr->member.caplen) : \
174 phdr->member.caplen)
176 CASE_RET_CAPLEN(DEFAULT, ppo, 0);
177 CASE_RET_CAPLEN(NSEC, ppn, 0);
178 CASE_RET_CAPLEN(KUZNETZOV, ppk, 0);
179 CASE_RET_CAPLEN(BORKMANN, ppb, 0);
181 CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
182 CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1);
183 CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
184 CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
186 default:
187 bug();
191 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
193 switch (type) {
194 #define CASE_SET_CAPLEN(what, member, swap) \
195 case (what): \
196 phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
197 break
199 CASE_SET_CAPLEN(DEFAULT, ppo, 0);
200 CASE_SET_CAPLEN(NSEC, ppn, 0);
201 CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
202 CASE_SET_CAPLEN(BORKMANN, ppb, 0);
204 CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
205 CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
206 CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
207 CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
209 default:
210 bug();
214 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
216 switch (type) {
217 #define CASE_RET_HDRLEN(what, member) \
218 case (what): \
219 return sizeof(phdr->member)
221 CASE_RET_HDRLEN(DEFAULT, ppo);
222 CASE_RET_HDRLEN(NSEC, ppn);
223 CASE_RET_HDRLEN(KUZNETZOV, ppk);
224 CASE_RET_HDRLEN(BORKMANN, ppb);
226 CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
227 CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
228 CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
229 CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
231 default:
232 bug();
236 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
238 switch (type) {
239 #define CASE_RET_TOTLEN(what, member, swap) \
240 case (what): \
241 return ((swap ? ___constant_swab32(phdr->member.caplen) : \
242 phdr->member.caplen) + sizeof(phdr->member))
244 CASE_RET_TOTLEN(DEFAULT, ppo, 0);
245 CASE_RET_TOTLEN(NSEC, ppn, 0);
246 CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
247 CASE_RET_TOTLEN(BORKMANN, ppb, 0);
249 CASE_RET_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
250 CASE_RET_TOTLEN(NSEC_SWAPPED, ppn, 1);
251 CASE_RET_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
252 CASE_RET_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
254 default:
255 bug();
259 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
260 struct sockaddr_ll *sll,
261 pcap_pkthdr_t *phdr,
262 enum pcap_type type)
264 switch (type) {
265 case DEFAULT:
266 phdr->ppo.ts.tv_sec = thdr->tp_sec;
267 phdr->ppo.ts.tv_usec = thdr->tp_nsec / 1000;
268 phdr->ppo.caplen = thdr->tp_snaplen;
269 phdr->ppo.len = thdr->tp_len;
270 break;
272 case DEFAULT_SWAPPED:
273 phdr->ppo.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
274 phdr->ppo.ts.tv_usec = ___constant_swab32(thdr->tp_nsec / 1000);
275 phdr->ppo.caplen = ___constant_swab32(thdr->tp_snaplen);
276 phdr->ppo.len = ___constant_swab32(thdr->tp_len);
277 break;
279 case NSEC:
280 phdr->ppn.ts.tv_sec = thdr->tp_sec;
281 phdr->ppn.ts.tv_nsec = thdr->tp_nsec;
282 phdr->ppn.caplen = thdr->tp_snaplen;
283 phdr->ppn.len = thdr->tp_len;
284 break;
286 case NSEC_SWAPPED:
287 phdr->ppn.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
288 phdr->ppn.ts.tv_nsec = ___constant_swab32(thdr->tp_nsec);
289 phdr->ppn.caplen = ___constant_swab32(thdr->tp_snaplen);
290 phdr->ppn.len = ___constant_swab32(thdr->tp_len);
291 break;
293 case KUZNETZOV:
294 phdr->ppk.ts.tv_sec = thdr->tp_sec;
295 phdr->ppk.ts.tv_usec = thdr->tp_nsec / 1000;
296 phdr->ppk.caplen = thdr->tp_snaplen;
297 phdr->ppk.len = thdr->tp_len;
298 phdr->ppk.ifindex = sll->sll_ifindex;
299 phdr->ppk.protocol = sll->sll_protocol;
300 phdr->ppk.pkttype = sll->sll_pkttype;
301 break;
303 case KUZNETZOV_SWAPPED:
304 phdr->ppk.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
305 phdr->ppk.ts.tv_usec = ___constant_swab32(thdr->tp_nsec / 1000);
306 phdr->ppk.caplen = ___constant_swab32(thdr->tp_snaplen);
307 phdr->ppk.len = ___constant_swab32(thdr->tp_len);
308 phdr->ppk.ifindex = ___constant_swab32((u32) sll->sll_ifindex);
309 phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
310 phdr->ppk.pkttype = sll->sll_pkttype;
311 break;
313 case BORKMANN:
314 phdr->ppb.ts.tv_sec = thdr->tp_sec;
315 phdr->ppb.ts.tv_nsec = thdr->tp_nsec;
316 phdr->ppb.caplen = thdr->tp_snaplen;
317 phdr->ppb.len = thdr->tp_len;
318 phdr->ppb.ifindex = (u32) sll->sll_ifindex;
319 phdr->ppb.protocol = sll->sll_protocol;
320 phdr->ppb.hatype = sll->sll_hatype;
321 phdr->ppb.pkttype = sll->sll_pkttype;
322 break;
324 case BORKMANN_SWAPPED:
325 phdr->ppb.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
326 phdr->ppb.ts.tv_nsec = ___constant_swab32(thdr->tp_nsec);
327 phdr->ppb.caplen = ___constant_swab32(thdr->tp_snaplen);
328 phdr->ppb.len = ___constant_swab32(thdr->tp_len);
329 phdr->ppb.ifindex = ___constant_swab32((u32) sll->sll_ifindex);
330 phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
331 phdr->ppb.hatype = sll->sll_hatype;
332 phdr->ppb.pkttype = sll->sll_pkttype;
333 break;
335 default:
336 bug();
340 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
341 enum pcap_type type,
342 struct tpacket2_hdr *thdr,
343 struct sockaddr_ll *sll)
345 switch (type) {
346 case DEFAULT:
347 thdr->tp_sec = phdr->ppo.ts.tv_sec;
348 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
349 thdr->tp_snaplen = phdr->ppo.caplen;
350 thdr->tp_len = phdr->ppo.len;
351 break;
353 case DEFAULT_SWAPPED:
354 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
355 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
356 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
357 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
358 break;
360 case NSEC:
361 thdr->tp_sec = phdr->ppn.ts.tv_sec;
362 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
363 thdr->tp_snaplen = phdr->ppn.caplen;
364 thdr->tp_len = phdr->ppn.len;
365 break;
367 case NSEC_SWAPPED:
368 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
369 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
370 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
371 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
372 break;
374 case KUZNETZOV:
375 thdr->tp_sec = phdr->ppk.ts.tv_sec;
376 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
377 thdr->tp_snaplen = phdr->ppk.caplen;
378 thdr->tp_len = phdr->ppk.len;
379 break;
381 case KUZNETZOV_SWAPPED:
382 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
383 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
384 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
385 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
386 break;
388 case BORKMANN:
389 thdr->tp_sec = phdr->ppb.ts.tv_sec;
390 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
391 thdr->tp_snaplen = phdr->ppb.caplen;
392 thdr->tp_len = phdr->ppb.len;
393 break;
395 case BORKMANN_SWAPPED:
396 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
397 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
398 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
399 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
400 break;
402 default:
403 bug();
407 #define FEATURE_UNKNOWN (0 << 0)
408 #define FEATURE_TIMEVAL_MS (1 << 0)
409 #define FEATURE_TIMEVAL_NS (1 << 1)
410 #define FEATURE_LEN (1 << 2)
411 #define FEATURE_CAPLEN (1 << 3)
412 #define FEATURE_IFINDEX (1 << 4)
413 #define FEATURE_PROTO (1 << 5)
414 #define FEATURE_HATYPE (1 << 6)
415 #define FEATURE_PKTTYPE (1 << 7)
417 struct pcap_magic_type {
418 uint32_t magic;
419 char *desc;
420 uint16_t features;
423 static const struct pcap_magic_type const pcap_magic_types[] __maybe_unused = {
425 .magic = ORIGINAL_TCPDUMP_MAGIC,
426 .desc = "tcpdump-capable pcap",
427 .features = FEATURE_TIMEVAL_MS |
428 FEATURE_LEN |
429 FEATURE_CAPLEN,
430 }, {
431 .magic = NSEC_TCPDUMP_MAGIC,
432 .desc = "tcpdump-capable pcap with ns resolution",
433 .features = FEATURE_TIMEVAL_NS |
434 FEATURE_LEN |
435 FEATURE_CAPLEN,
436 }, {
437 .magic = KUZNETZOV_TCPDUMP_MAGIC,
438 .desc = "Alexey Kuznetzov's pcap",
439 .features = FEATURE_TIMEVAL_MS |
440 FEATURE_LEN |
441 FEATURE_CAPLEN |
442 FEATURE_IFINDEX |
443 FEATURE_PROTO |
444 FEATURE_PKTTYPE,
445 }, {
446 .magic = BORKMANN_TCPDUMP_MAGIC,
447 .desc = "netsniff-ng pcap",
448 .features = FEATURE_TIMEVAL_NS |
449 FEATURE_LEN |
450 FEATURE_CAPLEN |
451 FEATURE_IFINDEX |
452 FEATURE_PROTO |
453 FEATURE_HATYPE |
454 FEATURE_PKTTYPE,
458 static inline void pcap_dump_type_features(void)
460 int i;
462 for (i = 0; i < array_size(pcap_magic_types); ++i) {
463 printf("%s:\n", pcap_magic_types[i].desc);
464 printf(" magic: 0x%x (swapped: 0x%x)\n",
465 pcap_magic_types[i].magic,
466 ___constant_swab32(pcap_magic_types[i].magic));
467 printf(" features:\n");
469 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
470 printf(" unknown\n");
471 continue;
474 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
475 printf(" timeval in us\n");
476 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
477 printf(" timeval in ns\n");
478 if (pcap_magic_types[i].features & FEATURE_LEN)
479 printf(" packet length\n");
480 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
481 printf(" packet cap-length\n");
482 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
483 printf(" packet ifindex\n");
484 if (pcap_magic_types[i].features & FEATURE_PROTO)
485 printf(" packet protocol\n");
486 if (pcap_magic_types[i].features & FEATURE_HATYPE)
487 printf(" hardware type\n");
488 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
489 printf(" packet type\n");
493 static const char *pcap_ops_group_to_str[] __maybe_unused = {
494 [PCAP_OPS_RW] = "rw",
495 [PCAP_OPS_SG] = "sg",
496 [PCAP_OPS_MM] = "mm",
499 static const struct pcap_file_ops const *pcap_ops[] __maybe_unused = {
500 [PCAP_OPS_RW] = &pcap_rw_ops,
501 [PCAP_OPS_SG] = &pcap_sg_ops,
502 [PCAP_OPS_MM] = &pcap_mm_ops,
505 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
506 uint32_t linktype, int32_t thiszone,
507 uint32_t snaplen)
509 bool swapped = pcap_magic_is_swapped(magic);
511 hdr->magic = magic;
512 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
513 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
514 hdr->thiszone = swapped ? ___constant_swab32(thiszone) : thiszone;
515 hdr->sigfigs = 0;
516 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
517 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
520 static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
522 pcap_check_magic(hdr->magic);
524 switch (hdr->linktype) {
525 case LINKTYPE_EN10MB:
526 case LINKTYPE_IEEE802_11:
527 case ___constant_swab32(LINKTYPE_EN10MB):
528 case ___constant_swab32(LINKTYPE_IEEE802_11):
529 break;
530 default:
531 panic("This file has not a valid pcap header\n");
534 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
535 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
536 panic("This file has not a valid pcap header\n");
537 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
538 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
539 panic("This file has not a valid pcap header\n");
542 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
543 uint32_t *linktype) __maybe_unused;
545 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
547 ssize_t ret;
548 struct pcap_filehdr hdr;
550 ret = read(fd, &hdr, sizeof(hdr));
551 if (unlikely(ret != sizeof(hdr)))
552 return -EIO;
554 pcap_validate_header(&hdr);
556 *magic = hdr.magic;
557 *linktype = hdr.linktype;
559 return 0;
562 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
563 uint32_t linktype) __maybe_unused;
565 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
567 ssize_t ret;
568 struct pcap_filehdr hdr;
570 memset(&hdr, 0, sizeof(hdr));
572 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
574 ret = write_or_die(fd, &hdr, sizeof(hdr));
575 if (unlikely(ret != sizeof(hdr)))
576 panic("Failed to write pkt file header!\n");
578 return 0;
581 #endif /* PCAP_IO_H */