2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009 - 2013 Daniel Borkmann.
5 * Copyright 2010 Emmanuel Roullit.
6 * Subject to the GPL, version 2.
17 #include <linux/if_packet.h>
23 #define TCPDUMP_MAGIC 0xa1b2c3d4
24 #define ORIGINAL_TCPDUMP_MAGIC TCPDUMP_MAGIC
25 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
26 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
27 #define BORKMANN_TCPDUMP_MAGIC 0xa1e2cb12
29 #define PCAP_VERSION_MAJOR 2
30 #define PCAP_VERSION_MINOR 4
31 #define PCAP_DEFAULT_SNAPSHOT_LEN 65535
33 #define LINKTYPE_EN10MB 1 /* Ethernet (10Mb) */
34 #define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 wireless */
38 uint16_t version_major
;
39 uint16_t version_minor
;
51 struct pcap_timeval_ns
{
57 struct pcap_timeval ts
;
62 struct pcap_pkthdr_ns
{
63 struct pcap_timeval_ns ts
;
68 struct pcap_pkthdr_kuz
{
69 struct pcap_timeval ts
;
77 struct pcap_pkthdr_bkm
{
78 struct pcap_timeval_ns ts
;
88 struct pcap_pkthdr ppo
;
89 struct pcap_pkthdr_ns ppn
;
90 struct pcap_pkthdr_kuz ppk
;
91 struct pcap_pkthdr_bkm ppb
;
95 DEFAULT
= ORIGINAL_TCPDUMP_MAGIC
,
96 NSEC
= NSEC_TCPDUMP_MAGIC
,
97 KUZNETZOV
= KUZNETZOV_TCPDUMP_MAGIC
,
98 BORKMANN
= BORKMANN_TCPDUMP_MAGIC
,
101 enum pcap_ops_groups
{
112 struct pcap_file_ops
{
113 int (*pull_fhdr_pcap
)(int fd
, uint32_t *magic
, uint32_t *linktype
);
114 int (*push_fhdr_pcap
)(int fd
, uint32_t magic
, uint32_t linktype
);
115 int (*prepare_access_pcap
)(int fd
, enum pcap_mode mode
, bool jumbo
);
116 ssize_t (*write_pcap
)(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
117 const uint8_t *packet
, size_t len
);
118 ssize_t (*read_pcap
)(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
119 uint8_t *packet
, size_t len
);
120 void (*prepare_close_pcap
)(int fd
, enum pcap_mode mode
);
121 void (*fsync_pcap
)(int fd
);
124 extern const struct pcap_file_ops pcap_rw_ops
;
125 extern const struct pcap_file_ops pcap_sg_ops
;
126 extern const struct pcap_file_ops pcap_mm_ops
;
128 static inline void pcap_check_magic(uint32_t magic
)
137 panic("This file has not a valid pcap header\n");
141 static inline u32
pcap_get_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
144 #define CASE_RET_CAPLEN(what, member) \
146 return phdr->member.caplen
147 CASE_RET_CAPLEN(DEFAULT
, ppo
);
148 CASE_RET_CAPLEN(NSEC
, ppn
);
149 CASE_RET_CAPLEN(KUZNETZOV
, ppk
);
150 CASE_RET_CAPLEN(BORKMANN
, ppb
);
156 static inline void pcap_set_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
, u32 len
)
159 #define CASE_SET_CAPLEN(what, member) \
161 phdr->member.caplen = len; \
163 CASE_SET_CAPLEN(DEFAULT
, ppo
);
164 CASE_SET_CAPLEN(NSEC
, ppn
);
165 CASE_SET_CAPLEN(KUZNETZOV
, ppk
);
166 CASE_SET_CAPLEN(BORKMANN
, ppb
);
172 static inline u32
pcap_get_hdr_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
175 #define CASE_RET_HDRLEN(what, member) \
177 return sizeof(phdr->member)
178 CASE_RET_HDRLEN(DEFAULT
, ppo
);
179 CASE_RET_HDRLEN(NSEC
, ppn
);
180 CASE_RET_HDRLEN(KUZNETZOV
, ppk
);
181 CASE_RET_HDRLEN(BORKMANN
, ppb
);
187 static inline u32
pcap_get_total_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
190 #define CASE_RET_TOTLEN(what, member) \
192 return phdr->member.caplen + sizeof(phdr->member)
193 CASE_RET_TOTLEN(DEFAULT
, ppo
);
194 CASE_RET_TOTLEN(NSEC
, ppn
);
195 CASE_RET_TOTLEN(KUZNETZOV
, ppk
);
196 CASE_RET_TOTLEN(BORKMANN
, ppb
);
202 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr
*thdr
,
203 struct sockaddr_ll
*sll
,
209 phdr
->ppo
.ts
.tv_sec
= thdr
->tp_sec
;
210 phdr
->ppo
.ts
.tv_usec
= thdr
->tp_nsec
/ 1000;
211 phdr
->ppo
.caplen
= thdr
->tp_snaplen
;
212 phdr
->ppo
.len
= thdr
->tp_len
;
216 phdr
->ppn
.ts
.tv_sec
= thdr
->tp_sec
;
217 phdr
->ppn
.ts
.tv_nsec
= thdr
->tp_nsec
;
218 phdr
->ppn
.caplen
= thdr
->tp_snaplen
;
219 phdr
->ppn
.len
= thdr
->tp_len
;
223 phdr
->ppk
.ts
.tv_sec
= thdr
->tp_sec
;
224 phdr
->ppk
.ts
.tv_usec
= thdr
->tp_nsec
/ 1000;
225 phdr
->ppk
.caplen
= thdr
->tp_snaplen
;
226 phdr
->ppk
.len
= thdr
->tp_len
;
227 phdr
->ppk
.ifindex
= sll
->sll_ifindex
;
228 phdr
->ppk
.protocol
= sll
->sll_protocol
;
229 phdr
->ppk
.pkttype
= sll
->sll_pkttype
;
233 phdr
->ppb
.ts
.tv_sec
= thdr
->tp_sec
;
234 phdr
->ppb
.ts
.tv_nsec
= thdr
->tp_nsec
;
235 phdr
->ppb
.caplen
= thdr
->tp_snaplen
;
236 phdr
->ppb
.len
= thdr
->tp_len
;
237 phdr
->ppb
.ifindex
= (u32
) sll
->sll_ifindex
;
238 phdr
->ppb
.protocol
= sll
->sll_protocol
;
239 phdr
->ppb
.hatype
= sll
->sll_hatype
;
240 phdr
->ppb
.pkttype
= sll
->sll_pkttype
;
248 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t
*phdr
,
250 struct tpacket2_hdr
*thdr
,
251 struct sockaddr_ll
*sll
)
255 thdr
->tp_sec
= phdr
->ppo
.ts
.tv_sec
;
256 thdr
->tp_nsec
= phdr
->ppo
.ts
.tv_usec
* 1000;
257 thdr
->tp_snaplen
= phdr
->ppo
.caplen
;
258 thdr
->tp_len
= phdr
->ppo
.len
;
262 thdr
->tp_sec
= phdr
->ppn
.ts
.tv_sec
;
263 thdr
->tp_nsec
= phdr
->ppn
.ts
.tv_nsec
;
264 thdr
->tp_snaplen
= phdr
->ppn
.caplen
;
265 thdr
->tp_len
= phdr
->ppn
.len
;
269 thdr
->tp_sec
= phdr
->ppk
.ts
.tv_sec
;
270 thdr
->tp_nsec
= phdr
->ppk
.ts
.tv_usec
* 1000;
271 thdr
->tp_snaplen
= phdr
->ppk
.caplen
;
272 thdr
->tp_len
= phdr
->ppk
.len
;
276 thdr
->tp_sec
= phdr
->ppb
.ts
.tv_sec
;
277 thdr
->tp_nsec
= phdr
->ppb
.ts
.tv_nsec
;
278 thdr
->tp_snaplen
= phdr
->ppb
.caplen
;
279 thdr
->tp_len
= phdr
->ppb
.len
;
287 #define FEATURE_UNKNOWN (0 << 0)
288 #define FEATURE_TIMEVAL_MS (1 << 0)
289 #define FEATURE_TIMEVAL_NS (1 << 1)
290 #define FEATURE_LEN (1 << 2)
291 #define FEATURE_CAPLEN (1 << 3)
292 #define FEATURE_IFINDEX (1 << 4)
293 #define FEATURE_PROTO (1 << 5)
294 #define FEATURE_HATYPE (1 << 6)
295 #define FEATURE_PKTTYPE (1 << 7)
297 struct pcap_magic_type
{
303 static const struct pcap_magic_type
const pcap_magic_types
[] __maybe_unused
= {
305 .magic
= ORIGINAL_TCPDUMP_MAGIC
,
306 .desc
= "tcpdump-capable pcap",
307 .features
= FEATURE_TIMEVAL_MS
|
311 .magic
= NSEC_TCPDUMP_MAGIC
,
312 .desc
= "tcpdump-capable pcap with ns resolution",
313 .features
= FEATURE_TIMEVAL_NS
|
317 .magic
= KUZNETZOV_TCPDUMP_MAGIC
,
318 .desc
= "Alexey Kuznetzov's pcap",
319 .features
= FEATURE_TIMEVAL_MS
|
326 .magic
= BORKMANN_TCPDUMP_MAGIC
,
327 .desc
= "netsniff-ng pcap",
328 .features
= FEATURE_TIMEVAL_NS
|
338 static inline void pcap_dump_type_features(void)
342 for (i
= 0; i
< array_size(pcap_magic_types
); ++i
) {
343 printf("%s:\n", pcap_magic_types
[i
].desc
);
344 printf(" magic: 0x%x\n", pcap_magic_types
[i
].magic
);
345 printf(" features:\n");
347 if (pcap_magic_types
[i
].features
== FEATURE_UNKNOWN
) {
348 printf(" unknown\n");
352 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_MS
)
353 printf(" timeval in us\n");
354 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_NS
)
355 printf(" timeval in ns\n");
356 if (pcap_magic_types
[i
].features
& FEATURE_LEN
)
357 printf(" packet length\n");
358 if (pcap_magic_types
[i
].features
& FEATURE_CAPLEN
)
359 printf(" packet cap-length\n");
360 if (pcap_magic_types
[i
].features
& FEATURE_IFINDEX
)
361 printf(" packet ifindex\n");
362 if (pcap_magic_types
[i
].features
& FEATURE_PROTO
)
363 printf(" packet protocol\n");
364 if (pcap_magic_types
[i
].features
& FEATURE_HATYPE
)
365 printf(" hardware type\n");
366 if (pcap_magic_types
[i
].features
& FEATURE_PKTTYPE
)
367 printf(" packet type\n");
371 static const char *pcap_ops_group_to_str
[] __maybe_unused
= {
372 [PCAP_OPS_RW
] = "rw",
373 [PCAP_OPS_SG
] = "sg",
374 [PCAP_OPS_MM
] = "mm",
377 static const struct pcap_file_ops
const *pcap_ops
[] __maybe_unused
= {
378 [PCAP_OPS_RW
] = &pcap_rw_ops
,
379 [PCAP_OPS_SG
] = &pcap_sg_ops
,
380 [PCAP_OPS_MM
] = &pcap_mm_ops
,
383 static inline void pcap_prepare_header(struct pcap_filehdr
*hdr
, uint32_t magic
,
384 uint32_t linktype
, int32_t thiszone
,
388 hdr
->version_major
= PCAP_VERSION_MAJOR
;
389 hdr
->version_minor
= PCAP_VERSION_MINOR
;
390 hdr
->thiszone
= thiszone
;
392 hdr
->snaplen
= snaplen
;
393 hdr
->linktype
= linktype
;
396 static inline void pcap_validate_header(const struct pcap_filehdr
*hdr
)
398 pcap_check_magic(hdr
->magic
);
400 switch (hdr
->linktype
) {
401 case LINKTYPE_EN10MB
:
402 case LINKTYPE_IEEE802_11
:
405 panic("This file has not a valid pcap header\n");
408 if (unlikely(hdr
->version_major
!= PCAP_VERSION_MAJOR
))
409 panic("This file has not a valid pcap header\n");
410 if (unlikely(hdr
->version_minor
!= PCAP_VERSION_MINOR
))
411 panic("This file has not a valid pcap header\n");
414 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
,
415 uint32_t *linktype
) __maybe_unused
;
417 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
, uint32_t *linktype
)
420 struct pcap_filehdr hdr
;
422 ret
= read(fd
, &hdr
, sizeof(hdr
));
423 if (unlikely(ret
!= sizeof(hdr
)))
426 pcap_validate_header(&hdr
);
429 *linktype
= hdr
.linktype
;
434 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
,
435 uint32_t linktype
) __maybe_unused
;
437 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
, uint32_t linktype
)
440 struct pcap_filehdr hdr
;
442 memset(&hdr
, 0, sizeof(hdr
));
444 pcap_prepare_header(&hdr
, magic
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
);
446 ret
= write_or_die(fd
, &hdr
, sizeof(hdr
));
447 if (unlikely(ret
!= sizeof(hdr
)))
448 panic("Failed to write pkt file header!\n");