c-如何理解存储在sockaddr_storage中的IP的IP版本



我是IPV6的新手,我需要将我的项目从IPV4风格移植到双栈支持风格,我在某个点上陷入了困境。我需要了解存储在sockaddr_storage中的地址的IP版本,而无需检查其家族。

我写了一个代码并尝试使用"inet_ntop"函数,但它将所有族相互转换,没有任何错误。例如,它将";fe80::9110:403c:1f99:acb";IP到";0.0.0.0";如果我试图使用AF_INET转换它,并且它是一个有效的IPV4地址,那么我的代码就会得到错误的操作。

请检查下面的代码;

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include "ipv6_util.h"
#define SUCCESS (EXIT_SUCCESS)
#define FAIL    (EXIT_FAILURE)
#define UNUSED(__val__) (void)(__val__)
#define PORT            9999
#define CONN_COUNT      1
#define BUFFER_SIZE     1024
#define QUIT_MESSAGE    "quit"
#define ACK_MESSAGE     "ack"
#define IPV6_IP_1      "::1"
#define IPV4_IP_1      "127.0.0.1"
#define IPV4_IP_2      "192.168.2.254"
#define IPV4_IP_3      "100.100.100.100"
#define IPV6_IP_2      "fe80::9110:403c:1f99:eacb"

void ipv6_util_get_ipadd_ver_from_addr2(const struct sockaddr_storage *ipaddress)
{
char address_buf[128] = {0};
memset(address_buf, 0, 128);
if (inet_ntop(AF_INET, &((struct sockaddr_in *)ipaddress)->sin_addr, address_buf, 128)) {
printf("it is ipv4n");
printf("buff: %s  %dn", address_buf, __LINE__);
//return;
}
memset(address_buf, 0, 128);
if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ipaddress)->sin6_addr, address_buf, 128)) {
printf("it is ipv6n");
printf("buff: %s  %dn", address_buf, __LINE__);
//return;
}
}
int main(void)
{
struct sockaddr_storage dumm;
memset(&dumm, 0, sizeof(struct sockaddr_storage));

printf("n");
memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET6, IPV6_IP_1, &((struct sockaddr_in6 *)&dumm)->sin6_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");

memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET, IPV4_IP_1, &((struct sockaddr_in *)&dumm)->sin_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");

memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET, IPV4_IP_2, &((struct sockaddr_in *)&dumm)->sin_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");

memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET6, IPV6_IP_2, &((struct sockaddr_in6 *)&dumm)->sin6_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");

memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET, IPV4_IP_3, &((struct sockaddr_in *)&dumm)->sin_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");

return SUCCESS;

return 0;
}

对于这个代码,我得到了这个输出;

it is ipv4
buff: 0.0.0.0  39
it is ipv6
buff: ::1  46

it is ipv4
buff: 127.0.0.1  39
it is ipv6
buff: ::  46

it is ipv4
buff: 192.168.2.254  39
it is ipv6
buff: ::  46

it is ipv4
buff: 0.0.0.0  39
it is ipv6
buff: fe80::9110:403c:1f99:eacb  46

it is ipv4
buff: 100.100.100.100  39
it is ipv6
buff: ::  46

所以我找不到它的原始版本。我该怎么做?

谢谢你的帮助。

地址族仅在ss_familysa_family成员中。

使用getaddrinfosockaddr转换为可读格式。

您不应该使用sockaddr_storage作为函数的参数,而是使用sockaddr并将sockaddr_storage强制转换为sockaddr

我按照Cheatah的建议尝试了getnameinfo函数,结果和我原来的帖子一样。我的意思是,在某个时刻,我似乎不得不将switchcase与sa_familiy一起使用。

谢谢大家。

最新更新