1 /* for io_module_func def'ns */
2 #include "io_module.h"
3 /* for mtcp related def'ns */
4 #include "mtcp.h"
5 /* for errno */
6 #include <errno.h>
7 /* for logging */
8 #include "debug.h"
9 /* for num_devices_* */
10 #include "config.h"
11 
12 #include <string.h>
13 #include <pcap.h>
14 
15 /*----------------------------------------------------------------------------*/
16 struct pcap_private_context {
17 	pcap_t *handle[MAX_DEVICES];
18 	char   *dev_name[MAX_DEVICES];
19 
20 	struct pcap_pkthdr phdr;
21 	const u_char *rdata;
22 	u_char wdata[ETHERNET_FRAME_LEN];
23 	uint16_t count[MAX_DEVICES];
24 } g_pcap_ctx;
25 /*----------------------------------------------------------------------------*/
26 void
27 pcap_init_handle(struct mtcp_thread_context *ctxt)
28 {
29 	ctxt->io_private_context = &g_pcap_ctx;
30 }
31 /*----------------------------------------------------------------------------*/
32 int32_t
33 pcap_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
34 {
35 	if (ifidx < 0 || ifidx >= MAX_DEVICES)
36 		return -1;
37 
38 	struct pcap_private_context *ppc = ctxt->io_private_context;
39 	if ((ppc->rdata = pcap_next(ppc->handle[ifidx], &ppc->phdr)) == NULL)
40 		return 0;
41 
42 	return 1; /* PCAP always receives only one packet */
43 }
44 /*----------------------------------------------------------------------------*/
45 uint8_t *
46 pcap_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len)
47 {
48 	struct pcap_private_context *ppc = ctxt->io_private_context;
49 	if (ppc->rdata == NULL)
50 		return NULL;
51 
52 	*len = ppc->phdr.caplen;
53 	return (uint8_t *)ppc->rdata;
54 }
55 /*----------------------------------------------------------------------------*/
56 int
57 pcap_send_pkts(struct mtcp_thread_context *ctxt, int nif)
58 {
59 	int ret = 0;
60 	struct pcap_private_context *ppc = ctxt->io_private_context;
61 
62 	if (ppc->count[nif] > 0) {
63 		ret = pcap_inject(ppc->handle[nif], ppc->wdata, ppc->phdr.len);
64 	}
65 
66 	ppc->count[nif] = 0;
67 	return (ret != -1) ? 1 : 0;
68 }
69 /*----------------------------------------------------------------------------*/
70 uint8_t *
71 pcap_get_wptr(struct mtcp_thread_context *ctxt, int ifidx, uint16_t pktsize)
72 {
73 	struct pcap_private_context *ppc = ctxt->io_private_context;
74 	/* phdr can be reused */
75 	ppc->phdr.caplen = ppc->phdr.len = pktsize;
76 	ppc->count[ifidx] = 1;
77 	return ppc->wdata;
78 }
79 /*----------------------------------------------------------------------------*/
80 int
81 pcap_get_nif(struct ifreq *ifr)
82 {
83 	int i;
84 
85 	for (i = 0; i < g_config.mos->netdev_table->num; i++)
86 		if (!strcmp(ifr->ifr_name, g_pcap_ctx.dev_name[i]))
87 			return i;
88 
89 	return -1;
90 }
91 /*----------------------------------------------------------------------------*/
92 int32_t
93 pcap_select(struct mtcp_thread_context *ctxt)
94 {
95 	return 0;
96 }
97 /*----------------------------------------------------------------------------*/
98 void
99 pcap_destroy_handle(struct mtcp_thread_context *ctxt)
100 {
101 	int i;
102 	struct pcap_private_context *ppc = ctxt->io_private_context;
103 	if (!ppc)
104 		return;
105 
106 	for (i = 0; i < g_config.mos->netdev_table->num; i++) {
107 		pcap_close(ppc->handle[i]);
108 	}
109 
110 	ctxt->io_private_context = NULL;
111 }
112 /*----------------------------------------------------------------------------*/
113 void
114 pcap_load_module_upper_half(void)
115 {
116 	int i;
117 	char errbuf[PCAP_ERRBUF_SIZE];
118 	struct netdev_entry **ent = g_config.mos->netdev_table->ent;
119 
120 	for (i = 0; i < g_config.mos->netdev_table->num; i++) {
121 		g_pcap_ctx.handle[i] = pcap_open_live(ent[i]->dev_name, BUFSIZ, 1,
122 										1, errbuf);
123 		if (!g_pcap_ctx.handle[i]) {
124 			TRACE_ERROR("Interface '%s' not found\n", ent[i]->dev_name);
125 			exit(EXIT_FAILURE);
126 		}
127 		g_pcap_ctx.dev_name[i] = ent[i]->dev_name;
128 	}
129 
130 	num_queues = 1;
131 }
132 /*----------------------------------------------------------------------------*/
133 io_module_func pcap_module_func = {
134 	.load_module_upper_half	   = pcap_load_module_upper_half,
135 	.load_module_lower_half	   = NULL,
136 	.init_handle		   = pcap_init_handle,
137 	.link_devices		   = NULL,
138 	.release_pkt		   = NULL,
139 	.send_pkts		   = pcap_send_pkts,
140 	.get_wptr   		   = pcap_get_wptr,
141 	.set_wptr   		   = NULL,
142 	.recv_pkts		   = pcap_recv_pkts,
143 	.get_rptr	   	   = pcap_get_rptr,
144 	.select			   = NULL,
145 	.destroy_handle		   = pcap_destroy_handle,
146 	.dev_ioctl		   = NULL,
147 	.get_nif		   = pcap_get_nif,
148 };
149 /*----------------------------------------------------------------------------*/
150