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

📄 icmp.c

📁 * A ncurses user interface. * Network statistics to view the amount of packets and data in many
💻 C
字号:
/*  This file is part of sniffer, a packet capture utility and  network moniter  The author can be contacted at <mistral@stev.org>  the lastest version is avilable from   http://stev.org  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <pthread.h>#include <string.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include "config.h"#include "sniff.h"#include "locks.h"#include "list.h"#include "log.h"#include "stat.h"#include "lookup.h"#include "in_ntoa.h"#include "ip.h"#include "udp.h"#include "tcp.h"#include "icmp.h"struct list_t *icmp_type;struct list_t *icmp_unreach;struct list_t *icmp_redirect;struct list_t *icmp_ttl;struct list_t *icmp_param;struct gen_stat icmp_stat;WINDOW *icmp_gui_window = NULL;pthread_mutex_t icmp_gui_mutex =  PTHREAD_MUTEX_INITIALIZER;FILE *icmp_log;/****************************************************************************** ICMP Packets ********************************************************************************************************/int icmp_handle(struct sniff_pkt *pkt, struct pkt_ip *ip, struct pkt_icmp *icmp) {	char *ip_source = NULL, *ip_dest = NULL;	unsigned short length;	struct icmp_type_t search_type, *type = NULL;	int i;#ifdef ICMP_CHECKSUM	unsigned short checksum;#endif	pkt->func = "icmp_handle";	if (pkt->dataleft < sizeof(struct pkt_icmp)) {		icmp_stat.dropped++;		return ERR_DATA;	}	pkt->dataleft -= sizeof(struct pkt_icmp);	/* find out how much data we have */	length = ntohs(ip->tot_len) - (ip->ihl * 4) - sizeof(struct pkt_icmp);	icmp_stat.packets++;	icmp_stat.bytes += length;	ip_source = lookup(ip->saddr, 0);	ip_dest = lookup(ip->daddr, 0);#ifdef ICMP_CHECKSUM	checksum = icmp->check;	icmp->check = 0;	/* we need to remember to add the icmp header length on */	icmp->check = ip_cksum( (void *) icmp, length + 8);	if (icmp->check != checksum) {		/* it failed */		log_error("Failed ICMP Checksum %s -> %s\n", ip_source, ip_dest);		icmp_stat.dropped++;		return ERR_CSUM;	}#endif	search_type.type = icmp->type;	i = list_search(icmp_type, &search_type);	/* we have a type we know about */	/* lets see if we have a code we know about */	type = list_get(icmp_type, i);	if (!type) return icmp_log_any(pkt, ip_source, ip_dest, ip, icmp);	if (type->code) return icmp_log_code(pkt, ip_source, ip_dest, type, ip, icmp);	return icmp_log_type(pkt, ip_source, ip_dest, type, ip, icmp);}inline int icmp_log_any (struct sniff_pkt *pkt, char *ip_source, char *ip_dest, struct pkt_ip *ip, struct pkt_icmp *icmp) {	int len = pkt->dataleft + sizeof(struct pkt_icmp);	if (icmp_log)		fprintf(icmp_log, "%s %s -> %s L:%u T:%.2X TTL:%u Type: 0x%.2X Code: 0x%.2X\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, icmp->type, icmp->code);	return icmp_gui_print("%s %s -> %s L:%u T:%.2X TTL:%u Type: 0x%.2X Code: 0x%.2X\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, icmp->type, icmp->code);}inline int icmp_log_type(struct sniff_pkt *pkt, char *ip_source, char *ip_dest, struct icmp_type_t *type, struct pkt_ip *ip, struct pkt_icmp *icmp) {	int len = pkt->dataleft + sizeof(struct pkt_icmp);	char buff[100];	if (type->func) {		buff[0] = (char ) NULL;		type->func(pkt, &buff[0], sizeof(buff), ip, icmp);		if (type->log && icmp_log)			fprintf(icmp_log, "%s %s -> %s L:%u T:%.2X TTL:%u %s %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc, &buff[0]);		return icmp_gui_print("%s %s -> %s L:%u T:%.2X TTL:%u %s %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc, &buff[0]);	}	if (type->log &&icmp_log)		fprintf(icmp_log, "%s %s -> %s L:%u T:%.2X TTL:%u %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc);	return icmp_gui_print("%s %s -> %s L:%u T:%.2X TTL:%u %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc);}inline int icmp_log_code(struct sniff_pkt *pkt, char *ip_source, char *ip_dest, struct icmp_type_t *type, struct pkt_ip *ip, struct pkt_icmp *icmp) {	int len = pkt->dataleft + sizeof(struct pkt_icmp);	struct icmp_code_t search, *code;	char buff[100];	int i;	search.code = icmp->code;	i = list_search(type->code, &search);	code = list_get(type->code, i);	if (!code) return icmp_log_type(pkt, ip_source, ip_dest, type, ip, icmp);	if (code->func) {		buff[0] = (char ) NULL;		code->func(pkt, &buff[0], sizeof(buff), ip, icmp);		if (code->log && icmp_log)			fprintf(icmp_log, "%s %s -> %s L:%u T:%.2X TTL:%u %s %s %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc, code->desc, &buff[0]);		return icmp_gui_print("%s %s -> %s L:%u T:%.2X TTL:%u %s %s %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc, code->desc, &buff[0]);	}	if (code->log && icmp_log)		fprintf(icmp_log, "%s %s -> %s L:%u T:%.2X TTL:%u %s %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc, code->desc);	return icmp_gui_print("%s %s -> %s L:%u T:%.2X TTL:%u %s %s\n", pkt->if_name, ip_source, ip_dest, len, ip->tos, ip->ttl, type->desc, code->desc);}int icmp_ping(struct sniff_pkt *pkt, char *buf, int buffleft, struct pkt_ip *ip, struct pkt_icmp *icmp) {	snprintf(buf, buffleft, "ID: %u SEQ: %u", icmp->un.echo.id, icmp->un.echo.sequence);	return 0;}int icmp_ping_reply(struct sniff_pkt *pkt, char *buf, int buffleft, struct pkt_ip *ip, struct pkt_icmp *icmp) {	snprintf(buf, buffleft, "ID: %u SEQ: %u", icmp->un.echo.id, icmp->un.echo.sequence);	return 0;}int icmp_do(struct sniff_pkt *pkt, char *buf, int buffleft, struct pkt_ip *ip, struct pkt_icmp *icmp) {	return icmp_proto(pkt, buf, buffleft, ip, icmp);}int icmp_proto(struct sniff_pkt *pkt, char *buf, int buffleft, struct pkt_ip *ip, struct pkt_icmp *icmp) {	struct pkt_ip *encap_ip;	struct pkt_icmp *encap_icmp;	struct pkt_udp *encap_udp;	struct pkt_tcp *encap_tcp;	char flags[9];	void *pointer;	/* next pointer */	char *ip_source, *ip_dest;	int ilen, i;	encap_ip = (struct pkt_ip *) ((void *) icmp + (sizeof(struct pkt_icmp)));	if (encap_ip->version != 4)		return snprintf(buf, buffleft, "\n\tIncorrect IP version %d should be 4", encap_ip->version);	if (encap_ip->ihl < 5)		return snprintf(buf, buffleft, "\n\tInvalid header length value");	ilen = encap_ip->ihl * 4;	pointer = (void *) ( (void *) encap_ip + ilen);	if (pkt->dataleft < ilen)		return snprintf(buf, buffleft, "\n\tNot enough data");	pkt->dataleft -= ilen;	ip_source = lookup(encap_ip->saddr, 0);	ip_dest = lookup(encap_ip->daddr, 0);	i = snprintf(buf, buffleft, "\n\tL:%u T:%.2X TTL:%u ", ntohs(encap_ip->tot_len), encap_ip->tos, encap_ip->ttl);	buffleft -= i;	buf += i;	switch(encap_ip->protocol) {		case IP_ICMP:			if (pkt->dataleft < sizeof(struct pkt_icmp))				return snprintf(buf, buffleft, "ICMP %s -> %s ICMP Out of Data", ip_source, ip_dest);			encap_icmp = pointer;			return snprintf(buf, buffleft, "ICMP %s -> %s Type: %u Code: %u", ip_source, ip_dest, encap_icmp->type, encap_icmp->code);			break;		case IP_TCP:			if (pkt->dataleft < sizeof(struct pkt_tcp))				return snprintf(buf, buffleft, "TCP %s -> %s Out of data", ip_source, ip_dest);			encap_tcp = pointer;			strcpy(&flags[0], "------\0\0"); /* we end a null */			if (encap_tcp->syn)				flags[0] = 'S';			if (encap_tcp->fin)				flags[1] = 'F';			if (encap_tcp->rst)				flags[2] = 'R';			if (encap_tcp->urg)				flags[3] = 'U';			if (encap_tcp->ack)				flags[4] = 'A';			if (encap_tcp->psh)				flags[5] = 'P';			return snprintf(buf, buffleft, "TCP %s[%u] -> %s[%u] %s SEQ:%lu ACK:%lu WIN:%u U:%u", ip_source, ntohs(encap_tcp->source)										, ip_dest, ntohs(encap_tcp->dest), &flags[0], encap_tcp->seq, encap_tcp->ack_seq										, ntohs(encap_tcp->window), ntohs(encap_tcp->urg_ptr));			break;		case IP_UDP:			if (pkt->dataleft < sizeof(struct pkt_udp))				return snprintf(buf, buffleft, "UDP %s -> %s Out of data", ip_source, ip_dest);			encap_udp = pointer;			return snprintf(buf, buffleft, "UDP %s[%u] -> %s[%u] L:%u", ip_source, ntohs(encap_udp->source), ip_dest, ntohs(encap_udp->dest), ntohs(encap_udp->len));			break;		default:			return snprintf(buf, buffleft, "%s -> %s Protocol %u", ip_source, ip_dest, encap_ip->protocol);			break;	}	log_unreach();	return 0;}int icmp_cmp_type(const struct icmp_type_t *c1, const struct icmp_type_t *c2) {	if (c1->type > c2->type) return -1;	if (c1->type < c2->type) return 1;	return 0;}int icmp_cmp_code(const struct icmp_code_t *c1, const struct icmp_code_t *c2) {	if (c1->code > c2->code) return -1;	if (c1->code < c2->code) return 1;	return 0;}int icmp_init( void ) {	int i = 0;	icmp_type = list_init();	if (!icmp_type)		return ERR_MISC;	list_setcmp(icmp_type, (void *) icmp_cmp_type);	while(icmp_base_type[i].type != 255) {		list_add_sort(icmp_type, &icmp_base_type[i]);		i++;	}	icmp_unreach = icmp_init_codes(ICMP_DESTUNREACH, icmp_base_unreach);	icmp_redirect = icmp_init_codes(ICMP_REDIRECT, icmp_base_redirect);	icmp_ttl = icmp_init_codes(ICMP_TIMEEXCEEDED, icmp_base_ttl);	icmp_param = icmp_init_codes(ICMP_PARMPROBLEM, icmp_base_param);	/* open up a file for loggin */#ifdef DEBUG	icmp_log = fopen("output/icmp", "w");#else	icmp_log = fopen("output/icmp", "w+");#endif	if (!icmp_log)		log_errno("fopen");	return 0;}struct list_t *icmp_init_codes(int type, struct icmp_code_t codes[]) {	int i = 0;	struct icmp_type_t search, *data;	struct list_t *tmp;	tmp = list_init();	if (!tmp)		return NULL;	list_setcmp(tmp, (void *) icmp_cmp_code);	while(codes[i].code != 255) {		list_add_sort(tmp, &codes[i]);		i++;	}	search.type = type;	i = list_search(icmp_type, &search);	if (i > 0)		data = list_get(icmp_type, i);		if (data)			data->code = tmp;		return tmp;}void icmp_gui(struct gui_t *p, int y, int x) {	WINDOW *draw;	char *foot_back, buff[80];		draw = newwin(p->twin->_maxy - 1, p->twin->_maxx - 1, 1, 1);	if (!draw) {		log_s("newwin failed");		SUNLOCK(&icmp_gui_mutex);		return;	}	wbkgd(draw, COLOR_PAIR(COL_BACK));	scrollok(draw, TRUE);	werase(draw);	wrefresh(draw);	SLOCK(&icmp_gui_mutex);	icmp_gui_window = draw;	SUNLOCK(&icmp_gui_mutex);	while (1) {		if (gui_wait(250, 0) == 1) {			switch(getch()) {				default:					goto get_out;					break;			}		} else {			stat_process(&icmp_stat);			SLOCK(&icmp_gui_mutex);			snprintf(&buff[0], 80, "ICMP Packets: %llu Data: %llu %s Drop: %llu",							icmp_stat.packets, icmp_stat.readable, icmp_stat.messure, icmp_stat.dropped);			wrefresh(draw);			gui_footer(p, &buff[0]);			SUNLOCK(&icmp_gui_mutex);		}	}get_out:	SLOCK(&icmp_gui_mutex);	icmp_gui_window = NULL;	SUNLOCK(&icmp_gui_mutex);	gui_footer(p, foot_back);	scrollok(draw, FALSE);	werase(draw);	wrefresh(draw);	delwin(draw);	return;}int icmp_gui_print(char *fmt, ...) {	va_list ap;	va_start(ap, fmt);	SLOCK(&icmp_gui_mutex);	vwprintw(icmp_gui_window, fmt, ap);	SUNLOCK(&icmp_gui_mutex);	va_end(ap);	return 0;}struct icmp_type_t icmp_base_type[] = {				/* Func  code log extra */	{ICMP_ECHOREPLY,			"Ping Reply",			icmp_ping_reply,	NULL, 1},	{ICMP_DESTUNREACH,			"Unreachable", 			icmp_do,			NULL, 0},	{ICMP_SOURCEQUENCH,			"Source Quence",		icmp_do,			NULL, 1},	{ICMP_REDIRECT,				"Redirect",				icmp_do, 			NULL, 1},	{ICMP_ALT_HOST,				"Alt Host",				NULL,				NULL, 0},	{ICMP_ECHO,					"Ping",					icmp_ping, 			NULL, 1},	{ICMP_ROUTER_ADVERT,		"Router Advert",		NULL, 				NULL, 1},	{ICMP_ROUTER_SELECT,		"Router Select",		NULL, 				NULL, 1},	{ICMP_TIMEEXCEEDED,			"Time Exceeded",		icmp_do, 			NULL, 0},	{ICMP_PARMPROBLEM,			"Param Problem",		icmp_do,			NULL, 1},	{ICMP_TIMESTAMP,			"Time Stamp",			NULL, 				NULL, 1},	{ICMP_TIMESTAMP_REPLY,		"Time Stamp Reply",		NULL, 				NULL, 1},	{ICMP_INFO_REQUEST,			"Info Request",			NULL, 				NULL, 1},	{ICMP_INFO_REPLY,			"Info Reply",			NULL,				NULL, 1},	{ICMP_ADDRMASK_REQUEST,		"Addr Mask Request",	NULL, 				NULL, 1},	{ICMP_ADDRMASK_REPLY,		"Addr Mask Reply",		NULL, 				NULL, 1},	{ICMP_TRACEROUTE,			"Traceroute",			NULL, 				NULL, 1},	{ICMP_DATAGRAM_CONVERROR,	"DGRAM Conv Error",		NULL, 				NULL, 1},	{ICMP_MOBILE_HOST_REDIRECT,	"Mobile Host Redir",	NULL, 				NULL, 1},	{ICMP_IPV6_WHEREAREYOU,		"IPV6 Where are you",	NULL, 				NULL, 1},	{ICMP_IPV6_IAMHERE,			"IPV6 I am here",		NULL, 				NULL, 1},	{ICMP_MOBILE_REG_REQUEST,	"Mobile Reg REQUEST",	NULL, 				NULL, 1},	{ICMP_MOBILE_REG_REPLY,		"Mobile Reg Reply",		NULL, 				NULL, 1},	{ICMP_DOMAIN_NAME_REQUEST,	"Domain Name Request",	NULL, 				NULL, 1},	{ICMP_DOMAIN_NAME_REPLY,	"Domain Name Reply",	NULL, 				NULL, 1},	{ICMP_SKIP,					"Skip",					NULL,				NULL, 1},	{ICMP_PHOTURIS,				"Photuris",				NULL, 				NULL, 1},	{255,				NULL,							NULL, 				NULL, 0}};struct icmp_code_t icmp_base_unreach[] = {				/* Func   Log? */	{ICMP_UNREACH_NET,				"Network",				icmp_do, 0},	{ICMP_UNREACH_HOST,				"Host",					icmp_do, 0},	{ICMP_UNREACH_PROTOCOL,			"Protocol",				icmp_do, 1},	{ICMP_UNREACH_PORT,				"Port",					icmp_do, 0},	{ICMP_UNREACH_FRAGNEEDED,		"Frag Needed",			icmp_do, 1},	{ICMP_UNREACH_SOURCEROUTE,		"Source Route Failed",	icmp_do, 1},	{ICMP_UNREACH_DESTNETWORK,		"Dest Network",			icmp_do, 0},	{ICMP_UNREACH_DESTHOST,			"Dest Host",			icmp_do, 0},	{ICMP_UNREACH_SOURCEHOST,		"Source Host",			icmp_do, 1},	{ICMP_UNREACH_PROHIB_NETWORK,	"Prohibited Network",	icmp_do, 1},	{ICMP_UNREACH_PROHIB_HOST,		"Prohibited Host",		icmp_do, 1},	{ICMP_UNREACH_DESTNETWORK_TOS,	"Network for TOS",		icmp_do, 1},	{ICMP_UNREACH_DESTHOST_TOS,		"Host for TOS",			icmp_do, 1},	{ICMP_UNREACH_PROHIB_ADMIN,		"Prohibited Admin",		icmp_do, 1},	{ICMP_UNREACH_PRECEDENCE_HOST,	"Precedence Host",		icmp_do, 1},	{ICMP_UNREACH_PRECEDENCE_CUTOFF,"Precedence Cutoff",	icmp_do, 1},	{255, NULL}};struct icmp_code_t icmp_base_redirect[] = {	{ICMP_REDIRECT_NETWORK,			"Network",		icmp_do, 1},	{ICMP_REDIRECT_HOST,			"Host",			icmp_do, 1},	{ICMP_REDIRECT_TOS_NETWORK,		"TOS Network",	icmp_do, 1},	{ICMP_REDIRECT_TOS_HOST,		"TOD Host",		icmp_do, 1},	{255, NULL}};struct icmp_code_t icmp_base_ttl[] = {	{ICMP_TTL_TTL,					"TTL",			icmp_do, 0},	{ICMP_TTL_FRAG,					"Fragment",		icmp_do, 1},	{255, NULL}};struct icmp_code_t icmp_base_param[] = {	{ICMP_PARAM_POINTER,			"Pointer",		icmp_do, 1},	{ICMP_PARAM_MISSING,			"Missing",		icmp_do, 1},	{ICMP_PARAM_BADLEN,				"Length",		icmp_do, 1},	{255, NULL}};

⌨️ 快捷键说明

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