分享

谨慎使用LINUX平台的gethostbyname

 lycbje 2013-12-30
编译运行下面的代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>

#include <pthread.h>

unsigned int get_ip4(char *host)
{
        //临时变量
        char                        dns_buff[8192];
        struct hostent                hostinfo, *phost;
        struct sockaddr_in        addr4;
        int                        i, flag, rc;

        time_t                        now;
        unsigned int                ip4;

        //尝试直接转换
        bzero(&addr4, sizeof(struct sockaddr_in));
        if (1 == inet_pton(AF_INET, host, &(addr4.sin_addr))) return(addr4.sin_addr.s_addr);

        //查询DNS
        if (0 == gethostbyname_r(host, &hostinfo, dns_buff, 8192, &phost, &rc)) {
                ip4 = *(unsigned int *)(hostinfo.h_addr);//新记录
        } else {
                ip4 = 0;//查询失败
        }
        return(ip4);

}

int main(int argc, char *argv[])
{
        unsigned int        ip4 = 0;
       
        ip4 = get_ip4("192.1468.80.38");
        return(0);
}

在freeBSD运行不会段错误, 在CentOS 4上就会段错误
现在我只好重新实现类似函数了
其它LINUX/UNIX平台的帮我实验下, 我想确定是LINUX还是仅仅是RHEL的问题
谢谢了关于gethostbyname_r的返回值
man手册是这么说的

/* GNU extensions */
       struct hostent *gethostbyname2(const char *name, int af);

       int gethostbyname_r (const char *name,
         struct hostent *ret, char *buf, size_t buflen,
         struct hostent **result, int *h_errnop);

       int gethostbyname2_r (const char *name, int af,
         struct hostent *ret, char *buf, size_t buflen,
         struct hostent **result, int *h_errnop);
......


       The functions gethostbyname() and gethostbyaddr() may return  pointers
       to  static  data, which may be overwritten by later calls. Copying the
       struct hostent does not suffice, since it contains pointers -  a  deep
       copy is required.

       Glibc2  also  has  a gethostbyname2() that works like gethostbyname(),
       but permits to specify the address family to which  the  address  must
       belong.

       Glibc2  also  has  reentrant versions gethostbyname_r() and gethostby-
       name2_r().  These return 0 on success and nonzero on error. The result
       of  the  call is now stored in the struct with address ret.  After the
       call, *result will be NULL on error or point to the result on success.
       Auxiliary  data is stored in the buffer buf of length buflen.  (If the
       buffer is too small, these functions will return ERANGE.)   No  global
       variable  h_errno  is modified, but the address of a variable in which
       to store error numbers is passed in h_errnop.

按照man的说法
gethostbyname_r()调用成功时返回0
*result指向解析成功的数据结构, *result如果为NULL则表示解析出错

我根据实验发现
如果被解析的字符串是类似"xxx.xxx.xxx.xxx"的 数字+点 字符串
那么gethostbyname_r并没有发出DNS请求
而是直接去计算了
192.1468.80.38显然不是合法的IP地址, 但gethostbyname_r()返回0
此时*result是NULL
所以我程序中的那句ip4 = *(unsigned int *)(hostinfo.h_addr);就会段错误

如果被解析的字串确实无法解析, gethostbyname_r()返回非零值
但前提是: 这个字串不能是类似"xxx.xxx.xxx.xxx"的 数字+点 字符串
否则gethostbyname_r根本不发出DNS请求

刚才在FreeBSD/MAC OS X上测试了一下
对于192.1468.80.38这样的非法IP地址, gethostbyname_r()返回非零值,
不会导致执行ip4 = *(unsigned int *)(hostinfo.h_addr);造成段错误

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多