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