2012-03-29 10 views
3

で動作しません。 Pleasesetsockopt()システムを使用したデバイスバインドのrawソケットはFedora Core 6(2.6.18-1.2798.fc6)

以下のサンプルコードでは、raw sockとeth0をバインドしました。プログラムを実行中に raw sockのrecvfromは、同じマシン(xx_86)のeth0 & eth1からのパケットを受信して​​います。 なぜ、この問題について私が助けてくれるのかはわかりません。 Fedoraのコア6(2.6.18-1.2798.fc6)

SAMPEコード:Linuxのmanページで

#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

あなたは 'setsockopt()'エラーで 'perror()'を持っていませんか? – ninjalj

答えて

6

ます(http:// linuxの は私がのsetsockoptが適切 OSを動作していない願っています。 die.net/man/7/socket):

SO_BINDTODEVICE

バインドPASで指定されるように "eth0の" などの特定のデバイス、このソケットsedインタフェース名。名前が空の文字列であるか、オプションの長さがゼロの場合、ソケットデバイスのバインディングは削除されます。渡されるオプションは、最大サイズがIFNAMSIZの可変長ヌル終了インタフェース名文字列です。ソケットがインターフェイスにバインドされている場合、その特定のインターフェイスから受信したパケットだけがソケットによって処理されます。これは、一部のソケットタイプ、特にAF_INETソケットでのみ機能することに注意してください。 パケットソケットではサポートされていません(通常のbind(2)を使用してください)

だから、代わりにバインドしてみてください。

+0

ありがとうございます。とても感謝しています。バインドアプローチで動作します –

4

ありがとう、貴重な時間をいただきありがとうございます。それはバインドのアプローチで働いています コードセグメントは私を助けてくれました。

setsockopt()は2.6.18

別のアプローチは、以下であるFedoraのバグです。

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; 
} 
関連する問題