I am writing a program for creating, sending, receiving and interpreting ARP packets. I have a structure representing an ARP header as follows:
struct ArpHeader { unsigned short hardwareType; unsigned short protocolType; unsigned char hardwareAddressLength; unsigned char protocolAddressLength; unsigned short operationCode; unsigned char senderHardwareAddress[6]; unsigned char senderProtocolAddress[4]; unsigned char targetHardwareAddress[6]; unsigned char targetProtocolAddress[4]; };
This only works for hardware addresses of length 6 and protocol addresses of length 4. The length of the address is also indicated in the header, so to be correct, the structure should look something like this:
struct ArpHeader { unsigned short hardwareType; unsigned short protocolType; unsigned char hardwareAddressLength; unsigned char protocolAddressLength; unsigned short operationCode; unsigned char senderHardwareAddress[hardwareAddressLength]; unsigned char senderProtocolAddress[protocolAddressLength]; unsigned char targetHardwareAddress[hardwareAddressLength]; unsigned char targetProtocolAddress[protocolAddressLength]; };
This obviously will not work, since the lengths of the addresses are not known at compile time. Pattern structures are not an option, since I would like to fill in the values ββfor the structure, and then just drop it (ArpHeader *) to (char *) to get an array of bytes that can be sent on the network or discard the received byte array from (char *) before (ArpHeader *) to interpret it.
One solution would be to create a class with all the header fields as member variables, a function to create a byte array representing the ARP header that can be sent on the network, and a constructor that will only accept the byte array (received on the network) and interpret him by reading all the header fields and writing them to member variables. This is not a good solution, as it will require LOT more code.
Otherwise, a similar structure for the UDP header, for example, is simple, since all header fields have a known constant size. I use
#pragma pack(push, 1) #pragma pack(pop)
around the structure declaration so that I can do a simple C-style to get an array of bytes to be sent on the network.
Is there any solution that I could use here that would be close to the structure, or at least not require much more code than the structure? I know that the last field in the structure (if it is an array) does not need a certain amount of compilation time, can I use something like this for my problem? Just leaving the dimensions of these 4 arrays empty will compile, but I have no idea how this will work. It just doesn't logically work, because the compiler had no idea where the second array starts if the size of the first array is unknown.