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
);
419 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr
*thdr
,
420 struct sockaddr_ll
*sll
,
424 __tpacket_hdr_to_pcap_pkthdr(thdr
->tp_sec
, thdr
->tp_nsec
,
425 thdr
->tp_snaplen
, thdr
->tp_len
,
429 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t
*phdr
,
431 struct tpacket2_hdr
*thdr
,
432 struct sockaddr_ll
*sll
)
436 thdr
->tp_sec
= phdr
->ppo
.ts
.tv_sec
;
437 thdr
->tp_nsec
= phdr
->ppo
.ts
.tv_usec
* 1000;
438 thdr
->tp_snaplen
= phdr
->ppo
.caplen
;
439 thdr
->tp_len
= phdr
->ppo
.len
;
442 case DEFAULT_SWAPPED
:
443 thdr
->tp_sec
= ___constant_swab32(phdr
->ppo
.ts
.tv_sec
);
444 thdr
->tp_nsec
= ___constant_swab32(phdr
->ppo
.ts
.tv_usec
) * 1000;
445 thdr
->tp_snaplen
= ___constant_swab32(phdr
->ppo
.caplen
);
446 thdr
->tp_len
= ___constant_swab32(phdr
->ppo
.len
);
450 thdr
->tp_sec
= phdr
->ppn
.ts
.tv_sec
;
451 thdr
->tp_nsec
= phdr
->ppn
.ts
.tv_nsec
;
452 thdr
->tp_snaplen
= phdr
->ppn
.caplen
;
453 thdr
->tp_len
= phdr
->ppn
.len
;
457 thdr
->tp_sec
= ___constant_swab32(phdr
->ppn
.ts
.tv_sec
);
458 thdr
->tp_nsec
= ___constant_swab32(phdr
->ppn
.ts
.tv_nsec
);
459 thdr
->tp_snaplen
= ___constant_swab32(phdr
->ppn
.caplen
);
460 thdr
->tp_len
= ___constant_swab32(phdr
->ppn
.len
);
464 thdr
->tp_sec
= phdr
->ppk
.ts
.tv_sec
;
465 thdr
->tp_nsec
= phdr
->ppk
.ts
.tv_usec
* 1000;
466 thdr
->tp_snaplen
= phdr
->ppk
.caplen
;
467 thdr
->tp_len
= phdr
->ppk
.len
;
469 sll
->sll_ifindex
= phdr
->ppk
.ifindex
;
470 sll
->sll_protocol
= phdr
->ppk
.protocol
;
471 sll
->sll_pkttype
= phdr
->ppk
.pkttype
;
475 case KUZNETZOV_SWAPPED
:
476 thdr
->tp_sec
= ___constant_swab32(phdr
->ppk
.ts
.tv_sec
);
477 thdr
->tp_nsec
= ___constant_swab32(phdr
->ppk
.ts
.tv_usec
) * 1000;
478 thdr
->tp_snaplen
= ___constant_swab32(phdr
->ppk
.caplen
);
479 thdr
->tp_len
= ___constant_swab32(phdr
->ppk
.len
);
481 sll
->sll_ifindex
= ___constant_swab32(phdr
->ppk
.ifindex
);
482 sll
->sll_protocol
= ___constant_swab16(phdr
->ppk
.protocol
);
483 sll
->sll_pkttype
= phdr
->ppk
.pkttype
;
488 thdr
->tp_sec
= phdr
->ppb
.ts
.tv_sec
;
489 thdr
->tp_nsec
= phdr
->ppb
.ts
.tv_nsec
;
490 thdr
->tp_snaplen
= phdr
->ppb
.caplen
;
491 thdr
->tp_len
= phdr
->ppb
.len
;
493 sll
->sll_ifindex
= phdr
->ppb
.ifindex
;
494 sll
->sll_protocol
= phdr
->ppb
.protocol
;
495 sll
->sll_hatype
= phdr
->ppb
.hatype
;
496 sll
->sll_pkttype
= phdr
->ppb
.pkttype
;
500 case BORKMANN_SWAPPED
:
501 thdr
->tp_sec
= ___constant_swab32(phdr
->ppb
.ts
.tv_sec
);
502 thdr
->tp_nsec
= ___constant_swab32(phdr
->ppb
.ts
.tv_nsec
);
503 thdr
->tp_snaplen
= ___constant_swab32(phdr
->ppb
.caplen
);
504 thdr
->tp_len
= ___constant_swab32(phdr
->ppb
.len
);
506 sll
->sll_ifindex
= ___constant_swab16(phdr
->ppb
.ifindex
);
507 sll
->sll_protocol
= ___constant_swab16(phdr
->ppb
.protocol
);
508 sll
->sll_hatype
= phdr
->ppb
.hatype
;
509 sll
->sll_pkttype
= phdr
->ppb
.pkttype
;
518 #define FEATURE_UNKNOWN (0 << 0)
519 #define FEATURE_TIMEVAL_MS (1 << 0)
520 #define FEATURE_TIMEVAL_NS (1 << 1)
521 #define FEATURE_LEN (1 << 2)
522 #define FEATURE_CAPLEN (1 << 3)
523 #define FEATURE_IFINDEX (1 << 4)
524 #define FEATURE_PROTO (1 << 5)
525 #define FEATURE_HATYPE (1 << 6)
526 #define FEATURE_PKTTYPE (1 << 7)
527 #define FEATURE_TSOURCE (1 << 8)
529 struct pcap_magic_type
{
530 const uint32_t magic
;
532 const uint16_t features
;
535 static const struct pcap_magic_type pcap_magic_types
[] __maybe_unused
= {
537 .magic
= ORIGINAL_TCPDUMP_MAGIC
,
538 .desc
= "tcpdump-capable pcap",
539 .features
= FEATURE_TIMEVAL_MS
|
543 .magic
= NSEC_TCPDUMP_MAGIC
,
544 .desc
= "tcpdump-capable pcap with ns resolution",
545 .features
= FEATURE_TIMEVAL_NS
|
549 .magic
= KUZNETZOV_TCPDUMP_MAGIC
,
550 .desc
= "Alexey Kuznetzov's pcap",
551 .features
= FEATURE_TIMEVAL_MS
|
558 .magic
= BORKMANN_TCPDUMP_MAGIC
,
559 .desc
= "netsniff-ng pcap",
560 .features
= FEATURE_TIMEVAL_NS
|
571 static inline void pcap_dump_type_features(void)
575 for (i
= 0; i
< array_size(pcap_magic_types
); ++i
) {
576 printf("%s:\n", pcap_magic_types
[i
].desc
);
577 printf(" magic: 0x%x (swapped: 0x%x)\n",
578 pcap_magic_types
[i
].magic
,
579 ___constant_swab32(pcap_magic_types
[i
].magic
));
580 printf(" features:\n");
582 if (pcap_magic_types
[i
].features
== FEATURE_UNKNOWN
) {
583 printf(" unknown\n");
587 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_MS
)
588 printf(" timeval in us\n");
589 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_NS
)
590 printf(" timeval in ns\n");
591 if (pcap_magic_types
[i
].features
& FEATURE_TSOURCE
)
592 printf(" timestamp source\n");
593 if (pcap_magic_types
[i
].features
& FEATURE_LEN
)
594 printf(" packet length\n");
595 if (pcap_magic_types
[i
].features
& FEATURE_CAPLEN
)
596 printf(" packet cap-length\n");
597 if (pcap_magic_types
[i
].features
& FEATURE_IFINDEX
)
598 printf(" packet ifindex\n");
599 if (pcap_magic_types
[i
].features
& FEATURE_PROTO
)
600 printf(" packet protocol\n");
601 if (pcap_magic_types
[i
].features
& FEATURE_HATYPE
)
602 printf(" hardware type\n");
603 if (pcap_magic_types
[i
].features
& FEATURE_PKTTYPE
)
604 printf(" packet type\n");
608 static const char *pcap_ops_group_to_str
[] __maybe_unused
= {
609 [PCAP_OPS_RW
] = "read/write",
610 [PCAP_OPS_SG
] = "scatter-gather",
611 [PCAP_OPS_MM
] = "mmap",
614 static const struct pcap_file_ops
*pcap_ops
[] __maybe_unused
= {
615 [PCAP_OPS_RW
] = &pcap_rw_ops
,
616 [PCAP_OPS_SG
] = &pcap_sg_ops
,
617 [PCAP_OPS_MM
] = &pcap_mm_ops
,
620 static inline void pcap_prepare_header(struct pcap_filehdr
*hdr
, uint32_t magic
,
621 uint32_t linktype
, int32_t thiszone
,
624 bool swapped
= pcap_magic_is_swapped(magic
);
627 hdr
->version_major
= swapped
? ___constant_swab16(PCAP_VERSION_MAJOR
) : PCAP_VERSION_MAJOR
;
628 hdr
->version_minor
= swapped
? ___constant_swab16(PCAP_VERSION_MINOR
) : PCAP_VERSION_MINOR
;
629 hdr
->thiszone
= swapped
? (int32_t) ___constant_swab32(thiszone
) : thiszone
;
631 hdr
->snaplen
= swapped
? ___constant_swab32(snaplen
) : snaplen
;
632 hdr
->linktype
= swapped
? ___constant_swab32(linktype
) : linktype
;
635 static const bool pcap_supported_linktypes
[LINKTYPE_MAX
] __maybe_unused
= {
636 /* tunX captures from wireshark/tcpdump, non-portable */
637 [101] = true, [102] = true, [103] = true,
638 [LINKTYPE_NULL
] = true,
639 [LINKTYPE_EN10MB
] = true,
640 [LINKTYPE_EN3MB
] = true,
641 [LINKTYPE_AX25
] = true,
642 [LINKTYPE_PRONET
] = true,
643 [LINKTYPE_CHAOS
] = true,
644 [LINKTYPE_IEEE802
] = true,
645 [LINKTYPE_SLIP
] = true,
646 [LINKTYPE_PPP
] = true,
647 [LINKTYPE_FDDI
] = true,
648 [LINKTYPE_ATM_CLIP
] = true,
649 [LINKTYPE_C_HDLC
] = true,
650 [LINKTYPE_IEEE802_11
] = true,
651 [LINKTYPE_FRELAY
] = true,
652 [LINKTYPE_ECONET
] = true,
653 [LINKTYPE_ARCNET_LINUX
] = true,
654 [LINKTYPE_LINUX_IRDA
] = true,
655 [LINKTYPE_CAN20B
] = true,
656 [LINKTYPE_IEEE802_15_4_LINUX
] = true,
657 [LINKTYPE_INFINIBAND
] = true,
658 [LINKTYPE_NETLINK
] = true,
661 static inline void pcap_validate_header(const struct pcap_filehdr
*hdr
)
666 pcap_check_magic(hdr
->magic
);
668 linktype
= pcap_magic_is_swapped(hdr
->magic
) ? bswap_32(hdr
->linktype
) : hdr
->linktype
;
669 if (linktype
< LINKTYPE_MAX
)
670 good
= pcap_supported_linktypes
[linktype
];
673 panic("This file has an unsupported pcap link type (%d)!\n", linktype
);
674 if (unlikely(hdr
->version_major
!= PCAP_VERSION_MAJOR
) &&
675 ___constant_swab16(hdr
->version_major
) != PCAP_VERSION_MAJOR
)
676 panic("This file has an invalid pcap major version (must be %d)\n", PCAP_VERSION_MAJOR
);
677 if (unlikely(hdr
->version_minor
!= PCAP_VERSION_MINOR
) &&
678 ___constant_swab16(hdr
->version_minor
) != PCAP_VERSION_MINOR
)
679 panic("This file has an invalid pcap minor version (must be %d)\n", PCAP_VERSION_MINOR
);
682 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
,
683 uint32_t *linktype
) __maybe_unused
;
685 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
, uint32_t *linktype
)
688 struct pcap_filehdr hdr
;
690 ret
= read(fd
, &hdr
, sizeof(hdr
));
691 if (unlikely(ret
!= sizeof(hdr
)))
694 pcap_validate_header(&hdr
);
697 *linktype
= hdr
.linktype
;
702 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
,
703 uint32_t linktype
) __maybe_unused
;
705 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
, uint32_t linktype
)
708 struct pcap_filehdr hdr
;
710 memset(&hdr
, 0, sizeof(hdr
));
712 pcap_prepare_header(&hdr
, magic
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
);
714 ret
= write_or_die(fd
, &hdr
, sizeof(hdr
));
715 if (unlikely(ret
!= sizeof(hdr
)))
716 panic("Failed to write pkt file header!\n");
721 #endif /* PCAP_IO_H */