Raw socket with device bind using setsockopt() system is not working in Fedora core 6(2.6.18-1.2798.fc6)
Solution 1
In the linux man page (http://linux.die.net/man/7/socket) :
SO_BINDTODEVICE
Bind this socket to a particular device like "eth0", as specified 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-terminated 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(2) there).
So, try the bind instead.
Solution 2
Thanks all,thanks you very much for valuable time. it is worked with bind approach The code segments had helped me.
setsockopt()
is bug in the fedora 2.6.18
alternative approach is below.
void BindToInterface(int raw , char *device , int protocol) {
struct sockaddr_ll sll;
struct ifreq ifr; bzero(&sll , sizeof(sll));
bzero(&ifr , sizeof(ifr));
strncpy((char *)ifr.ifr_name ,device , IFNAMSIZ);
//copy device name to ifr
if((ioctl(raw , SIOCGIFINDEX , &ifr)) == -1)
{
perror("Unable to find interface index");
exit(-1);
}
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(protocol);
if((bind(raw , (struct sockaddr *)&sll , sizeof(sll))) ==-1)
{
perror("bind: ");
exit(-1);
}
return 0;
}
Admin
Updated on June 09, 2022Comments
-
Admin almost 2 years
Please any one could help on this issue. Please
In the below sample code,we had bind raw sock with eth0. but while running the program the recvfrom of raw sock is receiving packets from eth0 & eth1 on same machine(xx_86). It is not clear to me why,could help one on this issue. I hope the setsockopt is not working properly OS: Fedora core 6(2.6.18-1.2798.fc6)
Sampe code:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <linux/if_ether.h> #include <net/if.h> #include <linux/filter.h> #include <sys/ioctl.h> #include <string.h> #include <arpa/inet.h> int main(int argc, char **argv) { int sock, i; unsigned char buffer[2048]; unsigned char tbuff[2048]; unsigned char *iphead, *ethhead,*phead; struct ifreq ethreq; // NOTE: use TCPDUMP to build the filter array. // set filter to sniff only port 443 // $ sudo tcpdump -dd port 443 // raw for recvfrom eth0 if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) == -1) { perror("socket"); exit(1); } // set network card to promiscuos strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); if (ioctl(sock,SIOCGIFFLAGS, ðreq) == -1) { perror("ioctl"); close(sock); exit(1); } ethreq.ifr_flags |= IFF_PROMISC; if (ioctl(sock, SIOCSIFFLAGS, ðreq) == -1) { perror("ioctl"); close(sock); exit(1); } //bind to sock with eth0 struct ifreq Interface; memset(&Interface, 0, sizeof(Interface)); strncpy(Interface.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ); if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &Interface, sizeof(Interface)) < 0) { close(sock); } //open the RAW socket for sendto int s = socket (PF_INET, SOCK_RAW, IPPROTO_RAW); struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(0); sin.sin_addr.s_addr = inet_addr ("10.3.161.104"); // inform kernal don't fill IP and Transport header int one = 1; const int *val = &one; if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) printf ("Warning: Cannot set HDRINCL!\n"); //bind the sock descriptor with eth0 struct ifreq Interface1; memset(&Interface1, 0, sizeof(Interface1)); strncpy(Interface1.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ); if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &Interface1, sizeof(Interface1)) < 0) { close(s); } while (1) { printf("----------------------\n"); i = recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL); printf("%d bytes read\n", i); // check header size: Ethernet = 14, IP = 20, TCP = 8 (sum = 42) if (i < 42) { perror("recvfrom():"); printf("Incomplete packet (errno is %d)\n", errno); close(sock); exit(0); } phead = buffer + 14; // (skip ethernet header) memcpy(tbuff,phead,i-14); iphead=tbuff; if (*iphead == 0x45) { int ptrindex= iphead[9]; switch(ptrindex){ case 1: printf("The transport protocl is:ICMP\n"); break; case 2: printf("The transport protol is:IGMP\n"); break; case 6: printf("The transport protocol is:TCP\n"); break; case 17: printf("The transport protocol is:UDP\n"); break; case 103: printf("The transport protocol is:PIM\n"); break; default: printf("The transport protocol is:%d\n",iphead[9]); } //printf("%d",*ptrindex); // printf("\n The transport protocol is :%u\n",iphead[9]); printf("Source Address: %d.%d.%d.%d, Port: %d\n", iphead[12], iphead[13], iphead[14], iphead[15], (iphead[20] << 8) + iphead[21]); printf("Dest Address: %d.%d.%d.%d, Port: %d\n", iphead[16], iphead[17], iphead[18], iphead[19], (iphead[22] << 8) + iphead[23]); if(sendto(s,tbuff,i-14,0,(struct sockaddr *)&sin,sizeof(sin))<0) printf("error\n"); else{printf("\nThe received packet is send\n");} memset(buffer,0,sizeof(buffer)); memset(tbuff,0,sizeof(tbuff)); } else{ printf("The non ip had received");} } close(sock); }
-
Admin about 12 yearsThanks all,thanks you very much for vaulable time. it is worked with bind approach