|
|
1.1 ! root 1: #include "m68000.h" ! 2: #include "ethernet.h" ! 3: #include "enet_pcap.h" ! 4: #include "queue.h" ! 5: #include "host.h" ! 6: ! 7: #if HAVE_PCAP ! 8: #if defined _WIN32 ! 9: #undef mkdir ! 10: #endif ! 11: #include <pcap.h> ! 12: ! 13: /****************/ ! 14: /* --- PCAP --- */ ! 15: ! 16: ! 17: /* PCAP prototypes */ ! 18: pcap_t *pcap_handle; ! 19: ! 20: /* queue prototypes */ ! 21: queueADT pcapq; ! 22: ! 23: int pcap_started; ! 24: static SDL_mutex *pcap_mutex = NULL; ! 25: SDL_Thread *pcap_tick_func_handle; ! 26: ! 27: //This function is to be periodically called ! 28: //to keep the internal packet state flowing. ! 29: static void pcap_tick(void) ! 30: { ! 31: struct pcap_pkthdr h; ! 32: const unsigned char *data; ! 33: ! 34: if (pcap_started) { ! 35: SDL_LockMutex(pcap_mutex); ! 36: data = pcap_next(pcap_handle,&h); ! 37: SDL_UnlockMutex(pcap_mutex); ! 38: ! 39: if (data && h.caplen > 0) { ! 40: if (h.caplen > 1516) ! 41: h.caplen = 1516; ! 42: ! 43: struct queuepacket *p; ! 44: p=(struct queuepacket *)malloc(sizeof(struct queuepacket)); ! 45: SDL_LockMutex(pcap_mutex); ! 46: p->len=h.caplen; ! 47: memcpy(p->data,data,h.caplen); ! 48: QueueEnter(pcapq,p); ! 49: SDL_UnlockMutex(pcap_mutex); ! 50: Log_Printf(LOG_WARN, "[PCAP] Output packet with %i bytes to queue",h.caplen); ! 51: } ! 52: } ! 53: } ! 54: ! 55: static int tick_func(void *arg) ! 56: { ! 57: while(pcap_started) ! 58: { ! 59: host_sleep_ms(10); ! 60: pcap_tick(); ! 61: } ! 62: return 0; ! 63: } ! 64: ! 65: ! 66: void enet_pcap_queue_poll(void) ! 67: { ! 68: if (pcap_started) { ! 69: SDL_LockMutex(pcap_mutex); ! 70: if (QueuePeek(pcapq)>0) ! 71: { ! 72: struct queuepacket *qp; ! 73: qp=QueueDelete(pcapq); ! 74: Log_Printf(LOG_WARN, "[PCAP] Getting packet from queue"); ! 75: enet_receive(qp->data,qp->len); ! 76: free(qp); ! 77: } ! 78: SDL_UnlockMutex(pcap_mutex); ! 79: } ! 80: } ! 81: ! 82: void enet_pcap_input(Uint8 *pkt, int pkt_len) { ! 83: if (pcap_started) { ! 84: Log_Printf(LOG_WARN, "[PCAP] Input packet with %i bytes",enet_tx_buffer.size); ! 85: SDL_LockMutex(pcap_mutex); ! 86: if (pcap_sendpacket(pcap_handle, pkt, pkt_len) < 0) { ! 87: Log_Printf(LOG_WARN, "[PCAP] Error: Couldn't transmit packet!"); ! 88: } ! 89: SDL_UnlockMutex(pcap_mutex); ! 90: } ! 91: } ! 92: ! 93: void enet_pcap_stop(void) { ! 94: int ret; ! 95: ! 96: if (pcap_started) { ! 97: Log_Printf(LOG_WARN, "Stopping PCAP"); ! 98: pcap_started=0; ! 99: QueueDestroy(pcapq); ! 100: SDL_DestroyMutex(pcap_mutex); ! 101: SDL_WaitThread(pcap_tick_func_handle, &ret); ! 102: pcap_close(pcap_handle); ! 103: } ! 104: } ! 105: ! 106: void enet_pcap_start(Uint8 *mac) { ! 107: char errbuf[PCAP_ERRBUF_SIZE]; ! 108: char *dev; ! 109: struct bpf_program fp; ! 110: char filter_exp[255]; ! 111: bpf_u_int32 net = 0xffffffff; ! 112: ! 113: if (!pcap_started) { ! 114: Log_Printf(LOG_WARN, "Starting PCAP"); ! 115: ! 116: #if 0 ! 117: dev = pcap_lookupdev(errbuf); ! 118: #else ! 119: dev = ConfigureParams.Ethernet.szInterfaceName; ! 120: #endif ! 121: if (dev == NULL) { ! 122: Log_Printf(LOG_WARN, "[PCAP] Error: Couldn't find device: %s", errbuf); ! 123: return; ! 124: } ! 125: Log_Printf(LOG_WARN, "Device: %s", dev); ! 126: ! 127: pcap_handle = pcap_open_live(dev, 1518, 1, 1000, errbuf); ! 128: ! 129: if (pcap_handle == NULL) { ! 130: Log_Printf(LOG_WARN, "[PCAP] Error: Couldn't open device %s: %s", dev, errbuf); ! 131: return; ! 132: } ! 133: ! 134: if (pcap_getnonblock(pcap_handle, errbuf) == 0) { ! 135: Log_Printf(LOG_WARN, "[PCAP] Setting interface to non-blocking mode."); ! 136: if (pcap_setnonblock(pcap_handle, 1, errbuf) != 0) { ! 137: Log_Printf(LOG_WARN, "[PCAP] Error: Couldn't set interface to non-blocking mode: %s", errbuf); ! 138: return; ! 139: } ! 140: } else { ! 141: Log_Printf(LOG_WARN, "[PCAP] Error: Unexpected error: %s", errbuf); ! 142: return; ! 143: } ! 144: ! 145: #if 1 // TODO: Check if we need to take care of RXMODE_ADDR_SIZE and RX_PROMISCUOUS/RX_ANY ! 146: sprintf(filter_exp,"(((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x) or (ether[0] & 0x01 = 0x01)))", ! 147: mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ! 148: ! 149: if (pcap_compile(pcap_handle, &fp, filter_exp, 0, net) == -1) { ! 150: Log_Printf(LOG_WARN, "[PCAP] Warning: Couldn't parse filter %s: %s", filter_exp, pcap_geterr(pcap_handle)); ! 151: } else { ! 152: if (pcap_setfilter(pcap_handle, &fp) == -1) { ! 153: Log_Printf(LOG_WARN, "[PCAP] Warning: Couldn't install filter %s: %s", filter_exp, pcap_geterr(pcap_handle)); ! 154: } ! 155: } ! 156: #endif ! 157: pcap_started=1; ! 158: pcapq = QueueCreate(); ! 159: pcap_mutex=SDL_CreateMutex(); ! 160: pcap_tick_func_handle=SDL_CreateThread(tick_func,"PCAPTickThread", (void *)NULL); ! 161: } ! 162: } ! 163: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.