0
votes

I have a raw ipv6 socket, from which I am getting this udp packet. socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)

I need to verify the udp checksum on the packet received, and to calculate the pseudo header, need to find the source ip address. Not sure how to get that from ipv6 raw socket.

For destination address, we have the IPV6_RECVPKTINFO socket option, but not sure how to get source address from it.

2

2 Answers

0
votes

Im not that into RAW Sockets and IPv6. Without having any code to execute, I recommend to look into the RFC. See here: https://www.ietf.org/rfc/rfc3542.txt. In particular look to Page21 - 4 to 6 and 6.2.

Also see the msg_control in: (ssize_t recvmsg(int socket, struct msghdr *message, int flags);)

struct msghdr {

    void         *msg_name        optional address
    socklen_t     msg_namelen     size of address
    struct iovec *msg_iov         scatter/gather array
    int           msg_iovlen      members in msg_iov
    void         *msg_control     ancillary data, see below
    socklen_t     msg_controllen  ancillary data buffer len
    int           msg_flags       flags on received message`
}
0
votes

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.