Raw Socket promiscuous mode not sniffing what I write
The solution is to look in the read packet if it is a PACKET_OUTGOING. Using this option you can diference the packet you put in the ethernet tx wire and the packet you read from the rx wire.
Open the Socket in promiscuous mode:
char* i = "eth0";
int fd;
struct ifreq ifr;
struct sockaddr_ll interfaceAddr;
struct packet_mreq mreq;
if ((fd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))) < 0)
return -1;
memset(&interfaceAddr,0,sizeof(interfaceAddr));
memset(&ifr,0,sizeof(ifr));
memset(&mreq,0,sizeof(mreq));
memcpy(&ifr.ifr_name,i,IFNAMSIZ);
ioctl(fd,SIOCGIFINDEX,&ifr);
interfaceAddr.sll_ifindex = ifr.ifr_ifindex;
interfaceAddr.sll_family = AF_PACKET;
if (bind(fd, (struct sockaddr *)&interfaceAddr,sizeof(interfaceAddr)) < 0)
return -2;
mreq.mr_ifindex = ifr.ifr_ifindex;
mreq.mr_type = PACKET_MR_PROMISC;
mreq.mr_alen = 6;
if (setsockopt(fd,SOL_PACKET,PACKET_ADD_MEMBERSHIP,
(void*)&mreq,(socklen_t)sizeof(mreq)) < 0)
return -3;
//...
And read. Now, We can differentiate between the Rx and Tx ethernet wire:
unsigned char buf[1500];
struct sockaddr_ll addr;
socklen_t addr_len = sizeof(addr);
n = recvfrom(fd, buf, 2000, 0, (struct sockaddr*)&addr, &addr_len);
if (n <= 0)
{
//Error reading
}
else if (addr.sll_pkttype == PACKET_OUTGOING)
{
//The read data are not writing by me.
//Use only this data to copy in the other network.
}
And it's all. Using it I don't read the data I write. I avoid the loop when I copy the network 1 frames to network 2 and the network 2 frames to network 1.
Packet socket in promiscuous mode only receiving local traffic
Along with Rob Jones' suggestion, try a tool like Wireshark to make sure that you're receiving the packets that you expect at the interface. At least that will confirm (or deny) that you have a problem with your code.
Also need to make sure that the interface itself is set to promiscuous mode.
If not then you can use the ioctl() to set it:
ifr.ifr_flags |= IFF_PROMISC;
if( ioctl(sock, SIOCSIFFLAGS, &ifr) != 0 )
{
// handle error here
}
While your application is running, make sure that ifconfig reports the PROMISC flag for that interface.
Note that this will need to be executed as a privileged user.
Tried out the code as presented. Works for me. Of course (due to the test on line 102) this will only print details for TCP traffic.
Is it possible to inject on a raw socket while sniffing in promiscous mode?
The short answer is yes. Below is the longer one...
I know that for normal promiscous mode operation of a wireless card, your not suppose to be able to interact with the network
I am not sure where you have got this knowledge from but the above statement is wrong. A promiscuous mode does not restrict what you can do and how you can interact with the network. By default, network interface cards are simply trying to reduce the amount of data they pass to the host for better efficiency. For example, NICs would not pass an Ethernet frame to the host if its destination MAC address does not match the address of the receiving media access controller. The only thing that promiscuous mode does is simply tells the device to pass everything it gets to the host, be that frame addressed for the host or not. In other words, whatever you were able to do with NIC in a normal operation mode, you can still do when it is in promiscuous mode. Plus, NIC does not filter anything for you anymore, so you can receive more (as long as the host can handle the load).
but is it possible to do it with raw sockets?
Yes, it is possible. As long as you have enough privileges, you can send and receive Ethernet frames from user-space using "raw" sockets API. Whether a devices is in promiscuous mode or not does not make any difference.
Also note that these days routers are very smart and they won't forward packets to your host even if you put your host's NIC into promiscuous mode. So in the right network your are not likely to receive anything that in fact is not intended for your host, and promiscuous mode won't make any difference.
If that helps, here is a simple example of exchanging custom packets with an FPGA board connected to the PC over Ethernet. It uses raw socket API and runs in user-space on Linux.
Reading from a promiscuous network device
On Linux you use a PF_PACKET socket to read data from a raw device, such as an ethernet interface running in promiscuous mode:
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
This will send copies of every packet received up to your socket. It is quite likely that you don't really want every packet, though. The kernel can perform a first level of filtering using BPF, the Berkeley Packet Filter. BPF is essentially a stack-based virtual machine: it handles a small set of instructions such as:
ldh = load halfword (from packet)
jeq = jump if equal
ret = return with exit code
BPF's exit code tells the kernel whether to copy the packet to the socket or not. It is possible to write relatively small BPF programs directly, using setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, ). (WARNING: The kernel takes a struct sock_fprog, not a struct bpf_program, do not mix those up or your program will not work on some platforms).
For anything reasonably complex, you really want to use libpcap. BPF is limited in what it can do, in particular in the number of instructions it can execute per packet. libpcap will take care of splitting a complex filter up into two pieces, with the kernel performing a first level of filtering and the more-capable user-space code dropping the packets it didn't actually want to see.
libpcap also abstracts the kernel interface out of your application code. Linux and BSD use similar APIs, but Solaris requires DLPI and Windows uses something else.
Raw socket bound to device not receiving all packets
The reason of receiving packets directed only to IP of your device is that you are using PF_INET
raw socket. When PF_INET
raw socket is used - skb
faces different sanity checks when goes across the stack (see below).
F.e. :
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
/*...*/
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
So the call trace is something like: __netif_receive_skb_core()
->ip_rcv()
->...->ip_local_deliver()
->...->raw_local_deliver()
->raw_rcv()
->...->tcp_rcv()
(you can check trace through the trace-cmd
).
But tcpdump/Wireshark obtains packets around __netif_receive_skb_core()
, i.e. before some sanity checks. Hence is discrepancy that confused you.
Therefore if you want skb
's to bypass a large part of Linux kernel network stack - you should use PF_PACKET
raw sockets.
Useful link
How do I create a tcp socket in promiscuous mode?
You want to use libpcap to grab raw packets. Run man 3 pcap
to get a list of all the relevant functions.
Related Topics
Are There in X86 Any Instructions to Accelerate Sha (Sha1/2/256/512) Encoding
Linux Executable Can't Find Shared Library in Same Folder
How Get Uuid of a Device/Partition in Linux Programatically
Struct Member Alignment - How to Assume No Padding
What Does ## in a #Define Mean
Error C2228: Left of '.Size' Must Have Class/Struct/Union
Std::Istream_Iterator<> with Copy_N() and Friends
C++ Is It Necessary to Delete Dynamically Allocated Objects at the End of the Main Scope
Issue Using Visual Studio 2010 Compiled C++ Dll in Windows 2000
How to Properly Setup Googletest on Os X Aside from Xcode
Unresolved Externals Despite Linking in Zlib.Lib
Std::Thread - "Terminate Called Without an Active Exception", Don't Want to 'Join' It
Qt - Qpushbutton Text Formatting
Redirecting Function Output to /Dev/Null
How to Format a Datetime to String Using Boost