waitpacket.c

来自「网络流量生成工具,开源软件,也可以作为网络流量检测软件使用」· C语言 代码 · 共 622 行

C
622
字号
/*  * $smu-mark$  * $name: waitpacket.c$  * $author: Salvatore Sanfilippo <antirez@invece.org>$  * $copyright: Copyright (C) 1999 by Salvatore Sanfilippo$  * $license: This software is under GPL version 2 of license$  * $date: Fri Nov  5 11:55:50 MET 1999$  * $rev: 8$  */ #include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <time.h>#include <ctype.h>#include <unistd.h>#include "hping2.h"#include "globals.h"static int icmp_unreach_rtt(void *quoted_ip, int size,			    int *seqp, float *ms_delay);static void print_tcp_timestamp(void *tcp, int tcpsize);/*	FIXME:	wait_packet don't support ip and tcp options,	it waits for 20 bytes IP hdr + 20 bytes TCP hdr.	--> ip options fixed 31/08/99 (MK)*/void	wait_packet(void){	char	packet	[LINK_PACKETSIZE],		recvflags[1024],		src_addr[1024],		dst_addr[1024],		*p;	int	recv_sport,		recv_dport,		size,		rstseq,		sequence,		winsize,		status,		match = FALSE,		ip_id,		rel_id;	float	ms_delay;	struct	in_addr	src, dst;	struct  myiphdr ip;	struct  mytcphdr tcp;	struct  myudphdr udp;	struct  myicmphdr icmp;	struct  myiphdr icmp_iph;	struct  icmp_tstamp_data icmp_tstamp;	char	hlen;#if (!defined OSTYPE_LINUX) || (defined FORCE_LIBPCAP)	size = pcap_recv(packet, LINK_PACKETSIZE);	if (size == -1) {		perror("[wait_packet] pcap_recv()");		return;	}#else	size = recv(sockpacket, packet, LINK_PACKETSIZE, 0);	if (size == -1) {		if (errno != EINTR)		{			perror("[wait_packet] recv");			print_statistics(-1);		}		else			return;	}#endif	if (size < linkhdr_size+IPHDR_SIZE)		return;	memcpy(&ip, packet+ABS_OFFSETIP, sizeof(ip));	hlen	 = ip.ihl << 2;	memcpy(&tcp, packet+ABS_OFFSETIP+hlen, sizeof(tcp));	memcpy(&udp, packet+ABS_OFFSETIP+hlen, sizeof(udp));	memcpy(&icmp, packet+ABS_OFFSETIP+hlen, sizeof(icmp));	memcpy(&icmp_iph, packet+ABS_OFFSETIP+hlen+8, sizeof(icmp_iph));	memcpy(&icmp_tstamp, packet+ABS_OFFSETIP+hlen+8, sizeof(icmp_tstamp));	/* --------- HCMP --------- */	if (opt_sign && (p = memstr(packet, rsign, size)))	{		struct hcmphdr *hcmph;		__u16 seqnum;		__u32 usec;		if (opt_debug)			fprintf(stderr, "HCMP received\n");		p+=strlen(rsign);		if ((size-(packet-p)) < sizeof(struct hcmphdr))		{			if (opt_verbose || opt_debug)				fprintf(stderr, "bad HCMP len received\n");			goto hcmp_exit;		}		hcmph = (struct hcmphdr*) p;		switch(hcmph->type)		{		case HCMP_RESTART:			seqnum = ntohs(hcmph->typedep.seqnum);			break;		case HCMP_SOURCE_QUENCH:		case HCMP_SOURCE_STIRUP:			usec = ntohl(hcmph->typedep.usec);		default:			if (opt_verbose || opt_debug)				fprintf(stderr, "bad HCMP type received\n");			goto hcmp_exit;		}		switch(hcmph->type)		{		case HCMP_RESTART:			src_id = seqnum;		/* set id */			datafiller(NULL, seqnum);	/* data seek */			goto hcmp_exit;		case HCMP_SOURCE_QUENCH:		case HCMP_SOURCE_STIRUP:			printf("Source quench / stirpu"				" still not implemented!\n");			goto hcmp_exit;		/* default handled in the first switch */		}	}hcmp_exit:	/* get source and target address */	memcpy(&src, &(ip.saddr), sizeof(struct in_addr));	memcpy(&dst, &(ip.daddr), sizeof(struct in_addr));	strncpy(src_addr, inet_ntoa(src), 1024);	strncpy(dst_addr, inet_ntoa(dst), 1024);	/* get ip->id */	if (opt_winid_order)		ip_id = ip.id;	else		ip_id = htons(ip.id);	/* get source and target port */	if (opt_udpmode)	/* UDP */	{		recv_sport = ntohs(udp.uh_sport);		recv_dport = ntohs(udp.uh_dport);	}	else			/* TCP */	{		recv_sport = ntohs(tcp.th_sport);		recv_dport = ntohs(tcp.th_dport);	}	/* --------- TCP --------- */	if ( ip.protocol == IPPROTO_TCP &&	     !memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr)) &&	     !memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)) &&	     (recv_sport == dst_port || opt_force_incdport)	)	{		match = TRUE;		winsize   = ntohs(tcp.th_win);		tcp_exitcode = tcp.th_flags;		recvflags[0] = '\0';		if (tcp.th_flags & TH_RST)  strcat(recvflags, "R");		if (tcp.th_flags & TH_SYN)  strcat(recvflags, "S");		if (tcp.th_flags & TH_ACK)  strcat(recvflags, "A");		if (tcp.th_flags & TH_FIN)  strcat(recvflags, "F");		if (tcp.th_flags & TH_PUSH) strcat(recvflags, "P");		if (tcp.th_flags & TH_URG)  strcat(recvflags, "U");		if (tcp.th_flags & TH_X)    strcat(recvflags, "X");		if (tcp.th_flags & TH_Y)    strcat(recvflags, "Y");		if (recvflags[0] == '\0')    strcat(recvflags, "none");		/* obtain round trip time */		sequence = 0;		status = rtt(&sequence, recv_dport, &ms_delay);		/* relativize packets ip->id */		if (opt_relid)			rel_id = relativize_id(sequence, &ip_id);		else			rel_id = FALSE;		if (opt_seqnum)		{			static __u32 old_th_seq = 0;			__u32 seq_diff, tmp;			tmp = ntohl(tcp.th_seq);			if (tmp >= old_th_seq)				seq_diff = tmp - old_th_seq;			else				seq_diff = (4294967295U - old_th_seq)					+ tmp;			old_th_seq = tmp;			printf("%10lu +%lu\n",				(unsigned long) tmp,				(unsigned long) seq_diff);		}		if (!opt_quiet && !opt_seqnum) {			if (status == S_RECV)				printf("DUP! ");			if (!opt_incdport)				printf("len=%d ip=%s ",					size - linkhdr_size, src_addr);			else				printf("len=%d ip=%s sport=%d ",					size - linkhdr_size, src_addr,					recv_sport);			printf("flags=%s ", recvflags);			if (ntohs(ip.frag_off) & DF)				printf("DF ");			printf("seq=%d ", sequence);			printf("ttl=%d ", ip.ttl);			printf("id");			if (rel_id == TRUE)				printf("=+");			else				putchar('=');			printf("%d ", ip_id);			printf("win=%d ", winsize);			printf("rtt=%.1f ms", ms_delay);			putchar('\n');		}		if (opt_verbose && !opt_quiet) {			printf("tos=%x ", ip.tos);			printf("iplen=%u ", htons(ip.tot_len));			printf("seq=%lu ", (unsigned long) ntohl(tcp.th_seq));			printf("ack=%lu ", (unsigned long) ntohl(tcp.th_ack));			printf("sum=%x ", tcp.th_sum);			printf("urp=%u ", tcp.th_urp);			putchar('\n');			putchar('\n');		}		if (opt_tcp_timestamp)			print_tcp_timestamp(packet+ABS_OFFSETIP+hlen, size - linkhdr_size - hlen);		fflush(stdout);		recv_pkt++;		if (opt_incdport && !opt_force_incdport)			dst_port++;	}	/* --------- ICMP --------- */	if ( ip.protocol == IPPROTO_ICMP )	{		match = TRUE;		/* Echo reply */		if ((icmp.type == 0  || icmp.type == ICMP_TIMESTAMPREPLY		     || icmp.type == ICMP_ADDRESSREPLY)		    && icmp.un.echo.id == (getpid() & 0xffff))		{			recv_pkt++;			if (!opt_quiet)			{				rstseq = icmp.un.echo.sequence;				/* obtain round trip time */				status = rtt(&rstseq, 0, &ms_delay);				/* relativize packets ip->id */				if (opt_relid)					rel_id = relativize_id(rstseq, &ip_id);				else					rel_id = FALSE;				printf("%d bytes from %s: ",				size - linkhdr_size, src_addr);				printf("icmp_seq=%d ", rstseq);				printf("ttl=%d ", ip.ttl);				printf("id");				if (rel_id == TRUE)					printf("=+");				else					putchar('=');				printf("%d ", ip_id);				printf("rtt=%.1f ms", ms_delay);				putchar('\n');				if (icmp.type == ICMP_TIMESTAMPREPLY) {					printf("ICMP timestamp: "					       "Originate=%u "					       "Receive=%u "					       "Transmit=%u\n",						(unsigned int)						  ntohl(icmp_tstamp.orig),						(unsigned int)						  ntohl(icmp_tstamp.recv),						(unsigned int)						  ntohl(icmp_tstamp.tran));					printf("ICMP timestamp RTT tsrtt=%lu\n",						(get_midnight_ut_ms() -						ntohl(icmp_tstamp.orig)));				}				if (icmp.type == ICMP_ADDRESSREPLY) {					unsigned char *addr =						(unsigned char*) packet+							ABS_OFFSETIP+hlen+8;					/* XXX: doesn't check the len */					printf("ICMP address mask: "					       "icmpam=%u.%u.%u.%u\n",					       		addr[0], addr[1],							addr[2], addr[3]);				}			}		}		else if ( icmp.type == 3 && /* Dest. Unreachable */			!memcmp(&icmp_iph.daddr,				&remote.sin_addr,				sizeof(ip.daddr)) &&			!memcmp(&ip.daddr,				&local.sin_addr,				sizeof(ip.daddr))		)		{			if (!opt_quiet)				log_icmp_unreach(src_addr, icmp.code);		}		else if (icmp.type == 11 && /* Time exceeded */			 !memcmp(&icmp_iph.daddr,				 &remote.sin_addr,				 sizeof(ip.daddr)) &&			 !memcmp(&ip.daddr,				 &local.sin_addr,				 sizeof(ip.daddr))		)		{			/* traceroute mode */			static unsigned char old_src_addr[4]={0,0,0,0};			if (opt_traceroute)			{				if (opt_tr_keep_ttl ||				    memcmp(&ip.saddr, old_src_addr, 4))				{					int sequence = 0, retval;					float rtt;					retval = icmp_unreach_rtt(						packet+ABS_OFFSETIP+hlen+8,						size - linkhdr_size - hlen - 8,						&sequence, &rtt);					memcpy(old_src_addr, &ip.saddr, 4);					printf("hop=%d ", src_ttl);					fflush(stdout);					log_icmp_timeexc(src_addr, icmp.code);					if (retval != -1)						printf("hop=%d "							"hoprtt=%.1f ms\n",								src_ttl, rtt);					if (!opt_tr_keep_ttl)						src_ttl++;				}			}			else			{				if (!opt_quiet)					log_icmp_timeexc(src_addr, icmp.code);			}		}		else			match = FALSE;	}	/* --------- UDP --------- */	if ( ip.protocol == IPPROTO_UDP &&	     !memcmp(&ip.saddr, &remote.sin_addr, sizeof(ip.saddr)) &&	     !memcmp(&ip.daddr, &local.sin_addr, sizeof(ip.daddr)) &&	     recv_sport == dst_port )	{		match = TRUE;		/* obtain round trip time */		sequence = 0;		status = rtt(&sequence, recv_dport, &ms_delay);		/* relativize ip->id */		if (opt_relid)			rel_id = relativize_id(sequence, &ip_id);		else			rel_id = FALSE;		if (!opt_quiet)		{			if (status == S_RECV)				printf("DUP! ");			if (!opt_incdport)				printf("len=%d ip=%s ",					size - linkhdr_size, src_addr);			else				printf("len=%d ip=%s sport=%d: ",					size - linkhdr_size, src_addr,					recv_sport);			printf("seq=%d ", sequence);			printf("ttl=%d ", ip.ttl);			printf("id");			if (rel_id == TRUE)				printf("=+");			else				putchar('=');			printf("%d ", ip_id);			printf("rtt=%.1f ms", ms_delay);			putchar('\n');		}		fflush(stdout);		recv_pkt++;		if (opt_incdport && !opt_force_incdport)			dst_port++;	}	/* ---------------- COMMON ---------------- */	/* dump the received packet in hex */	if (opt_hexdump && match && !opt_quiet)	{		unsigned char *byte;		int count = 0;		printf("\t\t");		for (byte = (unsigned char*) packet; byte < (unsigned char*) (packet+size); byte++)		{			count++;			printf("%02x", *byte);			if (count % 2 == 0) printf(" ");			if (count % 16 == 0) printf("\n\t\t");		}		printf("\n\n");	}	/* dump the received packet printable characters */	if (opt_contdump && match && !opt_quiet)	{		unsigned char *byte;		int count = 0;		printf("\t\t");		for (byte = (unsigned char*) packet; byte < (unsigned char*) (packet+size); byte++)		{			count ++;			if (isprint(*byte))				printf("%c", *byte);			else				printf(".");			if (count % 32 == 0) printf("\n\t\t");		}		printf("\n\n");	}	/* display IP options */	if (opt_rroute && match && !opt_quiet)	{		display_ipopt(packet+ABS_OFFSETIP);	}	/* --stop-tr stops hping in traceroute mode when the	 * first not ICMP time exceeded packet is received */	if (opt_traceroute && opt_tr_stop && match) {		if (ip.protocol != IPPROTO_ICMP ||		    icmp.type != 11)			print_statistics(0);	}	/* exit if 'count' is reached */	if (count != -1 && count == recv_pkt)		print_statistics(0);}/* Try to extract information about the original packet from the * ICMP error to obtain the round time trip * * Note that size is the the packet size starting from the * IP packet quoted in the ICMP error, it may be negative * if the ICMP is broken */static int icmp_unreach_rtt(void *quoted_ip, int size, int *seqp, float *ms_delay){	int src_port;	int sequence = 0;	int quoted_iphdr_size;	struct myudphdr udp;	struct myicmphdr icmp;	struct myiphdr qip;	/* The user specified --no-rtt */	if (opt_tr_no_rtt)		return -1;	if (size < sizeof(struct myiphdr))		return -1;	memcpy(&qip, quoted_ip, sizeof(struct myiphdr));	quoted_iphdr_size = qip.ihl << 2;	/* Ok, enough room, try to get the rtt,	 * but check if the original packet was an UDP/TCP one */	if (qip.protocol == IPPROTO_TCP ||	    qip.protocol == IPPROTO_UDP) {		/* We need at least 2 bytes of the quoted UDP/TCP header		 * for the source port */		if ((size - quoted_iphdr_size) < 2)			return -1;		/* Use the UDP header for both UDP and TCP, they are		* the same in the 4 first bytes (source and dest port) */		memcpy(&udp, quoted_ip+quoted_iphdr_size, sizeof(udp));		src_port = htons(udp.uh_sport);		return rtt(&sequence, src_port, ms_delay);	} else if (qip.protocol == IPPROTO_ICMP) {		int s;		/* We need the whole 8 byte ICMP header to get		 * the sequence field, also the type must be		 * ICMP_ECHO */		memcpy(&icmp, quoted_ip+quoted_iphdr_size, sizeof(icmp));		if ((size - quoted_iphdr_size) < 8 ||		    icmp.type != ICMP_ECHO)			return -1;		s = icmp.un.echo.sequence;		return rtt(&s, 0, ms_delay);	}	return -1; /* no way */}static void print_tcp_timestamp(void *tcp, int tcpsize){	int optlen;	unsigned char *opt;	__u32 tstamp, echo;	static __u32 last_tstamp = 0;	struct mytcphdr tmptcphdr;	unsigned int tcphdrlen;	if (tcpsize < TCPHDR_SIZE)		return;	memcpy(&tmptcphdr, tcp, sizeof(struct mytcphdr));	tcphdrlen = tmptcphdr.th_off * 4;	/* bad len or no options in the TCP header */	if (tcphdrlen <= 20 || tcphdrlen < tcpsize)		return;	optlen = tcphdrlen - TCPHDR_SIZE; 	opt = (unsigned char*)tcp + TCPHDR_SIZE; /* skips the TCP fix header */	while(optlen) {		switch(*opt) {		case 0: /* end of option */			return;		case 1: /* noop */			opt++;			optlen--;			continue;		default:			if (optlen < 2)				return;			if (opt[1] > optlen)				return;			if (opt[0] != 8) { /* not timestamp */				optlen -= opt[1];				opt += opt[1];				continue;			}			/* timestamp found */			if (opt[1] != 10) /* bad len */				return;			memcpy(&tstamp, opt+2, 4);			memcpy(&echo, opt+6, 4);			tstamp = ntohl(tstamp);			echo = ntohl(echo);			goto found;		}	}found:	printf("  TCP timestamp: tcpts=%u\n", tstamp);	if (last_tstamp && !opt_waitinusec) {		int tsdiff = (tstamp - last_tstamp) / sending_wait;		int hz_set[] = { 2, 10, 100, 1000, 0 };		int hzdiff = -1;		int hz = 0, sec;		int days, hours, minutes;		if (tsdiff > 0) {			int i = 0;			while(hz_set[i]) {				if (hzdiff == -1) {					hzdiff = ABS(tsdiff-hz_set[i]);					hz = hz_set[i];				} else if (hzdiff > ABS(tsdiff-hz_set[i])) {					hzdiff = ABS(tsdiff-hz_set[i]);					hz = hz_set[i];				}				i++;			}			printf("  HZ seems hz=%d\n", hz);			sec = tstamp/hz; /* Get the uptime in seconds */			days = sec / (3600*24);			sec %= 3600*24;			hours = sec / 3600;			sec %= 3600;			minutes = sec / 60;			sec %= 60;			printf("  System uptime seems: %d days, %d hours, "			       "%d minutes, %d seconds\n",			       		days, hours, minutes, sec);		}	}	printf("\n");	last_tstamp = tstamp;}

⌨️ 快捷键说明

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