Solved

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

Posted on 2008-10-24
8
992 Views
Last Modified: 2012-08-13
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

0
Comment
Question by:F-J-K
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 2
8 Comments
 
LVL 6

Accepted Solution

by:
Werrock earned 250 total points
ID: 22797687
Set the port in results->ai_addr before calling connect.

results->ai_addr.sin_port = htons(PORTNUMBER);
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22800018
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

0
 
LVL 1

Author Comment

by:F-J-K
ID: 22800144
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

0
Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

 
LVL 6

Expert Comment

by:Werrock
ID: 22800165
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);
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22800288
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...
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 250 total points
ID: 22802109
>> 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?

Yes.


>> RemotePortScanner.cpp:160: error: invalid conversion from char* to uint16_t

htons takes a uint16_t, not a char*. You have to pass it a uint16_t.
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22802259
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.



0
 
LVL 1

Author Comment

by:F-J-K
ID: 22802666
Worked i had to do

g++ fileName -lsocket -lnsl
0

Featured Post

Schedule a Tour of the ATEN booth at InfoComm 2017

Tour the ATEN booth to see the the Latest Addition to the Modular Matrix Switch Series, New 4K HDMI Over IP Extender and more! Enter ATEN's Ultimate Giveaway Sweepstakes for a chance to win one of several great prizes, including an ATEN US7220 2-Port Thunderbolt 2 Sharing Switch!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
I have seen several blogs and forum entries elsewhere state that because NTFS volumes do not support linux ownership or permissions, they cannot be used for anonymous ftp upload through the vsftpd program.   IT can be done and here's how to get i…
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question