pcap: Use SLL2 linktype for captures
This means we can use wireshark on our pcaps.
Signed-off-by: Rashmica Gupta <rashmica@linux.ibm.com>
Change-Id: I215af00e064d352e41d0a8eb87d5a30582998676
diff --git a/core.c b/core.c
index 5a5d247..51eda38 100644
--- a/core.c
+++ b/core.c
@@ -547,7 +547,8 @@
goto out;
if (mctp->capture)
- mctp->capture(pkt, mctp->capture_data);
+ mctp->capture(pkt, MCTP_MESSAGE_CAPTURE_INCOMING,
+ mctp->capture_data);
hdr = mctp_pktbuf_hdr(pkt);
@@ -681,7 +682,8 @@
return -1;
if (mctp->capture)
- mctp->capture(pkt, mctp->capture_data);
+ mctp->capture(pkt, MCTP_MESSAGE_CAPTURE_OUTGOING,
+ mctp->capture_data);
return bus->binding->tx(bus->binding, pkt);
}
diff --git a/libmctp.h b/libmctp.h
index b34abfe..76f8ec9 100644
--- a/libmctp.h
+++ b/libmctp.h
@@ -37,8 +37,10 @@
#define MCTP_HDR_TAG_SHIFT (0)
#define MCTP_HDR_TAG_MASK (0x7)
-#define MCTP_MESSAGE_TO_SRC true
-#define MCTP_MESSAGE_TO_DST false
+#define MCTP_MESSAGE_TO_SRC true
+#define MCTP_MESSAGE_TO_DST false
+#define MCTP_MESSAGE_CAPTURE_OUTGOING true
+#define MCTP_MESSAGE_CAPTURE_INCOMING false
/* Baseline Transmission Unit and packet size */
#define MCTP_BTU 64
@@ -72,7 +74,8 @@
struct mctp *mctp_init(void);
void mctp_set_max_message_size(struct mctp *mctp, size_t message_size);
-typedef void (*mctp_capture_fn)(struct mctp_pktbuf *pkt, void *user);
+typedef void (*mctp_capture_fn)(struct mctp_pktbuf *pkt, bool outgoing,
+ void *user);
void mctp_set_capture_handler(struct mctp *mctp, mctp_capture_fn fn,
void *user);
void mctp_destroy(struct mctp *mctp);
diff --git a/utils/mctp-capture.c b/utils/mctp-capture.c
index 05180ec..b38e92d 100644
--- a/utils/mctp-capture.c
+++ b/utils/mctp-capture.c
@@ -2,6 +2,18 @@
#include <stdio.h>
#include <sys/time.h>
+#include <string.h>
+
+#if HAVE_PCAP
+#include <pcap/sll.h>
+#include <linux/if_ether.h>
+#include "libmctp-alloc.h"
+
+#ifndef ETH_P_MCTP
+#define ETH_P_MCTP 0xfa
+#endif
+
+#endif
int capture_init(void)
{
@@ -20,19 +32,11 @@
{
int rc;
- if (cap->linktype < CAPTURE_LINKTYPE_FIRST ||
- cap->linktype > CAPTURE_LINKTYPE_LAST) {
- fprintf(stderr,
- "Invalid private linktype value %d: see https://www.tcpdump.org/linktypes.html\n",
- cap->linktype);
- return -1;
- }
-
- if (!(cap->pcap = pcap_open_dead(cap->linktype, UINT16_MAX))) {
+ if (!(cap->pcap = pcap_open_dead(CAPTURE_LINKTYPE_LINUX_SLL2,
+ UINT16_MAX))) {
fprintf(stderr, "pcap_open_dead: failed\n");
return -1;
}
-
if (!(cap->dumper = pcap_dump_open(cap->pcap, cap->path))) {
fprintf(stderr, "pcap_dump_open: failed\n");
return -1;
@@ -48,31 +52,94 @@
pcap_close(cap->pcap);
}
-void capture_binding(struct mctp_pktbuf *pkt, void *user)
+void capture_binding(struct mctp_pktbuf *pkt, bool outgoing, void *user)
{
pcap_dumper_t *dumper = user;
struct pcap_pkthdr hdr;
int rc;
+ uint8_t *pktbuf = NULL;
+ size_t size;
if ((rc = gettimeofday(&hdr.ts, NULL)) == -1)
return;
- hdr.caplen = mctp_pktbuf_size(pkt);
- hdr.len = mctp_pktbuf_size(pkt);
+ /* Write sll2 header */
+ size = sizeof(struct sll2_header) + mctp_pktbuf_size(pkt);
+ pktbuf = __mctp_alloc(size);
+ if (!pktbuf)
+ return;
- pcap_dump((u_char *)dumper, &hdr, (const u_char *)mctp_pktbuf_hdr(pkt));
+ struct sll2_header *sll2 = (struct sll2_header *)pktbuf;
+ sll2->sll2_protocol = htons(ETH_P_MCTP);
+ if (outgoing)
+ sll2->sll2_pkttype = LINUX_SLL_OUTGOING;
+ else
+ sll2->sll2_pkttype = LINUX_SLL_HOST;
+ sll2->sll2_reserved_mbz = 0x0;
+ sll2->sll2_if_index = 0x0;
+ sll2->sll2_hatype = 0x0;
+ sll2->sll2_halen = 0x0;
+ memset(sll2->sll2_addr, 0, SLL_ADDRLEN);
+
+ memcpy(pktbuf + sizeof(struct sll2_header), mctp_pktbuf_hdr(pkt),
+ mctp_pktbuf_size(pkt));
+
+ hdr.caplen = size;
+ hdr.len = size;
+
+ pcap_dump((u_char *)dumper, &hdr, (const u_char *)pktbuf);
+ __mctp_free(pktbuf);
}
-void capture_socket(pcap_dumper_t *dumper, const void *buf, size_t len)
+void capture_socket(pcap_dumper_t *dumper, const void *buf, size_t len,
+ bool outgoing, int eid)
{
struct pcap_pkthdr hdr;
int rc;
+ uint8_t *pktbuf = NULL;
+ size_t size;
if ((rc = gettimeofday(&hdr.ts, NULL)) == -1)
return;
- hdr.caplen = len;
- hdr.len = len;
+ /* Write sll2 header */
+ size = sizeof(struct sll2_header) + sizeof(struct mctp_hdr) + len;
+ pktbuf = __mctp_alloc(size);
+ if (!pktbuf)
+ return;
- pcap_dump((u_char *)dumper, &hdr, buf);
+ struct sll2_header *sll2 = (struct sll2_header *)pktbuf;
+ sll2->sll2_protocol = htons(ETH_P_MCTP);
+ if (outgoing)
+ sll2->sll2_pkttype = LINUX_SLL_OUTGOING;
+ else
+ sll2->sll2_pkttype = LINUX_SLL_HOST;
+ sll2->sll2_reserved_mbz = 0x0;
+ sll2->sll2_if_index = 0x0;
+ sll2->sll2_hatype = 0x0;
+ sll2->sll2_halen = 0x0;
+ memset(sll2->sll2_addr, 0, SLL_ADDRLEN);
+
+ /* Write fake mctp header */
+ struct mctp_hdr *mctp =
+ (struct mctp_hdr *)(pktbuf + sizeof(struct sll2_header));
+ mctp->ver = 1;
+ mctp->flags_seq_tag = 0xc0; //set SOM and EOM
+ if (outgoing) {
+ mctp->dest = eid;
+ mctp->src = 0;
+ } else {
+ mctp->dest = 0;
+ mctp->src = eid;
+ }
+
+ /* Ignore the eid at start of buf */
+ memcpy(pktbuf + sizeof(struct sll2_header) + sizeof(struct mctp_hdr),
+ buf + 1, len - 1);
+
+ hdr.caplen = size;
+ hdr.len = size;
+
+ pcap_dump((u_char *)dumper, &hdr, (const u_char *)pktbuf);
+ __mctp_free(pktbuf);
}
diff --git a/utils/mctp-capture.h b/utils/mctp-capture.h
index 8babf2e..e432df9 100644
--- a/utils/mctp-capture.h
+++ b/utils/mctp-capture.h
@@ -12,17 +12,16 @@
#if HAVE_PCAP
#include <pcap/pcap.h>
+
#else
typedef void pcap_t;
typedef void pcap_dumper_t;
#endif
-#define CAPTURE_LINKTYPE_FIRST 147
-#define CAPTURE_LINKTYPE_LAST 162
+#define CAPTURE_LINKTYPE_LINUX_SLL2 276
struct capture {
const char *path;
- int linktype;
pcap_t *pcap;
pcap_dumper_t *dumper;
};
@@ -31,8 +30,9 @@
int capture_init(void);
int capture_prepare(struct capture *cap);
void capture_close(struct capture *cap);
-void capture_binding(struct mctp_pktbuf *pkt, void *user);
-void capture_socket(pcap_dumper_t *dumper, const void *buf, size_t len);
+void capture_binding(struct mctp_pktbuf *pkt, bool outgoing, void *user);
+void capture_socket(pcap_dumper_t *dumper, const void *buf, size_t len,
+ bool outgoing, int eid);
#else
#include <stdio.h>
static inline int capture_init(void)
@@ -54,12 +54,13 @@
}
static inline void capture_binding(struct mctp_pktbuf *pkt __unused,
- void *user __unused)
+ bool outgoing __unused, void *user __unused)
{
}
static inline void capture_socket(pcap_dumper_t *dumper __unused,
- const void *buf __unused, size_t len __unused)
+ const void *buf __unused, size_t len __unused,
+ bool outgoing __unused, int eid __unused)
{
}
#endif
diff --git a/utils/mctp-demux-daemon.c b/utils/mctp-demux-daemon.c
index f9893bb..d07e141 100644
--- a/utils/mctp-demux-daemon.c
+++ b/utils/mctp-demux-daemon.c
@@ -399,11 +399,12 @@
goto out_close;
}
- if (ctx->pcap.socket.path)
- capture_socket(ctx->pcap.socket.dumper, ctx->buf, rc);
-
eid = *(uint8_t *)ctx->buf;
+ if (ctx->pcap.socket.path)
+ capture_socket(ctx->pcap.socket.dumper, ctx->buf, rc,
+ MCTP_MESSAGE_CAPTURE_OUTGOING, eid);
+
if (ctx->verbose)
fprintf(stderr, "client[%d] sent message: dest 0x%02x len %d\n",
idx, eid, rc - 1);
@@ -592,9 +593,7 @@
ctx->local_eid = local_eid_default;
ctx->verbose = false;
ctx->pcap.binding.path = NULL;
- ctx->pcap.binding.linktype = -1;
ctx->pcap.socket.path = NULL;
- ctx->pcap.socket.linktype = -1;
for (;;) {
rc = getopt_long(argc, argv, "b:es::v", options, NULL);
@@ -608,10 +607,12 @@
ctx->pcap.socket.path = optarg;
break;
case 'B':
- ctx->pcap.binding.linktype = atoi(optarg);
+ fprintf(stderr,
+ "binding-linktype argument is deprecated\n");
break;
case 'S':
- ctx->pcap.socket.linktype = atoi(optarg);
+ fprintf(stderr,
+ "socket-linktype argument is deprecated\n");
break;
case 'v':
ctx->verbose = true;
@@ -631,18 +632,6 @@
return EXIT_FAILURE;
}
- if (ctx->pcap.binding.linktype < 0 && ctx->pcap.binding.path) {
- fprintf(stderr, "missing binding-linktype argument\n");
- usage(argv[0]);
- return EXIT_FAILURE;
- }
-
- if (ctx->pcap.socket.linktype < 0 && ctx->pcap.socket.path) {
- fprintf(stderr, "missing socket-linktype argument\n");
- usage(argv[0]);
- return EXIT_FAILURE;
- }
-
/* setup initial buffer */
ctx->buf_size = 4096;
ctx->buf = malloc(ctx->buf_size);