xref: /openbmc/libmctp/utils/mctp-capture.c (revision f2988977)
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 	int rc;
34 
35 	if (!(cap->pcap = pcap_open_dead(CAPTURE_LINKTYPE_LINUX_SLL2,
36 					 UINT16_MAX))) {
37 		fprintf(stderr, "pcap_open_dead: failed\n");
38 		return -1;
39 	}
40 	if (!(cap->dumper = pcap_dump_open(cap->pcap, cap->path))) {
41 		fprintf(stderr, "pcap_dump_open: failed\n");
42 		return -1;
43 	}
44 
45 	return 0;
46 }
47 
48 void capture_close(struct capture *cap)
49 {
50 	pcap_dump_close(cap->dumper);
51 
52 	pcap_close(cap->pcap);
53 }
54 
55 void capture_binding(struct mctp_pktbuf *pkt, bool outgoing, void *user)
56 {
57 	pcap_dumper_t *dumper = user;
58 	struct pcap_pkthdr hdr;
59 	int rc;
60 	uint8_t *pktbuf = NULL;
61 	size_t size;
62 
63 	if ((rc = gettimeofday(&hdr.ts, NULL)) == -1)
64 		return;
65 
66 	/* Write sll2 header */
67 	size = sizeof(struct sll2_header) + mctp_pktbuf_size(pkt);
68 	pktbuf = __mctp_alloc(size);
69 	if (!pktbuf)
70 		return;
71 
72 	struct sll2_header *sll2 = (struct sll2_header *)pktbuf;
73 	sll2->sll2_protocol = htons(ETH_P_MCTP);
74 	if (outgoing)
75 		sll2->sll2_pkttype = LINUX_SLL_OUTGOING;
76 	else
77 		sll2->sll2_pkttype = LINUX_SLL_HOST;
78 	sll2->sll2_reserved_mbz = 0x0;
79 	sll2->sll2_if_index = 0x0;
80 	sll2->sll2_hatype = 0x0;
81 	sll2->sll2_halen = 0x0;
82 	memset(sll2->sll2_addr, 0, SLL_ADDRLEN);
83 
84 	memcpy(pktbuf + sizeof(struct sll2_header), mctp_pktbuf_hdr(pkt),
85 	       mctp_pktbuf_size(pkt));
86 
87 	hdr.caplen = size;
88 	hdr.len = size;
89 
90 	pcap_dump((u_char *)dumper, &hdr, (const u_char *)pktbuf);
91 	__mctp_free(pktbuf);
92 }
93 
94 void capture_socket(pcap_dumper_t *dumper, const void *buf, size_t len,
95 		    bool outgoing, int eid)
96 {
97 	struct pcap_pkthdr hdr;
98 	int rc;
99 	uint8_t *pktbuf = NULL;
100 	size_t size;
101 
102 	if ((rc = gettimeofday(&hdr.ts, NULL)) == -1)
103 		return;
104 
105 	/* Write sll2 header */
106 	size = sizeof(struct sll2_header) + sizeof(struct mctp_hdr) + len;
107 	pktbuf = __mctp_alloc(size);
108 	if (!pktbuf)
109 		return;
110 
111 	struct sll2_header *sll2 = (struct sll2_header *)pktbuf;
112 	sll2->sll2_protocol = htons(ETH_P_MCTP);
113 	if (outgoing)
114 		sll2->sll2_pkttype = LINUX_SLL_OUTGOING;
115 	else
116 		sll2->sll2_pkttype = LINUX_SLL_HOST;
117 	sll2->sll2_reserved_mbz = 0x0;
118 	sll2->sll2_if_index = 0x0;
119 	sll2->sll2_hatype = 0x0;
120 	sll2->sll2_halen = 0x0;
121 	memset(sll2->sll2_addr, 0, SLL_ADDRLEN);
122 
123 	/* Write fake mctp header */
124 	struct mctp_hdr *mctp =
125 		(struct mctp_hdr *)(pktbuf + sizeof(struct sll2_header));
126 	mctp->ver = 1;
127 	mctp->flags_seq_tag = 0xc0; //set SOM and EOM
128 	if (outgoing) {
129 		mctp->dest = eid;
130 		mctp->src = 0;
131 	} else {
132 		mctp->dest = 0;
133 		mctp->src = eid;
134 	}
135 
136 	/* Ignore the eid at start of buf */
137 	memcpy(pktbuf + sizeof(struct sll2_header) + sizeof(struct mctp_hdr),
138 	       buf + 1, len - 1);
139 
140 	hdr.caplen = size;
141 	hdr.len = size;
142 
143 	pcap_dump((u_char *)dumper, &hdr, (const u_char *)pktbuf);
144 	__mctp_free(pktbuf);
145 }
146