ai_addr指针中的28字节代表什么?

huangapple go评论51阅读模式
英文:

What does the 28 bytes mean in ai_addr->sa_data?

问题

第一个 6 字节和最后一个 6 字节有什么用?

英文:

I tested with "::1" and the ip address of a domain. It seems like the ipv6 address has an addrlen of 28. The first 6 was blank (I know the first two bytes of ipv4 is the 16bit port but I'm stumped here) and the last 6 bytes is blank. The middle 16bytes is the 128bit ipv6 address

What is the first 6 bytes and last 6 bytes used for?

答案1

得分: 0

sa_data字段的内容取决于sa_family字段中指定的地址族。

ai_addr->sa_familyAF_INET时,ai_addr指向一个sockaddr_in结构体:

struct sockaddr_in {
    sa_family_t    sin_family; /* 地址族:AF_INET */
    in_port_t      sin_port;   /* 端口(网络字节顺序) */
    struct in_addr sin_addr;   /* 互联网地址 */
};

/* 互联网地址 */
struct in_addr {
    uint32_t       s_addr;     /* 网络字节顺序中的地址 */
};

因此,ai_addr->sa_data包含了sin_portsin_addr字段的数据(6个字节)。sockaddr_in的总大小为8个字节。

ai_addr->sa_familyAF_INET6时,ai_addr指向一个sockaddr_in6结构体:

struct sockaddr_in6 {
    sa_family_t     sin6_family;   /* AF_INET6 */
    in_port_t       sin6_port;     /* 端口号 */
    uint32_t        sin6_flowinfo; /* IPv6流信息 */
    struct in6_addr sin6_addr;     /* IPv6地址 */
    uint32_t        sin6_scope_id; /* 作用域ID(2.4版引入) */
};

struct in6_addr {
    unsigned char   s6_addr[16];   /* IPv6地址 */
};

因此,ai_addr->sa_data包含了sin6_portsin6_scope_id字段的数据(26个字节)。sockaddr_in6的总大小为28个字节(在不包含sin6_scope_id的系统上除外)。

因此,您需要查看ai_addr->sa_family字段,然后对ai_addr进行类型转换(或使用memcpy())以正确访问其他字段,例如:

struct addrinfo hints, *addrs;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
...

int res = getaddrinfo(..., &hints, &addrs);
if (res != 0) ...
for (struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next) {
    switch (addr->ai_addr->sa_family) {
        case AF_INET: {
            struct sockaddr_in *ip4 = (struct sockaddr_in *) addr->ai_addr;
            /* 或者:
            struct sockaddr_in ip4;
            memcpy(&ip4, addr->ai_addr, sizeof(ip4));
            */
            // 根据需要使用ip4...
            break;
        }

        case AF_INET6: {
            struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *) addr->ai_addr;
            /* 或者:
            struct sockaddr_in6 ip6;
            memcpy(&ip6, addr->ai_addr, sizeof(ip6));
            */
            // 根据需要使用ip6...
            break;
        }
    }
}
freeaddrinfo(addrs);
英文:

The contents of the sa_data field are dependent on the address family specified in the sa_family field.

When ai_addr->sa_family is AF_INET, ai_addr is pointing at a sockaddr_in struct:

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

Thus, ai_addr->sa_data contains the data for the sin_port and sin_addr fields (6 bytes). The total size of sockaddr_in is 8 bytes.

When ai_addr->sa_family is AF_INET6, ai_addr is pointing at a sockaddr_in6 struct instead:

struct sockaddr_in6 {
    sa_family_t     sin6_family;   /* AF_INET6 */
    in_port_t       sin6_port;     /* port number */
    uint32_t        sin6_flowinfo; /* IPv6 flow information */
    struct in6_addr sin6_addr;     /* IPv6 address */
    uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
};

struct in6_addr {
    unsigned char   s6_addr[16];   /* IPv6 address */
};

Thus, ai_addr->sa_data contains the data for the sin6_port..sin6_scope_id fields (26 bytes). The total size of sockaddr_in6 is 28 bytes (except on systems where sin6_scope_id is not present).

So, you need to look at the ai_addr->sa_family field and then type-cast ai_addr (or memcpy() it) to access the other fields correctly, eg:

struct addrinfo hints, *addrs;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
...

int res = getaddrinfo(..., &hints, &addrs);
if (res != 0) ...
for(struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next) {
    switch (addr->ai_addr->sa_family) {
        case AF_INET: {
            struct sockaddr_in *ip4 = (struct sockaddr_in *) addr->ai_addr;
            /* alternatively:
            struct sockaddr_in ip4;
            memcpy(&ip4, addr->ai_addr, sizeof(ip4));
            */
            // use ip4 as needed...
            break;
        }

        case AF_INET6: {
            struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *) addr->ai_addr;
            /* alternatively:
            struct sockaddr_in6 ip6;
            memcpy(&ip6, addr->ai_addr, sizeof(ip6));
            */
            // use ip6 as needed...
            break;
        }
    }
}
freeaddrinfo(addrs);

huangapple
  • 本文由 发表于 2023年5月30日 08:14:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76360933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定