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
979 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
  • 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
 
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
VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

863 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

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now