build: Rename LD command variable to LDQ
[netsniff-ng.git] / pcap_io.h
blob35faa51eefefeeedc3b2a439e02c8668ca99c62c
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 <sys/socket.h>
17 #include <linux/if.h>
18 #include <linux/if_packet.h>
19 #include <linux/if_arp.h>
21 #include "built_in.h"
22 #include "die.h"
23 #include "dev.h"
24 #include "ioops.h"
25 #include "linktype.h"
27 #define TCPDUMP_MAGIC 0xa1b2c3d4
28 #define ORIGINAL_TCPDUMP_MAGIC TCPDUMP_MAGIC
29 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
30 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
31 #define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
33 #define PCAP_VERSION_MAJOR 2
34 #define PCAP_VERSION_MINOR 4
35 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535
37 #define PCAP_TSOURCE_SOFTWARE 1
38 #define PCAP_TSOURCE_SYS_HARDWARE 2
39 #define PCAP_TSOURCE_RAW_HARDWARE 3
41 struct pcap_filehdr {
42 uint32_t magic;
43 uint16_t version_major;
44 uint16_t version_minor;
45 int32_t thiszone;
46 uint32_t sigfigs;
47 uint32_t snaplen;
48 uint32_t linktype;
51 struct pcap_timeval {
52 int32_t tv_sec;
53 int32_t tv_usec;
56 struct pcap_timeval_ns {
57 int32_t tv_sec;
58 int32_t tv_nsec;
61 struct pcap_pkthdr {
62 struct pcap_timeval ts;
63 uint32_t caplen;
64 uint32_t len;
67 struct pcap_pkthdr_ns {
68 struct pcap_timeval_ns ts;
69 uint32_t caplen;
70 uint32_t len;
73 struct pcap_pkthdr_kuz {
74 struct pcap_timeval ts;
75 uint32_t caplen;
76 uint32_t len;
77 uint32_t ifindex;
78 uint16_t protocol;
79 uint8_t pkttype;
82 struct pcap_pkthdr_bkm {
83 struct pcap_timeval_ns ts;
84 uint32_t caplen;
85 uint32_t len;
86 uint16_t tsource;
87 uint16_t ifindex;
88 uint16_t protocol;
89 uint8_t hatype;
90 uint8_t pkttype;
93 typedef union {
94 struct pcap_pkthdr ppo;
95 struct pcap_pkthdr_ns ppn;
96 struct pcap_pkthdr_kuz ppk;
97 struct pcap_pkthdr_bkm ppb;
98 uint8_t raw;
99 } pcap_pkthdr_t;
101 enum pcap_type {
102 DEFAULT = ORIGINAL_TCPDUMP_MAGIC,
103 NSEC = NSEC_TCPDUMP_MAGIC,
104 KUZNETZOV = KUZNETZOV_TCPDUMP_MAGIC,
105 BORKMANN = BORKMANN_TCPDUMP_MAGIC,
107 DEFAULT_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
108 NSEC_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC),
109 KUZNETZOV_SWAPPED = ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
110 BORKMANN_SWAPPED = ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
113 enum pcap_ops_groups {
114 PCAP_OPS_RW = 0,
115 PCAP_OPS_SG,
116 PCAP_OPS_MM,
119 enum pcap_mode {
120 PCAP_MODE_RD = 0,
121 PCAP_MODE_WR,
124 struct pcap_file_ops {
125 void (*init_once_pcap)(bool enforce_prio);
126 int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
127 int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
128 int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
129 ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
130 const uint8_t *packet, size_t len);
131 ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
132 uint8_t *packet, size_t len);
133 void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
134 void (*fsync_pcap)(int fd);
137 extern const struct pcap_file_ops pcap_rw_ops __maybe_unused;
138 extern const struct pcap_file_ops pcap_sg_ops __maybe_unused;
139 extern const struct pcap_file_ops pcap_mm_ops __maybe_unused;
141 static inline uint16_t tp_to_pcap_tsource(uint32_t status)
143 if (status & TP_STATUS_TS_RAW_HARDWARE)
144 return PCAP_TSOURCE_RAW_HARDWARE;
145 else if (status & TP_STATUS_TS_SYS_HARDWARE)
146 return PCAP_TSOURCE_SYS_HARDWARE;
147 else if (status & TP_STATUS_TS_SOFTWARE)
148 return PCAP_TSOURCE_SOFTWARE;
149 else
150 return 0;
153 static inline int pcap_devtype_to_linktype(const char *ifname)
155 switch (device_type(ifname)) {
156 case ARPHRD_TUNNEL:
157 case ARPHRD_TUNNEL6:
158 case ARPHRD_LOOPBACK:
159 case ARPHRD_SIT:
160 case ARPHRD_IPDDP:
161 case ARPHRD_IPGRE:
162 case ARPHRD_IP6GRE:
163 case ARPHRD_ETHER: return LINKTYPE_EN10MB;
164 case ARPHRD_IEEE80211_RADIOTAP: return LINKTYPE_IEEE802_11_RADIOTAP;
165 case ARPHRD_IEEE80211_PRISM:
166 case ARPHRD_IEEE80211: return LINKTYPE_IEEE802_11;
167 case ARPHRD_NETLINK: return LINKTYPE_NETLINK;
168 case ARPHRD_EETHER: return LINKTYPE_EN3MB;
169 case ARPHRD_AX25: return LINKTYPE_AX25;
170 case ARPHRD_CHAOS: return LINKTYPE_CHAOS;
171 case ARPHRD_PRONET: return LINKTYPE_PRONET;
172 case ARPHRD_IEEE802_TR:
173 case ARPHRD_IEEE802: return LINKTYPE_IEEE802;
174 case ARPHRD_INFINIBAND: return LINKTYPE_INFINIBAND;
175 case ARPHRD_ATM: return LINKTYPE_ATM_CLIP;
176 case ARPHRD_DLCI: return LINKTYPE_FRELAY;
177 case ARPHRD_ARCNET: return LINKTYPE_ARCNET_LINUX;
178 case ARPHRD_CSLIP:
179 case ARPHRD_CSLIP6:
180 case ARPHRD_SLIP6:
181 case ARPHRD_SLIP: return LINKTYPE_SLIP;
182 case ARPHRD_PPP: return LINKTYPE_PPP;
183 case ARPHRD_CAN: return LINKTYPE_CAN20B;
184 case ARPHRD_ECONET: return LINKTYPE_ECONET;
185 case ARPHRD_RAWHDLC:
186 case ARPHRD_CISCO: return LINKTYPE_C_HDLC;
187 case ARPHRD_FDDI: return LINKTYPE_FDDI;
188 case ARPHRD_IEEE802154_MONITOR:
189 case ARPHRD_IEEE802154: return LINKTYPE_IEEE802_15_4_LINUX;
190 case ARPHRD_IRDA: return LINKTYPE_LINUX_IRDA;
191 default: return LINKTYPE_NULL;
195 static inline void pcap_check_magic(uint32_t magic)
197 switch (magic) {
199 case ORIGINAL_TCPDUMP_MAGIC:
200 case NSEC_TCPDUMP_MAGIC:
201 case KUZNETZOV_TCPDUMP_MAGIC:
202 case BORKMANN_TCPDUMP_MAGIC:
204 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
205 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
206 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
207 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
208 break;
210 default:
211 panic("This file has not a valid pcap header\n");
215 static inline bool pcap_magic_is_swapped(uint32_t magic)
217 bool swapped = false;
219 switch (magic) {
220 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
221 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
222 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
223 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
224 swapped = true;
227 return swapped;
230 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
232 switch (type) {
233 #define CASE_RET_CAPLEN(what, member, swap) \
234 case (what): \
235 return (swap ? ___constant_swab32(phdr->member.caplen) : \
236 phdr->member.caplen)
238 CASE_RET_CAPLEN(DEFAULT, ppo, 0);
239 CASE_RET_CAPLEN(NSEC, ppn, 0);
240 CASE_RET_CAPLEN(KUZNETZOV, ppk, 0);
241 CASE_RET_CAPLEN(BORKMANN, ppb, 0);
243 CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
244 CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1);
245 CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
246 CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
248 default:
249 bug();
253 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
255 switch (type) {
256 #define CASE_SET_CAPLEN(what, member, swap) \
257 case (what): \
258 phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
259 break
261 CASE_SET_CAPLEN(DEFAULT, ppo, 0);
262 CASE_SET_CAPLEN(NSEC, ppn, 0);
263 CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
264 CASE_SET_CAPLEN(BORKMANN, ppb, 0);
266 CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
267 CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
268 CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
269 CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
271 default:
272 bug();
276 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
278 switch (type) {
279 #define CASE_RET_HDRLEN(what, member) \
280 case (what): \
281 return sizeof(phdr->member)
283 CASE_RET_HDRLEN(DEFAULT, ppo);
284 CASE_RET_HDRLEN(NSEC, ppn);
285 CASE_RET_HDRLEN(KUZNETZOV, ppk);
286 CASE_RET_HDRLEN(BORKMANN, ppb);
288 CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
289 CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
290 CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
291 CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
293 default:
294 bug();
298 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
300 switch (type) {
301 #define CASE_RET_TOTLEN(what, member, swap) \
302 case (what): \
303 return ((swap ? ___constant_swab32(phdr->member.caplen) : \
304 phdr->member.caplen) + sizeof(phdr->member))
306 CASE_RET_TOTLEN(DEFAULT, ppo, 0);
307 CASE_RET_TOTLEN(NSEC, ppn, 0);
308 CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
309 CASE_RET_TOTLEN(BORKMANN, ppb, 0);
311 CASE_RET_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
312 CASE_RET_TOTLEN(NSEC_SWAPPED, ppn, 1);
313 CASE_RET_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
314 CASE_RET_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
316 default:
317 bug();
321 static inline void
322 __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, uint32_t snaplen,
323 uint32_t len, uint32_t status,
324 struct sockaddr_ll *sll, pcap_pkthdr_t *phdr,
325 enum pcap_type type)
327 switch (type) {
328 case DEFAULT:
329 phdr->ppo.ts.tv_sec = sec;
330 phdr->ppo.ts.tv_usec = nsec / 1000;
331 phdr->ppo.caplen = snaplen;
332 phdr->ppo.len = len;
333 break;
335 case DEFAULT_SWAPPED:
336 phdr->ppo.ts.tv_sec = ___constant_swab32(sec);
337 phdr->ppo.ts.tv_usec = ___constant_swab32(nsec / 1000);
338 phdr->ppo.caplen = ___constant_swab32(snaplen);
339 phdr->ppo.len = ___constant_swab32(len);
340 break;
342 case NSEC:
343 phdr->ppn.ts.tv_sec = sec;
344 phdr->ppn.ts.tv_nsec = nsec;
345 phdr->ppn.caplen = snaplen;
346 phdr->ppn.len = len;
347 break;
349 case NSEC_SWAPPED:
350 phdr->ppn.ts.tv_sec = ___constant_swab32(sec);
351 phdr->ppn.ts.tv_nsec = ___constant_swab32(nsec);
352 phdr->ppn.caplen = ___constant_swab32(snaplen);
353 phdr->ppn.len = ___constant_swab32(len);
354 break;
356 case KUZNETZOV:
357 phdr->ppk.ts.tv_sec = sec;
358 phdr->ppk.ts.tv_usec = nsec / 1000;
359 phdr->ppk.caplen = snaplen;
360 phdr->ppk.len = len;
361 phdr->ppk.ifindex = sll->sll_ifindex;
362 phdr->ppk.protocol = sll->sll_protocol;
363 phdr->ppk.pkttype = sll->sll_pkttype;
364 break;
366 case KUZNETZOV_SWAPPED:
367 phdr->ppk.ts.tv_sec = ___constant_swab32(sec);
368 phdr->ppk.ts.tv_usec = ___constant_swab32(nsec / 1000);
369 phdr->ppk.caplen = ___constant_swab32(snaplen);
370 phdr->ppk.len = ___constant_swab32(len);
371 phdr->ppk.ifindex = ___constant_swab32(sll->sll_ifindex);
372 phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
373 phdr->ppk.pkttype = sll->sll_pkttype;
374 break;
376 case BORKMANN:
377 phdr->ppb.ts.tv_sec = sec;
378 phdr->ppb.ts.tv_nsec = nsec;
379 phdr->ppb.caplen = snaplen;
380 phdr->ppb.len = len;
381 phdr->ppb.tsource = tp_to_pcap_tsource(status);
382 phdr->ppb.ifindex = (u16) sll->sll_ifindex;
383 phdr->ppb.protocol = sll->sll_protocol;
384 phdr->ppb.hatype = sll->sll_hatype;
385 phdr->ppb.pkttype = sll->sll_pkttype;
386 break;
388 case BORKMANN_SWAPPED:
389 phdr->ppb.ts.tv_sec = ___constant_swab32(sec);
390 phdr->ppb.ts.tv_nsec = ___constant_swab32(nsec);
391 phdr->ppb.caplen = ___constant_swab32(snaplen);
392 phdr->ppb.len = ___constant_swab32(len);
393 phdr->ppb.tsource = ___constant_swab16(tp_to_pcap_tsource(status));
394 phdr->ppb.ifindex = ___constant_swab16((u16) sll->sll_ifindex);
395 phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
396 phdr->ppb.hatype = sll->sll_hatype;
397 phdr->ppb.pkttype = sll->sll_pkttype;
398 break;
400 default:
401 bug();
405 /* We need to do this crap here since member offsets are not interleaved,
406 * so hopfully the compiler does his job here. ;-)
409 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
410 struct sockaddr_ll *sll,
411 pcap_pkthdr_t *phdr,
412 enum pcap_type type)
414 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
415 thdr->tp_snaplen, thdr->tp_len,
416 thdr->tp_status, sll, phdr, type);
419 #ifdef HAVE_TPACKET3
420 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
421 struct sockaddr_ll *sll,
422 pcap_pkthdr_t *phdr,
423 enum pcap_type type)
425 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
426 thdr->tp_snaplen, thdr->tp_len,
427 0, sll, phdr, type);
429 #endif
431 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
432 enum pcap_type type,
433 struct tpacket2_hdr *thdr,
434 struct sockaddr_ll *sll)
436 switch (type) {
437 case DEFAULT:
438 thdr->tp_sec = phdr->ppo.ts.tv_sec;
439 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
440 thdr->tp_snaplen = phdr->ppo.caplen;
441 thdr->tp_len = phdr->ppo.len;
442 break;
444 case DEFAULT_SWAPPED:
445 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
446 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
447 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
448 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
449 break;
451 case NSEC:
452 thdr->tp_sec = phdr->ppn.ts.tv_sec;
453 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
454 thdr->tp_snaplen = phdr->ppn.caplen;
455 thdr->tp_len = phdr->ppn.len;
456 break;
458 case NSEC_SWAPPED:
459 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
460 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
461 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
462 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
463 break;
465 case KUZNETZOV:
466 thdr->tp_sec = phdr->ppk.ts.tv_sec;
467 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
468 thdr->tp_snaplen = phdr->ppk.caplen;
469 thdr->tp_len = phdr->ppk.len;
470 if (sll) {
471 sll->sll_ifindex = phdr->ppk.ifindex;
472 sll->sll_protocol = phdr->ppk.protocol;
473 sll->sll_pkttype = phdr->ppk.pkttype;
475 break;
477 case KUZNETZOV_SWAPPED:
478 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
479 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
480 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
481 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
482 if (sll) {
483 sll->sll_ifindex = ___constant_swab32(phdr->ppk.ifindex);
484 sll->sll_protocol = ___constant_swab16(phdr->ppk.protocol);
485 sll->sll_pkttype = phdr->ppk.pkttype;
487 break;
489 case BORKMANN:
490 thdr->tp_sec = phdr->ppb.ts.tv_sec;
491 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
492 thdr->tp_snaplen = phdr->ppb.caplen;
493 thdr->tp_len = phdr->ppb.len;
494 if (sll) {
495 sll->sll_ifindex = phdr->ppb.ifindex;
496 sll->sll_protocol = phdr->ppb.protocol;
497 sll->sll_hatype = phdr->ppb.hatype;
498 sll->sll_pkttype = phdr->ppb.pkttype;
500 break;
502 case BORKMANN_SWAPPED:
503 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
504 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
505 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
506 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
507 if (sll) {
508 sll->sll_ifindex = ___constant_swab16(phdr->ppb.ifindex);
509 sll->sll_protocol = ___constant_swab16(phdr->ppb.protocol);
510 sll->sll_hatype = phdr->ppb.hatype;
511 sll->sll_pkttype = phdr->ppb.pkttype;
513 break;
515 default:
516 bug();
520 #define FEATURE_UNKNOWN (0 << 0)
521 #define FEATURE_TIMEVAL_MS (1 << 0)
522 #define FEATURE_TIMEVAL_NS (1 << 1)
523 #define FEATURE_LEN (1 << 2)
524 #define FEATURE_CAPLEN (1 << 3)
525 #define FEATURE_IFINDEX (1 << 4)
526 #define FEATURE_PROTO (1 << 5)
527 #define FEATURE_HATYPE (1 << 6)
528 #define FEATURE_PKTTYPE (1 << 7)
529 #define FEATURE_TSOURCE (1 << 8)
531 struct pcap_magic_type {
532 const uint32_t magic;
533 const char *desc;
534 const uint16_t features;
537 static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
539 .magic = ORIGINAL_TCPDUMP_MAGIC,
540 .desc = "tcpdump-capable pcap",
541 .features = FEATURE_TIMEVAL_MS |
542 FEATURE_LEN |
543 FEATURE_CAPLEN,
544 }, {
545 .magic = NSEC_TCPDUMP_MAGIC,
546 .desc = "tcpdump-capable pcap with ns resolution",
547 .features = FEATURE_TIMEVAL_NS |
548 FEATURE_LEN |
549 FEATURE_CAPLEN,
550 }, {
551 .magic = KUZNETZOV_TCPDUMP_MAGIC,
552 .desc = "Alexey Kuznetzov's pcap",
553 .features = FEATURE_TIMEVAL_MS |
554 FEATURE_LEN |
555 FEATURE_CAPLEN |
556 FEATURE_IFINDEX |
557 FEATURE_PROTO |
558 FEATURE_PKTTYPE,
559 }, {
560 .magic = BORKMANN_TCPDUMP_MAGIC,
561 .desc = "netsniff-ng pcap",
562 .features = FEATURE_TIMEVAL_NS |
563 FEATURE_LEN |
564 FEATURE_CAPLEN |
565 FEATURE_TSOURCE |
566 FEATURE_IFINDEX |
567 FEATURE_PROTO |
568 FEATURE_HATYPE |
569 FEATURE_PKTTYPE,
573 static inline void pcap_dump_type_features(void)
575 size_t i;
577 for (i = 0; i < array_size(pcap_magic_types); ++i) {
578 printf("%s:\n", pcap_magic_types[i].desc);
579 printf(" magic: 0x%x (swapped: 0x%x)\n",
580 pcap_magic_types[i].magic,
581 ___constant_swab32(pcap_magic_types[i].magic));
582 printf(" features:\n");
584 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
585 printf(" unknown\n");
586 continue;
589 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
590 printf(" timeval in us\n");
591 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
592 printf(" timeval in ns\n");
593 if (pcap_magic_types[i].features & FEATURE_TSOURCE)
594 printf(" timestamp source\n");
595 if (pcap_magic_types[i].features & FEATURE_LEN)
596 printf(" packet length\n");
597 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
598 printf(" packet cap-length\n");
599 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
600 printf(" packet ifindex\n");
601 if (pcap_magic_types[i].features & FEATURE_PROTO)
602 printf(" packet protocol\n");
603 if (pcap_magic_types[i].features & FEATURE_HATYPE)
604 printf(" hardware type\n");
605 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
606 printf(" packet type\n");
610 static const char *pcap_ops_group_to_str[] __maybe_unused = {
611 [PCAP_OPS_RW] = "read/write",
612 [PCAP_OPS_SG] = "scatter-gather",
613 [PCAP_OPS_MM] = "mmap",
616 static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
617 [PCAP_OPS_RW] = &pcap_rw_ops,
618 [PCAP_OPS_SG] = &pcap_sg_ops,
619 [PCAP_OPS_MM] = &pcap_mm_ops,
622 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
623 uint32_t linktype, int32_t thiszone,
624 uint32_t snaplen)
626 bool swapped = pcap_magic_is_swapped(magic);
628 hdr->magic = magic;
629 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
630 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
631 hdr->thiszone = swapped ? (int32_t) ___constant_swab32(thiszone) : thiszone;
632 hdr->sigfigs = 0;
633 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
634 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
637 static const bool pcap_supported_linktypes[LINKTYPE_MAX] __maybe_unused = {
638 /* tunX captures from wireshark/tcpdump, non-portable */
639 [101] = true, [102] = true, [103] = true,
640 [LINKTYPE_NULL] = true,
641 [LINKTYPE_EN10MB] = true,
642 [LINKTYPE_EN3MB] = true,
643 [LINKTYPE_AX25] = true,
644 [LINKTYPE_PRONET] = true,
645 [LINKTYPE_CHAOS] = true,
646 [LINKTYPE_IEEE802] = true,
647 [LINKTYPE_SLIP] = true,
648 [LINKTYPE_PPP] = true,
649 [LINKTYPE_FDDI] = true,
650 [LINKTYPE_ATM_CLIP] = true,
651 [LINKTYPE_C_HDLC] = true,
652 [LINKTYPE_IEEE802_11] = true,
653 [LINKTYPE_IEEE802_11_RADIOTAP] = true,
654 [LINKTYPE_FRELAY] = true,
655 [LINKTYPE_ECONET] = true,
656 [LINKTYPE_ARCNET_LINUX] = true,
657 [LINKTYPE_LINUX_IRDA] = true,
658 [LINKTYPE_CAN20B] = true,
659 [LINKTYPE_IEEE802_15_4_LINUX] = true,
660 [LINKTYPE_INFINIBAND] = true,
661 [LINKTYPE_NETLINK] = true,
664 static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
666 bool good = false;
667 uint32_t linktype;
669 pcap_check_magic(hdr->magic);
671 linktype = pcap_magic_is_swapped(hdr->magic) ? bswap_32(hdr->linktype) : hdr->linktype;
672 if (linktype < LINKTYPE_MAX)
673 good = pcap_supported_linktypes[linktype];
675 if (!good)
676 panic("This file has an unsupported pcap link type (%d)!\n", linktype);
677 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
678 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
679 panic("This file has an invalid pcap major version (must be %d)\n", PCAP_VERSION_MAJOR);
680 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
681 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
682 panic("This file has an invalid pcap minor version (must be %d)\n", PCAP_VERSION_MINOR);
685 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
686 uint32_t *linktype) __maybe_unused;
688 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
690 ssize_t ret;
691 struct pcap_filehdr hdr;
693 ret = read(fd, &hdr, sizeof(hdr));
694 if (unlikely(ret != sizeof(hdr)))
695 return -EIO;
697 pcap_validate_header(&hdr);
699 *magic = hdr.magic;
700 *linktype = hdr.linktype;
702 return 0;
705 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
706 uint32_t linktype) __maybe_unused;
708 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
710 ssize_t ret;
711 struct pcap_filehdr hdr;
713 memset(&hdr, 0, sizeof(hdr));
715 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
717 ret = write_or_die(fd, &hdr, sizeof(hdr));
718 if (unlikely(ret != sizeof(hdr)))
719 panic("Failed to write pkt file header!\n");
721 return 0;
724 #endif /* PCAP_IO_H */