/* 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 * * --------------------------------------------------------------------------- * 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 #include #include #include #include #include #include #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); }