You are using the socket interface. So, you receive the UDP packet using recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t addrlen);
or recvmsg(int sockfd, struct msghdr *msg, int flags);
.
Note that with most operating systems (Linux, Unix, Windows, ...), the CRC has already been checked before you get the packet, therefore you do not need to check the CRC.
With recvfrom()
, the source address is stored in a part of the buffer pointed by the 5th argument, that is a struct sockaddr_in6
structure. To allocate this buffer, you may prefer to use a sockaddr_storage
structure instead of a sockaddr_in6
, because it is large enough to accommodate all supported protocol-specific address structures, and you could re-use this buffer to handle other address types.
So you can compute your CRC using a pseudo-buffer filled with ((struct sockaddr_in6 *) src_addr)->sin6_addr
, that has type struct in6_addr
.
With recvmsg()
, you give a pointer to a struct msghdr
in the 2nd argument and the source address is stored in a part of the buffer pointed by the msg_name
field, in a struct sockaddr_in6
structure.
So you can compute your CRC using a pseudo-buffer filled with ((struct sockaddr_in6 *) msg_name)->sin6_addr
, that has type struct in6_addr
.
Finally, note that with BSD based systems like OS-X or FreeBSD, even if the scope id is stored in a field of the struct sockaddr_in6
structure, it is also embedded into the address itself as the second 16 bit word. Therefore, in such a case, you should not copy this part of the address into the pseudo-header, but replace it with 0.