在内核模块中,给定初始化为struct sockaddrsa_family,如何可靠地确定它是AF_UNSPEC还是struct sockaddr_in?在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的长度。例如,请参见:

ssize_t sendto (int sockfd, const void *buf, size_t buflen, int flags,
                    const struct sockaddr *addr, socklen_t addrlen);

使用缓冲区的大小,您应该能够很好地猜测需要使用哪种类型的sendto()
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;
        }
    }
}

在理想的情况下,sockaddr将被设置为seithersa_family(IPv4)或AF_INET(IPv6),但不幸的是,这里似乎不是这样。

关于c - 确定ipv4或ipv6数据结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31232771/

10-10 23:01