DWORD request_sniffer_capture_release(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid,i; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> release_capture()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> release_capture(0x%.8x)", ifid); result = ERROR_SUCCESS; do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface is not being captured #ifdef _WIN32 if(! j->adp || j->active == 1) #else if(! j->pcap || j->active == 1) #endif { result = ERROR_INVALID_PARAMETER; break; } lock_acquire(snifferm); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, j->cur_pkts); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, (unsigned int) j->cur_bytes); dprintf("sniffer>> release_capture() interface %d released %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes); for(i=0; i<j->max_pkts; i++) { if(!j->pkts[i]) break; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } free(j->pkts); memset(j, 0, sizeof(CaptureJob)); lock_release(snifferm); } while(0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid,i; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> stop_capture()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> stop_capture(0x%.8x)", ifid); result = ERROR_SUCCESS; do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface is not being captured if(! j->adp) { result = ERROR_INVALID_PARAMETER; break; } EnterCriticalSection(&sniffercs); j->active = 0; AdpSetMacFilter(j->adp, 0); AdpCloseAdapter(j->adp); AdpDestroy(j->adp); for(i=0; i<j->max_pkts; i++) { if(!j->pkts[i]) break; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } free(j->pkts); memset(j, 0, sizeof(CaptureJob)); LeaveCriticalSection(&sniffercs); dprintf("sniffer>> stop_capture() interface %d processed %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes); } while(0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; unsigned int rbuf,mbuf; unsigned int *tmp; CaptureJob *j; DWORD result,pcnt,bcnt,rcnt,i; DWORD thi, tlo; check_pssdk(); dprintf("sniffer>> capture_dump()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> capture_dump(0x%.8x)", ifid); result = ERROR_SUCCESS; EnterCriticalSection(&sniffercs); do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface was not captured if(! j->adp) { result = ERROR_INVALID_PARAMETER; break; } // Free any existing packet buffer if(j->dbuf) { free(j->dbuf); j->dbuf = NULL; j->dlen = 0; j->didx = 0; } // Add basic stats pcnt = 0; bcnt = 0; rcnt = 0; mbuf = (1024*1024); j->dbuf = malloc(mbuf); rbuf = 0; for(i=0; i<j->max_pkts; i++) { if(!j->pkts[i]) break; rbuf += (8 + 8 + 4 + PktGetPacketSize(j->pkts[i])); if(mbuf < rbuf) { mbuf += (1024*1024); j->dbuf = realloc(j->dbuf, mbuf); if(!j->dbuf) { dprintf("sniffer>> realloc of %d bytes failed!", rbuf); result = ERROR_NOT_ENOUGH_MEMORY; break; } } tmp = (unsigned int *)( j->dbuf + rcnt ); tlo = PktGetId(j->pkts[i], &thi); *tmp = htonl(thi); tmp++; *tmp = htonl(tlo); tmp++; tlo = PktGetTimeStamp(j->pkts[i], &thi); *tmp = htonl(thi); tmp++; *tmp = htonl(tlo); tmp++; tlo = PktGetPacketSize(j->pkts[i]); *tmp = htonl(tlo); tmp++; memcpy(j->dbuf+rcnt+20, PktGetPacketData(j->pkts[i]), tlo); rcnt += 20 + tlo; pcnt++; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } j->dlen = rcnt; packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, pcnt); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, rcnt); dprintf("sniffer>> finished processing packets"); j->cur_bytes = 0; j->cur_pkts = 0; j->idx_pkts = 0; } while(0); LeaveCriticalSection(&sniffercs); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacket, LPVOID pPacketData, DWORD IncPacketSize) { CaptureJob *j; HANDLE pkt; unsigned char *pktbuf; unsigned char *pktmax; struct eth_hdr *eth; struct ip_hdr *ip; struct tcp_hdr *tcp; // struct udp_hdr *udp; j = (CaptureJob *)Param; pktbuf = (unsigned char *)pPacketData; pktmax = pktbuf + IncPacketSize; // Only process active jobs if(!j->active) return; // Traffic filtering goes here do { // Skip matching on short packets if(IncPacketSize < ETH_HDR_LEN + IP_HDR_LEN + TCP_HDR_LEN){ dprintf("sniffer>> skipping exclusion because the packet is too small"); break; } // Match IP packets if(!peername4) { dprintf("sniffer>> skipping exclusion because peername4 is not defined"); break; } // Skip non-IP packets eth = (struct eth_hdr *) pktbuf; if(ntohs(eth->eth_type) != ETH_TYPE_IP) { dprintf("sniffer>> skipping non-IP packet from filter"); break; } // Skip non-TCP/UDP packets ip = (struct ip_hdr *) &pktbuf[ETH_HDR_LEN]; if(ip->ip_p != IP_PROTO_TCP && ip->ip_p != IP_PROTO_UDP) { dprintf("sniffer>> skipping non-TCP/UDP packet from filter: %d", ip->ip_p); break; } if(ip->ip_p == IP_PROTO_TCP) { tcp = (struct tcp_hdr *) &pktbuf[ETH_HDR_LEN + (ip->ip_hl * 4)]; if( (unsigned char *)tcp + TCP_HDR_LEN > pktmax) { dprintf("sniffer>> TCP packet is too short"); break; } // Ignore our own control session's traffic if ( (memcmp(&ip->ip_src, &peername4->sin_addr, 4) == 0 && tcp->th_sport == peername4->sin_port) || (memcmp(&ip->ip_dst, &peername4->sin_addr, 4) == 0 && tcp->th_dport == peername4->sin_port) ) { return; } // TODO: Scan through a list of included/excluded ports } // All done matching exclusions } while(0); // Thread-synchronized access to the queue EnterCriticalSection(&sniffercs); if(j->idx_pkts >= j->max_pkts) j->idx_pkts = 0; j->cur_pkts++; j->cur_bytes += IncPacketSize; pkt = PktCreate(j->mtu); PktCopyPacketToPacket(pkt, hPacket); if(j->pkts[j->idx_pkts]) PktDestroy(j->pkts[j->idx_pkts]); j->pkts[j->idx_pkts] = pkt; j->idx_pkts++; LeaveCriticalSection(&sniffercs); }
DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid, i; unsigned int bcnt; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> capture_dump_read()"); ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID); bcnt = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_BYTE_COUNT); bcnt = min(bcnt, 32 * 1024 * 1024); dprintf("sniffer>> capture_dump_read(0x%.8x, %d)", ifid, bcnt); result = ERROR_SUCCESS; do { // the interface is invalid if (ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0); goto fail; } j = &open_captures[ifid]; if (!j->dbuf) { packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0); goto fail; } if (j->didx + bcnt > j->dlen) { bcnt = j->dlen - j->didx; } packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, bcnt); packet_add_tlv_raw(response, TLV_TYPE_SNIFFER_PACKET, (unsigned char *)j->dbuf + j->didx, bcnt); j->didx += bcnt; } while (0); // Free memory if the read is complete if (j->didx >= j->dlen - 1) { free(j->dbuf); j->dbuf = NULL; j->didx = 0; j->dlen = 0; // if dump occurs when interface is not active, i.e sniff has ended, release info if (j->active == 0) { dprintf("sniffer>> capture_dump_read, release CaptureJob"); lock_acquire(snifferm); for (i = 0; i < j->max_pkts; i++) { if (!j->pkts[i]) break; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } free(j->pkts); memset(j, 0, sizeof(CaptureJob)); lock_release(snifferm); } } fail: packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; unsigned int rbuf, mbuf; unsigned int *tmp; CaptureJob *j; DWORD result, pcnt, rcnt, i; #ifdef _WIN64 ULONGLONG thilo; #endif DWORD thi, tlo; check_pssdk(); dprintf("sniffer>> capture_dump()"); ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> capture_dump(0x%.8x)", ifid); result = ERROR_SUCCESS; lock_acquire(snifferm); do { // the interface is invalid if (ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface was not captured #ifdef _WIN32 if (!j->adp) #else if(! j->pcap) #endif { result = ERROR_INVALID_PARAMETER; break; } // Free any existing packet buffer if (j->dbuf) { free(j->dbuf); j->dbuf = NULL; j->dlen = 0; j->didx = 0; } // Add basic stats pcnt = 0; rcnt = 0; mbuf = (1024 * 1024); j->dbuf = malloc(mbuf); rbuf = 0; for (i = 0; i < j->max_pkts; i++) { if (!j->pkts[i]) break; rbuf += (8 + 8 + 4 + PktGetPacketSize(j->pkts[i])); if (mbuf < rbuf) { mbuf += (1024 * 1024); j->dbuf = realloc(j->dbuf, mbuf); if (!j->dbuf) { dprintf("sniffer>> realloc of %d bytes failed!", rbuf); result = ERROR_NOT_ENOUGH_MEMORY; break; } } tmp = (unsigned int *)(j->dbuf + rcnt); #ifdef _WIN64 thilo = PktGetId(j->pkts[i]); thi = (DWORD)(thilo >> 32); tlo = (DWORD)(thilo & 0xFFFFFFFF); #else tlo = PktGetId(j->pkts[i], &thi); #endif *tmp = htonl(thi); tmp++; *tmp = htonl(tlo); tmp++; #ifdef _WIN64 thilo = PktGetTimeStamp(j->pkts[i]); thi = (DWORD)(thilo >> 32); tlo = (DWORD)(thilo & 0xFFFFFFFF); #else tlo = PktGetTimeStamp(j->pkts[i], &thi); #endif *tmp = htonl(thi); tmp++; *tmp = htonl(tlo); tmp++; tlo = PktGetPacketSize(j->pkts[i]); *tmp = htonl(tlo); tmp++; memcpy(j->dbuf + rcnt + 20, PktGetPacketData(j->pkts[i]), tlo); rcnt += 20 + tlo; pcnt++; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } j->dlen = rcnt; packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, pcnt); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, rcnt); // add capture datalink, needed when saving capture file, use TLV_TYPE_SNIFFER_INTERFACE_ID not to create a new TLV type packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_INTERFACE_ID, j->capture_linktype); dprintf("sniffer>> finished processing packets"); j->cur_bytes = 0; j->cur_pkts = 0; j->idx_pkts = 0; } while (0); lock_release(snifferm); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }