From venglin@own3d.freebsd.lublin.pl Mon Feb 28 12:55:01 2000
Return-Path: <venglin@own3d.freebsd.lublin.pl>
Received: from lagoon.freebsd.lublin.pl([212.182.117.180]) (11341 bytes) by packetstorm.securify.com
	via sendmail with P:smtp/D:user/T:local
	(sender: <venglin@own3d.freebsd.lublin.pl>) 
	id <m12PXBz-0006CeC@packetstorm.securify.com>
	for <submissions@packetstorm.securify.com>; Mon, 28 Feb 2000 12:54:59 -0800 (PST)
	(Smail-3.2.0.106 1999-Mar-31 #1 built 1999-Sep-18)
Received: (qmail 3449 invoked from network); 28 Feb 2000 07:25:51 -0000
Received: from lubi.freebsd.lublin.pl (qmailr@212.182.118.90)
  by lagoon.freebsd.lublin.pl with SMTP; 28 Feb 2000 07:25:51 -0000
Received: (qmail 75218 invoked from network); 28 Feb 2000 07:25:11 -0000
Received: from own3d.freebsd.lublin.pl (root@212.182.115.2)
  by mailhost.gadaczka.org with SMTP; 28 Feb 2000 07:25:11 -0000
Received: (from venglin@localhost)
	by own3d.freebsd.lublin.pl (8.9.3/8.8.7) id IAA07258
	for submissions@packetstorm.securify.com; Mon, 28 Feb 2000 08:24:27 +0100
Date: Mon, 28 Feb 2000 08:24:27 +0100
From: Przemyslaw Frasunek <venglin@freebsd.lublin.pl>
To: submissions@packetstorm.securify.com
Subject: new stuff
Message-ID: <20000228082427.A7253@freebsd.lublin.pl>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Mailer: Mutt 1.0pre3us
Status: RO

/*
*
* (c) 2000 babcia padlina / b0f
*
* plogd v2 -- syn/udp/icmp packet logger (freebsd version)
*
* [ compile with -lpcap ]
*
* bug reports: babunia@freebsd.lublin.pl
*
* $Log: plogd2.c,v $
* Revision 1.2  2000/02/28 00:07:51  venglin
* SIGSEGV in rfc931_lookup()
*
* Revision 1.1  2000/02/27 23:29:18  venglin
* Initial revision
*
*
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>

#define IDENT		113
#define BUFSIZE		1024
#define IP_SIZE         20
#define TCP_SIZE        20
#define DLT_LEN         14

/* static */

FILE *log;
pcap_t *ip_socket;

struct {
	unsigned int noresolve : 1;
	unsigned int noident : 1;
	unsigned int notcp : 1;
	unsigned int noudp : 1;
	unsigned int noicmp : 1;
} flags;

char rcsid[]="$Id: plogd2.c,v 1.2 2000/02/28 00:07:51 venglin Exp $";

/* prototypes */

static char     *hostlookup     __P((unsigned));
void            filter_packet   __P((u_char *, struct pcap_pkthdr *, u_char *));
void            log_syn         __P((struct ip *, struct tcphdr *));
void            log_icmp        __P((struct ip *, struct icmp *));
void            log_udp         __P((struct ip *, struct udphdr *));
void            usage           __P((char *));
int             rfc931_lookup   __P((long, unsigned, unsigned, char *));
void		loginit		__P((char *, char *));
void		debug		__P((const char *, ...));
void		fatal		__P((const char *, ...));

/* log routines */

void loginit(ofile, av0)
char *ofile, *av0;
{
	if (ofile)
	{
		if (!(log = fopen(ofile, "w")))
			fatal("fopen(): %s", strerror(errno));
	}
	else
	{
		closelog();
		openlog(av0, LOG_PID, LOG_DAEMON);
	}
}

void fatal(const char *fmt, ...)
{
	char buf[BUFSIZE];
	va_list args;

	va_start(args, fmt);
	vsnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);
	
	if (log)
		fprintf(log, "fatal: %s\n", buf);
	else
		syslog(LOG_ERR, "fatal: %.500s", buf);

	closelog();
	if (log)
		fclose(log);

	if (ip_socket)
		pcap_close(ip_socket);

	exit(1);
}

void debug(const char *fmt, ...)
{
	char buf[BUFSIZE];
	va_list args;

	va_start(args, fmt);
	vsnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);

	if (log)
		fprintf(log, "status: %s\n", buf);
	else
		syslog(LOG_NOTICE, "status: %.500s", buf);

	return;
}

/* signal handler */
void sigcatch(sig)
int sig;
{
	fatal("Received signal %d; terminating.", sig);
	return;
}

/* reverse host lookup routine */

char *hostlookup(unsigned int in)
{
        static char tmp[BUFSIZE];
        struct in_addr i;
        struct hostent *he = NULL;
   
        i.s_addr = in;

        if(!flags.noresolve)
                he = gethostbyaddr((char *)&i, sizeof(struct in_addr), AF_INET);

        if (he == NULL || flags.noresolve)
                strncpy(tmp, inet_ntoa(i), BUFSIZE-1);
        else
                strncpy(tmp, he->h_name, BUFSIZE-1);

        tmp[BUFSIZE]='\0';
        return (char *)tmp;
}

/* ident/tap (rfc931) lookup routine */

int rfc931_lookup(host, sport, dport, ident)
long host;
unsigned int sport, dport;
char *ident;
{
	char buf[BUFSIZE], tmp[BUFSIZE];
	char *cp;
	int sockfd, dump;
	struct sockaddr_in cli;

	bzero(&cli, sizeof(cli));
	cli.sin_family = AF_INET;
	cli.sin_addr.s_addr=host;
	cli.sin_port = htons(IDENT);

	sprintf(buf, "%u,%u\r\n", sport, dport);	

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		return -1;

	if(connect(sockfd, (struct sockaddr *)&cli, sizeof(cli)) < 0) 
		return -1;

	if (write(sockfd, buf, strlen(buf)) < 0)
	{
		close(sockfd);
		return -1;
	}

	bzero(buf, BUFSIZE);

	if (read(sockfd, buf, BUFSIZE-1) < 0)
	{
		close(sockfd);
		return -1;
	}

	close(sockfd);
	
	if (sscanf(buf, "%u , %u : USERID :%*[^:]:%s", &dump, &dump, tmp) != 3)
		return -1;

	if ((cp = strchr(tmp, '\r'))) 
		*cp = '\0';

	strncpy(ident, tmp, BUFSIZE);

	return 0;
}

/* tcp syn log routine */

void log_syn(ip, tcp)
struct ip *ip;
struct tcphdr *tcp;
{
	char ident[BUFSIZE];
	struct servent *service;

	if (flags.notcp)
		return;

	if (!flags.noident)
	{
		if (ntohs(tcp->th_dport) != IDENT)
		{
			if (rfc931_lookup((long)ip->ip_src.s_addr,
						(unsigned)ntohs(tcp->th_sport),
						(unsigned)ntohs(tcp->th_dport),
						ident) < 0)

				strcpy(ident, "unknown");
		}
		else
			strcpy(ident, "unknown");
	}
	else
		strcpy(ident, "unknown");	

	if ((service = getservbyport(tcp->th_dport, NULL)) != NULL)
		debug("connection from %s@%s (port %u) to service %s (port %u)",
				ident, hostlookup(ip->ip_src.s_addr),
				ntohs(tcp->th_sport), service->s_name,
				ntohs(tcp->th_dport));

	else

                debug("connection from %s@%s (port %u) to port %u", ident, 
				hostlookup(ip->ip_src.s_addr), 
				ntohs(tcp->th_sport), 
				ntohs(tcp->th_dport));

	return;
}

/* icmp log routine */

void log_icmp(ip, icmp)
struct ip *ip;
struct icmp *icmp;
{
	static char *icmptab[] =
	{
		"echo reply",
		NULL,
		NULL,
		"unreachable",
		"source quench",
		"redirect",
		NULL,
		NULL,
		"echo request",
		"router advertisement",
		"router solicitation",
		"time exceed",
		"parameter problem",
		"timestamp request",
		"timestamp reply",
		"information request",
		"information reply",
		"address mask request",
		"address mask reply",
		NULL
	};

	if (flags.noicmp)
		return;

	debug("icmp %s from %s", icmptab[icmp->icmp_type], 
			hostlookup(ip->ip_src.s_addr));

	return;
}

/* udp log routine */

void log_udp(ip, udp)
struct ip *ip;
struct udphdr *udp;
{
	struct servent *service;

	if (flags.noudp)
		return;

	if ((service = getservbyport(udp->uh_dport, NULL)) != NULL)
		debug("udp packet from %s (port %u) to service %s (port %u)",
				hostlookup(ip->ip_src.s_addr),
				ntohs(udp->uh_sport), service->s_name,
				ntohs(udp->uh_dport));

	else

                debug("udp packet from %s (port %u) to port %u",
				hostlookup(ip->ip_src.s_addr),
				ntohs(udp->uh_sport), ntohs(udp->uh_dport));

	return;
}

/* filter routine */

void filter_packet(u, p, packet)
u_char *u, *packet;
struct pcap_pkthdr *p;
{
	unsigned short ip_options = 0;
	struct ip *ip;
	struct tcphdr *tcp;	
	struct icmp *icmp;
	struct udphdr *udp;
	static u_char align_buf[4096];
      
	ip = (struct ip *) (packet + DLT_LEN);

	bcopy((char *)ip, (char *)align_buf, p->len);
	packet = align_buf;

	ip = (struct ip *)align_buf;

	switch(ip->ip_p)
	{
		case IPPROTO_TCP:

			ip_options = ip->ip_hl;
			ip_options -= 5;
			ip_options *= 4;

			tcp = (struct tcphdr *)(packet + IP_SIZE + ip_options);
			ip->ip_off &= 0xFF9F;
			if(ip->ip_off != 0) return; 

			if((tcp->th_flags & TH_SYN) && !(tcp->th_flags & TH_ACK))
				log_syn(ip, tcp);
			break;

		case IPPROTO_ICMP:

			ip_options = ip->ip_hl;
			ip_options -= 5;
			ip_options *= 4;

			icmp = (struct icmp *)(packet + IP_SIZE + ip_options);
			log_icmp(ip, icmp);
			
			break;

		case IPPROTO_UDP:

			ip_options = ip->ip_hl;
			ip_options -= 5;
			ip_options *= 4;

			udp = (struct udphdr *)(packet + IP_SIZE + ip_options);
			log_udp(ip, udp);

			break;
	}
}

/* nice usage routine */

void usage(av0)
char *av0;
{
	(void)fprintf(stderr, 
		      "\nusage: %s [-r] [-l] [-t] [-u] [-c] [-o file] [-i interface] \"filt_expr\"\n\n" 
		      "\t[-r]\t\tdon't resolve hostnames\n"
		      "\t[-l]\t\tdon't perform rfc931 lookup\n"
		      "\t[-t]\t\tdon't log tcp connections\n"
		      "\t[-u]\t\tdon't log udp packets\n"
		      "\t[-c]\t\tdon't log icmp packets\n"
		      "\t[-o]\t\toutput file (default: syslogd)\n"
		      "\t[-i]\t\tnetwork interface\n"
		      "\t\"filt_expr\"\ttcpdump compatibile filter expression\n\n", av0);
	exit(0);
}

/* ...and main! */

int main(argc, argv)
int argc;
char **argv;
{
	extern char *optarg;
	extern int optind;

	int ch, f;
	char *iface, *ofile, *av0, errbuf[PCAP_ERRBUF_SIZE];
	bpf_u_int32 network, netmask;
	struct bpf_program prog;

	if (strchr(argv[0], '/'))
		av0 = strrchr(argv[0], '/') + 1;
	else
		av0 = argv[0];

	opterr = flags.noresolve = flags.noident = flags.notcp = flags.noudp = 
		flags.noicmp = 0;

	iface = ofile = NULL;
	log = NULL;
	ip_socket = NULL;

	while ((ch = getopt(argc, argv, "rltuci:a:o:e:")) != -1)
		switch((char)ch)
		{

			case 'r':
				flags.noresolve = 1;
				break;

			case 'l':
				flags.noident = 1;
				break;

			case 't':
				flags.notcp = 1;
				break;

			case 'u':
				flags.noudp = 1;
				break;

			case 'c':
				flags.noicmp = 1;
				break;

			case 'i':
				iface = strdup(optarg);
				if (!iface)
					fatal("malloc(): %s", strerror(errno));
				break;

			case 'o':
				ofile = strdup(optarg);
				if (!ofile)
					fatal("malloc(): %s", strerror(errno));
				break;

			case '?':
			default:

				(void)usage(av0);

		}
		
	argc -= optind;
	argv += optind;

	if (argc < 1)
		(void)usage(av0);

	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, sigcatch);
	signal(SIGQUIT, sigcatch);
 	signal(SIGTERM, sigcatch);
	signal(SIGSEGV, sigcatch);
	signal(SIGBUS, sigcatch);

	loginit(ofile, av0);

	if (!iface)
	{
		iface = strdup(pcap_lookupdev(errbuf));

		if (!iface)
			fatal("pcap_lookupdev(): %s", errbuf);
	}

	if (pcap_lookupnet(iface, &network, &netmask, errbuf) < 0)
		fatal("pcap_lookupnet(): %s", errbuf);

	if (!(ip_socket = pcap_open_live(iface, 1024, 0, 1024, errbuf)))
		fatal("pcap_open_live(): %s", errbuf);

	if (pcap_datalink(ip_socket) != DLT_EN10MB)
		fatal("pcap_datalink(): only ethernet hardware supported");

	if (pcap_compile(ip_socket, &prog, *argv, 1, netmask) < 0)
		fatal("pcap_compile(): %s", errbuf);

	if (pcap_setfilter(ip_socket, &prog) < 0)
		fatal("pcap_setfilter(): %s", errbuf);

	debug("ready to rock on %s (%s)", iface, *argv);

	f = fork();

	if (f < 0)
		debug("fork(): %s (continuing in foreground)", strerror(errno));

	if (f > 0)
	{
		debug("fork ok (pid %d)", f);
		return 0;
	}

	setsid();

	free(iface);
	free(ofile);
	
	while(1)
		pcap_loop(ip_socket, -1, (pcap_handler)filter_packet, NULL);
}

-- 
* Fido: 2:480/124 ** WWW: http://www.freebsd.lublin.pl ** NIC-HDL: PMF9-RIPE *
* Inet: venglin@freebsd.lublin.pl ** PGP: D48684904685DF43  EA93AFA13BE170BF *

