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
;
96 DEFAULT
= ORIGINAL_TCPDUMP_MAGIC
,
97 NSEC
= NSEC_TCPDUMP_MAGIC
,
98 KUZNETZOV
= KUZNETZOV_TCPDUMP_MAGIC
,
99 BORKMANN
= BORKMANN_TCPDUMP_MAGIC
,
102 enum pcap_ops_groups
{
113 struct pcap_file_ops
{
114 int (*pull_fhdr_pcap
)(int fd
, uint32_t *magic
, uint32_t *linktype
);
115 int (*push_fhdr_pcap
)(int fd
, uint32_t magic
, uint32_t linktype
);
116 int (*prepare_access_pcap
)(int fd
, enum pcap_mode mode
, bool jumbo
);
117 ssize_t (*write_pcap
)(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
118 const uint8_t *packet
, size_t len
);
119 ssize_t (*read_pcap
)(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
120 uint8_t *packet
, size_t len
);
121 void (*prepare_close_pcap
)(int fd
, enum pcap_mode mode
);
122 void (*fsync_pcap
)(int fd
);
125 extern const struct pcap_file_ops pcap_rw_ops
;
126 extern const struct pcap_file_ops pcap_sg_ops
;
127 extern const struct pcap_file_ops pcap_mm_ops
;
129 static inline void pcap_check_magic(uint32_t magic
)
138 panic("This file has not a valid pcap header\n");
142 static inline u32
pcap_get_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
145 #define CASE_RET_CAPLEN(what, member) \
147 return phdr->member.caplen
148 CASE_RET_CAPLEN(DEFAULT
, ppo
);
149 CASE_RET_CAPLEN(NSEC
, ppn
);
150 CASE_RET_CAPLEN(KUZNETZOV
, ppk
);
151 CASE_RET_CAPLEN(BORKMANN
, ppb
);
157 static inline void pcap_set_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
, u32 len
)
160 #define CASE_SET_CAPLEN(what, member) \
162 phdr->member.caplen = len; \
164 CASE_SET_CAPLEN(DEFAULT
, ppo
);
165 CASE_SET_CAPLEN(NSEC
, ppn
);
166 CASE_SET_CAPLEN(KUZNETZOV
, ppk
);
167 CASE_SET_CAPLEN(BORKMANN
, ppb
);
173 static inline u32
pcap_get_hdr_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
176 #define CASE_RET_HDRLEN(what, member) \
178 return sizeof(phdr->member)
179 CASE_RET_HDRLEN(DEFAULT
, ppo
);
180 CASE_RET_HDRLEN(NSEC
, ppn
);
181 CASE_RET_HDRLEN(KUZNETZOV
, ppk
);
182 CASE_RET_HDRLEN(BORKMANN
, ppb
);
188 static inline u32
pcap_get_total_length(pcap_pkthdr_t
*phdr
, enum pcap_type type
)
191 #define CASE_RET_TOTLEN(what, member) \
193 return phdr->member.caplen + sizeof(phdr->member)
194 CASE_RET_TOTLEN(DEFAULT
, ppo
);
195 CASE_RET_TOTLEN(NSEC
, ppn
);
196 CASE_RET_TOTLEN(KUZNETZOV
, ppk
);
197 CASE_RET_TOTLEN(BORKMANN
, ppb
);
203 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr
*thdr
,
204 struct sockaddr_ll
*sll
,
210 phdr
->ppo
.ts
.tv_sec
= thdr
->tp_sec
;
211 phdr
->ppo
.ts
.tv_usec
= thdr
->tp_nsec
/ 1000;
212 phdr
->ppo
.caplen
= thdr
->tp_snaplen
;
213 phdr
->ppo
.len
= thdr
->tp_len
;
217 phdr
->ppn
.ts
.tv_sec
= thdr
->tp_sec
;
218 phdr
->ppn
.ts
.tv_nsec
= thdr
->tp_nsec
;
219 phdr
->ppn
.caplen
= thdr
->tp_snaplen
;
220 phdr
->ppn
.len
= thdr
->tp_len
;
224 phdr
->ppk
.ts
.tv_sec
= thdr
->tp_sec
;
225 phdr
->ppk
.ts
.tv_usec
= thdr
->tp_nsec
/ 1000;
226 phdr
->ppk
.caplen
= thdr
->tp_snaplen
;
227 phdr
->ppk
.len
= thdr
->tp_len
;
228 phdr
->ppk
.ifindex
= sll
->sll_ifindex
;
229 phdr
->ppk
.protocol
= sll
->sll_protocol
;
230 phdr
->ppk
.pkttype
= sll
->sll_pkttype
;
234 phdr
->ppb
.ts
.tv_sec
= thdr
->tp_sec
;
235 phdr
->ppb
.ts
.tv_nsec
= thdr
->tp_nsec
;
236 phdr
->ppb
.caplen
= thdr
->tp_snaplen
;
237 phdr
->ppb
.len
= thdr
->tp_len
;
238 phdr
->ppb
.ifindex
= (u32
) sll
->sll_ifindex
;
239 phdr
->ppb
.protocol
= sll
->sll_protocol
;
240 phdr
->ppb
.hatype
= sll
->sll_hatype
;
241 phdr
->ppb
.pkttype
= sll
->sll_pkttype
;
249 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t
*phdr
,
251 struct tpacket2_hdr
*thdr
,
252 struct sockaddr_ll
*sll
)
256 thdr
->tp_sec
= phdr
->ppo
.ts
.tv_sec
;
257 thdr
->tp_nsec
= phdr
->ppo
.ts
.tv_usec
* 1000;
258 thdr
->tp_snaplen
= phdr
->ppo
.caplen
;
259 thdr
->tp_len
= phdr
->ppo
.len
;
263 thdr
->tp_sec
= phdr
->ppn
.ts
.tv_sec
;
264 thdr
->tp_nsec
= phdr
->ppn
.ts
.tv_nsec
;
265 thdr
->tp_snaplen
= phdr
->ppn
.caplen
;
266 thdr
->tp_len
= phdr
->ppn
.len
;
270 thdr
->tp_sec
= phdr
->ppk
.ts
.tv_sec
;
271 thdr
->tp_nsec
= phdr
->ppk
.ts
.tv_usec
* 1000;
272 thdr
->tp_snaplen
= phdr
->ppk
.caplen
;
273 thdr
->tp_len
= phdr
->ppk
.len
;
277 thdr
->tp_sec
= phdr
->ppb
.ts
.tv_sec
;
278 thdr
->tp_nsec
= phdr
->ppb
.ts
.tv_nsec
;
279 thdr
->tp_snaplen
= phdr
->ppb
.caplen
;
280 thdr
->tp_len
= phdr
->ppb
.len
;
288 #define FEATURE_UNKNOWN (0 << 0)
289 #define FEATURE_TIMEVAL_MS (1 << 0)
290 #define FEATURE_TIMEVAL_NS (1 << 1)
291 #define FEATURE_LEN (1 << 2)
292 #define FEATURE_CAPLEN (1 << 3)
293 #define FEATURE_IFINDEX (1 << 4)
294 #define FEATURE_PROTO (1 << 5)
295 #define FEATURE_HATYPE (1 << 6)
296 #define FEATURE_PKTTYPE (1 << 7)
298 struct pcap_magic_type
{
304 static const struct pcap_magic_type
const pcap_magic_types
[] __maybe_unused
= {
306 .magic
= ORIGINAL_TCPDUMP_MAGIC
,
307 .desc
= "tcpdump-capable pcap",
308 .features
= FEATURE_TIMEVAL_MS
|
312 .magic
= NSEC_TCPDUMP_MAGIC
,
313 .desc
= "tcpdump-capable pcap with ns resolution",
314 .features
= FEATURE_TIMEVAL_NS
|
318 .magic
= KUZNETZOV_TCPDUMP_MAGIC
,
319 .desc
= "Alexey Kuznetzov's pcap",
320 .features
= FEATURE_TIMEVAL_MS
|
327 .magic
= BORKMANN_TCPDUMP_MAGIC
,
328 .desc
= "netsniff-ng pcap",
329 .features
= FEATURE_TIMEVAL_NS
|
339 static inline void pcap_dump_type_features(void)
343 for (i
= 0; i
< array_size(pcap_magic_types
); ++i
) {
344 printf("%s:\n", pcap_magic_types
[i
].desc
);
345 printf(" magic: 0x%x\n", pcap_magic_types
[i
].magic
);
346 printf(" features:\n");
348 if (pcap_magic_types
[i
].features
== FEATURE_UNKNOWN
) {
349 printf(" unknown\n");
353 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_MS
)
354 printf(" timeval in us\n");
355 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_NS
)
356 printf(" timeval in ns\n");
357 if (pcap_magic_types
[i
].features
& FEATURE_LEN
)
358 printf(" packet length\n");
359 if (pcap_magic_types
[i
].features
& FEATURE_CAPLEN
)
360 printf(" packet cap-length\n");
361 if (pcap_magic_types
[i
].features
& FEATURE_IFINDEX
)
362 printf(" packet ifindex\n");
363 if (pcap_magic_types
[i
].features
& FEATURE_PROTO
)
364 printf(" packet protocol\n");
365 if (pcap_magic_types
[i
].features
& FEATURE_HATYPE
)
366 printf(" hardware type\n");
367 if (pcap_magic_types
[i
].features
& FEATURE_PKTTYPE
)
368 printf(" packet type\n");
372 static const char *pcap_ops_group_to_str
[] __maybe_unused
= {
373 [PCAP_OPS_RW
] = "rw",
374 [PCAP_OPS_SG
] = "sg",
375 [PCAP_OPS_MM
] = "mm",
378 static const struct pcap_file_ops
const *pcap_ops
[] __maybe_unused
= {
379 [PCAP_OPS_RW
] = &pcap_rw_ops
,
380 [PCAP_OPS_SG
] = &pcap_sg_ops
,
381 [PCAP_OPS_MM
] = &pcap_mm_ops
,
384 static inline void pcap_prepare_header(struct pcap_filehdr
*hdr
, uint32_t magic
,
385 uint32_t linktype
, int32_t thiszone
,
389 hdr
->version_major
= PCAP_VERSION_MAJOR
;
390 hdr
->version_minor
= PCAP_VERSION_MINOR
;
391 hdr
->thiszone
= thiszone
;
393 hdr
->snaplen
= snaplen
;
394 hdr
->linktype
= linktype
;
397 static inline void pcap_validate_header(const struct pcap_filehdr
*hdr
)
399 pcap_check_magic(hdr
->magic
);
401 switch (hdr
->linktype
) {
402 case LINKTYPE_EN10MB
:
403 case LINKTYPE_IEEE802_11
:
406 panic("This file has not a valid pcap header\n");
409 if (unlikely(hdr
->version_major
!= PCAP_VERSION_MAJOR
))
410 panic("This file has not a valid pcap header\n");
411 if (unlikely(hdr
->version_minor
!= PCAP_VERSION_MINOR
))
412 panic("This file has not a valid pcap header\n");
415 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
,
416 uint32_t *linktype
) __maybe_unused
;
418 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
, uint32_t *linktype
)
421 struct pcap_filehdr hdr
;
423 ret
= read(fd
, &hdr
, sizeof(hdr
));
424 if (unlikely(ret
!= sizeof(hdr
)))
427 pcap_validate_header(&hdr
);
430 *linktype
= hdr
.linktype
;
435 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
,
436 uint32_t linktype
) __maybe_unused
;
438 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
, uint32_t linktype
)
441 struct pcap_filehdr hdr
;
443 memset(&hdr
, 0, sizeof(hdr
));
445 pcap_prepare_header(&hdr
, magic
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
);
447 ret
= write_or_die(fd
, &hdr
, sizeof(hdr
));
448 if (unlikely(ret
!= sizeof(hdr
)))
449 panic("Failed to write pkt file header!\n");