Reputation: 331
I am trying to find whether the ports are open or closed in a given host. I am bewildered whether this is a correct approach to do it. Here I only check ports from 0 to 1024. Could someone say whether it is correct since most of my ports are closed and some are only open and also is there any way to print the port name like if port number is 80 the port name is HTTP.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netdb.h>
#include<error.h>
#include<errno.h>
char *convert_int_to_string(int num)
{
int tmp;
int i = 0;
int j = 0;
static char a[5] = {'0'};
while (num > 0) {
tmp = num % 10;
a[i++] = tmp + '0';
num = num / 10;
}
a[i] = '\0';
for (j = 0; j < i / 2; j++) {
tmp = a[j];
a[j] = a[i - j - 1];
a[i - j - 1] = tmp;
}
return a;
}
int main(int argc, char **argv)
{
int status;
char *node;
char *port_no;
int sock_fd;
int i = 0;
struct addrinfo hints, *serviceinfo;
if (argc != 2)
error(1, errno, "Too many or few arguments\n");
node = argv[1];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
for (i = 0; i < 1024; i++) {
port_no = convert_int_to_string(i);
status = getaddrinfo(node, port_no, &hints, &serviceinfo);
if (status != 0) {
error(1, errno, "error in getaddrinfo() function call\n");
}
sock_fd = socket(serviceinfo->ai_family, serviceinfo->ai_socktype, serviceinfo->ai_protocol);
if (sock_fd == -1)
error(1, errno, "error in socket() function call\n");
status = connect(sock_fd, serviceinfo->ai_addr, serviceinfo->ai_addrlen);
if (status != -1)
printf("Port : %s is open\n", port_no);
else
printf("Port : %s is closed\n", port_no);
}
}
Upvotes: 1
Views: 347
Reputation: 47
If you're only trying to check TCP ports and not UDP, I would recommend simply trying to connect() to the server and wait a certain amount of time before you assume that port is closed.
You'll have to use poll() or select() in order to timeout the connect() call. (C: socket connection timeout)
Here's a working example: (works only with IPs, not domain name so you'd have to ping the server in order to find out its IP address or implement the dns query yourself)
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
#define MAX_PORT 1024
#define TIMEOUT 5000
int main(int argc, char *argv[])
{
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = inet_addr(argv[1])
};
struct pollfd fds[1];
for (uint16_t port = 0; port < MAX_PORT; port++) {
int8_t sock = socket(PF_INET, SOCK_STREAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
fds[0].fd = sock;
fds[0].events = POLLOUT;
addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
if (errno == EINPROGRESS) {
if (poll(fds, 1, TIMEOUT) > 0)
printf("Port %d opened.\n", port);
else
printf("Port %d closed.\n", port);
}
else
printf("Port %d closed.\n", port);
}
else
printf("Port %d opened.\n", port);
close(sock);
}
}
Upvotes: 1