2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann.
4 * Subject to the GPL, version 2.
21 static size_t map_size
= 0;
22 static char *ptr_va_start
, *ptr_va_curr
;
24 static void __pcap_mmap_write_need_remap(int fd
)
27 off_t pos
, map_size_old
= map_size
;
28 off_t offset
= ptr_va_curr
- ptr_va_start
;
30 map_size
= PAGE_ALIGN(map_size_old
* 10 / 8);
32 pos
= lseek(fd
, map_size
, SEEK_SET
);
34 panic("Cannot lseek pcap file!\n");
36 ret
= write_or_die(fd
, "", 1);
38 panic("Cannot write file!\n");
40 ptr_va_start
= mremap(ptr_va_start
, map_size_old
, map_size
, MREMAP_MAYMOVE
);
41 if (ptr_va_start
== MAP_FAILED
)
42 panic("mmap of file failed!");
44 ret
= madvise(ptr_va_start
, map_size
, MADV_SEQUENTIAL
);
46 panic("Failed to give kernel mmap advise!\n");
48 ptr_va_curr
= ptr_va_start
+ offset
;
51 static ssize_t
pcap_mm_write(int fd
, pcap_pkthdr_t
*phdr
, enum pcap_type type
,
52 const uint8_t *packet
, size_t len
)
54 size_t hdrsize
= pcap_get_hdr_length(phdr
, type
);
56 if ((off_t
) (ptr_va_curr
- ptr_va_start
) + hdrsize
+ len
> map_size
)
57 __pcap_mmap_write_need_remap(fd
);
59 memcpy(ptr_va_curr
, &phdr
->raw
, hdrsize
);
60 ptr_va_curr
+= hdrsize
;
61 memcpy(ptr_va_curr
, packet
, len
);
67 static ssize_t
pcap_mm_read(int fd __maybe_unused
, pcap_pkthdr_t
*phdr
,
68 enum pcap_type type
, uint8_t *packet
, size_t len
)
70 size_t hdrsize
= pcap_get_hdr_length(phdr
, type
), hdrlen
;
72 if (unlikely((off_t
) (ptr_va_curr
+ hdrsize
- ptr_va_start
) > (off_t
) map_size
))
75 memcpy(&phdr
->raw
, ptr_va_curr
, hdrsize
);
76 ptr_va_curr
+= hdrsize
;
77 hdrlen
= pcap_get_length(phdr
, type
);
79 if (unlikely((off_t
) (ptr_va_curr
+ hdrlen
- ptr_va_start
) > (off_t
) map_size
))
81 if (unlikely(hdrlen
== 0 || hdrlen
> len
))
84 memcpy(packet
, ptr_va_curr
, hdrlen
);
85 ptr_va_curr
+= hdrlen
;
87 return hdrsize
+ hdrlen
;
90 static inline off_t
____get_map_size(bool jumbo
)
92 int allocsz
= jumbo
? 16 : 3;
94 return PAGE_ALIGN(sizeof(struct pcap_filehdr
) + (RUNTIME_PAGE_SIZE
* allocsz
) * 1024);
97 static void __pcap_mm_prepare_access_wr(int fd
, bool jumbo
)
103 map_size
= ____get_map_size(jumbo
);
105 ret
= fstat(fd
, &sb
);
107 panic("Cannot fstat pcap file!\n");
108 if (!S_ISREG (sb
.st_mode
))
109 panic("pcap dump file is not a regular file!\n");
111 pos
= lseek(fd
, map_size
, SEEK_SET
);
113 panic("Cannot lseek pcap file!\n");
115 ret
= write_or_die(fd
, "", 1);
117 panic("Cannot write file!\n");
119 ptr_va_start
= mmap(NULL
, map_size
, PROT_WRITE
, MAP_SHARED
, fd
, 0);
120 if (ptr_va_start
== MAP_FAILED
)
121 panic("mmap of file failed!");
122 ret
= madvise(ptr_va_start
, map_size
, MADV_SEQUENTIAL
);
124 panic("Failed to give kernel mmap advise!\n");
126 ptr_va_curr
= ptr_va_start
+ sizeof(struct pcap_filehdr
);
129 static void __pcap_mm_prepare_access_rd(int fd
)
134 ret
= fstat(fd
, &sb
);
136 panic("Cannot fstat pcap file!\n");
137 if (!S_ISREG (sb
.st_mode
))
138 panic("pcap dump file is not a regular file!\n");
140 map_size
= sb
.st_size
;
141 ptr_va_start
= mmap(NULL
, map_size
, PROT_READ
, MAP_SHARED
| MAP_LOCKED
, fd
, 0);
142 if (ptr_va_start
== MAP_FAILED
)
143 panic("mmap of file failed!");
144 ret
= madvise(ptr_va_start
, map_size
, MADV_SEQUENTIAL
);
146 panic("Failed to give kernel mmap advise!\n");
148 ptr_va_curr
= ptr_va_start
+ sizeof(struct pcap_filehdr
);
151 static void pcap_mm_init_once(bool enforce_prio
)
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 __maybe_unused
)
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
,