【问题标题】:getaddrinfo() returning 2.0.0.0getaddrinfo() 返回 2.0.0.0
【发布时间】:2013-11-23 14:39:24
【问题描述】:

我正在尝试查找主机名的 IP 地址,即 www.google.com

我调用 getaddrinfo() 扫描列表,创建一个原始 ipv4 icmp 套接字,然后我将套接字绑定到地址

当我检查在 wireshark 中发送的数据包时,无论我传递给 getaddrinfo() 的主机名是什么,地址都显示为 2.0.0.0

  int                  skt, errno;
   struct sockaddr_in   addr;
   struct addrinfo      hints;  //prefered addr type(connection)
   struct addrinfo  *   list;   //list of addr structs
   struct addrinfo  *   addrptr;//the one i am gonna use

   struct in_addr test;

    if(servname == NULL){
        fprintf(stderr, "No servname!\n");
        exit(1);
    }

    /*
     * prefered connection type
     */

    bzero(&hints, sizeof(hints));
    hints.ai_flags                = 0;
    hints.ai_family               = AF_INET;
    hints.ai_socktype             = SOCK_RAW;
    hints.ai_protocol             = IPPROTO_ICMP;                 

    /*get IP*/
    if((errno = getaddrinfo(servname, 0, &hints, &list))<0){
        fprintf(stderr, "addrinfo error, lookup fail:  %s",
        gai_strerror(errno));
        exit(1);
    }

   addrptr=list;
   //start scanning 
   while(addrptr){
       //start
       if((skt = socket(addrptr->ai_family, addrptr->ai_socktype, addrptr->ai_protocol))<0){
        perror("socket()");
        exit(1);
       }
           if(skt > 0)
            if(connect(skt,addrptr->ai_addr, addrptr->ai_addrlen)==0)
                break;
            printf("attempt connect\n");
            close (skt);
            addrptr=addrptr->ai_next;
    }


 //once IP has been found set destination address an port=0
 dstaddr.sin_addr.s_addr = ((struct in_addr *)addrptr->ai_addr)->s_addr;
 dstaddr.sin_port        = 0;

【问题讨论】:

  • 您是否尝试过使用gethostbybname() 将您的主机名转换为IP 地址? getaddrinfo() 在内部使用这个函数。
  • 这是我的网络课程中的一项课外作业,他们有点强调使用 getaddrinfo(),因为它是“现代”方法。
  • @Babbleshack 他们是对的。 gethostbyname() 不应再使用,至少在新程序中是这样。最好使用getaddrinfo()getnameinfo();它们涵盖了您可能想要完成的所有事情。
  • 好的,所以我认为我正确接收了 IP 地址,但是我将数据 addrptr 复制到 dstaddr 不正确

标签: c sockets


【解决方案1】:

您的代码中似乎有一些错误:

  • addrptr=list-&gt;ai_next 应该是 addrptr=addr-&gt;ai_next 来遍历列表。
  • 在 while 循环之后,addrptr-&gt;ai_addr 保存最后找到的条目,而不是 list-&gt;ai_addr
  • bind()成功 时返回零,因此您应该与 if(bind(...) == 0) break; 核对
  • 除非我弄错了,bind() 用于将套接字绑定到本地地址。 要检查是否可以通过某个地址访问主机,请改用 connect()

这是我尝试过的代码:

int main(int argc, const char * argv[])
{
    int                  skt, errno;
    struct addrinfo      hints;  //prefered addr type(connection)
    struct addrinfo  *   list;   //list of addr structs
    struct addrinfo  *   addrptr;//the one i am gonna use

    char *servname = "www.google.com";

    memset(&hints, 0, sizeof(hints));
    hints.ai_flags                = 0;
    hints.ai_family               = AF_INET;
    hints.ai_socktype             = SOCK_RAW;
    hints.ai_protocol             = IPPROTO_ICMP;

    if ((errno = getaddrinfo(servname, 0, &hints, &list))<0){
        fprintf(stderr, "addrinfo error, lookup fail:  %s", gai_strerror(errno));
        exit(1);
    }

    for (addrptr = list; addrptr != NULL; addrptr = addrptr->ai_next) {
        if ((skt = socket(addrptr->ai_family, addrptr->ai_socktype, addrptr->ai_protocol)) == -1)
            continue;
        if(connect(skt,addrptr->ai_addr, addrptr->ai_addrlen) == 0)
            break;
        close (skt);
    }

    if (addrptr != NULL) {
        char host[NI_MAXHOST];
        getnameinfo(addrptr->ai_addr, addrptr->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
        printf("%s can be reached at %s\n", servname, host);
    }

    return 0;
}

输出是:“www.google.com 可以到达 173.194.113.146”

更新:你复制找到的地址的代码是错误的,应该是

struct sockaddr_in dstaddr;
memcpy(&dstaddr, addrptr->ai_addr, sizeof(dstaddr));
dstaddr.sin_port        = 0;

【讨论】:

  • 谢谢,我已经进行了第一次更改,只是忘记更新问题了。我会让其他人看看会发生什么
  • 我正在查看一些笔记,据我所知,我应该使用绑定,但我找不到原因;或想出一个。在列表用完之前,绑定或连接都没有成功。
  • @Babbleshack:我已经用if(connect(skt,addrptr-&gt;ai_addr, addrptr-&gt;ai_addrlen) == 0) break; 测试了代码,它返回了一个有效的 www.google.com 的 IP 地址 (173.194.113.146)。请注意,您必须与== 0 确认是否成功。
  • 我不认为我没有安装防火墙软件,我使用的是 linux 机器。
  • @Babbleshack:你试过 if(connect(...) == 0) break 吗?
【解决方案2】:

澄清一下,这发生在投射时

struct sockaddr_in dest;
struct addrinfo* ainfo_arr;

/*getaddrinfo(hostname,NULL,&hints,&ainfo_arr);*/

dest = *( (struct sockaddr_in*) ainfo_arr);
//casting addrinfo to sockaddr_in

而不是

struct sockaddr_in dest;
struct addrinfo* ainfo_arr;

/*getaddrinfo(hostname,NULL,&hints,&ainfo_arr);*/

dest = *( (struct sockaddr_in*) ainfo_arr->ai_addr);
//casting sockaddr to sockaddr_in

所以dest 中的数据无效

(可能是AF_PACKEThttps://stackoverflow.com/a/40254078/6569209

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2019-02-15
    • 2017-02-02
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多