The IP Protocol injected, inspected, detected, infected - Part I

Programmers that deal with networks and TCP/IP, sometimes want or need to do the following nasty things to or with the protocol:

Today we will look at several tools that may be used to do the above, On a Linux system. Some of these tools are available on other platforms - some not.

Note: we will not cover the topics in the order stated above - it was there just because of a song...

IP Inspection - The little sniffer that could

Using Ethereal - Starting A Capture Session

Viewing The Captured Packets

Using Display Filters

Tethereal And Capture Files

Ethereal - Behind The Scenes

IP Detection with libpcap - The Packet Capturing Library

Basic Work With libpcap - The main Function

#include <pcap.h>

/* for some error messages. */
char err_buf[PCAP_ERRBUF_SIZE];
int rc;

/* open the device for capturing - read first 40 bytes of each packet. */
pcap_t* pc = pcap_open_live("ppp0", 40, 0 /* not promiscuous */,
                            50 /* read timeout, in milli-seconds. */
                            err_buf);
if (!pc) {
    fprintf(stderr, "error in pcap_open_line: %s\n", err_buf);
    exit(1);
}

/* capture 10 packets. 'pcap_packet_cb' is our per-packet callback.         */
/* 'pc' will be passed to the callback, along with the packet, for context. */
rc = pcap_loop(pc, 10, pcap_packet_cb, (u_char*)pc);
if (rc == -1)
    pcap_error(pc, "pcap failed:");

/* cleanup - close the device. */
pcap_close(pc);

Basic Work With libpcap - The Callback Function

#include <pcap.h>

/* A callback function invoked for each captured packet. */
void pcap_packet_cb(u_char* uparam,
                    const struct pcap_pkthdr* hdr,
                    const u_char* p_data)    /* <-- the actual packet's data. */
{
    /* we passed this to pcap_loop() */
    pcap_t* pc = (pcap_t*)uparam;
    struct pcap_stat ps;

    /* we'll just collect packet counts for now. */
    int rc = pcap_stats(pc, &ps);
    if (rc == -1)
        pcap_perror(pc, "");
    else
        printf("packets captured: %u, packets dropped: %u\n",
               ps.ps_recv, ps.ps_drop);
}

Basic Work With libpcap - Printing The Raw Data

#include <pcap.h>

/* A callback function invoked for each captured packet. */
void pcap_packet_cb(u_char* uparam,
                    const struct pcap_pkthdr* hdr,
                    const u_char* p_data)    /* <-- the actual packet's data. */
{
    int i;
    static int packet_count = 0;

    /* increase the packet's counter. */
    packet_count++;

    /* lets dump the packet's data on screen.            */
    /* we print as many bytes as were actually captured. */
    printf("PACKET %d:\n", packet_count);
    for (i = 0; i < hdr->caplen; ++i) {
        printf(" 0x%x", *(p_data+i));
    }
    printf("\n\n");
}

Basic Work With libpcap - Protocol Parsing

Basic Work With libpcap - Understanding The IP header

Basic Work With libpcap - Understanding The TCP header

Basic Work With libpcap - Protocol Parsing - Useful Include Files

#include <sys/types.h>    /* \                                 */
#include <sys/socket.h>   /*  > for inet_ntop and its friends. */
#include <arpa/inet.h>    /* /                                 */
#include <netinet/ip.h>   /* to parse IP headers.  */
#include <netinet/tcp.h>  /* to parse TCP headers. */

Basic Work With libpcap - Protocol Parsing - The Callback Function's Code

Here is a code to print the source/destination data for TCP traffic. */
static int packet_count = 0;
struct iphdr* ip_hdr;          /* to get IP protocol data.  */
struct tcphdr* tcp_hdr;        /* to get TCP protocol data. */
char src_ip[100], dst_ip[100];
int src_port, dst_port;

/* we're only interested in TCP packets. */
ip_hdr = (struct iphdr*)p_data;  /* the captured data is an IP packet. */
if (ip_hdr->protocol != IPPROTO_TCP) {
    printf("protocol in IP packet (0x%x) is not TCP\n", ip_hdr->protocol);
    return;
}

Basic Work With libpcap - Protocol Parsing - The Callback Function's Code (Cont.)

/* lets get the src and dst addresses - translate from */
/* network-byte-order binary data. */
inet_ntop(AF_INET, &ip_hdr->saddr, src_ip, sizeof(src_ip));
inet_ntop(AF_INET, &ip_hdr->daddr, dst_ip, sizeof(dst_ip));

/* lets get the port numbers - the payload of the IP packet is TCP.  */
/* NOTE: in IP, the ihl (IP Header Length) field contains the number */
/* of 4-octet chunks composing the IP packet's header.               */
tcp_hdr = (struct tcphdr*)(p_data + ip_hdr->ihl * 4);
src_port = ntohs(tcp_hdr->source);  /* ports are in network byte order. */
dst_port = ntohs(tcp_hdr->dest);

printf("PACKET: src %s:%d, dst %s:%d\n",
       src_ip, src_port, dst_ip, dst_port);

Identifying The Protocol Stack Dynamically

Using Filters

/* first we need to compile the filter.           */
/* Note: the filter requires knowing our netmask. */
bpf_u_int32 netmask;
inet_pton(AF_INET, "255.255.255.0", &netmask);

struct bpf_program filter;
char* filter_str = "port 22";
rc = pcap_compile(pc, &filter, filter_str, 1 /*optimize*/, netmask);
if (rc == -1) {
    fprintf(stderr, "Failed compiling filter '%s' - %s\n",
            filter_str, pcap_geterr(pc));
    exit(1);
}

/* then set this program as our filter. */
rc = pcap_setfilter(pc, &filter);
if (rc == -1) {
    fprintf(stderr, "Failed setting filter for pcap - %s\n",
            pcap_geterr(pc));
    exit(1);
}

/* after we're done with the filter struct - free it. */
pcap_freecode(&filter);
Originally written by Valid HTML 4.01!guy keren