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);
}
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.