build: announcement: also add v prefix to checkout command
[netsniff-ng.git] / pcap_io.h
blob5d338bb5ff7b825d1ba2391f3c738d54dcf074b2
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"
26 #define TCPDUMP_MAGIC 0xa1b2c3d4
27 #define ORIGINAL_TCPDUMP_MAGIC TCPDUMP_MAGIC
28 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
29 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
30 #define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
32 #define PCAP_VERSION_MAJOR 2
33 #define PCAP_VERSION_MINOR 4
34 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535
36 #define PCAP_TSOURCE_SOFTWARE 1
37 #define PCAP_TSOURCE_SYS_HARDWARE 2
38 #define PCAP_TSOURCE_RAW_HARDWARE 3
40 #define LINKTYPE_NULL 0
41 #define LINKTYPE_EN10MB 1
42 #define LINKTYPE_EN3MB 2
43 #define LINKTYPE_AX25 3
44 #define LINKTYPE_PRONET 4
45 #define LINKTYPE_CHAOS 5
46 #define LINKTYPE_IEEE802 6
47 #define LINKTYPE_SLIP 8
48 #define LINKTYPE_PPP 9
49 #define LINKTYPE_FDDI 10
50 #define LINKTYPE_ATM_CLIP 19
51 #define LINKTYPE_C_HDLC 104
52 #define LINKTYPE_IEEE802_11 105
53 #define LINKTYPE_FRELAY 107
54 #define LINKTYPE_ECONET 115
55 #define LINKTYPE_ARCNET_LINUX 129
56 #define LINKTYPE_LINUX_IRDA 144
57 #define LINKTYPE_CAN20B 190
58 #define LINKTYPE_IEEE802_15_4_LINUX 191
59 #define LINKTYPE_INFINIBAND 247
60 #define LINKTYPE_NETLINK 253
61 #define LINKTYPE_MAX 254
63 struct pcap_filehdr {
64 uint32_t magic;
65 uint16_t version_major;
66 uint16_t version_minor;
67 int32_t thiszone;
68 uint32_t sigfigs;
69 uint32_t snaplen;
70 uint32_t linktype;
73 struct pcap_timeval {
74 int32_t tv_sec;
75 int32_t tv_usec;
78 struct pcap_timeval_ns {
79 int32_t tv_sec;
80 int32_t tv_nsec;
83 struct pcap_pkthdr {
84 struct pcap_timeval ts;
85 uint32_t caplen;
86 uint32_t len;
89 struct pcap_pkthdr_ns {
90 struct pcap_timeval_ns ts;
91 uint32_t caplen;
92 uint32_t len;
95 struct pcap_pkthdr_kuz {
96 struct pcap_timeval ts;
97 uint32_t caplen;
98 uint32_t len;
99 uint32_t ifindex;
100 uint16_t protocol;
101 uint8_t pkttype;
104 struct pcap_pkthdr_bkm {
105 struct pcap_timeval_ns ts;
106 uint32_t caplen;
107 uint32_t len;
108 uint16_t tsource;
109 uint16_t ifindex;
110 uint16_t protocol;
111 uint8_t hatype;
112 uint8_t pkttype;
115 typedef union {
116 struct pcap_pkthdr ppo;
117 struct pcap_pkthdr_ns ppn;
118 struct pcap_pkthdr_kuz ppk;
119 struct pcap_pkthdr_bkm ppb;
120 uint8_t raw;
121 } pcap_pkthdr_t;
123 enum pcap_type {
124 DEFAULT = ORIGINAL_TCPDUMP_MAGIC,
125 NSEC = NSEC_TCPDUMP_MAGIC,
126 KUZNETZOV = KUZNETZOV_TCPDUMP_MAGIC,
127 BORKMANN = BORKMANN_TCPDUMP_MAGIC,
129 DEFAULT_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
130 NSEC_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC),
131 KUZNETZOV_SWAPPED = ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
132 BORKMANN_SWAPPED = ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
135 enum pcap_ops_groups {
136 PCAP_OPS_RW = 0,
137 PCAP_OPS_SG,
138 PCAP_OPS_MM,
141 enum pcap_mode {
142 PCAP_MODE_RD = 0,
143 PCAP_MODE_WR,
146 struct pcap_file_ops {
147 void (*init_once_pcap)(void);
148 int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
149 int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
150 int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
151 ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
152 const uint8_t *packet, size_t len);
153 ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
154 uint8_t *packet, size_t len);
155 void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
156 void (*fsync_pcap)(int fd);
159 extern const struct pcap_file_ops pcap_rw_ops __maybe_unused;
160 extern const struct pcap_file_ops pcap_sg_ops __maybe_unused;
161 extern const struct pcap_file_ops pcap_mm_ops __maybe_unused;
163 static inline uint16_t tp_to_pcap_tsource(uint32_t status)
165 if (status & TP_STATUS_TS_RAW_HARDWARE)
166 return PCAP_TSOURCE_RAW_HARDWARE;
167 else if (status & TP_STATUS_TS_SYS_HARDWARE)
168 return PCAP_TSOURCE_SYS_HARDWARE;
169 else if (status & TP_STATUS_TS_SOFTWARE)
170 return PCAP_TSOURCE_SOFTWARE;
171 else
172 return 0;
175 static inline int pcap_devtype_to_linktype(const char *ifname)
177 switch (device_type(ifname)) {
178 case ARPHRD_TUNNEL:
179 case ARPHRD_TUNNEL6:
180 case ARPHRD_LOOPBACK:
181 case ARPHRD_SIT:
182 case ARPHRD_IPDDP:
183 case ARPHRD_IPGRE:
184 case ARPHRD_IP6GRE:
185 case ARPHRD_ETHER: return LINKTYPE_EN10MB;
186 case ARPHRD_IEEE80211_PRISM:
187 case ARPHRD_IEEE80211_RADIOTAP:
188 case ARPHRD_IEEE80211: return LINKTYPE_IEEE802_11;
189 case ARPHRD_NETLINK: return LINKTYPE_NETLINK;
190 case ARPHRD_EETHER: return LINKTYPE_EN3MB;
191 case ARPHRD_AX25: return LINKTYPE_AX25;
192 case ARPHRD_CHAOS: return LINKTYPE_CHAOS;
193 case ARPHRD_PRONET: return LINKTYPE_PRONET;
194 case ARPHRD_IEEE802_TR:
195 case ARPHRD_IEEE802: return LINKTYPE_IEEE802;
196 case ARPHRD_INFINIBAND: return LINKTYPE_INFINIBAND;
197 case ARPHRD_ATM: return LINKTYPE_ATM_CLIP;
198 case ARPHRD_DLCI: return LINKTYPE_FRELAY;
199 case ARPHRD_ARCNET: return LINKTYPE_ARCNET_LINUX;
200 case ARPHRD_CSLIP:
201 case ARPHRD_CSLIP6:
202 case ARPHRD_SLIP6:
203 case ARPHRD_SLIP: return LINKTYPE_SLIP;
204 case ARPHRD_PPP: return LINKTYPE_PPP;
205 case ARPHRD_CAN: return LINKTYPE_CAN20B;
206 case ARPHRD_ECONET: return LINKTYPE_ECONET;
207 case ARPHRD_RAWHDLC:
208 case ARPHRD_CISCO: return LINKTYPE_C_HDLC;
209 case ARPHRD_FDDI: return LINKTYPE_FDDI;
210 case ARPHRD_IEEE802154_MONITOR:
211 case ARPHRD_IEEE802154: return LINKTYPE_IEEE802_15_4_LINUX;
212 case ARPHRD_IRDA: return LINKTYPE_LINUX_IRDA;
213 default: return LINKTYPE_NULL;
217 static inline void pcap_check_magic(uint32_t magic)
219 switch (magic) {
221 case ORIGINAL_TCPDUMP_MAGIC:
222 case NSEC_TCPDUMP_MAGIC:
223 case KUZNETZOV_TCPDUMP_MAGIC:
224 case BORKMANN_TCPDUMP_MAGIC:
226 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
227 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
228 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
229 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
230 break;
232 default:
233 panic("This file has not a valid pcap header\n");
237 static inline bool pcap_magic_is_swapped(uint32_t magic)
239 bool swapped = false;
241 switch (magic) {
242 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
243 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
244 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
245 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
246 swapped = true;
249 return swapped;
252 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
254 switch (type) {
255 #define CASE_RET_CAPLEN(what, member, swap) \
256 case (what): \
257 return (swap ? ___constant_swab32(phdr->member.caplen) : \
258 phdr->member.caplen)
260 CASE_RET_CAPLEN(DEFAULT, ppo, 0);
261 CASE_RET_CAPLEN(NSEC, ppn, 0);
262 CASE_RET_CAPLEN(KUZNETZOV, ppk, 0);
263 CASE_RET_CAPLEN(BORKMANN, ppb, 0);
265 CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
266 CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1);
267 CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
268 CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
270 default:
271 bug();
275 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
277 switch (type) {
278 #define CASE_SET_CAPLEN(what, member, swap) \
279 case (what): \
280 phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
281 break
283 CASE_SET_CAPLEN(DEFAULT, ppo, 0);
284 CASE_SET_CAPLEN(NSEC, ppn, 0);
285 CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
286 CASE_SET_CAPLEN(BORKMANN, ppb, 0);
288 CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
289 CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
290 CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
291 CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
293 default:
294 bug();
298 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
300 switch (type) {
301 #define CASE_RET_HDRLEN(what, member) \
302 case (what): \
303 return sizeof(phdr->member)
305 CASE_RET_HDRLEN(DEFAULT, ppo);
306 CASE_RET_HDRLEN(NSEC, ppn);
307 CASE_RET_HDRLEN(KUZNETZOV, ppk);
308 CASE_RET_HDRLEN(BORKMANN, ppb);
310 CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
311 CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
312 CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
313 CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
315 default:
316 bug();
320 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
322 switch (type) {
323 #define CASE_RET_TOTLEN(what, member, swap) \
324 case (what): \
325 return ((swap ? ___constant_swab32(phdr->member.caplen) : \
326 phdr->member.caplen) + sizeof(phdr->member))
328 CASE_RET_TOTLEN(DEFAULT, ppo, 0);
329 CASE_RET_TOTLEN(NSEC, ppn, 0);
330 CASE_RET_TOTLEN(KUZNETZOV, ppk, 0);
331 CASE_RET_TOTLEN(BORKMANN, ppb, 0);
333 CASE_RET_TOTLEN(DEFAULT_SWAPPED, ppo, 1);
334 CASE_RET_TOTLEN(NSEC_SWAPPED, ppn, 1);
335 CASE_RET_TOTLEN(KUZNETZOV_SWAPPED, ppk, 1);
336 CASE_RET_TOTLEN(BORKMANN_SWAPPED, ppb, 1);
338 default:
339 bug();
343 static inline void
344 __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, uint32_t snaplen,
345 uint32_t len, uint32_t status,
346 struct sockaddr_ll *sll, pcap_pkthdr_t *phdr,
347 enum pcap_type type)
349 switch (type) {
350 case DEFAULT:
351 phdr->ppo.ts.tv_sec = sec;
352 phdr->ppo.ts.tv_usec = nsec / 1000;
353 phdr->ppo.caplen = snaplen;
354 phdr->ppo.len = len;
355 break;
357 case DEFAULT_SWAPPED:
358 phdr->ppo.ts.tv_sec = ___constant_swab32(sec);
359 phdr->ppo.ts.tv_usec = ___constant_swab32(nsec / 1000);
360 phdr->ppo.caplen = ___constant_swab32(snaplen);
361 phdr->ppo.len = ___constant_swab32(len);
362 break;
364 case NSEC:
365 phdr->ppn.ts.tv_sec = sec;
366 phdr->ppn.ts.tv_nsec = nsec;
367 phdr->ppn.caplen = snaplen;
368 phdr->ppn.len = len;
369 break;
371 case NSEC_SWAPPED:
372 phdr->ppn.ts.tv_sec = ___constant_swab32(sec);
373 phdr->ppn.ts.tv_nsec = ___constant_swab32(nsec);
374 phdr->ppn.caplen = ___constant_swab32(snaplen);
375 phdr->ppn.len = ___constant_swab32(len);
376 break;
378 case KUZNETZOV:
379 phdr->ppk.ts.tv_sec = sec;
380 phdr->ppk.ts.tv_usec = nsec / 1000;
381 phdr->ppk.caplen = snaplen;
382 phdr->ppk.len = len;
383 phdr->ppk.ifindex = sll->sll_ifindex;
384 phdr->ppk.protocol = sll->sll_protocol;
385 phdr->ppk.pkttype = sll->sll_pkttype;
386 break;
388 case KUZNETZOV_SWAPPED:
389 phdr->ppk.ts.tv_sec = ___constant_swab32(sec);
390 phdr->ppk.ts.tv_usec = ___constant_swab32(nsec / 1000);
391 phdr->ppk.caplen = ___constant_swab32(snaplen);
392 phdr->ppk.len = ___constant_swab32(len);
393 phdr->ppk.ifindex = ___constant_swab32(sll->sll_ifindex);
394 phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
395 phdr->ppk.pkttype = sll->sll_pkttype;
396 break;
398 case BORKMANN:
399 phdr->ppb.ts.tv_sec = sec;
400 phdr->ppb.ts.tv_nsec = nsec;
401 phdr->ppb.caplen = snaplen;
402 phdr->ppb.len = len;
403 phdr->ppb.tsource = tp_to_pcap_tsource(status);
404 phdr->ppb.ifindex = (u16) sll->sll_ifindex;
405 phdr->ppb.protocol = sll->sll_protocol;
406 phdr->ppb.hatype = sll->sll_hatype;
407 phdr->ppb.pkttype = sll->sll_pkttype;
408 break;
410 case BORKMANN_SWAPPED:
411 phdr->ppb.ts.tv_sec = ___constant_swab32(sec);
412 phdr->ppb.ts.tv_nsec = ___constant_swab32(nsec);
413 phdr->ppb.caplen = ___constant_swab32(snaplen);
414 phdr->ppb.len = ___constant_swab32(len);
415 phdr->ppb.tsource = ___constant_swab16(tp_to_pcap_tsource(status));
416 phdr->ppb.ifindex = ___constant_swab16((u16) sll->sll_ifindex);
417 phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
418 phdr->ppb.hatype = sll->sll_hatype;
419 phdr->ppb.pkttype = sll->sll_pkttype;
420 break;
422 default:
423 bug();
427 /* We need to do this crap here since member offsets are not interleaved,
428 * so hopfully the compiler does his job here. ;-)
431 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
432 struct sockaddr_ll *sll,
433 pcap_pkthdr_t *phdr,
434 enum pcap_type type)
436 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
437 thdr->tp_snaplen, thdr->tp_len,
438 thdr->tp_status, sll, phdr, type);
441 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
442 struct sockaddr_ll *sll,
443 pcap_pkthdr_t *phdr,
444 enum pcap_type type)
446 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
447 thdr->tp_snaplen, thdr->tp_len,
448 0, sll, phdr, type);
451 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
452 enum pcap_type type,
453 struct tpacket2_hdr *thdr)
455 switch (type) {
456 case DEFAULT:
457 thdr->tp_sec = phdr->ppo.ts.tv_sec;
458 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
459 thdr->tp_snaplen = phdr->ppo.caplen;
460 thdr->tp_len = phdr->ppo.len;
461 break;
463 case DEFAULT_SWAPPED:
464 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
465 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
466 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
467 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
468 break;
470 case NSEC:
471 thdr->tp_sec = phdr->ppn.ts.tv_sec;
472 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
473 thdr->tp_snaplen = phdr->ppn.caplen;
474 thdr->tp_len = phdr->ppn.len;
475 break;
477 case NSEC_SWAPPED:
478 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
479 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
480 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
481 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
482 break;
484 case KUZNETZOV:
485 thdr->tp_sec = phdr->ppk.ts.tv_sec;
486 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
487 thdr->tp_snaplen = phdr->ppk.caplen;
488 thdr->tp_len = phdr->ppk.len;
489 break;
491 case KUZNETZOV_SWAPPED:
492 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
493 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
494 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
495 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
496 break;
498 case BORKMANN:
499 thdr->tp_sec = phdr->ppb.ts.tv_sec;
500 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
501 thdr->tp_snaplen = phdr->ppb.caplen;
502 thdr->tp_len = phdr->ppb.len;
503 break;
505 case BORKMANN_SWAPPED:
506 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
507 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
508 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
509 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
510 break;
512 default:
513 bug();
517 #define FEATURE_UNKNOWN (0 << 0)
518 #define FEATURE_TIMEVAL_MS (1 << 0)
519 #define FEATURE_TIMEVAL_NS (1 << 1)
520 #define FEATURE_LEN (1 << 2)
521 #define FEATURE_CAPLEN (1 << 3)
522 #define FEATURE_IFINDEX (1 << 4)
523 #define FEATURE_PROTO (1 << 5)
524 #define FEATURE_HATYPE (1 << 6)
525 #define FEATURE_PKTTYPE (1 << 7)
526 #define FEATURE_TSOURCE (1 << 8)
528 struct pcap_magic_type {
529 const uint32_t magic;
530 const char *desc;
531 const uint16_t features;
534 static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
536 .magic = ORIGINAL_TCPDUMP_MAGIC,
537 .desc = "tcpdump-capable pcap",
538 .features = FEATURE_TIMEVAL_MS |
539 FEATURE_LEN |
540 FEATURE_CAPLEN,
541 }, {
542 .magic = NSEC_TCPDUMP_MAGIC,
543 .desc = "tcpdump-capable pcap with ns resolution",
544 .features = FEATURE_TIMEVAL_NS |
545 FEATURE_LEN |
546 FEATURE_CAPLEN,
547 }, {
548 .magic = KUZNETZOV_TCPDUMP_MAGIC,
549 .desc = "Alexey Kuznetzov's pcap",
550 .features = FEATURE_TIMEVAL_MS |
551 FEATURE_LEN |
552 FEATURE_CAPLEN |
553 FEATURE_IFINDEX |
554 FEATURE_PROTO |
555 FEATURE_PKTTYPE,
556 }, {
557 .magic = BORKMANN_TCPDUMP_MAGIC,
558 .desc = "netsniff-ng pcap",
559 .features = FEATURE_TIMEVAL_NS |
560 FEATURE_LEN |
561 FEATURE_CAPLEN |
562 FEATURE_TSOURCE |
563 FEATURE_IFINDEX |
564 FEATURE_PROTO |
565 FEATURE_HATYPE |
566 FEATURE_PKTTYPE,
570 static inline void pcap_dump_type_features(void)
572 size_t i;
574 for (i = 0; i < array_size(pcap_magic_types); ++i) {
575 printf("%s:\n", pcap_magic_types[i].desc);
576 printf(" magic: 0x%x (swapped: 0x%x)\n",
577 pcap_magic_types[i].magic,
578 ___constant_swab32(pcap_magic_types[i].magic));
579 printf(" features:\n");
581 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
582 printf(" unknown\n");
583 continue;
586 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
587 printf(" timeval in us\n");
588 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
589 printf(" timeval in ns\n");
590 if (pcap_magic_types[i].features & FEATURE_TSOURCE)
591 printf(" timestamp source\n");
592 if (pcap_magic_types[i].features & FEATURE_LEN)
593 printf(" packet length\n");
594 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
595 printf(" packet cap-length\n");
596 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
597 printf(" packet ifindex\n");
598 if (pcap_magic_types[i].features & FEATURE_PROTO)
599 printf(" packet protocol\n");
600 if (pcap_magic_types[i].features & FEATURE_HATYPE)
601 printf(" hardware type\n");
602 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
603 printf(" packet type\n");
607 static const char *pcap_ops_group_to_str[] __maybe_unused = {
608 [PCAP_OPS_RW] = "rw",
609 [PCAP_OPS_SG] = "sg",
610 [PCAP_OPS_MM] = "mm",
613 static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
614 [PCAP_OPS_RW] = &pcap_rw_ops,
615 [PCAP_OPS_SG] = &pcap_sg_ops,
616 [PCAP_OPS_MM] = &pcap_mm_ops,
619 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
620 uint32_t linktype, int32_t thiszone,
621 uint32_t snaplen)
623 bool swapped = pcap_magic_is_swapped(magic);
625 hdr->magic = magic;
626 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
627 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
628 hdr->thiszone = swapped ? (int32_t) ___constant_swab32(thiszone) : thiszone;
629 hdr->sigfigs = 0;
630 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
631 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
634 static const bool pcap_supported_linktypes[LINKTYPE_MAX] __maybe_unused = {
635 /* tunX captures from wireshark/tcpdump, non-portable */
636 [101] = true, [102] = true, [103] = true,
637 [LINKTYPE_NULL] = true,
638 [LINKTYPE_EN10MB] = true,
639 [LINKTYPE_EN3MB] = true,
640 [LINKTYPE_AX25] = true,
641 [LINKTYPE_PRONET] = true,
642 [LINKTYPE_CHAOS] = true,
643 [LINKTYPE_IEEE802] = true,
644 [LINKTYPE_SLIP] = true,
645 [LINKTYPE_PPP] = true,
646 [LINKTYPE_FDDI] = true,
647 [LINKTYPE_ATM_CLIP] = true,
648 [LINKTYPE_C_HDLC] = true,
649 [LINKTYPE_IEEE802_11] = true,
650 [LINKTYPE_FRELAY] = true,
651 [LINKTYPE_ECONET] = true,
652 [LINKTYPE_ARCNET_LINUX] = true,
653 [LINKTYPE_LINUX_IRDA] = true,
654 [LINKTYPE_CAN20B] = true,
655 [LINKTYPE_IEEE802_15_4_LINUX] = true,
656 [LINKTYPE_INFINIBAND] = true,
657 [LINKTYPE_NETLINK] = true,
660 static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
662 bool good = false;
663 uint32_t linktype_swab = bswap_32(hdr->linktype);
664 pcap_check_magic(hdr->magic);
666 if (hdr->linktype < LINKTYPE_MAX) {
667 if (pcap_supported_linktypes[hdr->linktype])
668 good = true;
671 if (linktype_swab < LINKTYPE_MAX) {
672 if (pcap_supported_linktypes[linktype_swab])
673 good = true;
676 if (!good)
677 panic("This file has an unsupported pcap link type (%d)!\n", hdr->linktype);
678 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
679 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
680 panic("This file has not a valid pcap header\n");
681 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
682 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
683 panic("This file has not a valid pcap header\n");
686 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
687 uint32_t *linktype) __maybe_unused;
689 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
691 ssize_t ret;
692 struct pcap_filehdr hdr;
694 ret = read(fd, &hdr, sizeof(hdr));
695 if (unlikely(ret != sizeof(hdr)))
696 return -EIO;
698 pcap_validate_header(&hdr);
700 *magic = hdr.magic;
701 *linktype = hdr.linktype;
703 return 0;
706 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
707 uint32_t linktype) __maybe_unused;
709 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
711 ssize_t ret;
712 struct pcap_filehdr hdr;
714 memset(&hdr, 0, sizeof(hdr));
716 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
718 ret = write_or_die(fd, &hdr, sizeof(hdr));
719 if (unlikely(ret != sizeof(hdr)))
720 panic("Failed to write pkt file header!\n");
722 return 0;
725 #endif /* PCAP_IO_H */