ARP packet network program

Discussion in 'C Programming' started by AngreGanon@gmail.com, Dec 15, 2007.

  1. Guest

    Hi all~
    I've written a network program in C.

    This program catputures ARP request packet and reply wrong ARP packet.
    Hi. I've written a small program to learn to write in C. But
    unfortunately the output is all jumbled up and not nice
    Caputuring is ok, but couldn't send ARP packet. What's wrong?

    ( using 2PC, this program run in Linux and moitoring other PC,Window
    XP)
    (generator packet prgram is BillSniff, monitoring program is
    WireShark)




    #include <sys/socket.h>
    #include <sys/ioctl.h>
    #include <sys/time.h>

    #include <asm/types.h>

    #include <math.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>

    #include <linux/if_packet.h>
    #include <linux/if_ether.h>
    #include <linux/if_arp.h>

    #define BUF_SIZE 42
    #define DEVICE "eth0"
    #define ETH_P_NULL 0x0
    #define ETH_MAC_LEN ETH_ALEN
    #define ETH_ARP 0x0806

    int s = 0; /*Socketdescriptor*/
    void* buffer = NULL;
    long total_packets = 0;
    long answered_packets = 0;

    void sigint(int signum);

    struct __attribute__((packed)) arp_header
    {
    unsigned short arp_hd;
    unsigned short arp_pr;
    unsigned char arp_hdl;
    unsigned char arp_prl;
    unsigned short arp_op;
    unsigned char arp_sha[6];
    unsigned char arp_spa[4];
    unsigned char arp_dha[6];
    unsigned char arp_dpa[4];
    };


    int main(void) {
    buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/
    unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/
    struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to
    ethernet header*/
    unsigned char* arphead = buffer + 14;
    struct arp_header *ah;


    unsigned char src_mac[6]; /*our MAC address*/

    struct ifreq ifr;
    struct sockaddr_ll socket_address;
    int ifindex = 0; /*Ethernet Interface index*/
    int i;
    int length; /*length of received packet*/
    int sent;

    printf("Server started, entering initialiation phase...\n");

    /*open socket*/
    s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (s == -1) {
    perror("socket():");
    exit(1);
    }
    printf("Successfully opened socket: %i\n", s);

    /*retrieve ethernet interface index*/
    strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ);
    if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
    perror("SIOCGIFINDEX");
    exit(1);
    }
    ifindex = ifr.ifr_ifindex;
    printf("Successfully got interface index: %i\n", ifindex);

    /*retrieve corresponding MAC*/
    if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
    perror("SIOCGIFINDEX");
    exit(1);
    }
    for (i = 0; i < 6; i++) {
    src_mac = ifr.ifr_hwaddr.sa_data;
    }
    printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:
    %02X\n",
    src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);

    /*prepare sockaddr_ll*/
    socket_address.sll_family = PF_PACKET;
    socket_address.sll_protocol = htons(ETH_P_IP);
    socket_address.sll_ifindex = ifindex;
    socket_address.sll_hatype = ARPHRD_ETHER;
    socket_address.sll_pkttype = PACKET_OTHERHOST;
    socket_address.sll_halen = ETH_ALEN;
    socket_address.sll_addr[6] = 0x00;
    socket_address.sll_addr[7] = 0x00;


    /*establish signal handler*/
    signal(SIGINT, sigint);
    printf("Successfully established signal handler for SIGINT\n");

    printf("We are in production state, waiting for incoming packets....
    \n");

    while (1) {
    /*Wait for incoming packet...*/
    length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL);
    if (length == -1)
    {
    perror("recvfrom():");
    exit(1);
    }


    if(htons(eh->h_proto) == 0x806)
    {

    unsigned char buf_arp_dha[6];
    unsigned char buf_arp_dpa[4];

    ah = (struct arp_header *)arphead;
    if(htons(ah->arp_op) != 0x0001)
    continue;

    printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr);
    printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl);
    printf("OPERATION : %x \n", ah->arp_op);
    printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    ah->arp_sha[0],
    ah->arp_sha[1],
    ah->arp_sha[2],
    ah->arp_sha[3],
    ah->arp_sha[4],
    ah->arp_sha[5]
    );
    printf("SENDER IP address: %02d:%02d:%02d:%02d\n",
    ah->arp_spa[0],
    ah->arp_spa[1],
    ah->arp_spa[2],
    ah->arp_spa[3]
    );
    printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    ah->arp_dha[0],
    ah->arp_dha[1],
    ah->arp_dha[2],
    ah->arp_dha[3],
    ah->arp_dha[4],
    ah->arp_dha[5]
    );
    printf("TARGET IP address: %02d:%02d:%02d:%02d\n",
    ah->arp_dpa[0],
    ah->arp_dpa[1],
    ah->arp_dpa[2],
    ah->arp_dpa[3]
    );

    printf("+++++++++++++++++++++++++++++++++++++++\n");
    printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    eh->h_dest[0],
    eh->h_dest[1],
    eh->h_dest[2],
    eh->h_dest[3],
    eh->h_dest[4],
    eh->h_dest[5]
    );
    printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    eh->h_source[0],
    eh->h_source[1],
    eh->h_source[2],
    eh->h_source[3],
    eh->h_source[4],
    eh->h_source[5]
    );
    memcpy( (void*)etherhead, (const void*)(etherhead+ETH_MAC_LEN),
    ETH_MAC_LEN);
    memcpy( (void*)(etherhead+ETH_MAC_LEN), (const void*)src_mac,
    ETH_MAC_LEN);
    eh->h_proto = ETH_ARP;
    printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n");
    printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    eh->h_dest[0],
    eh->h_dest[1],
    eh->h_dest[2],
    eh->h_dest[3],
    eh->h_dest[4],
    eh->h_dest[5]
    );
    printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    eh->h_source[0],
    eh->h_source[1],
    eh->h_source[2],
    eh->h_source[3],
    eh->h_source[4],
    eh->h_source[5]
    );
    ah->arp_hd = ntohs(ah->arp_hd);
    ah->arp_pr = ntohs(ah->arp_pr);

    ah->arp_op = 0x0002;

    buf_arp_dpa[0] = ah->arp_dpa[0];
    buf_arp_dpa[1] = ah->arp_dpa[1];
    buf_arp_dpa[2] = ah->arp_dpa[2];
    buf_arp_dpa[3] = ah->arp_dpa[3];

    ah->arp_dha[0] = ah->arp_sha[0];
    ah->arp_dha[1] = ah->arp_sha[1];
    ah->arp_dha[2] = ah->arp_sha[2];
    ah->arp_dha[3] = ah->arp_sha[3];
    ah->arp_dha[4] = ah->arp_sha[4];
    ah->arp_dha[5] = ah->arp_sha[5];

    ah->arp_dpa[0] = ah->arp_spa[0];
    ah->arp_dpa[1] = ah->arp_spa[1];
    ah->arp_dpa[2] = ah->arp_spa[2];
    ah->arp_dpa[3] = ah->arp_spa[3];

    ah->arp_spa[0] = buf_arp_dpa[0];
    ah->arp_spa[1] = buf_arp_dpa[1];
    ah->arp_spa[2] = buf_arp_dpa[2];
    ah->arp_spa[3] = buf_arp_dpa[3];

    ah->arp_sha[0] = 0x12;
    ah->arp_sha[1] = 0x34;
    ah->arp_sha[2] = 0x56;
    ah->arp_sha[3] = 0x78;
    ah->arp_sha[4] = 0x9a;
    ah->arp_sha[5] = 0xbc;

    socket_address.sll_addr[0] = eh->h_dest[0];
    socket_address.sll_addr[1] = eh->h_dest[1];
    socket_address.sll_addr[2] = eh->h_dest[2];
    socket_address.sll_addr[3] = eh->h_dest[3];
    socket_address.sll_addr[4] = eh->h_dest[4];
    socket_address.sll_addr[5] = eh->h_dest[5];
    printf("=======================================\n");
    printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    ah->arp_sha[0],
    ah->arp_sha[1],
    ah->arp_sha[2],
    ah->arp_sha[3],
    ah->arp_sha[4],
    ah->arp_sha[5]
    );
    printf("SENDER IP address: %02d:%02d:%02d:%02d\n",
    ah->arp_spa[0],
    ah->arp_spa[1],
    ah->arp_spa[2],
    ah->arp_spa[3]
    );
    printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    ah->arp_dha[0],
    ah->arp_dha[1],
    ah->arp_dha[2],
    ah->arp_dha[3],
    ah->arp_dha[4],
    ah->arp_dha[5]
    );
    printf("TARGET IP address: %02d:%02d:%02d:%02d\n",
    ah->arp_dpa[0],
    ah->arp_dpa[1],
    ah->arp_dpa[2],
    ah->arp_dpa[3]
    );
    printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr);
    printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl);
    printf("OPERATION : %x \n", ah->arp_op);

    sent = sendto(s, buffer, BUF_SIZE, 0, (struct
    sockaddr*)&socket_address, sizeof(socket_address));
    if (sent == -1)
    {
    perror("sendto():");
    exit(1);
    }

    answered_packets++;
    }

    total_packets++;

    }
    }


    void sigint(int signum) {
    /*Clean up.......*/

    struct ifreq ifr;

    if (s == -1)
    return;

    strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ);
    ioctl(s, SIOCGIFFLAGS, &ifr);
    ifr.ifr_flags &= ~IFF_PROMISC;
    ioctl(s, SIOCSIFFLAGS, &ifr);
    close(s);

    free(buffer);

    printf("Server terminating....\n");

    printf("Totally received: %d packets\n", total_packets);
    printf("Answered %d packets\n", answered_packets);
    exit(0);
    }
     
    , Dec 15, 2007
    #1
    1. Advertising

  2. Flash Gordon Guest

    wrote, On 15/12/07 07:48:
    > Hi all~
    > I've written a network program in C.


    C does not have networking support, you have written a program in C +
    extra libraries.

    > This program catputures ARP request packet and reply wrong ARP packet.
    > Hi. I've written a small program to learn to write in C. But
    > unfortunately the output is all jumbled up and not nice
    > Caputuring is ok, but couldn't send ARP packet. What's wrong?
    >
    > ( using 2PC, this program run in Linux and moitoring other PC,Window
    > XP)
    > (generator packet prgram is BillSniff, monitoring program is
    > WireShark)


    Since you mention Linux, try compiling the program using gcc with the
    options "-std=c99 -pedantic -Wall -Wextra". The compiler will tell you
    about lots of problems than.

    > #include <sys/socket.h>
    > #include <sys/ioctl.h>
    > #include <sys/time.h>
    >
    > #include <asm/types.h>


    All the above headers are not standard C and so not topical here.

    > #include <math.h>
    > #include <string.h>
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <unistd.h>


    unistd.c is also not standard C and so not topical here.

    > #include <signal.h>
    >
    > #include <linux/if_packet.h>
    > #include <linux/if_ether.h>
    > #include <linux/if_arp.h>


    The above three headers are Linux specific and so not topical here and
    possibly not topical in comp.programmer.unix where the earlier headers
    would have been topical. However, there are plenty of Linux groups.

    > #define BUF_SIZE 42
    > #define DEVICE "eth0"
    > #define ETH_P_NULL 0x0
    > #define ETH_MAC_LEN ETH_ALEN
    > #define ETH_ARP 0x0806
    >
    > int s = 0; /*Socketdescriptor*/
    > void* buffer = NULL;
    > long total_packets = 0;
    > long answered_packets = 0;


    Global variable. Yuck. Horrible. Redesign your program so you do to
    avoid them since as you start working on larger projects they make
    things harder and messier.

    Also void* is generally not a good type for a buffer, unsigned char*
    would be more sensible if it is binary data.

    > void sigint(int signum);
    >
    > struct __attribute__((packed)) arp_header


    __attribute__ is gcc specific (well, Intel's compiler that aims to be
    gcc compatible will accept it as well).

    > {
    > unsigned short arp_hd;
    > unsigned short arp_pr;
    > unsigned char arp_hdl;
    > unsigned char arp_prl;
    > unsigned short arp_op;
    > unsigned char arp_sha[6];
    > unsigned char arp_spa[4];
    > unsigned char arp_dha[6];
    > unsigned char arp_dpa[4];
    > };
    >
    >
    > int main(void) {
    > buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/


    Don't cast the return value of malloc. It is not required and in general
    casts should be avoided unless you *really* know *exactly* why they are
    needed, since normally when casts are added they are not the correct
    solution to the problem.

    > unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/
    > struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to
    > ethernet header*/
    > unsigned char* arphead = buffer + 14;


    Standard C does not allow arithmetic on void* pointers, one reason for
    using unsigned char* as the type for buffer.

    <snip>

    > printf("Totally received: %d packets\n", total_packets);
    > printf("Answered %d packets\n", answered_packets);


    long and int are not the same type, %d is for int not long.

    > exit(0);
    > }


    Most of the above problems, and a few more besides, where shown by using
    the compiler options I have suggested. If you are nice to it your
    compiler can be a very good friend and help you a lot.
    --
    Flash Gordon
     
    Flash Gordon, Dec 15, 2007
    #2
    1. Advertising

  3. wrote:
    > Hi all~
    > I've written a network program in C.
    >
    > This program catputures ARP request packet and reply wrong ARP packet.


    Details of networking are not topical here, and you may have better luck
    in comp.unix.programmer or some similar group.

    That said, wherever you post, you need to be clearer about the error /
    problem - define "jumbled up" for instance. Are bytes in the wrong order
    maybe ? Is it total garbage? does the PC or Linux box crash?

    > Hi. I've written a small program to learn to write in C.


    Networking is a pretty advanced place to start learning C.

    --
    Mark McIntyre

    CLC FAQ <http://c-faq.com/>
    CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
     
    Mark McIntyre, Dec 15, 2007
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Li Han
    Replies:
    2
    Views:
    508
    bobicanprogram
    Feb 9, 2009
  2. Gelonida N
    Replies:
    4
    Views:
    890
    Gelonida N
    Sep 11, 2011
  3. M. R.
    Replies:
    3
    Views:
    199
    K. R.
    Oct 25, 2007
  4. Robin Wood

    network packet capture

    Robin Wood, Dec 21, 2007, in forum: Ruby
    Replies:
    0
    Views:
    130
    Robin Wood
    Dec 21, 2007
  5. Ralle
    Replies:
    4
    Views:
    87
    Asaf Las
    Feb 3, 2014
Loading...

Share This Page