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.
16 #include <sys/socket.h>
18 #include <linux/if_packet.h>
19 #include <linux/if_arp.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
43 uint16_t version_major
;
44 uint16_t version_minor
;
56 struct pcap_timeval_ns
{
62 struct pcap_timeval ts
;
67 struct pcap_pkthdr_ns
{
68 struct pcap_timeval_ns ts
;
73 struct pcap_pkthdr_kuz
{
74 struct pcap_timeval ts
;
82 struct pcap_pkthdr_bkm
{
83 struct pcap_timeval_ns ts
;
94 struct pcap_pkthdr ppo
;
95 struct pcap_pkthdr_ns ppn
;
96 struct pcap_pkthdr_kuz ppk
;
97 struct pcap_pkthdr_bkm ppb
;
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
{
124 struct pcap_file_ops
{
125 void (*init_once_pcap
)(void);
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
;
153 static inline int pcap_devtype_to_linktype(const char *ifname
)
155 switch (device_type(ifname
)) {
158 case ARPHRD_LOOPBACK
:
163 case ARPHRD_ETHER
: return LINKTYPE_EN10MB
;
164 case ARPHRD_IEEE80211_PRISM
:
165 case ARPHRD_IEEE80211_RADIOTAP
:
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
;
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
;
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
)
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
):
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;
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
):
230 static inline u32
pcap_get_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
233 #define CASE_RET_CAPLEN(what, member, swap) \
235 return (swap ? ___constant_swab32(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);
253 static inline void pcap_set_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
, u32 len
)
256 #define CASE_SET_CAPLEN(what, member, swap) \
258 phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
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);
276 static inline u32
pcap_get_hdr_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
279 #define CASE_RET_HDRLEN(what, member) \
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
);
298 static inline u32
pcap_get_total_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
301 #define CASE_RET_TOTLEN(what, member, swap) \
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);
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
,
329 phdr
->ppo
.ts
.tv_sec
= sec
;
330 phdr
->ppo
.ts
.tv_usec
= nsec
/ 1000;
331 phdr
->ppo
.caplen
= snaplen
;
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
);
343 phdr
->ppn
.ts
.tv_sec
= sec
;
344 phdr
->ppn
.ts
.tv_nsec
= nsec
;
345 phdr
->ppn
.caplen
= snaplen
;
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
);
357 phdr
->ppk
.ts
.tv_sec
= sec
;
358 phdr
->ppk
.ts
.tv_usec
= nsec
/ 1000;
359 phdr
->ppk
.caplen
= snaplen
;
361 phdr
->ppk
.ifindex
= sll
->sll_ifindex
;
362 phdr
->ppk
.protocol
= sll
->sll_protocol
;
363 phdr
->ppk
.pkttype
= sll
->sll_pkttype
;
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
;
377 phdr
->ppb
.ts
.tv_sec
= sec
;
378 phdr
->ppb
.ts
.tv_nsec
= nsec
;
379 phdr
->ppb
.caplen
= snaplen
;
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
;
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
;
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
,
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
);
420 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr
*thdr
,
421 struct sockaddr_ll
*sll
,
425 __tpacket_hdr_to_pcap_pkthdr(thdr
->tp_sec
, thdr
->tp_nsec
,
426 thdr
->tp_snaplen
, thdr
->tp_len
,
431 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t
*phdr
,
433 struct tpacket2_hdr
*thdr
,
434 struct sockaddr_ll
*sll
)
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
;
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
);
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
;
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
);
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
;
471 sll
->sll_ifindex
= phdr
->ppk
.ifindex
;
472 sll
->sll_protocol
= phdr
->ppk
.protocol
;
473 sll
->sll_pkttype
= phdr
->ppk
.pkttype
;
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
);
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
;
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
;
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
;
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
);
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
;
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
;
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
|
545 .magic
= NSEC_TCPDUMP_MAGIC
,
546 .desc
= "tcpdump-capable pcap with ns resolution",
547 .features
= FEATURE_TIMEVAL_NS
|
551 .magic
= KUZNETZOV_TCPDUMP_MAGIC
,
552 .desc
= "Alexey Kuznetzov's pcap",
553 .features
= FEATURE_TIMEVAL_MS
|
560 .magic
= BORKMANN_TCPDUMP_MAGIC
,
561 .desc
= "netsniff-ng pcap",
562 .features
= FEATURE_TIMEVAL_NS
|
573 static inline void pcap_dump_type_features(void)
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");
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
,
626 bool swapped
= pcap_magic_is_swapped(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
;
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_FRELAY
] = true,
654 [LINKTYPE_ECONET
] = true,
655 [LINKTYPE_ARCNET_LINUX
] = true,
656 [LINKTYPE_LINUX_IRDA
] = true,
657 [LINKTYPE_CAN20B
] = true,
658 [LINKTYPE_IEEE802_15_4_LINUX
] = true,
659 [LINKTYPE_INFINIBAND
] = true,
660 [LINKTYPE_NETLINK
] = true,
663 static inline void pcap_validate_header(const struct pcap_filehdr
*hdr
)
668 pcap_check_magic(hdr
->magic
);
670 linktype
= pcap_magic_is_swapped(hdr
->magic
) ? bswap_32(hdr
->linktype
) : hdr
->linktype
;
671 if (linktype
< LINKTYPE_MAX
)
672 good
= pcap_supported_linktypes
[linktype
];
675 panic("This file has an unsupported pcap link type (%d)!\n", linktype
);
676 if (unlikely(hdr
->version_major
!= PCAP_VERSION_MAJOR
) &&
677 ___constant_swab16(hdr
->version_major
) != PCAP_VERSION_MAJOR
)
678 panic("This file has an invalid pcap major version (must be %d)\n", PCAP_VERSION_MAJOR
);
679 if (unlikely(hdr
->version_minor
!= PCAP_VERSION_MINOR
) &&
680 ___constant_swab16(hdr
->version_minor
) != PCAP_VERSION_MINOR
)
681 panic("This file has an invalid pcap minor version (must be %d)\n", PCAP_VERSION_MINOR
);
684 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
,
685 uint32_t *linktype
) __maybe_unused
;
687 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
, uint32_t *linktype
)
690 struct pcap_filehdr hdr
;
692 ret
= read(fd
, &hdr
, sizeof(hdr
));
693 if (unlikely(ret
!= sizeof(hdr
)))
696 pcap_validate_header(&hdr
);
699 *linktype
= hdr
.linktype
;
704 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
,
705 uint32_t linktype
) __maybe_unused
;
707 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
, uint32_t linktype
)
710 struct pcap_filehdr hdr
;
712 memset(&hdr
, 0, sizeof(hdr
));
714 pcap_prepare_header(&hdr
, magic
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
);
716 ret
= write_or_die(fd
, &hdr
, sizeof(hdr
));
717 if (unlikely(ret
!= sizeof(hdr
)))
718 panic("Failed to write pkt file header!\n");
723 #endif /* PCAP_IO_H */