recvfrom read the same frame multiple times

596 Views Asked by At

im playing around with STP packets and writing a program raw sockets to modify them. Reading fropm eth0 sending to eth1. System is ubuntu 14.10/ Kernel 3.somewhat. Packets are generated with additional computers with Karat and Wireshark is running this interfaces too. Inject a packet and after first run recvfrom didn't stop. Read the same packet from eth0 and send it to eth1. Debugging session ??????? The final edition should read all frame from eth0 , forward all and put all STP in a "unicast tunnel" - Read alle eth1 frame an forward eth0 and "unpack" special "Tunnel" frames.

i put some code here:

    typedef struct {
            unsigned char mac[6];
            unsigned char ifName[IFNAMSIZ];
            int sockfd;
            struct sockaddr_ll socketaddress;
            struct ifreq ifopts;                    /* set promiscuous mode */

    } interfaces;

    extern int errno;

    nt i;
    int sockopt;
    ssize_t numbytes;

    unsigned char InBuf[BUF_SIZ];   // this is the frame buffer

    interfaces in,out;          // interface struct var's

   unsigned char PeerMac[6]; // Peer mac for simple Tunnel
   unsigned char myMac[6];  // my Peer address
   int c;


    unsigned char IEEE802_1q_STP[6] =  {0x01, 0x80, 0xC2, 0x00, 0x00, 0x0d};    


    /* Header structures */
    struct ether_header *InTunnelPtr = (struct ether_header*) InBuf;
    struct ether_header *InPtr = (struct ether_header*) (InBuf+14);  
/ First Do it for IN_IF
    memset(&in.socketaddress, 0, sizeof(struct sockaddr_ll));  // clear Var
    in.socketaddress.sll_family = PF_PACKET;
    in.socketaddress.sll_protocol = htons(ETH_P_ALL); // just dummy, don't needed
    in.socketaddress.sll_halen = ETH_ALEN;


/* Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
    if ((in.sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
        perror("listener: socket");
        return -1;
    }

    memset (&in.ifopts, 0, sizeof (struct ifreq));

// Set interface to promiscuous mode - do we need to do this every time?
    strncpy(in.ifopts.ifr_name, in.ifName, IFNAMSIZ-1); // set if name
    ioctl(in.sockfd, SIOCGIFFLAGS, &in.ifopts);   // get current flags
    in.ifopts.ifr_flags |= IFF_PROMISC;         // set promiscuous mode
    ioctl(in.sockfd, SIOCSIFFLAGS, &in.ifopts);  // write flags
    // get my mac addr
    //ioctl(in.sockfd,SIOCGIFHWADDR,&in.ifopts);
    //memcpy(in.mac,in.ifopts.ifr_hwaddr.sa_data,ETH_ALEN);

// find Interface index
    strncpy(in.ifopts.ifr_name, in.ifName, IFNAMSIZ-1);  //
    ioctl(in.sockfd, SIOCGIFINDEX, &in.ifopts);          // get if index

    in.socketaddress.sll_ifindex=in.ifopts.ifr_ifindex;  // set index to sockaddr_ll

// Allow the socket to be reused - incase connection is closed prematurely
    if (setsockopt(in.sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
        perror("setsockopt");
        close(in.sockfd);
        exit(EXIT_FAILURE);
    }
// Bind to device
    if (setsockopt(in.sockfd, SOL_SOCKET, SO_BINDTODEVICE, in.ifName, IFNAMSIZ-1) == -1) {
        perror("SO_BINDTODEVICE");
        close(in.sockfd);
        exit(EXIT_FAILURE);
    }
// -----------------------------------
// Now, do the OUT Interface
// -----------------------------------
    memset(&out.socketaddress, 0, sizeof(struct sockaddr_ll));  // clear Var
    out.socketaddress.sll_family = PF_PACKET;
    out.socketaddress.sll_protocol = htons(ETH_P_ALL); // just dummy, don't needed
    out.socketaddress.sll_halen = ETH_ALEN;


// Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
    if ((out.sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
        perror("listener: socket");
        exit(EXIT_FAILURE);
    }

    memset (&out.ifopts, 0, sizeof (struct ifreq));

// Set interface to promiscuous mode - do we need to do this every time? */
    strncpy(out.ifopts.ifr_name, out.ifName, IFNAMSIZ-1);
    ioctl(out.sockfd, SIOCGIFFLAGS, &out.ifopts);
    out.ifopts.ifr_flags |= IFF_PROMISC;
    ioctl(out.sockfd, SIOCSIFFLAGS, &out.ifopts);
    // get my mac addr
    // ioctl(out.sockfd,SIOCGIFHWADDR,&out.ifopts);
    // memcpy(out.mac, out.ifopts.ifr_hwaddr.sa_data, ETH_ALEN);

// find Interface index */
    strncpy(out.ifopts.ifr_name, out.ifName, IFNAMSIZ-1);
    ioctl(out.sockfd, SIOCGIFINDEX, &out.ifopts);

    out.socketaddress.sll_ifindex=out.ifopts.ifr_ifindex;

// Allow the socket to be reused - incase connection is closed prematurely */
    if (setsockopt(out.sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
        perror("setsockopt");
        close(out.sockfd);
        exit(EXIT_FAILURE);
    }
// Bind to device */
if (setsockopt(out.sockfd, SOL_SOCKET, SO_BINDTODEVICE, out.ifName, IFNAMSIZ-1) == -1) {
        perror("SO_BINDTODEVICE");
        close(out.sockfd);
        exit(EXIT_FAILURE);
    }

// Working LOOP
// interface in
// buffer structur
//   ------------------------------------------------------------
//   | dest  | source | len |   recv packet                     |
//   ------------------------------------------------------------
//   ^InTunnelPtr           ^ InPtr
repeat:
    numbytes=0;

    numbytes = recvfrom(in.sockfd, &InBuf[14], BUF_SIZ, 0, NULL, NULL) ;


/* let the game begin */
// test multicast addresses here
// and do something:-)

    if (numbytes > 0) {
 /*     if (memcmp(InPtr->ether_dhost,CISCOSHARED_STP, ETH_ALEN) == 0) {
            if (debug == 1) printf("Cisco Shard stp found");
        }
        else if (memcmp(InPtr->ether_dhost,IEEE802_1AD_STP, ETH_ALEN)==0) {
            if ( debug == 1) printf("IEEE802.1AD stp found");
        }
        else */

        if (memcmp(InPtr->ether_dhost,IEEE802_1D_STP, ETH_ALEN)==0)   // this tunnel
        {
            if (debug == 1) printf("IEEE802.1D stp for tunnel eth1\n");

            memcpy(InTunnelPtr->ether_dhost,PeerMac , ETH_ALEN);  // Copy PeerMac to destination  address
            memcpy(InTunnelPtr->ether_shost,myMac , ETH_ALEN);    // Copy my peer mac to source address
            InTunnelPtr->ether_type=numbytes+14;                                            // set tunnel header len

//          if (numbytes = sendto(out.sockfd, &InBuf[0] , (numbytes+14), 0,(struct sockaddr_ll *)&out.socketaddress,sizeof(out.socketaddress)) < 0)
            i = numbytes+14;

            if (numbytes = sendall_eth1(out.sockfd, &InBuf[0] , &i, &out.socketaddress, sizeof(out.socketaddress)) < 0)
            {
                printf("send error %s \n",strerror(errno));
            }

        } else {                            // send untunneled packet out

            if (debug == 1) printf ("send untunneled packet eth1\n");
//          if (numbytes = sendto(out.sockfd, &InBuf[14], numbytes, 0,(struct sockaddr_ll *)&out.socketaddress,sizeof(out.socketaddress)) < 0)
            i = numbytes;

            if (numbytes =
                  sendall_eth1(out.sockfd, &InBuf[14], &i, &out.socketaddress, sizeof(out.socketaddress)) < 0)
            {
                printf("send error %s \n",strerror(errno));
            }
        }
    }

goto repeat
0

There are 0 best solutions below