For a school project, I have to develop a TFTP server in C. I have to build a packet in a array of char like this :
2 bytes 2 bytes n bytes
+--------+-----------+--------+
| CODE | Block # | Data |
+--------+-----------+--------+
Here is how I build this packet:
int tftp_make_data(char *buffer, size_t *length, uint16_t block, const char *data, size_t n) {
memset(buffer, 0, *length);
*length = 0;
*(buffer) = DATA;
*length += sizeof(uint16_t);
*(buffer + *length) = block;
*length += sizeof(uint16_t);
memcpy(buffer + *length, data, n);
*length += n;
return 0;
}
This function fill buffer
with the packet content and fill length
with the size of the packet.
This works fine if block
is lower than 128. If it's greeter than 128, it becomes -128.
Can you help me?
Unless something is one byte in size, you cannot assign it to *buffer
. Both of these assignments are incorrect:
*(buffer) = DATA;
*(buffer + *length) = block;
When you are writing uint16_t
, use memcpy
:
uint16_t dataToWrite = ...;
memcpy(buffer + *length, &dataToWrite, sizeof(uint16_t));
You are not done yet, because you need to decide what to assign dataToWrite
. If you do this
uint16_t dataToWrite = block;
the data sent over the wire will be in hardware-specific order, which should never happen. Instead, you need to use one of hton
-family functions to convert your number to network format:
uint16_t dataToWrite = htons(block);
I check it on the same machine, just with
printf("block : %d\n", packet[sizeof(uint_16)]);
This is incorrect, for the same reason as the assignment: packet[sizeof(uint_16)]
makes an int
or unsigned int
from the char
/uint8_t
value stored at position sizeof(uint_16)
, and it also ignores the other byte.
To fix this you need to use memcpy
again. Of course, if you used htons
on the writing side, you need to use ntohs
before printing:
uint16_t dataToPrint;
memcpy(dataToPrint, &packet[sizeof(uint16_t)], sizeof(uint16_t));
dataToPrint = ntohs(dataToPrint);
printf("block : %u\n", dataToPrint);