/**************************************************************************** ** Current version of sngrep launches a thread that execs original ngrep ** binary. sngrep was born with the idea of parsing ngrep output. ** This could be changed with a bit of effort to a network capturing thread ** using libpcap functions, but we'll keep this way for now. ** ** Also, take into account that as a parser, we expect ngrep header in an ** expecific format that is obtained using ngrep arguments -qpt which are ** forced by the exec process. ** ** U DD/MM/YY hh:mm:ss.uuuuuu fff.fff.fff.fff:pppp -> fff.fff.fff.fff:pppp ** ** If any other parameters are supplied to sngrep that changes this header ** (let's say -T), sngrep will fail at parsing any header :( ** ****************************************************************************/ int online_capture(void *pargv) { char **argv = (char**) pargv; int argc = 1; char cmdline[512]; FILE *fp; char stdout_line[2048] = ""; char msg_header[256], msg_payload[20480]; // Build the commald line to execute ngrep memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline, "%s %s %s %s", STDBUF_BIN, STDBUF_ARGS, NGREP_BIN, NGREP_ARGS); // Add save to temporal file (if option enabled) if (!is_option_disabled("sngrep.tmpfile")) sprintf(cmdline + strlen(cmdline), " -O %s", get_option_value("sngrep.tmpfile")); while (argv[argc]){ if (strchr(argv[argc], ' ')) { sprintf(cmdline + strlen(cmdline), " \"%s\"", argv[argc++]); } else { sprintf(cmdline + strlen(cmdline), " %s", argv[argc++]); } } // Open the command for reading. fp = popen(cmdline, "r"); if (fp == NULL) { printf("Failed to run command\n"); return 1; } // Read the output a line at a time - output it. while (fgets(stdout_line, 1024, fp) != NULL) { if (!strncmp(stdout_line, "\n", 1) && strlen(msg_header) && strlen(msg_payload)) { // Parse message struct sip_msg *msg; if ((msg = sip_load_message(msg_header, strdup((const char*) msg_payload)))) { // Update the ui ui_new_msg_refresh(msg); } // Initialize structures strcpy(msg_header, ""); strcpy(msg_payload, ""); } else { if (!strncmp(stdout_line, "U ", 2)) { strcpy(msg_header, stdout_line); } else { if (strlen(msg_header)) { strcat(msg_payload, stdout_line); } } } } // Close read pipe pclose(fp); return 0; }
int load_from_file(const char* file) { char cmdline[256]; FILE *fp; char stdout_line[2048] = ""; char msg_header[256], msg_payload[20480]; // Build the commald line to execute ngrep sprintf(cmdline, "%s %s %s %s -I %s", STDBUF_BIN, STDBUF_ARGS, NGREP_BIN, NGREP_ARGS, file); // Open the command for reading. fp = popen(cmdline, "r"); if (fp == NULL) { printf("Failed to run command\n"); return 1; } // Read the output a line at a time - output it. while (fgets(stdout_line, 1024, fp) != NULL) { if (!strncmp(stdout_line, "\n", 1) && strlen(msg_header) && strlen(msg_payload)) { // Parse message sip_load_message(msg_header, strdup((const char*) msg_payload)); // Initialize structures memset(msg_header, 0, 256); memset(msg_payload, 0, 20480); } else { if (!strncmp(stdout_line, "U ", 2)) { strcpy(msg_header, stdout_line); } else { if (strlen(msg_header)) { strcat(msg_payload, stdout_line); } } } } // Close read pipe pclose(fp); return 0; }
void parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packet) { // IP header data struct ip *ip4; #ifdef WITH_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 uint32_t ip_off = 0; // Fragmentation flag uint8_t ip_frag = 0; // Fragmentation offset uint16_t ip_frag_off = 0; //! Source Address char ip_src[ADDRESSLEN]; //! Destination Address char ip_dst[ADDRESSLEN]; // Source and Destination Ports u_short sport, dport; // UDP header data struct udphdr *udp; // UDP header size uint16_t udp_off; // TCP header data struct tcphdr *tcp; // TCP header size uint16_t tcp_off; // Packet payload data u_char *payload = NULL; // Packet payload size uint32_t size_payload = header->caplen; // SIP message transport int transport; // Media structure for RTP packets rtp_stream_t *stream; // Captured packet info capture_packet_t *pkt; // Ignore packets while capture is paused if (capture_is_paused()) return; // Check if we have reached capture limit if (capinfo.limit && sip_calls_count() >= capinfo.limit) return; // Get IP header ip4 = (struct ip *) (packet + capinfo.link_hl); #ifdef WITH_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_frag = ip_off & (IP_MF | IP_OFFMASK); ip_frag_off = (ip_frag) ? (ip_off & IP_OFFMASK) * 8 : 0; // TODO Get fragment information inet_ntop(AF_INET, &ip4->ip_src, ip_src, sizeof(ip_src)); inet_ntop(AF_INET, &ip4->ip_dst, ip_dst, sizeof(ip_dst)); break; #ifdef WITH_IPV6 case 6: ip_hl = sizeof(struct ip6_hdr); ip_proto = ip6->ip6_nxt; 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); // TODO Get fragment information } inet_ntop(AF_INET6, &ip6->ip6_src, ip_src, sizeof(ip_src)); inet_ntop(AF_INET6, &ip6->ip6_dst, ip_dst, sizeof(ip_dst)); break; #endif default: return; } // Only interested in UDP packets if (ip_proto == IPPROTO_UDP) { // Get UDP header udp = (struct udphdr *)((u_char *)(ip4) + ip_hl); udp_off = (ip_frag_off) ? 0 : sizeof(struct udphdr); // Set packet ports sport = htons(udp->uh_sport); dport = htons(udp->uh_dport); // Get actual payload size size_payload -= capinfo.link_hl + ip_hl + udp_off; #ifdef WITH_IPV6 if (ip_ver == 6) size_payload -= ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); #endif // Get payload start payload = (u_char *) (udp) + udp_off; // Set transport UDP transport = CAPTURE_PACKET_SIP_UDP; } else if (ip_proto == IPPROTO_TCP) { // Get TCP header tcp = (struct tcphdr *)((u_char *)(ip4 )+ ip_hl); tcp_off = (ip_frag_off) ? 0 : (tcp->th_off * 4); // Set packet ports sport = htons(tcp->th_sport); dport = htons(tcp->th_dport); // Get actual payload size size_payload -= capinfo.link_hl + ip_hl + tcp_off; #ifdef WITH_IPV6 if (ip_ver == 6) size_payload -= ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); #endif // Get payload start payload = (u_char *)(tcp) + tcp_off; // Set transport TCP transport = CAPTURE_PACKET_SIP_TCP; } else { // Not handled protocol return; } if ((int32_t)size_payload < 0) size_payload = 0; // Create a structure for this captured packet pkt = capture_packet_create(header, packet, header->caplen); capture_packet_set_type(pkt, transport); // For TCP and UDP, use payload directly from the packet capture_packet_set_payload(pkt, NULL, size_payload); #ifdef WITH_OPENSSL // Check if packet is TLS if (capinfo.keyfile && transport == CAPTURE_PACKET_SIP_TCP) tls_process_segment(ip4, pkt); #endif // Check if packet is WS or WSS if (transport == CAPTURE_PACKET_SIP_TCP) capture_ws_check_packet(pkt); // We're only interested in packets with payload if (capture_packet_get_payload_len(pkt)) { // Parse this header and payload if (sip_load_message(pkt, ip_src, sport, ip_dst, dport)) { // Store this packets in output file dump_packet(capinfo.pd, header, packet); return; } // Check if this packet belongs to a RTP stream // TODO Store this packet in the stream if ((stream = rtp_check_stream(pkt, ip_src, sport, ip_dst, dport))) { // We have an RTP packet! capture_packet_set_type(pkt, CAPTURE_PACKET_RTP); // Store this pacekt if capture rtp is enabled if (capinfo.rtp_capture) { call_add_rtp_packet(stream_get_call(stream), pkt); } else { capture_packet_destroy(pkt); } // Store this packets in output file dump_packet(capinfo.pd, header, packet); return; } } // Not an interesting packet ... capture_packet_destroy(pkt); }
void parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packet) { // Datalink Header size int size_link; // Ethernet header data struct ether_header *eptr; // Ethernet header type u_short ether_type; // IP header data struct nread_ip *ip; // IP header size int size_ip; // UDP header data struct nread_udp *udp; // XXX Fake header (Like the one from ngrep) char msg_header[256]; // Packet payload data u_char *msg_payload; // Packet payload size int size_payload; // Parsed message data sip_msg_t *msg; // Get link header size from datalink type if (linktype == DLT_EN10MB) { eptr = (struct ether_header *) packet; if ((ether_type = ntohs(eptr->ether_type)) != ETHERTYPE_IP) return; size_link = SIZE_ETHERNET; } else if (linktype == DLT_LINUX_SLL) { size_link = SLL_HDR_LEN; } else if (linktype == DLT_NULL) { size_link = DLT_RAW; } else { // Something we are not prepared to parse :( fprintf(stderr, "Error handing linktype %d\n", linktype); return; } // Get IP header ip = (struct nread_ip*) (packet + size_link); size_ip = IP_HL(ip) * 4; // Only interested in UDP packets if (ip->ip_p != IPPROTO_UDP) return; // Get UDP header udp = (struct nread_udp*) (packet + size_link + size_ip); // Get package payload msg_payload = (u_char *) (packet + size_link + size_ip + SIZE_UDP); size_payload = htons(udp->udp_hlen) - SIZE_UDP; msg_payload[size_payload] = '\0'; // XXX Process timestamp struct timeval ut_tv = header->ts; time_t t = (time_t) ut_tv.tv_sec; // XXX Get current time char timestr[200]; struct tm *time = localtime(&t); strftime(timestr, sizeof(timestr), "%Y/%m/%d %T", time); // XXX Build a header string sprintf(msg_header, "U %s.%06ld", timestr, ut_tv.tv_usec); sprintf(msg_header, "%s %s:%u", msg_header, inet_ntoa(ip->ip_src), htons(udp->udp_sport)); sprintf(msg_header, "%s -> %s:%u", msg_header, inet_ntoa(ip->ip_dst), htons(udp->udp_dport)); // Parse this header and payload if ((msg = sip_load_message(msg_header, (const char*) msg_payload)) && !strcasecmp((const char*)mode, "Online") ) { ui_new_msg_refresh(msg); } }
void parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packet) { // Datalink Header size int size_link; // IP version uint32_t ip_ver; // IP header data struct ip *ip4; #ifdef WITH_IPV6 // IPv6 header data struct ip6_hdr *ip6; #endif // IP protocol uint8_t ip_proto; // IP segment length uint32_t ip_len; // IP header size uint32_t size_ip; // Fragment offset uint16_t ip_off = 0; // Fragmentation flag uint8_t ip_frag = 0; // Fragmentation offset uint16_t ip_frag_off = 0; //! Source Address char ip_src[INET6_ADDRSTRLEN + 1]; //! Destination Address char ip_dst[INET6_ADDRSTRLEN + 1]; // UDP header data struct udphdr *udp; // UDP header size uint16_t udp_size; // TCP header data struct tcphdr *tcp; // TCP header size uint16_t tcp_size; // Packet payload data u_char *msg_payload = NULL; // Packet payload size uint32_t size_payload; // Parsed message data sip_msg_t *msg; // Total packet size uint32_t size_packet; // SIP message transport int transport; /* 0 UDP, 1 TCP, 2 TLS */ // Source and Destination Ports u_short sport, dport; // Ignore packets while capture is paused if (capture_is_paused()) return; // Check if we have reached capture limit if (capinfo.limit && sip_calls_count() >= capinfo.limit) return; // Get link header size from datalink type size_link = datalink_size(capinfo.link); // Get IP header ip4 = (struct ip*) (packet + size_link); #ifdef WITH_IPV6 // Get IPv6 header ip6 = (struct ip6_hdr*)(packet + size_link); #endif // Get IP version ip_ver = ip4->ip_v; switch(ip_ver) { case 4: size_ip = ip4->ip_hl * 4; ip_proto = ip4->ip_p; ip_len = ntohs(ip4->ip_len); inet_ntop(AF_INET, &ip4->ip_src, ip_src, sizeof(ip_src)); inet_ntop(AF_INET, &ip4->ip_dst, ip_dst, sizeof(ip_dst)); ip_off = ntohs(ip4->ip_off); ip_frag = ip_off & (IP_MF | IP_OFFMASK); ip_frag_off = (ip_frag) ? (ip_off & IP_OFFMASK) * 8 : 0; break; #ifdef WITH_IPV6 case 6: size_ip = sizeof(struct ip6_hdr); ip_proto = ip6->ip6_nxt; ip_len = ntohs(ip6->ip6_plen); inet_ntop(AF_INET6, &ip6->ip6_src, ip_src, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &ip6->ip6_dst, ip_dst, INET6_ADDRSTRLEN); if (ip_proto == IPPROTO_FRAGMENT) { struct ip6_frag *ip6f = (struct ip6_frag *) (ip6 + ip_len); ip_frag_off = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK); } break; #endif default: return; } // Only interested in UDP packets if (ip_proto == IPPROTO_UDP) { // Set transport UDP transport = 0; // Get UDP header udp = (struct udphdr*) (packet + size_link + size_ip); udp_size = (ip_frag_off) ? 0 : sizeof(struct udphdr); // Set packet ports sport = udp->uh_sport; dport = udp->uh_dport; size_payload = htons(udp->uh_ulen) - udp_size; if ((int32_t)size_payload > 0 ) { // Get packet payload msg_payload = malloc(size_payload + 1); memset(msg_payload, 0, size_payload + 1); memcpy(msg_payload, (u_char *) (packet + size_link + size_ip + udp_size), size_payload); } // Total packet size size_packet = size_link + size_ip + udp_size + size_payload; } else if (ip_proto == IPPROTO_TCP) { // Set transport TCP transport = 1; tcp = (struct tcphdr*) (packet + size_link + size_ip); tcp_size = (ip_frag_off) ? 0 : (tcp->th_off * 4); // Set packet ports sport = tcp->th_sport; dport = tcp->th_dport; // We're only interested in packets with payload size_payload = ip_len - (size_ip + tcp_size); if ((int32_t)size_payload > 0) { // Get packet payload msg_payload = malloc(size_payload + 1); memset(msg_payload, 0, size_payload + 1); memcpy(msg_payload, (u_char *) (packet + size_link + size_ip + tcp_size), size_payload); } // Total packet size size_packet = size_link + size_ip + tcp_size + size_payload; #ifdef WITH_OPENSSL if (!msg_payload || !strstr((const char*) msg_payload, "SIP/2.0")) { if (capture_get_keyfile()) { // Allocate memory for the payload msg_payload = malloc(size_payload + 1); memset(msg_payload, 0, size_payload + 1); // Try to decrypt the packet tls_process_segment(ip4, &msg_payload, &size_payload); // Check if we have decoded payload if (size_payload <= 0) free(msg_payload); // Set Transport TLS transport = 2; } } #endif } else { // Not handled protocol return; } // Increase capture stats if (ip4->ip_v == 4 && capinfo.devices) { if(is_local_address(ip4->ip_src.s_addr)) { capinfo.local_ports[htons(sport)]++; capinfo.remote_ports[htons(dport)]++; } else { capinfo.remote_ports[htons(sport)]++; capinfo.local_ports[htons(dport)]++; } } // We're only interested in packets with payload if (size_payload <= 0) return; // Parse this header and payload msg = sip_load_message(header, ip_src, sport, ip_dst, dport, msg_payload); free(msg_payload); // This is not a sip message, Bye! if (!msg) return; // Store Transport attribute if (transport == 0) { msg_set_attribute(msg, SIP_ATTR_TRANSPORT, "UDP"); } else if (transport == 1) { msg_set_attribute(msg, SIP_ATTR_TRANSPORT, "TCP"); } else if (transport == 2) { msg_set_attribute(msg, SIP_ATTR_TRANSPORT, "TLS"); } // Set message PCAP data msg->pcap_packet = malloc(size_packet); memcpy(msg->pcap_packet, packet, size_packet); // Store this packets in output file dump_packet(capinfo.pd, header, packet); }