I have this code
uint8_t *p = (uint8_t *)tcph + 20; // or sizeof (struct tcphdr)
uint8_t *end = (uint8_t *)tcph + tcph->doff * 4;
uint16_t mss = 0;
printf("jjjj %d %d",p ,end);
while (p < end) {
uint8_t kind = *p++;
printf("kind = %d\n",kind);
if (kind == 0) {
break;
}
if (kind == 1) {
// No-op option with no length.
printf("\nNo-opt\n");
continue;
}
printf("p before %x\n",p);
uint8_t size = *p++;
printf("p after %x size = %x\n",p,size);
if (kind == 2) {
mss = ntohs(*(uint16_t *)p);
printf("\nMSS = %x MSS = %d\n",(mss),htons(mss));
}
p += (size - 2);
printf("p super after %x\n",p);
}
the thing is that the tcp MSS starts at something like thing
Following is Point one
sizeof(struct tcphdr)+[uint8_t(kind)+uint8_t(length)+uint16_t(thats value of MSS)]=option1 , ....
So the above code is extracting MSS's two byte value from above memory layout (shown in point 1)
The thing is the while loop is used to extract all options that are linked to tcp protocol
so this like uint8_t kind = *p++; escape the initial one byte before any option
so that now we are at kind value of first option (since this is only tcp option on my system so its also last)
then I am doing uint8_t size = *p++; so now p advanced to second byte since p is one byte size which is tcp option length. Now
to extract the actual option like mss value which has kind value == 2 shouldnt I increment one byte more to get passed the sizeof option length space too, but this code does not do it. So the question is my p current point is standing at length space and the code is doing this to extract the mss value which is at third byte from right (most significant bit ) why is that mss = ntohs(*(uint16_t *)p);
So I'm reading from a file descriptor which contains an int variable in its raw byte format.
So I'm doing:
char buffer[sizeof(int)];
ssize_t sizeOfFile = read(sock_fd, buffer, sizeof(int));
int extractedInt = ???;
How can I convert that buffer to an integer? I was thinking of memcpy but was wondering if there are better ways.
You could read directly an integer
int extractedInt;
ssize_t sizeOfFile = read(sock_fd, &extractedInt, sizeof(int));
read will read the size of an int bytes, and store them into extractedInt.
If your int is actually a string in a file you want to convert to an int, the procedure is a bit different.
#define SIZE 20
char buffer[SIZE]; // ensure there is enough space for a string containing an integer
ssize_t sizeOfFile = read(sock_fd, buffer, SIZE);
int extractedInt = atoi(buffer); // convert string to integer
I can guess from your code that you're reading from the network. This is then not portable to just read a int from the buffer, in your network protocol you chose a certain endianness but you cannot expect that all the platforms where your program will run to have the same, so it will lead to bad convertions.
And other proposed solutions of asking read to return an int will lead to the same problem.
So in your case, I can only advice to iterate through your array and compute the integer by progressively placing the bytes at the right place depending on the endianness of the platform.
You can detect the endianness of the build target platform by using the macro __BYTE_ORDER__in GCC.
There is an example for network data that is big endian:
// construct an `int` with the bytes in the given buffer
// considering the buffer contains the representation
// of an int in big endian
int buffer_to_int(char* buffer, int buffer_size) {
int result = 0;
int i;
char sign = buffer[0] & 0x80;
char * res_bytes = (char*)&result; // this pointer allows to access the int bytes
int offset = sizeof(int) - buffer_size;
if( sign != 0 )
sign = 0xFF;
if( offset < 0 ) {
// not representable with a `int` type
// we chose here to return the closest representable value
if( sign == 0 ) { //positive
return INT_MAX;
} else {
return INT_MIN;
}
}
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
for(i=0; i<buffer_size; i++) {
res_bytes[i] = buffer[buffer_size-i-1]; // invert the bytes
}
for(i=0; i<offset; i++){
res_bytes[buffer_size+i] = sign;
}
#else
// same endianness, so simply copy bytes using memcpy
memcpy(&result + offset, buffer, buffer_size);
for(i=0; i<offset; i++){
res_bytes[i] = sign;
}
#endif
return result;
}
I'm working in the arduino environment. I have a struct defined as follows. The struct will ultimately be encrypted and sent wirelessly over a radio link layer. It's 32bytes long.
struct SENSORTYPE{
int sensor1:8;
int sensor2:8;
int sensor3:8;
int sensor4:8;
};
struct SENSOR{
float sensor1;
float sensor2;
float sensor3;
float sensor4;
};
struct HEADER{
byte type;
short id;
short to;
short from;
byte version;
long _buff;
SENSORTYPE sensortype;
SENSOR sensor;
};
HEADER header;
I have an XTEA encryption/decryption routine that's defined as follows and is verified to work. It operates on two 32bit blocks at at time.
void xteaEncrypt( unsigned long v[2])
void xteaDecrypt(unsigned long v[2])
What I'm trying to do is run header through xteaEncrypt. I'm getting tripped up on converting my struct to the two 32bit numbers. The following is what I have so far.
#define BLOCK_SIZE 8
header.type = 1; //test value
header._buff = 1; //test value
byte data[BLOCK_SIZE]; //8 byte buffer to encrypt/decrypt
byte buff[32]; //32 byte buffer to put encrypted/decrypted data into
for (uint32_t i = 0; i < 4; i++){ //4 times (4 * 8 = 32)
memcpy(data, &header+(i*BLOCK_SIZE), BLOCK_SIZE); //copy 8 bytes from header struct into data
xteaEncrypt((uint32_t*)data); //encrypt data
memcpy(&buff+(i*8), data, BLOCK_SIZE); //put encrypted data into the new buffer
}
memcpy(&header, &buff, sizeof(header)); //copy into original header for convenience
//now decrypt it back
for (uint32_t i = 0; i < 4; i++){
memcpy(data, &header+(i*BLOCK_SIZE), BLOCK_SIZE);
xteaDecrypt((uint32_t*)data);
memcpy(&buff+(i*8), data, BLOCK_SIZE);
}
memcpy(&header, &buff, sizeof(header));
After encryption header.type = 0xee and header._buff = C0010000. After decryption, header.type = 1 and _buff still = C0010000 so it would seem there is an error in my memcpy'ing but I can't find it. Any help would be greatly appreciated. This one has been particularly hard to debug for me. If I'm going about this completely wrong let me know and point me in the right direction.
You're getting tripped up by pointer arithmetic. Consider the snippet &header+(i*BLOCK_SIZE). What you evidently expect to happen is that you'll get some address, let's call it addr, and then add some small number to it to calculate a new address, i.e.
finalAddress = addr + (i * 8);
But because &header is a pointer to a struct HEADER, the actual calculation the compiler does is
finalAddress = addr + (sizeof(struct HEADER) * i * 8);
The result is an address that's well beyond the end of the header for any i greater than 0. The same thing is happening with &buff+(i*8), since &buff is a pointer to 32 bytes.
To solve the problem, I recommend using intermediate variables that are char *, e.g.
char *headAddress = (char *)&header;
char *buffAddress = (char *)&buff;
for (uint32_t i = 0; i < 4; i++)
{
memcpy(data, headAddress+(i*BLOCK_SIZE), BLOCK_SIZE);
xteaEncrypt((uint32_t*)data);
memcpy(&buffAddress+(i*BLOCK_SIZE), data, BLOCK_SIZE);
}
I have a college project where need to convert an int to a buffer of char.
I need to use memcpy but when I copy the values it's not work because the msg_buf still empty.
I have some constraints:
- I need to use memcpy because my teacher will test my code like memcmp(msg_str, &opcode, 2) == 0).
Here is my code:
int message_to_buffer(struct message_t *msg, char **msg_buf){
int opcode = htons(msg->opcode);
int c_type = htons(msg->c_type);
int result;
int buffer = sizeof(opcode) + sizeof(c_type);
switch(msg->c_type){
case CT_RESULT:
result = htonl(msg->content.result);
buffer += sizeof(result);
*msg_buf = (char*)malloc(sizeof(char) * 12);
if(msg_buf == NULL)
return -1;
memcpy(*msg_buf,&opcode,sizeof(opcode));
break;
};
return buffer;
}
What is wrong here?
More specifically, you need to be copying the shorts as shorts, not ints. sizeof(short) != sizeof(int) (usually, depending on the architecture):
int message_to_buffer(struct message_t *msg, char **msg_buf){
short opcode = htons(msg->opcode);
short c_type = htons(msg->c_type);
int result;
char* buffer = NULL, *buf_start=NULL;
*msg_buf = NULL;
switch(msg->c_type){
case CT_RESULT:
result = htonl(msg->content.result);
buffer = (char*)malloc(sizeof(char) * 12);
if (buffer == NULL)
return -1;
buf_start = buffer;
memcpy(buffer,&opcode,sizeof(opcode)); // sizeof(short) == 2; sizeof(int) == 4
buffer += sizeof(opcode);
memcpy(buffer,&c_type,sizeof(c_type)); // sizeof(short) == 2; sizeof(int) == 4
buffer += sizeof(c_type);
memcpy(buffer,&result, sizeof(result));
buffer += sizeof(result);
*msg_buf = buf_start;
break;
};
return buffer - buf_start;
}
I think your problem may be that you are calling htons() on an int. htons() is meant to be used with values of type short, so you may be losing the upper 16 bits of your msg->opcode and msg->c_type there. Try replacing htons() with htonl() instead.
Also, it looks like you are allocating a 12-byte buffer with malloc(), but only writing 4 bytes into it, leaving the latter 8 bytes of it uninitialized/undefined. Is that intentional?
Why don't you use itoa function to convert int to char*? So you replace your memcpy with itoa function.
Reference: http://www.cplusplus.com/reference/cstdlib/itoa/
[EDIT]
If your compiler does not support itoa, you can use sprintf instead.
I need to put into a char* some uint32_t and uint16_t numbers. Then I need to get them back from the buffer.
I have read some questions and I've tried to use sprintf to put them into the char* and sscanf get the original numbers again. However, I'm not able to get them correctly.
Here's an example of my code with only 2 numbers. But I need more than 2, that's why I use realloc. Also, I don't know how to use sprintf and sscanf properly with uint16_t
uint32_t gid = 1100;
uint32_t uid = 1000;
char* buffer = NULL;
uint32_t offset = 0;
buffer = realloc(buffer, sizeof(uint32_t));
sprintf(buffer, "%d", gid);
offset += sizeof(uint32_t);
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
sprintf(buffer+sizeof(uint32_t), "%d", uid);
uint32_t valorGID;
uint32_t valorUID;
sscanf(buffer, "%d", &valorGID);
buffer += sizeof(uint32_t);
sscanf(buffer, "%d", &valorUID);
printf("ValorGID %d ValorUID %d \n", valorGID, valorUID);
And what I get is
ValorGID 11001000 ValorUID 1000
What I need to get is
ValorGID 1100 ValorUID 1000
I am new in C, so any help would be appreciated.
buffer = realloc(buffer, sizeof(uint32_t));
sprintf(buffer, "%d", gid);
offset += sizeof(uint32_t);
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
sprintf(buffer+sizeof(uint32_t), "%d", uid);
This doesn't really make sense, and will not work as intended except in lucky circumstances.
Let us assume that the usual CHAR_BIT == 8 holds, so sizeof(uint32_t) == 4. Further, let us assume that int is a signed 32-bit integer in two's complement representation without padding bits.
sprintf(buffer, "%d", gid) prints the decimal string representation of the bit-pattern of gid interpreted as an int to buffer. Under the above assumptions, gid is interpreted as a number between -2147483648 and 2147483647 inclusive. Thus the decimal string representation may contain a '-', contains 1 to 10 digits and the 0-terminator, altogether it uses two to twelve bytes. But you have allocated only four bytes, so whenever 999 < gid < 2^32-99 (the signed two's complement interpretation is > 999 or < -99), sprintf writes past the allocated buffer size.
That is undefined behaviour.
It's likely to not crash immediately because allocating four bytes usually gives you a larger chunk of memory effectively (if e.g. malloc always returns 16-byte aligned blocks, the twelve bytes directly behind the allocated four cannot be used by other parts of the programme, but belong to the programme's address space, and writing to them will probably go undetected). But it can easily crash later when the end of the allocated chunk lies on a page boundary.
Also, since you advance the write offset by four bytes for subsequent sprintfs, part of the previous number gets overwritten if the string representation (excluding the 0-termnator) used more than four bytes (while the programme didn't yet crash due to writing to non-allocated memory).
The line
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
contains further errors.
buffer = realloc(buffer, new_size); loses the reference to the allocated memory and causes a leak if realloc fails. Use a temporary and check for success
char *temp = realloc(buffer, new_size);
if (temp == NULL) {
/* reallocation failed, recover or cleanup */
free(buffer);
exit(EXIT_FAILURE);
}
/* it worked */
buffer = temp;
/* temp = NULL; or let temp go out of scope */
The new size sizeof(uint32_t) + sizeof(buffer) of the new allocation is always the same, sizeof(uint32_t) + sizeof(char*). That's typically eight or twelve bytes, so it doesn't take many numbers to write outside the allocated area and cause a crash or memory corruption (which may cause a crash much later).
You must keep track of the number of bytes allocated to buffer and use that to calculate the new size. There is no (portable¹) way to determine the size of the allocated memory block from the pointer to its start.
Now the question is whether you want to store the string representations or the bit patterns in the buffer.
Storing the string representations has the problem that the length of the string representation varies with the value. So you need to include separators between the representations of the numbers, or ensure that all representations have the same length by padding (with spaces or leading zeros) if necessary. That would for example work like
#include <stdint.h>
#include <inttypes.h>
#define MAKESTR(x) # x
#define STR(x) MAKESTR(x)
/* A uint32_t can use 10 decimal digits, so let each field be 10 chars wide */
#define FIELD_WIDTH 10
uint32_t gid = 1100;
uint32_t uid = 1000;
size_t buf_size = 0, offset = 0;
char *buffer = NULL, *temp = NULL;
buffer = realloc(buffer, FIELD_WIDTH + 1); /* one for the '\0' */
if (buffer == NULL) {
exit(EXIT_FAILURE);
}
buf_size = FIELD_WIDTH + 1;
sprintf(buffer, "%0" STR(FIELD_WIDTH) PRIu32, gid);
offset += FIELD_WIDTH;
temp = realloc(buffer, buf_size + FIELD_WIDTH);
if (temp == NULL) {
free(buffer);
exit(EXIT_FAILURE);
}
buffer = temp;
temp = NULL;
buf_size += FIELD_WIDTH;
sprintf(buffer + offset, "%0" STR(FIELD_WIDTH) PRIu32, uid);
offset += FIELD_WIDTH;
/* more */
uint32_t valorGID;
uint32_t valorUID;
/* rewind for scanning */
offset = 0;
sscanf(buffer + offset, "%" STR(FIELD_WIDTH) SCNu32, &valorGID);
offset += FIELD_WIDTH;
sscanf(buffer + offset, "%" STR(FIELD_WIDTH) SCNu32, &valorUID);
printf("ValorGID %u ValorUID %u \n", valorGID, valorUID);
with zero-padded fixed-width fields. If you'd rather use separators than a fixed width, the calculation of the required length and the offsets becomes more complicated, but unless the numbers are large, it would use less space.
If you'd rather store the bit-patterns, which would be the most compact way of storing, you'd use something like
size_t buf_size = 0, offset = 0;
unsigned char *buffer = NULL, temp = NULL;
buffer = realloc(buffer, sizeof(uint32_t));
if (buffer == NULL) {
exit(EXIT_FAILURE);
}
buf_size = sizeof(uint32_t);
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
buffer[offset + b] = (gid >> b*8) & 0xFF;
}
offset += sizeof(uint32_t);
temp = realloc(buffer, buf_size + sizeof(uint32_t));
if (temp == NULL) {
free(buffer);
exit(EXIT_FAILURE);
}
buffer = temp;
temp = NULL;
buf_size += sizeof(uint32_t);
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
buffer[offset + b] = (uid >> b*8) & 0xFF;
}
offset += sizeof(uint32_t);
/* And for reading the values */
uint32_t valorGID, valorUID;
/* rewind */
offset = 0;
valorGID = 0;
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
valorGID |= buffer[offset + b] << b*8;
}
offset += sizeof(uint32_t);
valorUID = 0;
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
valorUID |= buffer[offset + b] << b*8;
}
offset += sizeof(uint32_t);
¹ If you know how malloc etc. work in your implementation, it may be possible to find the size from malloc's bookkeeping data.
The format specifier '%d' is for int and thus is wrong for uint32_t. First uint32_t is an unsigned type, so you should at least use '%u', but then it might also have a different width than int or unsigned. There are macros foreseen in the standard: PRIu32 for printf and SCNu32 for scanf. As an example:
sprintf(buffer, "%" PRIu32, gid);
The representation returned by sprintf is a char*. If you are trying to store an array of integers as their string representatins then your fundamental data type is a char**. This is a ragged matrix of char if we are storing only the string data itself, but since the longest string a uint32_t can yield is 10 chars, plus one for the terminating null, it makes sense to preallocate this many bytes to hold each string.
So to store n uint32_t's from array a in array s as strings:
const size_t kMaxIntLen=11;
uint32_t *a,b;
// fill a somehow
...
size_t n,i;
char **s.*d;
if((d=(char*)malloc(n*kMaxIntLen))==NULL)
// error!
if((s=(char**)malloc(n*sizeof(char*)))==NULL)
// error!
for(i=0;i<n;i++)
{
s[i]=d+i; // this is incremented by sizeof(char*) each iteration
snprintf(s[i],kMaxIntLen,"%u",a[i]); // snprintf to be safe
}
Now the ith number is at s[i] so to print it is just printf("%s",s[i]);, and to retrieve it as an integer into b is sscanf(s[i],"%u",&b);.
Subsequent memory management is a bit trickier. Rather than constantly using using realloc() to grow the buffer, it is better to preallocate a chunk of memory and only alter it when exhausted. If realloc() fails it returns NULL, so store a pointer to your main buffer before calling it and that way you won't lose a reference to your data. Reallocate the d buffer first - again allocate enough room for several more strings - then if it succeeds see if d has changed. If so, destroy (free()) the s buffer, malloc() it again and rebuild the indices (you have to do this since if d has changed all your indices are stale). If not, realloc() s and fix up the new indices. I would suggest wrapping this whole thing in a structure and having a set of routines to operate on it, e.g.:
typedef struct StringArray
{
char **strArray;
char *data;
size_t nStrings;
} StringArray;
This is a lot of work. Do you have to use C? This is vastly easier as a C++ STL vector<string> or list<string> with the istringstream classes and the push_back() container method.
uint32_t gid = 1100;
uint32_t uid = 1000;
char* buffer = NULL;
uint32_t offset = 0;
buffer = realloc(buffer, sizeof(uint32_t));
sprintf(buffer, "%d", gid);
offset += sizeof(uint32_t);
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
sprintf(buffer+sizeof(uint32_t), "%d", uid);
uint32_t valorGID;
uint32_t valorUID;
sscanf(buffer, "%4d", &valorGID);
buffer += sizeof(uint32_t);
sscanf(buffer, "%d", &valorUID);
printf("ValorGID %d ValorUID %d \n", valorGID, valorUID);
`
I think this may resolve the issue !