Add trafgen_dev.c module which provides generic way of
reading and writing packets to/from networking device or a pcap file.

Also allow to handle output pcap file via '-o, --out, --dev' option.

It might be useful in future for testing some link protocols which is
not easy to capture (e.g. wlan packets) w/o having some special setup.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 trafgen.8        |   5 +-
 trafgen.c        | 102 +++++++++------------
 trafgen/Makefile |   1 +
 trafgen_dev.c    | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 trafgen_dev.h    |  49 +++++++++++
 trafgen_l2.c     |   4 +
 trafgen_l3.c     |   8 +-
 trafgen_proto.c  |  50 ++++++-----
 trafgen_proto.h  |   6 +-
 9 files changed, 396 insertions(+), 92 deletions(-)
 create mode 100644 trafgen_dev.c
 create mode 100644 trafgen_dev.h

diff --git a/trafgen.8 b/trafgen.8
index fd9788a..50deacf 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -74,8 +74,9 @@ It is also possible to specify PCAP file with .pcap extension 
via -i,--in option
 by default packets will be sent at rate considering timestamp from PCAP file 
which
 might be reset via -b/-t options.
 .PP
-.SS -o <dev>, -d <dev>, --out <dev>, --dev <dev>
-Defines the outgoing networking device such as eth0, wlan0 and others.
+.SS -o <dev|pcap>, -d <dev|pcap>, --out <dev|pcap>, --dev <dev|pcap>
+Defines the outgoing networking device such as eth0, wlan0 and others or
+a pcap file.
 .PP
 .SS -p, --cpp
 Pass the packet configuration to the C preprocessor before reading it into
diff --git a/trafgen.c b/trafgen.c
index b25760f..cc54f9e 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -57,6 +57,7 @@
 #include "csum.h"
 #include "trafgen_proto.h"
 #include "pcap_io.h"
+#include "trafgen_dev.h"
 
 enum shaper_type {
        SHAPER_NONE,
@@ -79,6 +80,8 @@ struct shaper {
 struct ctx {
        bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce, 
qdisc_path;
        size_t reserve_size;
+       struct dev_io *dev_out;
+       struct dev_io *dev_in;
        unsigned long num;
        unsigned int cpus;
        uid_t uid; gid_t gid;
@@ -145,7 +148,6 @@ static const char *copyright = "Please report bugs to 
<netsniff-ng@googlegroups.
        "This is free software: you are free to change and redistribute it.\n"
        "There is NO WARRANTY, to the extent permitted by law.";
 
-static int sock;
 static struct cpu_stats *stats;
 static unsigned int seed;
 
@@ -664,11 +666,6 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
        unsigned long num = 1, i = 0;
        struct timeval start, end, diff;
        unsigned long long tx_bytes = 0, tx_packets = 0;
-       struct sockaddr_ll saddr = {
-               .sll_family = PF_PACKET,
-               .sll_halen = ETH_ALEN,
-               .sll_ifindex = device_ifindex(ctx->device),
-       };
 
        if (ctx->num > 0)
                num = ctx->num;
@@ -688,8 +685,7 @@ static void xmit_slowpath_or_die(struct ctx *ctx, unsigned 
int cpu, unsigned lon
        while (likely(sigint == 0 && num > 0 && plen > 0)) {
                packet_apply_dyn_elements(i);
 retry:
-               ret = sendto(sock, packets[i].payload, packets[i].len, 0,
-                            (struct sockaddr *) &saddr, sizeof(saddr));
+               ret = dev_io_write(ctx->dev_out, packets[i].payload, 
packets[i].len);
                if (unlikely(ret < 0)) {
                        if (errno == ENOBUFS) {
                                sched_yield();
@@ -745,15 +741,16 @@ retry:
 
 static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned 
long orig_num)
 {
-       int ifindex = device_ifindex(ctx->device);
+       int ifindex = dev_io_ifindex_get(ctx->dev_out);
        uint8_t *out = NULL;
        unsigned int it = 0;
        unsigned long num = 1, i = 0;
-       size_t size = ring_size(ctx->device, ctx->reserve_size);
+       size_t size = ring_size(dev_io_name_get(ctx->dev_out), 
ctx->reserve_size);
        struct ring tx_ring;
        struct frame_map *hdr;
        struct timeval start, end, diff;
        unsigned long long tx_bytes = 0, tx_packets = 0;
+       int sock = dev_io_fd_get(ctx->dev_out);
 
        set_sock_prio(sock, 512);
 
@@ -938,69 +935,37 @@ static void xmit_packet_precheck(struct ctx *ctx, 
unsigned int cpu)
        }
 }
 
-static void pcap_load_packets(const char *path)
+static void pcap_load_packets(struct dev_io *dev)
 {
-       const struct pcap_file_ops *pcap_io = pcap_ops[PCAP_OPS_SG];
-       uint32_t link_type, magic;
-       pcap_pkthdr_t phdr;
+       struct timespec tstamp;
        size_t buf_len;
        uint8_t *buf;
-       int ret;
-       int fd;
-
-       fd = open(path, O_RDONLY | O_LARGEFILE | O_NOATIME);
-       if (fd < 0 && errno == EPERM)
-               fd = open_or_die(path, O_RDONLY | O_LARGEFILE);
-       if (fd < 0)
-               panic("Cannot open file %s! %s.\n", path, strerror(errno));
-
-       if (pcap_io->init_once_pcap)
-               pcap_io->init_once_pcap(false);
-
-       ret = pcap_io->pull_fhdr_pcap(fd, &magic, &link_type);
-       if (ret)
-               panic("Error reading pcap header!\n");
-
-       if (pcap_io->prepare_access_pcap) {
-               ret = pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, false);
-               if (ret)
-                       panic("Error prepare reading pcap!\n");
-       }
+       int pkt_len;
 
        buf_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
        buf = xmalloc_aligned(buf_len, CO_CACHE_LINE_SIZE);
 
-       while (pcap_io->read_pcap(fd, &phdr, magic, buf, buf_len) > 0) {
+       while ((pkt_len = dev_io_read(dev, buf, buf_len, &tstamp)) > 0) {
                struct packet *pkt;
-               size_t pkt_len;
-
-               pkt_len = pcap_get_length(&phdr, magic);
-               if (!pkt_len)
-                       continue;
 
                realloc_packet();
 
                pkt = current_packet();
-
                pkt->len = pkt_len;
                pkt->payload = xzmalloc(pkt_len);
                memcpy(pkt->payload, buf, pkt_len);
-               pcap_get_tstamp(&phdr, magic, &pkt->tstamp);
+               memcpy(&pkt->tstamp, &tstamp, sizeof(tstamp));
        }
 
-       if (pcap_io->prepare_close_pcap)
-               pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD);
-
        free(buf);
-       close(fd);
 }
 
 static void main_loop(struct ctx *ctx, char *confname, bool slow,
                      unsigned int cpu, bool invoke_cpp, char **cpp_argv,
                      unsigned long orig_num)
 {
-       if (ctx->pcap_in) {
-               pcap_load_packets(ctx->pcap_in);
+       if (ctx->dev_in && dev_io_is_pcap(ctx->dev_in)) {
+               pcap_load_packets(ctx->dev_in);
                shaper_set_tstamp(&ctx->sh, &packets[0].tstamp);
                ctx->num = plen;
        } else {
@@ -1029,18 +994,14 @@ static void main_loop(struct ctx *ctx, char *confname, 
bool slow,
                fflush(stdout);
        }
 
-       sock = pf_socket();
-
-       if (ctx->qdisc_path == false)
-               set_sock_qdisc_bypass(sock, ctx->verbose);
+       if (dev_io_is_netdev(ctx->dev_out) && ctx->qdisc_path == false)
+               set_sock_qdisc_bypass(dev_io_fd_get(ctx->dev_out), 
ctx->verbose);
 
        if (slow)
                xmit_slowpath_or_die(ctx, cpu, orig_num);
        else
                xmit_fastpath_or_die(ctx, cpu, orig_num);
 
-       close(sock);
-
        cleanup_packets();
 }
 
@@ -1306,16 +1267,12 @@ int main(int argc, char **argv)
                panic("No networking device given!\n");
        if (confname == NULL && !ctx.packet_str)
                panic("No configuration file or packet string given!\n");
-       if (device_mtu(ctx.device) == 0)
-               panic("This is no networking device!\n");
 
        register_signal(SIGINT, signal_handler);
        register_signal(SIGQUIT, signal_handler);
        register_signal(SIGTERM, signal_handler);
        register_signal(SIGHUP, signal_handler);
 
-       protos_init(ctx.device);
-
        if (prio_high) {
                set_proc_prio(-20);
                set_sched_status(SCHED_FIFO, 
sched_get_priority_max(SCHED_FIFO));
@@ -1334,7 +1291,21 @@ int main(int argc, char **argv)
                sleep(0);
        }
 
-       if (shaper_is_set(&ctx.sh) || (ctx.pcap_in)) {
+       if (ctx.pcap_in) {
+               ctx.dev_in = dev_io_open(ctx.pcap_in, DEV_IO_IN);
+               if (!ctx.dev_in)
+                       panic("Failed open input device\n");
+       }
+
+       ctx.dev_out = dev_io_open(ctx.device, DEV_IO_OUT);
+       if (!ctx.dev_out)
+               panic("Failed open output device\n");
+
+       protos_init(ctx.dev_out);
+
+       if (shaper_is_set(&ctx.sh) || (ctx.dev_in && dev_io_is_pcap(ctx.dev_in))
+                       || dev_io_is_pcap(ctx.dev_out)) {
+
                prctl(PR_SET_TIMERSLACK, 1UL);
                /* Fall back to single core to not mess up correct timing.
                 * We are slow anyway!
@@ -1351,9 +1322,10 @@ int main(int argc, char **argv)
        if (ctx.num)
                ctx.cpus = min_t(unsigned int, ctx.num, ctx.cpus);
 
-       irq = device_irq_number(ctx.device);
-       if (set_irq_aff)
+       if (set_irq_aff && dev_io_is_netdev(ctx.dev_out)) {
+               irq = device_irq_number(ctx.device);
                device_set_irq_affinity_list(irq, 0, ctx.cpus - 1);
+       }
 
        stats = setup_shared_var(ctx.cpus);
 
@@ -1411,9 +1383,13 @@ int main(int argc, char **argv)
 thread_out:
        xunlockme();
        destroy_shared_var(stats, ctx.cpus);
-       if (set_irq_aff)
+       if (dev_io_is_netdev(ctx.dev_out) && set_irq_aff)
                device_restore_irq_affinity_list();
 
+       dev_io_close(ctx.dev_out);
+       if (ctx.dev_in)
+               dev_io_close(ctx.dev_in);
+
        argv_free(cpp_argv);
        free(ctx.device);
        free(ctx.device_trans);
diff --git a/trafgen/Makefile b/trafgen/Makefile
index d38f0b0..381f94d 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -25,6 +25,7 @@ trafgen-objs =        xmalloc.o \
                pcap_rw.o \
                pcap_mm.o \
                iosched.o \
+               trafgen_dev.o \
                trafgen_proto.o \
                trafgen_l2.o \
                trafgen_l3.o \
diff --git a/trafgen_dev.c b/trafgen_dev.c
new file mode 100644
index 0000000..de6a225
--- /dev/null
+++ b/trafgen_dev.c
@@ -0,0 +1,263 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Copyright 2011 - 2013 Daniel Borkmann <dbor...@tik.ee.ethz.ch>,
+ * Swiss federal institute of technology (ETH Zurich)
+ * Subject to the GPL, version 2.
+ */
+
+#define _GNU_SOURCE
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <net/ethernet.h>
+
+#include "sock.h"
+#include "xmalloc.h"
+#include "pcap_io.h"
+#include "built_in.h"
+#include "trafgen_dev.h"
+
+static int dev_pcap_open(struct dev_io *dev, const char *name, enum 
dev_io_mode_t mode)
+{
+       dev->pcap_magic = ORIGINAL_TCPDUMP_MAGIC;
+       dev->pcap_ops = pcap_ops[PCAP_OPS_SG];
+
+       if (mode == DEV_IO_IN) {
+               if (!strncmp("-", name, strlen("-"))) {
+                       dev->fd = dup_or_die(fileno(stdin));
+                       close(fileno(stdin));
+               } else {
+                       dev->fd = open(name, O_RDONLY | O_LARGEFILE | 
O_NOATIME);
+                       if (dev->fd < 0 && errno == EPERM)
+                               dev->fd = open_or_die(name, O_RDONLY | 
O_LARGEFILE);
+               }
+
+               dev->pcap_mode = PCAP_MODE_RD;
+       } else if (mode & DEV_IO_OUT) {
+               if (!strncmp("-", name, strlen("-"))) {
+                       dev->fd = dup_or_die(fileno(stdout));
+                       close(fileno(stdout));
+               } else {
+                       dev->fd = open_or_die_m(name, O_RDWR | O_CREAT | 
O_TRUNC |
+                                               O_LARGEFILE, DEFFILEMODE);
+               }
+
+               dev->pcap_mode = PCAP_MODE_WR;
+       } else {
+               bug();
+       }
+
+       if (dev->fd < 0)
+               panic("pcap_dev: Cannot open file %s! %s.\n", name, 
strerror(errno));
+
+       if (dev->pcap_ops->init_once_pcap)
+               dev->pcap_ops->init_once_pcap(false);
+
+       if (mode == DEV_IO_IN) {
+               if (dev->pcap_ops->pull_fhdr_pcap(dev->fd, &dev->pcap_magic, 
&dev->link_type))
+                       panic("Error reading pcap header!\n");
+       }
+
+       if (dev->pcap_ops->prepare_access_pcap) {
+               if (dev->pcap_ops->prepare_access_pcap(dev->fd, dev->pcap_mode, 
false))
+                       panic("Error prepare reading pcap!\n");
+       }
+
+       return 0;
+}
+
+static int dev_pcap_read(struct dev_io *dev, uint8_t *buf, size_t len,
+                        struct timespec *tstamp)
+{
+       pcap_pkthdr_t phdr;
+       size_t pkt_len;
+
+       if (dev->pcap_ops->read_pcap(dev->fd, &phdr, dev->pcap_magic, buf, len) 
<= 0)
+               return -1;
+
+       pkt_len = pcap_get_length(&phdr, dev->pcap_magic);
+       if (!pkt_len)
+               return -1;
+
+       pcap_get_tstamp(&phdr, dev->pcap_magic, tstamp);
+
+       return pkt_len;
+}
+
+static int dev_pcap_write(struct dev_io *dev, const uint8_t *buf, size_t len)
+{
+       struct timeval time;
+       pcap_pkthdr_t phdr;
+       int ret;
+
+       /* Write PCAP file header only once */
+       if (!dev->is_initialized) {
+               if (dev->pcap_ops->push_fhdr_pcap(dev->fd, dev->pcap_magic, 
dev->link_type)) {
+                       fprintf(stderr, "Error writing pcap header!\n");
+                       return -1;
+               }
+
+               if (dev->pcap_ops->prepare_access_pcap) {
+                       if (dev->pcap_ops->prepare_access_pcap(dev->fd, 
PCAP_MODE_WR, true)) {
+                               fprintf(stderr, "Error prepare writing 
pcap!\n");
+                               return -1;
+                       }
+               }
+
+               dev->is_initialized = true;
+       }
+
+       bug_on(gettimeofday(&time, NULL));
+
+       phdr.ppo.ts.tv_sec = time.tv_sec;
+       phdr.ppo.ts.tv_usec = time.tv_usec;
+       phdr.ppo.caplen = len;
+       phdr.ppo.len = len;
+
+       ret = dev->pcap_ops->write_pcap(dev->fd, &phdr, dev->pcap_magic,
+                                       buf, pcap_get_length(&phdr, 
dev->pcap_magic));
+
+       if (unlikely(ret != (int) pcap_get_total_length(&phdr, 
dev->pcap_magic))) {
+               fprintf(stderr, "Write error to pcap!\n");
+               return -1;
+       }
+
+       return ret;
+}
+
+static void dev_pcap_close(struct dev_io *dev)
+{
+       if (dev->pcap_mode == PCAP_MODE_WR)
+               dev->pcap_ops->fsync_pcap(dev->fd);
+
+       if (dev->pcap_ops->prepare_close_pcap)
+               dev->pcap_ops->prepare_close_pcap(dev->fd, dev->pcap_mode);
+
+       close(dev->fd);
+}
+
+static const struct dev_io_ops dev_pcap_ops = {
+       .open = dev_pcap_open,
+       .read = dev_pcap_read,
+       .write = dev_pcap_write,
+       .close = dev_pcap_close,
+};
+
+static int dev_net_open(struct dev_io *dev, const char *name, enum 
dev_io_mode_t mode)
+{
+       dev->ifindex = __device_ifindex(name);
+       dev->dev_type = device_type(name);
+       dev->fd = pf_socket();
+
+       return 0;
+}
+
+static int dev_net_write(struct dev_io *dev, const uint8_t *buf, size_t len)
+{
+       struct sockaddr_ll saddr = {
+               .sll_family = PF_PACKET,
+               .sll_halen = ETH_ALEN,
+               .sll_ifindex = dev->ifindex,
+       };
+
+       return sendto(dev->fd, buf, len, 0, (struct sockaddr *) &saddr, 
sizeof(saddr));
+}
+
+static void dev_net_close(struct dev_io *dev)
+{
+}
+
+static const struct dev_io_ops dev_net_ops = {
+       .open = dev_net_open,
+       .write = dev_net_write,
+       .close = dev_net_close,
+};
+
+struct dev_io *dev_io_open(const char *name, enum dev_io_mode_t mode)
+{
+       struct dev_io *dev = xzmalloc(sizeof(struct dev_io));
+
+       if (strstr(name, ".pcap")) {
+               dev->ops = &dev_pcap_ops;
+       } else if (device_mtu(name) > 0) {
+               dev->ops = &dev_net_ops;
+       } else {
+               fprintf(stderr, "No networking device or pcap file: %s\n", 
name);
+               return NULL;
+       }
+
+       if (dev->ops->open) {
+               if (dev->ops->open(dev, name, mode)) {
+                       xfree(dev);
+                       return NULL;
+               }
+       }
+
+       dev->name = xstrdup(name);
+       return dev;
+};
+
+int dev_io_write(struct dev_io *dev, const uint8_t *buf, size_t len)
+{
+       bug_on(!dev);
+       bug_on(!dev->ops);
+
+       if (dev->ops->write)
+               return dev->ops->write(dev, buf, len);
+
+       return 0;
+}
+
+int dev_io_read(struct dev_io *dev, uint8_t *buf, size_t len,
+               struct timespec *tstamp)
+{
+       bug_on(!dev);
+       bug_on(!dev->ops);
+
+       if (dev->ops->read)
+               return dev->ops->read(dev, buf, len, tstamp);
+
+       return 0;
+}
+
+const char *dev_io_name_get(struct dev_io *dev)
+{
+       return dev->name;
+}
+
+bool dev_io_is_netdev(struct dev_io *dev)
+{
+       return dev->ops == &dev_net_ops;
+}
+
+bool dev_io_is_pcap(struct dev_io *dev)
+{
+       return dev->ops == &dev_pcap_ops;
+}
+
+void dev_io_link_type_set(struct dev_io *dev, int link_type)
+{
+       dev->link_type = link_type;
+}
+
+int dev_io_ifindex_get(struct dev_io *dev)
+{
+       return dev->ifindex;
+}
+
+int dev_io_fd_get(struct dev_io *dev)
+{
+       return dev->fd;
+}
+
+void dev_io_close(struct dev_io *dev)
+{
+       if (dev) {
+               if (dev->ops->close)
+                       dev->ops->close(dev);
+
+               free(dev->name);
+               free(dev);
+       }
+}
diff --git a/trafgen_dev.h b/trafgen_dev.h
new file mode 100644
index 0000000..4fc1a4d
--- /dev/null
+++ b/trafgen_dev.h
@@ -0,0 +1,49 @@
+#ifndef TRAFGEN_DEV_H
+#define TRAFGEN_DEV_H
+
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "pcap_io.h"
+
+enum dev_io_mode_t {
+       DEV_IO_IN       = 1 << 0,
+       DEV_IO_OUT      = 1 << 1,
+};
+
+struct dev_io_ops;
+
+struct dev_io {
+       int fd;
+       char *name;
+       int ifindex;
+       int dev_type;
+       uint32_t link_type;
+               uint32_t pcap_magic;
+       bool is_initialized;
+       enum pcap_mode pcap_mode;
+
+       const struct pcap_file_ops *pcap_ops;
+       const struct dev_io_ops *ops;
+};
+
+struct dev_io_ops {
+       int (* open) (struct dev_io *dev, const char *name, enum dev_io_mode_t 
mode);
+       int (* write) (struct dev_io *dev, const uint8_t *buf, size_t len);
+       int (* read) (struct dev_io *dev, uint8_t *buf, size_t len, struct 
timespec *tstamp);
+       void (* close) (struct dev_io *dev);
+};
+
+extern struct dev_io *dev_io_open(const char *name, enum dev_io_mode_t mode);
+extern int dev_io_write(struct dev_io *dev, const uint8_t *buf, size_t len);
+extern int dev_io_read(struct dev_io *dev, uint8_t *buf, size_t len,
+                      struct timespec *tstamp);
+extern int dev_io_ifindex_get(struct dev_io *dev);
+extern int dev_io_fd_get(struct dev_io *dev);
+extern const char *dev_io_name_get(struct dev_io *dev);
+extern void dev_io_link_type_set(struct dev_io *dev, int link_type);
+extern bool dev_io_is_netdev(struct dev_io *dev);
+extern bool dev_io_is_pcap(struct dev_io *dev);
+extern void dev_io_close(struct dev_io *dev);
+
+#endif /* TRAFGEN_DEV_H */
diff --git a/trafgen_l2.c b/trafgen_l2.c
index 427ff9b..4858c5f 100644
--- a/trafgen_l2.c
+++ b/trafgen_l2.c
@@ -8,7 +8,9 @@
 
 #include "die.h"
 #include "built_in.h"
+#include "linktype.h"
 #include "trafgen_l2.h"
+#include "trafgen_dev.h"
 #include "trafgen_proto.h"
 
 static struct proto_field eth_fields[] = {
@@ -48,6 +50,8 @@ static void eth_header_init(struct proto_hdr *hdr)
        proto_header_fields_add(hdr, eth_fields, array_size(eth_fields));
 
        proto_hdr_field_set_default_dev_mac(hdr, ETH_SRC_ADDR);
+
+       dev_io_link_type_set(proto_dev_get(), LINKTYPE_EN10MB);
 }
 
 static const struct proto_ops eth_proto_ops = {
diff --git a/trafgen_l3.c b/trafgen_l3.c
index 7c8a786..7199b89 100644
--- a/trafgen_l3.c
+++ b/trafgen_l3.c
@@ -35,10 +35,10 @@ static struct proto_field ipv4_fields[] = {
 
 static void ipv4_header_init(struct proto_hdr *hdr)
 {
-       const char *dev = proto_dev_get();
+       struct dev_io *dev = proto_dev_get();
 
        /* In case of tun interface we do not need to create Ethernet header */
-       if (dev && device_mtu(dev) && device_type(dev) != ARPHRD_NONE)
+       if (dev_io_is_pcap(dev) || device_type(dev_io_name_get(dev)) != 
ARPHRD_NONE)
                proto_lower_default_add(hdr, PROTO_ETH);
 
        proto_header_fields_add(hdr, ipv4_fields, array_size(ipv4_fields));
@@ -140,10 +140,10 @@ static struct proto_field ipv6_fields[] = {
 
 static void ipv6_header_init(struct proto_hdr *hdr)
 {
-       const char *dev = proto_dev_get();
+       struct dev_io *dev = proto_dev_get();
 
        /* In case of tun interface we do not need to create Ethernet header */
-       if (dev && device_mtu(dev) && device_type(dev) != ARPHRD_NONE)
+       if (dev_io_is_netdev(dev) && device_type(dev_io_name_get(dev)) != 
ARPHRD_NONE)
                proto_lower_default_add(hdr, PROTO_ETH);
 
        proto_header_fields_add(hdr, ipv6_fields, array_size(ipv6_fields));
diff --git a/trafgen_proto.c b/trafgen_proto.c
index 0353d6b..c2cbffb 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -24,7 +24,7 @@
                ((f)->mask ? (f)->mask : (0xffffffff))) >> (f)->shift)
 
 struct ctx {
-       const char *dev;
+       struct dev_io *dev;
 };
 static struct ctx ctx;
 
@@ -508,11 +508,13 @@ static void __proto_hdr_field_set_dev_mac(struct 
proto_hdr *hdr, uint32_t fid,
        if (proto_hdr_field_is_set(hdr, fid))
                return;
 
-       ret = device_hw_address(ctx.dev, mac, sizeof(mac));
-       if (ret < 0)
-               panic("Could not get device hw address\n");
+       if (dev_io_is_netdev(ctx.dev)) {
+               ret = device_hw_address(dev_io_name_get(ctx.dev), mac, 
sizeof(mac));
+               if (ret < 0)
+                       panic("Could not get device hw address\n");
 
-       __proto_field_set_bytes(field, mac, 6, is_default, false);
+               __proto_field_set_bytes(field, mac, 6, is_default, false);
+       }
 }
 
 void proto_hdr_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
@@ -536,14 +538,17 @@ static void __proto_hdr_field_set_dev_ipv4(struct 
proto_hdr *hdr, uint32_t fid,
        if (proto_hdr_field_is_set(hdr, fid))
                return;
 
-       ret = device_address(ctx.dev, AF_INET, &ss);
-       if (ret < 0) {
-               fprintf(stderr, "Warning: Could not get device IPv4 address for 
%s\n", ctx.dev);
-               return;
-       }
+       if (dev_io_is_netdev(ctx.dev)) {
+               ret = device_address(dev_io_name_get(ctx.dev), AF_INET, &ss);
+               if (ret < 0) {
+                       fprintf(stderr, "Warning: Could not get device IPv4 
address for %s\n",
+                               dev_io_name_get(ctx.dev));
+                       return;
+               }
 
-       ss4 = (struct sockaddr_in *) &ss;
-       __proto_field_set_bytes(field, (uint8_t *)&ss4->sin_addr.s_addr, 4, 
is_default, false);
+               ss4 = (struct sockaddr_in *) &ss;
+               __proto_field_set_bytes(field, (uint8_t 
*)&ss4->sin_addr.s_addr, 4, is_default, false);
+       }
 }
 
 void proto_hdr_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
@@ -567,14 +572,17 @@ static void __proto_hdr_field_set_dev_ipv6(struct 
proto_hdr *hdr, uint32_t fid,
        if (proto_hdr_field_is_set(hdr, fid))
                return;
 
-       ret = device_address(ctx.dev, AF_INET6, &ss);
-       if (ret < 0) {
-               fprintf(stderr, "Warning: Could not get device IPv6 address for 
%s\n", ctx.dev);
-               return;
-       }
+       if (dev_io_is_netdev(ctx.dev)) {
+               ret = device_address(dev_io_name_get(ctx.dev), AF_INET6, &ss);
+               if (ret < 0) {
+                       fprintf(stderr, "Warning: Could not get device IPv6 
address for %s\n",
+                               dev_io_name_get(ctx.dev));
+                       return;
+               }
 
-       ss6 = (struct sockaddr_in6 *) &ss;
-       __proto_field_set_bytes(field, (uint8_t *)&ss6->sin6_addr.s6_addr, 16, 
is_default, false);
+               ss6 = (struct sockaddr_in6 *) &ss;
+               __proto_field_set_bytes(field, (uint8_t 
*)&ss6->sin6_addr.s6_addr, 16, is_default, false);
+       }
 }
 
 void proto_hdr_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
@@ -658,7 +666,7 @@ void proto_field_set_default_string(struct proto_field 
*field, const char *str)
        __proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1, true, 
false);
 }
 
-void protos_init(const char *dev)
+void protos_init(struct dev_io *dev)
 {
        ctx.dev = dev;
 
@@ -792,7 +800,7 @@ void proto_field_dyn_apply(struct proto_field *field)
                field->hdr->ops->field_changed(field);
 }
 
-const char *proto_dev_get(void)
+struct dev_io *proto_dev_get(void)
 {
        return ctx.dev;
 }
diff --git a/trafgen_proto.h b/trafgen_proto.h
index f3d07ba..d3da963 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -5,6 +5,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#include "trafgen_dev.h"
+
 enum proto_id {
        PROTO_NONE = 0,
        PROTO_ETH,
@@ -94,7 +96,7 @@ struct proto_field {
        struct proto_hdr *hdr;
 };
 
-extern void protos_init(const char *dev);
+extern void protos_init(struct dev_io *dev);
 extern void proto_ops_register(const struct proto_ops *ops);
 
 extern struct proto_hdr *proto_header_push(enum proto_id pid);
@@ -176,6 +178,6 @@ extern void proto_field_set_default_string(struct 
proto_field *field, const char
 extern void proto_field_func_add(struct proto_field *field,
                                 struct proto_field_func *func);
 
-extern const char *proto_dev_get(void);
+extern struct dev_io *proto_dev_get(void);
 
 #endif /* TRAFGEN_PROTO_H */
-- 
2.12.1

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to