int call_msg_is_retrans(sip_msg_t *msg) { sip_msg_t *prev = NULL; vector_iter_t it; // Get previous message in call with same origin and destination it = vector_iterator(msg->call->msgs); vector_iterator_set_current(&it, vector_index(msg->call->msgs, msg)); while ((prev = vector_iterator_prev(&it))) { if (addressport_equals(prev->packet->src, msg->packet->src) && addressport_equals(prev->packet->dst, msg->packet->dst)) break; } return (prev && !strcasecmp(msg_get_payload(msg), msg_get_payload(prev))); }
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_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; }