2012-03-29 1 views
3

에서 작동하지 않습니다. 아무도이 문제에 도움이 될 수 있습니다. Pleasesetsockopt() 시스템을 사용하는 장치 바인드가있는 원시 소켓이 Fedora Core 6 (2.6.18-1.2798.fc6)

아래의 샘플 코드에서는 raw sock과 eth0를 바인드했습니다. 그러나 프로그램을 실행하는 동안 raw sock의 recvfrom은 동일한 시스템 (xx_86)의 eth0 & eth1에서 패킷을 수신하고 있습니다. 왜이 문제에 도움이 될 수 있는지는 분명하지 않습니다. 페도라 코어 6 (2.6.18-1.2798.fc6)

Sampe 코드 : 리눅스 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 : // 리눅스 은 내가 setsockopt를 제대로 OS를 작동하지 않습니다 바랍니다. die.net/man/7/socket)

SO_BINDTODEVICE

인드 PAS에 명시된 "eth0를"와 같은 특정 장치에이 소켓 sed 인터페이스 이름. 이름이 빈 문자열이거나 옵션 길이가 0이면 소켓 장치 바인딩이 제거됩니다. 전달 된 옵션은 최대 크기가 IFNAMSIZ 인 가변 길이 Null 종료 인터페이스 이름 문자열입니다. 소켓이 인터페이스에 바인드 된 경우 해당 특정 인터페이스에서 수신 된 패킷 만 소켓에서 처리됩니다. 이것은 일부 소켓 유형, 특히 AF_INET 소켓에서만 작동합니다. 패킷 소켓에는 지원되지 않습니다 (정상적인 bind (2) 사용).

따라서 바인드를 시도하십시오.

+0

감사합니다. 대단히 감사합니다. 바인드 방식으로 작동합니다. –

4

감사합니다. 귀중한 시간을 가져 주셔서 감사합니다. 그것은 바인드 접근 방식으로 작동합니다. 코드 세그먼트가 도움이되었습니다.

setsockopt()은 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; 
} 
관련 문제