summaryrefslogtreecommitdiff
path: root/trafgen_dump.c
diff options
context:
space:
mode:
authorVadim Kochan <vadim4j@gmail.com>2017-07-29 12:46:09 +0300
committerTobias Klauser <tklauser@distanz.ch>2017-08-10 09:03:46 +0200
commit439af62bca4794d78d53fb4634f560d6a75f0adb (patch)
tree346cc168c42bbe1d7f0eb6bd493d244016172a01 /trafgen_dump.c
parent19348cec323373d84674c1d2cf34315cbf47c80d (diff)
trafgen: Dump proto headers in *.cfg format
Added trafgen_dump.c module which dumps headers from packet in .cfg format. Packet is dumped if -o <file>.cfg was specified, it might be useful to specify *.pcap file as input and convert it into .cfg file to edit proto fields in human readable format. To make it possible several main changes were added: 1) packet id is embedded into struct packet.id, and it is updated on each realloc_packet() 2) Added new struct proto_hdr.get_next_proto callback to make possible apply fields of next header. 3) Added new dev_io ops for writting packets into .cfg file, to re-use common dev_io mechsnism for packets dumping. Before dump the default ETH_PROTO fields are applied as first header and then next proto_hdr is identified via .get_next_proto(...) callback. Meanwhile only eth, arp, vlan, ip4, udp, & tcp protos can be dissected into *.cfg format. Signed-off-by: Vadim Kochan <vadim4j@gmail.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'trafgen_dump.c')
-rw-r--r--trafgen_dump.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/trafgen_dump.c b/trafgen_dump.c
new file mode 100644
index 0000000..ff68e8b
--- /dev/null
+++ b/trafgen_dump.c
@@ -0,0 +1,258 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Subject to the GPL, version 2.
+ */
+
+#include <stdio.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/ethernet.h>
+
+#include "trafgen_l2.h"
+#include "trafgen_l3.h"
+#include "trafgen_l4.h"
+#include "trafgen_proto.h"
+#include "trafgen_dump.h"
+
+#define DUMP(fmt, ...) fprintf((ctx)->file, fmt, ##__VA_ARGS__)
+
+#define PKT_START() DUMP("{\n")
+#define PKT_END() DUMP("}\n")
+
+#define HDR_START(h) DUMP(" %s(", h)
+#define HDR_END(h) DUMP(" ),\n")
+
+#define FIELD_START(fmt, ...) DUMP(fmt",\n", ##__VA_ARGS__)
+#define FIELD_END(fmt, ...) DUMP(" "fmt"\n", ##__VA_ARGS__)
+#define FIELD(fmt, ...) DUMP(" "fmt",\n", ##__VA_ARGS__)
+
+struct dump_ctx {
+ FILE *file;
+};
+
+static int proto_dump_eth(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ uint8_t *mac;
+
+ HDR_START("eth");
+
+ mac = proto_hdr_field_get_bytes(hdr, ETH_DST_ADDR);
+ FIELD_START("da=%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ mac = proto_hdr_field_get_bytes(hdr, ETH_SRC_ADDR);
+ FIELD("sa=%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ FIELD_END("type=0x%x", proto_hdr_field_get_u16(hdr, ETH_TYPE));
+
+ HDR_END();
+ return 0;
+}
+
+static int proto_dump_vlan(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ HDR_START("vlan");
+
+ FIELD_START("id=%d", proto_hdr_field_get_u16(hdr, VLAN_VID));
+ FIELD("pcp=%d", proto_hdr_field_get_u16(hdr, VLAN_PCP));
+ FIELD("dei=%d", proto_hdr_field_get_u16(hdr, VLAN_DEI));
+ FIELD_END("tpid=0x%x", proto_hdr_field_get_u16(hdr, VLAN_TPID));
+
+ HDR_END();
+ return 0;
+}
+
+static int proto_dump_arp(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ char ip_str[INET_ADDRSTRLEN];
+ uint16_t oper;
+ uint8_t *mac;
+ uint32_t ip;
+
+ HDR_START("arp");
+
+ mac = proto_hdr_field_get_bytes(hdr, ARP_SHA);
+ FIELD_START("smac=%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ ip = proto_hdr_field_get_be32(hdr, ARP_SPA);
+ inet_ntop(AF_INET, &ip, ip_str, sizeof(ip_str));
+ FIELD("sip=%s", ip_str);
+
+ mac = proto_hdr_field_get_bytes(hdr, ARP_THA);
+ FIELD("tmac=%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ ip = proto_hdr_field_get_be32(hdr, ARP_TPA);
+ inet_ntop(AF_INET, &ip, ip_str, sizeof(ip_str));
+ FIELD("tip=%s", ip_str);
+
+ oper = proto_hdr_field_get_u16(hdr, ARP_OPER);
+
+ if (oper == ARPOP_REQUEST)
+ FIELD_END("op=request");
+ else if (oper == ARPOP_REPLY)
+ FIELD_END("op=reply");
+ else
+ FIELD_END("op=0x%x", oper);
+
+ HDR_END();
+ return 0;
+}
+
+static int proto_dump_ip4(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ char ip_sa_str[INET_ADDRSTRLEN];
+ char ip_da_str[INET_ADDRSTRLEN];
+ uint32_t ip;
+
+ ip = proto_hdr_field_get_be32(hdr, IP4_SADDR);
+ inet_ntop(AF_INET, &ip, ip_sa_str, sizeof(ip_sa_str));
+
+ ip = proto_hdr_field_get_be32(hdr, IP4_DADDR);
+ inet_ntop(AF_INET, &ip, ip_da_str, sizeof(ip_da_str));
+
+ HDR_START("ip4");
+
+ FIELD_START("ver=0x%x", proto_hdr_field_get_u8(hdr, IP4_VER));
+ FIELD("ihl=0x%x", proto_hdr_field_get_u8(hdr, IP4_IHL));
+ FIELD("dscp=0x%x", proto_hdr_field_get_u8(hdr, IP4_DSCP));
+ FIELD("ecn=0x%x", proto_hdr_field_get_u8(hdr, IP4_ECN));
+ FIELD("tos=0x%x", proto_hdr_field_get_u8(hdr, IP4_TOS));
+ FIELD("len=%d", proto_hdr_field_get_u16(hdr, IP4_LEN));
+ FIELD("id=0x%x", proto_hdr_field_get_u16(hdr, IP4_ID));
+ FIELD("flags=0x%x", proto_hdr_field_get_u16(hdr, IP4_FLAGS));
+ if (proto_hdr_field_get_u16(hdr, IP4_MF))
+ FIELD("mf");
+ if (proto_hdr_field_get_u16(hdr, IP4_DF))
+ FIELD("df");
+ FIELD("frag=0x%x", proto_hdr_field_get_u16(hdr, IP4_FRAG_OFFS));
+ FIELD("ttl=%d", proto_hdr_field_get_u8(hdr, IP4_TTL));
+ FIELD("proto=0x%x", proto_hdr_field_get_u8(hdr, IP4_PROTO));
+ FIELD("csum=0x%x", proto_hdr_field_get_u16(hdr, IP4_CSUM));
+ FIELD("sa=%s", ip_sa_str);
+ FIELD_END("da=%s", ip_da_str);
+
+ HDR_END();
+ return 0;
+}
+
+static int proto_dump_udp(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ HDR_START("udp");
+
+ FIELD_START("dp=%d", proto_hdr_field_get_u16(hdr, UDP_SPORT));
+ FIELD("sp=%d", proto_hdr_field_get_u16(hdr, UDP_DPORT));
+ FIELD("len=%d", proto_hdr_field_get_u16(hdr, UDP_LEN));
+ FIELD_END("csum=0x%x", proto_hdr_field_get_u16(hdr, UDP_CSUM));
+
+ HDR_END();
+ return 0;
+}
+
+static int proto_dump_tcp(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ HDR_START("tcp");
+
+ FIELD_START("dp=%d", proto_hdr_field_get_u16(hdr, TCP_SPORT));
+ FIELD("sp=%d", proto_hdr_field_get_u16(hdr, TCP_DPORT));
+ FIELD("seq=0x%x", proto_hdr_field_get_u32(hdr, TCP_SEQ));
+ FIELD("ackseq=0x%x", proto_hdr_field_get_u32(hdr, TCP_ACK_SEQ));
+ FIELD("hlen=%d", proto_hdr_field_get_u16(hdr, TCP_DOFF));
+ if (proto_hdr_field_get_u16(hdr, TCP_CWR))
+ FIELD("cwr");
+ if (proto_hdr_field_get_u16(hdr, TCP_ECE))
+ FIELD("ecn");
+ if (proto_hdr_field_get_u16(hdr, TCP_URG))
+ FIELD("urg");
+ if (proto_hdr_field_get_u16(hdr, TCP_ACK))
+ FIELD("ack");
+ if (proto_hdr_field_get_u16(hdr, TCP_PSH))
+ FIELD("psh");
+ if (proto_hdr_field_get_u16(hdr, TCP_RST))
+ FIELD("rst");
+ if (proto_hdr_field_get_u16(hdr, TCP_SYN))
+ FIELD("syn");
+ if (proto_hdr_field_get_u16(hdr, TCP_FIN))
+ FIELD("fin");
+ FIELD("win=%d", proto_hdr_field_get_u16(hdr, TCP_WINDOW));
+ FIELD("csum=0x%x", proto_hdr_field_get_u16(hdr, TCP_CSUM));
+ FIELD_END("urgptr=0x%x", proto_hdr_field_get_u16(hdr, TCP_URG_PTR));
+
+ HDR_END();
+ return 0;
+}
+
+static int proto_dump_hdr(struct dump_ctx *ctx, struct proto_hdr *hdr)
+{
+ switch (hdr->ops->id) {
+ case PROTO_ETH:
+ return proto_dump_eth(ctx, hdr);
+ case PROTO_VLAN:
+ return proto_dump_vlan(ctx, hdr);
+ case PROTO_ARP:
+ return proto_dump_arp(ctx, hdr);
+ case PROTO_IP4:
+ return proto_dump_ip4(ctx, hdr);
+ case PROTO_UDP:
+ return proto_dump_udp(ctx, hdr);
+ case PROTO_TCP:
+ return proto_dump_tcp(ctx, hdr);
+ default:
+ return -1;
+ }
+}
+
+int packet_dump_fd(struct packet *pkt, int fd)
+{
+ struct proto_hdr *hdr;
+ enum proto_id pid;
+ struct dump_ctx _ctx;
+ struct dump_ctx *ctx = &_ctx;
+ size_t dump_len = 0;
+ uint32_t i;
+
+ _ctx.file = fdopen(fd, "w");
+ if (!_ctx.file)
+ return -1;
+
+ /* handle case if there is already proto headers */
+ if (pkt->headers_count == 0) {
+ hdr = proto_packet_apply(PROTO_ETH, pkt);
+
+ while ((pid = proto_hdr_get_next_proto(hdr)) != __PROTO_MAX) {
+ if (hdr->pkt_offset + hdr->len >= pkt->len)
+ break;
+
+ hdr = proto_packet_apply(pid, pkt);
+ }
+ }
+
+ PKT_START();
+ for (i = 0; i < pkt->headers_count; i++) {
+ hdr = pkt->headers[i];
+
+ if (proto_dump_hdr(ctx, hdr))
+ break;
+
+ dump_len += hdr->len;
+ }
+
+ /* print rest as a bytes */
+ if (dump_len < pkt->len) {
+ int j = 1;
+
+ DUMP(" ");
+ for (i = dump_len; i < pkt->len; ++i, ++j) {
+ if (j % 15 == 0)
+ DUMP("\n ");
+ DUMP("0x%02x,", pkt->payload[i]);
+ }
+ DUMP("\n");
+ }
+ PKT_END();
+
+ fflush(ctx->file);
+ return 0;
+}