This C language code is used to scan the open ports on a specific range of IP addresses. The program takes three command line arguments: the IP address to be scanned, the start port, and the end port in the scan range. The program then iterates through the specified range of ports and calls the "scan_port" function to check if the port is open or closed.
The "scan_port" function creates a TCP socket, sets the IP and port, and then attempts to connect to the port at the specified IP address. If the connection is successful, the port is open and the function returns 1. Otherwise, the port is closed and the function returns 0.
int scan_port(char *ip_address, int port) {
// Create a non-blocking TCP socket
int socket_desc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socket_desc == -1) {
printf("Failed to create socket");
return -1;
}
One way to make the above code scan ports faster is to use concurrency, that is, run multiple port checks at the same time instead of waiting for each check to complete before starting the next. One way to achieve this in C is through the use of threads.
Setting the socket to non-blocking mode allows the program to continue running while it waits for the server's response to connect to the port. This means it won't hang while you wait, which can improve program performance when scanning multiple ports or scanning ports on multiple IP addresses. Additionally, this can also help prevent the program from crashing if the server is down.
// Set the socket to non-blocking mode
int flags = fcntl(socket_desc, F_GETFL, 0);
if (flags == -1) {
printf("Failed to get socket flags");
close(socket_desc);
return -1;
}
if (fcntl(socket_desc, F_SETFL, flags | O_NONBLOCK) == -1) {
printf("Failed to set socket to non-blocking mode");
close(socket_desc);
return -1;
}
The connect() function is used to establish a connection between the local socket and the remote socket (in this case, the server). If this function returns a value less than zero, it indicates that the connection failed.
This code checks if the error that occurred on the connection is EINPROGRESS, which means that the connection is in progress and has not completed yet. This is because a non-blocking socket is being used, which means that the connect() function may return immediately before the connection is complete.
// Start a non-blocking connect operation
if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
if (errno == EINPROGRESS) {
These codes are used to wait for a socket connection to complete in non-blocking mode using the select() function.
First, an empty file descriptor set (fd_set) called write_fds is created and the socket descriptor (socket_desc) is added to the set using the FD_SET() function. Then, a timeout of 100ms is set using the timeval structure, which is used to specify the timeout in the select() function.
// The connection is in progress, wait for it to complete or timeout
fd_set write_fds;
struct timeval timeout;
FD_ZERO(&write_fds);
FD_SET(socket_desc, &write_fds);
timeout.tv_sec = 0;
timeout.tv_usec = 100000; // 100ms timeout
int select_result = select(socket_desc + 1, NULL, &write_fds, NULL, &timeout);
if (select_result == -1) {
printf("Failed to select socket for non-blocking connect");
close(socket_desc);
return -1;
} else if (select_result == 0) {