build: add DESTDIR support
[netsniff-ng.git] / pcap_io.h
blob41fe4706eef1569b5d8ffab6fad2020aa4515e30
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,
454 struct sockaddr_ll *sll)
456 switch (type) {
457 case DEFAULT:
458 thdr->tp_sec = phdr->ppo.ts.tv_sec;
459 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
460 thdr->tp_snaplen = phdr->ppo.caplen;
461 thdr->tp_len = phdr->ppo.len;
462 break;
464 case DEFAULT_SWAPPED:
465 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
466 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
467 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
468 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
469 break;
471 case NSEC:
472 thdr->tp_sec = phdr->ppn.ts.tv_sec;
473 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
474 thdr->tp_snaplen = phdr->ppn.caplen;
475 thdr->tp_len = phdr->ppn.len;
476 break;
478 case NSEC_SWAPPED:
479 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
480 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
481 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
482 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
483 break;
485 case KUZNETZOV:
486 thdr->tp_sec = phdr->ppk.ts.tv_sec;
487 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
488 thdr->tp_snaplen = phdr->ppk.caplen;
489 thdr->tp_len = phdr->ppk.len;
490 if (sll) {
491 sll->sll_ifindex = phdr->ppk.ifindex;
492 sll->sll_protocol = phdr->ppk.protocol;
493 sll->sll_pkttype = phdr->ppk.pkttype;
495 break;
497 case KUZNETZOV_SWAPPED:
498 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
499 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
500 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
501 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
502 if (sll) {
503 sll->sll_ifindex = ___constant_swab32(phdr->ppk.ifindex);
504 sll->sll_protocol = ___constant_swab16(phdr->ppk.protocol);
505 sll->sll_pkttype = phdr->ppk.pkttype;
507 break;
509 case BORKMANN:
510 thdr->tp_sec = phdr->ppb.ts.tv_sec;
511 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
512 thdr->tp_snaplen = phdr->ppb.caplen;
513 thdr->tp_len = phdr->ppb.len;
514 if (sll) {
515 sll->sll_ifindex = phdr->ppb.ifindex;
516 sll->sll_protocol = phdr->ppb.protocol;
517 sll->sll_hatype = phdr->ppb.hatype;
518 sll->sll_pkttype = phdr->ppb.pkttype;
520 break;
522 case BORKMANN_SWAPPED:
523 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
524 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
525 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
526 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
527 if (sll) {
528 sll->sll_ifindex = ___constant_swab16(phdr->ppb.ifindex);
529 sll->sll_protocol = ___constant_swab16(phdr->ppb.protocol);
530 sll->sll_hatype = phdr->ppb.hatype;
531 sll->sll_pkttype = phdr->ppb.pkttype;
533 break;
535 default:
536 bug();
540 #define FEATURE_UNKNOWN (0 << 0)
541 #define FEATURE_TIMEVAL_MS (1 << 0)
542 #define FEATURE_TIMEVAL_NS (1 << 1)
543 #define FEATURE_LEN (1 << 2)
544 #define FEATURE_CAPLEN (1 << 3)
545 #define FEATURE_IFINDEX (1 << 4)
546 #define FEATURE_PROTO (1 << 5)
547 #define FEATURE_HATYPE (1 << 6)
548 #define FEATURE_PKTTYPE (1 << 7)
549 #define FEATURE_TSOURCE (1 << 8)
551 struct pcap_magic_type {
552 const uint32_t magic;
553 const char *desc;
554 const uint16_t features;
557 static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
559 .magic = ORIGINAL_TCPDUMP_MAGIC,
560 .desc = "tcpdump-capable pcap",
561 .features = FEATURE_TIMEVAL_MS |
562 FEATURE_LEN |
563 FEATURE_CAPLEN,
564 }, {
565 .magic = NSEC_TCPDUMP_MAGIC,
566 .desc = "tcpdump-capable pcap with ns resolution",
567 .features = FEATURE_TIMEVAL_NS |
568 FEATURE_LEN |
569 FEATURE_CAPLEN,
570 }, {
571 .magic = KUZNETZOV_TCPDUMP_MAGIC,
572 .desc = "Alexey Kuznetzov's pcap",
573 .features = FEATURE_TIMEVAL_MS |
574 FEATURE_LEN |
575 FEATURE_CAPLEN |
576 FEATURE_IFINDEX |
577 FEATURE_PROTO |
578 FEATURE_PKTTYPE,
579 }, {
580 .magic = BORKMANN_TCPDUMP_MAGIC,
581 .desc = "netsniff-ng pcap",
582 .features = FEATURE_TIMEVAL_NS |
583 FEATURE_LEN |
584 FEATURE_CAPLEN |
585 FEATURE_TSOURCE |
586 FEATURE_IFINDEX |
587 FEATURE_PROTO |
588 FEATURE_HATYPE |
589 FEATURE_PKTTYPE,
593 static inline void pcap_dump_type_features(void)
595 size_t i;
597 for (i = 0; i < array_size(pcap_magic_types); ++i) {
598 printf("%s:\n", pcap_magic_types[i].desc);
599 printf(" magic: 0x%x (swapped: 0x%x)\n",
600 pcap_magic_types[i].magic,
601 ___constant_swab32(pcap_magic_types[i].magic));
602 printf(" features:\n");
604 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
605 printf(" unknown\n");
606 continue;
609 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
610 printf(" timeval in us\n");
611 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
612 printf(" timeval in ns\n");
613 if (pcap_magic_types[i].features & FEATURE_TSOURCE)
614 printf(" timestamp source\n");
615 if (pcap_magic_types[i].features & FEATURE_LEN)
616 printf(" packet length\n");
617 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
618 printf(" packet cap-length\n");
619 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
620 printf(" packet ifindex\n");
621 if (pcap_magic_types[i].features & FEATURE_PROTO)
622 printf(" packet protocol\n");
623 if (pcap_magic_types[i].features & FEATURE_HATYPE)
624 printf(" hardware type\n");
625 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
626 printf(" packet type\n");
630 static const char *pcap_ops_group_to_str[] __maybe_unused = {
631 [PCAP_OPS_RW] = "read/write",
632 [PCAP_OPS_SG] = "scatter-gather",
633 [PCAP_OPS_MM] = "mmap",
636 static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
637 [PCAP_OPS_RW] = &pcap_rw_ops,
638 [PCAP_OPS_SG] = &pcap_sg_ops,
639 [PCAP_OPS_MM] = &pcap_mm_ops,
642 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
643 uint32_t linktype, int32_t thiszone,
644 uint32_t snaplen)
646 bool swapped = pcap_magic_is_swapped(magic);
648 hdr->magic = magic;
649 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
650 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
651 hdr->thiszone = swapped ? (int32_t) ___constant_swab32(thiszone) : thiszone;
652 hdr->sigfigs = 0;
653 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
654 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
657 static const bool pcap_supported_linktypes[LINKTYPE_MAX] __maybe_unused = {
658 /* tunX captures from wireshark/tcpdump, non-portable */
659 [101] = true, [102] = true, [103] = true,
660 [LINKTYPE_NULL] = true,
661 [LINKTYPE_EN10MB] = true,
662 [LINKTYPE_EN3MB] = true,
663 [LINKTYPE_AX25] = true,
664 [LINKTYPE_PRONET] = true,
665 [LINKTYPE_CHAOS] = true,
666 [LINKTYPE_IEEE802] = true,
667 [LINKTYPE_SLIP] = true,
668 [LINKTYPE_PPP] = true,
669 [LINKTYPE_FDDI] = true,
670 [LINKTYPE_ATM_CLIP] = true,
671 [LINKTYPE_C_HDLC] = true,
672 [LINKTYPE_IEEE802_11] = true,
673 [LINKTYPE_FRELAY] = true,
674 [LINKTYPE_ECONET] = true,
675 [LINKTYPE_ARCNET_LINUX] = true,
676 [LINKTYPE_LINUX_IRDA] = true,
677 [LINKTYPE_CAN20B] = true,
678 [LINKTYPE_IEEE802_15_4_LINUX] = true,
679 [LINKTYPE_INFINIBAND] = true,
680 [LINKTYPE_NETLINK] = true,
683 static inline void pcap_validate_header(const struct pcap_filehdr *hdr)
685 bool good = false;
686 uint32_t linktype;
688 pcap_check_magic(hdr->magic);
690 linktype = pcap_magic_is_swapped(hdr->magic) ? bswap_32(hdr->linktype) : hdr->linktype;
691 if (linktype < LINKTYPE_MAX)
692 good = pcap_supported_linktypes[linktype];
694 if (!good)
695 panic("This file has an unsupported pcap link type (%d)!\n", linktype);
696 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
697 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
698 panic("This file has an invalid pcap major version (must be %d)\n", PCAP_VERSION_MAJOR);
699 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
700 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
701 panic("This file has an invalid pcap minor version (must be %d)\n", PCAP_VERSION_MINOR);
704 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
705 uint32_t *linktype) __maybe_unused;
707 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
709 ssize_t ret;
710 struct pcap_filehdr hdr;
712 ret = read(fd, &hdr, sizeof(hdr));
713 if (unlikely(ret != sizeof(hdr)))
714 return -EIO;
716 pcap_validate_header(&hdr);
718 *magic = hdr.magic;
719 *linktype = hdr.linktype;
721 return 0;
724 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
725 uint32_t linktype) __maybe_unused;
727 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
729 ssize_t ret;
730 struct pcap_filehdr hdr;
732 memset(&hdr, 0, sizeof(hdr));
734 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
736 ret = write_or_die(fd, &hdr, sizeof(hdr));
737 if (unlikely(ret != sizeof(hdr)))
738 panic("Failed to write pkt file header!\n");
740 return 0;
743 #endif /* PCAP_IO_H */