views:

622

answers:

1

Hi everybody. I'm still struggling to get my sample code working on a 64 bit machine. My previous problem was solved because of missing/outdated headers/libraries.

I compile this code as follow: gcc -Wall -g -o server server.c and gcc -Wall -g -o client client.c I run them on 2 linux machines(both 32bit) and it works fine. When I recompile this code on 64 bit machines then it seems that no packets go through from the client to the server. Putting tcpdump on the client it seems that it is sending malformed headers that gets rejected all the time. Can anybody enlighten me?

#include "client.h"
#include "util.h"

#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 ETH_FRAME_TOTALLEN
#define NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA 100000 /*how often to measure travelling time with one certain amount of data*/

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

int main(int argc, char* argv[]) 
{
    buffer = (void*)malloc(BUF_SIZE);   /*Buffer for ethernet frame*/
    unsigned char* etherhead = buffer;  /*Pointer to ethenet header*/
    unsigned char* data = buffer + 14;  /*Userdata in ethernet frame*/
    struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to ethernet header*/

    unsigned char src_mac[6];       /*our MAC address */
    unsigned char dest_mac[6] = {0x00, 0x1E, 0x4F, 0xB1, 0xCB, 0x43};   /*MAC address, hardcoded...... :-(*/ 

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

    /*stuff for time measuring: */
    struct timeval begin;
    struct timeval end;
    struct timeval result;
    unsigned long long allovertime;

    printf("Client 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, ETH0, 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[i] = ifr.ifr_hwaddr.sa_data[i];
    }
    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[0]  = dest_mac[0];
    socket_address.sll_addr[1]  = dest_mac[1];
        socket_address.sll_addr[2]  = dest_mac[2];
        socket_address.sll_addr[3]  = dest_mac[3];
        socket_address.sll_addr[4]  = dest_mac[4];
        socket_address.sll_addr[5]  = dest_mac[5];
    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");

    /*init random number generator*/
    srand(time(NULL));

    printf("We are in production state, sending packets to: %02X:%02X:%02X:%02X:%02X:%02X\n",
            dest_mac[0],dest_mac[1],dest_mac[2],dest_mac[3],dest_mac[4],dest_mac[5]);

    for (i = 50; i <= 1500; i += 50) {

        allovertime = 0;

        for (k = 0; k < NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA; k++) {
            /*prepare buffer*/
            memcpy((void*)buffer, (void*)dest_mac, ETH_MAC_LEN);
            memcpy((void*)(buffer+ETH_MAC_LEN), (void*)src_mac, ETH_MAC_LEN);
            eh->h_proto = ETH_P_NULL;
            /*fill it with random data....*/
            for (j = 0; j < i; j++) {
                data[j] = (unsigned char)((int) (256.0*rand()/(RAND_MAX+1.0)));
            }

            /*clear the timers:*/
            timerclear(&begin);
            timerclear(&end);

            /*get time before sending.....*/
             gettimeofday(&begin,NULL);


            /*send packet*/
            sent = sendto(s, buffer, i+ETH_HEADER_LEN, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
            if (sent == -1) {
                perror("sendto():");
                exit(1);
            }

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

            /*get time after sending.....*/
            gettimeofday(&end,NULL);
            /*...and calculate difference.........*/
            timersub(&end,&begin,&result); 

                allovertime += ((result.tv_sec * 1000000 ) + result.tv_usec );

            total_sent_packets++;
        }

        printf("Sending %i bytes takes %lld microseconds in average\n",i ,allovertime/NUMBER_OF_MESUREMENTS_PER_AMOUNT_OF_DATA);
    }
    return (0);
}

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

    struct ifreq ifr;

        if (s == -1)
            return;

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

    free(buffer);

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

    printf("Totally sent: %ld packets\n", total_sent_packets);
    exit(0);
}

------------------server.c---------------------

#include "server.h"
#include "util.h"

#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 ETH_FRAME_TOTALLEN

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

int main(int argc, char* argv[]) 
{
    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 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, ETH0, 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[i] = ifr.ifr_hwaddr.sa_data[i];
    }
    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 (keyboard)*/
    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);
        }
        /*See if we should answer (Ethertype == 0x0 && destination address == our MAC)*/
        if (eh->h_proto == ETH_P_NULL && memcmp( (const void*)eh->h_dest, (const void*)src_mac, ETH_MAC_LEN) == 1 ) 
        {
            /*exchange addresses in buffer*/
            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);

            /*prepare sockaddr_ll*/
            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];

            /*send answer*/
            sent = sendto(s, buffer, length-4, 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, ETH0, 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: %ld packets\n", total_packets);
    printf("Answered %ld packets\n", answered_packets);
    exit(0);
}
A: 

Sorry for all the code, but I didn't know how to make it shorter as i wasn't sure where the error was. Anyway, I found the problem, so apologies for the "wall of code" guys!

It turns out the problem was how our switches are configured. After I got 2 machines on the same subnet the code worked beautiful!

NomadAlien