proto: Remove unnecessary include of hash.h
[netsniff-ng.git] / pcap_io.h
blob061c214769b8de4d7d9a0758aedae4fe7b1dd01d
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)(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;
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_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;
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 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
420 struct sockaddr_ll *sll,
421 pcap_pkthdr_t *phdr,
422 enum pcap_type type)
424 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
425 thdr->tp_snaplen, thdr->tp_len,
426 0, sll, phdr, type);
429 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
430 enum pcap_type type,
431 struct tpacket2_hdr *thdr,
432 struct sockaddr_ll *sll)
434 switch (type) {
435 case DEFAULT:
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;
440 break;
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);
447 break;
449 case NSEC:
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;
454 break;
456 case NSEC_SWAPPED:
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);
461 break;
463 case KUZNETZOV:
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;
468 if (sll) {
469 sll->sll_ifindex = phdr->ppk.ifindex;
470 sll->sll_protocol = phdr->ppk.protocol;
471 sll->sll_pkttype = phdr->ppk.pkttype;
473 break;
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);
480 if (sll) {
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;
485 break;
487 case BORKMANN:
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;
492 if (sll) {
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;
498 break;
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);
505 if (sll) {
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;
511 break;
513 default:
514 bug();
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;
531 const char *desc;
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 |
540 FEATURE_LEN |
541 FEATURE_CAPLEN,
542 }, {
543 .magic = NSEC_TCPDUMP_MAGIC,
544 .desc = "tcpdump-capable pcap with ns resolution",
545 .features = FEATURE_TIMEVAL_NS |
546 FEATURE_LEN |
547 FEATURE_CAPLEN,
548 }, {
549 .magic = KUZNETZOV_TCPDUMP_MAGIC,
550 .desc = "Alexey Kuznetzov's pcap",
551 .features = FEATURE_TIMEVAL_MS |
552 FEATURE_LEN |
553 FEATURE_CAPLEN |
554 FEATURE_IFINDEX |
555 FEATURE_PROTO |
556 FEATURE_PKTTYPE,
557 }, {
558 .magic = BORKMANN_TCPDUMP_MAGIC,
559 .desc = "netsniff-ng pcap",
560 .features = FEATURE_TIMEVAL_NS |
561 FEATURE_LEN |
562 FEATURE_CAPLEN |
563 FEATURE_TSOURCE |
564 FEATURE_IFINDEX |
565 FEATURE_PROTO |
566 FEATURE_HATYPE |
567 FEATURE_PKTTYPE,
571 static inline void pcap_dump_type_features(void)
573 size_t i;
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");
584 continue;
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,
622 uint32_t snaplen)
624 bool swapped = pcap_magic_is_swapped(magic);
626 hdr->magic = 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;
630 hdr->sigfigs = 0;
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)
663 bool good = false;
664 uint32_t linktype;
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];
672 if (!good)
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)
687 ssize_t ret;
688 struct pcap_filehdr hdr;
690 ret = read(fd, &hdr, sizeof(hdr));
691 if (unlikely(ret != sizeof(hdr)))
692 return -EIO;
694 pcap_validate_header(&hdr);
696 *magic = hdr.magic;
697 *linktype = hdr.linktype;
699 return 0;
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)
707 ssize_t ret;
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");
718 return 0;
721 #endif /* PCAP_IO_H */