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).
Related
I'm working with POSIX sockets in C.
Given X, I have a need to verify that the socketfd contains at least X bytes before proceeding to perform an operation with it.
With that being said, I don't want to receive X bytes and store it into a buffer using recv as X has the potential of being very large.
My first idea was to use MSG_PEEK...
int x = 9999999
char buffer[1];
int num_bytes = recv(socketfd, buffer, X, MSG_PEEK);
(value == X) ? good : bad;
...
...
...
// Do some operation
But I'm concerned X > 1 is corrupting memory, flag MSG_TRUNC seems to resolve the memory concern but removes X bytes from socketfd.
There's a big difference between e.g. TCP and UDP in this regards.
UDP is packet based, you send and receive packets of fixed size, basically.
TCP is a streaming protocol, where data begins to stream on connection and stops at disconnection. There are no message boundaries or delimiters in TCP, other than what you add at the application layer. It's simply a stream of bytes without any meaning (in TCP's point of view).
That means there's no way to tell how much will be received with a single recv call.
You need to come up with an application-level protocol (on top of TCP) which can either tell the size of the data to be received; For example there might be a fixed-size data-header that contains the size of the following data; Or you could have a specific delimiter between messages, something that can't occur in the stream of bytes.
Then you receive in a loop until you either have received all the data, or until you have received the delimiter. But note, with a delimiter there's the possibility that you also receive the beginning of the next message, so you need to be able to handle partial beginnings of message after the current message have been fully received.
int num_bytes = recv(socketfd, buffer, X, MSG_PEEK);
This will copy up to X byte into buffer and return it without removing it from the socket. But your buffer is only 1 byte large. Increase your buffer.
Have you tried this?
ssize_t available = recv(socketfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
Or this?
size_t available;
ioctl(socketfd, FIONREAD, &available);
I'm very new to C++, but I'm trying to learn some basics of TCP socket coding. Anyway, I've been able to send and receive messages, but I want to prefix my packets with the length of the packet (like I did in C# apps I made in the past) so when my window gets the FD_READ command, I have the following code to read just the first two bytes of the packet to use as a short int.
char lengthBuffer[2];
int rec = recv(sck, lengthBuffer, sizeof(lengthBuffer), 0);
short unsigned int toRec = lengthBuffer[1] << 8 | lengthBuffer[0];
What's confusing me is that after a packet comes in the 'rec' variable, which says how many bytes were read is one, not two, and if I make the lengthBuffer three chars instead of two, it reads three bytes, but if it's four, it also reads three (only odd numbers). I can't tell if I'm making some really stupid mistake here, or fundamentally misunderstanding some part of the language or the API. I'm aware that recv doesn't guarantee any number of bytes will be read, but if it's just two, it shouldn't take multiple reads.
Because you cannot assume how much data will be available, you'll need to continuously read from the socket until you have the amount you want. Something like this should work:
ssize_t rec = 0;
do {
int result = recv(sck, &lengthBuffer[rec], sizeof(lengthBuffer) - rec, 0);
if (result == -1) {
// Handle error ...
break;
}
else if (result == 0) {
// Handle disconnect ...
break;
}
else {
rec += result;
}
}
while (rec < sizeof(lengthBuffer));
Streamed sockets:
The sockets are generally used in a streamed way: you'll receive all the data sent, but not necessarily all at once. You may as well receive pieces of data.
Your approach of sending the length is hence valid: once you've received the length, you cann then load a buffer, if needed accross successive reads, until you got everything that you expected. So you have to loop on receives, and define a strategy on how to ahandle extra bytes received.
Datagramme (packet oriented) sockets:
If your application is really packet oriented, you may consider to create a datagramme socket, by requesting linux or windows socket(), the SOCK_DGRAM, or better SOCK_SEQPACKET socket type.
Risk with your binary size data:
Be aware that the way you send and receive your size data appers to be assymetric. You have hence a major risk if the sending and receiving between machine with CPU/architectures that do not use the same endian-ness. You can find here some hints on how to ame your code platform/endian-independent.
TCP socket is a stream based, not packet (I assume you use TCP, as to send length of packet in data does not make any sense in UDP). Amount of bytes you receive at once does not have to much amount was sent. For example you may send 10 bytes, but receiver may receive 1 + 2 + 1 + 7 or whatever combination. Your code has to handle that, be able to receive data partially and react when you get enough data (that's why you send data packet length for example).
I am writing some network packet sniffing code in C (running on an Ethernet LAN). While attempting to print out the Ethernet header, I've run into a bit of confusion. According to Wikipedia the first 8 bytes consist of the preamble and a delimiter and the next 6 are the MAC destination address.
However, when I actually run my code, I see that in the bytes I get from the recvfrom call, the initial 8 bytes (preamble and delimiter) are missing. In other words, I can start reading the destination address from the first byte itself.
Here is the relevant part of the code
char buffer[BUFFERSIZE];
struct addrinfo servinfo;
servinfo.ai_family = PF_PACKET;
servinfo.ai_socktype = SOCK_RAW;
servinfo.ai_protocol = htons(ETH_P_ALL);
int fd = socket(servinfo.ai_family, servinfo.ai_socktype, servinfo.ai_protocol);
int plen = recvfrom(fd, buffer, BUFFERSIZE, 0, &caddr, &clen);
int c = 0;
printf("Destination Address: %02x:%02x:%02x:%02x:%02x:%02x\n",buffer[c], buffer[c+1], buffer[c+2], buffer[c+3], buffer[c+4], buffer[c+5]);
printf("Source Address: %02x:%02x:%02x:%02x:%02x:%02x\n",buffer[c+6], buffer[c+7], buffer[c+8], buffer[c+9], buffer[c+10], buffer[c+11]);
This prints the correct destination address, whereas I should have gotten the correct result by printing after skipping the first 8 bytes in the buffer.
What am I missing here, or doing wrong?
This prints the correct destination address, whereas I should have
gotten the correct result by printing after skipping the first 8 bytes
in the buffer
The preamble is a very low-level concept, handled strictly by the NIC. It's not even visible to the OS, let alone returned by recvfrom.
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.
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]