正确修改现有代码以循环子网的方法

时间:2018-01-07 06:53:02

标签: c subnet port-scanning

我正在编写一个端口扫描程序,目的是遍历整个子网,看看端口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世界中仍处于初级阶段。

2 个答案:

答案 0 :(得分:4)

子网不仅仅是#34;最后一个字节&#34;。而在CIDR中有一个前缀长度/子网掩码。您只需要子网中的一个地址,子网掩码作为无符号整数,但是主机字节顺序,(您需要使用)关于ntohlinet_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]

让我知道。