Необработанный сокет с привязкой устройства с помощью setsockopt () не работает в ядре Fedora 6 (2.6.18-1.2798.fc6)

Пожалуйста, кто-нибудь может помочь в этом вопросе. пожалуйста

В приведенном ниже примере кода мы связали raw sock с eth0. но во время работы программы recvfrom raw sock получает пакеты от eth0 и eth1 на той же машине (xx_86). Мне не понятно, почему, может помочь один в этом вопросе. Я надеюсь, что setsockopt не работает должным образом ОС: Fedora Core 6 (2.6.18-1.2798.fc6)

Код Sampe:

#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);
}
 ninjalj29 мар. 2012 г., 12:23
Хорошо, почему у вас нетperror() наsetsockopt() ошибка?

Ответы на вопрос(2)

SO_BINDTODEVICE

Свяжите этот сокет с конкретным устройством, таким как «eth0», как указано в переданном имени интерфейса. Если имя является пустой строкой или длина параметра равна нулю, привязка устройства сокета удаляется. Переданная опция является строкой имени интерфейса переменной длины с нулевым символом в конце с максимальным размером IFNAMSIZ. Если сокет связан с интерфейсом, сокетом обрабатываются только пакеты, полученные от этого конкретного интерфейса. Обратите внимание, что это работает только для некоторых типов сокетов, особенно для сокетов AF_INET.Он не поддерживается для сокетов пакетов (используйте там обычный bind (2)).

Итак, попробуйте связать вместо этого.

 viswanathan J29 мар. 2012 г., 16:59
Спасибо всем большое спасибо за потраченное время. это работает с подходом связывания

связывания Сегменты кода помогли мне.

setsockopt() это ошибка в Fedora 2.6.18

Альтернативный подход ниже.

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;
} 

Ваш ответ на вопрос