pcap_rw: simplify code by using raw
[netsniff-ng.git] / pcap.h
blob8062aea5a32b9171db8e57afc566c1ef06721855
1 /*
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.
7 */
9 #ifndef PCAP_H
10 #define PCAP_H
12 #include <unistd.h>
13 #include <stdint.h>
14 #include <stdbool.h>
15 #include <errno.h>
16 #include <sys/time.h>
17 #include <linux/if_packet.h>
19 #include "built_in.h"
20 #include "die.h"
21 #include "xio.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 */
36 struct pcap_filehdr {
37 uint32_t magic;
38 uint16_t version_major;
39 uint16_t version_minor;
40 int32_t thiszone;
41 uint32_t sigfigs;
42 uint32_t snaplen;
43 uint32_t linktype;
46 struct pcap_timeval {
47 int32_t tv_sec;
48 int32_t tv_usec;
51 struct pcap_timeval_ns {
52 int32_t tv_sec;
53 int32_t tv_nsec;
56 struct pcap_pkthdr {
57 struct pcap_timeval ts;
58 uint32_t caplen;
59 uint32_t len;
62 struct pcap_pkthdr_ns {
63 struct pcap_timeval_ns ts;
64 uint32_t caplen;
65 uint32_t len;
68 struct pcap_pkthdr_kuz {
69 struct pcap_timeval ts;
70 uint32_t caplen;
71 uint32_t len;
72 int ifindex;
73 uint16_t protocol;
74 uint8_t pkttype;
77 struct pcap_pkthdr_bkm {
78 struct pcap_timeval_ns ts;
79 uint32_t caplen;
80 uint32_t len;
81 uint32_t ifindex;
82 uint16_t protocol;
83 uint8_t hatype;
84 uint8_t pkttype;
87 typedef union {
88 struct pcap_pkthdr ppo;
89 struct pcap_pkthdr_ns ppn;
90 struct pcap_pkthdr_kuz ppk;
91 struct pcap_pkthdr_bkm ppb;
92 uint8_t raw;
93 } pcap_pkthdr_t;
95 enum pcap_type {
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 {
103 PCAP_OPS_RW = 0,
104 PCAP_OPS_SG,
105 PCAP_OPS_MM,
108 enum pcap_mode {
109 PCAP_MODE_RD = 0,
110 PCAP_MODE_WR,
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)
131 switch (magic) {
132 case DEFAULT:
133 case NSEC:
134 case KUZNETZOV:
135 case BORKMANN:
136 break;
137 default:
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)
144 switch (type) {
145 #define CASE_RET_CAPLEN(what, member) \
146 case (what): \
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);
152 default:
153 bug();
157 static inline void pcap_set_length(pcap_pkthdr_t *phdr, enum pcap_type type, u32 len)
159 switch (type) {
160 #define CASE_SET_CAPLEN(what, member) \
161 case (what): \
162 phdr->member.caplen = len; \
163 break
164 CASE_SET_CAPLEN(DEFAULT, ppo);
165 CASE_SET_CAPLEN(NSEC, ppn);
166 CASE_SET_CAPLEN(KUZNETZOV, ppk);
167 CASE_SET_CAPLEN(BORKMANN, ppb);
168 default:
169 bug();
173 static inline u32 pcap_get_hdr_length(pcap_pkthdr_t *phdr, enum pcap_type type)
175 switch (type) {
176 #define CASE_RET_HDRLEN(what, member) \
177 case (what): \
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);
183 default:
184 bug();
188 static inline u32 pcap_get_total_length(pcap_pkthdr_t *phdr, enum pcap_type type)
190 switch (type) {
191 #define CASE_RET_TOTLEN(what, member) \
192 case (what): \
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);
198 default:
199 bug();
203 static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
204 struct sockaddr_ll *sll,
205 pcap_pkthdr_t *phdr,
206 enum pcap_type type)
208 switch (type) {
209 case DEFAULT:
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;
214 break;
216 case NSEC:
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;
221 break;
223 case KUZNETZOV:
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;
231 break;
233 case BORKMANN:
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;
242 break;
244 default:
245 bug();
249 static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
250 enum pcap_type type,
251 struct tpacket2_hdr *thdr,
252 struct sockaddr_ll *sll)
254 switch (type) {
255 case DEFAULT:
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;
260 break;
262 case NSEC:
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;
267 break;
269 case KUZNETZOV:
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;
274 break;
276 case BORKMANN:
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;
281 break;
283 default:
284 bug();
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 {
299 uint32_t magic;
300 char *desc;
301 uint16_t features;
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 |
309 FEATURE_LEN |
310 FEATURE_CAPLEN,
311 }, {
312 .magic = NSEC_TCPDUMP_MAGIC,
313 .desc = "tcpdump-capable pcap with ns resolution",
314 .features = FEATURE_TIMEVAL_NS |
315 FEATURE_LEN |
316 FEATURE_CAPLEN,
317 }, {
318 .magic = KUZNETZOV_TCPDUMP_MAGIC,
319 .desc = "Alexey Kuznetzov's pcap",
320 .features = FEATURE_TIMEVAL_MS |
321 FEATURE_LEN |
322 FEATURE_CAPLEN |
323 FEATURE_IFINDEX |
324 FEATURE_PROTO |
325 FEATURE_PKTTYPE,
326 }, {
327 .magic = BORKMANN_TCPDUMP_MAGIC,
328 .desc = "netsniff-ng pcap",
329 .features = FEATURE_TIMEVAL_NS |
330 FEATURE_LEN |
331 FEATURE_CAPLEN |
332 FEATURE_IFINDEX |
333 FEATURE_PROTO |
334 FEATURE_HATYPE |
335 FEATURE_PKTTYPE,
339 static inline void pcap_dump_type_features(void)
341 int i;
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");
350 continue;
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,
386 uint32_t snaplen)
388 hdr->magic = magic;
389 hdr->version_major = PCAP_VERSION_MAJOR;
390 hdr->version_minor = PCAP_VERSION_MINOR;
391 hdr->thiszone = thiszone;
392 hdr->sigfigs = 0;
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:
404 break;
405 default:
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)
420 ssize_t ret;
421 struct pcap_filehdr hdr;
423 ret = read(fd, &hdr, sizeof(hdr));
424 if (unlikely(ret != sizeof(hdr)))
425 return -EIO;
427 pcap_validate_header(&hdr);
429 *magic = hdr.magic;
430 *linktype = hdr.linktype;
432 return 0;
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)
440 ssize_t ret;
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");
451 return 0;
454 #endif /* PCAP_H */