xio: rename xio to ioops and reduce its includes
[netsniff-ng.git] / pcap_mm.c
blob848f7e08e2d27511284d382fa177cae72de8a63f
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #define _GNU_SOURCE
8 #include <stdio.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <stdbool.h>
14 #include <sys/mman.h>
16 #include "pcap_io.h"
17 #include "ioops.h"
18 #include "xutils.h"
19 #include "built_in.h"
20 #include "iosched.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 fmemcpy(ptr_va_curr, &phdr->raw, hdrsize);
61 ptr_va_curr += hdrsize;
62 fmemcpy(ptr_va_curr, packet, len);
63 ptr_va_curr += len;
65 return hdrsize + 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))
74 return -EIO;
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))
81 return -EIO;
82 if (unlikely(hdrlen == 0 || hdrlen > len))
83 return -EINVAL;
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)
100 int ret;
101 off_t pos;
102 struct stat sb;
104 map_size = ____get_map_size(jumbo);
106 ret = fstat(fd, &sb);
107 if (ret < 0)
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);
113 if (pos < 0)
114 panic("Cannot lseek pcap file!\n");
116 ret = write_or_die(fd, "", 1);
117 if (ret != 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);
124 if (ret < 0)
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)
132 int ret;
133 struct stat sb;
135 ret = fstat(fd, &sb);
136 if (ret < 0)
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);
146 if (ret < 0)
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)
154 set_ioprio_be();
157 static int pcap_mm_prepare_access(int fd, enum pcap_mode mode, bool jumbo)
159 switch (mode) {
160 case PCAP_MODE_RD:
161 __pcap_mm_prepare_access_rd(fd);
162 break;
163 case PCAP_MODE_WR:
164 __pcap_mm_prepare_access_wr(fd, jumbo);
165 break;
166 default:
167 bug();
170 return 0;
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)
180 int ret;
182 ret = munmap(ptr_va_start, map_size);
183 if (ret < 0)
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));
188 if (ret)
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,