2013-11-27 12 views
7

Sto eseguendo un progetto su linux (ubuntu 13.10) che utilizza socket raw che si connette a un dispositivo.binding vs SO_BINDTODEVICE socket

Qui è il mio codice:

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

Tuttavia ho 2 carte del NIC sul mio computer e mi piacerebbe ascoltare solo uno di loro. diciamo etho. Ho trovato due opzioni si legano e SO_BINDTODEVICE come segue:

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

legare Solo opere. Quindi la mia domanda è qual è la differenza tra i due?

+1

Hai provato 'strlen (ifName)' invece di 'IFNAMSIZ-1'? Solo una supposizione ... –

+0

@PerJohansson: Sarebbe una cattiva idea. La pagina man dice "L'opzione passata è una stringa di nome dell'interfaccia ** a lunghezza variabile ** terminata da null con la dimensione massima di" IFNAMSIZ' ", ma' strlen' non potrebbe il null. –

risposta

9

Dalla pagina man Linux man 7 socket per l'opzione presa SO_BINDTODEVICE:

Si noti che questo funziona solo per alcuni tipi di socket, in particolare AF_INET prese. Non è supportato per socket di pacchetti (utilizzare il normale bind (2) qui).

0

ecco la versione di lavoro.

{ 
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) { 
     } 
}