Raw socket with device bind using setsockopt() system is not working in Fedora core 6(2.6.18-1.2798.fc6)

14,304

Solution 1

In the linux man page (http://linux.die.net/man/7/socket) :

SO_BINDTODEVICE

Bind this socket to a particular device like "eth0", as specified in the passed interface name. If the name is an empty string or the option length is zero, the socket device binding is removed. The passed option is a variable-length null-terminated interface name string with the maximum size of IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this only works for some socket types, particularly AF_INET sockets. It is not supported for packet sockets (use normal bind(2) there).

So, try the bind instead.

Solution 2

Thanks all,thanks you very much for valuable time. it is worked with bind approach The code segments had helped me.

setsockopt() is bug in the fedora 2.6.18

alternative approach is below.

void BindToInterface(int raw , char *device , int protocol) { 
    struct sockaddr_ll sll;
    struct ifreq ifr; bzero(&sll , sizeof(sll));
    bzero(&ifr , sizeof(ifr)); 
    strncpy((char *)ifr.ifr_name ,device , IFNAMSIZ); 
    //copy device name to ifr 
    if((ioctl(raw , SIOCGIFINDEX , &ifr)) == -1)
    { 
        perror("Unable to find interface index");
        exit(-1); 
    }
    sll.sll_family = AF_PACKET; 
    sll.sll_ifindex = ifr.ifr_ifindex; 
    sll.sll_protocol = htons(protocol); 
    if((bind(raw , (struct sockaddr *)&sll , sizeof(sll))) ==-1)
    {
        perror("bind: ");
        exit(-1);
    }
    return 0;
} 
Share:
14,304
Admin
Author by

Admin

Updated on June 09, 2022

Comments

  • Admin
    Admin almost 2 years

    Please any one could help on this issue. Please

    In the below sample code,we had bind raw sock with eth0. but while running the program the recvfrom of raw sock is receiving packets from eth0 & eth1 on same machine(xx_86). It is not clear to me why,could help one on this issue. I hope the setsockopt is not working properly OS: Fedora core 6(2.6.18-1.2798.fc6)

    Sampe code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <linux/if_ether.h>
    #include <net/if.h>
    #include <linux/filter.h>
    #include <sys/ioctl.h> 
    #include <string.h>
    #include <arpa/inet.h>
    
    int main(int argc, char **argv) {
    int sock, i;
    unsigned char buffer[2048];
    unsigned char tbuff[2048];
    unsigned char *iphead, *ethhead,*phead;
    struct ifreq ethreq;
    
    // NOTE: use TCPDUMP to build the filter array.
    // set filter to sniff only port 443
    // $ sudo tcpdump -dd port 443
    
    // raw for recvfrom eth0
    
    if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) == -1) {
        perror("socket");
        exit(1);
    }
      // set network card to promiscuos
    strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);
    if (ioctl(sock,SIOCGIFFLAGS, &ethreq) == -1) {
        perror("ioctl");
        close(sock);
        exit(1);
    }
    ethreq.ifr_flags |= IFF_PROMISC;
    if (ioctl(sock, SIOCSIFFLAGS, &ethreq) == -1) {
        perror("ioctl");
        close(sock);
        exit(1);
    }
    
    //bind to sock with eth0 
    
     struct ifreq Interface;
     memset(&Interface, 0, sizeof(Interface));
     strncpy(Interface.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
     if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &Interface, sizeof(Interface)) < 0)    { close(sock); }
    
    
        //open the RAW socket for sendto
    
     int s = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
    
         struct sockaddr_in sin;
         memset(&sin,0,sizeof(sin));
         sin.sin_family = AF_INET;
         sin.sin_port = htons(0);
         sin.sin_addr.s_addr = inet_addr ("10.3.161.104");
    
      // inform kernal don't fill IP and Transport header
    
         int one = 1;
         const int *val = &one;
         if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
         printf ("Warning: Cannot set HDRINCL!\n");
    
         //bind the sock descriptor with eth0
    
         struct ifreq Interface1;
         memset(&Interface1, 0, sizeof(Interface1));
         strncpy(Interface1.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
         if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &Interface1, sizeof(Interface1)) < 0) { close(s); }
    
    
    while (1) {
        printf("----------------------\n");
        i = recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL);
        printf("%d bytes read\n", i);
    
        // check header size: Ethernet = 14, IP = 20, TCP = 8 (sum = 42)
        if (i < 42) {
            perror("recvfrom():");
            printf("Incomplete packet (errno is %d)\n", errno);
            close(sock);
            exit(0);
        }
    
        phead = buffer + 14; // (skip ethernet  header)
        memcpy(tbuff,phead,i-14); 
        iphead=tbuff;
        if (*iphead == 0x45) {
            int ptrindex= iphead[9];
            switch(ptrindex){
    
             case 1:
                    printf("The transport protocl is:ICMP\n");
                    break;
             case 2:
                    printf("The transport protol is:IGMP\n");
                    break;
             case 6:
                   printf("The transport protocol is:TCP\n");
                   break;
             case 17:
                   printf("The transport protocol is:UDP\n");
                   break;
             case 103:
                  printf("The transport protocol is:PIM\n"); 
                  break; 
             default:
                 printf("The transport protocol is:%d\n",iphead[9]);
            }           
            //printf("%d",*ptrindex);
           // printf("\n The transport protocol is :%u\n",iphead[9]);
            printf("Source Address: %d.%d.%d.%d, Port: %d\n",
                iphead[12], iphead[13], iphead[14], iphead[15], (iphead[20] << 8) + iphead[21]);
            printf("Dest Address: %d.%d.%d.%d, Port: %d\n",
                iphead[16], iphead[17], iphead[18], iphead[19], (iphead[22] << 8) + iphead[23]);
    
    
         if(sendto(s,tbuff,i-14,0,(struct sockaddr *)&sin,sizeof(sin))<0)
          printf("error\n");
    
         else{printf("\nThe received packet is send\n");}
    
         memset(buffer,0,sizeof(buffer));
         memset(tbuff,0,sizeof(tbuff));
    
        }
       else{ printf("The non ip had received");}
    
        }
           close(sock);
    }
    
  • Admin
    Admin about 12 years
    Thanks all,thanks you very much for vaulable time. it is worked with bind approach