2013-11-27 12 views
7

Ich bin ein Projekt unter Linux (Ubuntu 13.10), die Raw Socket Verbindung zu einem Gerät verwendet.Bind vs SO_BINDTODEVICE Socket

Hier ist mein Code:

/* builed socket */ 
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { 
    perror("listener: socket"); 
    return -1; 
} 

/* Set interface to promiscuous mode */ 
strncpy(ifopts.ifr_name, ifName, IFNAMSIZ-1); 
ioctl(sockfd, SIOCGIFFLAGS, &ifopts); 
ifopts.ifr_flags |= IFF_PROMISC; 
ioctl(sockfd, SIOCSIFFLAGS, &ifopts); 

/* Allow the socket to be reused - incase connection is closed prematurely */ 
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) { 
    perror("setsockopt"); 
    close(sockfd); 
    return -2; 
} 

Jedoch habe ich 2 NIC-Karten auf meinem Computer haben, und ich würde nur zu einem von ihnen hören mögen. Sagen wir Ethos. Ich fand zwei Optionen binden und SO_BINDTODEVICE wie folgt:

/* option 1. Bind to device */ 
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, IFNAMSIZ-1) == -1) { 
    perror("SO_BINDTODEVICE"); 
    close(sockfd); 
    return -4; 
} 


/* option 2. Bind to device */ 
memset(&sock_address, 0, sizeof(sock_address)); 
sock_address.sll_family = PF_PACKET; 
sock_address.sll_protocol = htons(ETH_P_ALL); 
sock_address.sll_ifindex = if_nametoindex(ifName); 
if (bind(sockfd, (struct sockaddr*) &sock_address, sizeof(sock_address)) < 0) { 
    perror("bind failed\n"); 
    close(sockfd); 
    return -4; 
} 

Nur Bindung funktioniert. Also meine Frage ist, was ist der Unterschied zwischen den beiden?

+1

Haben Sie 'strlen (ifName)' anstelle von 'IFNAMSIZ-1' versucht? Nur eine Vermutung ... –

+0

@PerJohansson: Das wäre eine schlechte Idee. Die Manpage sagt: "Die übergebene Option ist ein String mit variabler Länge ** nullterminierter ** Schnittstellenname mit der maximalen Größe von 'IFNAMSIZ'", aber 'strlen' könnte nicht die Null sein. –

Antwort

9

Von Linux-man-Seite man 7 socket für Socket-Option SO_BINDTODEVICE:

Beachten Sie, dass diese besonders AF_INET Steckdosen nur für einige Socket-Typen arbeitet. Es wird nicht für Paket-Sockets unterstützt (verwenden Sie dort normal bind (2)).

0

hier ist die Arbeitsversion.

{ 
struct ifreq if_bind; 
strncpy(if_bind.ifr_name, ifName.c_str(), IFNAMSIZ); 

if(setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&if_bind, sizeof(if_bind)) < 0) { 
     } 
} 
Verwandte Themen