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
;
273 sll
->sll_ifindex
= phdr
->ppk
.ifindex
;
274 sll
->sll_protocol
= phdr
->ppk
.protocol
;
275 sll
->sll_pkttype
= phdr
->ppk
.pkttype
;
279 thdr
->tp_sec
= phdr
->ppb
.ts
.tv_sec
;
280 thdr
->tp_nsec
= phdr
->ppb
.ts
.tv_nsec
;
281 thdr
->tp_snaplen
= phdr
->ppb
.caplen
;
282 thdr
->tp_len
= phdr
->ppb
.len
;
283 sll
->sll_ifindex
= (int) phdr
->ppb
.ifindex
;
284 sll
->sll_protocol
= phdr
->ppb
.protocol
;
285 sll
->sll_hatype
= phdr
->ppb
.hatype
;
286 sll
->sll_pkttype
= phdr
->ppb
.pkttype
;
294 #define FEATURE_UNKNOWN (0 << 0)
295 #define FEATURE_TIMEVAL_MS (1 << 0)
296 #define FEATURE_TIMEVAL_NS (1 << 1)
297 #define FEATURE_LEN (1 << 2)
298 #define FEATURE_CAPLEN (1 << 3)
299 #define FEATURE_IFINDEX (1 << 4)
300 #define FEATURE_PROTO (1 << 5)
301 #define FEATURE_HATYPE (1 << 6)
302 #define FEATURE_PKTTYPE (1 << 7)
304 struct pcap_magic_type
{
310 static const struct pcap_magic_type
const pcap_magic_types
[] __maybe_unused
= {
312 .magic
= ORIGINAL_TCPDUMP_MAGIC
,
313 .desc
= "tcpdump-capable pcap",
314 .features
= FEATURE_TIMEVAL_MS
|
318 .magic
= NSEC_TCPDUMP_MAGIC
,
319 .desc
= "tcpdump-capable pcap with ns resolution",
320 .features
= FEATURE_TIMEVAL_NS
|
324 .magic
= KUZNETZOV_TCPDUMP_MAGIC
,
325 .desc
= "Alexey Kuznetzov's pcap",
326 .features
= FEATURE_TIMEVAL_MS
|
333 .magic
= BORKMANN_TCPDUMP_MAGIC
,
334 .desc
= "netsniff-ng pcap",
335 .features
= FEATURE_TIMEVAL_NS
|
345 static inline void pcap_dump_type_features(void)
349 for (i
= 0; i
< array_size(pcap_magic_types
); ++i
) {
350 printf("%s:\n", pcap_magic_types
[i
].desc
);
351 printf(" magic: 0x%x\n", pcap_magic_types
[i
].magic
);
352 printf(" features:\n");
354 if (pcap_magic_types
[i
].features
== FEATURE_UNKNOWN
) {
355 printf(" unknown\n");
359 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_MS
)
360 printf(" timeval in us\n");
361 if (pcap_magic_types
[i
].features
& FEATURE_TIMEVAL_NS
)
362 printf(" timeval in ns\n");
363 if (pcap_magic_types
[i
].features
& FEATURE_LEN
)
364 printf(" packet length\n");
365 if (pcap_magic_types
[i
].features
& FEATURE_CAPLEN
)
366 printf(" packet cap-length\n");
367 if (pcap_magic_types
[i
].features
& FEATURE_IFINDEX
)
368 printf(" packet ifindex\n");
369 if (pcap_magic_types
[i
].features
& FEATURE_PROTO
)
370 printf(" packet protocol\n");
371 if (pcap_magic_types
[i
].features
& FEATURE_HATYPE
)
372 printf(" hardware type\n");
373 if (pcap_magic_types
[i
].features
& FEATURE_PKTTYPE
)
374 printf(" packet type\n");
378 static const char *pcap_ops_group_to_str
[] __maybe_unused
= {
379 [PCAP_OPS_RW
] = "rw",
380 [PCAP_OPS_SG
] = "sg",
381 [PCAP_OPS_MM
] = "mm",
384 static const struct pcap_file_ops
const *pcap_ops
[] __maybe_unused
= {
385 [PCAP_OPS_RW
] = &pcap_rw_ops
,
386 [PCAP_OPS_SG
] = &pcap_sg_ops
,
387 [PCAP_OPS_MM
] = &pcap_mm_ops
,
390 static inline void pcap_prepare_header(struct pcap_filehdr
*hdr
, uint32_t magic
,
391 uint32_t linktype
, int32_t thiszone
,
395 hdr
->version_major
= PCAP_VERSION_MAJOR
;
396 hdr
->version_minor
= PCAP_VERSION_MINOR
;
397 hdr
->thiszone
= thiszone
;
399 hdr
->snaplen
= snaplen
;
400 hdr
->linktype
= linktype
;
403 static inline void pcap_validate_header(const struct pcap_filehdr
*hdr
)
405 pcap_check_magic(hdr
->magic
);
407 switch (hdr
->linktype
) {
408 case LINKTYPE_EN10MB
:
409 case LINKTYPE_IEEE802_11
:
412 panic("This file has not a valid pcap header\n");
415 if (unlikely(hdr
->version_major
!= PCAP_VERSION_MAJOR
))
416 panic("This file has not a valid pcap header\n");
417 if (unlikely(hdr
->version_minor
!= PCAP_VERSION_MINOR
))
418 panic("This file has not a valid pcap header\n");
421 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
,
422 uint32_t *linktype
) __maybe_unused
;
424 static int pcap_generic_pull_fhdr(int fd
, uint32_t *magic
, uint32_t *linktype
)
427 struct pcap_filehdr hdr
;
429 ret
= read(fd
, &hdr
, sizeof(hdr
));
430 if (unlikely(ret
!= sizeof(hdr
)))
433 pcap_validate_header(&hdr
);
436 *linktype
= hdr
.linktype
;
441 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
,
442 uint32_t linktype
) __maybe_unused
;
444 static int pcap_generic_push_fhdr(int fd
, uint32_t magic
, uint32_t linktype
)
447 struct pcap_filehdr hdr
;
449 memset(&hdr
, 0, sizeof(hdr
));
451 pcap_prepare_header(&hdr
, magic
, linktype
, 0, PCAP_DEFAULT_SNAPSHOT_LEN
);
453 ret
= write_or_die(fd
, &hdr
, sizeof(hdr
));
454 if (unlikely(ret
!= sizeof(hdr
)))
455 panic("Failed to write pkt file header!\n");