c-确定是ipv4还是ipv6数据结构



在内核模块中,给定一个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(,但不幸的是,这里的情况并非如此。

最新更新