Monitoring Application Network Traffic in Qt - c++

I've been searching for this for a while, but is there a way to monitor the network traffic coming/going from a specific application using the appliances that are already built into the Qt library? I've found some solutions using things like WinPCap and other similar utilities, but I was hoping to keep it all in the Qt (in C++) house as that is what I am most familiar with.
Thanks! Any pointers are greatly appreciated!

Some example of c# sniffer socket creation.
mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw,
ProtocolType.IP);
// Bind the socket to the selected IP address
mainSocket.Bind(newIPEndPoint(IPAddress.Parse(cmbInterfaces.Text),0));
// Set the socket options
mainSocket.SetSocketOption(SocketOptionLevel.IP, //Applies only to IP packets
SocketOptionName.HeaderIncluded, //Set the include header
true); //option to true
byte[] byTrue = newbyte[4]{1, 0, 0, 0};
byte[] byOut = newbyte[4];
//Socket.IOControl is analogous to the WSAIoctl method of Winsock 2
mainSocket.IOControl(IOControlCode.ReceiveAll, //SIO_RCVALL of Winsock
byTrue, byOut);
//Start receiving the packets asynchronously
mainSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None,
newAsyncCallback(OnReceive), null);
May be qt provides some api for creating such sockets.After creating such socket you'll get raw pacets on it parsing headers and other info is on you.

Related

FTP NLST results in '425: Can't open data connection for transfer' only on some client machines

I'm currently running a FileZilla FTP server on a network. My issue is that on seemingly random machines, when the user navigates to a directory (which they are able to do) and attempts to ls (i.e. data transfer) their end hangs waiting for a response, while the server reports this 425: Can't open data connection for transfer mentioned above. This result varies depending on the client machine used, where some (either local or remote) are able to proceed and others stuck here. I understand that this is because simple FTP commands like CWDing operate on the 20/21 ports, whereas FTP data transfer operate on some other port number, which in turn may be blocked by a firewall somewhere along the chain. My question is, how do I account for these varying ports (if this truly is the issue), as as best I know they could be anything above 1024?
My end goal with this project is to implement a very simple FTP solution, ideally using WinINet, however, so far I've run into the same problem:
BOOL CWebFileFinder::FindFile(const CString& URL)
{
CString ServerName;
CString strObject;
INTERNET_PORT nPort;
DWORD dwServiceType = AFX_INET_SERVICE_FTP;
if (AfxParseURL(URL, dwServiceType, ServerName, strObject, nPort))
{
m_Connection = m_Session.GetFtpConnection(ServerName, m_Username, m_Password, nPort/*, true*/); // results in findfile still failing
if (m_Connection)
{
m_Connection->SetCurrentDirectory("sms"); // CDs into this dir
m_Finder = new CFtpFileFind(m_Connection);
if (m_Finder)
{
More = m_Finder->FindFile(_T("*.*")); // hangs here
}
}
}
catch (CException* pEx)
{
CString str;
LPTSTR error = str.GetBuffer(255);
pEx->GetErrorMessage(error, 255);
pEx->Delete();
str.ReleaseBuffer();
}
return More;
}
As far as I can see, either I need to call to open this data port prior to the LIST, or find the firewalls blocking these ports and create a rule to prevent that (What ports does Wininet listen on for Active FTP data connection?). Of course I could also be just completely off-base – Any insights at all would be greatly appreciated!
Your FTP server seems to require an encrypted connection (TLS/SSL).
WinInet does not support encrypted FTP.
See C++/Win32 The basics of FTP security and using SSL.

LibUV create UDP stream from existing socket

I know very little about how unix works, so please excuse my ignorance.
I have a path to a socket on my linux box, /data/sock/socket.
I want to send data to that socket with LibUV, but I am unsure how to go about that.
I currently have it set up to create its own socket,
uv_udp_t m_socket;
uv_udp_send_t m_send_req;
sockaddr_in m_addr;
uv_udp_init(uv_default_loop(), &m_socket);
uv_ip4_addr("0.0.0.0", 8008, &m_addr);
char buff[6] = "Hello\0";
auto buf = uv_buf_init(buff, 6);
uv_udp_send(&m_send_req, &m_socket, &buf, 1, (const struct sockaddr*)&m_addr, NULL);
How can I use the socket I have on my filesystem, rather than using the one created through code?
Those sockets are called "local domain" sockets, and not UDP sockets. Fortunately, LibUV does support those (only on UNIX, obviously; although on Windows the same LibUV API use "Named Pipes" under the hood.)
Anyways... In short, you have to use the pipe API (i.e. uv_pipe_init and uv_pipe_bind()/uv_pipe_connect,) instead of uv_udp_* functions.
You can find the documentation for LibUV's pipe API here.

C++: One client communicating with multiple server

I was wondering, if it is possible to let one client communicate with multiple server at the same time. As far as I know, common browsers like for example firefox are doing exactly this.
The problem I have now is, that the client has to listen and wait for data from the server, rather then requesting it itself. It has to listen to multiple server at once. Is this even possible? What happens if the client is listening to server 1 and server 2 sends something? Is the package lost or will it be resend until the client communicates a successful receival? The protocol used is TCP.
edit: platform is Windows. Thanks for pointing this out Arunmu.
This is nothing different from regular socket programming using select/poll/epoll OR using thread-pool OR using process-per-connection OR whatever model that you know.
I can show you a rough pseudo-code on how to do it with epoll.
NOTE: None of my functions exist in C++, its just for explanation purpose. ANd I am ALSO assuming that you are on Linux, since you have mentioned nothing about the platform.
socket sd = connect("server.com", 8080);
sd.set_nonblocking(1);
epoll_event event;
event.data.fd = sd
epoll_ctl(ADD, event);
...
...
while (True) {
auto n = epoll_wait(events, 1);
for (int i : 1...n) {
if (events[i].data.fd == sd) // The socket added in epoll_ctl
{
std::thread(&Session::read_handler, rd_hndler_, sd); // Call the read in another thread or same thread
}
}
}
I hope you got the gist. In essence, think of server like a client and client like a server and you have your problem solved (kind of). Check out below link to know more about epoll
https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/
To see an fully functional server design using epoll, checkout:
https://github.com/arun11299/cpp-reactor-server/blob/master/epoll/reactor.cc

TCP IOCP won't receive after acceptex

I'm trying to write an IOCP server. Basically, I have it accepting new connections. For the purpose of my testing, I'm running and connecting to 127.0.0.1.
I create the pseudo socket prior to calling AcceptEx(). Once a connection is accepted, the new pseudo socket is used for communication. This new socket is associated with an io completion port [CreateIoCompletionPort], I then assign it a few options, [SO_EXCLUSIVEADDRUSE] and [SO_CONDITIONAL_ACCEPT], and then I call WSARecv() to accept incoming data.
The problem is that once my remote connection connects to the server, it sends data, but that data is never received. I'm wondering if someone could offer some ideas as to why it's not receiving data? Perhaps my logic is flawed? I stepped through my code several times. no errors are recorded.
EDIT: Fixed the wording. I create the socket before AcceptEx() call.
Basic logic in my code:
// Create socket, associate with IOCP
WSASocket(af, type, proto, lpProtoInfo, g, dwFlags);
HANDLE hIOCP = GetPool()->GetQueueHandle();
CreateIoCompletionPort(hSource, hIOCP, 0, 0) != NULL;
// Server bind and listen
bind(m_shSocket, pAddr, nAddrLen);
listen(m_shSocket, nBacklog);
// Creation of the pseudo socket
SOCKET s = ::WSASocket(m_iSocketAf, m_iSocketType, m_iSocketProto, m_pWpi, m_SocketGroup, m_dwSocketFlags);
DWORD dwBytes;
BOOL bRet = m_fnAcceptEx(m_shSocket, s, chOutput, 0, sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16, &dwBytes, m_pcbAccept);
// ... New Connection comes in, it's accepted ...
// Associate new pseudo socket with IOCP
HANDLE hNewIOCP = GetPool()->GetQueueHandle();
CreateIoCompletionPort((HANDLE) s, hNewIOCP , 0, 0) != NULL;
// ... Remote socket sends ...
// ... Remote socket and Pseudo socket call WSARecv ...
// ... Pseudo socket does not receive ...
NOTE: I tried sending from the pseudo socket to the remote socket, same problem as sending data in the reverse way.
You need to post some code but your description doesn't make sense. That's NOT how AcceptEx() based servers operate.
With an AcceptEx() based server you create your accepted socket before you post the AcceptEx(). You then post the AcceptEx() with the listening socket and the new socket and a buffer which allows you to receive the remote address and, optionally, data.
So if you are describing your code in your original question then your code is wrong or you're not using AcceptEx(). I'm currently ignoring the 'few options' that you throw into the mix as they simply further confuse things at present without any code to analyse.
You might be interested in downloading my free IOCP based server framework, which includes working AcceptEx() and traditional Accept() based server code. You can get it from here: http://www.serverframework.com/products---the-free-framework.html
Are you calling GetQueuedCompletionStatus to get the data?
In case you are not doing this just to learn for yourself, I would also recommend that you use boost::asio - an excellent library that allows you to let someone else do the tedious code for handling the io completion ports.
I figured it out. I'm an idiot. I was sending zero bytes.

How do I receive raw, layer 2 packets in C/C++?

How do I receive layer 2 packets in POSIXy C++? The packets only have src and dst MAC address, type/length, and custom formatted data. They're not TCP or UDP or IP or IGMP or ARP or whatever - they're a home-brewed format given unto me by the Hardware guys.
My socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW) never returns from its recvfrom().
I can send fine, I just can't receive no matter what options I fling at the network stack.
(Platform is VxWorks, but I can translate POSIX or Linux or whatever...)
receive code (current incarnation):
int s;
if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) {
printf("socket create error.");
return -1;
}
struct ifreq _ifr;
strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0"));
ioctl(s, IP_SIOCGIFINDEX, &_ifr);
struct sockaddr_ll _sockAttrib;
memset(&_sockAttrib, 0, sizeof(_sockAttrib));
_sockAttrib.sll_len = sizeof(_sockAttrib);
_sockAttrib.sll_family = AF_PACKET;
_sockAttrib.sll_protocol = IFT_ETHER;
_sockAttrib.sll_ifindex = _ifr.ifr_ifindex;
_sockAttrib.sll_hatype = 0xFFFF;
_sockAttrib.sll_pkttype = PACKET_HOST;
_sockAttrib.sll_halen = 6;
_sockAttrib.sll_addr[0] = 0x00;
_sockAttrib.sll_addr[1] = 0x02;
_sockAttrib.sll_addr[2] = 0x03;
_sockAttrib.sll_addr[3] = 0x12;
_sockAttrib.sll_addr[4] = 0x34;
_sockAttrib.sll_addr[5] = 0x56;
int _sockAttribLen = sizeof(_sockAttrib);
char packet[64];
memset(packet, 0, sizeof(packet));
if (recvfrom(s, (char *)packet, sizeof(packet), 0,
(struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0)
{
printf("packet receive error.");
}
// code never reaches here
I think the way to do this is to write your own Network Service that binds to the MUX layer in the VxWorks network stack. This is reasonably well documented in the VxWorks Network Programmer's Guide and something I have done a number of times.
A custom Network Service can be configured to see all layer 2 packets received on a network interface using the MUX_PROTO_SNARF service type, which is how Wind River's own WDB protocol works, or packets with a specific protocol type.
It is also possible to add a socket interface to your custom Network Service by writing a custom socket back-end that sits between the Network Service and the socket API. This is not required if you are happy to do the application processing in the Network Service.
You haven't said which version of VxWorks you are using but I think the above holds for VxWorks 5.5.x and 6.x
Have you tried setting the socket protocol to htons(ETH_P_ALL) as prescribed in packet(7)? What you're doing doesn't have much to do with IP (although IPPROTO_RAW may be some wildcard value, dunno)
I think this is going to be a bit tougher problem to solve than you expect. Given that it's not IP at all (or apparently any other protocol anything will recognize), I don't think you'll be able to solve your problem(s) entirely with user-level code. On Linux, I think you'd need to write your own device agnostic interface driver (probably using NAPI). Getting it to work under VxWorks will almost certainly be non-trivial (more like a complete rewrite from the ground-up than what most people would think of as a port).
Have you tried confirming via Wireshark that a packet has actually been sent from the other end?
Also, for debugging, ask your hardware guys if they have a debug pin (you can attach to a logic analyzer) that they can assert when it receives a packet. Just to make sure that the hardware is getting the packets fine.
First you need to specify the protocol as ETH_P_ALL so that your interface gets all the packet. Set your socket to be on promiscuous mode. Then bind your RAW socket to an interface before you perform a receive.