I have these two functions:
static inline void *ether_payload(void *pkt)
{
return ((char*)pkt) + 14;
}
static inline uint16_t ip_id(const void *pkt)
{
const char *cpkt = pkt;
uint16_t id;
memcpy(&id, &cpkt[4], sizeof(id));
return ntohs(id);
}
Now, there's a type safety issue. For the first function, void pointer means Ethernet header. For the second function, void pointer means IPv4 header. This creates a huge possibility that somebody accidentally calls the second function for an Ethernet header directly. If somebody does so, the compiler gives no warning.
I would like to eliminate this type safety issue through two dummy structs the contents of which are never defined:
struct etherhdr;
struct ipv4hdr;
Now the functions would be:
static inline struct ipv4hdr *ether_payload(struct etherhdr *pkt)
{
return (struct ipv4hdr*)(((char*)pkt) + 14);
}
static inline uint16_t ip_id(const struct ipv4hdr *pkt)
{
const char *cpkt = (const char*)pkt;
uint16_t id;
memcpy(&id, &cpkt[4], sizeof(id));
return ntohs(id);
}
This solves the type safety issue. Note I'm not actually accessing the Ethernet or IP headers through a struct which would be very bad practice indeed.
My question is, am I violating strict aliasing rules by defining such an API? Note the data is never accessed via the struct; the data is just accessed via memcpy using a char pointer. My understanding is that char pointer can alias to anything.
Let's leave the fact that Ethernet packet can contain IPv6 as irrelevant, as this was just a very simple example.