mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / trafgen_dev.c
blobb01a96db66203a5d29715d45384c64b5740aef4c
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 free(dev);
261 fprintf(stderr, "No networking device or pcap file: %s\n", name);
262 return NULL;
265 return dev;
268 extern void dev_io_open(struct dev_io *dev)
270 bug_on(!dev);
271 bug_on(!dev->ops);
273 if (dev->ops->open)
274 if (dev->ops->open(dev, dev->name, dev->mode))
275 panic("Cannot open io %s mode %d\n", dev->name,
276 dev->mode);
279 int dev_io_write(struct dev_io *dev, struct packet *pkt)
281 bug_on(!dev);
282 bug_on(!dev->ops);
284 if (dev->ops->write)
285 return dev->ops->write(dev, pkt);
287 return 0;
290 struct packet *dev_io_read(struct dev_io *dev)
292 bug_on(!dev);
293 bug_on(!dev->ops);
295 if (dev->ops->read)
296 return dev->ops->read(dev);
298 return NULL;
301 const char *dev_io_name_get(struct dev_io *dev)
303 return dev->name;
306 bool dev_io_is_netdev(struct dev_io *dev)
308 return dev->ops == &dev_net_ops;
311 bool dev_io_is_pcap(struct dev_io *dev)
313 return dev->ops == &dev_pcap_ops;
316 int dev_io_link_type_set(struct dev_io *dev, int link_type)
318 if (dev->ops->set_link_type) {
319 if (dev->ops->set_link_type(dev, link_type))
320 return -1;
323 dev->link_type = link_type;
324 return 0;
327 int dev_io_ifindex_get(struct dev_io *dev)
329 return dev->ifindex;
332 int dev_io_fd_get(struct dev_io *dev)
334 return dev->fd;
337 void dev_io_close(struct dev_io *dev)
339 if (dev) {
340 if (dev->ops->close)
341 dev->ops->close(dev);
343 free(dev->name);
344 free(dev);