在内核模块中,给定一个struct sockaddr
,其中sa_family
初始化为AF_UNSPEC
,我如何可靠地确定它是struct sockaddr_in
还是struct sockaddr_in6
?在Linux 3.16.0-4-686-pae(x86(上。
struct sockaddr {
unsigned short sa_family; // AF_UNSPEC
char sa_data[14]; // ?
};
struct sockaddr_in {
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr_in6 {
unsigned short sin6_family;
unsigned short sin6_port;
unsigned int sin6_flowinfo;
struct in6_addr sin6_addr;
unsigned int sin6_scope_id;
};
通常,当某个东西调用内核并给出struct sockaddr
时,它还必须给出struct sockaddr
的长度。例如,参见sendto()
:
ssize_t sendto (int sockfd, const void *buf, size_t buflen, int flags,
const struct sockaddr *addr, socklen_t addrlen);
使用缓冲区的大小,您应该能够很好地猜测需要使用哪种类型的sockaddr
:
if (addr.sa_family == AF_UNSPEC) {
switch (addrlen) {
case sizeof (struct sockaddr_in): {
addr.sa_family = AF_INET;
break;
}
case sizeof (struct sockaddr_in6): {
addr.sa_family = AF_INET6;
break;
}
default: {
// handle error
break;
}
}
}
在理想的情况下,sa_family
将被设置为AF_INET
(IPv4(或AF_INET6
(IPv6(,但不幸的是,这里的情况并非如此。