/**************************************************************************** ** 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; }
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); } }