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