Link to home
Start Free TrialLog in
Avatar of F-J-K
F-J-KFlag for Canada

asked on

How can i connect to a specific port in remote host by using connect()? C++ - Linux Socket Programming

I'm trying to write a code that connects to scan range of ports of one of my hosts remotely ....
I submitted a rough code just to illustrate the point. Please look at the places where i commented with asteriks //*******.

I'm using connect(). connect function will not connect if a port is not specified.

getaddrinfo(remoteIP, NULL, &hints, &results); this piece of code, will take remoteIP user entered and put it into ai_addr. Second parameter represents local port number, i put NULL, because i'm after the remoteIP ports not my local ports. Can you help me how to connect to a specific port for a remote host?

Note: i'm using getaddrinfo() which supposes to do everything automatically, instead of filling things manually.

I hope my question is clear enough.
#include<iostream>
#include<string>
#include<sstream>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<errno.h>
using namespace std;
 
int main()
{
	struct addrinfo hints;      	//fill your host info - hints is input
	struct addrinfo *results;	//gets your host info - results is output
	//remoteIP variable that holds th given IP
	int startingPort;               //stores the starting range of port number
	int endingPort;                 //stores the ending rage of port number
	int status;                     //receives the status of your pc address
	
	system("clear");
	
	//set size of hints to zero
	memset(&hints, 0, sizeof hints);
 
	//fill some of your host address info
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
 
	//ask user to enter remoteIP...
	
	//remoteIP variable carries the entered IP
 
	//ask port range from user
	cout<<"Enter Starting Port: ";
	cin>>startingPort;
 
	cout<<"Enter Ending Port: ";
	cin>>endingPort;
 
	cout<<endl;
 
	cout<<"Start Scanning Ports on: "<<remoteIP<<endl;
 
	//check the status
	while(startingPort <= endingPort)
	{
		//************I put NULL in the middle because there is no 
		//***********need to specify any port on our local machine
		//***********connect() will get specify any random local IP
		//***********for us**********************************
		status = getaddrinfo(remoteIP, NULL, &hints, &results);
 
		if(status != 0)
		{
			fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
			exit(1);
		}
 
		//create a socket.
		int socketfd;
		socketfd = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
 
		if(socketfd == -1 )
		{
			cout<<"Error: failed to create a socket.\n";
			return 2;
		}
 
 
		//***********************connect to remoteIP*************************************//
		//*********ai_addr holds the ip address & should hold the port too. However,//
		//*********how can i insert the starting port into ai_addr?********//
		int connectStatus;
		connectStatus = connect(socketfd, results->ai_addr, results->ai_addrlen);
	
		if(connectStatus == -1 )
		{		
			cout << "connect failed; reason = " << strerror(errno) <<endl; 
	
		}else{
			cout<<"Port "<<currentPort<<" is OPEN.\n";
		}
 
		close(socketfd);
	
		//move to the next port in the specified range
		startingPort++;
 
	}
 
	return 0;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Werrock
Werrock
Flag of Sweden image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of F-J-K

ASKER

Note: ai_addr is of type struct sockaddr .....
sin_port is in struct socksaddr_in

I should do this:

struct sockaddr *specifyPort = (struct sockaddr_in*)results->ai_addr;

specifyPort->sin_port = htons(currentPort);

BUT here we fill specifyPort, not "results" & we are going to connect using "results" like this

connectStatus = connect(socketfd, results->ai_addr, results->ai_addrlen);

Questions:

1. As far as i know, any changes i make in specifyPort will effect results because specifyPort points to the same place where results point, am i right?

2. I did the steps i just mentioned above, however i get compiler error:

RemotePortScanner.cpp: In function int main():
RemotePortScanner.cpp:160: error: invalid conversion from char* to uint16_t
RemotePortScanner.cpp:160: error:   initializing argument 1 of uint16_t htons(uint16_t)

Can you guide me please?!


struct addrinfo {
 
int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc.
 
int ai_family; // AF_INET, AF_INET6, AF_UNSPEC  .... main result will be given 		   // sa_family in ai_addr
 
int ai_socktype; // SOCK_STREAM, SOCK_DGRAM
 
int ai_protocol; // use 0 for "any"
 
size_t ai_addrlen; // size of ai_addr in bytes
 
struct sockaddr *ai_addr; // struct sockaddr_in or _in6
 
char *ai_canonname; // full canonical hostname
 
struct addrinfo *ai_next; // linked list, next node
 
};
 
struct sockaddr {
 
unsigned short sa_family;
char sa_data[14]; // 14 bytes of protocol address
 
};
 
struct sockaddr_in {
 
short int sin_family; // Address family, AF_INET
 
unsigned short int sin_port; // Port number
 
struct in_addr sin_addr; // Internet address
 
unsigned char sin_zero[8]; // Same size as struct sockaddr
 
};

Open in new window

Avatar of F-J-K

ASKER

This one seems to work when i put the IP address as 127.0.1.1
It could catch the open ports and the closed ones.

I did not try to put any of my remote address yet, as i can not recall it.
I will try it when i get home.

Can you check my code below please...

Thats where i made the change

//******************************************************************
            struct sockaddr_in *specifyPort = (struct sockaddr_in *)results->ai_addr;

            specifyPort->sin_port = htons(startingPort);
//****************************************************************
#include<iostream>
#include<string>
#include<sstream>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<errno.h>
using namespace std;
 
 
struct addrinfo hints;      	//fill your host info - hints is input
struct addrinfo *results;	//gets your host info - results is output
char *remoteIP = new char[40];  //holds inserted remote IP
string tempPort;                //holds ports temporarly
int startingPort;               //stores the starting range of port number
int status;                     //receives the status of your pc address
int currentPort;           //holds current port
 
//program description
void progDesc()
{
     cout<<"This is a simple port scanner, scan range of\n";
     cout<<"ports on your local machine...\n"<<endl;
 
}
 
 
//getaddrinfe locates your machine, more specific
//details of your host address is returned to results. 
void getAddrIn()
{
	status = getaddrinfo(remoteIP, NULL , &hints, &results);
 
	if(status != 0)
	{
		fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
		exit(1);
	}
}
 
//get host name of the remote IP
void grabHostName()
{
	//carries your target's host name
	char hostName[100];
	struct addrinfo *p;
	
	cout<<"Host name for \""<<remoteIP<<"\" is:";
 
	//print all your local IP Addresses
	for(p = results; p != NULL; p = p->ai_next)
	{
		void *addr;
		string ipVer;
		if(p->ai_family == AF_INET)
		{
			struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
			addr = &(ipv4->sin_addr);
			ipVer = "IPv4";
 
		}else{
			struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
			addr = &(ipv6->sin6_addr);
			ipVer = "IPv6";
		}
 
		//inet_ntop(p->ai_family, addr, ipString, sizeof ipString);
		cout<<""<<ipVer<<": ";
		//printf("%s\n", ipString);
		cout<<endl;
	}	
}
 
 
//Run the program
int main()
{
	int endingPort;                 //stores the ending rage of port number
 
	system("clear");
 
	//tell user what program does
	progDesc();
	
	//set size of hints to zero
	memset(&hints, 0, sizeof hints);
 
	//fill some of your host address info
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
 
	//ask for remote IP
	cout<<"Please enter your target IP: ";
	cin>>remoteIP;
 
	getAddrIn();
 
	//ask port range from user
	cout<<"Enter Starting Port: ";
	cin>>startingPort;
 
	cout<<"Enter Ending Port: ";
	cin>>endingPort;
 
	cout<<endl;
 
	cout<<"Start Checking: "<<endl;
 
 
	//check the status
	while(startingPort <= endingPort)
	{
		//call getaddrinfo()
		getAddrIn();
 
		//create a socket.
		int socketfd;
		socketfd = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
 
		if(socketfd == -1 )
		{
			cout<<"Error: failed to create a socket.\n";
			return 2;
		}
 
//******************************************************************
		struct sockaddr_in *specifyPort = (struct sockaddr_in *)results->ai_addr;
 
		specifyPort->sin_port = htons(startingPort);
//****************************************************************
		int connectStatus;
		connectStatus = connect(socketfd, results->ai_addr, results->ai_addrlen);
	
		if(connectStatus == -1 )
		{		
			if(errno == ECONNREFUSED)
				cout<<"Port "<<startingPort<<" is Closed or Blocked.\n";
			//Alternatively, you can do:
			//cout << "connect failed; reason = " << strerror(errno) <<endl; 	
		}else{
			cout<<"Port "<<startingPort<<" is OPEN.\n";
		}
 
 
		close(socketfd);
	
		//move to the next port in the specified range
		startingPort++;
 
	}
 
	//deallocate memory
	delete[] remoteIP;
 
	//free linkedlist of struct addrinfo *results 
	freeaddrinfo(results);
 
	return 0;
}

Open in new window

In status = getaddrinfo(remoteIP, NULL, &hints, &results);
NULL is the servname value. You can specify a port number here, for example:
char *port = "80";
status = getaddrinfo(remoteIP, port, &hints, &results);
Avatar of F-J-K

ASKER

Now thats confuses me, as what i have been reading in Beej's Guide to Network Programming, the place of NULL, carries a local port number. If i do not want to specify any local port number, i should put NULL.
Connect() will specify one for me automatically.
If i'm a server & want to listen on port e.g. 3460, i would do

status = getaddrinfo(localIP, 3460, &hints, &results);

I may understood it wrong! i will double check...
SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of F-J-K

ASKER

Yes this seems to work, i just upload it to my remote host part of a UNIX server. I compiled the code by g++ under UNIX Solaris, i keep getting these extra unknown errors:

Undefined first referenced
symbol in file
__xnet_connect /var/tmp//ccidZvCu.o
__xnet_socket /var/tmp//ccidZvCu.o
getaddrinfo /var/tmp//ccidZvCu.o
freeaddrinfo /var/tmp//ccidZvCu.o
gai_strerror /var/tmp//ccidZvCu.o
ld: fatal: Symbol referencing errors. No output written to a.out
collect2: ld returned 1 exit status

I think the problem is about linking. Can you tell me how to link in command line, i have not done it before..

g++ myCode.cpp ....... how to link?
i will google it anyway.

I will run it in Unix & scan the ports of the current machine i'm in right now, to see if it works or not.
I passed 127.0.1.1 to remoteIP, it scanned well. I hope its going to work for remote hosts too.



Avatar of F-J-K

ASKER

Worked i had to do

g++ fileName -lsocket -lnsl