我正在编写一个端口扫描程序,目的是遍历整个子网,看看端口445是否在任何主机上打开,作为学习C编程的一种方式。当前设置此程序的方式,需要手动输入单个IP地址,扫描仪将关闭。它完美地工作(最后)。
我面临的当前问题:我不确定如何让这个程序扫描整个子网,而不仅仅是单个主机。在研究了这个问题后,我认为最好的路径是剥离IP地址的最后一个八位字节,然后从1-254开始循环。但是,我不完全确定如何开始解决这个问题。这是我目前的代码(经过充分评论澄清):
...
void portScan() {
struct hostent *host;
int err, i , sock ,start , end;
char hostname[100];
struct sockaddr_in sa;
//Get the hostname to scan
printf("Enter hostname or IP to scan: ");
gets(hostname);
//Get start port number
start = 445;
//Get end port number
end = 445;
//Initialise the sockaddr_in structure
strncpy((char*)&sa , "" , sizeof sa);
sa.sin_family = AF_INET;
//direct ip address, use it
if(isdigit(hostname[0])) {
sa.sin_addr.s_addr = inet_addr(hostname);
}
//Start the port scan loop
printf("Starting the portscan loop : \n");
for( i = start ; i <= end ; i++) {
//Fill in the port number
sa.sin_port = htons(i);
//Create a socket of type internet
sock = socket(AF_INET , SOCK_STREAM , 0);
//Check whether socket was created or not
if(sock < 0) {
perror("\nSocket");
exit(1);
}
//Connect using that socket and sockaddr structure
err = connect(sock , (struct sockaddr*)&sa , sizeof sa);
//not connected
if(err < 0) {
//printf("%s %-5d %s\r" , hostname , i, strerror(errno));
fflush(stdout);
}
//connected
else {
printf("%-5d open\n", i);
}
close(sock);
}
printf("\r");
fflush(stdout);
}
TL; DR:我不确定如何修改此代码以去除IP地址的最后一个八位字节,并通过用1 - 254替换最后一个八位字节来遍历子网。任何反馈,想法或者非常感谢帮助!在C世界中仍处于初级阶段。
答案 0 :(得分:4)
子网不仅仅是#34;最后一个字节&#34;。而在CIDR中有一个前缀长度/子网掩码。您只需要子网中的一个地址,子网掩码作为无符号整数,但是主机字节顺序,(您需要使用)关于ntohl
和inet_addr
的返回值的htonl
,可以将整数转换为可以存储到s_addr
中的地址。)
您&
使用子网掩码的主机地址获取网络地址。
您使用掩码的 inverse |
网络地址获取广播地址。
网络中的主机地址 是这两者之间的所有数字,因此您可以编写一个以network_address + 1
开头并以{{结尾的for循环1}}。
因此,如果您的主机地址是10.24.41.169且前缀长度为broadcast_address - 1
,则十六进制的地址为 0x0A1829A9 。网络掩码有23个第一位设置为1并且休息为0,即23
,即十六进制为0b11111111111111111111111000000000
。
0xFFFFFE00
现在网络地址为uint32_t host = 0x0A1829A9;
uint32_t netmask = 0xFFFFFE00;
:
host & netmask
广播地址为uint32_t network_address = host & netmask;
或network_address | ~netmask;
:
host_address | ~netmask
子网内的地址可以由一个相当无脑的uint32_t network_address = host_address | ~netmask;
循环
for
从Davis Herring,要将前缀长度转换为子网掩码,您可以使用
for (uint32_t address = network_address + 1; address < broadcast_address; address ++) {
}
答案 1 :(得分:1)
我可以通过几种方式看到这一点,这很好,因为您可以根据初始输入获得IP。但是我觉得这个主题可能会指向正确的方向: How to increment an IP address in a loop? [C]
让我知道。