File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / hping2 / scan.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:11:37 2012 UTC (12 years, 3 months ago) by misho
Branches: hping2, MAIN
CVS tags: v2_0_0rc3p7, v2_0_0rc3p5, v2_0_0rc3p4, v2_0_0rc3p0, v2_0_0rc3, HEAD
hping2

    1: /* Scanner mode for hping2
    2:  * Copyright(C) 2003 Salvatore Sanfilippo
    3:  * All rights reserved */
    4: 
    5: /* TODO:
    6:  * an application-level aware UDP scanner.
    7:  * add ICMP handling in replies.
    8:  * The algorithm is far from be optimal, also there isn't a clear
    9:  * way to delay smaller amounts of time then usleep(1) without
   10:  * to use a dummy loop.
   11:  * */
   12: 
   13: #include <stdio.h>
   14: #include <stdlib.h>
   15: #include <string.h>
   16: #include <sys/types.h>
   17: #if 0
   18: #include <sys/ipc.h>
   19: #endif
   20: #include <sys/shm.h>
   21: #include <sys/sem.h>
   22: #include <unistd.h>
   23: #include <netdb.h>
   24: #include <sys/time.h>
   25: #include <signal.h>
   26: 
   27: #include <sys/socket.h>
   28: #include <netinet/in.h>
   29: #include <arpa/inet.h>
   30: 
   31: #include <errno.h>
   32: #include <fcntl.h>
   33: 
   34: #if 0
   35: #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
   36: /* union semun is defined by including <sys/sem.h> */
   37: #else
   38: /* according to X/OPEN we have to define it ourselves */
   39: union semun {
   40: 	int val;                    /* value for SETVAL */
   41: 	struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
   42: 	unsigned short int *array;  /* array for GETALL, SETALL */
   43: 	struct seminfo *__buf;      /* buffer for IPC_INFO */
   44: };
   45: #endif
   46: #endif
   47: 
   48: #include "hping2.h"
   49: #include "globals.h"
   50: #include "hstring.h"
   51: 
   52: #define SEM_MODE 0777
   53: #define MAXPORT 65535
   54: 
   55: int opt_scan_probes = 8;
   56: float avrgms = 0;
   57: int avrgcount = 0;
   58: 
   59: /* ---------------------------- data structures ----------------------------- */
   60: 
   61: /* Note that while we don't use any kind of locking, to access
   62:  * this fields is safe. the 'retry' field is only accessed by the
   63:  * sendinf half, while the 'active' field is set by the receiver
   64:  * and tested by the sender so atomicity isn't an issue. */
   65: struct portinfo {
   66: 	int active;
   67: 	int retry;
   68: 	time_t sentms; /* Upss... added this that requires locking, FIXME */
   69: };
   70: 
   71: /* ------------------------- shared memory related -------------------------- */
   72: 
   73: static int id;	/* shared memory id */
   74: 
   75: static int shm_creat(int size)
   76: {
   77: 	id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
   78: 	if (id == -1)
   79: 	{
   80: 		perror("[shm_creat] shmget");
   81: 		return -1; /* on error -1 */
   82: 	}
   83: 	return id; /* on success > 0 */
   84: }
   85: 
   86: static void *shm_attach(void)
   87: {
   88: 	void *shared;
   89: 
   90: 	shared = shmat(id, 0, 0);
   91: 	if (shared == (void*) -1)
   92: 	{
   93: 		perror("[shm_attach] shmat");
   94: 		return NULL; /* on error NULL */
   95: 	}
   96: 	return shared; /* on success the address */
   97: }
   98: 
   99: static int shm_rm(void)
  100: {
  101: 	struct shmid_ds shmemds;
  102: 
  103: 	return shmctl(id, IPC_RMID, &shmemds);
  104: }
  105: 
  106: static int shm_detach(void *addr)
  107: {
  108: 	return shmdt(addr);
  109: }
  110: 
  111: static void *shm_init(int size)
  112: {
  113: 	if (shm_creat(size) == -1)
  114: 		return NULL;
  115: 	return shm_attach();
  116: }
  117: 
  118: static void shm_close(void *addr)
  119: {
  120: 	shm_detach(addr);
  121: 	shm_rm();
  122: }
  123: 
  124: /* ------------------------------ locking ---------------------------------- */
  125: 
  126: /* Note that a mutex can't be used with shared memory (on Linux), the only left
  127:  * option is a semaphore, but I tried to protect the critical code
  128:  * using the functions above: the scanner becomes too slow. For now
  129:  * it's better to have nothing at all, for the future we need something
  130:  * like a spinlock. (btw, note that the code should be safe on x86) */
  131: 
  132: /* I left this code here, just in the case it will be useful for testing */
  133: #if 0
  134: static int sem_init(void)
  135: {
  136: 	int semid, sem_key;
  137: 
  138: 	if ((sem_key = ftok("/tmp/hpingscansem", 1)) == -1) {
  139: 		perror("ftok");
  140: 		exit(1);
  141: 	}
  142: 
  143: 	/* Semi-safe semaphore initialization from R.Stevens */
  144: 
  145: 	/* Try to create the semaphore with EXCL */
  146: 	if ((semid = semget(sem_key, 1, IPC_CREAT|IPC_EXCL|SEM_MODE)) != -1) {
  147: 		/* success, we need to initialize it */
  148: 		union semun arg;
  149: 
  150: 		arg.val = 1;
  151: 		if (semctl(semid, 0, SETVAL, arg) == -1) {
  152: 			perror("semctl");
  153: 			exit(1);
  154: 		}
  155: 	} else if (errno == EEXIST) {
  156: 		if ((semid = semget(sem_key, 1, SEM_MODE)) == -1) {
  157: 			perror("semget");
  158: 			exit(1);
  159: 		}
  160: 	} else {
  161: 		perror("semget");
  162: 		exit(1);
  163: 	}
  164: 	return semid;
  165: }
  166: 
  167: static int ports_lock(int semid)
  168: {
  169: 	struct sembuf op[1];
  170: 
  171: 	op[0].sem_num = 0;
  172: 	op[0].sem_op = -1;
  173: 	op[0].sem_flg = SEM_UNDO;
  174: 	return semop(semid, op, 1);
  175: }
  176: 
  177: static int ports_unlock(int semid)
  178: {
  179: 	struct sembuf op[1];
  180: 
  181: 	op[0].sem_num = 0;
  182: 	op[0].sem_op = +1;
  183: 	op[0].sem_flg = SEM_UNDO;
  184: 	return semop(semid, op, 1);
  185: }
  186: #endif
  187: 
  188: /* -------------------------------- misc ----------------------------------- */
  189: static char *tcp_strflags(char *s, unsigned int flags)
  190: {
  191: 	char *ftab = "FSRPAYXY", *p = s;
  192: 	int bit = 0;
  193: 
  194: 	memset(s, '.', 8);
  195: 	s[8] = '\0';
  196: 	while(bit < 8) {
  197: 		if (flags & (1 << bit))
  198: 			p[bit] = ftab[bit];
  199: 		bit++;
  200: 	}
  201: 	return s;
  202: }
  203: 
  204: static char *port_to_name(int port)
  205: {
  206: 	struct servent *se;
  207: 
  208: 	se = getservbyport(htons(port), NULL);
  209: 	if (!se)
  210: 		return "";
  211: 	else
  212: 		return se->s_name;
  213: }
  214: 
  215: /* ----------------------------- ports parsing ------------------------------ */
  216: static int parse_ports(struct portinfo *pi, char *ports)
  217: {
  218: 	char *args[32], *p = strdup(ports);
  219: 	int argc, j, i;
  220: 
  221: 	if (!p) {
  222: 		fprintf(stderr, "Out of memory");
  223: 		return 1;
  224: 	}
  225: 	argc = strftok(",", ports, args, 32);
  226: 	for (j = 0; j < argc; j++) {
  227: 		int neg = 0;
  228: 		char *a = args[j];
  229: 
  230: 		/* ports negation */
  231: 		if (a[0] == '!') {
  232: 			neg = 1;
  233: 			a++;
  234: 		}
  235: 		/* range */
  236: 		if (strchr(a, '-')) {
  237: 			char *range[2];
  238: 			int low, high;
  239: 
  240: 			strftok("-", a, range, 2);
  241: 			if (!strisnum(range[0]) || !strisnum(range[1]))
  242: 				goto err; /* syntax error */
  243: 			low = strtol(range[0], NULL, 0);
  244: 			high = strtol(range[1], NULL, 0);
  245: 			if (low > high) {
  246: 				int t;
  247: 				t = high;
  248: 				high = low;
  249: 				low = t;
  250: 			}
  251: 			for (i = low; i <= high; i++)
  252: 				pi[i].active = !neg;
  253: 		/* all the ports */
  254: 		} else if (!strcmp(a, "all")) {
  255: 			for (i = 0; i <= MAXPORT; i++)
  256: 				pi[i].active = !neg;
  257: 		/* /etc/services ports */
  258: 		} else if (!strcmp(a, "known")) {
  259: 			struct servent *se;
  260: 			setservent(0);
  261: 			while((se = getservent()) != NULL) {
  262: 				int port = ntohs(se->s_port);
  263: 				if (port < 0 || port > MAXPORT)
  264: 					continue;
  265: 				pi[port].active = !neg;
  266: 			}
  267: 		/* a single port */
  268: 		} else {
  269: 			int port;
  270: 			if (!strisnum(a))
  271: 				goto err; /* syntax error */
  272: 			port = strtol(a, NULL, 0);
  273: 			if (port < 0 || port > MAXPORT)
  274: 				goto err; /* syntax error */
  275: 			pi[port].active = !neg;
  276: 		}
  277: 	}
  278: 	free(p);
  279: 	return 0;
  280: err:
  281: 	free(p);
  282: 	return 1;
  283: }
  284: 
  285: /* -------------------------------- output ---------------------------------- */
  286: static void sender(struct portinfo *pi)
  287: {
  288: 	int i, retry = 0;
  289: 	time_t start_time;
  290: 
  291: 	start_time = get_midnight_ut_ms();
  292: 
  293: 	while(1) {
  294: 		int active = 0;
  295: 		int recvd = 0;
  296: 		retry ++;
  297: 		for (i = 0; i < MAXPORT; i++) {
  298: 			if (pi[i].active && pi[i].retry) {
  299: 				active++;
  300: 				pi[i].retry--;
  301: 				sequence = -1;
  302: 				dst_port = i;
  303: 				pi[i].sentms = get_midnight_ut_ms();
  304: 				send_tcp();
  305: 				if (opt_waitinusec) {
  306: 					if (usec_delay.it_interval.tv_usec)
  307: 						usleep(usec_delay.it_interval.tv_usec);
  308: 				} else {
  309: 					sleep(sending_wait);
  310: 				}
  311: 			}
  312: 		}
  313: 		avrgms = (float) pi[MAXPORT+1].active;
  314: 		if (retry >= 3) {
  315: 			if (opt_debug)
  316: 				printf("AVRGMS %f\n", avrgms);
  317: 			if (avrgms)
  318: 				usleep((int) (avrgms*1000));
  319: 			else
  320: 				sleep(1);
  321: 		}
  322: 		for (i = 0; i < MAXPORT; i++) {
  323: 			if (!pi[i].active && pi[i].retry)
  324: 				recvd++;
  325: 		}
  326: 		/* More to scan? */
  327: 		if (!active) {
  328: 			if (!recvd)
  329: 				sleep(1);
  330: 			fprintf(stderr, "All replies received. Done.\n");
  331: 			printf("Not responding ports: ");
  332: 			for (i = 0; i < MAXPORT; i++) {
  333: 				if (pi[i].active && !pi[i].retry)
  334: 					printf("(%d %.11s) ", i, port_to_name(i));
  335: 			}
  336: 			printf("\n");
  337: 			exit(0);
  338: 		}
  339: 		/* Are we sending too fast? */
  340: 		if ((!recvd && opt_waitinusec &&
  341: 		    usec_delay.it_interval.tv_usec == 0 &&
  342: 		    (get_midnight_ut_ms() - start_time) > 500) ||
  343: 			(opt_scan_probes-retry) <= 2)
  344: 		{
  345: 			if (opt_debug)
  346: 				printf("SLOWING DONW\n");
  347: 			usec_delay.it_interval.tv_usec *= 10;
  348: 			usec_delay.it_interval.tv_usec ++;
  349: 		}
  350: 	}
  351: }
  352: 
  353: /* -------------------------------- input  ---------------------------------- */
  354: static void receiver(struct portinfo *pi, int childpid)
  355: {
  356: 	struct myiphdr ip;
  357: 	char packet[IP_MAX_SIZE+linkhdr_size];
  358: 
  359: 	while(1)
  360: 	{
  361: 		int len, iplen;
  362: 
  363: 		len = read_packet(packet, IP_MAX_SIZE+linkhdr_size);
  364: 		if (len == -1) {
  365: 			perror("read_packet");
  366: 			continue;
  367: 		}
  368: 		/* minimal sanity checks */
  369: 		if (len < linkhdr_size)
  370: 			continue;
  371: 		iplen = len - linkhdr_size;
  372: 		if (iplen < sizeof(struct myiphdr))
  373: 			continue;
  374: 		/* copy the ip header in an access-safe place */
  375: 		memcpy(&ip, packet+linkhdr_size, sizeof(ip));
  376: 		/* check if the dest IP matches */
  377: 		if (memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)))
  378: 			continue;
  379: 		/* check if the source IP matches */
  380: 		if (ip.protocol != IPPROTO_ICMP &&
  381: 		    memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr)))
  382: 			continue;
  383: 		if (ip.protocol == IPPROTO_TCP) {
  384: 			struct mytcphdr tcp;
  385: 			int iphdrlen = ip.ihl << 2;
  386: 			char flags[16];
  387: 			time_t rttms;
  388: 			int sport;
  389: 
  390: 			/* more sanity checks */
  391: 			if ((iplen - iphdrlen) < sizeof(tcp))
  392: 				continue;
  393: 			/* time to copy the TCP header in a safe place */
  394: 			memcpy(&tcp, packet+linkhdr_size+iphdrlen, sizeof(tcp));
  395: 
  396: 			/* check if the TCP dest port matches */
  397: #if 0
  398: 			printf("SRC: %d DST: %d\n",
  399: 					ntohs(tcp.th_sport),
  400: 					ntohs(tcp.th_dport));
  401: #endif
  402: 			if (ntohs(tcp.th_dport) != initsport)
  403: 				continue;
  404: 			sport = htons(tcp.th_sport);
  405: 			if (pi[sport].active == 0)
  406: 				continue;
  407: 
  408: 
  409: 			/* Note that we don't care about a wrote RTT
  410: 			 * result due to resend on the same port. */
  411: 			rttms = get_midnight_ut_ms() - pi[sport].sentms;
  412: 
  413: 			avrgcount++;
  414: 			avrgms = (avrgms*(avrgcount-1)/avrgcount)+(rttms/avrgcount);
  415: 			/* The avrg RTT is shared using shared memory,
  416: 			 * no locking... */
  417: 			pi[MAXPORT+1].active = (int) avrgms;
  418: 
  419: 			tcp_strflags(flags, tcp.th_flags);
  420: #if 0
  421: 			printf("%5d: %s %3d %5d %5d %10ld (%2d)\n",
  422: 					sport,
  423: 					flags,
  424: 					ip.ttl,
  425: 					ip.id,
  426: 					ntohs(tcp.th_win),
  427: 					(long) rttms,
  428: 					opt_scan_probes-(pi[sport].retry));
  429: #endif
  430: 			if ((tcp.th_flags & TH_SYN) || opt_verbose) {
  431: 			printf("%5d %-11.11s: %s %3d %5d %5d\n",
  432: 					sport,
  433: 					port_to_name(sport),
  434: 					flags,
  435: 					ip.ttl,
  436: 					ip.id,
  437: 					ntohs(tcp.th_win));
  438: 			fflush(stdout);
  439: 			}
  440: 			pi[sport].active = 0;
  441: 		} else if (ip.protocol == IPPROTO_ICMP) {
  442: 			struct myicmphdr icmp;
  443: 			struct myiphdr subip;
  444: 			struct mytcphdr subtcp;
  445: 			int iphdrlen = ip.ihl << 2;
  446: 			unsigned char *p;
  447: 			int port;
  448: 			struct in_addr gwaddr;
  449: 
  450: 			/* more sanity checks, we are only interested
  451: 			 * in ICMP quoting the original packet. */
  452: 			if ((iplen - iphdrlen) < sizeof(icmp)+sizeof(subip)+sizeof(subtcp))
  453: 				continue;
  454: 			/* time to copy headers in a safe place */
  455: 			p = packet+linkhdr_size+iphdrlen;
  456: 			memcpy(&icmp, p, sizeof(subtcp));
  457: 			p += sizeof(icmp);
  458: 			memcpy(&subip, p, sizeof(ip));
  459: 			p += sizeof(ip);
  460: 			memcpy(&subtcp, p, sizeof(subtcp));
  461: 
  462: 			/* Check if the ICMP quoted packet matches */
  463: 			/* check if the source IP matches */
  464: 			if (memcmp(&subip.saddr, &local.sin_addr, sizeof(subip.saddr)))
  465: 				continue;
  466: 			/* check if the destination IP matches */
  467: 			if (memcmp(&subip.daddr, &remote.sin_addr, sizeof(subip.daddr)))
  468: 				continue;
  469: 			/* check if the quoted TCP packet port matches */
  470: 			if (ntohs(subtcp.th_sport) != initsport)
  471: 				continue;
  472: 			port = htons(subtcp.th_dport);
  473: 			if (pi[port].active == 0)
  474: 				continue;
  475: 			pi[port].active = 0;
  476: 			memcpy(&gwaddr.s_addr, &ip.saddr, 4);
  477: 			printf("%5d:                      %3d %5d       (ICMP %3d %3d from %s)\n",
  478: 					port,
  479: 					ip.ttl,
  480: 					ntohs(ip.id),
  481: 					icmp.type,
  482: 					icmp.code,
  483: 					inet_ntoa(gwaddr));
  484: 		}
  485: 	}
  486: }
  487: 
  488: /* ---------------------------------- main ---------------------------------- */
  489: static void do_exit(int sid)
  490: {
  491: 	exit(0);
  492: }
  493: 
  494: void scanmain(void)
  495: {
  496: 	struct portinfo *pi;
  497: 	int ports = 0, i;
  498: 	int childpid;
  499: 
  500: 	pi = shm_init(sizeof(*pi)*(MAXPORT+2));
  501: 	pi[MAXPORT+1].active = 0; /* hold the average RTT */
  502: 	if (pi == NULL) {
  503: 		fprintf(stderr, "Unable to create the shared memory");
  504: 		shm_close(pi);
  505: 		exit(1);
  506: 	}
  507: 	for (i = 0; i <= MAXPORT; i++) {
  508: 		pi[i].active = 0;
  509: 		pi[i].retry = opt_scan_probes;
  510: 	}
  511: 	if (parse_ports(pi, opt_scanports)) {
  512: 		fprintf(stderr, "Ports syntax error for scan mode\n");
  513: 		shm_close(pi);
  514: 		exit(1);
  515: 	}
  516: 	for (i = 0; i <= MAXPORT; i++) {
  517: 		if (!pi[i].active)
  518: 			pi[i].retry = 0;
  519: 	}
  520: 	for (i = 0; i <= MAXPORT; i++)
  521: 		ports += pi[i].active;
  522: 	fprintf(stderr, "%d ports to scan, use -V to see all the replies\n", ports);
  523: 	fprintf(stderr, "+----+-----------+---------+---+-----+-----+\n");
  524: 	fprintf(stderr, "|port| serv name |  flags  |ttl| id  | win |\n");
  525: 	fprintf(stderr, "+----+-----------+---------+---+-----+-----+\n");
  526: 
  527: 	/* We are ready to fork, the input and output parts
  528: 	 * are separated processes */
  529: 	if ((childpid = fork()) == -1) {
  530: 		perror("fork");
  531: 		shm_close(pi);
  532: 		exit(1);
  533: 	}
  534: 	/* The parent is the receiver, the child the sender.
  535: 	 * it's almost the same but this way is simpler
  536: 	 * to make it working in pipe with other commands like grep. */
  537: 	if (childpid) { /* parent */
  538: 		Signal(SIGCHLD, do_exit);
  539: 		Signal(SIGINT, do_exit);
  540: 		Signal(SIGTERM, do_exit);
  541: 		receiver(pi, childpid);
  542: 	} else {	/* child */
  543: 		Signal(SIGINT, do_exit);
  544: 		Signal(SIGTERM, do_exit);
  545: 		sender(pi);
  546: 	}
  547: 	/* UNREACHED */
  548: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>