trafgen: fix packet socket initialization with multiple CPUs
[netsniff-ng.git] / trafgen_dev.c
blob489da98d7daf9899e83a19337ec58a97c0c7dc5b
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
4 * Swiss federal institute of technology (ETH Zurich)
5 * Subject to the GPL, version 2.
6 */
8 #define _GNU_SOURCE
10 #include <fcntl.h>
11 #include <sys/stat.h>
12 #include <string.h>
13 #include <net/ethernet.h>
15 #include "sock.h"
16 #include "xmalloc.h"
17 #include "pcap_io.h"
18 #include "built_in.h"
19 #include "mac80211.h"
20 #include "linktype.h"
21 #include "trafgen_dev.h"
22 #include "trafgen_conf.h"
23 #include "trafgen_dump.h"
25 static int dev_pcap_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
27 dev->pcap_magic = ORIGINAL_TCPDUMP_MAGIC;
28 dev->pcap_ops = pcap_ops[PCAP_OPS_SG];
30 if (mode == DEV_IO_IN) {
31 if (!strncmp("-", name, strlen("-"))) {
32 dev->fd = dup_or_die(fileno(stdin));
33 close(fileno(stdin));
34 } else {
35 dev->fd = open(name, O_RDONLY | O_LARGEFILE | O_NOATIME);
36 if (dev->fd < 0 && errno == EPERM)
37 dev->fd = open_or_die(name, O_RDONLY | O_LARGEFILE);
40 dev->pcap_mode = PCAP_MODE_RD;
41 dev->buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
42 dev->buf = xmalloc_aligned(dev->buf_len, CO_CACHE_LINE_SIZE);
43 } else if (mode & DEV_IO_OUT) {
44 if (!strncmp("-", name, strlen("-"))) {
45 dev->fd = dup_or_die(fileno(stdout));
46 close(fileno(stdout));
47 } else {
48 dev->fd = open_or_die_m(name, O_RDWR | O_CREAT | O_TRUNC |
49 O_LARGEFILE, DEFFILEMODE);
52 dev->pcap_mode = PCAP_MODE_WR;
53 } else {
54 bug();
57 if (dev->fd < 0)
58 panic("pcap_dev: Cannot open file %s! %s.\n", name, strerror(errno));
60 if (dev->pcap_ops->init_once_pcap)
61 dev->pcap_ops->init_once_pcap(false);
63 if (mode == DEV_IO_IN) {
64 if (dev->pcap_ops->pull_fhdr_pcap(dev->fd, &dev->pcap_magic, &dev->link_type))
65 panic("Error reading pcap header!\n");
68 if (dev->pcap_ops->prepare_access_pcap) {
69 if (dev->pcap_ops->prepare_access_pcap(dev->fd, dev->pcap_mode, false))
70 panic("Error prepare reading pcap!\n");
73 return 0;
76 static struct packet *dev_pcap_read(struct dev_io *dev)
78 size_t len = dev->buf_len;
79 uint8_t *buf = dev->buf;
80 pcap_pkthdr_t phdr;
81 struct packet *pkt;
82 size_t pkt_len;
84 if (dev->pcap_ops->read_pcap(dev->fd, &phdr, dev->pcap_magic, buf, len) <= 0)
85 return NULL;
87 pkt_len = pcap_get_length(&phdr, dev->pcap_magic);
88 if (!pkt_len)
89 return NULL;
91 pkt = realloc_packet();
93 pkt->len = pkt_len;
94 pkt->is_created = true;
95 pkt->payload = xzmalloc(pkt_len);
96 memcpy(pkt->payload, buf, pkt_len);
97 pcap_get_tstamp(&phdr, dev->pcap_magic, &pkt->tstamp);
99 return pkt;
102 static int dev_pcap_write(struct dev_io *dev, struct packet *pkt)
104 uint8_t *buf = pkt->payload;
105 size_t len = pkt->len;
106 struct timeval time;
107 pcap_pkthdr_t phdr;
108 int ret;
110 /* Write PCAP file header only once */
111 if (!dev->is_initialized) {
112 if (dev->pcap_ops->push_fhdr_pcap(dev->fd, dev->pcap_magic, dev->link_type)) {
113 fprintf(stderr, "Error writing pcap header!\n");
114 return -1;
117 if (dev->pcap_ops->prepare_access_pcap) {
118 if (dev->pcap_ops->prepare_access_pcap(dev->fd, PCAP_MODE_WR, true)) {
119 fprintf(stderr, "Error prepare writing pcap!\n");
120 return -1;
124 dev->is_initialized = true;
127 bug_on(gettimeofday(&time, NULL));
129 phdr.ppo.ts.tv_sec = time.tv_sec;
130 phdr.ppo.ts.tv_usec = time.tv_usec;
131 phdr.ppo.caplen = len;
132 phdr.ppo.len = len;
134 ret = dev->pcap_ops->write_pcap(dev->fd, &phdr, dev->pcap_magic,
135 buf, pcap_get_length(&phdr, dev->pcap_magic));
137 if (unlikely(ret != (int) pcap_get_total_length(&phdr, dev->pcap_magic))) {
138 fprintf(stderr, "Write error to pcap!\n");
139 return -1;
142 return ret;
145 static void dev_pcap_close(struct dev_io *dev)
147 if (dev->pcap_mode == PCAP_MODE_WR) {
148 dev->pcap_ops->fsync_pcap(dev->fd);
149 } else if (dev->pcap_mode == PCAP_MODE_RD) {
150 free(dev->buf);
151 dev->buf_len = 0;
152 dev->buf = NULL;
155 if (dev->pcap_ops->prepare_close_pcap)
156 dev->pcap_ops->prepare_close_pcap(dev->fd, dev->pcap_mode);
158 close(dev->fd);
161 static const struct dev_io_ops dev_pcap_ops = {
162 .open = dev_pcap_open,
163 .read = dev_pcap_read,
164 .write = dev_pcap_write,
165 .close = dev_pcap_close,
168 static int dev_net_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
170 dev->ifindex = __device_ifindex(name);
171 dev->dev_type = device_type(name);
172 dev->fd = pf_socket();
174 return 0;
177 static int dev_net_write(struct dev_io *dev, struct packet *pkt)
179 struct sockaddr_ll saddr = {
180 .sll_family = PF_PACKET,
181 .sll_halen = ETH_ALEN,
182 .sll_ifindex = dev->ifindex,
184 uint8_t *buf = pkt->payload;
185 size_t len = pkt->len;
187 return sendto(dev->fd, buf, len, 0, (struct sockaddr *) &saddr, sizeof(saddr));
190 static int dev_net_set_link_type(struct dev_io *dev, int link_type)
192 if (link_type != LINKTYPE_IEEE802_11 && link_type != LINKTYPE_IEEE802_11_RADIOTAP)
193 return 0;
195 dev->trans = xstrdup(dev->name);
196 xfree(dev->name);
198 enter_rfmon_mac80211(dev->trans, &dev->name);
199 dev->ifindex = __device_ifindex(dev->name);
200 dev->dev_type = device_type(dev->name);
202 return 0;
205 static void dev_net_close(struct dev_io *dev)
207 if (dev->link_type == LINKTYPE_IEEE802_11 || dev->link_type == LINKTYPE_IEEE802_11_RADIOTAP)
208 leave_rfmon_mac80211(dev->name);
210 free(dev->trans);
213 static const struct dev_io_ops dev_net_ops = {
214 .open = dev_net_open,
215 .write = dev_net_write,
216 .set_link_type = dev_net_set_link_type,
217 .close = dev_net_close,
220 static int dev_cfg_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
222 dev->fd = open_or_die_m(name, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, DEFFILEMODE);
223 return 0;
226 static int dev_cfg_write(struct dev_io *dev, struct packet *pkt)
228 if (packet_dump_fd(pkt, dev->fd))
229 return -1;
231 return pkt->len;
234 static void dev_cfg_close(struct dev_io *dev)
236 close(dev->fd);
239 static const struct dev_io_ops dev_cfg_ops = {
240 .open = dev_cfg_open,
241 .write = dev_cfg_write,
242 .close = dev_cfg_close,
245 struct dev_io *dev_io_create(const char *name, enum dev_io_mode_t mode)
247 struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
249 dev->mode = mode;
250 if (strstr(name, ".pcap")) {
251 dev->name = xstrdup(name);
252 dev->ops = &dev_pcap_ops;
253 } else if (strstr(name, ".cfg")) {
254 dev->name = xstrdup(name);
255 dev->ops = &dev_cfg_ops;
256 } else if (device_mtu(name) > 0) {
257 dev->name = xstrndup(name, IFNAMSIZ);
258 dev->ops = &dev_net_ops;
259 } else {
260 fprintf(stderr, "No networking device or pcap file: %s\n", name);
261 return NULL;
264 return dev;
267 extern void dev_io_open(struct dev_io *dev)
269 bug_on(!dev);
270 bug_on(!dev->ops);
272 if (dev->ops->open)
273 if (dev->ops->open(dev, dev->name, dev->mode))
274 panic("Cannot open io %s mode %d\n", dev->name,
275 dev->mode);
278 int dev_io_write(struct dev_io *dev, struct packet *pkt)
280 bug_on(!dev);
281 bug_on(!dev->ops);
283 if (dev->ops->write)
284 return dev->ops->write(dev, pkt);
286 return 0;
289 struct packet *dev_io_read(struct dev_io *dev)
291 bug_on(!dev);
292 bug_on(!dev->ops);
294 if (dev->ops->read)
295 return dev->ops->read(dev);
297 return NULL;
300 const char *dev_io_name_get(struct dev_io *dev)
302 return dev->name;
305 bool dev_io_is_netdev(struct dev_io *dev)
307 return dev->ops == &dev_net_ops;
310 bool dev_io_is_pcap(struct dev_io *dev)
312 return dev->ops == &dev_pcap_ops;
315 int dev_io_link_type_set(struct dev_io *dev, int link_type)
317 if (dev->ops->set_link_type) {
318 if (dev->ops->set_link_type(dev, link_type))
319 return -1;
322 dev->link_type = link_type;
323 return 0;
326 int dev_io_ifindex_get(struct dev_io *dev)
328 return dev->ifindex;
331 int dev_io_fd_get(struct dev_io *dev)
333 return dev->fd;
336 void dev_io_close(struct dev_io *dev)
338 if (dev) {
339 if (dev->ops->close)
340 dev->ops->close(dev);
342 free(dev->name);
343 free(dev);