我有一个原始的ipv6套接字,我从中获得了这个udp数据包。 套接字(AF_INET6,SOCK_RAW,IPPROTO_UDP)
我需要在收到的数据包上验证udp校验和,并计算伪头,需要找到源ip地址。不确定如何从ipv6原始套接字获取该信息。
对于目标地址,我们有IPV6_RECVPKTINFO套接字选项,但不确定如何从中获取源地址。
答案 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。