Например, чтобы установить сетевой интерфейс в неразборчивый режим, можно использовать setsockopt
как
struct packet_mreq opt;
opt.mr_ifindex = the_very_interface_index;
setsockopt(socket_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void*)&opt, sizeof(opt));
С другой стороны, как предложено в пакете (7), можно также использовать ioctl
с опцией SIOCSIFFLAGS, например
struct ifreq req;
strcpy(req.ifr_name, the_very_interface_name);
ioctl(socket_fd, SIOCGIFFLAGS, &req);
req.ifr_flags |= IFF_PROMISC;
ioctl(socket_fd, SIOCSIFFLAGS, &req);
Я понимаю, что эти два способа полностью эквивалентны, но есть ли разница? В противном случае, почему есть два способа сделать одно и то же?
Между ними очень мало различий, как можно увидеть, просмотрев источник. В частности, рассмотрим вызывающих абонентов __dev_set_promiscuity
.
setsockopt
в конечном итоге вызывает dev_set_promiscuity
.ioctl
в конечном итоге вызывает dev_change_flags
.Всегда существовало некоторое дублирование механизмов из-за интерфейса файлового дескриптора с устройствами. Например send()
против write()
. Честно говоря, я никогда не задумывался об этом слишком глубоко. Я полагаю, что интерфейсы ioctl
естественно добавлять для универсальных устройств, а интерфейсы setsockopt
естественно добавлять для сокетов, так что оба в конечном итоге существуют. Вы можете думать о сокетах как об абстракции более высокого уровня над сетевым устройством, поэтому интерфейс более высокого уровня для изменения параметров не будет необоснованным дополнением.