2012-03-29 3 views
3

Bitte irgendjemand könnte zu diesem Thema helfen. BitteRaw Socket mit Gerätebindung mit setsockopt() System funktioniert nicht in Fedora Core 6 (2.6.18-1.2798.fc6)

In der folgenden Beispiel-Code hatten wir binden Rohsocke mit eth0. aber während das Programm läuft der recvfrom der rohen Socke empfängt Pakete von eth0 & eth1 auf der gleichen Maschine (xx_86). Es ist mir nicht klar, warum, könnte einem zu diesem Thema helfen. Ich hoffe, die Setsockopt nicht richtig OS funktioniert: 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); 
} 
+0

Ok, warum haben Sie keine 'perror()' auf 'setsockopt()' Fehler? – ninjalj

Antwort

6

im Linux-man-Seite (http: // Linux. die.net/man/7/socket):

SO_BINDTODEVICE

Bind diese Buchse an ein bestimmtes Gerät wie "eth0", wie sie in den angegebenen pas sed Schnittstellenname. Wenn der Name eine leere Zeichenfolge ist oder die Option length den Wert null hat, wird die Socket-Gerätebindung entfernt. Bei der übergebenen Option handelt es sich um eine NULL-terminierte Schnittstellennamenszeichenfolge variabler Länge mit der maximalen Größe von IFNAMSIZ. Wenn ein Socket an eine Schnittstelle gebunden ist, werden nur Pakete, die von dieser bestimmten Schnittstelle empfangen werden, vom Socket verarbeitet. Beachten Sie, dass dies nur für einige Socket-Typen funktioniert, insbesondere für AF_INET-Sockets. Es wird nicht für Packet-Sockets unterstützt (verwenden Sie dort normal bind (2)).

Also, versuchen Sie die Bindung stattdessen.

+0

Vielen Dank, vielen Dank für die wertvolle Zeit. Es ist mit Bind Ansatz gearbeitet –

4

Vielen Dank, vielen Dank für die wertvolle Zeit. es wird mit bind approach gearbeitet Die Code-Segmente hatten mir geholfen.

setsockopt() ist Fehler in der fedora 2.6.18

alternativer Ansatz ist unten.

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