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