packet_t * capture_packet_reasm_tcp(packet_t *packet, struct tcphdr *tcp, u_char *payload, int size_payload) { vector_iter_t it = vector_iterator(capture_cfg.tcp_reasm); packet_t *pkt; u_char *new_payload; //! Assembled if ((int32_t) size_payload <= 0) return packet; while ((pkt = vector_iterator_next(&it))) { if (addressport_equals(pkt->src, packet->src) && addressport_equals(pkt->dst, packet->dst)) { break; } } // If we already have this packet stored if (pkt) { frame_t *frame; // Append this frames to the original packet vector_iter_t frames = vector_iterator(packet->frames); while ((frame = vector_iterator_next(&frames))) packet_add_frame(pkt, frame->header, frame->data); // Destroy current packet as its frames belong to the stored packet packet_destroy(packet); } else { // First time this packet has been seen pkt = packet; // Add To the possible reassembly list vector_append(capture_cfg.tcp_reasm, packet); } // Store firt tcp sequence if (pkt->tcp_seq == 0) { pkt->tcp_seq = ntohl(tcp->th_seq); } // If the first frame of this packet if (vector_count(pkt->frames) == 1) { // Set initial payload packet_set_payload(pkt, payload, size_payload); } else { // Check payload length. Dont handle too big payload packets if (pkt->payload_len + size_payload > MAX_CAPTURE_LEN) { packet_destroy(pkt); vector_remove(capture_cfg.tcp_reasm, pkt); return NULL; } new_payload = sng_malloc(pkt->payload_len + size_payload); if (pkt->tcp_seq < ntohl(tcp->th_seq)) { // Append payload to the existing pkt->tcp_seq = ntohl(tcp->th_seq); memcpy(new_payload, pkt->payload, pkt->payload_len); memcpy(new_payload + pkt->payload_len, payload, size_payload); } else { // Prepend payload to the existing memcpy(new_payload, payload, size_payload); memcpy(new_payload + size_payload, pkt->payload, pkt->payload_len); } packet_set_payload(pkt, new_payload, pkt->payload_len + size_payload); sng_free(new_payload); } // This packet is ready to be parsed int valid = sip_validate_packet(pkt); if (valid == VALIDATE_COMPLETE_SIP) { // Full SIP packet! vector_remove(capture_cfg.tcp_reasm, pkt); return pkt; } else if (valid == VALIDATE_NOT_SIP) { vector_remove(capture_cfg.tcp_reasm, pkt); return pkt; } // An incomplete SIP Packet return NULL; }
packet_t * capture_eep_receive_v3() { struct hep_generic hg; hep_chunk_ip4_t src_ip4, dst_ip4; #ifdef USE_IPV6 hep_chunk_ip6_t src_ip6, dst_ip6; #endif hep_chunk_t payload_chunk; hep_chunk_t authkey_chunk; uint8_t family, proto; char password[100]; int password_len; unsigned char *payload = 0; uint32_t len, pos; char buffer[MAX_CAPTURE_LEN] ; //! Source and Destination Address address_t src, dst; //! EEP client data struct sockaddr eep_client; socklen_t eep_client_len; //! Packet header struct pcap_pkthdr header; //! New created packet pointer packet_t *pkt; /* Receive EEP generic header */ if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) return NULL; /* Copy initial bytes to EEP Generic header */ memcpy(&hg, buffer, sizeof(struct hep_generic)); /* header check */ if (memcmp(hg.header.id, "\x48\x45\x50\x33", 4) != 0) return NULL; /* IP proto */ family = hg.ip_family.data; /* Proto ID */ proto = hg.ip_proto.data; len = ntohs(hg.header.length) - sizeof(struct hep_generic); pos = sizeof(struct hep_generic); /* IPv4 */ if (family == AF_INET) { /* SRC IP */ memcpy(&src_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); inet_ntop(AF_INET, &src_ip4.data, src.ip, sizeof(src.ip)); pos += sizeof(struct hep_chunk_ip4); /* DST IP */ memcpy(&dst_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); inet_ntop(AF_INET, &dst_ip4.data, dst.ip, sizeof(src.ip)); pos += sizeof(struct hep_chunk_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(family == AF_INET6) { /* SRC IPv6 */ memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); inet_ntop(AF_INET6, &src_ip6.data, src.ip, sizeof(src.ip)); pos += sizeof(struct hep_chunk_ip6); /* DST IP */ memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); inet_ntop(AF_INET6, &dst_ip6.data, dst.ip, sizeof(dst.ip)); pos += sizeof(struct hep_chunk_ip6); } #endif /* SRC PORT */ src.port = ntohs(hg.src_port.data); /* DST PORT */ dst.port = ntohs(hg.dst_port.data); /* TIMESTAMP*/ header.ts.tv_sec = ntohl(hg.time_sec.data); header.ts.tv_usec = ntohl(hg.time_usec.data); /* Protocol TYPE */ /* Capture ID */ /* auth key */ if (eep_cfg.capt_srv_password != NULL) { memcpy(&authkey_chunk, (void*) buffer + pos, sizeof(authkey_chunk)); pos += sizeof(authkey_chunk); password_len = ntohs(authkey_chunk.length) - sizeof(authkey_chunk); memcpy(password, (void*) buffer + pos, password_len); pos += password_len; // Validate the password if (strncmp(password, eep_cfg.capt_srv_password, password_len) != 0) return NULL; } /* Payload */ memcpy(&payload_chunk, (void*) buffer + pos, sizeof(payload_chunk)); pos += sizeof(payload_chunk); // Calculate payload size header.caplen = header.len = ntohs(payload_chunk.length) - sizeof(payload_chunk); // Receive packet payload payload = sng_malloc(header.caplen); memcpy(payload, (void*) buffer + pos, header.caplen); // Create a new packet pkt = packet_create((family == AF_INET)?4:6, proto, src, dst, 0); packet_add_frame(pkt, &header, payload); packet_set_type(pkt, PACKET_SIP_UDP); packet_set_payload(pkt, payload, header.caplen); /* FREE */ sng_free(payload); return pkt; }
packet_t * capture_packet_reasm_ip(capture_info_t *capinfo, const struct pcap_pkthdr *header, u_char *packet, uint32_t *size, uint32_t *caplen) { // IP header data struct ip *ip4; #ifdef USE_IPV6 // IPv6 header data struct ip6_hdr *ip6; #endif // IP version uint32_t ip_ver; // IP protocol uint8_t ip_proto; // IP header size uint32_t ip_hl = 0; // Fragment offset uint16_t ip_off = 0; // IP content len uint16_t ip_len = 0; // Fragmentation flag uint16_t ip_frag = 0; // Fragmentation identifier uint32_t ip_id = 0; // Fragmentation offset uint16_t ip_frag_off = 0; //! Source Address address_t src = { }; //! Destination Address address_t dst = { }; //! Common interator for vectors vector_iter_t it; //! Packet containers packet_t *pkt; //! Storage for IP frame frame_t *frame; uint32_t len_data = 0; // Get IP header ip4 = (struct ip *) (packet + capinfo->link_hl); #ifdef USE_IPV6 // Get IPv6 header ip6 = (struct ip6_hdr *) (packet + capinfo->link_hl); #endif // Get IP version ip_ver = ip4->ip_v; switch (ip_ver) { case 4: ip_hl = ip4->ip_hl * 4; ip_proto = ip4->ip_p; ip_off = ntohs(ip4->ip_off); ip_len = ntohs(ip4->ip_len); ip_frag = ip_off & (IP_MF | IP_OFFMASK); ip_frag_off = (ip_frag) ? (ip_off & IP_OFFMASK) * 8 : 0; ip_id = ntohs(ip4->ip_id); inet_ntop(AF_INET, &ip4->ip_src, src.ip, sizeof(src.ip)); inet_ntop(AF_INET, &ip4->ip_dst, dst.ip, sizeof(dst.ip)); break; #ifdef USE_IPV6 case 6: ip_hl = sizeof(struct ip6_hdr); ip_proto = ip6->ip6_nxt; ip_len = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen) + ip_hl; if (ip_proto == IPPROTO_FRAGMENT) { struct ip6_frag *ip6f = (struct ip6_frag *) (ip6 + ip_hl); ip_frag_off = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK); ip_id = ntohl(ip6f->ip6f_ident); } inet_ntop(AF_INET6, &ip6->ip6_src, src.ip, sizeof(src.ip)); inet_ntop(AF_INET6, &ip6->ip6_dst, dst.ip, sizeof(dst.ip)); break; #endif default: return NULL; } // Fixup VSS trailer in ethernet packets *caplen = capinfo->link_hl + ip_len; // Remove IP Header length from payload *size = *caplen - capinfo->link_hl - ip_hl; // If no fragmentation if (ip_frag == 0) { // Just create a new packet with given network data pkt = packet_create(ip_ver, ip_proto, src, dst, ip_id); packet_add_frame(pkt, header, packet); return pkt; } // Look for another packet with same id in IP reassembly vector it = vector_iterator(capture_cfg.ip_reasm); while ((pkt = vector_iterator_next(&it))) { if (addressport_equals(pkt->src, src) && addressport_equals(pkt->dst, dst) && pkt->ip_id == ip_id) { break; } } // If we already have this packet stored, append this frames to existing one if (pkt) { packet_add_frame(pkt, header, packet); } else { // Add To the possible reassembly list pkt = packet_create(ip_ver, ip_proto, src, dst, ip_id); packet_add_frame(pkt, header, packet); vector_append(capture_cfg.ip_reasm, pkt); return NULL; } // If no more fragments if ((ip_off & IP_MF) == 0) { // TODO Dont check the flag, check the holes // Calculate assembled IP payload data it = vector_iterator(pkt->frames); while ((frame = vector_iterator_next(&it))) { struct ip *frame_ip = (struct ip *) (frame->data + capinfo->link_hl); len_data += frame->header->caplen - capinfo->link_hl - frame_ip->ip_hl * 4; } // Check packet content length if (len_data > MAX_CAPTURE_LEN) return NULL; // Initialize memory for the assembly packet memset(packet, 0, capinfo->link_hl + ip_hl + len_data); it = vector_iterator(pkt->frames); while ((frame = vector_iterator_next(&it))) { // Get IP header struct ip *frame_ip = (struct ip *) (frame->data + capinfo->link_hl); memcpy(packet + capinfo->link_hl + ip_hl + (ntohs(frame_ip->ip_off) & IP_OFFMASK) * 8, frame->data + capinfo->link_hl + frame_ip->ip_hl * 4, frame->header->caplen - capinfo->link_hl - frame_ip->ip_hl * 4); } *caplen = capinfo->link_hl + ip_hl + len_data; *size = len_data; // Return the assembled IP packet vector_remove(capture_cfg.ip_reasm, pkt); return pkt; } return NULL; }
packet_t * capture_eep_receive_v2() { uint8_t family, proto; unsigned char *payload = 0; uint32_t pos; char buffer[MAX_CAPTURE_LEN] ; //! Source Address address_t src; //! Destination address address_t dst; //! Packet header struct pcap_pkthdr header; //! New created packet pointer packet_t *pkt; //! EEP client data struct sockaddr eep_client; socklen_t eep_client_len; struct hep_hdr hdr; struct hep_timehdr hep_time; struct hep_iphdr hep_ipheader; #ifdef USE_IPV6 struct hep_ip6hdr hep_ip6header; #endif // Initialize buffer memset(buffer, 0, MAX_CAPTURE_LEN); /* Receive EEP generic header */ if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) return NULL; /* Copy initial bytes to HEPv2 header */ memcpy(&hdr, buffer, sizeof(struct hep_hdr)); // Check HEP version if (hdr.hp_v != 2) return NULL; /* IP proto */ family = hdr.hp_f; /* Proto ID */ proto = hdr.hp_p; pos = sizeof(struct hep_hdr); /* IPv4 */ if (family == AF_INET) { memcpy(&hep_ipheader, (void*) buffer + pos, sizeof(struct hep_iphdr)); inet_ntop(AF_INET, &hep_ipheader.hp_src, src.ip, sizeof(src.ip)); inet_ntop(AF_INET, &hep_ipheader.hp_dst, dst.ip, sizeof(dst.ip)); pos += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 /* IPv6 */ else if(family == AF_INET6) { memcpy(&hep_ip6header, (void*) buffer + pos, sizeof(struct hep_ip6hdr)); inet_ntop(AF_INET6, &hep_ip6header.hp6_src, src.ip, sizeof(src.ip)); inet_ntop(AF_INET6, &hep_ip6header.hp6_dst, dst.ip, sizeof(dst.ip)); pos += sizeof(struct hep_ip6hdr); } #endif /* PORTS */ src.port = ntohs(hdr.hp_sport); dst.port = ntohs(hdr.hp_dport); /* TIMESTAMP*/ memcpy(&hep_time, (void*) buffer + pos, sizeof(struct hep_timehdr)); pos += sizeof(struct hep_timehdr); header.ts.tv_sec = hep_time.tv_sec; header.ts.tv_usec = hep_time.tv_usec; /* Protocol TYPE */ /* Capture ID */ // Calculate payload size (Total size - headers size) header.caplen = header.len = ntohs(hdr.hp_l) - pos; // Copy packet payload payload = sng_malloc(header.caplen + 1); memcpy(payload, (void*) buffer + pos, header.caplen); // Create a new packet pkt = packet_create((family == AF_INET) ? 4 : 6, proto, src, dst, 0); packet_add_frame(pkt, &header, payload); packet_set_transport_data(pkt, src.port, dst.port); packet_set_type(pkt, PACKET_SIP_UDP); packet_set_payload(pkt, payload, header.caplen); /* FREE */ sng_free(payload); return pkt; }