免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 35492 | 回复: 9
打印 上一主题 下一主题

[函数] 谨慎使用LINUX平台的gethostbyname_r函数 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-31 17:18 |只看该作者 |倒序浏览
编译运行下面的代码:

#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的问题
谢谢了

[[i] 本帖最后由 safedead 于 2007-8-31 17:25 编辑 [/i]]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2007-08-31 18:01 |只看该作者
关于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
3 [报告]
发表于 2007-09-01 16:25 |只看该作者
楼主很细心

论坛徽章:
0
4 [报告]
发表于 2009-10-26 14:21 |只看该作者

论坛徽章:
0
5 [报告]
发表于 2014-11-11 17:58 |只看该作者
“刚才在FreeBSD/MAC OS X上测试了一下
对于192.1468.80.38这样的非法IP地址,gethostbyname_r()返回非零值,”。
    请问下,gethostbyname_r函数是iOS的哪个头文件里?

论坛徽章:
0
6 [报告]
发表于 2014-11-13 21:21 |只看该作者
回复 1# safedead

没用过这个函数, 不过既然你看了文档, 那么是不是应该判断一下result是不是NULL再做赋值呢?

   

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
7 [报告]
发表于 2014-11-14 15:40 |只看该作者
safedead 发表于 2007-08-31 17:18
编译运行下面的代码:

#include

ip4 = *(unsigned int *)(hostinfo.h_addr);//

返回局部数据?
到哪都是得死的,没死是侥幸。


跟get...._r没关系。。

论坛徽章:
0
8 [报告]
发表于 2014-11-15 12:26 |只看该作者
yulihua49 发表于 2014-11-14 15:40
ip4 = *(unsigned int *)(hostinfo.h_addr);//

返回局部数据?


你再看看。。。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
9 [报告]
发表于 2014-11-15 16:22 |只看该作者
本帖最后由 yulihua49 于 2014-11-15 16:30 编辑
xphh2008 发表于 2014-11-15 12:26
你再看看。。。

return(ip4);//你死定了。。。。
unsigned int get_ip4(char *host,char *buf)
{
。。。。。。。
              memcpy(buf,hostinfo.h_addr,?));      

论坛徽章:
0
10 [报告]
发表于 2014-11-15 16:25 |只看该作者
yulihua49 发表于 2014-11-15 16:22
return(ip4);//你死定了。。。。


开玩笑,返回的又不是指针。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP