Thread: packet decoder in C

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Jun 2012
    Posts
    1

    packet decoder in C

    This is a homework assignment, and I have to extract Ethernet data from the packet . also I should count tne number of different protocols.
    I uploaded the whole program . I appreciate if anybody can help me.
    I saw similar code on this site.
    Do yu think this code is correct , because Eternet header has 8 byte preamle so destination addr should be p[8] not p[0] . Am I right?

    here is the code:

    #define RETSIGTYPE void
    #include <sys/types.h>
    #include <sys/time.h>
    #include <netinet/in.h>
    #include <pcap.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>


    #ifndef setsignal_h
    #define setsignal_h


    RETSIGTYPE (*setsignal(int, RETSIGTYPE (*)(int)))(int);
    #endif


    char cpre580f98[] = "netdump";


    void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p);


    int packettype;


    char *program_name;


    /* Externs */
    extern void bpf_dump(struct bpf_program *, int);


    extern char *copy_argv(char **);


    /* Forwards */
    void program_ending(int);


    /* Length of saved portion of packet. */
    int snaplen = 1500;;


    static pcap_t *pd;


    extern int optind;
    extern int opterr;
    extern char *optarg;
    int pflag = 0, aflag = 0;


    int
    main(int argc, char **argv)
    {
    int cnt, op, i, done = 0;
    bpf_u_int32 localnet, netmask;
    char *cp, *cmdbuf, *device;
    struct bpf_program fcode;
    void (*oldhandler)(int);
    u_char *pcap_userdata;
    char ebuf[PCAP_ERRBUF_SIZE];


    cnt = -1;
    device = NULL;

    if ((cp = strrchr(argv[0], '/')) != NULL)
    program_name = cp + 1;
    else
    program_name = argv[0];


    opterr = 0;
    while ((i = getopt(argc, argv, "pa")) != -1)
    {
    switch (i)
    {
    case 'p':
    pflag = 1;
    break;
    case 'a':
    aflag = 1;
    break;
    case '?':
    default:
    done = 1;
    break;
    }
    if (done) break;
    }
    if (argc > (optind)) cmdbuf = copy_argv(&argv[optind]);
    else cmdbuf = "";


    if (device == NULL) {
    device = pcap_lookupdev(ebuf);
    if (device == NULL)
    error("%s", ebuf);
    }
    pd = pcap_open_live(device, snaplen, 1, 1000, ebuf);
    if (pd == NULL)
    error("%s", ebuf);
    i = pcap_snapshot(pd);
    if (snaplen < i) {
    warning("snaplen raised from %d to %d", snaplen, i);
    snaplen = i;
    }
    if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
    localnet = 0;
    netmask = 0;
    warning("%s", ebuf);
    }
    /*
    * Let user own process after socket has been opened.
    */
    setuid(getuid());


    if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
    error("%s", pcap_geterr(pd));

    (void)setsignal(SIGTERM, program_ending);
    (void)setsignal(SIGINT, program_ending);
    /* Cooperate with nohup(1) */
    if ((oldhandler = setsignal(SIGHUP, program_ending)) != SIG_DFL)
    (void)setsignal(SIGHUP, oldhandler);


    if (pcap_setfilter(pd, &fcode) < 0)
    error("%s", pcap_geterr(pd));
    pcap_userdata = 0;
    (void)fprintf(stderr, "%s: listening on %s\n", program_name, device);
    if (pcap_loop(pd, cnt, raw_print, pcap_userdata) < 0) {
    (void)fprintf(stderr, "%s: pcap_loop: %s\n",
    program_name, pcap_geterr(pd));
    exit(1);
    }
    pcap_close(pd);
    exit(0);
    }


    /* routine is executed on exit */
    // this subroutin print total number of packets we should add number of IP packets, number of ARP and number of broadcast
    // ctrIP, ctrARP, ctrBCAST
    // initialize these at the begining of program as global var and to zero
    void program_ending(int signo)
    {
    struct pcap_stat stat;


    if (pd != NULL && pcap_file(pd) == NULL) {
    (void)fflush(stdout);
    putc('\n', stderr);
    if (pcap_stats(pd, &stat) < 0)
    (void)fprintf(stderr, "pcap_stats: %s\n",
    pcap_geterr(pd));
    else {
    (void)fprintf(stderr, "%d packets received by filter\n",
    stat.ps_recv);
    (void)fprintf(stderr, "%d packets dropped by kernel\n",
    stat.ps_drop);
    }
    }
    exit(0);
    }


    /* Like default_print() but data need not be aligned */
    void
    default_print_unaligned(register const u_char *cp, register u_int length)
    {
    register u_int i, s;
    register int nshorts;


    nshorts = (u_int) length / sizeof(u_short);
    i = 0;
    while (--nshorts >= 0) {
    if ((i++ % 8) == 0)
    (void)printf("\n\t\t\t");
    s = *cp++;
    (void)printf(" %02x%02x", s, *cp++);
    }
    if (length & 1) {
    if ((i % 8) == 0)
    (void)printf("\n\t\t\t");
    (void)printf(" %02x", *cp);
    }
    }


    /*
    * By default, print the packet out in hex.
    */
    void
    default_print(register const u_char *bp, register u_int length)
    {
    register const u_short *sp;
    register u_int i;
    register int nshorts;


    if ((long)bp & 1) {
    default_print_unaligned(bp, length);
    return;
    }
    sp = (u_short *)bp;
    nshorts = (u_int) length / sizeof(u_short);
    i = 0;
    while (--nshorts >= 0) {
    if ((i++ % 8) == 0)
    (void)printf("\n\t");
    (void)printf(" %04x", ntohs(*sp++));
    }
    if (length & 1) {
    if ((i % 8) == 0)
    (void)printf("\n\t");
    (void)printf(" %02x", *(u_char *)sp);
    }
    }


    /*
    insert your code in this routine


    */
    void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
    { {
    u_int length = h->len;
    u_int caplen = h->caplen;


    /* At this point we start extracting data from the packet, with the var idx keeping up with where we are in the packet */


    // Print total packet size
    printf("\nPacket Length\t%d bytes", h->len);


    // Decode Ethernet (Layer 2) Header Info
    int idx; // counter variable for indexing through packet
    char eth_destination[6]; // var to store the ethernet destination address
    char eth_source[6]; // var to store the ethernet source address
    short eth_type; // var to store the ethernet type value
    char eth_payload[10]; // string array to store payload description
    char eth_bcast[6] = "0xFF";


    // Extract Ethernet Destination Address (1st 6 bytes)
    for ( idx = 0; idx < 6; idx++)
    {
    eth_destination[idx] = p[idx];
    }
    // Extract Ethernet Source Address (2nd 6 bytes)
    for ( idx = 6; idx < 12; idx++)
    {
    eth_source[idx-6] = p[idx];
    }
    // Combine two byte Ethernet Type/Length field into one value
    eth_type = p[12] * 256 + p[13];
    // Check the packet type and increment related counter
    if ( eth_type >= 0x600) {
    switch ( eth_type )
    {
    case 0x800: // Check to see if the type indicates that the packet is IP
    ctrIP++;
    strcpy(eth_payload, "IP");
    break;
    case 0x806: // Check to see if the type indicates that the packet is ARP
    ctrARP++;
    strcpy(eth_payload, "ARP");
    break;
    default:
    break;
    }
    }
    // Check to see if the destination was a broadcast packet and increment related counter
    /*
    if ((eth_destination[0] == 0xFF ) && (eth_destination[1] == 0xFF ) && (eth_destination[2] == 0xFF ) && (eth_destination[3] == 0xFF ) && (eth_destination[4] == 0xFF ) && (eth_destination[5] == 0xFF )) {
    ctrBCAST++;
    }
    */


    // Print Ethernet (Layer 2) Header Info
    printf("Layer\tField\tValue\n");
    printf("ETHERNET\tDestination\t%02x:%02x:%02x:%02x :%02x:%02x\n", eth_destination[0],eth_destination[1],eth_destination[2],eth_destination[3],eth_destination[4],eth_destination[5]);
    printf("\t\tSource\t%02x:%02x:%02x:%02x:%02x:%02x\ n", eth_source[0],eth_source[1],eth_source[2],eth_source[3],eth_source[4],eth_source[5]);
    printf("\t\tType\t0x%02x\n", eth_type);
    printf("\t\tPayload\t%s\n", eth_payload);


    // All packets will have ethernet info (decoded and printed above).
    // At this point we have to determine what kind of data is at the next layer up (layer 3) and decode/print the data accordingly.
    // This is done based on the eth_type variable.
    if ( eth_type >= 0x600) {
    switch ( eth_type )
    {
    case 0x800: // IP Packet
    // insert code to decode and print IP (should this be a separate sub-routine?
    break;
    case 0x806: // ARP Packet
    // insert code to decode and print ARP
    break;
    default:
    break;
    }
    }
    exit(0);
    }
    Attached Files Attached Files
    Last edited by eshoja; 06-05-2012 at 11:32 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with a resistor decoder
    By usernameisvalid in forum C Programming
    Replies: 5
    Last Post: 06-25-2011, 05:21 PM
  2. Writing a packet decoder in C
    By bosque in forum C Programming
    Replies: 4
    Last Post: 04-25-2011, 11:29 AM
  3. Mpeg2 decoder
    By thangdc01_02 in forum C Programming
    Replies: 6
    Last Post: 11-21-2010, 04:09 PM
  4. decoder
    By jalenamichelle in forum C++ Programming
    Replies: 1
    Last Post: 11-03-2010, 06:24 AM
  5. MP3 Decoder
    By Pete in forum Projects and Job Recruitment
    Replies: 4
    Last Post: 05-02-2005, 08:35 AM