Caching packets captured from pcap - c

This is a follow-up question to this:
Rebuilding a packet to inject via pcap
What I want to accomplish:
functionA: Capture packets with pcap. Modify source/destination addresses. Recalculate checksums. Inject with pcap.
functionB: Create two threads. Thread 1 sends a magic packet to wake sleeping client. Thread 2 captures packets with pcap and caches the packets into an array of u_char *'s, since pcap puts the packet data serially into "u_char * packet". When both threads terminate, I then change the headers then inject each of the cached packets.
What I need help with:
functionA: I can do everything but calculate checksums. I tried to verify the original checksum by calculating it myself with a function but they never match. However, this issue is not as important because I don't need it to demo my final project. I understand that if IP checksums are incorrect, the receiving computer will discard the packet. But when I demo, so long as my client computer can be shown to have received this incorrect packet, I have proven my overall concept and will not fail. :)
functionB: I guess this is the more important problem. I don't know of an easy way to cache my captured packets. What I'm working on right now is as follows:
functionB creates a pointer to an array that stores u_char * called cachedPackets. So cachedPackets basically points to an array that stores "strings".
It'll be something like this? u_char ** cachedPackets[100], enough array elements for 100 packets.
After this, I start two threads. Thread1 to wake my sleeping client. Thread2 to open another pcap session so no data is lost while client is waking. Thread1 is easy, I've already tested my send magic packet function independently. Thread2 is where I'm screwing up.
Thread2 eventually calls int pcap_loop(pcap_t *p, int cut, pcap_handler callback, u_char *user).
callback is the function that will be run after each packet is captured. It is where I will be caching the packet into the array.
callback takes parameters ( u_char* user,
const struct pcap_pkthdr* packet_header,
const u_char* packet_data )
user is the same string in the 4th argument of pcap_loop.
So I was thinking, I could sneakily give my callback function the pointer to the array of string by type casting it.
pcap_loop(asdf, asdf, callback, (u_char *)cachedPackets);
Since I don't know how big the incoming packets will be, I'll dynamically allocate enough space in the callback function. I will also keep track of my position in the array with a static int.
this is what the callback looks like:
void cacheCall(u_char * user, const struct pcap_pkthdr * header, const u_char * packet)
static int cacheindex = 0;
u_char ** cachethis = (u_char **)user;
//u_char * cachething = *cachethis;
(*cachethis)[cacheindex] = (u_char *) malloc(header->len); <--- 497
int i = 0;
for(i = 0; i < header->len; i++)
{
(*cachethis)[cacheindex][i] = packet[i]; <-------------------503
}
//memcpy(cachething[cacheindex], packet, header->len);
cacheindex++;
but when I compile, i get
497: warning: assignment makes integer from pointer without a cast
503: error: subscripted value is neither array nor pointer
That was pretty longwinded, hopefully my knowledge of what I'm doing isn't completely misinformed. Any help would be awesome! :)

u_char ** cachethis;
cachethis is a pointer-to-pointer-to-u_char.
So:
*cachethis
is a pointer-to-u_char, and:
(*cachethis)[i]
is a plain u_char.
So line 497 tries to store a pointer into an u_char, and line 503 tries to subscript a u_char, both of which are invalid.
Looks like what you want is simply:
cachethis[i]
and
cachethis[i][j]

Related

Retrieve unaligned netlink message size in kernel space

I am working on a Linux kernel module which has a bi-directional communication link with a userspace module provided by netlink.
I have an issue with an incorrect message length calculation on messages sent from userspace to kernel space. The message is sent from userspace like this:
this->sendLock.lock();
this->netlinkTxHeader->nlmsg_len = NLMSG_SPACE(len);
this->netlinkTxIov.iov_len = this->netlinkTxHeader->nlmsg_len;
memcpy(NLMSG_DATA(this->netlinkTxHeader), buf, len);
int32_t status = sendmsg(this->netlinkSock, &this->netlinkTxMsg, 0);
And is received in kernel space like this:
unsigned char* buf = (unsigned char*)NLMSG_DATA(nlh);
int len = NLMSG_PAYLOAD(nlh, 0);
However the calculated value of len always seems to be the aligned size, which I don't want. For example, I can see from debug information that the userspace process sends a message with a payload of 14 bytes (excluding netlink headers). When this is received in the kernel module, however, NLMSG_PAYLOAD returns a length of 16 bytes.
Is there any way to get the unaligned payload length (i.e. the actual payload length) back in the kernel module? I looked through the macros in netlink.h but I don't see anything which would help.
Note that the nlmsghdr object is derived using the netlink_rcv_skb() function in the kernel module.
The only other way I can see to fix this is to prefix the actual length in the payload information which I think would work, but doesn't really feel "correct".
See man 3 netlink: you need to use NLMSG_LENGTH(len) (and not NLMSG_SPACE(len)) to calculate the nlmsg_len field of the nlmsghdr.

Copying char* values through Queues and threads on MBED OS

I am trying to implement some RTOS threads on Arm MBED OS over a K64F board. I am parting from the RTOS examples and I have succesfully run and communicated different threads using Queues. I am having problems when copying char* values from one struct to another to get a message from one queue to another. I believe I am misunderstanding something and that my problem is related to pointers and memory handling but I am not able to get through it.
I have defined diferent queues to send data to various threads. I have also created a basic data structure containing everything I need to go among these threads. In this struct I have a char* variable (rHostAddr) containing the remote host address that requested a service.
MemoryPool<cMsg, 16> AMPool;
Queue<cMsg, 16> AMQueue;
MemoryPool<cMsg, 16> ioLedPool;
Queue<cMsg, 16> ioLedQueue;
typedef struct{
...
char* rHostAddr;
...
} cMsg;
In the Main Thread I am creating this data structure and putting it in the first queue (AMQueue).
--- Main Thread ---
cMsg *message = AMPool.alloc();
char* rcvaddrs = "111.111.111.111";
message->rHostAddr = "111.111.111.111";
rcvaddrs = (char*)addr.get_ip_address();
message->rHostAddr = rcvaddrs;
AMQueue.put(message);
On the Thread 1 I wait for a message to arrive and on certain conditions I copy the whole structure to a new one created from the corresponding pool and insert it on a new queue (ioLedQueue).
--- Thread 1 ---
cMsg *msg;
cMsg *ledm = ioLedPool.alloc();
osEvent evt = AMQueue.get();
msg = (cMsg*)evt.value.p;
msg.rHostAddr = ledm.rHostAddr;
printf("\t -- Host 1 -- %s\n\r", ledm->rHostAddr);
ioLedQueue.put(ledm);
On the Thread 2 I get the message structure and the data .
--- Thread 2 ---
cMsg *msg;
osEvent evt = ioLedQueue.get();
msg = (cMsg*)evt.value.p;
printf("\t -- Host 2 -- %s\n\r", msg->rHostAddr);
On this stage rHostAddr is empty. I can see the value on the printf "Host 1" but not in the "Host 2"
I believe (if I am not wrong) that the problem comes from assigning with = operand, as I am copying the address, not the value, and it is lost when first pool memory is freed. I have tried copying the value with memcpy, strcpy and even my own char by char but system hangs when calling this methods.
How can I copy the value through this queues?
I move it here as the correct answer was written as a comment. Converting the value to a array of chars was the way to go, so the string data is part of the struct.
char rHostAddr[40];
Now the assignation can be done with srtcpy method and it is passed through all the process correctly:
char* rcvaddrs = (char*)addr.get_ip_address();
strcpy(message->rHostAddr,rcvaddrs);
Take a look at this solution from ARM mbed:
https://github.com/ARMmbed/mbed-events

packet handlers in different threads in pcap

I'm trying to work with pcap and want it to work in a way wherein once I receive a packet, I want that packet to be processed independently while my pcap_loop() stills sniffs on other incoming packets.
This way I have my packet being processed and wait for an ACK for a specified time. If I don't receive an ACK, I take some other action.
What I don't understand is how to create a thread for a packet after it is sniffed..so that each packet is processed independently of the other.
So it would be something of this sort,
pcap_loop(handle, -1, got_packet, NULL)
When creating a pthread where should I have my have my code for
pthread_create(pthread_t, NULL, &got_packet, NULL)
Thanks for your help!
The following code below just captures one packet and then exits.
EDited to include code frags:
struct parameter {
u_char *param1;
const struct pcap_pkthdr *param2;
u_char *param3;
};
pcap_loop(handle, -1, create_thread, NULL);
void create_thread(u_char *args, const struct pcap_pkthdr *header, u_char *packet)
{
struct parameter thrd_args;
thrd_args.param1 = args;
thrd_args.param2 = header;
thrd_args.param3 = packet;
pthread_t packet_handler;
pthread_create(&packet_handler, NULL, &got_packet, (void *)&thrd_args);
error handling....
pthread_exit(NULL);
}
void *got_packet(void *thrd_args)
{
struct parameters *thread_args;
thread_args = thrd_args;
u_char *args = &thread_args->param1;
const struct pcap_pkthdr *header = &thread_args->param2;
u_char *packet = &thread_args->param3;
}
Is there a real good reason for you to handle the packet processing in a different thread? The pcap driver stores packets for you in a queue so you will not miss them if they arrive while you process previous packets (depending of course on the size of the buffer you stated when you created the sniffer). Be that as it may, you should probably create the thread in your got_packet function (which will be called by the pcap driver every time a packet is sniffed) and give it the address of a different processing function like so: pthread_create(pthread_t, NULL, &process_packet, NULL) . Of course you need to somehow pass the packet to your new processing thread, but I'll leave that for you to figure out.
I did it bit differently, maybe this will help anyone. Once pcap_loop receives a packet, call appropriate function, where you create new thread and do pthread_detach() along with return 0. The new thread will handle the packet and pcap will the same way process another packet in another thread.
You will then have as many threads as you will receive packets.

Writing messages of different types through sockets in C

I want to send a message to my Binder class via TCP socket connection in C. I have to pass in a request type (char*), ip address (int), argTypes(int array) etc. through this connection using the write() method. What's the best method to send all of the information in one single message?
There's no guarantee that you can send/receive all your data in a single read/write operation;
too many factors may influence the quality/packet-size/connection-stability/etc.
This question/answer explains it.
Some C-examples here.
A good explanation of socket programming in C.
A quick overview of TCP/IP.
About sending different types of messages:
The data you send is from your server-app is received by your client-app who then can interpret this data any way it likes.
If your data is related, you can create a struct in a separate header and use it in both the client and server code and send a variable of this struct across. If it is not related, then I am not sure why you would need to send them across as one single message.
If you want to transmit and receive your data with a single write and single read, then you have to use a datagram socket. Since a datagram socket is connectionless, you cannot use write/read. Instead, you use sendto/recvfrom or sendmsg/recvmsg. Since a datagram socket is unreliable, you will have to implement your own protocol to tolerate out of order data delivery and data loss.
If you don't want to deal with the unreliable nature of a datagram socket, then you want a stream socket. Since a stream socket is connected, transmitted data are guaranteed and are in order. If the data you send always has the same size, then you can mimic a datagram by using blocking mode for your send call and then passing in MSG_WAITALL in the recv call.
#define MY_MSG_SIZE 9876
int my_msg_send (int sock, const void *msg) {
int r, sent = 0;
do {
r = send(sock, (const char *)msg + sent, MY_MSG_SIZE - sent,
MSG_NOSIGNAL);
if (r <= 0) {
if (r < 0 && errno == EINTR) continue;
break;
}
sent += r;
} while (sent < MY_MSG_SIZE);
if (sent) return sent;
return r;
}
int my_msg_recv (int sock, void *msg) {
int r, rcvd = 0;
do {
r = recv(sock, (char *)msg + rcvd, MY_MSG_SIZE - rcvd, MSG_WAITALL);
if (r <= 0) {
if (r < 0 && errno == EINTR) continue;
break;
}
rcvd += r;
while (rcvd < MY_MSG_SIZE);
if (rcvd) return rcvd;
return r;
}
Notice that the software still has to deal with certain error cases. In the case of EINTR, the I/O operation needs to be retried. For other errors, the delivery or retrieval of data may be incomplete. But generally, for blocking sockets, we expect only one iteration for the do-while loops above.
If your messages are not always the same size, then you need a way to frame the messages. A framed message means you need a way to detect the start of a message, and the end of a message. Perhaps the easiest way to frame a message over a streaming socket is to precede a message with its size. Then the receiver would first read out the size, and then read the rest of the message. You should be able to easily adapt the sample code for my_msg_send and my_msg_recv to do that.
Finally, there is the question of your message itself. If the messages are not always the same size, this likely means there are one or more variable length records within the message. Examples are an array of values, or a string. If both the sender and receiver agree to the order of the records, then it is enough to precede each variable length record with its length. So suppose your message had the following structure:
struct my_data {
const char *name;
int address;
int *types;
int number_of_types;
};
Then you could represent an instance of struct my_data like this:
NAME_LEN : 4 bytes
NAME : NAME_LEN bytes
ADDRESS : 4 bytes
TYPES_LEN : 4 bytes
TYPES : TYPES_LEN * 4 bytes
NAME_LEN would be obtained from strlen(msg->name), and TYPES_LEN would obtain its value from msg->number_of_types. When you send the message, it would be preceded by the total length of the message above.
We have been using 32 bit quantities to represent the length, which is likely sufficient for your purposes. When transmitting a number over a socket, the sender and receiver has to agree on the byte order of the number. That is, whether the number 1 is represented as 0.0.0.1 or as 1.0.0.0. This can typically be handled using network byte ordering, which uses the former. The socket header files provides the macro htonl which converts a 32 bit value from the host's native byte order to network byte order. This is used when storing a value in, say NAME_LEN. The receiver would use the corresponding macro ntohl to restore the transmitted value back to a representation used by the host. The macros could of course be no-ops if the hosts native byte ordering matches network byte order already. Using these macros is of particular importance when sending and receiving data in a heterogeneous environment, since the sender and receiver may have different host byte orderings.

pcap why always packets of 8 bytes... why?

I'm using the pcap library but I don't know why I get always this output:
new packet with size: udata= 8 hdr=8 pkt=8
This is the code:
void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt)
{
DEBUG("DANY new packet with size: udata= %d hdr=%d pkt=%d", (int) sizeof(udata),(int) sizeof(hdr),(int) sizeof(pkt) );
...
stuff
}
and in another file I use:
status = pcap_loop (pcap_obj,
-1 /* How many packets it should sniff for before returning (a negative value
means it should sniff until an error occurs (loop forever) ) */,
handle_pcap /* Callback that will be called*/,
NULL /* Arguments to send to the callback (NULL is nothing) */);
Is it normal that output?
I think not because sometimes my program works sometimes doesn't..
You are printing the size of the pointers instead of looking into the pcap_pkthdr* hdr to see the size of the packet.
You can find the size of the captured data and the size of the entire packet by looking at hdr->caplen and hdr->len.
Um. You are getting the size of (the various) pointers.
e.g. sizeof(udata) gets the size of a u_char *. That's why the numbers look suspect.
If you want the sizes of the packets, they are in hdr->caplen and hdr->len (the former is the captured length, the latter is the packet length).

Resources