ipv6的UDP校验和验证:如何从辅助数据中获取ipv6源地址

时间:2018-10-26 08:36:13

标签: c sockets udp ipv6

我有一个原始的ipv6套接字,我从中获得了这个udp数据包。 套接字(AF_INET6,SOCK_RAW,IPPROTO_UDP)

我需要在收到的数据包上验证udp校验和,并计算伪头,需要找到源ip地址。不确定如何从ipv6原始套接字获取该信息。

对于目标地址,我们有IPV6_RECVPKTINFO套接字选项,但不确定如何从中获取源地址。

2 个答案:

答案 0 :(得分:0)

这不是RAW套接字和IPv6。建议不要研究任何代码,而无需执行任何代码。参见此处:https://www.ietf.org/rfc/rfc3542.txt。特别要注意的是Page21-4至6和6.2。

另请参见:(ssize_t recvmsg(int socket, struct msghdr *message, int flags);)中的msg_control

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`
}

答案 1 :(得分:0)

您正在使用套接字接口。因此,您将使用recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t addrlen);recvmsg(int sockfd, struct msghdr *msg, int flags);接收UDP数据包。

请注意,对于大多数操作系统(Linux,Unix,Windows等),在获取数据包之前已经检查了CRC,因此您无需检查CRC。

对于recvfrom(),源地址存储在第5个参数所指向的缓冲区的一部分中,即struct sockaddr_in6结构。要分配此缓冲区,您可能更喜欢使用sockaddr_storage结构而不是sockaddr_in6,因为它足够大以容纳所有受支持的协议特定的地址结构,并且您可以重新使用此缓冲区来处理其他地址类型。

因此,您可以使用填充为 ((struct sockaddr_in6 *) src_addr)->sin6_addr 且类型为struct in6_addr的伪缓冲区来计算CRC。

使用recvmsg(),您可以在第二个参数中提供指向struct msghdr的指针,并且源地址存储在msg_name字段所指向的缓冲区的一部分中,{ {1}}结构。

因此,您可以使用填充为 struct sockaddr_in6 且类型为((struct sockaddr_in6 *) msg_name)->sin6_addr的伪缓冲区来计算CRC。

最后,请注意,对于基于BSD的系统,例如OS-X或FreeBSD,即使作用域ID存储在struct in6_addr结构的字段中,它也将其作为地址嵌入到地址本身中。第二个16位字。因此,在这种情况下,您不应将地址的这一部分复制到伪标题中,而应将其替换为0。