判断是ipv4还是ipv6数据结构

Determine if ipv4 or ipv6 data structure

在内核模块中,给定 struct sockaddrsa_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),但不幸的是,这似乎不是这里的案例。