特定のIPで開いているすべてのポートをスキャンし、開いているポートとその上で実行されているサービスの名前のみを返すTCPポートスキャナーがあります。これを行うには、ソケットを作成し、非ブロッキング モードに設定しますselect()
。ポートがタイムアウトした場合は、ポートが閉じていることを意味し、それ以外の場合は開いています。問題は、開いているポートをスキャンしようとしても、select() が常にタイムアウトすることです。誰かに私の間違いを指摘してもらいたいのですが、私の論理は間違っていますか?
#include <stdlib.h>
#include <iostream>
#include <cstdio>
#include <string.h>
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/time.h>
#include <errno.h>
using namespace std;
fd_set working_set;
hostent *he;
char* protoc [2] = { "tcp","udpn" };
int port;
struct sockaddr_in servaddr;
int sendfd;
servent *srvport;
void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
void set_block(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | ~O_NONBLOCK);
}
int main( int argc, char* argv[] )
{
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
char* host = argv[1];
char* pro = argv[2];
int portlow = atoi(argv[3]);
int porthigh = atoi(argv[4]);
fprintf(stderr, "n Scanning host=%s, protocol=%s, ports: %d -> %d \n",
host, pro, portlow, porthigh);
if(strcmp(pro, protoc[0])==0)
pro = protoc[0];
else if (strcmp(pro, protoc[1])==0)
pro = protoc[1];
else
{
herror("n specify valid protocol - tcp or udpn");
exit(-1);
}
if((he = gethostbyname(argv[1])) == NULL)
{
herror("n *** gethostbyname() failed ***n");
exit(-1);
}
/*In case TCP protocol is selected for scan, app opens streaming socket
for every port to be scanned, tries to connect to it, and if successful
it displays information about service using struct servent.
*/
if(strcmp(pro, protoc[0])==0) // tcp scan
{
for(port = portlow; port <= porthigh; port++)
{
// open stream socket
if((sendfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("*** socket(,SOCK_STREAM,) failed ***n");
exit(-1);
}
set_nonblock(sendfd);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
servaddr.sin_addr = *((struct in_addr *)he->h_addr);
int res = connect(sendfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
int ser;
if (res < 0) {
if (errno == EINPROGRESS) {
timeout.tv_sec = 0;
timeout.tv_usec = 10;
FD_SET(sendfd, &working_set);
if ((ser=select(sendfd+1, NULL, &working_set, NULL, &timeout)) > 0) {
srvport = getservbyport(htons(port), protoc[0]);
}
else {
fprintf(stderr, "Timeout or error() %d\n",ser);
perror("select(): ");
}
}
else {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
}
if(srvport != NULL)
printf("tport %d: %sn \n ", port, srvport->s_name);
else if (ser=0)
close(sendfd);
fflush(stdout);
}
//set_block(sendfd);
}//end of for()
}
}