int capture_online(const char *dev, const char *outfile) { capture_info_t *capinfo; //! Error string char errbuf[PCAP_ERRBUF_SIZE]; // Set capture mode capture_cfg.status = CAPTURE_ONLINE; // Create a new structure to handle this capture source if (!(capinfo = sng_malloc(sizeof(capture_info_t)))) { fprintf(stderr, "Can't allocate memory for capture data!\n"); return 1; } // Try to find capture device information if (pcap_lookupnet(dev, &capinfo->net, &capinfo->mask, errbuf) == -1) { fprintf(stderr, "Can't get netmask for device %s\n", dev); capinfo->net = 0; capinfo->mask = 0; return 2; } // Open capture device capinfo->handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); if (capinfo->handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); return 2; } // Store capture device capinfo->device = dev; // Get datalink to parse packets correctly capinfo->link = pcap_datalink(capinfo->handle); // Check linktypes sngrep knowns before start parsing packets if ((capinfo->link_hl = datalink_size(capinfo->link)) == -1) { fprintf(stderr, "Unable to handle linktype %d\n", capinfo->link); return 3; } // Add this capture information as packet source vector_append(capture_cfg.sources, capinfo); // If requested store packets in a dump file if (outfile && !capture_cfg.pd) { if ((capture_cfg.pd = dump_open(outfile)) == NULL) { fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, pcap_geterr(capinfo->handle)); return 2; } } return 0; }
int capture_offline(const char *infile, const char *outfile) { capture_info_t *capinfo; // Error text (in case of file open error) char errbuf[PCAP_ERRBUF_SIZE]; // Set capture mode capture_cfg.status = CAPTURE_OFFLINE_LOADING; // Create a new structure to handle this capture source if (!(capinfo = sng_malloc(sizeof(capture_info_t)))) { fprintf(stderr, "Can't allocate memory for capture data!\n"); return 1; } // Set capture input file capinfo->infile = infile; // Open PCAP file if ((capinfo->handle = pcap_open_offline(infile, errbuf)) == NULL) { fprintf(stderr, "Couldn't open pcap file %s: %s\n", infile, errbuf); return 1; } // Get datalink to parse packets correctly capinfo->link = pcap_datalink(capinfo->handle); // Check linktypes sngrep knowns before start parsing packets if ((capinfo->link_hl = datalink_size(capinfo->link)) == -1) { fprintf(stderr, "Unable to handle linktype %d\n", capinfo->link); return 3; } // Add this capture information as packet source vector_append(capture_cfg.sources, capinfo); // If requested store packets in a dump file if (outfile && !capture_cfg.pd) { if ((capture_cfg.pd = dump_open(outfile)) == NULL) { fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, pcap_geterr(capinfo->handle)); return 2; } } return 0; }
int capture_online(const char *dev, const char *outfile) { //! Error string char errbuf[PCAP_ERRBUF_SIZE]; // Set capture mode capinfo.status = CAPTURE_ONLINE; // Try to find capture device information if (pcap_lookupnet(dev, &capinfo.net, &capinfo.mask, errbuf) == -1) { fprintf(stderr, "Can't get netmask for device %s\n", dev); capinfo.net = 0; capinfo.mask = 0; } // Open capture device capinfo.handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); if (capinfo.handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); return 2; } // If requested store packets in a dump file if (outfile) { if ((capinfo.pd = dump_open(outfile)) == NULL) { fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, pcap_geterr(capinfo.handle)); return 2; } } // Get datalink to parse packets correctly capinfo.link = pcap_datalink(capinfo.handle); // Check linktypes sngrep knowns before start parsing packets if ((capinfo.link_hl = datalink_size(capinfo.link)) == -1) { fprintf(stderr, "Unable to handle linktype %d\n", capinfo.link); return 3; } // Get Local devices addresses pcap_findalldevs(&capinfo.devices, errbuf); return 0; }
int capture_offline(const char *infile, const char *outfile) { // Error text (in case of file open error) char errbuf[PCAP_ERRBUF_SIZE]; // Set capture mode capinfo.status = CAPTURE_OFFLINE_LOADING; // Set capture input file capinfo.infile = infile; // Open PCAP file if ((capinfo.handle = pcap_open_offline(infile, errbuf)) == NULL) { fprintf(stderr, "Couldn't open pcap file %s: %s\n", infile, errbuf); return 1; } // If requested store packets in a dump file if (outfile) { if ((capinfo.pd = dump_open(outfile)) == NULL) { fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, pcap_geterr(capinfo.handle)); return 2; } } // Get datalink to parse packets correctly capinfo.link = pcap_datalink(capinfo.handle); // Check linktypes sngrep knowns before start parsing packets if ((capinfo.link_hl = datalink_size(capinfo.link)) == -1) { fprintf(stderr, "Unable to handle linktype %d\n", capinfo.link); return 3; } return 0; }
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); }