2013-11-27 2 views
7

Я запускаю проект на linux (ubuntu 13.10), который использует raw-сокет, подключаемый к устройству.bind vs SO_BINDTODEVICE socket

Вот мой код:

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

Однако у меня есть 2 сетевые карты на моем компьютере, и я хотел бы, чтобы слушать только один из них. скажем, это. Я нашел два варианта привязки и SO_BINDTODEVICE следующим образом:

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

связывают только произведения. Итак, мой вопрос в чем разница между этими двумя?

+1

Вы пробовали 'strlen (ifName)' вместо 'IFNAMSIZ-1'? Просто догадаться ... –

+0

@PerJohansson: Это была бы плохая идея. На странице руководства говорится: «Пропущенный параметр представляет собой строку имени интерфейса интерфейса переменной длины ** с максимальным размером« IFNAMSIZ », но« strlen »не может иметь значение null. –

ответ

9

От Linux человек-страницы man 7 socket для опции сокета SO_BINDTODEVICE:

Обратите внимание, что это работает только для некоторых типов сокетов, в частности AF_INET розетки. Он не поддерживается для пакетов сокетов (используйте обычный bind (2) там).

0

это - рабочая версия.

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