Reinjecting modified packets in netfilter module - c++

I have used netfiler_queue to create a NFQUEUE module for iptables that handles all outgoing UDP packets.
I want to modify all UDP packets that match a certain pattern, and reinject them into the network.
Here is some example code:
...
static int Callback( nfq_q_handle *myQueue, struct nfgenmsg *msg, nfq_data *pkt, void *cbData) {
uint32_t id = 0;
nfqnl_msg_packet_hdr *header;
if ((header = nfq_get_msg_packet_hdr(pkt))) {
id = ntohl(header->packet_id);
}
// Get the packet payload
unsigned char *pktData;
int len = nfq_get_payload(pkt, &pktData);
// The following is an example.
// In reality, it involves more parsing of the packet payload.
if (len && pktData[40] == 'X') {
// Modify byte 40
pktData[40] = 'Y';
}
// Pass through the (modified) packet.
return nfq_set_verdict(myQueue, id, NF_ACCEPT, 0, NULL);
}
...
int main(){
...
struct nfq_handle nfqHandle;
nfq_create_queue(nfqHandle, 0, &Callback, NULL)
...
return 0;
}
The modified packet does not get reinjected into the stream. How would I inject the modified version of the packet?

Two things. First:
return nfq_set_verdict(myQueue, id, NF_ACCEPT, 0, NULL);
should be:
return nfq_set_verdict(myQueue, id, NF_ACCEPT, len, pktData);
That tells it you want to send a modified packet. (you might need some type casting)
Second, you just modified the packet. The IP stack isn't helping you out any more at this point, so you'll need to recompute the UDP checksum for that packet, or zero it out so the other end won't even check it.
The UDP checksum will live in bytes 0x1A and 0x1B of your packet, so this will zero them out:
pktData[0x1a] = 0;
pktData[0x1b] = 0;
and then your packet will go through.

Related

using DPDK-basicfwd example how to send custom packet to desired port

Requirement: I would like to make use of DPDK basicfwd, to send back custom reply to the incoming port.
Explanation:
DPDK ports: Port-0 and Port-1
Sample code: edited DPDK basicfwd.
Custom Function: PacketHandler()
Requirement: Sometimes I need to send custom packet(kind of RST packet) to incoming port.
example: Port-0 -> RX burst -> PacketHandler() -> normal packets fwd to Port-1, special packets send back to Port-0
Code Snippet:
while (isRun) {
num_rx = rte_eth_rx_burst(port_id, queue_id, mbufs, BURST_SIZE);
if (num_rx == 0) {
continue;
}
num_tx = 0;
for (int idx = 0; idx < num_rx; idx++) {
struct pcap_pkthdr pktHdr;
gettimeofday(&pktHdr.ts, NULL);
pktHdr.caplen = rte_pktmbuf_pkt_len(mbufs[idx]);
pktHdr.len = rte_pktmbuf_pkt_len(mbufs[idx]);
if (PacketHandler(&pktHdr, rte_pktmbuf_mtod(mbufs[idx], unsigned char *)) > 1) {
printf("Blocked Packets, do not fwd");
//TODO: send custom packet to incoming way
rte_pktmbuf_free(mbufs[idx]);
continue;
}
txbufs[num_tx++] = mbufs[idx];
}
if (num_tx > 0) {
sent = rte_eth_tx_burst(port_id ^ 1, queue_id, txbufs, num_tx);
for (int idx = sent; idx < num_tx; idx++) {
rte_pktmbuf_free(txbufs[idx]);
}
}
}
My custom packet type is u_char. How can i send my packet to incoming way?
Thanks
Option 1: Simple way (but can affect performance)
get packets via rte_eth_rx_burst
iterate packets, to update dest_port = PacketHandler() ? mbufs[idx]->port : (mbufs[idx]->port ^ 1)
Send packet out with rte_eth_tx_burst with dest_port
Comment out the tx_burst generic call below.
Option 2:
Create 2 mbuf-array namely mbufs_inport, and mbufs_outport.
Iterate packets, to invoke PacketHandler(). Matching Packets goes to mbufs_inport and non-matching goes to mbufs_outport
to invoke rte_eth_tx_burst for mbufs_inport and mbufs_outprt.
Option 3:
register rx-callback to filter packets with packethandler.
Now you have the option to directly send back the selected back based on mbuf->portid. While non-matching packets continue in the main loop.
If there is concern about packet order or previous packets needs to be processed, make use of mbuf-udata64 as a place holder for exit port. For cases not matching set is as -1. Then in the main loop, you have convert tx_burst for n packets to iterate for each as you have to check for udata64 value.

Recv function for TCP Socket programming

I am new in Socket Programming. I am trying to create a client application. The server is a camera which communicates using TCP. The camera is sending continuous data. Using Wireshark, I can see that the camera is sending continuous packets of different sizes, but not more than 1514 bytes. But my recv function is always returning 2000 which is the size of my buffer.
unsigned char buf[2000];
int bytesIn = recv(sock, (char*)buf, sizeof(buf) , 0);
if (bytesIn > 0)
{
std::cout << bytesIn << std::endl;
}
The first packet I receive is of size 9 bytes, which recv returns correct, but after that it always returns 2000.
Can anyone please tell me the solution so that I can get the correct size of the actual data payload?
EDIT
int bytesIn = recv(sock, (char*)buf, sizeof(buf) , 0);
if (bytesIn > 0)
{
while (bytes != 1514)
{
if (count == 221184)
{
break;
}
buffer[count++] = buf[bytes++];
}
std::cout << count;
}
EDIT:
Here is my Wireshark capture:
My Code to handle packets
int bytesIn = recv(sock, (char*)&buf, sizeof(buf) , 0);
if (bytesIn > 0)
{
if (flag1 == true)
{
while ((bytes != 1460 && (buf[bytes] != 0)) && _fillFlag)
{
buffer[fill++] = buf[bytes++];
if (fill == 221184)
{
flag1 = false;
_fillFlag = false;
fill = 0;
queue.Enqueue(buffer, sizeof(buffer));
break;
}
}
}
if ((strncmp(buf, _string2, 10) == 0))
{
flag1 = true;
}
}
For each frame camera is sending 221184 bytes and after each frame it sends a packet of data 9 bytes which I used to compare this 9 bytes are constant.
This 221184 bytes send by camera doesn't have 0 so I use this condition in while loop. This code is working and showing the frame but after few frame it shows fully black frame. I think the mistake is in receiving the packet.
Size of per frame is : 221184 (fixed)
Size of per recv is : 0 ~ 1514
My implementation here :
DWORD MakeFrame(int socket)
{
INT nFrameSize = 221184;
INT nSizeToRecv = 221184;
INT nRecvSize = 2000;
INT nReceived = 0;
INT nTotalReceived = 0;
BYTE byCamera[2000] = { 0 }; // byCamera size = nRecvSize
BYTE byFrame[221184] = { 0 }; // byFrame size = nFrameSize
while(0 != nSizeToRecv)
{
nRecvSize = min(2000, nSizeToRecv);
nReceived = recv(socket, (char*)byCamera, nRecvSize, 0);
memcpy_s(byFrame + nTotalReceived, nFrameSize, byCamera, nReceived);
nSizeToRecv -= nReceived;
nTotalReceived += nReceived;
}
// byFrame is ready to use.
// ...
// ...
return WSAGetLastError();
}
The first packet I receive is of size 9 bytes which it print correct after that it always print 2000. So can anyone please tell me the solution that I only get the size of actual data payload.
TCP is no packet-oriented, but a stream-oriented transport protocol. There is no notion of packets in TCP (apart maybe from a MTU). If you want to work in packets, you have to either use UDP (which is in fact packet-oriented, but by default not reliable concerning order, discarding and alike) or you have to implement your packet logic in TCP, i.e. reading from a stream and partition the data into logical packets once received.

DPDK packet lost and disorder

I did a simple test program using DPDK: program1 in computer1 is to send packet, and program2 in computer2 is to receive packet. computer1 and computer2 are directly connected, no switch.
In program 1, I use a packId to indicate the sequence of packet id.
while(true){
pkt = rte_pktmbuf_alloc(mbuf_pool);
uint8_t* pchar = rte_pktmbuf_mod(pkt, uint8_t*);
//set mac address and packet length. (pkt 0 to pkt 13).
//use from byte 14 to store uint_64 packId;
uint64_t* pPackId = (uint64_t*)(pchar+14);
*pPackId = packId;
packId++;
//put 1024 bytes data inside packet.
uint16_t sent = rte_eth_tx_burst(0, 0, &pkt, 1);
while(sent!=1)
{
sent = rte_eth_tx_burst(0, 0, &pkt, 1);
}
}
In receiver, i define long RX ring: nb_rxd=3072:
rte_eth_dev_adjust_nb_rx_tx_desc(0, &nb_rxd, &nb_txd);
rte_eth_rx_queue_setup(0, 0, nb_rxd, rte_eth_dev_socket_id(0), NULL, mbuf_pool);
There is a for loop to receive packets, and check packet sequence id.
for(;;)
{
strcut rte_mbuf *bufs[32];
const uint16_t nb_rx = rte_eth_rx_burst(0, 0, bus, 32);
if(unlikely(nb_rx==0))
continue;
int m = 0;
for (m=0; m<nb_rx;m++)
{
uint8_t* pchar = rte_pktmbuf_mtod(buf[m], uint8_t*);
uint64_t* pPackId = pchar+14;
uint64_t packid = *pPackId;
if(expectedPackid!=packid){
printf...
expectedPackid = packid+1;
}
else expectedPackid++;
}
}
Based on program2, I see a lot of packet lost and disorder. The received packet is put inside the ring buffer. Should it receive in order, and I also find there is packet lost, but my program1's sending speed is only around 1gbps.
rte_eth_stats_get() is very useful for troubleshooting. From the rte_eth_stats, I found ipackets is correct, q_ipackets[0] is correct, and imissed is 0, ierrors is 0, rx_nombuf is 0, q_errors[0] is 0. So it should be codes in program2 has problem. After check codes, it is because some memory management in program2.

Corruption of data in memcpy

I'm currently working on a project using sockets via WinSock and have come across a peculiar problem. I'll attach the code before I start explaining.
#include "Connection.h"
Connection::Connection(SOCKET sock, int socketType)
: m_sock(sock), m_recvCount(0), m_sendCount(0), m_socketType(socketType)
{
printf("Succesfully created connection\n");
}
Connection::~Connection(void)
{
printf("Closing socket %d", m_sock);
closesocket(m_sock);
}
void Connection::ProcessMessage(const NetMessage *message){
printf("Got network message: type %d, data %s\n", message->type, message->data);
}
bool Connection::ReadSocket(){
// Call this when the socket is ready to read.
// Returns true if the socket should be closed.
// used to store count between the sockets
int count = 0;
if(m_socketType == SOCK_STREAM){
// attempt to read a TCP socket message
// Receive as much data from the client as will fit in the buffer.
count = recv(m_sock, &m_recvBuf[m_recvCount], sizeof(m_recvBuf) - m_recvCount, 0);
}
else if(m_socketType == SOCK_DGRAM){
// attempt to read UDP socket message
// temporarily stores details of the address which sent the message
// since UDP doesn't worry about whether it's connected to the
// sender or not
sockaddr_in fromAddr;
int fromAddrSize = sizeof(fromAddr);
count = recvfrom(m_sock, &m_recvBuf[m_recvCount], sizeof(m_recvBuf) - m_recvCount, 0, (sockaddr*) &fromAddr, &fromAddrSize);
}
else{
printf("Unknown socket type %d\n", m_socketType);
return true;
}
if (count <= 0)
{
printf("Tried to receive on socket %d and got %d bytes\n", m_sock, count);
printf("Client connection closed or broken\n");
return true;
}
// if we get to this point we have essentially received a complete message
// and must process it
printf("Received %d bytes from the client (total %d)\n", count, m_recvCount);
m_recvCount += count;
// Have we received a complete message?
// if so, process it
if (m_recvCount == sizeof NetMessage)
{
ProcessMessage((const NetMessage *) m_recvBuf);
m_recvCount = 0;
}
return false;
}
bool Connection::WriteSocket(){
// Sends the data in the send buffer through the socket
int count;
if(m_socketType == SOCK_STREAM){
// attempt to read TCP socket message
count = send(m_sock, m_sendBuf, m_sendCount, 0);
}
else if(m_socketType == SOCK_DGRAM){
// attempt to read UDP socket message
count = sendto(m_sock, m_sendBuf, m_sendCount, 0, 0, 0);
}
else{
// unhandled type of socket, kill server
printf("Unknown socket type %d", m_socketType);
return true;
}
if (count <= 0)
{
// we have received an error from the socket
printf("Client connection closed or broken\n");
return true;
}
m_sendCount -= count;
printf("Sent %d bytes to the client (%d left)\n", count, m_sendCount);
printf("Data: %s", m_sendBuf);
// Remove the sent data from the start of the buffer.
memmove(m_sendBuf, &m_sendBuf[count], m_sendCount);
return false;
}
bool Connection::WantWrite(){
if(m_sendCount > 0){
return true;
}
return false;
}
bool Connection::WantRead(){
return true;
}
bool Connection::SetMessage(const NetMessage *message){
// store contents of the message in the send buffer
// to allow us to send later
if (m_sendCount + sizeof(NetMessage) > sizeof(m_sendBuf))
{
return true;
}
memcpy(&m_sendBuf, message, sizeof(message));
m_sendCount += sizeof(NetMessage);
return false;
}
and the protocol
/* Definitions for the network protocol that the client and server use to communicate */
#ifndef PROTOCOL_H
#define PROTOCOL_H
// Message types.
enum MessageType
{
MT_UNKNOWN = 0,
MT_WELCOME = 1,
MT_KEYPRESS = 2,
MT_CHATMESSAGE = 3
};
// The message structure.
// This is a "plain old data" type, so we can send it over the network.
// (In a real program, we would want this structure to be packed.)
struct NetMessage
{
MessageType type;
char* data;
NetMessage()
: type(MT_UNKNOWN)
{
}
};
#endif
Essentially the protocol holds the definition of the messages that the client and server throw around to each other. The problem I am having is that, in connection.cpp line 132 (memcpy), the message becomes garbled in sendBuf.
http://imgur.com/MekQfgm,9ShRtHi
The image above shows exactly what is happening. As said in protocol.h the struct is a POD so when I do memcpy it should transfer the number of bytes as is held in the struct (so for example the message type should be 1 byte, followed by 7 or 8 bytes of data, in the example).
Can anyone shed some light on this? It's driving me crazy.
The line you wrote will copy 4 bytes (sizeof(pointer)) on 32bit systems:
memcpy(&m_sendBuf, message, sizeof(message));
what you probably meant is:
memcpy(&m_sendBuf, message, sizeof(NetMessage));
Edit:
In addition, as a commenter remarked, your data type is NOT a POD. It holds a pointer. You transfer that pointer. At the target system, it will point to the same place in RAM, but there will not be anything there. You need to actually make your datatype a POD by using an array or you need to find a way to transfer the data pointed to. You can achieve this by transfering the type, a length and a number of characters. That means that your receiver can NOT rely on messages being of fixed size.

How to stub a socket in C?

I've written client code that's supposed to send some data through a socket and read back an answer from the remote server.
I would like to unit-test that code. The function's signature is something along the lines of:
double call_remote(double[] args, int fd);
where fd is the file descriptor of the socket to the remote server.
Now the call_remote function will, after sending the data, block on reading the answer from the server. How can I stub such a remote server for unit-testing the code?
Ideally I would like something like:
int main() {
int stub = /* initialize stub */
double expected = 42.0;
assert(expected == call_remote(/* args */, stub);
return 0;
}
double stub_behavior(double[] args) {
return 42.0;
}
I would like stub_behavior to be called and send the 42.0 value down the stubbed file descriptor.
Any easy way I can do that?
If this is a POSIX system, you can use fork() and socketpair():
#define N_DOUBLES_EXPECTED 10
double stub_behaviour(double []);
int initialize_stub(void)
{
int sock[2];
double data[N_DOUBLES_EXPECTED];
socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
if (fork()) {
/* Parent process */
close(sock[0]);
return sock[1];
}
/* Child process */
close(sock[1]);
/* read N_DOUBLES_EXPECTED in */
read(sock[0], data, sizeof data);
/* execute stub */
data[0] = stub_behaviour(data);
/* write one double back */
write(sock[0], data, sizeof data[0]);
close(sock[0]);
_exit(0);
}
int main()
{
int stub = initialize_stub();
double expected = 42.0;
assert(expected == call_remote(/* args */, stub);
return 0;
}
double stub_behavior(double args[])
{
return 42.0;
}
...of course, you will probably want to add some error checking, and alter the logic that reads the request.
The file descriptor created by socketpair() is a normal socket, and thus socket calls like send() and recv() will work fine on it.
You could use anything which can be accessed with a file descriptor. A file or, if you want simulate blocking behaviour, a pipe.
Note: obviosly socket specific calls (setsockopt, fcntl, ioctl, ...) wouldn't work.
I encountered the same situation and I'll share my approach. I created network dumps of exactly what the client should send, and what the server response should be. I then did a byte-by-byte comparison of the client request to ensure it matched. If the request is valid, I read from the response file and send it back to the client.
I'm happy to provide more details (when I'm at a machine with access to this code)
Here is a C++ implementation (I know, the original question was for C, but it is easy to convert back to C if desired). It probably doesn't work for very large strings, as the socket will probably block if the string can't be buffered. But it works for small unit tests.
/// Class creates a simple socket for testing out functions that write to a socket.
/// Usage:
/// 1. Call GetSocket() to get a file description socket ID
/// 2. write to that socket FD
/// 3. Call ReadAll() read back all the data that was written to that socket.
/// The sockets are all closed by ReadAll(), so this is a one-use object.
///
/// \example
/// MockSocket ms;
/// int socket = ms.GetSocket();
/// send(socket,"foo bar",7);
/// ...
/// std::string s = ms.ReadAll();
/// EXPECT_EQ("foo bar",s);
class MockSocket
{
public:
~MockSocket()
{
}
int GetSocket()
{
socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_);
return sockets_[0];
}
std::string ReadAll()
{
close(sockets_[0]);
std::string s;
char buffer[256];
while (true)
{
int n = read(sockets_[1], buffer, sizeof(buffer));
if (n > 0) s.append(buffer,n);
if (n <= 0) break;
}
close(sockets_[1]);
return s;
}
private:
int sockets_[2];
};