man: add description about different pcap formats
[netsniff-ng.git] / pcap_io.h
blob09d89fb49bbc4c1179e10da0c1cb9426dd2a4368
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 PCAP_TSOURCE_SOFTWARE 1
33 #define PCAP_TSOURCE_SYS_HARDWARE 2
34 #define PCAP_TSOURCE_RAW_HARDWARE 3
36 #define LINKTYPE_EN10MB 1 /* Ethernet (10Mb) */
37 #define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 wireless */
39 struct pcap_filehdr {
40 uint32_t magic;
41 uint16_t version_major;
42 uint16_t version_minor;
43 int32_t thiszone;
44 uint32_t sigfigs;
45 uint32_t snaplen;
46 uint32_t linktype;
49 struct pcap_timeval {
50 int32_t tv_sec;
51 int32_t tv_usec;
54 struct pcap_timeval_ns {
55 int32_t tv_sec;
56 int32_t tv_nsec;
59 struct pcap_pkthdr {
60 struct pcap_timeval ts;
61 uint32_t caplen;
62 uint32_t len;
65 struct pcap_pkthdr_ns {
66 struct pcap_timeval_ns ts;
67 uint32_t caplen;
68 uint32_t len;
71 struct pcap_pkthdr_kuz {
72 struct pcap_timeval ts;
73 uint32_t caplen;
74 uint32_t len;
75 int ifindex;
76 uint16_t protocol;
77 uint8_t pkttype;
80 struct pcap_pkthdr_bkm {
81 struct pcap_timeval_ns ts;
82 uint32_t caplen;
83 uint32_t len;
84 uint16_t tsource;
85 uint16_t ifindex;
86 uint16_t protocol;
87 uint8_t hatype;
88 uint8_t pkttype;
91 typedef union {
92 struct pcap_pkthdr ppo;
93 struct pcap_pkthdr_ns ppn;
94 struct pcap_pkthdr_kuz ppk;
95 struct pcap_pkthdr_bkm ppb;
96 uint8_t raw;
97 } pcap_pkthdr_t;
99 enum pcap_type {
100 DEFAULT = ORIGINAL_TCPDUMP_MAGIC,
101 NSEC = NSEC_TCPDUMP_MAGIC,
102 KUZNETZOV = KUZNETZOV_TCPDUMP_MAGIC,
103 BORKMANN = BORKMANN_TCPDUMP_MAGIC,
105 DEFAULT_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
106 NSEC_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC),
107 KUZNETZOV_SWAPPED = ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
108 BORKMANN_SWAPPED = ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
111 enum pcap_ops_groups {
112 PCAP_OPS_RW = 0,
113 PCAP_OPS_SG,
114 PCAP_OPS_MM,
117 enum pcap_mode {
118 PCAP_MODE_RD = 0,
119 PCAP_MODE_WR,
122 struct pcap_file_ops {
123 void (*init_once_pcap)(void);
124 int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
125 int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
126 int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
127 ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
128 const uint8_t *packet, size_t len);
129 ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
130 uint8_t *packet, size_t len);
131 void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
132 void (*fsync_pcap)(int fd);
135 extern const struct pcap_file_ops pcap_rw_ops;
136 extern const struct pcap_file_ops pcap_sg_ops;
137 extern const struct pcap_file_ops pcap_mm_ops;
139 static inline uint16_t tp_to_pcap_tsource(uint32_t status)
141 if (status & TP_STATUS_TS_RAW_HARDWARE)
142 return PCAP_TSOURCE_RAW_HARDWARE;
143 else if (status & TP_STATUS_TS_SYS_HARDWARE)
144 return PCAP_TSOURCE_SYS_HARDWARE;
145 else if (status & TP_STATUS_TS_SOFTWARE)
146 return PCAP_TSOURCE_SOFTWARE;
147 else
148 return 0;
151 static inline void pcap_check_magic(uint32_t magic)
153 switch (magic) {
155 case ORIGINAL_TCPDUMP_MAGIC:
156 case NSEC_TCPDUMP_MAGIC:
157 case KUZNETZOV_TCPDUMP_MAGIC:
158 case BORKMANN_TCPDUMP_MAGIC:
160 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
161 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
162 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
163 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
164 break;
166 default:
167 panic("This file has not a valid pcap header\n");
171 static inline bool pcap_magic_is_swapped(uint32_t magic)
173 bool swapped = false;
175 switch (magic) {
176 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
177 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
178 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
179 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
180 swapped = true;
183 return swapped;
186 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
188 switch (type) {
189 #define CASE_RET_CAPLEN(what, member, swap) \
190 case (what): \
191 return (swap ? ___constant_swab32(phdr->member.caplen) : \
192 phdr->member.caplen)
194 CASE_RET_CAPLEN(DEFAULT, ppo, 0);
195 CASE_RET_CAPLEN(NSEC, ppn, 0);
196 CASE_RET_CAPLEN(KUZNETZOV, ppk, 0);
197 CASE_RET_CAPLEN(BORKMANN, ppb, 0);
199 CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
200 CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1);
201 CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
202 CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
204 default:
205 bug();
209 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
211 switch (type) {
212 #define CASE_SET_CAPLEN(what, member, swap) \
213 case (what): \
214 phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
215 break
217 CASE_SET_CAPLEN(DEFAULT, ppo, 0);
218 CASE_SET_CAPLEN(NSEC, ppn, 0);
219 CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
220 CASE_SET_CAPLEN(BORKMANN, ppb, 0);
222 CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
223 CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
224 CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
225 CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
227 default:
228 bug();
232 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
234 switch (type) {
235 #define CASE_RET_HDRLEN(what, member) \
236 case (what): \
237 return sizeof(phdr->member)
239 CASE_RET_HDRLEN(DEFAULT, ppo);
240 CASE_RET_HDRLEN(NSEC, ppn);
241 CASE_RET_HDRLEN(KUZNETZOV, ppk);
242 CASE_RET_HDRLEN(BORKMANN, ppb);
244 CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
245 CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
246 CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
247 CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
249 default:
250 bug();
254 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
256 switch (type) {
257 #define CASE_RET_TOTLEN(what, member, swap) \
258 case (what): \
259 return ((swap ? ___constant_swab32(phdr->member.caplen) : \
260 phdr->member.caplen) + sizeof(phdr->member))
262 CASE_RET_TOTLEN(DEFAULT, ppo, 0);
263 CASE_RET_TOTLEN(NSEC, ppn, 0);
264 CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
265 CASE_RET_TOTLEN(BORKMANN, ppb, 0);
267 CASE_RET_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
268 CASE_RET_TOTLEN(NSEC_SWAPPED, ppn, 1);
269 CASE_RET_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
270 CASE_RET_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
272 default:
273 bug();
277 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
278 struct sockaddr_ll *sll,
279 pcap_pkthdr_t *phdr,
280 enum pcap_type type)
282 switch (type) {
283 case DEFAULT:
284 phdr->ppo.ts.tv_sec = thdr->tp_sec;
285 phdr->ppo.ts.tv_usec = thdr->tp_nsec / 1000;
286 phdr->ppo.caplen = thdr->tp_snaplen;
287 phdr->ppo.len = thdr->tp_len;
288 break;
290 case DEFAULT_SWAPPED:
291 phdr->ppo.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
292 phdr->ppo.ts.tv_usec = ___constant_swab32(thdr->tp_nsec / 1000);
293 phdr->ppo.caplen = ___constant_swab32(thdr->tp_snaplen);
294 phdr->ppo.len = ___constant_swab32(thdr->tp_len);
295 break;
297 case NSEC:
298 phdr->ppn.ts.tv_sec = thdr->tp_sec;
299 phdr->ppn.ts.tv_nsec = thdr->tp_nsec;
300 phdr->ppn.caplen = thdr->tp_snaplen;
301 phdr->ppn.len = thdr->tp_len;
302 break;
304 case NSEC_SWAPPED:
305 phdr->ppn.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
306 phdr->ppn.ts.tv_nsec = ___constant_swab32(thdr->tp_nsec);
307 phdr->ppn.caplen = ___constant_swab32(thdr->tp_snaplen);
308 phdr->ppn.len = ___constant_swab32(thdr->tp_len);
309 break;
311 case KUZNETZOV:
312 phdr->ppk.ts.tv_sec = thdr->tp_sec;
313 phdr->ppk.ts.tv_usec = thdr->tp_nsec / 1000;
314 phdr->ppk.caplen = thdr->tp_snaplen;
315 phdr->ppk.len = thdr->tp_len;
316 phdr->ppk.ifindex = sll->sll_ifindex;
317 phdr->ppk.protocol = sll->sll_protocol;
318 phdr->ppk.pkttype = sll->sll_pkttype;
319 break;
321 case KUZNETZOV_SWAPPED:
322 phdr->ppk.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
323 phdr->ppk.ts.tv_usec = ___constant_swab32(thdr->tp_nsec / 1000);
324 phdr->ppk.caplen = ___constant_swab32(thdr->tp_snaplen);
325 phdr->ppk.len = ___constant_swab32(thdr->tp_len);
326 phdr->ppk.ifindex = ___constant_swab32((u32) sll->sll_ifindex);
327 phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
328 phdr->ppk.pkttype = sll->sll_pkttype;
329 break;
331 case BORKMANN:
332 phdr->ppb.ts.tv_sec = thdr->tp_sec;
333 phdr->ppb.ts.tv_nsec = thdr->tp_nsec;
334 phdr->ppb.caplen = thdr->tp_snaplen;
335 phdr->ppb.len = thdr->tp_len;
336 phdr->ppb.tsource = tp_to_pcap_tsource(thdr->tp_status);
337 phdr->ppb.ifindex = (u16) sll->sll_ifindex;
338 phdr->ppb.protocol = sll->sll_protocol;
339 phdr->ppb.hatype = sll->sll_hatype;
340 phdr->ppb.pkttype = sll->sll_pkttype;
341 break;
343 case BORKMANN_SWAPPED:
344 phdr->ppb.ts.tv_sec = ___constant_swab32(thdr->tp_sec);
345 phdr->ppb.ts.tv_nsec = ___constant_swab32(thdr->tp_nsec);
346 phdr->ppb.caplen = ___constant_swab32(thdr->tp_snaplen);
347 phdr->ppb.len = ___constant_swab32(thdr->tp_len);
348 phdr->ppb.tsource = ___constant_swab16(tp_to_pcap_tsource(thdr->tp_status));
349 phdr->ppb.ifindex = ___constant_swab16((u32) sll->sll_ifindex);
350 phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
351 phdr->ppb.hatype = sll->sll_hatype;
352 phdr->ppb.pkttype = sll->sll_pkttype;
353 break;
355 default:
356 bug();
360 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
361 enum pcap_type type,
362 struct tpacket2_hdr *thdr,
363 struct sockaddr_ll *sll)
365 switch (type) {
366 case DEFAULT:
367 thdr->tp_sec = phdr->ppo.ts.tv_sec;
368 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
369 thdr->tp_snaplen = phdr->ppo.caplen;
370 thdr->tp_len = phdr->ppo.len;
371 break;
373 case DEFAULT_SWAPPED:
374 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
375 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
376 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
377 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
378 break;
380 case NSEC:
381 thdr->tp_sec = phdr->ppn.ts.tv_sec;
382 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
383 thdr->tp_snaplen = phdr->ppn.caplen;
384 thdr->tp_len = phdr->ppn.len;
385 break;
387 case NSEC_SWAPPED:
388 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
389 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
390 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
391 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
392 break;
394 case KUZNETZOV:
395 thdr->tp_sec = phdr->ppk.ts.tv_sec;
396 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
397 thdr->tp_snaplen = phdr->ppk.caplen;
398 thdr->tp_len = phdr->ppk.len;
399 break;
401 case KUZNETZOV_SWAPPED:
402 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
403 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
404 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
405 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
406 break;
408 case BORKMANN:
409 thdr->tp_sec = phdr->ppb.ts.tv_sec;
410 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
411 thdr->tp_snaplen = phdr->ppb.caplen;
412 thdr->tp_len = phdr->ppb.len;
413 break;
415 case BORKMANN_SWAPPED:
416 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
417 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
418 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
419 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
420 break;
422 default:
423 bug();
427 #define FEATURE_UNKNOWN (0 << 0)
428 #define FEATURE_TIMEVAL_MS (1 << 0)
429 #define FEATURE_TIMEVAL_NS (1 << 1)
430 #define FEATURE_LEN (1 << 2)
431 #define FEATURE_CAPLEN (1 << 3)
432 #define FEATURE_IFINDEX (1 << 4)
433 #define FEATURE_PROTO (1 << 5)
434 #define FEATURE_HATYPE (1 << 6)
435 #define FEATURE_PKTTYPE (1 << 7)
436 #define FEATURE_TSOURCE (1 << 8)
438 struct pcap_magic_type {
439 const uint32_t magic;
440 const char *desc;
441 const uint16_t features;
444 static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
446 .magic = ORIGINAL_TCPDUMP_MAGIC,
447 .desc = "tcpdump-capable pcap",
448 .features = FEATURE_TIMEVAL_MS |
449 FEATURE_LEN |
450 FEATURE_CAPLEN,
451 }, {
452 .magic = NSEC_TCPDUMP_MAGIC,
453 .desc = "tcpdump-capable pcap with ns resolution",
454 .features = FEATURE_TIMEVAL_NS |
455 FEATURE_LEN |
456 FEATURE_CAPLEN,
457 }, {
458 .magic = KUZNETZOV_TCPDUMP_MAGIC,
459 .desc = "Alexey Kuznetzov's pcap",
460 .features = FEATURE_TIMEVAL_MS |
461 FEATURE_LEN |
462 FEATURE_CAPLEN |
463 FEATURE_IFINDEX |
464 FEATURE_PROTO |
465 FEATURE_PKTTYPE,
466 }, {
467 .magic = BORKMANN_TCPDUMP_MAGIC,
468 .desc = "netsniff-ng pcap",
469 .features = FEATURE_TIMEVAL_NS |
470 FEATURE_LEN |
471 FEATURE_CAPLEN |
472 FEATURE_TSOURCE |
473 FEATURE_IFINDEX |
474 FEATURE_PROTO |
475 FEATURE_HATYPE |
476 FEATURE_PKTTYPE,
480 static inline void pcap_dump_type_features(void)
482 int i;
484 for (i = 0; i < array_size(pcap_magic_types); ++i) {
485 printf("%s:\n", pcap_magic_types[i].desc);
486 printf(" magic: 0x%x (swapped: 0x%x)\n",
487 pcap_magic_types[i].magic,
488 ___constant_swab32(pcap_magic_types[i].magic));
489 printf(" features:\n");
491 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
492 printf(" unknown\n");
493 continue;
496 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
497 printf(" timeval in us\n");
498 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
499 printf(" timeval in ns\n");
500 if (pcap_magic_types[i].features & FEATURE_TSOURCE)
501 printf(" timestamp source\n");
502 if (pcap_magic_types[i].features & FEATURE_LEN)
503 printf(" packet length\n");
504 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
505 printf(" packet cap-length\n");
506 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
507 printf(" packet ifindex\n");
508 if (pcap_magic_types[i].features & FEATURE_PROTO)
509 printf(" packet protocol\n");
510 if (pcap_magic_types[i].features & FEATURE_HATYPE)
511 printf(" hardware type\n");
512 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
513 printf(" packet type\n");
517 static const char *pcap_ops_group_to_str[] __maybe_unused = {
518 [PCAP_OPS_RW] = "rw",
519 [PCAP_OPS_SG] = "sg",
520 [PCAP_OPS_MM] = "mm",
523 static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
524 [PCAP_OPS_RW] = &pcap_rw_ops,
525 [PCAP_OPS_SG] = &pcap_sg_ops,
526 [PCAP_OPS_MM] = &pcap_mm_ops,
529 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
530 uint32_t linktype, int32_t thiszone,
531 uint32_t snaplen)
533 bool swapped = pcap_magic_is_swapped(magic);
535 hdr->magic = magic;
536 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
537 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
538 hdr->thiszone = swapped ? ___constant_swab32(thiszone) : thiszone;
539 hdr->sigfigs = 0;
540 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
541 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
544 static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
546 pcap_check_magic(hdr->magic);
548 switch (hdr->linktype) {
549 case LINKTYPE_EN10MB:
550 case LINKTYPE_IEEE802_11:
551 case ___constant_swab32(LINKTYPE_EN10MB):
552 case ___constant_swab32(LINKTYPE_IEEE802_11):
553 break;
554 default:
555 panic("This file has not a valid pcap header\n");
558 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
559 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
560 panic("This file has not a valid pcap header\n");
561 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
562 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
563 panic("This file has not a valid pcap header\n");
566 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
567 uint32_t *linktype) __maybe_unused;
569 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
571 ssize_t ret;
572 struct pcap_filehdr hdr;
574 ret = read(fd, &hdr, sizeof(hdr));
575 if (unlikely(ret != sizeof(hdr)))
576 return -EIO;
578 pcap_validate_header(&hdr);
580 *magic = hdr.magic;
581 *linktype = hdr.linktype;
583 return 0;
586 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
587 uint32_t linktype) __maybe_unused;
589 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
591 ssize_t ret;
592 struct pcap_filehdr hdr;
594 memset(&hdr, 0, sizeof(hdr));
596 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
598 ret = write_or_die(fd, &hdr, sizeof(hdr));
599 if (unlikely(ret != sizeof(hdr)))
600 panic("Failed to write pkt file header!\n");
602 return 0;
605 #endif /* PCAP_IO_H */