xio: add nacl's randombyte function
[netsniff-ng.git] / pcap_mm.c
blobcd966cfca214b4070b1b9ed2a8311e5d15150806
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 - 2013 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #define _GNU_SOURCE
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <stdbool.h>
15 #include <sys/mman.h>
17 #include "pcap.h"
18 #include "xio.h"
19 #include "xutils.h"
20 #include "built_in.h"
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)
27 int ret;
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);
34 if (pos < 0)
35 panic("Cannot lseek pcap file!\n");
37 ret = write_or_die(fd, "", 1);
38 if (ret != 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);
46 if (ret < 0)
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 switch (type) {
61 #define CASE_HDR_WRITE(what, __member__) \
62 case (what): \
63 fmemcpy(ptr_va_curr, &phdr->__member__, hdrsize); \
64 break
65 CASE_HDR_WRITE(DEFAULT, ppo);
66 CASE_HDR_WRITE(NSEC, ppn);
67 CASE_HDR_WRITE(KUZNETZOV, ppk);
68 CASE_HDR_WRITE(BORKMANN, ppb);
69 default:
70 bug();
73 ptr_va_curr += hdrsize;
74 fmemcpy(ptr_va_curr, packet, len);
75 ptr_va_curr += len;
77 return hdrsize + len;
80 static ssize_t pcap_mm_read(int fd, pcap_pkthdr_t *phdr, enum pcap_type type,
81 uint8_t *packet, size_t len)
83 size_t hdrsize = pcap_get_hdr_length(phdr, type), hdrlen;
85 if (unlikely((off_t) (ptr_va_curr + hdrsize - ptr_va_start) > map_size))
86 return -EIO;
88 switch (type) {
89 #define CASE_HDR_READ(what, __member__) \
90 case (what): \
91 fmemcpy(&phdr->__member__, ptr_va_curr, hdrsize); \
92 break
93 CASE_HDR_READ(DEFAULT, ppo);
94 CASE_HDR_READ(NSEC, ppn);
95 CASE_HDR_READ(KUZNETZOV, ppk);
96 CASE_HDR_READ(BORKMANN, ppb);
97 default:
98 bug();
101 ptr_va_curr += hdrsize;
102 hdrlen = pcap_get_length(phdr, type);
104 if (unlikely((off_t) (ptr_va_curr + hdrlen - ptr_va_start) > map_size))
105 return -EIO;
106 if (unlikely(hdrlen == 0 || hdrlen > len))
107 return -EINVAL;
109 fmemcpy(packet, ptr_va_curr, hdrlen);
110 ptr_va_curr += hdrlen;
112 return hdrsize + hdrlen;
115 static inline off_t ____get_map_size(bool jumbo)
117 int allocsz = jumbo ? 16 : 3;
119 return PAGE_ALIGN(sizeof(struct pcap_filehdr) + (PAGE_SIZE * allocsz) * 1024);
122 static void __pcap_mm_prepare_access_wr(int fd, bool jumbo)
124 int ret;
125 off_t pos;
126 struct stat sb;
128 map_size = ____get_map_size(jumbo);
130 ret = fstat(fd, &sb);
131 if (ret < 0)
132 panic("Cannot fstat pcap file!\n");
133 if (!S_ISREG (sb.st_mode))
134 panic("pcap dump file is not a regular file!\n");
136 pos = lseek(fd, map_size, SEEK_SET);
137 if (pos < 0)
138 panic("Cannot lseek pcap file!\n");
140 ret = write_or_die(fd, "", 1);
141 if (ret != 1)
142 panic("Cannot write file!\n");
144 ptr_va_start = mmap(0, map_size, PROT_WRITE, MAP_SHARED, fd, 0);
145 if (ptr_va_start == MAP_FAILED)
146 panic("mmap of file failed!");
147 ret = madvise(ptr_va_start, map_size, MADV_SEQUENTIAL);
148 if (ret < 0)
149 panic("Failed to give kernel mmap advise!\n");
151 ptr_va_curr = ptr_va_start + sizeof(struct pcap_filehdr);
154 static void __pcap_mm_prepare_access_rd(int fd)
156 int ret;
157 struct stat sb;
159 ret = fstat(fd, &sb);
160 if (ret < 0)
161 panic("Cannot fstat pcap file!\n");
162 if (!S_ISREG (sb.st_mode))
163 panic("pcap dump file is not a regular file!\n");
165 map_size = sb.st_size;
166 ptr_va_start = mmap(0, map_size, PROT_READ, MAP_SHARED | MAP_LOCKED, fd, 0);
167 if (ptr_va_start == MAP_FAILED)
168 panic("mmap of file failed!");
169 ret = madvise(ptr_va_start, map_size, MADV_SEQUENTIAL);
170 if (ret < 0)
171 panic("Failed to give kernel mmap advise!\n");
173 ptr_va_curr = ptr_va_start + sizeof(struct pcap_filehdr);
176 static int pcap_mm_prepare_access(int fd, enum pcap_mode mode, bool jumbo)
178 set_ioprio_be();
180 switch (mode) {
181 case PCAP_MODE_RD:
182 __pcap_mm_prepare_access_rd(fd);
183 break;
184 case PCAP_MODE_WR:
185 __pcap_mm_prepare_access_wr(fd, jumbo);
186 break;
187 default:
188 bug();
191 return 0;
194 static void pcap_mm_fsync(int fd)
196 msync(ptr_va_start, (off_t) (ptr_va_curr - ptr_va_start), MS_ASYNC);
199 static void pcap_mm_prepare_close(int fd, enum pcap_mode mode)
201 int ret;
203 ret = munmap(ptr_va_start, map_size);
204 if (ret < 0)
205 panic("Cannot unmap the pcap file!\n");
207 if (mode == PCAP_MODE_WR) {
208 ret = ftruncate(fd, (off_t) (ptr_va_curr - ptr_va_start));
209 if (ret)
210 panic("Cannot truncate the pcap file!\n");
214 const struct pcap_file_ops pcap_mm_ops = {
215 .pull_fhdr_pcap = pcap_generic_pull_fhdr,
216 .push_fhdr_pcap = pcap_generic_push_fhdr,
217 .prepare_access_pcap = pcap_mm_prepare_access,
218 .prepare_close_pcap = pcap_mm_prepare_close,
219 .read_pcap = pcap_mm_read,
220 .write_pcap = pcap_mm_write,
221 .fsync_pcap = pcap_mm_fsync,