summaryrefslogtreecommitdiff
path: root/pcap_io.h
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
committerDaniel Borkmann <dborkman@redhat.com>2013-03-15 10:41:48 +0100
commit1a9fbac03c684f29cff9ac44875bd9504a89f54e (patch)
tree1b2e40dbe5dc1899ef5b62c4325c9b94c9c450fc /pcap_io.h
all: import netsniff-ng 0.5.8-rc0 source
We decided to get rid of the old Git history and start a new one for several reasons: *) Allow / enforce only high-quality commits (which was not the case for many commits in the history), have a policy that is more close to the one from the Linux kernel. With high quality commits, we mean code that is logically split into commits and commit messages that are signed-off and have a proper subject and message body. We do not allow automatic Github merges anymore, since they are total bullshit. However, we will either cherry-pick your patches or pull them manually. *) The old archive was about ~27MB for no particular good reason. This basically derived from the bad decision that also some PDF files where stored there. From this moment onwards, no binary objects are allowed to be stored in this repository anymore. The old archive is not wiped away from the Internet. You will still be able to find it, e.g. on git.cryptoism.org etc. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'pcap_io.h')
-rw-r--r--pcap_io.h581
1 files changed, 581 insertions, 0 deletions
diff --git a/pcap_io.h b/pcap_io.h
new file mode 100644
index 0000000..0784195
--- /dev/null
+++ b/pcap_io.h
@@ -0,0 +1,581 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Copyright 2009 - 2013 Daniel Borkmann.
+ * Copyright 2010 Emmanuel Roullit.
+ * Subject to the GPL, version 2.
+ */
+
+#ifndef PCAP_IO_H
+#define PCAP_IO_H
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <linux/if_packet.h>
+
+#include "built_in.h"
+#include "die.h"
+#include "xio.h"
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+#define ORIGINAL_TCPDUMP_MAGIC TCPDUMP_MAGIC
+#define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
+#define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
+#define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
+
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+#define PCAP_DEFAULT_SNAPSHOT_LEN 65535
+
+#define LINKTYPE_EN10MB 1 /* Ethernet (10Mb) */
+#define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+struct pcap_filehdr {
+ uint32_t magic;
+ uint16_t version_major;
+ uint16_t version_minor;
+ int32_t thiszone;
+ uint32_t sigfigs;
+ uint32_t snaplen;
+ uint32_t linktype;
+};
+
+struct pcap_timeval {
+ int32_t tv_sec;
+ int32_t tv_usec;
+};
+
+struct pcap_timeval_ns {
+ int32_t tv_sec;
+ int32_t tv_nsec;
+};
+
+struct pcap_pkthdr {
+ struct pcap_timeval ts;
+ uint32_t caplen;
+ uint32_t len;
+};
+
+struct pcap_pkthdr_ns {
+ struct pcap_timeval_ns ts;
+ uint32_t caplen;
+ uint32_t len;
+};
+
+struct pcap_pkthdr_kuz {
+ struct pcap_timeval ts;
+ uint32_t caplen;
+ uint32_t len;
+ int ifindex;
+ uint16_t protocol;
+ uint8_t pkttype;
+};
+
+struct pcap_pkthdr_bkm {
+ struct pcap_timeval_ns ts;
+ uint32_t caplen;
+ uint32_t len;
+ uint32_t ifindex;
+ uint16_t protocol;
+ uint8_t hatype;
+ uint8_t pkttype;
+};
+
+typedef union {
+ struct pcap_pkthdr ppo;
+ struct pcap_pkthdr_ns ppn;
+ struct pcap_pkthdr_kuz ppk;
+ struct pcap_pkthdr_bkm ppb;
+ uint8_t raw;
+} pcap_pkthdr_t;
+
+enum pcap_type {
+ DEFAULT = ORIGINAL_TCPDUMP_MAGIC,
+ NSEC = NSEC_TCPDUMP_MAGIC,
+ KUZNETZOV = KUZNETZOV_TCPDUMP_MAGIC,
+ BORKMANN = BORKMANN_TCPDUMP_MAGIC,
+
+ DEFAULT_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
+ NSEC_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC),
+ KUZNETZOV_SWAPPED = ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
+ BORKMANN_SWAPPED = ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
+};
+
+enum pcap_ops_groups {
+ PCAP_OPS_RW = 0,
+ PCAP_OPS_SG,
+ PCAP_OPS_MM,
+};
+
+enum pcap_mode {
+ PCAP_MODE_RD = 0,
+ PCAP_MODE_WR,
+};
+
+struct pcap_file_ops {
+ int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
+ int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
+ int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
+ ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
+ const uint8_t *packet, size_t len);
+ ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
+ uint8_t *packet, size_t len);
+ void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
+ void (*fsync_pcap)(int fd);
+};
+
+extern const struct pcap_file_ops pcap_rw_ops;
+extern const struct pcap_file_ops pcap_sg_ops;
+extern const struct pcap_file_ops pcap_mm_ops;
+
+static inline void pcap_check_magic(uint32_t magic)
+{
+ switch (magic) {
+
+ case ORIGINAL_TCPDUMP_MAGIC:
+ case NSEC_TCPDUMP_MAGIC:
+ case KUZNETZOV_TCPDUMP_MAGIC:
+ case BORKMANN_TCPDUMP_MAGIC:
+
+ case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
+ case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
+ case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
+ case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
+ break;
+
+ default:
+ panic("This file has not a valid pcap header\n");
+ }
+}
+
+static inline bool pcap_magic_is_swapped(uint32_t magic)
+{
+ bool swapped = false;
+
+ switch (magic) {
+ case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
+ case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
+ case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
+ case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
+ swapped = true;
+ }
+
+ return swapped;
+}
+
+static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
+{
+ switch (type) {
+#define CASE_RET_CAPLEN(what, member, swap) \
+ case (what): \
+ return (swap ? ___constant_swab32(phdr->member.caplen) : \
+ phdr->member.caplen)
+
+ CASE_RET_CAPLEN(DEFAULT, ppo, 0);
+ CASE_RET_CAPLEN(NSEC, ppn, 0);
+ CASE_RET_CAPLEN(KUZNETZOV, ppk, 0);
+ CASE_RET_CAPLEN(BORKMANN, ppb, 0);
+
+ CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
+ CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1);
+ CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
+ CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
+
+ default:
+ bug();
+ }
+}
+
+static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
+{
+ switch (type) {
+#define CASE_SET_CAPLEN(what, member, swap) \
+ case (what): \
+ phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
+ break
+
+ CASE_SET_CAPLEN(DEFAULT, ppo, 0);
+ CASE_SET_CAPLEN(NSEC, ppn, 0);
+ CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
+ CASE_SET_CAPLEN(BORKMANN, ppb, 0);
+
+ CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
+ CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
+ CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
+ CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
+
+ default:
+ bug();
+ }
+}
+
+static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
+{
+ switch (type) {
+#define CASE_RET_HDRLEN(what, member) \
+ case (what): \
+ return sizeof(phdr->member)
+
+ CASE_RET_HDRLEN(DEFAULT, ppo);
+ CASE_RET_HDRLEN(NSEC, ppn);
+ CASE_RET_HDRLEN(KUZNETZOV, ppk);
+ CASE_RET_HDRLEN(BORKMANN, ppb);
+
+ CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
+ CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
+ CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
+ CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
+
+ default:
+ bug();
+ }
+}
+
+static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
+{
+ switch (type) {
+#define CASE_RET_TOTLEN(what, member, swap) \
+ case (what): \
+ return ((swap ? ___constant_swab32(phdr->member.caplen) : \
+ phdr->member.caplen) + sizeof(phdr->member))
+
+ CASE_RET_TOTLEN(DEFAULT, ppo, 0);
+ CASE_RET_TOTLEN(NSEC, ppn, 0);
+ CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
+ CASE_RET_TOTLEN(BORKMANN, ppb, 0);
+
+ CASE_RET_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
+ CASE_RET_TOTLEN(NSEC_SWAPPED, ppn, 1);
+ CASE_RET_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
+ CASE_RET_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
+
+ default:
+ bug();
+ }
+}
+
+static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
+ struct sockaddr_ll *sll,
+ pcap_pkthdr_t *phdr,
+ enum pcap_type type)
+{
+ switch (type) {
+ case DEFAULT:
+ phdr->ppo.ts.tv_sec = thdr->tp_sec;
+ phdr->ppo.ts.tv_usec = thdr->tp_nsec / 1000;
+ phdr->ppo.caplen = thdr->tp_snaplen;
+ phdr->ppo.len = thdr->tp_len;
+ break;
+
+ case DEFAULT_SWAPPED:
+ phdr->ppo.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
+ phdr->ppo.ts.tv_usec = ___constant_swab32(thdr->tp_nsec / 1000);
+ phdr->ppo.caplen = ___constant_swab32(thdr->tp_snaplen);
+ phdr->ppo.len = ___constant_swab32(thdr->tp_len);
+ break;
+
+ case NSEC:
+ phdr->ppn.ts.tv_sec = thdr->tp_sec;
+ phdr->ppn.ts.tv_nsec = thdr->tp_nsec;
+ phdr->ppn.caplen = thdr->tp_snaplen;
+ phdr->ppn.len = thdr->tp_len;
+ break;
+
+ case NSEC_SWAPPED:
+ phdr->ppn.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
+ phdr->ppn.ts.tv_nsec = ___constant_swab32(thdr->tp_nsec);
+ phdr->ppn.caplen = ___constant_swab32(thdr->tp_snaplen);
+ phdr->ppn.len = ___constant_swab32(thdr->tp_len);
+ break;
+
+ case KUZNETZOV:
+ phdr->ppk.ts.tv_sec = thdr->tp_sec;
+ phdr->ppk.ts.tv_usec = thdr->tp_nsec / 1000;
+ phdr->ppk.caplen = thdr->tp_snaplen;
+ phdr->ppk.len = thdr->tp_len;
+ phdr->ppk.ifindex = sll->sll_ifindex;
+ phdr->ppk.protocol = sll->sll_protocol;
+ phdr->ppk.pkttype = sll->sll_pkttype;
+ break;
+
+ case KUZNETZOV_SWAPPED:
+ phdr->ppk.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
+ phdr->ppk.ts.tv_usec = ___constant_swab32(thdr->tp_nsec / 1000);
+ phdr->ppk.caplen = ___constant_swab32(thdr->tp_snaplen);
+ phdr->ppk.len = ___constant_swab32(thdr->tp_len);
+ phdr->ppk.ifindex = ___constant_swab32((u32) sll->sll_ifindex);
+ phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
+ phdr->ppk.pkttype = sll->sll_pkttype;
+ break;
+
+ case BORKMANN:
+ phdr->ppb.ts.tv_sec = thdr->tp_sec;
+ phdr->ppb.ts.tv_nsec = thdr->tp_nsec;
+ phdr->ppb.caplen = thdr->tp_snaplen;
+ phdr->ppb.len = thdr->tp_len;
+ phdr->ppb.ifindex = (u32) sll->sll_ifindex;
+ phdr->ppb.protocol = sll->sll_protocol;
+ phdr->ppb.hatype = sll->sll_hatype;
+ phdr->ppb.pkttype = sll->sll_pkttype;
+ break;
+
+ case BORKMANN_SWAPPED:
+ phdr->ppb.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
+ phdr->ppb.ts.tv_nsec = ___constant_swab32(thdr->tp_nsec);
+ phdr->ppb.caplen = ___constant_swab32(thdr->tp_snaplen);
+ phdr->ppb.len = ___constant_swab32(thdr->tp_len);
+ phdr->ppb.ifindex = ___constant_swab32((u32) sll->sll_ifindex);
+ phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
+ phdr->ppb.hatype = sll->sll_hatype;
+ phdr->ppb.pkttype = sll->sll_pkttype;
+ break;
+
+ default:
+ bug();
+ }
+}
+
+static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
+ enum pcap_type type,
+ struct tpacket2_hdr *thdr,
+ struct sockaddr_ll *sll)
+{
+ switch (type) {
+ case DEFAULT:
+ thdr->tp_sec = phdr->ppo.ts.tv_sec;
+ thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
+ thdr->tp_snaplen = phdr->ppo.caplen;
+ thdr->tp_len = phdr->ppo.len;
+ break;
+
+ case DEFAULT_SWAPPED:
+ thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
+ thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
+ thdr->tp_len = ___constant_swab32(phdr->ppo.len);
+ break;
+
+ case NSEC:
+ thdr->tp_sec = phdr->ppn.ts.tv_sec;
+ thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
+ thdr->tp_snaplen = phdr->ppn.caplen;
+ thdr->tp_len = phdr->ppn.len;
+ break;
+
+ case NSEC_SWAPPED:
+ thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
+ thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
+ thdr->tp_len = ___constant_swab32(phdr->ppn.len);
+ break;
+
+ case KUZNETZOV:
+ thdr->tp_sec = phdr->ppk.ts.tv_sec;
+ thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
+ thdr->tp_snaplen = phdr->ppk.caplen;
+ thdr->tp_len = phdr->ppk.len;
+ break;
+
+ case KUZNETZOV_SWAPPED:
+ thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
+ thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
+ thdr->tp_len = ___constant_swab32(phdr->ppk.len);
+ break;
+
+ case BORKMANN:
+ thdr->tp_sec = phdr->ppb.ts.tv_sec;
+ thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
+ thdr->tp_snaplen = phdr->ppb.caplen;
+ thdr->tp_len = phdr->ppb.len;
+ break;
+
+ case BORKMANN_SWAPPED:
+ thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
+ thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
+ thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
+ thdr->tp_len = ___constant_swab32(phdr->ppb.len);
+ break;
+
+ default:
+ bug();
+ }
+}
+
+#define FEATURE_UNKNOWN (0 << 0)
+#define FEATURE_TIMEVAL_MS (1 << 0)
+#define FEATURE_TIMEVAL_NS (1 << 1)
+#define FEATURE_LEN (1 << 2)
+#define FEATURE_CAPLEN (1 << 3)
+#define FEATURE_IFINDEX (1 << 4)
+#define FEATURE_PROTO (1 << 5)
+#define FEATURE_HATYPE (1 << 6)
+#define FEATURE_PKTTYPE (1 << 7)
+
+struct pcap_magic_type {
+ const uint32_t magic;
+ const char *desc;
+ const uint16_t features;
+};
+
+static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
+ {
+ .magic = ORIGINAL_TCPDUMP_MAGIC,
+ .desc = "tcpdump-capable pcap",
+ .features = FEATURE_TIMEVAL_MS |
+ FEATURE_LEN |
+ FEATURE_CAPLEN,
+ }, {
+ .magic = NSEC_TCPDUMP_MAGIC,
+ .desc = "tcpdump-capable pcap with ns resolution",
+ .features = FEATURE_TIMEVAL_NS |
+ FEATURE_LEN |
+ FEATURE_CAPLEN,
+ }, {
+ .magic = KUZNETZOV_TCPDUMP_MAGIC,
+ .desc = "Alexey Kuznetzov's pcap",
+ .features = FEATURE_TIMEVAL_MS |
+ FEATURE_LEN |
+ FEATURE_CAPLEN |
+ FEATURE_IFINDEX |
+ FEATURE_PROTO |
+ FEATURE_PKTTYPE,
+ }, {
+ .magic = BORKMANN_TCPDUMP_MAGIC,
+ .desc = "netsniff-ng pcap",
+ .features = FEATURE_TIMEVAL_NS |
+ FEATURE_LEN |
+ FEATURE_CAPLEN |
+ FEATURE_IFINDEX |
+ FEATURE_PROTO |
+ FEATURE_HATYPE |
+ FEATURE_PKTTYPE,
+ },
+};
+
+static inline void pcap_dump_type_features(void)
+{
+ int i;
+
+ for (i = 0; i < array_size(pcap_magic_types); ++i) {
+ printf("%s:\n", pcap_magic_types[i].desc);
+ printf(" magic: 0x%x (swapped: 0x%x)\n",
+ pcap_magic_types[i].magic,
+ ___constant_swab32(pcap_magic_types[i].magic));
+ printf(" features:\n");
+
+ if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
+ printf(" unknown\n");
+ continue;
+ }
+
+ if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
+ printf(" timeval in us\n");
+ if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
+ printf(" timeval in ns\n");
+ if (pcap_magic_types[i].features & FEATURE_LEN)
+ printf(" packet length\n");
+ if (pcap_magic_types[i].features & FEATURE_CAPLEN)
+ printf(" packet cap-length\n");
+ if (pcap_magic_types[i].features & FEATURE_IFINDEX)
+ printf(" packet ifindex\n");
+ if (pcap_magic_types[i].features & FEATURE_PROTO)
+ printf(" packet protocol\n");
+ if (pcap_magic_types[i].features & FEATURE_HATYPE)
+ printf(" hardware type\n");
+ if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
+ printf(" packet type\n");
+ }
+}
+
+static const char *pcap_ops_group_to_str[] __maybe_unused = {
+ [PCAP_OPS_RW] = "rw",
+ [PCAP_OPS_SG] = "sg",
+ [PCAP_OPS_MM] = "mm",
+};
+
+static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
+ [PCAP_OPS_RW] = &pcap_rw_ops,
+ [PCAP_OPS_SG] = &pcap_sg_ops,
+ [PCAP_OPS_MM] = &pcap_mm_ops,
+};
+
+static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
+ uint32_t linktype, int32_t thiszone,
+ uint32_t snaplen)
+{
+ bool swapped = pcap_magic_is_swapped(magic);
+
+ hdr->magic = magic;
+ hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
+ hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
+ hdr->thiszone = swapped ? ___constant_swab32(thiszone) : thiszone;
+ hdr->sigfigs = 0;
+ hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
+ hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
+}
+
+static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
+{
+ pcap_check_magic(hdr->magic);
+
+ switch (hdr->linktype) {
+ case LINKTYPE_EN10MB:
+ case LINKTYPE_IEEE802_11:
+ case ___constant_swab32(LINKTYPE_EN10MB):
+ case ___constant_swab32(LINKTYPE_IEEE802_11):
+ break;
+ default:
+ panic("This file has not a valid pcap header\n");
+ }
+
+ if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
+ ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
+ panic("This file has not a valid pcap header\n");
+ if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
+ ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
+ panic("This file has not a valid pcap header\n");
+}
+
+static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
+ uint32_t *linktype) __maybe_unused;
+
+static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
+{
+ ssize_t ret;
+ struct pcap_filehdr hdr;
+
+ ret = read(fd, &hdr, sizeof(hdr));
+ if (unlikely(ret != sizeof(hdr)))
+ return -EIO;
+
+ pcap_validate_header(&hdr);
+
+ *magic = hdr.magic;
+ *linktype = hdr.linktype;
+
+ return 0;
+}
+
+static int pcap_generic_push_fhdr(int fd, uint32_t magic,
+ uint32_t linktype) __maybe_unused;
+
+static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
+{
+ ssize_t ret;
+ struct pcap_filehdr hdr;
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
+
+ ret = write_or_die(fd, &hdr, sizeof(hdr));
+ if (unlikely(ret != sizeof(hdr)))
+ panic("Failed to write pkt file header!\n");
+
+ return 0;
+}
+
+#endif /* PCAP_IO_H */