2.3 当参数name是主机名时的处理
当net_addr()函数返回INADDR_NONE,则需要考虑参数name是主机名。即
if (iaddr.s_addr == INADDR_NONE)//name是计算机名
{
if (numeric)
{
bail("Can't parse %s as an IP address", name);
}
.......
}
2.3.1 numeric值的判断
在“2.1 函数定义”中提到,gethostpoop()函数的参数numeric的值是与参数name对应的,当numeric的值是0时,则name的值必须是主机名;当numeric的值是非0时,则name的值必须是IP地址。所以,当参数name是主机名时,必须要判断numeric的值是否是0,如果不是0,则弹出错误信息。
2.3.2 根据主机名获取主机信息
hostent = gethostbyname(name);
if (!hostent)
{
char my_h_errno[10] = { 0 };
_itoa(h_errno, my_h_errno, 10);
bail("%s: forward host lookup failed: h_errno %s ", name, my_h_errno);
}
else
{
.......
}
其中,gethostbyname()函数的作用是通过主机名获取主机信息。该函数的参数为主机名,返回值是hostent结构的指针。gethostbyname()函数及hostent结构的详细说明请参考《Winsock网络编程获取主机信息》。如果成功获取了主机信息,则gethostbyname()函数返回获取到的主机信息,如果获取失败,则返回空指针。从以上代码可以,如果获取主机信息失败,则通过自定义的bail()打印出错信息,并退出程序。
2.3.3 处理主机信息
如果成功获取了主机信息,则在“2.3.2 根据主机名获取主机信息”提到的else语句中,对获取到主机信息进行处理。
strncpy(poop->name, hostent->h_name, sizeof(poop->name));
for (x = 0; hostent->h_addr_list[x] && (x < 8); x++)
{
memcpy(&poop->iaddrs[x], hostent->h_addr_list[x], sizeof(IA));
strncpy(poop->addrs[x], inet_ntoa(poop->iaddrs[x]), sizeof(poop->addrs[0]));
}
其中,hostent->h_name是获取到的主机名,将其拷贝到poop->name中。之后,通过for循环遍历获取到的主机IP地址列表,其中x<8保证了只处理IP列表中的前8个IP地址。将IP地址拷贝到poop->iaddrs数组的相应元素中;inet_ntoa()函数将数字格式的IP地址转换为XXX.XXX.XXX.XXX格式,最后通过strncpy()函数将其拷贝到poop->addrs数组中的相应元素中。
2.3.4 无需详细信息的处理
netcat的-v参数表示是否详细输出信息,当加入该参数时,netcat源代码中的o_verbose值为非0,如果不加该参数时,o_verbose的值是0。所以,在“2.3.3 处理主机信息”中获取了主机信息之后,有如下代码
if (!o_verbose)
{
return (poop);
}
如果o_verbose的值是0,则说明netcat没有加入-v函数,此时无需显示详细信息,则程序直接返回poop即可。