xref: /openbmc/libmctp/utils/mctp-capture.c (revision 3ef47785)
1 #include "utils/mctp-capture.h"
2 
3 #include <stdio.h>
4 #include <sys/time.h>
5 #include <string.h>
6 
7 #if HAVE_PCAP
8 #include <pcap/sll.h>
9 #include <linux/if_ether.h>
10 #include "libmctp-alloc.h"
11 
12 #ifndef ETH_P_MCTP
13 #define ETH_P_MCTP 0xfa
14 #endif
15 
16 #endif
17 
18 int capture_init(void)
19 {
20 	char errbuf[PCAP_ERRBUF_SIZE];
21 	int rc;
22 
23 	if ((rc = pcap_init(PCAP_CHAR_ENC_UTF_8, errbuf)) == -1) {
24 		fprintf(stderr, "pcap_init: %s\n", errbuf);
25 		return -1;
26 	}
27 
28 	return 0;
29 }
30 
31 int capture_prepare(struct capture *cap)
32 {
33 	if (!(cap->pcap = pcap_open_dead(CAPTURE_LINKTYPE_LINUX_SLL2,
34 					 UINT16_MAX))) {
35 		fprintf(stderr, "pcap_open_dead: failed\n");
36 		return -1;
37 	}
38 	if (!(cap->dumper = pcap_dump_open(cap->pcap, cap->path))) {
39 		fprintf(stderr, "pcap_dump_open: failed\n");
40 		return -1;
41 	}
42 
43 	return 0;
44 }
45 
46 void capture_close(struct capture *cap)
47 {
48 	pcap_dump_close(cap->dumper);
49 
50 	pcap_close(cap->pcap);
51 }
52 
53 void capture_binding(struct mctp_pktbuf *pkt, bool outgoing, void *user)
54 {
55 	pcap_dumper_t *dumper = user;
56 	struct pcap_pkthdr hdr;
57 	int rc;
58 	uint8_t *pktbuf = NULL;
59 	size_t size;
60 
61 	if ((rc = gettimeofday(&hdr.ts, NULL)) == -1)
62 		return;
63 
64 	/* Write sll2 header */
65 	size = sizeof(struct sll2_header) + mctp_pktbuf_size(pkt);
66 	pktbuf = __mctp_alloc(size);
67 	if (!pktbuf)
68 		return;
69 
70 	struct sll2_header *sll2 = (struct sll2_header *)pktbuf;
71 	sll2->sll2_protocol = htons(ETH_P_MCTP);
72 	if (outgoing)
73 		sll2->sll2_pkttype = LINUX_SLL_OUTGOING;
74 	else
75 		sll2->sll2_pkttype = LINUX_SLL_HOST;
76 	sll2->sll2_reserved_mbz = 0x0;
77 	sll2->sll2_if_index = 0x0;
78 	sll2->sll2_hatype = 0x0;
79 	sll2->sll2_halen = 0x0;
80 	memset(sll2->sll2_addr, 0, SLL_ADDRLEN);
81 
82 	memcpy(pktbuf + sizeof(struct sll2_header), mctp_pktbuf_hdr(pkt),
83 	       mctp_pktbuf_size(pkt));
84 
85 	hdr.caplen = size;
86 	hdr.len = size;
87 
88 	pcap_dump((u_char *)dumper, &hdr, (const u_char *)pktbuf);
89 	__mctp_free(pktbuf);
90 }
91 
92 void capture_socket(pcap_dumper_t *dumper, const void *buf, size_t len,
93 		    bool outgoing, int eid)
94 {
95 	struct pcap_pkthdr hdr;
96 	int rc;
97 	uint8_t *pktbuf = NULL;
98 	size_t size;
99 
100 	if ((rc = gettimeofday(&hdr.ts, NULL)) == -1)
101 		return;
102 
103 	/* Write sll2 header */
104 	size = sizeof(struct sll2_header) + sizeof(struct mctp_hdr) + len;
105 	pktbuf = __mctp_alloc(size);
106 	if (!pktbuf)
107 		return;
108 
109 	struct sll2_header *sll2 = (struct sll2_header *)pktbuf;
110 	sll2->sll2_protocol = htons(ETH_P_MCTP);
111 	if (outgoing)
112 		sll2->sll2_pkttype = LINUX_SLL_OUTGOING;
113 	else
114 		sll2->sll2_pkttype = LINUX_SLL_HOST;
115 	sll2->sll2_reserved_mbz = 0x0;
116 	sll2->sll2_if_index = 0x0;
117 	sll2->sll2_hatype = 0x0;
118 	sll2->sll2_halen = 0x0;
119 	memset(sll2->sll2_addr, 0, SLL_ADDRLEN);
120 
121 	/* Write fake mctp header */
122 	struct mctp_hdr *mctp =
123 		(struct mctp_hdr *)(pktbuf + sizeof(struct sll2_header));
124 	mctp->ver = 1;
125 	mctp->flags_seq_tag = 0xc0; //set SOM and EOM
126 	if (outgoing) {
127 		mctp->dest = eid;
128 		mctp->src = 0;
129 	} else {
130 		mctp->dest = 0;
131 		mctp->src = eid;
132 	}
133 
134 	/* Ignore the eid at start of buf */
135 	memcpy(pktbuf + sizeof(struct sll2_header) + sizeof(struct mctp_hdr),
136 	       (const uint8_t *)buf + 1, len - 1);
137 
138 	hdr.caplen = size;
139 	hdr.len = size;
140 
141 	pcap_dump((u_char *)dumper, &hdr, (const u_char *)pktbuf);
142 	__mctp_free(pktbuf);
143 }
144