2012-03-29 4 views
3

Пожалуйста, любой может помочь по этой проблеме. Пожалуйста,Розетка с привязкой устройства с использованием системы setsockopt() не работает в ядре Fedora 6 (2.6.18-1.2798.fc6)

В приведенном ниже примере кода у нас был привязанный сырой носок с eth0. но при запуске программы recvfrom сырого носка принимает пакеты от 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); 
} 
+0

Хорошо, почему у вас нет 'perror()' on 'setsockopt()' error? – ninjalj

ответ

6

На странице Linux человек (HTTP: // Linux. die.net/man/7/socket):

SO_BINDTODEVICE

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

Итак, попробуйте привязку.

+0

Спасибо всем, спасибо вам большое за vaulable время. он работает с привязкой –

4

Спасибо, спасибо большое за ценное время. он работает с привязкой Сегменты кода помогли мне.

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

 Смежные вопросы

  • Нет связанных вопросов^_^