/* icmpmon might be lame piece, but is done more for experimenting
 * purposes rather than a something neato :)
 *
 * will show you all ICMP packets reaching your box, which could be useful 
 * in detecting attacks/portscans sometimes.
 * 
 *				comments: fygrave@tigerteam.net
 *				flames  : postmaster@localhost
 * 				browsers: http://www.kalug.lug.net
 */


/* BSD compatibility */
#define __USE_BSD

#include <stdio.h>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

char *icmppack[]={"ICMP ECHO REPLY","#1","#2","ICMP DEST UNREACHABLE",
	"ICMP SOURCE QUENCH","ICMP REDIRECT","#6","#7","ICMP ECHO",
	"ROUTER ADVERTISEMENT","ROUTER SOLICITATION","ICMP TIME EXCEEDED",
	"ICMP PARAM PROBLEM",
	"ICMP TIMESTAMP REQUEST","ICMP INFO REQUEST","ICMP INFO REPLY",
	"ICMP ADDRESS","ICMP ADDRESS REPLY"};
char *icmpunreach[]={"Network unreachable", "host unreachable", 
	"protocol unreachable", "port unreachable","need fragmentation",
	"source routed fialed","net denied","host denied","bad tos for net",
	"bad tos for host","filter denied","host precedence violation",
	"precedence cutoff"};
char *icmpredir[]={"Network redirect","host redirect","tos and net redir",
	"tos and host redir"};
char *icmptimex[]={"time exceed in transit","time exceed in reassembly"};






int sendpack( int s, u_long srcaddr, u_short srcport, u_long dstaddr, u_short dstport, u_char *packet) {

	return 0;
}

int main(argc,argv)
	int argc;
	char **argv;
{
	int rawfd,rd,rsize;
	int one=1;
	u_char buf[1024];
	struct sockaddr_in raddr;
	struct ip *ip;
	struct icmp *icmp;

if ((rawfd=socket(PF_INET,SOCK_RAW,IPPROTO_ICMP))<0) {
		perror("RawSocket:");
		exit(1);
	}
	if (setsockopt(rawfd,IPPROTO_IP,IP_HDRINCL,&one,sizeof(one))<0) {
		perror("SetSockOpt:");
		close(rawfd);
		exit(1);
	}


		
	printf("Listening to ICMP packets\n");
	for(;;) {
		fflush(stdout);
		if ((rd=recvfrom(rawfd,buf,1024,0,(struct sockaddr *)&raddr,&rsize))<0) break;
	ip=(struct ip *)buf;
	icmp=(struct icmp *)&buf[ip->ip_hl<<2];
	
	
	printf("%s packet from: %s ",icmppack[icmp->icmp_type],inet_ntoa(ip->ip_src));
/* details */
	switch(icmp->icmp_type) {
		case ICMP_UNREACH :
			printf("[%s]\n",icmpunreach[icmp->icmp_code]);
			break;
		case ICMP_REDIRECT :
			printf("[%s]\n",icmpredir[icmp->icmp_code]);
			break;
		case ICMP_TIMXCEED :
			printf("[%s]\n",icmptimex[icmp->icmp_code]);
			break;
		default: 
			printf("\n");
	}
	}
	close(rawfd);
	return 0;
}

