⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_scan.c

📁 在网络中,有时候会想检查自己电脑的端口的状态,这是端口扫描器的C语言源代码,
💻 C
字号:
 /*  * tcp_scan - determine available tcp services, optionally collect banners  * and detect telnet options  *   * Author: Wietse Venema.  */#include <sys/types.h>#include <sys/param.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <netinet/tcp.h>#include <arpa/telnet.h>#include <stdio.h>#include <signal.h>#include <netdb.h>#include <string.h>#include <errno.h>extern int errno;extern char *optarg;extern int optind;#ifndef __STDC__extern char *strerror();#endif#define offsetof(t,m)	(size_t)(&(((t *)0)->m))#ifndef IPPORT_TELNET#define IPPORT_TELNET	23#endif#ifndef FD_SET#include <sys/select.h>#endif#ifndef INADDR_ANY#define INADDR_ANY 0xffffffff#endif#include "lib.h"#define BANNER_LENGTH	2048		/* upper bound on banner info */#define BANNER_TIME	10		/* time for host to send banner */#define BANNER_IDLE	1		/* delay after last banner info */#define YES     1#define NO      0#define WAIT	1#define NOWAIT	0int     verbose;			/* default silent mode */int     banner_time = BANNER_TIME;	/* banner timeout */int     open_file_limit;		/* max nr of open files */int     load_limit;			/* max nr of open sockets */struct timeval now;			/* banner_info last update time */fd_set  write_socket_mask;		/* sockets with connect() in progress */fd_set  read_socket_mask;		/* sockets with connect() finished */int     ports_busy;			/* number of open sockets */int     ports_done;			/* number of finished sockets */int     max_sock;			/* max socket file descriptor */int     want_err;			/* want good/bad news */int     show_all;			/* report all ports */char   *src_port = 0;			/* port to send from */int    *socket_to_port;			/* socket to port number */typedef struct {    unsigned char *buf;			/* banner information or null */    int     count;			/* amount of banner received sofar */    int     flags;			/* see below */    struct timeval connect_time;	/* when connect() finished */    struct timeval read_time;		/* time of last banner update */} BANNER_INFO;BANNER_INFO *banner_info = 0;#define F_TELNET	(1<<0)		/* telnet options seen */int     icmp_sock;			/* for unreachable reports */static struct sockaddr_in dst;		/* remote endpoint info */static struct sockaddr_in src;		/* local endpoint info */static char *send_string;		/* string to send */int     response_time;			/* need some response */#define NEW(type, count) (type *) mymalloc((count) * sizeof(type))#define time_since(t) (now.tv_sec - t.tv_sec + 1e-6 * (now.tv_usec - t.tv_usec))/* main - command-line interface */main(argc, argv)int     argc;char   *argv[];{    int     c;    struct protoent *pe;    char  **ports;    progname = argv[0];    if (geteuid())	error("This program needs root privileges");    open_file_limit = open_limit();    load_limit = open_file_limit - 10;    while ((c = getopt(argc, argv, "abl:s:t:S:uUvw:")) != EOF) {	switch (c) {	case 'a':	    show_all = 1;	    break;	case 'b':	    if (banner_info == 0)		banner_info = NEW(BANNER_INFO, open_file_limit);	    break;	case 'l':	    if ((load_limit = atoi(optarg)) <= 0)		usage("invalid load limit");	    if (load_limit > open_file_limit - 10)		load_limit = open_file_limit - 10;	    break;	case 's':	    send_string = optarg;	    signal(SIGPIPE, SIG_IGN);	    break;	case 'S':	    src_port = optarg;	    break;	case 't':	    if ((response_time = atoi(optarg)) <= 0)		usage("invalid timeout");	    break;	case 'u':	    want_err = EHOSTUNREACH;	    break;	case 'U':	    want_err = ~EHOSTUNREACH;	    break;	case 'v':	    verbose = 1;	    break;	case 'w':	    if ((banner_time = atoi(optarg)) <= 0)		usage("invalid timeout");	    break;	default:	    usage((char *) 0);	    break;	}    }    argc -= (optind - 1);    argv += (optind - 1);    if (argc < 3)	usage("missing host or service argument");    socket_to_port = NEW(int, open_file_limit);    FD_ZERO(&write_socket_mask);    FD_ZERO(&read_socket_mask);    ports_busy = 0;    /*     * Allocate the socket to read ICMP replies.     */    if ((pe = getprotobyname("icmp")) == 0)	error("icmp: unknown protocol");    if ((icmp_sock = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)	error("icmp socket: %m");    FD_SET(icmp_sock, &read_socket_mask);    /*     * Scan the ports.     */    memset((char *) &dst, 0, sizeof(dst));    dst.sin_addr = find_addr(argv[1]);    dst.sin_family = AF_INET;    if (src_port) {	memset((char *) &src, 0, sizeof(src));	src.sin_addr.s_addr = INADDR_ANY;	src.sin_port = find_port(src_port, "tcp");	src.sin_family = AF_INET;    }    if (response_time > 0)	alarm(response_time);    for (ports = argv + 2; *ports; ports++)	scan_ports(*ports);    while (ports_busy > 0)	monitor_ports(WAIT);    return (0);}/* usage - explain command syntax */usage(why)char   *why;{    if (why)	remark(why);    error("usage: %s [-abuU] [-l load] [-s string] [-S src_port] [-w time] host ports...",	  progname);}/* scan_ports - scan ranges of ports */scan_ports(service)char   *service;{    char   *cp;    int     min_port;    int     max_port;    int     port;    int     sock;    /*     * Translate service argument to range of port numbers.     */    if ((cp = strchr(service, '-')) != 0) {	*cp++ = 0;	min_port = (service[0] ? ntohs(find_port(service, "tcp")) : 1);	max_port = (cp[0] ? ntohs(find_port(cp, "tcp")) : 65535);    } else {	min_port = max_port = ntohs(find_port(service, "tcp"));    }    /*     * Iterate over each port in the given range. Try to keep as many sockets     * open at the same time as possible. Gradually increase the number of     * probes so that they will be spread in time.     */    for (port = min_port; port <= max_port; port++) {	if (verbose)	    remark("connecting to port %d", port);	dst.sin_port = htons(port);	while ((sock = socket(dst.sin_family, SOCK_STREAM, 0)) < 0) {	    remark("socket: %m");	    monitor_ports(WAIT);	}	if (src_port && bind(sock, (struct sockaddr *) & src, sizeof(src)) < 0)	    error("bind port %s: %m", src_port);	add_socket(sock, port);	non_blocking(sock, YES);	if (connect(sock, (struct sockaddr *) & dst, sizeof(dst)) < 0	    && errno != EINPROGRESS) {	    if (errno == EADDRINUSE)		error("connect: %m");	    report_and_drop_socket(sock, errno);	    continue;	}	if (ports_busy < load_limit && ports_busy < ports_done) {	    monitor_ports(NOWAIT);	} else {	    while (ports_busy >= load_limit || ports_busy >= ports_done)		monitor_ports(WAIT);	}    }}/* monitor_ports - watch for socket activity */monitor_ports(wait)int     wait;{    fd_set  read_mask;    fd_set  write_mask;    static struct timeval waitsome = {1, 1,};    static struct timeval waitnot = {0, 0,};    int     sock;    char    ch;    if (banner_info == 0) {	/*	 * When a connect() completes, report the socket and get rid of it.	 */	write_mask = write_socket_mask;	read_mask = read_socket_mask;	if (select(max_sock + 1, &read_mask, &write_mask, (fd_set *) 0,		   wait ? (struct timeval *) 0 : &waitnot) < 0)	    error("select: %m");	if (FD_ISSET(icmp_sock, &read_mask))	    receive_icmp(icmp_sock);	for (sock = 0; ports_busy > 0 && sock <= max_sock; sock++) {	    if (FD_ISSET(sock, &write_mask)) {		if (read(sock, &ch, 1) < 0 && errno != EWOULDBLOCK && errno != EAGAIN) {		    if (errno == EADDRINUSE)			error("connect: %m");		    report_and_drop_socket(sock, errno);		} else {		    report_and_drop_socket(sock, 0);		}	    }	}    } else {	/*	 * When a connect() completes, try to receive some data within	 * banner_time seconds. Assume we have received all banner data when	 * a socket stops sending for BANNER_IDLE seconds.	 */	write_mask = write_socket_mask;	read_mask = read_socket_mask;	if (select(max_sock + 1, &read_mask, &write_mask, (fd_set *) 0,		   wait ? &waitsome : &waitnot) < 0)	    error("select: %m");	if (FD_ISSET(icmp_sock, &read_mask))	    receive_icmp(icmp_sock);	gettimeofday(&now, (struct timezone *) 0);	for (sock = 0; ports_busy > 0 && sock <= max_sock; sock++) {	    if (sock == icmp_sock)		continue;	    if (FD_ISSET(sock, &write_mask)) {		FD_CLR(sock, &write_socket_mask);		FD_SET(sock, &read_socket_mask);		banner_info[sock].connect_time = now;		if (send_string)		    do_send_string(sock);	    } else if (FD_ISSET(sock, &read_mask)) {		switch (read_socket(sock)) {		case -1:		    if (errno != EWOULDBLOCK && errno != EAGAIN)			report_and_drop_socket(sock, errno);		    break;		case 0:		    report_and_drop_socket(sock, 0);		    break;		}	    } else if (FD_ISSET(sock, &read_socket_mask)) {		if (time_since_connect(sock) > banner_time		    || time_since_read(sock) > BANNER_IDLE)		    report_and_drop_socket(sock, 0);	    }	}    }}/* read_socket - read data from server */read_socket(sock)int     sock;{    BANNER_INFO *bp = banner_info + sock;    unsigned char *cp;    int     len;    int     count;    if (bp->buf == 0)	bp->buf = (unsigned char *) mymalloc(BANNER_LENGTH);    cp = bp->buf + bp->count;    len = BANNER_LENGTH - bp->count;    if (len == 0)	return (0);    bp->read_time = now;    /*     * Process banners with one-character reads so that we can detect telnet     * options.     */    if ((count = read(sock, cp, 1)) == 1) {	if (cp[0] == IAC) {	    if ((count = read(sock, cp + 1, 2)) == 2) {		if (cp[1] == WILL || cp[1] == WONT) {		    cp[1] = DONT;		    bp->flags |= F_TELNET;		    write(sock, cp, 3);		} else if (cp[1] == DO || cp[1] == DONT) {		    cp[1] = WONT;		    bp->flags |= F_TELNET;		    write(sock, cp, 3);		}	    }	} else {				/* cp[0] != IAC */	    bp->count++;	}    }    return (count);}/* report_and_drop_socket - report what we know about this service */report_and_drop_socket(sock, err)int     sock;int     err;{    alarm(0);    if (show_all || want_err == err || (want_err < 0 && want_err != ~err)) {	struct servent *sp;	int     port = socket_to_port[sock];	printf("%d:%s:", port, (sp = getservbyport(htons(port), "tcp")) != 0 ?	       sp->s_name : "UNKNOWN");	if (banner_info) {	    BANNER_INFO *bp = banner_info + sock;	    if (bp->flags & F_TELNET)		putchar('t');	    putchar(':');	    if (bp->count > 0)		print_data(stdout, bp->buf, bp->count);	}	if (err && show_all)	    printf("%s", strerror(err));	printf("\n");	fflush(stdout);    }    drop_socket(sock);}/* add_socket - say this socket is being connected */add_socket(sock, port)int     sock;int     port;{    BANNER_INFO *bp;    socket_to_port[sock] = port;    if (banner_info) {	bp = banner_info + sock;	bp->count = 0;	bp->buf = 0;	bp->flags = 0;    }    FD_SET(sock, &write_socket_mask);    if (sock > max_sock)	max_sock = sock;    ports_busy++;}/* drop_socket - release socket resources */drop_socket(sock)int     sock;{    BANNER_INFO *bp;    if (banner_info && (bp = banner_info + sock)->buf)	free((char *) bp->buf);    close(sock);    FD_CLR(sock, &read_socket_mask);    FD_CLR(sock, &write_socket_mask);    ports_busy--;    ports_done++;}/* time_since_read - how long since read() completed? */time_since_read(sock)int     sock;{    BANNER_INFO *bp = banner_info + sock;    return (bp->count == 0 ? 0 : time_since(bp->read_time));}/* time_since_connect - how long since connect() completed? */time_since_connect(sock)int     sock;{    BANNER_INFO *bp = banner_info + sock;    return (time_since(bp->connect_time));}/* receive_icmp - receive and decode ICMP message */receive_icmp(sock)int     sock;{    union {	char    chars[BUFSIZ];	struct ip ip;    }       buf;    int     data_len;    int     hdr_len;    struct ip *ip;    struct icmp *icmp;    struct tcphdr *tcp;    int     port;    if ((data_len = recv(sock, (char *) &buf, sizeof(buf), 0)) < 0) {	error("error: recv: %m");	return;    }    /*     * Extract the IP header.     */    ip = &buf.ip;    if (ip->ip_p != IPPROTO_ICMP) {	error("error: not ICMP proto (%d)", ip->ip_p);	return;    }    /*     * Extract the IP payload.     */    hdr_len = ip->ip_hl << 2;    if (data_len - hdr_len < ICMP_MINLEN) {	remark("short ICMP packet (%d bytes)", data_len);	return;    }    icmp = (struct icmp *) ((char *) ip + hdr_len);    data_len -= hdr_len;    if (icmp->icmp_type != ICMP_UNREACH)	return;    /*     * Extract the offending IP packet header.     */    if (data_len < offsetof(struct icmp, icmp_ip) + sizeof(icmp->icmp_ip)) {	remark("short IP header in ICMP");	return;    }    ip = &(icmp->icmp_ip);    if (ip->ip_p != IPPROTO_TCP)	return;    if (ip->ip_dst.s_addr != dst.sin_addr.s_addr)	return;    /*     * Extract the offending TCP packet header.     */    hdr_len = ip->ip_hl << 2;    tcp = (struct tcphdr *) ((char *) ip + hdr_len);    data_len -= hdr_len;    if (data_len < offsetof(struct tcphdr, th_dport) + sizeof(tcp->th_dport)) {	remark("short TCP header in ICMP");	return;    }    /*     * Process ICMP subcodes.     */    switch (icmp->icmp_code) {    case ICMP_UNREACH_NET:    case ICMP_UNREACH_PROTOCOL:	/* error("error: network or protocol unreachable"); */	/* NOTREACHED */    case ICMP_UNREACH_PORT:    case ICMP_UNREACH_HOST:	port = ntohs(tcp->th_dport);	for (sock = 0; sock < open_file_limit; sock++)	    if (socket_to_port[sock] == port) {		report_and_drop_socket(sock, EHOSTUNREACH);		return;	    }	break;    }}/* do_send_string - send the send string */do_send_string(sock)int     sock;{    char    buf[BUFSIZ];    char   *cp = buf;    char    ch;    int     c;    int     i;    char   *s = send_string;    while (*s && cp < buf + sizeof(buf) - 1) {	/* don't overflow the buffer */	if (*s != '\\') {			/* ordinary character */	    *cp++ = *s++;	} else if (isdigit(*++s) && *s < '8') {	/* \nnn octal code */	    sscanf(s, "%3o", &c);	    *cp++ = c;	    for (i = 0; i < 3 && isdigit(*s) && *s < '8'; i++)		s++;	} else if ((ch = *s++) == 0) {		/* at string terminator */	    break;	} else if (ch == 'b') {			/* \b becomes backspace */	    *cp++ = '\b';	} else if (ch == 'f') {			/* \f becomes formfeed */	    *cp++ = '\f';	} else if (ch == 'n') {			/* \n becomes newline */	    *cp++ = '\n';	} else if (ch == 'r') {			/* \r becomes carriage ret */	    *cp++ = '\r';	} else if (ch == 's') {			/* \s becomes blank */	    *cp++ = ' ';	} else if (ch == 't') {			/* \t becomes tab */	    *cp++ = '\t';	} else {				/* \any becomes any */	    *cp++ = ch;	}    }    write(sock, buf, cp - buf);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -