Thread: packet decoder in C

  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.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Read this: Announcements - General Programming Boards.

    Fix your post to use code tags, and make sure your code is properly indented: SourceForge.net: Indentation - cpwiki.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    So what is your question?

    I see boilerplate code with comments like "insert your code in this routine" and not a lot of apparent effort on your part.

    > 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?
    Why don't you try it first and see?
    Compare with wireshark for reference.

    Maybe the mistakes (if there are any) are deliberate, so as to see who is paying attention and stimulate some learning.
    For sure, you won't learn about networking and protocols if all you have to do is add printf() statements.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

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