trafgen: Get packet from proto_hdr if possible
[netsniff-ng-new.git] / trafgen_dev.c
blobd7f1cd51e3b70804e0d448b84ef99f639fa409aa
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"
23 static int dev_pcap_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
25 dev->pcap_magic = ORIGINAL_TCPDUMP_MAGIC;
26 dev->pcap_ops = pcap_ops[PCAP_OPS_SG];
28 if (mode == DEV_IO_IN) {
29 if (!strncmp("-", name, strlen("-"))) {
30 dev->fd = dup_or_die(fileno(stdin));
31 close(fileno(stdin));
32 } else {
33 dev->fd = open(name, O_RDONLY | O_LARGEFILE | O_NOATIME);
34 if (dev->fd < 0 && errno == EPERM)
35 dev->fd = open_or_die(name, O_RDONLY | O_LARGEFILE);
38 dev->pcap_mode = PCAP_MODE_RD;
39 } else if (mode & DEV_IO_OUT) {
40 if (!strncmp("-", name, strlen("-"))) {
41 dev->fd = dup_or_die(fileno(stdout));
42 close(fileno(stdout));
43 } else {
44 dev->fd = open_or_die_m(name, O_RDWR | O_CREAT | O_TRUNC |
45 O_LARGEFILE, DEFFILEMODE);
48 dev->pcap_mode = PCAP_MODE_WR;
49 } else {
50 bug();
53 if (dev->fd < 0)
54 panic("pcap_dev: Cannot open file %s! %s.\n", name, strerror(errno));
56 if (dev->pcap_ops->init_once_pcap)
57 dev->pcap_ops->init_once_pcap(false);
59 if (mode == DEV_IO_IN) {
60 if (dev->pcap_ops->pull_fhdr_pcap(dev->fd, &dev->pcap_magic, &dev->link_type))
61 panic("Error reading pcap header!\n");
64 if (dev->pcap_ops->prepare_access_pcap) {
65 if (dev->pcap_ops->prepare_access_pcap(dev->fd, dev->pcap_mode, false))
66 panic("Error prepare reading pcap!\n");
69 return 0;
72 static int dev_pcap_read(struct dev_io *dev, uint8_t *buf, size_t len,
73 struct timespec *tstamp)
75 pcap_pkthdr_t phdr;
76 size_t pkt_len;
78 if (dev->pcap_ops->read_pcap(dev->fd, &phdr, dev->pcap_magic, buf, len) <= 0)
79 return -1;
81 pkt_len = pcap_get_length(&phdr, dev->pcap_magic);
82 if (!pkt_len)
83 return -1;
85 pcap_get_tstamp(&phdr, dev->pcap_magic, tstamp);
87 return pkt_len;
90 static int dev_pcap_write(struct dev_io *dev, const uint8_t *buf, size_t len)
92 struct timeval time;
93 pcap_pkthdr_t phdr;
94 int ret;
96 /* Write PCAP file header only once */
97 if (!dev->is_initialized) {
98 if (dev->pcap_ops->push_fhdr_pcap(dev->fd, dev->pcap_magic, dev->link_type)) {
99 fprintf(stderr, "Error writing pcap header!\n");
100 return -1;
103 if (dev->pcap_ops->prepare_access_pcap) {
104 if (dev->pcap_ops->prepare_access_pcap(dev->fd, PCAP_MODE_WR, true)) {
105 fprintf(stderr, "Error prepare writing pcap!\n");
106 return -1;
110 dev->is_initialized = true;
113 bug_on(gettimeofday(&time, NULL));
115 phdr.ppo.ts.tv_sec = time.tv_sec;
116 phdr.ppo.ts.tv_usec = time.tv_usec;
117 phdr.ppo.caplen = len;
118 phdr.ppo.len = len;
120 ret = dev->pcap_ops->write_pcap(dev->fd, &phdr, dev->pcap_magic,
121 buf, pcap_get_length(&phdr, dev->pcap_magic));
123 if (unlikely(ret != (int) pcap_get_total_length(&phdr, dev->pcap_magic))) {
124 fprintf(stderr, "Write error to pcap!\n");
125 return -1;
128 return ret;
131 static void dev_pcap_close(struct dev_io *dev)
133 if (dev->pcap_mode == PCAP_MODE_WR)
134 dev->pcap_ops->fsync_pcap(dev->fd);
136 if (dev->pcap_ops->prepare_close_pcap)
137 dev->pcap_ops->prepare_close_pcap(dev->fd, dev->pcap_mode);
139 close(dev->fd);
142 static const struct dev_io_ops dev_pcap_ops = {
143 .open = dev_pcap_open,
144 .read = dev_pcap_read,
145 .write = dev_pcap_write,
146 .close = dev_pcap_close,
149 static int dev_net_open(struct dev_io *dev, const char *name, enum dev_io_mode_t mode)
151 dev->ifindex = __device_ifindex(name);
152 dev->dev_type = device_type(name);
153 dev->fd = pf_socket();
155 return 0;
158 static int dev_net_write(struct dev_io *dev, const uint8_t *buf, size_t len)
160 struct sockaddr_ll saddr = {
161 .sll_family = PF_PACKET,
162 .sll_halen = ETH_ALEN,
163 .sll_ifindex = dev->ifindex,
166 return sendto(dev->fd, buf, len, 0, (struct sockaddr *) &saddr, sizeof(saddr));
169 static int dev_net_set_link_type(struct dev_io *dev, int link_type)
171 if (link_type != LINKTYPE_IEEE802_11 && link_type != LINKTYPE_IEEE802_11_RADIOTAP)
172 return 0;
174 dev->trans = xstrdup(dev->name);
175 xfree(dev->name);
177 enter_rfmon_mac80211(dev->trans, &dev->name);
178 dev->ifindex = __device_ifindex(dev->name);
179 dev->dev_type = device_type(dev->name);
181 return 0;
184 static void dev_net_close(struct dev_io *dev)
186 if (dev->link_type == LINKTYPE_IEEE802_11 || dev->link_type == LINKTYPE_IEEE802_11_RADIOTAP)
187 leave_rfmon_mac80211(dev->name);
189 free(dev->trans);
192 static const struct dev_io_ops dev_net_ops = {
193 .open = dev_net_open,
194 .write = dev_net_write,
195 .set_link_type = dev_net_set_link_type,
196 .close = dev_net_close,
199 struct dev_io *dev_io_open(const char *name, enum dev_io_mode_t mode)
201 struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
203 if (strstr(name, ".pcap")) {
204 dev->name = xstrdup(name);
205 dev->ops = &dev_pcap_ops;
206 } else if (device_mtu(name) > 0) {
207 dev->name = xstrndup(name, IFNAMSIZ);
208 dev->ops = &dev_net_ops;
209 } else {
210 fprintf(stderr, "No networking device or pcap file: %s\n", name);
211 return NULL;
214 if (dev->ops->open) {
215 if (dev->ops->open(dev, name, mode)) {
216 xfree(dev);
217 return NULL;
221 return dev;
224 int dev_io_write(struct dev_io *dev, const uint8_t *buf, size_t len)
226 bug_on(!dev);
227 bug_on(!dev->ops);
229 if (dev->ops->write)
230 return dev->ops->write(dev, buf, len);
232 return 0;
235 int dev_io_read(struct dev_io *dev, uint8_t *buf, size_t len,
236 struct timespec *tstamp)
238 bug_on(!dev);
239 bug_on(!dev->ops);
241 if (dev->ops->read)
242 return dev->ops->read(dev, buf, len, tstamp);
244 return 0;
247 const char *dev_io_name_get(struct dev_io *dev)
249 return dev->name;
252 bool dev_io_is_netdev(struct dev_io *dev)
254 return dev->ops == &dev_net_ops;
257 bool dev_io_is_pcap(struct dev_io *dev)
259 return dev->ops == &dev_pcap_ops;
262 int dev_io_link_type_set(struct dev_io *dev, int link_type)
264 if (dev->ops->set_link_type) {
265 if (dev->ops->set_link_type(dev, link_type))
266 return -1;
269 dev->link_type = link_type;
270 return 0;
273 int dev_io_ifindex_get(struct dev_io *dev)
275 return dev->ifindex;
278 int dev_io_fd_get(struct dev_io *dev)
280 return dev->fd;
283 void dev_io_close(struct dev_io *dev)
285 if (dev) {
286 if (dev->ops->close)
287 dev->ops->close(dev);
289 free(dev->name);
290 free(dev);