It’s needed to read raw data from one interface and send it via another.
open&&config(the same for sock_raw_outer):
sock_raw_inner = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); setsockopt(sock_raw_inner, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 4); struct ifreq if_idx1; memset(&if_idx1, 0, sizeof(struct ifreq)); strncpy(if_idx1.ifr_name, opt, strlen(opt)); ioctl(sock_raw_inner, SIOCGIFINDEX, &if_idx1);
then in cycle:
data_size = recvfrom(sock_raw_inner, buffer, 65536, MSG_DONTWAIT, NULL, NULL); if (data_size > 0) { struct sockaddr_ll socket_address; socket_address.sll_ifindex = if_idx2.ifr_ifindex; socket_address.sll_halen = ETH_ALEN; //copy dest socket_address.sll_addr[0] = buffer[0]; socket_address.sll_addr[1] = buffer[1]; socket_address.sll_addr[2] = buffer[2]; socket_address.sll_addr[3] = buffer[3]; socket_address.sll_addr[4] = buffer[4]; socket_address.sll_addr[5] = buffer[5]; sendto(sock_raw_outer, buffer, size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) }
then, if I catch on sock_raw_inner any packet(arp request, for example), it sended on sock_raw_inner again and again by sendto. What’s wrong? Thanks.
Advertisement
Answer
Your sock_raw_inner is still listening on every interface because the bind on eth0 you are trying to perform is not supported. So the packet sent to another interface is indeed then received by your sock_raw_inner
Extract from man (7) socket (see bold text)
SO_BINDTODEVICE Bind this socket to a particular device like “eth0”, as speci- fied in the passed interface name. If the name is an empty string or the option length is zero, the socket device binding is removed. The passed option is a variable-length null termi- nated interface name string with the maximum size of IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this only works for some socket types, particularly AF_INET sockets. It is not supported for packet sockets (use normal bind(8) there).