2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann.
4 * Subject to the GPL, version 2.
22 static size_t map_size
= 0;
23 static char *ptr_va_start
, *ptr_va_curr
;
25 static void __pcap_mmap_write_need_remap(int fd
)
28 off_t pos
, map_size_old
= map_size
;
29 off_t offset
= ptr_va_curr
- ptr_va_start
;
31 map_size
= PAGE_ALIGN(map_size_old
* 10 / 8);
33 pos
= lseek(fd
, map_size
, SEEK_SET
);
35 panic("Cannot lseek pcap file!\n");
37 ret
= write_or_die(fd
, "", 1);
39 panic("Cannot write file!\n");
41 ptr_va_start
= mremap(ptr_va_start
, map_size_old
, map_size
, MREMAP_MAYMOVE
);
42 if (ptr_va_start
== MAP_FAILED
)
43 panic("mmap of file failed!");
45 ret
= madvise(ptr_va_start
, map_size
, MADV_SEQUENTIAL
);
47 panic("Failed to give kernel mmap advise!\n");
49 ptr_va_curr
= ptr_va_start
+ offset
;
52 static ssize_t
pcap_mm_write(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
53 const uint8_t *packet
, size_t len
)
55 size_t hdrsize
= pcap_get_hdr_length(phdr
, type
);
57 if ((off_t
) (ptr_va_curr
- ptr_va_start
) + hdrsize
+ len
> map_size
)
58 __pcap_mmap_write_need_remap(fd
);
60 fmemcpy(ptr_va_curr
, &phdr
->raw
, hdrsize
);
61 ptr_va_curr
+= hdrsize
;
62 fmemcpy(ptr_va_curr
, packet
, len
);
68 static ssize_t
pcap_mm_read(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
69 uint8_t *packet
, size_t len
)
71 size_t hdrsize
= pcap_get_hdr_length(phdr
, type
), hdrlen
;
73 if (unlikely((off_t
) (ptr_va_curr
+ hdrsize
- ptr_va_start
) > map_size
))
76 fmemcpy(&phdr
->raw
, ptr_va_curr
, hdrsize
);
77 ptr_va_curr
+= hdrsize
;
78 hdrlen
= pcap_get_length(phdr
, type
);
80 if (unlikely((off_t
) (ptr_va_curr
+ hdrlen
- ptr_va_start
) > map_size
))
82 if (unlikely(hdrlen
== 0 || hdrlen
> len
))
85 fmemcpy(packet
, ptr_va_curr
, hdrlen
);
86 ptr_va_curr
+= hdrlen
;
88 return hdrsize
+ hdrlen
;
91 static inline off_t
____get_map_size(bool jumbo
)
93 int allocsz
= jumbo
? 16 : 3;
95 return PAGE_ALIGN(sizeof(struct pcap_filehdr
) + (PAGE_SIZE
* allocsz
) * 1024);
98 static void __pcap_mm_prepare_access_wr(int fd
, bool jumbo
)
104 map_size
= ____get_map_size(jumbo
);
106 ret
= fstat(fd
, &sb
);
108 panic("Cannot fstat pcap file!\n");
109 if (!S_ISREG (sb
.st_mode
))
110 panic("pcap dump file is not a regular file!\n");
112 pos
= lseek(fd
, map_size
, SEEK_SET
);
114 panic("Cannot lseek pcap file!\n");
116 ret
= write_or_die(fd
, "", 1);
118 panic("Cannot write file!\n");
120 ptr_va_start
= mmap(0, map_size
, PROT_WRITE
, MAP_SHARED
, fd
, 0);
121 if (ptr_va_start
== MAP_FAILED
)
122 panic("mmap of file failed!");
123 ret
= madvise(ptr_va_start
, map_size
, MADV_SEQUENTIAL
);
125 panic("Failed to give kernel mmap advise!\n");
127 ptr_va_curr
= ptr_va_start
+ sizeof(struct pcap_filehdr
);
130 static void __pcap_mm_prepare_access_rd(int fd
)
135 ret
= fstat(fd
, &sb
);
137 panic("Cannot fstat pcap file!\n");
138 if (!S_ISREG (sb
.st_mode
))
139 panic("pcap dump file is not a regular file!\n");
141 map_size
= sb
.st_size
;
142 ptr_va_start
= mmap(0, map_size
, PROT_READ
, MAP_SHARED
| MAP_LOCKED
, fd
, 0);
143 if (ptr_va_start
== MAP_FAILED
)
144 panic("mmap of file failed!");
145 ret
= madvise(ptr_va_start
, map_size
, MADV_SEQUENTIAL
);
147 panic("Failed to give kernel mmap advise!\n");
149 ptr_va_curr
= ptr_va_start
+ sizeof(struct pcap_filehdr
);
152 static void pcap_mm_init_once(void)
157 static int pcap_mm_prepare_access(int fd
, enum pcap_mode mode
, bool jumbo
)
161 __pcap_mm_prepare_access_rd(fd
);
164 __pcap_mm_prepare_access_wr(fd
, jumbo
);
173 static void pcap_mm_fsync(int fd
)
175 msync(ptr_va_start
, (off_t
) (ptr_va_curr
- ptr_va_start
), MS_ASYNC
);
178 static void pcap_mm_prepare_close(int fd
, enum pcap_mode mode
)
182 ret
= munmap(ptr_va_start
, map_size
);
184 panic("Cannot unmap the pcap file!\n");
186 if (mode
== PCAP_MODE_WR
) {
187 ret
= ftruncate(fd
, (off_t
) (ptr_va_curr
- ptr_va_start
));
189 panic("Cannot truncate the pcap file!\n");
193 const struct pcap_file_ops pcap_mm_ops
= {
194 .init_once_pcap
= pcap_mm_init_once
,
195 .pull_fhdr_pcap
= pcap_generic_pull_fhdr
,
196 .push_fhdr_pcap
= pcap_generic_push_fhdr
,
197 .prepare_access_pcap
= pcap_mm_prepare_access
,
198 .prepare_close_pcap
= pcap_mm_prepare_close
,
199 .read_pcap
= pcap_mm_read
,
200 .write_pcap
= pcap_mm_write
,
201 .fsync_pcap
= pcap_mm_fsync
,