Add Ethernet packet generation via command line:
trafgen --dev eth0 eth sa=af:cd:4b:c3:56:6a da=af:cd:4b:c3:56:6a
proto=0x0800
Added separated layer2_gen.c module which will contain L2 related proto
generators.
By default source MAC address is used from specified device, and
destination MAC address is broadcast FF:FF:FF:FF:FF:FF.
Signed-off-by: Vadim Kochan <[email protected]>
---
layer2_gen.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
proto_gen.c | 3 ++
trafgen/Makefile | 2 +
3 files changed, 150 insertions(+)
create mode 100644 layer2_gen.c
diff --git a/layer2_gen.c b/layer2_gen.c
new file mode 100644
index 0000000..a338dbd
--- /dev/null
+++ b/layer2_gen.c
@@ -0,0 +1,145 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include <net/if_arp.h>
+#include <linux/if_ether.h>
+
+#include "dev.h"
+#include "xmalloc.h"
+#include "net_utils.h"
+#include "proto_gen.h"
+
+#define ETH_BCAST_ADDR { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+
+enum eth_field {
+ ETH_DST_ADDR,
+ ETH_SRC_ADDR,
+ ETH_PROTO_ID,
+};
+
+static void eth_set_proto_field(struct proto_gen *prot, int proto_id)
+{
+ if (!proto_field_exist(prot, ETH_PROTO_ID))
+ proto_field_add(prot, ETH_PROTO_ID, 2);
+
+ proto_field_set_value(prot, ETH_PROTO_ID, proto_id);
+}
+
+static int eth_parse_param(struct proto_gen *prot, char *name, char *val)
+{
+ uint8_t addr[6] = {};
+
+ if (!strcasecmp("dst", name) || !strcasecmp("da", name)) {
+ int ret = str2mac(val, &addr[0]);
+ proto_field_set_bytes(prot, ETH_DST_ADDR, &addr[0]);
+
+ return ret == 0 ? ETH_DST_ADDR : -1;
+ }
+
+ if (!strcasecmp("src", name) || !strcasecmp("sa", name)) {
+ int ret = str2mac(val, &addr[0]);
+ proto_field_set_bytes(prot, ETH_SRC_ADDR, &addr[0]);
+
+ return ret == 0 ? ETH_SRC_ADDR : -1;
+ }
+
+ if (!strcasecmp("type", name) || !strcasecmp("proto", name)) {
+ char *ptr = NULL;
+ int proto_id = htons(strtol(val, &ptr, 0));
+
+ if (errno == ERANGE || errno == EINVAL || ptr == val)
+ return -1;
+
+ eth_set_proto_field(prot, proto_id);
+ return ETH_PROTO_ID;
+ }
+
+ return -1;
+}
+
+static void eth_set_next_proto(struct proto_gen *prot, struct proto_gen *next)
+{
+ int proto_id = 0;
+
+ switch (next->id) {
+ case NET_PROTO_ARP:
+ proto_id = ETH_P_ARP;
+ break;
+ case NET_PROTO_IPV4:
+ proto_id = ETH_P_IP;
+ break;
+ case NET_PROTO_IPV6:
+ proto_id = ETH_P_IPV6;
+ break;
+ case NET_PROTO_NONE:
+ case NET_PROTO_ETH:
+ case NET_PROTO_UDP:
+ case NET_PROTO_TCP:
+ break;
+ }
+
+ eth_set_proto_field(prot, htons(proto_id));
+}
+
+static void eth_print_help(struct proto_gen *prot)
+{
+#define ETH_PROT_HELP \
+ "| eth proto: Sends Ethernet packets.\n" \
+ "| Parameters:\n" \
+ "|\n" \
+ "| src,sa = XX:XX:XX:XX:XX:XX ..... Source MAC
address\n" \
+ "| dst,da = XX:XX:XX:XX:XX:XX ..... Destination MAC
address\n" \
+ "| proto,type = decimal | 0xXXX ..... Sets
proto/type/len value\n" \
+ "| data,payload = hexadecimal ..... Binary payload
data\n" \
+ "| text = ascii string ..... Textual payload
data\n" \
+ "|\n" \
+ "| EXAMPLES:\n" \
+ "| trafgen --dev eth0 eth sa=af:cd:4b:c3:56:6a
da=af:cd:4b:c3:56:6a proto=0x0800\n" \
+ "|\n" \
+ "\n"
+
+ printf(ETH_PROT_HELP);
+}
+
+static void eth_check_fields(struct proto_gen *prot)
+{
+ if (!proto_field_is_set(prot, ETH_DST_ADDR)) {
+ uint8_t bcast[6] = ETH_BCAST_ADDR;
+
+ proto_field_set_bytes(prot, ETH_DST_ADDR, &bcast[0]);
+ }
+
+ if (!proto_field_is_set(prot, ETH_SRC_ADDR)) {
+ uint8_t addr[6] = {0};
+
+ if (!device_hw_address(prot->ctx->device, &addr[0]))
+ proto_field_set_bytes(prot, ETH_SRC_ADDR, &addr[0]);
+ }
+}
+
+static void eth_proto_init(struct proto_gen *prot)
+{
+ proto_field_add(prot, ETH_DST_ADDR, 6);
+ proto_field_add(prot, ETH_SRC_ADDR, 6);
+
+ /* Do not add proto field here as it can be set
+ * from specified payload or after vlan headers */
+}
+
+static struct proto_gen eth_gen = {
+ .id = NET_PROTO_ETH,
+ .name = "eth",
+ .min_size = 15,
+ .proto_init = eth_proto_init,
+ .parse_param = eth_parse_param,
+ .set_next_proto = eth_set_next_proto,
+ .print_help = eth_print_help,
+ .check_fields = eth_check_fields,
+};
+
+void layer2_gen_register(void)
+{
+ proto_gen_register(ð_gen);
+}
diff --git a/proto_gen.c b/proto_gen.c
index eee6227..1abebab 100644
--- a/proto_gen.c
+++ b/proto_gen.c
@@ -11,6 +11,8 @@
static struct proto_gen *protos;
+extern void layer2_gen_register(void);
+
struct proto_gen *proto_gen_by_name(char *name)
{
struct proto_gen *p = protos;
@@ -41,6 +43,7 @@ void proto_gen_register(struct proto_gen *prot)
void proto_gen_init(void)
{
+ layer2_gen_register();
}
void proto_gen_uninit(void)
diff --git a/trafgen/Makefile b/trafgen/Makefile
index c935c0b..723cd8d 100644
--- a/trafgen/Makefile
+++ b/trafgen/Makefile
@@ -18,6 +18,8 @@ trafgen-objs = xmalloc.o \
ring.o \
timer.o \
proto_gen.o \
+ net_utils.o \
+ layer2_gen.o \
trafgen_lexer.yy.o \
trafgen_parser.tab.o \
trafgen.o
--
2.4.2
--
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 [email protected].
For more options, visit https://groups.google.com/d/optout.