Предупреждение: Это происходит из-за каннибализации некоторого кода, который я написал для производственного программного обеспечения, использующего PF_PACKET
, который был только для Ethernet, поэтому может быть неполным / неточным.
Вы используете ETH_P_ALL
, который даст вам что-нибудь. Но есть много символов ETH_P_*
на выбор (например, ETH_P_802_3_MIN
).
Привязка / выбор не основаны не только на вызове socket
, но и на заданном интерфейсе .
Сначала вам нужен интерфейс имя , которое вы хотите (например, eth0
) из списка, который вы можете получить из ifconfig
.
Затем получите интерфейс index , используя ioctl(SIOCGIFINDEX,...)
из имени интерфейса [или вы можете просто жестко закодировать его, так как ifconfig
распечатает их в порядке индекса].
Затем bind
к этому интерфейсу на основе индекса интерфейса.
Поскольку вам известен тип интерфейса (например, вы выбрали eth0
или wifi и т. Д.), После этого вы сможете переваривать заголовок физического уровня, поскольку вы знаете, является ли он struct eth_hdr
или нет.
Обратите внимание, что существует ряд других SIOCGIF*
ioctl, которые вы можете использовать для получения списка интерфейсов и другой информации, которая может позволить вам различать тип интерфейса [и, следовательно, какой физический заголовок ожидать].
В любом случае, вот пример кода из того, что я сделал:
int
init(const char *intf)
// intf -- interface name (e.g. eth0, etc. -- whatever comes from ifconfig)
{
int err;
#if 1
int styp = SOCK_RAW;
#else
int styp = SOCK_DGRAM;
#endif
int netsock = socket(PF_PACKET,styp,htons(ETH_P_ALL));
struct ifreq ifr;
memset(&ifr,0,sizeof(ifr));
strncpy(ifr.ifr_name,intf,sizeof(ifr.ifr_name));
// get the index number of the interface
err = ioctl(ntc->ntc_sock,SIOCGIFINDEX,&ifr);
if (err < 0)
do_whatever;
printf("init: IFRIDX ifr_ifindex=%d\n",ifr.ifr_ifindex);
int ifidx = ifr.ifr_ifindex;
struct sockaddr_ll addr;
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = ifidx;
err = bind(netsock,(struct sockaddr *) &addr,
sizeof(struct sockaddr_ll));
if (err < 0)
do_whatever;
return netsock;
}