trafgen: Fix output pcap file name length trimming
[netsniff-ng.git] / trafgen_dev.c
blob80e7481b2da91b10c7a3dd68e1d81b071e637670
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 "trafgen_dev.h"
21 static int dev_pcap_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
23 dev->pcap_magic = ORIGINAL_TCPDUMP_MAGIC;
24 dev->pcap_ops = pcap_ops[PCAP_OPS_SG];
26 if (mode == DEV_IO_IN) {
27 if (!strncmp("-", name, strlen("-"))) {
28 dev->fd = dup_or_die(fileno(stdin));
29 close(fileno(stdin));
30 } else {
31 dev->fd = open(name, O_RDONLY | O_LARGEFILE | O_NOATIME);
32 if (dev->fd < 0 && errno == EPERM)
33 dev->fd = open_or_die(name, O_RDONLY | O_LARGEFILE);
36 dev->pcap_mode = PCAP_MODE_RD;
37 } else if (mode & DEV_IO_OUT) {
38 if (!strncmp("-", name, strlen("-"))) {
39 dev->fd = dup_or_die(fileno(stdout));
40 close(fileno(stdout));
41 } else {
42 dev->fd = open_or_die_m(name, O_RDWR | O_CREAT | O_TRUNC |
43 O_LARGEFILE, DEFFILEMODE);
46 dev->pcap_mode = PCAP_MODE_WR;
47 } else {
48 bug();
51 if (dev->fd < 0)
52 panic("pcap_dev: Cannot open file %s! %s.\n", name, strerror(errno));
54 if (dev->pcap_ops->init_once_pcap)
55 dev->pcap_ops->init_once_pcap(false);
57 if (mode == DEV_IO_IN) {
58 if (dev->pcap_ops->pull_fhdr_pcap(dev->fd, &dev->pcap_magic, &dev->link_type))
59 panic("Error reading pcap header!\n");
62 if (dev->pcap_ops->prepare_access_pcap) {
63 if (dev->pcap_ops->prepare_access_pcap(dev->fd, dev->pcap_mode, false))
64 panic("Error prepare reading pcap!\n");
67 return 0;
70 static int dev_pcap_read(struct dev_io *dev, uint8_t *buf, size_t len,
71 struct timespec *tstamp)
73 pcap_pkthdr_t phdr;
74 size_t pkt_len;
76 if (dev->pcap_ops->read_pcap(dev->fd, &phdr, dev->pcap_magic, buf, len) <= 0)
77 return -1;
79 pkt_len = pcap_get_length(&phdr, dev->pcap_magic);
80 if (!pkt_len)
81 return -1;
83 pcap_get_tstamp(&phdr, dev->pcap_magic, tstamp);
85 return pkt_len;
88 static int dev_pcap_write(struct dev_io *dev, const uint8_t *buf, size_t len)
90 struct timeval time;
91 pcap_pkthdr_t phdr;
92 int ret;
94 /* Write PCAP file header only once */
95 if (!dev->is_initialized) {
96 if (dev->pcap_ops->push_fhdr_pcap(dev->fd, dev->pcap_magic, dev->link_type)) {
97 fprintf(stderr, "Error writing pcap header!\n");
98 return -1;
101 if (dev->pcap_ops->prepare_access_pcap) {
102 if (dev->pcap_ops->prepare_access_pcap(dev->fd, PCAP_MODE_WR, true)) {
103 fprintf(stderr, "Error prepare writing pcap!\n");
104 return -1;
108 dev->is_initialized = true;
111 bug_on(gettimeofday(&time, NULL));
113 phdr.ppo.ts.tv_sec = time.tv_sec;
114 phdr.ppo.ts.tv_usec = time.tv_usec;
115 phdr.ppo.caplen = len;
116 phdr.ppo.len = len;
118 ret = dev->pcap_ops->write_pcap(dev->fd, &phdr, dev->pcap_magic,
119 buf, pcap_get_length(&phdr, dev->pcap_magic));
121 if (unlikely(ret != (int) pcap_get_total_length(&phdr, dev->pcap_magic))) {
122 fprintf(stderr, "Write error to pcap!\n");
123 return -1;
126 return ret;
129 static void dev_pcap_close(struct dev_io *dev)
131 if (dev->pcap_mode == PCAP_MODE_WR)
132 dev->pcap_ops->fsync_pcap(dev->fd);
134 if (dev->pcap_ops->prepare_close_pcap)
135 dev->pcap_ops->prepare_close_pcap(dev->fd, dev->pcap_mode);
137 close(dev->fd);
140 static const struct dev_io_ops dev_pcap_ops = {
141 .open = dev_pcap_open,
142 .read = dev_pcap_read,
143 .write = dev_pcap_write,
144 .close = dev_pcap_close,
147 static int dev_net_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
149 dev->ifindex = __device_ifindex(name);
150 dev->dev_type = device_type(name);
151 dev->fd = pf_socket();
153 return 0;
156 static int dev_net_write(struct dev_io *dev, const uint8_t *buf, size_t len)
158 struct sockaddr_ll saddr = {
159 .sll_family = PF_PACKET,
160 .sll_halen = ETH_ALEN,
161 .sll_ifindex = dev->ifindex,
164 return sendto(dev->fd, buf, len, 0, (struct sockaddr *) &saddr, sizeof(saddr));
167 static const struct dev_io_ops dev_net_ops = {
168 .open = dev_net_open,
169 .write = dev_net_write,
172 struct dev_io *dev_io_open(const char *name, enum dev_io_mode_t mode)
174 struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
176 if (strstr(name, ".pcap")) {
177 dev->name = xstrdup(name);
178 dev->ops = &dev_pcap_ops;
179 } else if (device_mtu(name) > 0) {
180 dev->name = xstrndup(name, IFNAMSIZ);
181 dev->ops = &dev_net_ops;
182 } else {
183 fprintf(stderr, "No networking device or pcap file: %s\n", name);
184 return NULL;
187 if (dev->ops->open) {
188 if (dev->ops->open(dev, name, mode)) {
189 xfree(dev);
190 return NULL;
194 return dev;
197 int dev_io_write(struct dev_io *dev, const uint8_t *buf, size_t len)
199 bug_on(!dev);
200 bug_on(!dev->ops);
202 if (dev->ops->write)
203 return dev->ops->write(dev, buf, len);
205 return 0;
208 int dev_io_read(struct dev_io *dev, uint8_t *buf, size_t len,
209 struct timespec *tstamp)
211 bug_on(!dev);
212 bug_on(!dev->ops);
214 if (dev->ops->read)
215 return dev->ops->read(dev, buf, len, tstamp);
217 return 0;
220 const char *dev_io_name_get(struct dev_io *dev)
222 return dev->name;
225 bool dev_io_is_netdev(struct dev_io *dev)
227 return dev->ops == &dev_net_ops;
230 bool dev_io_is_pcap(struct dev_io *dev)
232 return dev->ops == &dev_pcap_ops;
235 void dev_io_link_type_set(struct dev_io *dev, int link_type)
237 dev->link_type = link_type;
240 int dev_io_ifindex_get(struct dev_io *dev)
242 return dev->ifindex;
245 int dev_io_fd_get(struct dev_io *dev)
247 return dev->fd;
250 void dev_io_close(struct dev_io *dev)
252 if (dev) {
253 if (dev->ops->close)
254 dev->ops->close(dev);
256 free(dev->name);
257 free(dev);