curvetun: Fix issues detected by the Coverity scanner
[netsniff-ng.git] / pcap_io.h
blob5056e58e0560c7b276e44739c4c366af27e413f0
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 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 not a valid pcap header\n");
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 u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
378 switch (type) {
379 #define CASE_RET_HDRLEN(what, member) \
380 case (what): \
381 return sizeof(phdr->member)
383 CASE_RET_HDRLEN(DEFAULT, ppo);
384 CASE_RET_HDRLEN(NSEC, ppn);
385 CASE_RET_HDRLEN(DEFAULT_LL, ppo_ll);
386 CASE_RET_HDRLEN(NSEC_LL, ppn_ll);
387 CASE_RET_HDRLEN(KUZNETZOV, ppk);
388 CASE_RET_HDRLEN(BORKMANN, ppb);
390 CASE_RET_HDRLEN(DEFAULT_SWAPPED, ppo);
391 CASE_RET_HDRLEN(NSEC_SWAPPED, ppn);
392 CASE_RET_HDRLEN(DEFAULT_LL_SWAPPED, ppo_ll);
393 CASE_RET_HDRLEN(NSEC_LL_SWAPPED, ppn_ll);
394 CASE_RET_HDRLEN(KUZNETZOV_SWAPPED, ppk);
395 CASE_RET_HDRLEN(BORKMANN_SWAPPED, ppb);
397 default:
398 bug();
402 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
404 return pcap_get_hdr_length(phdr, type) + pcap_get_length(phdr, type);
407 static inline void
408 __tpacket_hdr_to_pcap_pkthdr(uint32_t sec, uint32_t nsec, uint32_t snaplen,
409 uint32_t len, uint32_t status,
410 struct sockaddr_ll *sll, pcap_pkthdr_t *phdr,
411 enum pcap_type type)
413 switch (type) {
414 case DEFAULT:
415 case DEFAULT_LL:
416 phdr->ppo.ts.tv_sec = sec;
417 phdr->ppo.ts.tv_usec = nsec / 1000;
418 phdr->ppo.caplen = snaplen;
419 phdr->ppo.len = len;
420 if (type == DEFAULT_LL) {
421 phdr->ppo.caplen += sizeof(struct pcap_ll);
422 phdr->ppo.len += sizeof(struct pcap_ll);
423 sockaddr_to_ll(sll, &phdr->ppo_ll.ll);
425 break;
427 case DEFAULT_SWAPPED:
428 case DEFAULT_LL_SWAPPED:
429 phdr->ppo.ts.tv_sec = ___constant_swab32(sec);
430 phdr->ppo.ts.tv_usec = ___constant_swab32(nsec / 1000);
431 phdr->ppo.caplen = ___constant_swab32(snaplen);
432 phdr->ppo.len = ___constant_swab32(len);
433 if (type == DEFAULT_LL_SWAPPED) {
434 phdr->ppo.caplen = ___constant_swab32(snaplen + sizeof(struct pcap_ll));
435 phdr->ppo.len = ___constant_swab32(len + sizeof(struct pcap_ll));
436 sockaddr_to_ll(sll, &phdr->ppo_ll.ll);
438 break;
440 case NSEC:
441 case NSEC_LL:
442 phdr->ppn.ts.tv_sec = sec;
443 phdr->ppn.ts.tv_nsec = nsec;
444 phdr->ppn.caplen = snaplen;
445 phdr->ppn.len = len;
446 if (type == NSEC_LL) {
447 phdr->ppn.caplen += sizeof(struct pcap_ll);
448 phdr->ppn.len += sizeof(struct pcap_ll);
449 sockaddr_to_ll(sll, &phdr->ppn_ll.ll);
451 break;
453 case NSEC_SWAPPED:
454 case NSEC_LL_SWAPPED:
455 phdr->ppn.ts.tv_sec = ___constant_swab32(sec);
456 phdr->ppn.ts.tv_nsec = ___constant_swab32(nsec);
457 phdr->ppn.caplen = ___constant_swab32(snaplen);
458 phdr->ppn.len = ___constant_swab32(len);
459 if (type == NSEC_LL_SWAPPED) {
460 phdr->ppn.caplen = ___constant_swab32(snaplen + sizeof(struct pcap_ll));
461 phdr->ppn.len = ___constant_swab32(len + sizeof(struct pcap_ll));
462 sockaddr_to_ll(sll, &phdr->ppn_ll.ll);
464 break;
466 case KUZNETZOV:
467 phdr->ppk.ts.tv_sec = sec;
468 phdr->ppk.ts.tv_usec = nsec / 1000;
469 phdr->ppk.caplen = snaplen;
470 phdr->ppk.len = len;
471 phdr->ppk.ifindex = sll->sll_ifindex;
472 phdr->ppk.protocol = sll->sll_protocol;
473 phdr->ppk.pkttype = sll->sll_pkttype;
474 break;
476 case KUZNETZOV_SWAPPED:
477 phdr->ppk.ts.tv_sec = ___constant_swab32(sec);
478 phdr->ppk.ts.tv_usec = ___constant_swab32(nsec / 1000);
479 phdr->ppk.caplen = ___constant_swab32(snaplen);
480 phdr->ppk.len = ___constant_swab32(len);
481 phdr->ppk.ifindex = ___constant_swab32(sll->sll_ifindex);
482 phdr->ppk.protocol = ___constant_swab16(sll->sll_protocol);
483 phdr->ppk.pkttype = sll->sll_pkttype;
484 break;
486 case BORKMANN:
487 phdr->ppb.ts.tv_sec = sec;
488 phdr->ppb.ts.tv_nsec = nsec;
489 phdr->ppb.caplen = snaplen;
490 phdr->ppb.len = len;
491 phdr->ppb.tsource = tp_to_pcap_tsource(status);
492 phdr->ppb.ifindex = (u16) sll->sll_ifindex;
493 phdr->ppb.protocol = sll->sll_protocol;
494 phdr->ppb.hatype = sll->sll_hatype;
495 phdr->ppb.pkttype = sll->sll_pkttype;
496 break;
498 case BORKMANN_SWAPPED:
499 phdr->ppb.ts.tv_sec = ___constant_swab32(sec);
500 phdr->ppb.ts.tv_nsec = ___constant_swab32(nsec);
501 phdr->ppb.caplen = ___constant_swab32(snaplen);
502 phdr->ppb.len = ___constant_swab32(len);
503 phdr->ppb.tsource = ___constant_swab16(tp_to_pcap_tsource(status));
504 phdr->ppb.ifindex = ___constant_swab16((u16) sll->sll_ifindex);
505 phdr->ppb.protocol = ___constant_swab16(sll->sll_protocol);
506 phdr->ppb.hatype = sll->sll_hatype;
507 phdr->ppb.pkttype = sll->sll_pkttype;
508 break;
510 default:
511 bug();
515 /* We need to do this crap here since member offsets are not interleaved,
516 * so hopfully the compiler does his job here. ;-)
519 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
520 struct sockaddr_ll *sll,
521 pcap_pkthdr_t *phdr,
522 enum pcap_type type)
524 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
525 thdr->tp_snaplen, thdr->tp_len,
526 thdr->tp_status, sll, phdr, type);
529 #ifdef HAVE_TPACKET3
530 static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
531 struct sockaddr_ll *sll,
532 pcap_pkthdr_t *phdr,
533 enum pcap_type type)
535 __tpacket_hdr_to_pcap_pkthdr(thdr->tp_sec, thdr->tp_nsec,
536 thdr->tp_snaplen, thdr->tp_len,
537 0, sll, phdr, type);
539 #endif
541 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
542 enum pcap_type type,
543 struct tpacket2_hdr *thdr,
544 struct sockaddr_ll *sll)
546 switch (type) {
547 case DEFAULT:
548 case DEFAULT_LL:
549 thdr->tp_sec = phdr->ppo.ts.tv_sec;
550 thdr->tp_nsec = phdr->ppo.ts.tv_usec * 1000;
551 thdr->tp_snaplen = phdr->ppo.caplen;
552 thdr->tp_len = phdr->ppo.len;
553 if (type == DEFAULT_LL) {
554 thdr->tp_snaplen -= sizeof(struct pcap_ll);
555 thdr->tp_len -= sizeof(struct pcap_ll);
556 if (sll)
557 ll_to_sockaddr(&phdr->ppo_ll.ll, sll);
559 break;
561 case DEFAULT_SWAPPED:
562 case DEFAULT_LL_SWAPPED:
563 thdr->tp_sec = ___constant_swab32(phdr->ppo.ts.tv_sec);
564 thdr->tp_nsec = ___constant_swab32(phdr->ppo.ts.tv_usec) * 1000;
565 thdr->tp_snaplen = ___constant_swab32(phdr->ppo.caplen);
566 thdr->tp_len = ___constant_swab32(phdr->ppo.len);
567 if (type == DEFAULT_LL_SWAPPED) {
568 thdr->tp_snaplen -= sizeof(struct pcap_ll);
569 thdr->tp_len -= sizeof(struct pcap_ll);
570 if (sll)
571 ll_to_sockaddr(&phdr->ppo_ll.ll, sll);
573 break;
575 case NSEC:
576 case NSEC_LL:
577 thdr->tp_sec = phdr->ppn.ts.tv_sec;
578 thdr->tp_nsec = phdr->ppn.ts.tv_nsec;
579 thdr->tp_snaplen = phdr->ppn.caplen;
580 thdr->tp_len = phdr->ppn.len;
581 if (type == NSEC_LL) {
582 thdr->tp_snaplen -= sizeof(struct pcap_ll);
583 thdr->tp_len -= sizeof(struct pcap_ll);
584 if (sll)
585 ll_to_sockaddr(&phdr->ppn_ll.ll, sll);
587 break;
589 case NSEC_SWAPPED:
590 case NSEC_LL_SWAPPED:
591 thdr->tp_sec = ___constant_swab32(phdr->ppn.ts.tv_sec);
592 thdr->tp_nsec = ___constant_swab32(phdr->ppn.ts.tv_nsec);
593 thdr->tp_snaplen = ___constant_swab32(phdr->ppn.caplen);
594 thdr->tp_len = ___constant_swab32(phdr->ppn.len);
595 if (type == NSEC_LL_SWAPPED) {
596 thdr->tp_snaplen -= sizeof(struct pcap_ll);
597 thdr->tp_len -= sizeof(struct pcap_ll);
598 if (sll)
599 ll_to_sockaddr(&phdr->ppn_ll.ll, sll);
601 break;
603 case KUZNETZOV:
604 thdr->tp_sec = phdr->ppk.ts.tv_sec;
605 thdr->tp_nsec = phdr->ppk.ts.tv_usec * 1000;
606 thdr->tp_snaplen = phdr->ppk.caplen;
607 thdr->tp_len = phdr->ppk.len;
608 if (sll) {
609 sll->sll_ifindex = phdr->ppk.ifindex;
610 sll->sll_protocol = phdr->ppk.protocol;
611 sll->sll_pkttype = phdr->ppk.pkttype;
613 break;
615 case KUZNETZOV_SWAPPED:
616 thdr->tp_sec = ___constant_swab32(phdr->ppk.ts.tv_sec);
617 thdr->tp_nsec = ___constant_swab32(phdr->ppk.ts.tv_usec) * 1000;
618 thdr->tp_snaplen = ___constant_swab32(phdr->ppk.caplen);
619 thdr->tp_len = ___constant_swab32(phdr->ppk.len);
620 if (sll) {
621 sll->sll_ifindex = ___constant_swab32(phdr->ppk.ifindex);
622 sll->sll_protocol = ___constant_swab16(phdr->ppk.protocol);
623 sll->sll_pkttype = phdr->ppk.pkttype;
625 break;
627 case BORKMANN:
628 thdr->tp_sec = phdr->ppb.ts.tv_sec;
629 thdr->tp_nsec = phdr->ppb.ts.tv_nsec;
630 thdr->tp_snaplen = phdr->ppb.caplen;
631 thdr->tp_len = phdr->ppb.len;
632 if (sll) {
633 sll->sll_ifindex = phdr->ppb.ifindex;
634 sll->sll_protocol = phdr->ppb.protocol;
635 sll->sll_hatype = phdr->ppb.hatype;
636 sll->sll_pkttype = phdr->ppb.pkttype;
638 break;
640 case BORKMANN_SWAPPED:
641 thdr->tp_sec = ___constant_swab32(phdr->ppb.ts.tv_sec);
642 thdr->tp_nsec = ___constant_swab32(phdr->ppb.ts.tv_nsec);
643 thdr->tp_snaplen = ___constant_swab32(phdr->ppb.caplen);
644 thdr->tp_len = ___constant_swab32(phdr->ppb.len);
645 if (sll) {
646 sll->sll_ifindex = ___constant_swab16(phdr->ppb.ifindex);
647 sll->sll_protocol = ___constant_swab16(phdr->ppb.protocol);
648 sll->sll_hatype = phdr->ppb.hatype;
649 sll->sll_pkttype = phdr->ppb.pkttype;
651 break;
653 default:
654 bug();
658 #define FEATURE_UNKNOWN (0 << 0)
659 #define FEATURE_TIMEVAL_MS (1 << 0)
660 #define FEATURE_TIMEVAL_NS (1 << 1)
661 #define FEATURE_LEN (1 << 2)
662 #define FEATURE_CAPLEN (1 << 3)
663 #define FEATURE_IFINDEX (1 << 4)
664 #define FEATURE_PROTO (1 << 5)
665 #define FEATURE_HATYPE (1 << 6)
666 #define FEATURE_PKTTYPE (1 << 7)
667 #define FEATURE_TSOURCE (1 << 8)
669 struct pcap_magic_type {
670 const uint32_t magic;
671 const char *desc;
672 const uint16_t features;
675 static const struct pcap_magic_type pcap_magic_types[] __maybe_unused = {
677 .magic = ORIGINAL_TCPDUMP_MAGIC,
678 .desc = "tcpdump-capable pcap",
679 .features = FEATURE_TIMEVAL_MS |
680 FEATURE_LEN |
681 FEATURE_CAPLEN,
682 }, {
683 .magic = NSEC_TCPDUMP_MAGIC,
684 .desc = "tcpdump-capable pcap with ns resolution",
685 .features = FEATURE_TIMEVAL_NS |
686 FEATURE_LEN |
687 FEATURE_CAPLEN,
688 }, {
689 .magic = KUZNETZOV_TCPDUMP_MAGIC,
690 .desc = "Alexey Kuznetzov's pcap",
691 .features = FEATURE_TIMEVAL_MS |
692 FEATURE_LEN |
693 FEATURE_CAPLEN |
694 FEATURE_IFINDEX |
695 FEATURE_PROTO |
696 FEATURE_PKTTYPE,
697 }, {
698 .magic = BORKMANN_TCPDUMP_MAGIC,
699 .desc = "netsniff-ng pcap",
700 .features = FEATURE_TIMEVAL_NS |
701 FEATURE_LEN |
702 FEATURE_CAPLEN |
703 FEATURE_TSOURCE |
704 FEATURE_IFINDEX |
705 FEATURE_PROTO |
706 FEATURE_HATYPE |
707 FEATURE_PKTTYPE,
711 static inline void pcap_dump_type_features(void)
713 size_t i;
715 for (i = 0; i < array_size(pcap_magic_types); ++i) {
716 printf("%s:\n", pcap_magic_types[i].desc);
717 printf(" magic: 0x%x (swapped: 0x%x)\n",
718 pcap_magic_types[i].magic,
719 ___constant_swab32(pcap_magic_types[i].magic));
720 printf(" features:\n");
722 if (pcap_magic_types[i].features == FEATURE_UNKNOWN) {
723 printf(" unknown\n");
724 continue;
727 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_MS)
728 printf(" timeval in us\n");
729 if (pcap_magic_types[i].features & FEATURE_TIMEVAL_NS)
730 printf(" timeval in ns\n");
731 if (pcap_magic_types[i].features & FEATURE_TSOURCE)
732 printf(" timestamp source\n");
733 if (pcap_magic_types[i].features & FEATURE_LEN)
734 printf(" packet length\n");
735 if (pcap_magic_types[i].features & FEATURE_CAPLEN)
736 printf(" packet cap-length\n");
737 if (pcap_magic_types[i].features & FEATURE_IFINDEX)
738 printf(" packet ifindex\n");
739 if (pcap_magic_types[i].features & FEATURE_PROTO)
740 printf(" packet protocol\n");
741 if (pcap_magic_types[i].features & FEATURE_HATYPE)
742 printf(" hardware type\n");
743 if (pcap_magic_types[i].features & FEATURE_PKTTYPE)
744 printf(" packet type\n");
748 static const char *pcap_ops_group_to_str[] __maybe_unused = {
749 [PCAP_OPS_RW] = "read/write",
750 [PCAP_OPS_SG] = "scatter-gather",
751 [PCAP_OPS_MM] = "mmap",
754 static const struct pcap_file_ops *pcap_ops[] __maybe_unused = {
755 [PCAP_OPS_RW] = &pcap_rw_ops,
756 [PCAP_OPS_SG] = &pcap_sg_ops,
757 [PCAP_OPS_MM] = &pcap_mm_ops,
760 static inline void pcap_prepare_header(struct pcap_filehdr *hdr, uint32_t magic,
761 uint32_t linktype, int32_t thiszone,
762 uint32_t snaplen)
764 bool swapped = pcap_magic_is_swapped(magic);
766 /* As *_LL types are just internal, we need to remap pcap
767 * magics to actually valid types.
769 switch (magic) {
770 case ORIGINAL_TCPDUMP_MAGIC_LL:
771 magic = ORIGINAL_TCPDUMP_MAGIC;
772 break;
773 case NSEC_TCPDUMP_MAGIC_LL:
774 magic = NSEC_TCPDUMP_MAGIC;
775 break;
776 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL):
777 magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC);
778 break;
779 case ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL):
780 magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC);
781 break;
784 hdr->magic = magic;
785 hdr->version_major = swapped ? ___constant_swab16(PCAP_VERSION_MAJOR) : PCAP_VERSION_MAJOR;
786 hdr->version_minor = swapped ? ___constant_swab16(PCAP_VERSION_MINOR) : PCAP_VERSION_MINOR;
787 hdr->thiszone = swapped ? (int32_t) ___constant_swab32(thiszone) : thiszone;
788 hdr->sigfigs = 0;
789 hdr->snaplen = swapped ? ___constant_swab32(snaplen) : snaplen;
790 hdr->linktype = swapped ? ___constant_swab32(linktype) : linktype;
793 static const bool pcap_supported_linktypes[LINKTYPE_MAX] __maybe_unused = {
794 /* tunX captures from wireshark/tcpdump, non-portable */
795 [101] = true, [102] = true, [103] = true,
796 [LINKTYPE_NULL] = true,
797 [LINKTYPE_EN10MB] = true,
798 [LINKTYPE_EN3MB] = true,
799 [LINKTYPE_AX25] = true,
800 [LINKTYPE_PRONET] = true,
801 [LINKTYPE_CHAOS] = true,
802 [LINKTYPE_IEEE802] = true,
803 [LINKTYPE_SLIP] = true,
804 [LINKTYPE_PPP] = true,
805 [LINKTYPE_FDDI] = true,
806 [LINKTYPE_ATM_CLIP] = true,
807 [LINKTYPE_C_HDLC] = true,
808 [LINKTYPE_IEEE802_11] = true,
809 [LINKTYPE_IEEE802_11_RADIOTAP] = true,
810 [LINKTYPE_FRELAY] = true,
811 [LINKTYPE_ECONET] = true,
812 [LINKTYPE_ARCNET_LINUX] = true,
813 [LINKTYPE_LINUX_IRDA] = true,
814 [LINKTYPE_CAN20B] = true,
815 [LINKTYPE_IEEE802_15_4_LINUX] = true,
816 [LINKTYPE_INFINIBAND] = true,
817 [LINKTYPE_NETLINK] = true,
818 [LINKTYPE_LINUX_SLL] = true,
821 static inline void pcap_validate_header(struct pcap_filehdr *hdr)
823 bool good = false;
824 uint32_t linktype;
826 pcap_check_magic(hdr->magic);
828 linktype = pcap_magic_is_swapped(hdr->magic) ? bswap_32(hdr->linktype) : hdr->linktype;
829 if (linktype < LINKTYPE_MAX)
830 good = pcap_supported_linktypes[linktype];
832 if (!good)
833 panic("This file has an unsupported pcap link type (%d)!\n", linktype);
834 if (unlikely(hdr->version_major != PCAP_VERSION_MAJOR) &&
835 ___constant_swab16(hdr->version_major) != PCAP_VERSION_MAJOR)
836 panic("This file has an invalid pcap major version (must be %d)\n", PCAP_VERSION_MAJOR);
837 if (unlikely(hdr->version_minor != PCAP_VERSION_MINOR) &&
838 ___constant_swab16(hdr->version_minor) != PCAP_VERSION_MINOR)
839 panic("This file has an invalid pcap minor version (must be %d)\n", PCAP_VERSION_MINOR);
841 /* Remap to internal *_LL types in case of LINKTYPE_LINUX_SLL. */
842 if (linktype == LINKTYPE_LINUX_SLL || linktype == LINKTYPE_NETLINK) {
843 switch (hdr->magic) {
844 case ORIGINAL_TCPDUMP_MAGIC:
845 hdr->magic = ORIGINAL_TCPDUMP_MAGIC_LL;
846 break;
847 case NSEC_TCPDUMP_MAGIC:
848 hdr->magic = NSEC_TCPDUMP_MAGIC_LL;
849 break;
850 case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
851 hdr->magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL);
852 break;
853 case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
854 hdr->magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL);
855 break;
860 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic,
861 uint32_t *linktype) __maybe_unused;
863 static int pcap_generic_pull_fhdr(int fd, uint32_t *magic, uint32_t *linktype)
865 ssize_t ret;
866 struct pcap_filehdr hdr;
868 ret = read(fd, &hdr, sizeof(hdr));
869 if (unlikely(ret != sizeof(hdr)))
870 return -EIO;
872 pcap_validate_header(&hdr);
874 *magic = hdr.magic;
875 *linktype = hdr.linktype;
877 return 0;
880 static int pcap_generic_push_fhdr(int fd, uint32_t magic,
881 uint32_t linktype) __maybe_unused;
883 static int pcap_generic_push_fhdr(int fd, uint32_t magic, uint32_t linktype)
885 ssize_t ret;
886 struct pcap_filehdr hdr;
888 memset(&hdr, 0, sizeof(hdr));
890 pcap_prepare_header(&hdr, magic, linktype, 0, PCAP_DEFAULT_SNAPSHOT_LEN);
892 ret = write_or_die(fd, &hdr, sizeof(hdr));
893 if (unlikely(ret != sizeof(hdr)))
894 panic("Failed to write pkt file header!\n");
896 return 0;
899 #endif /* PCAP_IO_H */