Esempio n. 1
0
/****************************************************************************
 ** 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;
}
Esempio n. 2
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;
}
Esempio n. 3
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);
}
Esempio n. 4
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);
    }
}
Esempio n. 5
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);

}