How to make TAP adapter accept all traffic form PC? - networking

I'm developing a client application to capture traffic on a PC. I'm using OpenVpn tun/tap adapter. But it dosen't work, when I'm testing application traffic goes through Wireless LAN adapter. How to make all traffic go through tun/tap adapter?
DWORD active = 1;
DWORD len;
int status = DeviceIoControl(handle,
TAP_CONTROL_CODE(6, 0), // TAP_IOCTL_SET_MEDIA_STATUS
&active,
sizeof(active),
&active,
sizeof(active),
&len,
NULL
);
if(status == 0)
{
return NULL;
}
int configtun[3] = {0x01000b0a, 0x01000b0a, 0x0000ffff}; // IP, NETWORK, MASK
configtun[0] = inet_addr(ip);
configtun[1] = inet_addr(ip);
char *p = (char*)(configtun+1);
*(p+3) = 0;
status = DeviceIoControl(handle,
TAP_CONTROL_CODE(10, 0), // TAP_IOCTL_CONFIG_TUN
&configtun,
sizeof(configtun),
&configtun,
sizeof(configtun),//active),
&len,
NULL
);
if(status == 0)
{
return NULL;
}

Related

netfilter_queue ipv4 optional header removal

I'm implementing netfilter_queue-based user program that deletes ipv4 optional header 'Time Stamp'
ping works well with this program, because it uses ICMP transmission.
But TCP-based applications doesn't work. I've checked it with wireshark, and this program deletes timestamp well. Instead, TCP-based application doesn't send ACK for that packet, and remote server retransmits the same packet indefinitely.
Is there any missing procedures for TCP packet processing? I just modified IPv4 header part only. Then why the tcp transmission doesn't work at all?
My main code is:
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data)
{
unsigned int timestamp = 0;
bool ptype = true;
int pnow = 20;
int plast = 20;
int ihl;
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
unsigned char* rawBuff = NULL;
int len;
len = nfq_get_payload(nfa, &rawBuff);
if(len < 0) printf("Failed to get payload");
struct pkt_buff* pkBuff = pktb_alloc(AF_INET, rawBuff, len, 0x20);
struct iphdr* ip = nfq_ip_get_hdr(pkBuff);
ihl = ip->ihl;
uint8_t* buff = NULL;
if( (ip->daddr != 0x0101007f) && (ip->daddr != 0x0100007f) && (ip->daddr != 0x0100A9C0) && (ip->saddr != 0x0100A9C0)) { // filter_out dns
if(ip->version == 4) {
if(ihl != 5) { // if ipv4 packet header is longer than default packet header
buff = pktb_data(pkBuff); // packet buffer
plast = ihl * 4;
while(pnow != plast) {
if(buff[pnow] == 0x44) { // timestamp type
ptype = false;
break;
}
else {
if(buff[pnow+1] == 0) {
pnow = pnow + 4;
}
else {
pnow = pnow + buff[pnow+1];
}
}
}
}
if(!ptype) {
timestamp = buff[pnow + 4] << 24 | buff[pnow + 5] << 16 | buff[pnow + 6] << 8 | buff[pnow + 7];
if(timestamp > 100000) { // if TS is big, delete it.
ip->ihl -= 2;
nfq_ip_mangle(pkBuff, pnow, 0, 8, "", 0);
}
}
}
}
nfq_ip_set_checksum(ip);
if(nfq_ip_set_transport_header(pkBuff, ip) < 0) printf("Failed to set transport header");
int result = 0;
result = nfq_set_verdict(qh, ntohl(ph->packet_id), NF_ACCEPT, pktb_len(pkBuff), pktb_data(pkBuff));
pktb_free(pkBuff);
return result;
}
iptables setting is:
sudo iptables -t mangle -A PREROUTING -j NFQUEUE -p all --queue-num 0
sudo iptables -t mangle -A POSTROUTING -j NFQUEUE -p all --queue-num 0
It seems that netfilter_queue is malfunctioning. After debugging Kernel, I could identify that skbuff's network_header pointer is not updated even I changed netfilter_queue's equivalent pointer. Mangled packet is dropped by packet length checking code.
Shouldn't you place the TCP header just after the IP header?
0...............20.........28..........48..........
+---------------+----------+-----------+-----------+
|IP HEADER |IP OPTIONS| TCP HEADER|TCP OPTIONS|
+---------------+----------+-----------+-----------+
So, decreasing ihl value, you're creating a gap between IP header and TCP header.
You need to use memmove along with decreasing ihl value.

ESP32 TCP client

I want to set up TCP server on windows and TCP client on ESP32. Main idea is to send String to ESP32 change it and send it back to server, but I'm really new with all of this stuff and got stuck on setting up TCP client on ESP32. Examples or references would be really helpful.
int create_ipv4_socket()
{
struct addrinfo hints;
struct addrinfo *res;
struct in_addr *addr;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int err = getaddrinfo(UDP_IPV4_ADDR, TCP_PORT, &hints, &res);
if(err != 0 || res == NULL) {
printf("DNS lookup failed err=%d res=%p\n", err, res);
return -1;
}
/* Code to print the resolved IP.
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
printf("DNS lookup succeeded. IP=%s\n", inet_ntoa(*addr));
l_sock = socket(res->ai_family, res->ai_socktype, 0);
if(l_sock < 0) {
printf("... Failed to allocate socket.\n");
freeaddrinfo(res);
return -1;
}
struct timeval to;
to.tv_sec = 2;
to.tv_usec = 0;
setsockopt(l_sock,SOL_SOCKET,SO_SNDTIMEO,&to,sizeof(to));
if(connect(l_sock, res->ai_addr, res->ai_addrlen) != 0) {
printf("... socket connect failed errno=%d\n", errno);
close(l_sock);
freeaddrinfo(res);
return -1;
}
printf("... connected\n");
freeaddrinfo(res);
// All set, socket is configured for sending and receiving
return l_sock;
}
From this forum https://www.esp32.com/viewtopic.php?t=5965
How do you communicate with your ESP? if you communicate through UART, just send him AT command he need by writing on the UART port:
"AT+CIPSTATUS\r\n"
and then wait for his response.
If you are connected to your ESP32 directly with your computer, just use putty and directly send AT command to it.
A non exhaustive list of AT's command can be found here:
https://www.espressif.com/sites/default/files/documentation/esp32_at_instruction_set_and_examples_en.pdf

Can't receive the response package by winsock2 from http server

I'm sure my program has got the ip from the server by the url.
When I send the GET request, although it was successfully send, it couldn't get the response. I'm not sure if the server had gotten my request, how should I check if the server get my request?
The connection will close after sending a request and waiting for a period of time . The "recv" function will response 0, and the buffer get nothing.
I wonder if there are any error of my "sendbuf = GET / HTTP/1.1\r\n\r\n".
Should I use 1.1 or 1.0?
char *sendbuf = "GET / HTTP/1.1\r\n\r\n";
//to get the ip from DNS server
pHostEnt = gethostbyname( "www.google.com.tw");
ppaddr = (int**)pHostEnt->h_addr_list;
sockAddr.sin_addr.s_addr = **ppaddr;
printf("%s",inet_ntoa(sockAddr.sin_addr) );
//to create the socket and connect to it
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(inet_ntoa(sockAddr.sin_addr));
serverAddress.sin_port = htons(SERVER_PORT);
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
connect(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
//send request
int iResult = send( serverSocket, sendbuf, (int)strlen(sendbuf), 0 );
//get response
if (bytesRead=recv(serverSocket, buf, MAX_SIZE, 0) < 0)
printf("Error with send()");
else
printf("Successfully sent html fetch response");
Using HTTP 1.1 is fine, but your request is incomplete as HTTP 1.1 requires the Host header, at the very least (in order for servers to support virtual hosts).
More importantly, you are not doing any error handling. You need to do that.
You are also not taking into account that gethostname() can return multiple IP addresses. You need to connect() to each address until one succeeds, or until you exhaust the list.
Try this:
char *sendbuf = "GET / HTTP/1.1\r\nHost: www.google.com.tw\r\n\r\n";
//to get the ip from DNS server
pHostEnt = gethostbyname( "www.google.com.tw"); // you should be using getaddrinfo() instead!
if (!pHostEnd)
{
printf("Unable to resolve www.google.com.tw\n");
return; // or whatever...
}
if (pHostEnt->h_addrtype != AF_INET)
{
printf("www.google.com.tw did not resolve to an IPv4 IP address\n");
return; // or whatever...
}
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET)
{
printf("Unable to create socket\n");
return; // or whatever...
}
in_addr **ppaddr = (in_addr**) pHostEnt->h_addr_list;
sockaddr_in serverAddress = {0};
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(SERVER_PORT);
bool connected = false;
int i = 0;
while (ppadd[i] != NULL)
{
// connect to server
serverAddress.sin_addr = *(ppaddr[i]);
printf("Connecting to %s\n", inet_ntoa(serverAddress.sin_addr);
if (connect(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == 0)
{
connected = true;
break;
}
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(serverSocket, &writefds);
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (select(0, NULL, &writefds, NULL, &timeout) > 0)
{
connected = true;
break;
}
}
++i;
}
if (!connected)
{
printf("Unable to connect to www.google.com.tw\n");
return; // or whatever...
}
printf("Connected, sending request\n");
//send request
char *ptr = sendbuf;
int len = strlen(sendbuf);
do
{
int bytesSent = send( serverSocket, ptr, len, 0 );
if (bytesSent > 0)
{
ptr += bytesSent;
len -= bytesSent;
continue;
}
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(serverSocket, &writefds);
timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;
if (select(0, NULL, &writefds, NULL, &timeout) > 0)
continue;
}
printf("Unable to send request\n");
return; // or whatever...
}
while (len > 0);
printf("Reading response\n");
//get response
do
{
int bytesRead = recv(serverSocket, buf, MAX_SIZE, 0);
if (bytesRead > 0)
{
// process buf as needed...
// make sure you are paying attention to the
// Content-Length and Transfer-Encoding headers,
// as they tell you how to read the response.
// Refer to RFC 2616 Section 4.4 for details...
contine;
}
if (bytesRead == 0)
{
printf("Disconnected");
return; // or whatever...
}
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(serverSocket, &readfds);
timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;
if (select(0, &readfds, NULL, NULL, &timeout) > 0)
continue;
}
printf("Unable to read response\n");
return; // or whatever...
}
while (true);
closesocket(serverSocket);

How to use function "send" (Winsock) to stream video in VS10 with OpenCV?

I used OpenCV on VS10 to stream video from my webcam. I also used winsock2 to transmit a message and an image in the same computer from server-client TCP/IP (local host). Now I'm trying to stream video in real-timing. I don't know if with function "send" I can specify the length of each frame because I think that it can also send a constant char. Anyone know what function could I use to solve my problem?
Source code:
Server.cpp
#include "Server.h"
using namespace std;
//Our main function
//void main()
int _tmain(int argc, _TCHAR* argv[])
{
//We have to start de Winsock-dll
long answer;
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD (2,1);
//Stard the dll
answer = WSAStartup(DLLVERSION, &wsaData);
//The dll was started, now I use the winsock funcitions in the program
//Structure for the sockets
SOCKADDR_IN addr;
//addr = our structure
int addrlen = sizeof(addr);
//Now we have to create our sockets
//sListen = socket which is listening for incoming connection
SOCKET sListen;
//sConnect = socket which is operating if a connection was found!
SOCKET sConnect;
//Now we have to setup our sockets:
//AF_INET = means that our socket belongs to the internet family
//SOCK_STREAM = means that our socket is a connection-orientated socket
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
//Now we have to setup our structure
//inet_addr = IP of our socket (I use 127.0.0.1...this is the loopback adress)
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Retype the family
addr.sin_family = AF_INET;
//Now we have to setup the port in the structure;
//Now our server has the IP: 127.0.0.1 and the port 1234
addr.sin_port = htons (1234);
//Now we have to setup our sListen socket
sListen = socket(AF_INET, SOCK_STREAM, NULL);
//Now we blind the socket
//The socket becomes the structure addr
bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
//We have to say that the socket is listening for an incoming connection
listen(sListen, SOMAXCONN);
//SOMAXCON means that the server is listenning without any limit
//We have to start the capture of the frames to send it
//Well first of all initialize the frames and the default camera
//Using OpenCV
CvCapture *capture = 0;
IplImage *frame = 0;
int key = 0;
capture = cvCaptureFromCAM(0);
//At last we have to say what the serve sould do if a connection was found!
//For this we create a endless loop:
for(;;)
{
cout << "Waiting for an incoming connection" <<endl;
//if a connection was found << "..." <<endl
if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
{
cout << "A connection was found" <<endl;
//Second part in reference to Youtube 2
//1r: The server should send a message with the funcion send();
//The number of the letters +1
//Ex: Number of the letters: 14+1=15
answer = send(sConnect, "Bonjour",8, NULL);
//*************************Third part of the project
//Sending an image captured from the cam
//always check
if ( !capture )
{
fprintf( stderr, "Cannot open initialize webcam!\n" );
return 1;
}
//create a window for the video
cvNamedWindow( "server", CV_WINDOW_AUTOSIZE );
while( key != 'q' )
{
//get a frame
frame = cvQueryFrame(capture);
//always check
if( !frame ) break;
//display current frame
cvShowImage( "server", frame );
//exit if user press 'q'
key = cvWaitKey(1);
}
char StartStream(IplImage *frame);
int streamSize(IplImage *frame);
if(frame!=0)
{
return sizeof(*frame->imageData);
}
char* buffer = new char[10000];
int len = 10000;
//int sent = 0;
for(int i=0; i<len; i+= answer)
{
answer = send(sConnect, buffer+i, len-i, 0);
}
}
//free memory
cvDestroyWindow( "server" );
cvReleaseCapture( &capture );
}
return 0;
}
Client.cpp
#include "Client.h"
using namespace std;
//void main()
int _tmain(int argc, _TCHAR* argv[])
{
string confirm;
char message[200];
string strmessage;
//IplImage *pImg;
//Start the functions of the Winsock-DLL
long answer;
WSAData wsaData;
WORD DLLVersion;
DLLVersion = MAKEWORD(2,1);
answer = WSAStartup(DLLVersion, &wsaData);
//Setup our Sockets and SOCKADDR_IN
SOCKADDR_IN addr;
//we will need addrlen later maybe!
int addrlen = sizeof(addr);
//Now setup our Socket
SOCKET sConnect;
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
//IP of our server
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Now we have to retype de family
addr.sin_family = AF_INET;
//Port of our server
addr.sin_port = htons(1234);
//Now we will ask the client if he wants to connect
cout << "Do you want to connect to your server? [Y/N]" <<endl;
cin >> confirm;
//If the user don't want to connect the client will close
if (confirm == "N")
{
exit(1);
}
else
{
if (confirm == "Y")
{
//function connect
connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
//Our client is working
//Now we program the client that he should recv a message from the server
//Our client should receive the message with the function recv();
//With new char "message"
answer = recv(sConnect, message, sizeof(message), NULL);
//The client should display the message
//With new string strmessage
strmessage = message;
cout << strmessage <<endl;
//the client also should display the image recived
char* buffer = new char[10000];
int len = 10000;
//int rec = 0;
int i=0;
for(int i=0; i<len; i+= answer)
{
while (answer = recv(sConnect, buffer+i, len-i, 0))
{
IplImage *frame = cvCreateImage(cvSize(640,480), 8, 3);
frame->imageData = (char *)buffer;
cvNamedWindow( "client", CV_WINDOW_AUTOSIZE );
cvShowImage( "client", frame );
}
return 0;
}
getchar();
}
}
getchar();
}
I receive the message and the confirmation of the connection in the server. And also it opens the webcam but the client doesn't receive anything.
You can try the cv_video_server and client.

Problem in listening to multicast in C++ with multiple NICs

I am trying to write a multicast client on a machine with two NICs, and I can't make it work. I can see with a sniffer that once I start the program the NIC (eth4) start receiving the multicast datagrams, However, I can't recieve() any in my program.
When running "tshark -i eth4 -R udp.port==xxx (multicast port)"
I get:
1059.435483 y.y.y.y. (some ip) -> z.z.z.z (multicast ip, not my eth4 NIC IP) UDP Source port: kkk (some other port) Destination port: xxx (multicast port)
Searched the web for some examples/explanations, but it seems like I do what everybody else does. Any help will be appreciated. (anything to do with route/iptables/code?)
bool connectionManager::sendMulticastJoinRequest()
{
struct sockaddr_in localSock;
struct ip_mreqn group;
char* mc_addr_str = SystemManager::Instance()->getTCP_IP_CHT();
char* local_addr_str = SystemManager::Instance()->getlocal_IP_TOLA();
int port = SystemManager::Instance()->getTCP_Port_CHT();
/* Create a datagram socket on which to receive. */
CHT_UDP_Feed_sock = socket(AF_INET, SOCK_DGRAM, 0);
if(CHT_UDP_Feed_sock < 0)
{
perror("Opening datagram socket error");
return false;
}
/* application to receive copies of the multicast datagrams. */
{
int reuse = 1;
if(setsockopt(CHT_UDP_Feed_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(CHT_UDP_Feed_sock);
return false;
}
}
/* Bind to the proper port number with the IP address */
/* specified as INADDR_ANY. */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(port);
localSock.sin_addr.s_addr =inet_addr(local_addr_str); // htonl(INADDR_ANY); //
if(bind(CHT_UDP_Feed_sock, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(CHT_UDP_Feed_sock);
return false;
}
/* Join the multicast group mc_addr_str on the local local_addr_str */
/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
group.imr_ifindex = if_nametoindex("eth4");
if (setsockopt(CHT_UDP_Feed_sock, SOL_SOCKET, SO_BINDTODEVICE, "eth4", 5) < 0)
return false;
group.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
group.imr_address.s_addr = htonl(INADDR_ANY); //also tried inet_addr(local_addr_str); instead
if(setsockopt(CHT_UDP_Feed_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(CHT_UDP_Feed_sock);
return false;
}
// Read from the socket.
char databuf[1024];
int datalen = sizeof(databuf);
if(read(CHT_UDP_Feed_sock, databuf, datalen) < 0)
{
perror("Reading datagram message error");
close(CHT_UDP_Feed_sock);
return false;
}
else
{
printf("Reading datagram message...OK.\n");
printf("The message from multicast server is: \"%s\"\n", databuf);
}
return true;
}
Just a thought, (I've not done much work with multicast), but could it be because you're binding to a specific IP address? The socket could be only accepting packets destined for it's bound IP address and rejecting the multicast ones?
Well, there is some time ago since I didn't play with multicast. Don't you need root/admin rights to use it? did you enable them when launching your program?

Resources