/* Copyright 1998 by Vadim Kolontsov
* All rights reserved
*
* Distribute freely, except: don't remove my name from the source or
* documentation (don't take credit for my work), mark your changes (don't
* get me blamed for your possible bugs), don't alter or remove this
* notice. May be sold if buildable source is provided to buyer. No
* warrantee of any kind, express or implied, is included with this
* software; use at your own risk, responsibility for damages (if any) to
* anyone resulting from the use of this software rests entirely with the
* user.
*
* Send bug reports, bug fixes, enhancements, requests, flames, etc., and
* I'll try to keep a version up to date. I can be reached as follows:
*
* Vadim Kolontsov <sb@123.org>
*
* ---------------------------------------------------------------------------
* Traceroute Detector, version 0.2
* Dedicated to beloved Gala.
*
* Version 0.2
*
* The main idea is detecting UDP (unix traceroute) and ICMP (windows tracert)
* packets with TTL == 1. Easy, isn't it..
*
* Tested under FreeBSD 2.2.2/Linux 2.1.113, should work with other systems
* with BPF library. Can use ethernet or loopback interface.
* Based on some my very old code.
*
* http://sb.123.org/tdetect.html
*
*-----------------------------------------------------------------------
* Made usefull by Mike Eddington
*
* Now fork()'s at runtime to deamon.
* Logs messages to syslog(3).
*
* Note: log floods should be "ok" with built in syslog stuff
* (that "last message repeated N times" stuff).
*
*/
#include <stdio.h>
#include <pcap.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
#define _PATH_DEVNULL "/dev/null"
void log( char* str )
{
syslog(SYSLOG_LEVEL, str);
}
void error(char *errstr)
{
printf("error: %s\n", errstr);
exit(-1);
}
/* Make daemon */
void daemonize(void)
{
int fd;
/* Now daemonize.. */
switch (fork())
{
case -1:
error("Can't daemonize");
case 0:
break;
default:
_exit(0);
}
if (setsid() == -1)
error("Can't set session leader");
if (chdir("/") == -1)
error("Can't chdir to /");
if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
{
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > 2)
close(fd);
}
}
/* Analyzers */
extern void ether_analyzer(u_char *,const struct pcap_pkthdr *, const u_char *);
extern void null_analyzer(u_char *, const struct pcap_pkthdr *, const u_char *);
/* (not implemented yet)
extern void slip_analyzer(u_char *, const struct pcap_pkthdr *, const u_char *);
extern void ppp_analyzer(u_char *, const struct pcap_pkthdr *, const u_char *);
extern void fddi_analyzer(u_char *, const struct pcap_pkthdr *, const u_char *);
*/
struct analyzer {
pcap_handler handler;
int type;
};
static struct analyzer analyzers[] = {
/* { slip_analyzer, DLT_SLIP },
{ ppp_analyzer, DLT_PPP },
{ fddi_analyzer, DLT_FDDI },
*/ { ether_analyzer, DLT_EN10MB },
{ null_analyzer, DLT_NULL },
{ NULL, 0 }
};
/* Select analyzer function for data link */
static pcap_handler select_analyzer(int type)
{
struct analyzer *an;
for (an = analyzers; an->handler; ++an)
if (an->type == type)
return(an->handler);
error("unknown data link");
exit(0); /* NOTREACHED */
}
/* Keeps broadcast address for my network */
struct in_addr broadcast;
char tmsg[100];
int main(int argc, char *argv[])
{
register char *cmdbuf = NULL;
pcap_t *pd;
bpf_u_int32 localnet, netmask;
char errbuf[PCAP_ERRBUF_SIZE];
u_char *userdata = NULL;
pcap_handler handler;
struct bpf_program bpfprog;
if (argc != 2)
{
printf("Usage: %s interface\n", argv[0]);
exit(-1);
}
if (!(pd = pcap_open_live(argv[1], 4096, 1, 1000, errbuf)))
error(errbuf);
if (pcap_lookupnet(argv[1], &localnet, &netmask, errbuf) < 0)
error(errbuf);
broadcast.s_addr = localnet | ~netmask;
openlog(SYSLOG_APP_NAME, LOG_NDELAY, SYSLOG_LOG );
sprintf(tmsg, "Traceroute Detector active on %s\n", argv[1]);
log(tmsg);
if (pcap_compile(pd, &bpfprog, cmdbuf, 1, netmask) < 0)
error(pcap_geterr(pd));
if (pcap_setfilter(pd, &bpfprog) < 0)
error(pcap_geterr(pd));
handler = select_analyzer(pcap_datalink(pd));
daemonize();
pcap_loop(pd, -1, handler, userdata);
pcap_close(pd);
closelog();
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1