mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / pcap_io.h
blobaf5ce8e198587bb014c560a8a2d5f0acc16d07a5
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 <net/if_arp.h>
18 #include <linux/if.h>
19 #include <linux/if_packet.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 ORIGINAL_TCPDUMP_MAGIC_LL 0xb1b2c3d4 /* Internal dummy just for mapping */
31 #define NSEC_TCPDUMP_MAGIC_LL 0xb1b23c4d /* Internal dummy just for mapping */
32 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
33 #define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
35 #define PCAP_VERSION_MAJOR 2
36 #define PCAP_VERSION_MINOR 4
37 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535
39 #define PCAP_TSOURCE_SOFTWARE 1
40 #define PCAP_TSOURCE_SYS_HARDWARE 2
41 #define PCAP_TSOURCE_RAW_HARDWARE 3
43 struct pcap_filehdr {
44 uint32_t magic;
45 uint16_t version_major;
46 uint16_t version_minor;
47 int32_t thiszone;
48 uint32_t sigfigs;
49 uint32_t snaplen;
50 uint32_t linktype;
53 struct pcap_timeval {
54 int32_t tv_sec;
55 int32_t tv_usec;
58 struct pcap_timeval_ns {
59 int32_t tv_sec;
60 int32_t tv_nsec;
63 struct pcap_ll {
64 uint16_t pkttype;
65 uint16_t hatype;
66 uint16_t len;
67 uint8_t addr[8];
68 uint16_t protocol;
71 struct pcap_pkthdr {
72 struct pcap_timeval ts;
73 uint32_t caplen;
74 uint32_t len;
77 struct pcap_pkthdr_ns {
78 struct pcap_timeval_ns ts;
79 uint32_t caplen;
80 uint32_t len;
83 struct pcap_pkthdr_ll {
84 struct pcap_timeval ts;
85 uint32_t caplen;
86 uint32_t len;
87 struct pcap_ll ll;
90 struct pcap_pkthdr_ns_ll {
91 struct pcap_timeval_ns ts;
92 uint32_t caplen;
93 uint32_t len;
94 struct pcap_ll ll;
97 struct pcap_pkthdr_kuz {
98 struct pcap_timeval ts;
99 uint32_t caplen;
100 uint32_t len;
101 uint32_t ifindex;
102 uint16_t protocol;
103 uint8_t pkttype;
106 struct pcap_pkthdr_bkm {
107 struct pcap_timeval_ns ts;
108 uint32_t caplen;
109 uint32_t len;
110 uint16_t tsource;
111 uint16_t ifindex;
112 uint16_t protocol;
113 uint8_t hatype;
114 uint8_t pkttype;
117 typedef union {
118 struct pcap_pkthdr ppo;
119 struct pcap_pkthdr_ns ppn;
120 struct pcap_pkthdr_ll ppo_ll;
121 struct pcap_pkthdr_ns_ll ppn_ll;
122 struct pcap_pkthdr_kuz ppk;
123 struct pcap_pkthdr_bkm ppb;
124 uint8_t raw;
125 } pcap_pkthdr_t;
127 enum pcap_type {
128 DEFAULT = ORIGINAL_TCPDUMP_MAGIC,
129 NSEC = NSEC_TCPDUMP_MAGIC,
130 DEFAULT_LL = ORIGINAL_TCPDUMP_MAGIC_LL,
131 NSEC_LL = NSEC_TCPDUMP_MAGIC_LL,
132 KUZNETZOV = KUZNETZOV_TCPDUMP_MAGIC,
133 BORKMANN = BORKMANN_TCPDUMP_MAGIC,
135 DEFAULT_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC),
136 NSEC_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC),
137 DEFAULT_LL_SWAPPED = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL),
138 NSEC_LL_SWAPPED = ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL),
139 KUZNETZOV_SWAPPED = ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC),
140 BORKMANN_SWAPPED = ___constant_swab32(BORKMANN_TCPDUMP_MAGIC),
143 enum pcap_ops_groups {
144 PCAP_OPS_RW = 0,
145 PCAP_OPS_SG,
146 PCAP_OPS_MM,
149 enum pcap_mode {
150 PCAP_MODE_RD = 0,
151 PCAP_MODE_WR,
154 struct pcap_file_ops {
155 void (*init_once_pcap)(bool enforce_prio);
156 int (*pull_fhdr_pcap)(int fd, uint32_t *magic, uint32_t *linktype);
157 int (*push_fhdr_pcap)(int fd, uint32_t magic, uint32_t linktype);
158 int (*prepare_access_pcap)(int fd, enum pcap_mode mode, bool jumbo);
159 ssize_t (*write_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
160 const uint8_t *packet, size_t len);
161 ssize_t (*read_pcap)(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
162 uint8_t *packet, size_t len);
163 void (*prepare_close_pcap)(int fd, enum pcap_mode mode);
164 void (*fsync_pcap)(int fd);
167 extern const struct pcap_file_ops pcap_rw_ops __maybe_unused;
168 extern const struct pcap_file_ops pcap_sg_ops __maybe_unused;
169 extern const struct pcap_file_ops pcap_mm_ops __maybe_unused;
171 static inline void sockaddr_to_ll(const struct sockaddr_ll *sll,
172 struct pcap_ll *ll)
174 ll->pkttype = cpu_to_be16(sll->sll_pkttype);
175 ll->hatype = cpu_to_be16(sll->sll_hatype);
176 ll->len = cpu_to_be16(sll->sll_halen);
177 ll->protocol = sll->sll_protocol; /* already be16 */
179 memcpy(ll->addr, sll->sll_addr, sizeof(ll->addr));
182 static inline void ll_to_sockaddr(const struct pcap_ll *ll,
183 struct sockaddr_ll *sll)
185 sll->sll_pkttype = be16_to_cpu(ll->pkttype);
186 sll->sll_hatype = be16_to_cpu(ll->hatype);
187 sll->sll_halen = be16_to_cpu(ll->len);
188 sll->sll_protocol = ll->protocol; /* stays be16 */
190 memcpy(sll->sll_addr, ll->addr, sizeof(ll->addr));
193 static inline uint16_t tp_to_pcap_tsource(uint32_t status)
195 if (status & TP_STATUS_TS_RAW_HARDWARE)
196 return PCAP_TSOURCE_RAW_HARDWARE;
197 else if (status & TP_STATUS_TS_SYS_HARDWARE)
198 return PCAP_TSOURCE_SYS_HARDWARE;
199 else if (status & TP_STATUS_TS_SOFTWARE)
200 return PCAP_TSOURCE_SOFTWARE;
201 else
202 return 0;
205 static inline int pcap_devtype_to_linktype(int dev_type)
207 switch (dev_type) {
208 case ARPHRD_TUNNEL:
209 case ARPHRD_TUNNEL6:
210 case ARPHRD_LOOPBACK:
211 case ARPHRD_SIT:
212 case ARPHRD_IPDDP:
213 case ARPHRD_IPGRE:
214 case ARPHRD_IP6GRE:
215 case ARPHRD_ETHER:
216 return LINKTYPE_EN10MB;
217 case ARPHRD_IEEE80211_RADIOTAP:
218 return LINKTYPE_IEEE802_11_RADIOTAP;
219 case ARPHRD_IEEE80211_PRISM:
220 case ARPHRD_IEEE80211:
221 return LINKTYPE_IEEE802_11;
222 case ARPHRD_NETLINK:
223 return LINKTYPE_NETLINK;
224 case ARPHRD_EETHER:
225 return LINKTYPE_EN3MB;
226 case ARPHRD_AX25:
227 return LINKTYPE_AX25;
228 case ARPHRD_CHAOS:
229 return LINKTYPE_CHAOS;
230 case ARPHRD_PRONET:
231 return LINKTYPE_PRONET;
232 case ARPHRD_IEEE802_TR:
233 case ARPHRD_IEEE802:
234 return LINKTYPE_IEEE802;
235 case ARPHRD_INFINIBAND:
236 return LINKTYPE_INFINIBAND;
237 case ARPHRD_ATM:
238 return LINKTYPE_ATM_CLIP;
239 case ARPHRD_DLCI:
240 return LINKTYPE_FRELAY;
241 case ARPHRD_ARCNET:
242 return LINKTYPE_ARCNET_LINUX;
243 case ARPHRD_CSLIP:
244 case ARPHRD_CSLIP6:
245 case ARPHRD_SLIP6:
246 case ARPHRD_SLIP:
247 return LINKTYPE_SLIP;
248 case ARPHRD_PPP:
249 return LINKTYPE_PPP;
250 case ARPHRD_CAN:
251 return LINKTYPE_CAN20B;
252 case ARPHRD_ECONET:
253 return LINKTYPE_ECONET;
254 case ARPHRD_RAWHDLC:
255 case ARPHRD_CISCO:
256 return LINKTYPE_C_HDLC;
257 case ARPHRD_FDDI:
258 return LINKTYPE_FDDI;
259 case ARPHRD_IEEE802154_MONITOR:
260 case ARPHRD_IEEE802154:
261 return LINKTYPE_IEEE802_15_4_LINUX;
262 case ARPHRD_IRDA:
263 return LINKTYPE_LINUX_IRDA;
264 default:
265 return LINKTYPE_NULL;
269 static inline bool link_has_sll_hdr(uint32_t link_type)
271 switch (link_type) {
272 case LINKTYPE_NETLINK:
273 case LINKTYPE_LINUX_SLL:
274 case ___constant_swab32(LINKTYPE_NETLINK):
275 case ___constant_swab32(LINKTYPE_LINUX_SLL):
276 return true;
277 default:
278 return false;
282 static inline int pcap_dev_to_linktype(const char *ifname)
284 return pcap_devtype_to_linktype(device_type(ifname));
287 static inline void pcap_check_magic(uint32_t magic)
289 switch (magic) {
291 case ORIGINAL_TCPDUMP_MAGIC:
292 case NSEC_TCPDUMP_MAGIC:
293 case KUZNETZOV_TCPDUMP_MAGIC:
294 case BORKMANN_TCPDUMP_MAGIC:
296 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
297 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
298 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
299 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
300 break;
302 default:
303 panic("This file has an unsupported pcap magic number(0x%x)\n", magic);
307 static inline bool pcap_magic_is_swapped(uint32_t magic)
309 bool swapped = false;
311 switch (magic) {
312 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
313 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
314 case ___constant_swab32(KUZNETZOV_TCPDUMP_MAGIC):
315 case ___constant_swab32(BORKMANN_TCPDUMP_MAGIC):
316 swapped = true;
319 return swapped;
322 static inline u32 pcap_get_length(pcap_pkthdr_t *phdr, enum pcap_type type)
324 switch (type) {
325 #define CASE_RET_CAPLEN(what, member, swap, extra) \
326 case (what): \
327 return (swap ? ___constant_swab32(phdr->member.caplen) : \
328 phdr->member.caplen) - extra
330 CASE_RET_CAPLEN(DEFAULT, ppo, 0, 0);
331 CASE_RET_CAPLEN(NSEC, ppn, 0, 0);
332 CASE_RET_CAPLEN(DEFAULT_LL, ppo_ll, 0, sizeof(struct pcap_ll));
333 CASE_RET_CAPLEN(NSEC_LL, ppn_ll, 0, sizeof(struct pcap_ll));
334 CASE_RET_CAPLEN(KUZNETZOV, ppk, 0, 0);
335 CASE_RET_CAPLEN(BORKMANN, ppb, 0, 0);
337 CASE_RET_CAPLEN(DEFAULT_SWAPPED, ppo, 1, 0);
338 CASE_RET_CAPLEN(NSEC_SWAPPED, ppn, 1, 0);
339 CASE_RET_CAPLEN(DEFAULT_LL_SWAPPED, ppo_ll, 1, sizeof(struct pcap_ll));
340 CASE_RET_CAPLEN(NSEC_LL_SWAPPED, ppn_ll, 1, sizeof(struct pcap_ll));
341 CASE_RET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1, 0);
342 CASE_RET_CAPLEN(BORKMANN_SWAPPED, ppb, 1, 0);
344 default:
345 bug();
349 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
351 switch (type) {
352 #define CASE_SET_CAPLEN(what, member, swap) \
353 case (what): \
354 phdr->member.caplen = (swap ? ___constant_swab32(len) : len); \
355 break
357 CASE_SET_CAPLEN(DEFAULT, ppo, 0);
358 CASE_SET_CAPLEN(NSEC, ppn, 0);
359 CASE_SET_CAPLEN(DEFAULT_LL, ppo_ll, 0);
360 CASE_SET_CAPLEN(NSEC_LL, ppn_ll, 0);
361 CASE_SET_CAPLEN(KUZNETZOV, ppk, 0);
362 CASE_SET_CAPLEN(BORKMANN, ppb, 0);
364 CASE_SET_CAPLEN(DEFAULT_SWAPPED, ppo, 1);
365 CASE_SET_CAPLEN(NSEC_SWAPPED, ppn, 1);
366 CASE_SET_CAPLEN(DEFAULT_LL_SWAPPED, ppo_ll, 1);
367 CASE_SET_CAPLEN(NSEC_LL_SWAPPED, ppn_ll, 1);
368 CASE_SET_CAPLEN(KUZNETZOV_SWAPPED, ppk, 1);
369 CASE_SET_CAPLEN(BORKMANN_SWAPPED, ppb, 1);
371 default:
372 bug();
376 static inline void pcap_get_tstamp(pcap_pkthdr_t *phdr, enum pcap_type type,
377 struct timespec *ts)
379 switch (type) {
380 case DEFAULT:
381 case DEFAULT_LL:
382 ts->tv_sec = phdr->ppo.ts.tv_sec;
383 ts->tv_nsec = phdr->ppo.ts.tv_usec * 1000;
384 break;
386 case DEFAULT_SWAPPED:
387 case DEFAULT_LL_SWAPPED:
388 ts->tv_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
389 ts->tv_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;;
390 break;
392 case NSEC:
393 case NSEC_LL:
394 ts->tv_sec = phdr->ppn.ts.tv_sec;
395 ts->tv_nsec = phdr->ppn.ts.tv_nsec / 1000;
396 break;
398 case NSEC_SWAPPED:
399 case NSEC_LL_SWAPPED:
400 ts->tv_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
401 ts->tv_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
402 break;
404 case KUZNETZOV:
405 ts->tv_sec = phdr->ppk.ts.tv_sec;
406 ts->tv_nsec = phdr->ppk.ts.tv_usec;
407 break;
409 case KUZNETZOV_SWAPPED:
410 ts->tv_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
411 ts->tv_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec);
412 break;
414 case BORKMANN:
415 ts->tv_sec = phdr->ppb.ts.tv_sec;
416 ts->tv_nsec = phdr->ppb.ts.tv_nsec;
417 break;
419 case BORKMANN_SWAPPED:
420 ts->tv_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
421 ts->tv_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
422 break;
424 default:
425 bug();
429 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
431 switch (type) {
432 #define CASE_RET_HDRLEN(what, member) \
433 case (what): \
434 return sizeof(phdr->member)
436 CASE_RET_HDRLEN(DEFAULT, ppo);
437 CASE_RET_HDRLEN(NSEC, ppn);
438 CASE_RET_HDRLEN(DEFAULT_LL, ppo_ll);
439 CASE_RET_HDRLEN(NSEC_LL, ppn_ll);
440 CASE_RET_HDRLEN(KUZNETZOV, ppk);
441 CASE_RET_HDRLEN(BORKMANN, ppb);
443 CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
444 CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
445 CASE_RET_HDRLEN(DEFAULT_LL_SWAPPED, ppo_ll);
446 CASE_RET_HDRLEN(NSEC_LL_SWAPPED, ppn_ll);
447 CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
448 CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
450 default:
451 bug();
455 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
457 return pcap_get_hdr_length(phdr, type) + pcap_get_length(phdr, type);
460 static inline void
461 __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, uint32_t snaplen,
462 uint32_t len, uint32_t status,
463 struct sockaddr_ll *sll, pcap_pkthdr_t *phdr,
464 enum pcap_type type)
466 switch (type) {
467 case DEFAULT:
468 case DEFAULT_LL:
469 phdr->ppo.ts.tv_sec = sec;
470 phdr->ppo.ts.tv_usec = nsec / 1000;
471 phdr->ppo.caplen = snaplen;
472 phdr->ppo.len = len;
473 if (type == DEFAULT_LL) {
474 phdr->ppo.caplen += sizeof(struct pcap_ll);
475 phdr->ppo.len += sizeof(struct pcap_ll);
476 sockaddr_to_ll(sll, &phdr->ppo_ll.ll);
478 break;
480 case DEFAULT_SWAPPED:
481 case DEFAULT_LL_SWAPPED:
482 phdr->ppo.ts.tv_sec = ___constant_swab32(sec);
483 phdr->ppo.ts.tv_usec = ___constant_swab32(nsec / 1000);
484 phdr->ppo.caplen = ___constant_swab32(snaplen);
485 phdr->ppo.len = ___constant_swab32(len);
486 if (type == DEFAULT_LL_SWAPPED) {
487 phdr->ppo.caplen = ___constant_swab32(snaplen + sizeof(struct pcap_ll));
488 phdr->ppo.len = ___constant_swab32(len + sizeof(struct pcap_ll));
489 sockaddr_to_ll(sll, &phdr->ppo_ll.ll);
491 break;
493 case NSEC:
494 case NSEC_LL:
495 phdr->ppn.ts.tv_sec = sec;
496 phdr->ppn.ts.tv_nsec = nsec;
497 phdr->ppn.caplen = snaplen;
498 phdr->ppn.len = len;
499 if (type == NSEC_LL) {
500 phdr->ppn.caplen += sizeof(struct pcap_ll);
501 phdr->ppn.len += sizeof(struct pcap_ll);
502 sockaddr_to_ll(sll, &phdr->ppn_ll.ll);
504 break;
506 case NSEC_SWAPPED:
507 case NSEC_LL_SWAPPED:
508 phdr->ppn.ts.tv_sec = ___constant_swab32(sec);
509 phdr->ppn.ts.tv_nsec = ___constant_swab32(nsec);
510 phdr->ppn.caplen = ___constant_swab32(snaplen);
511 phdr->ppn.len = ___constant_swab32(len);
512 if (type == NSEC_LL_SWAPPED) {
513 phdr->ppn.caplen = ___constant_swab32(snaplen + sizeof(struct pcap_ll));
514 phdr->ppn.len = ___constant_swab32(len + sizeof(struct pcap_ll));
515 sockaddr_to_ll(sll, &phdr->ppn_ll.ll);
517 break;
519 case KUZNETZOV:
520 phdr->ppk.ts.tv_sec = sec;
521 phdr->ppk.ts.tv_usec = nsec / 1000;
522 phdr->ppk.caplen = snaplen;
523 phdr->ppk.len = len;
524 phdr->ppk.ifindex = sll->sll_ifindex;
525 phdr->ppk.protocol = sll->sll_protocol;
526 phdr->ppk.pkttype = sll->sll_pkttype;
527 break;
529 case KUZNETZOV_SWAPPED:
530 phdr->ppk.ts.tv_sec = ___constant_swab32(sec);
531 phdr->ppk.ts.tv_usec = ___constant_swab32(nsec / 1000);
532 phdr->ppk.caplen = ___constant_swab32(snaplen);
533 phdr->ppk.len = ___constant_swab32(len);
534 phdr->ppk.ifindex = ___constant_swab32(sll->sll_ifindex);
535 phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
536 phdr->ppk.pkttype = sll->sll_pkttype;
537 break;
539 case BORKMANN:
540 phdr->ppb.ts.tv_sec = sec;
541 phdr->ppb.ts.tv_nsec = nsec;
542 phdr->ppb.caplen = snaplen;
543 phdr->ppb.len = len;
544 phdr->ppb.tsource = tp_to_pcap_tsource(status);
545 phdr->ppb.ifindex = (u16) sll->sll_ifindex;
546 phdr->ppb.protocol = sll->sll_protocol;
547 phdr->ppb.hatype = sll->sll_hatype;
548 phdr->ppb.pkttype = sll->sll_pkttype;
549 break;
551 case BORKMANN_SWAPPED:
552 phdr->ppb.ts.tv_sec = ___constant_swab32(sec);
553 phdr->ppb.ts.tv_nsec = ___constant_swab32(nsec);
554 phdr->ppb.caplen = ___constant_swab32(snaplen);
555 phdr->ppb.len = ___constant_swab32(len);
556 phdr->ppb.tsource = ___constant_swab16(tp_to_pcap_tsource(status));
557 phdr->ppb.ifindex = ___constant_swab16((u16) sll->sll_ifindex);
558 phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
559 phdr->ppb.hatype = sll->sll_hatype;
560 phdr->ppb.pkttype = sll->sll_pkttype;
561 break;
563 default:
564 bug();
568 /* We need to do this crap here since member offsets are not interleaved,
569 * so hopfully the compiler does his job here. ;-)
572 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
573 struct sockaddr_ll *sll,
574 pcap_pkthdr_t *phdr,
575 enum pcap_type type)
577 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
578 thdr->tp_snaplen, thdr->tp_len,
579 thdr->tp_status, sll, phdr, type);
582 #ifdef HAVE_TPACKET3
583 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
584 struct sockaddr_ll *sll,
585 pcap_pkthdr_t *phdr,
586 enum pcap_type type)
588 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
589 thdr->tp_snaplen, thdr->tp_len,
590 0, sll, phdr, type);
592 #endif
594 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
595 enum pcap_type type,
596 struct tpacket2_hdr *thdr,
597 struct sockaddr_ll *sll)
599 switch (type) {
600 case DEFAULT:
601 case DEFAULT_LL:
602 thdr->tp_sec = phdr->ppo.ts.tv_sec;
603 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
604 thdr->tp_snaplen = phdr->ppo.caplen;
605 thdr->tp_len = phdr->ppo.len;
606 if (type == DEFAULT_LL) {
607 thdr->tp_snaplen -= sizeof(struct pcap_ll);
608 thdr->tp_len -= sizeof(struct pcap_ll);
609 if (sll)
610 ll_to_sockaddr(&phdr->ppo_ll.ll, sll);
612 break;
614 case DEFAULT_SWAPPED:
615 case DEFAULT_LL_SWAPPED:
616 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
617 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
618 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
619 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
620 if (type == DEFAULT_LL_SWAPPED) {
621 thdr->tp_snaplen -= sizeof(struct pcap_ll);
622 thdr->tp_len -= sizeof(struct pcap_ll);
623 if (sll)
624 ll_to_sockaddr(&phdr->ppo_ll.ll, sll);
626 break;
628 case NSEC:
629 case NSEC_LL:
630 thdr->tp_sec = phdr->ppn.ts.tv_sec;
631 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
632 thdr->tp_snaplen = phdr->ppn.caplen;
633 thdr->tp_len = phdr->ppn.len;
634 if (type == NSEC_LL) {
635 thdr->tp_snaplen -= sizeof(struct pcap_ll);
636 thdr->tp_len -= sizeof(struct pcap_ll);
637 if (sll)
638 ll_to_sockaddr(&phdr->ppn_ll.ll, sll);
640 break;
642 case NSEC_SWAPPED:
643 case NSEC_LL_SWAPPED:
644 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
645 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
646 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
647 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
648 if (type == NSEC_LL_SWAPPED) {
649 thdr->tp_snaplen -= sizeof(struct pcap_ll);
650 thdr->tp_len -= sizeof(struct pcap_ll);
651 if (sll)
652 ll_to_sockaddr(&phdr->ppn_ll.ll, sll);
654 break;
656 case KUZNETZOV:
657 thdr->tp_sec = phdr->ppk.ts.tv_sec;
658 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
659 thdr->tp_snaplen = phdr->ppk.caplen;
660 thdr->tp_len = phdr->ppk.len;
661 if (sll) {
662 sll->sll_ifindex = phdr->ppk.ifindex;
663 sll->sll_protocol = phdr->ppk.protocol;
664 sll->sll_pkttype = phdr->ppk.pkttype;
666 break;
668 case KUZNETZOV_SWAPPED:
669 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
670 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
671 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
672 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
673 if (sll) {
674 sll->sll_ifindex = ___constant_swab32(phdr->ppk.ifindex);
675 sll->sll_protocol = ___constant_swab16(phdr->ppk.protocol);
676 sll->sll_pkttype = phdr->ppk.pkttype;
678 break;
680 case BORKMANN:
681 thdr->tp_sec = phdr->ppb.ts.tv_sec;
682 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
683 thdr->tp_snaplen = phdr->ppb.caplen;
684 thdr->tp_len = phdr->ppb.len;
685 if (sll) {
686 sll->sll_ifindex = phdr->ppb.ifindex;
687 sll->sll_protocol = phdr->ppb.protocol;
688 sll->sll_hatype = phdr->ppb.hatype;
689 sll->sll_pkttype = phdr->ppb.pkttype;
691 break;
693 case BORKMANN_SWAPPED:
694 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
695 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
696 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
697 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
698 if (sll) {
699 sll->sll_ifindex = ___constant_swab16(phdr->ppb.ifindex);
700 sll->sll_protocol = ___constant_swab16(phdr->ppb.protocol);
701 sll->sll_hatype = phdr->ppb.hatype;
702 sll->sll_pkttype = phdr->ppb.pkttype;
704 break;
706 default:
707 bug();
711 #define FEATURE_UNKNOWN (0 << 0)
712 #define FEATURE_TIMEVAL_MS (1 << 0)
713 #define FEATURE_TIMEVAL_NS (1 << 1)
714 #define FEATURE_LEN (1 << 2)
715 #define FEATURE_CAPLEN (1 << 3)
716 #define FEATURE_IFINDEX (1 << 4)
717 #define FEATURE_PROTO (1 << 5)
718 #define FEATURE_HATYPE (1 << 6)
719 #define FEATURE_PKTTYPE (1 << 7)
720 #define FEATURE_TSOURCE (1 << 8)
722 struct pcap_magic_type {
723 const uint32_t magic;
724 const char *desc;
725 const uint16_t features;
728 static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
730 .magic = ORIGINAL_TCPDUMP_MAGIC,
731 .desc = "tcpdump-capable pcap",
732 .features = FEATURE_TIMEVAL_MS |
733 FEATURE_LEN |
734 FEATURE_CAPLEN,
735 }, {
736 .magic = NSEC_TCPDUMP_MAGIC,
737 .desc = "tcpdump-capable pcap with ns resolution",
738 .features = FEATURE_TIMEVAL_NS |
739 FEATURE_LEN |
740 FEATURE_CAPLEN,
741 }, {
742 .magic = KUZNETZOV_TCPDUMP_MAGIC,
743 .desc = "Alexey Kuznetzov's pcap",
744 .features = FEATURE_TIMEVAL_MS |
745 FEATURE_LEN |
746 FEATURE_CAPLEN |
747 FEATURE_IFINDEX |
748 FEATURE_PROTO |
749 FEATURE_PKTTYPE,
750 }, {
751 .magic = BORKMANN_TCPDUMP_MAGIC,
752 .desc = "netsniff-ng pcap",
753 .features = FEATURE_TIMEVAL_NS |
754 FEATURE_LEN |
755 FEATURE_CAPLEN |
756 FEATURE_TSOURCE |
757 FEATURE_IFINDEX |
758 FEATURE_PROTO |
759 FEATURE_HATYPE |
760 FEATURE_PKTTYPE,
764 static inline void pcap_dump_type_features(void)
766 size_t i;
768 for (i = 0; i < array_size(pcap_magic_types); ++i) {
769 printf("%s:\n", pcap_magic_types[i].desc);
770 printf(" magic: 0x%x (swapped: 0x%x)\n",
771 pcap_magic_types[i].magic,
772 ___constant_swab32(pcap_magic_types[i].magic));
773 printf(" features:\n");
775 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
776 printf(" unknown\n");
777 continue;
780 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
781 printf(" timeval in us\n");
782 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
783 printf(" timeval in ns\n");
784 if (pcap_magic_types[i].features & FEATURE_TSOURCE)
785 printf(" timestamp source\n");
786 if (pcap_magic_types[i].features & FEATURE_LEN)
787 printf(" packet length\n");
788 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
789 printf(" packet cap-length\n");
790 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
791 printf(" packet ifindex\n");
792 if (pcap_magic_types[i].features & FEATURE_PROTO)
793 printf(" packet protocol\n");
794 if (pcap_magic_types[i].features & FEATURE_HATYPE)
795 printf(" hardware type\n");
796 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
797 printf(" packet type\n");
801 static const char *pcap_ops_group_to_str[] __maybe_unused = {
802 [PCAP_OPS_RW] = "read/write",
803 [PCAP_OPS_SG] = "scatter-gather",
804 [PCAP_OPS_MM] = "mmap",
807 static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
808 [PCAP_OPS_RW] = &pcap_rw_ops,
809 [PCAP_OPS_SG] = &pcap_sg_ops,
810 [PCAP_OPS_MM] = &pcap_mm_ops,
813 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
814 uint32_t linktype, int32_t thiszone,
815 uint32_t snaplen)
817 bool swapped = pcap_magic_is_swapped(magic);
819 /* As *_LL types are just internal, we need to remap pcap
820 * magics to actually valid types.
822 switch (magic) {
823 case ORIGINAL_TCPDUMP_MAGIC_LL:
824 magic = ORIGINAL_TCPDUMP_MAGIC;
825 break;
826 case NSEC_TCPDUMP_MAGIC_LL:
827 magic = NSEC_TCPDUMP_MAGIC;
828 break;
829 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL):
830 magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC);
831 break;
832 case ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL):
833 magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC);
834 break;
837 hdr->magic = magic;
838 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
839 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
840 hdr->thiszone = swapped ? (int32_t) ___constant_swab32(thiszone) : thiszone;
841 hdr->sigfigs = 0;
842 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
843 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
846 static const bool pcap_supported_linktypes[LINKTYPE_MAX] __maybe_unused = {
847 /* tunX captures from wireshark/tcpdump, non-portable */
848 [101] = true, [102] = true, [103] = true,
849 [LINKTYPE_NULL] = true,
850 [LINKTYPE_EN10MB] = true,
851 [LINKTYPE_EN3MB] = true,
852 [LINKTYPE_AX25] = true,
853 [LINKTYPE_PRONET] = true,
854 [LINKTYPE_CHAOS] = true,
855 [LINKTYPE_IEEE802] = true,
856 [LINKTYPE_SLIP] = true,
857 [LINKTYPE_PPP] = true,
858 [LINKTYPE_FDDI] = true,
859 [LINKTYPE_ATM_CLIP] = true,
860 [LINKTYPE_C_HDLC] = true,
861 [LINKTYPE_IEEE802_11] = true,
862 [LINKTYPE_IEEE802_11_RADIOTAP] = true,
863 [LINKTYPE_FRELAY] = true,
864 [LINKTYPE_ECONET] = true,
865 [LINKTYPE_ARCNET_LINUX] = true,
866 [LINKTYPE_LINUX_IRDA] = true,
867 [LINKTYPE_CAN20B] = true,
868 [LINKTYPE_IEEE802_15_4_LINUX] = true,
869 [LINKTYPE_INFINIBAND] = true,
870 [LINKTYPE_NETLINK] = true,
871 [LINKTYPE_LINUX_SLL] = true,
874 static inline void pcap_validate_header(struct pcap_filehdr *hdr)
876 bool good = false;
877 uint32_t linktype;
879 pcap_check_magic(hdr->magic);
881 linktype = pcap_magic_is_swapped(hdr->magic) ? bswap_32(hdr->linktype) : hdr->linktype;
882 if (linktype < LINKTYPE_MAX)
883 good = pcap_supported_linktypes[linktype];
885 if (!good)
886 panic("This file has an unsupported pcap link type (%d)!\n", linktype);
887 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
888 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
889 panic("This file has an invalid pcap major version (must be %d)\n", PCAP_VERSION_MAJOR);
890 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
891 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
892 panic("This file has an invalid pcap minor version (must be %d)\n", PCAP_VERSION_MINOR);
894 /* Remap to internal *_LL types in case of LINKTYPE_LINUX_SLL. */
895 if (linktype == LINKTYPE_LINUX_SLL || linktype == LINKTYPE_NETLINK) {
896 switch (hdr->magic) {
897 case ORIGINAL_TCPDUMP_MAGIC:
898 hdr->magic = ORIGINAL_TCPDUMP_MAGIC_LL;
899 break;
900 case NSEC_TCPDUMP_MAGIC:
901 hdr->magic = NSEC_TCPDUMP_MAGIC_LL;
902 break;
903 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
904 hdr->magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL);
905 break;
906 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
907 hdr->magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL);
908 break;
913 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
914 uint32_t *linktype) __maybe_unused;
916 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
918 ssize_t ret;
919 struct pcap_filehdr hdr;
921 ret = read(fd, &hdr, sizeof(hdr));
922 if (unlikely(ret != sizeof(hdr)))
923 return -EIO;
925 pcap_validate_header(&hdr);
927 *magic = hdr.magic;
928 *linktype = hdr.linktype;
930 return 0;
933 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
934 uint32_t linktype) __maybe_unused;
936 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
938 ssize_t ret;
939 struct pcap_filehdr hdr;
941 memset(&hdr, 0, sizeof(hdr));
943 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
945 ret = write_or_die(fd, &hdr, sizeof(hdr));
946 if (unlikely(ret != sizeof(hdr)))
947 panic("Failed to write pkt file header!\n");
949 return 0;
952 #endif /* PCAP_IO_H */