/* passlogd - passive syslog capture daemon copyright (c) 2005 - christian void file: passlog.c history: 07jun01 cvoid: added -S syslog-like output option. 05jun01 cvoid: added -p and -e options for otto. 04jun01 cvoid: added syslogging stuff. 03jun01 cvoid: broke into multiple source files. 03jun01 cvoid: added logfile and getopt code. 01jun01 cvoid: created from angst source. */ #include #include #include #include #include "passlog.h" u_char buffer[BUFSIZE]; /* to store the data of a connection */ pcap_t *pd; /* packet capture descriptor */ u_int hdrlen; /* encapsulation header length */ pcap_handler callback; int debug = 0; /* global flags */ int vflag = 0; int sflag = 0; int rflag = 0; int fflag = 0; int dflag = 0; /* display flag for output formatting */ int conflag = 1; char logfile[MAXPATH]; /* log file */ int logfd; /* MAIN */ int main(int argc, char *argv[]) { int c; char logfile[MAXPATH]; /* log file */ int datalink = 0; /* link layer type */ int promisc_flag = 1; /* default to set promiscuous mode */ int flood_flag = 0; /* default to passive sniffing */ int f_flag = 1; /* enable IP forwarding flag */ int e_flag = 0; /* user supplied filter expression flag */ char expr[BUFSIZE]; /* user supplied filter expression buffer */ char filter_expr[BUFSIZE]; /* final filter expression */ bpf_u_int32 localnet, netmask;/* network number, associated netmask */ struct bpf_program filter; /* filter program */ char errbuf[PCAP_ERRBUF_SIZE];/* libpcap error handling buffer */ char *errstr; int port = 514; char filterstr[64]; char ignorestr[16]; char devstr[16]; int ignore; /* default values */ memset(devstr,0,sizeof(devstr)); char *a="any"; strncpy(devstr,a,strlen(a)); while ((c = getopt(argc, argv, "hsrdi:p:e:f::S")) != EOF) { switch (c) { case 'h': printf("passlogd %s - passive syslog capture daemon\n", VERSION); printf("copyright (c) 2005 - christian void \n\n"); printf("usage: passlogd [-hvsr][-f]\n"); printf(" -h display this message\n"); printf(" -s log captured messages to local syslog\n"); printf(" -r reverse lookup ip addresses\n"); printf(" -d debug mode\n"); printf(" -i ignore packets from \n"); printf(" -p listen for syslog packets to (default: 514)\n"); printf(" -e set the interface to listen on\n"); printf(" -f log to (default: /var/log/passlog)\n"); printf(" -S use syslog format in logfile\n\n"); printf("by default, passlogd logs all messages to stdio without performing\n"); printf("reverse lookups. packets captured and logged via syslog locally are\n"); printf("reported using the captured facility and loglevel. messages captured\n"); printf("to a logfile are written wholesale.\n"); exit(0); case 's': sflag = 1; conflag = 0; break; case 'r': rflag = 1; break; case 'i': ignore = 1; if (strlen(optarg) < sizeof(ignorestr)){ strncpy(ignorestr, optarg, strlen(optarg)); } else { printf("invalid ip address\n"); exit(-1); } break; case 'd': debug = 1; break; case 'e': if(strlen(optarg) < sizeof(devstr)){ memset(devstr,0,sizeof(devstr)); strncpy(devstr, optarg, strlen(optarg)); } else { printf("invalid device\n"); exit(-1); } break; case 'p': /* set the port in the filter program */ port = atoi(optarg); break; case 'f': fflag = 1; conflag = 0; memset(logfile, 0, MAXPATH); if(optarg){ if(strlen(optarg) < MAXPATH){ strncpy(logfile, optarg, strlen(optarg)); } else { printf("invalid filename\n"); exit(-1); } } else { /* no filename specified, use default */ strncpy(&logfile, "/var/log/passlog", 16); } break; case 'S': dflag = 1; break; default: /* by default we log to stdio */ printf("logging to console...\n"); } } if(debug){ /* dump command line paramaters */ printf("vflag: %d\n", vflag); printf("sflag: %d\n", sflag); printf("rflag: %d\n", rflag); printf("fflag: %d\n", fflag); if(fflag){ printf("file: %s\n", logfile); } } /* log our impending startup via syslog */ openlog("passlogd", 0, LOG_DAEMON); syslog(LOG_INFO, "starting..."); syslog(LOG_INFO, "listening for syslog packets sent to port %d on any host", port); if(ignore) syslog(LOG_INFO, "ignoring messages from %s", ignorestr); closelog(); init_buf(buffer, sizeof(buffer)); /* set the callback function */ callback = (pcap_handler)sl_parse; if((pd = pcap_open_live(devstr, SNAPLEN, promisc_flag, TIMEOUT, errbuf)) == NULL){ printf("pcap_open_live error: %s\n", errbuf); printf("most likely, you are not root...\n"); exit(-1); } /* determine link layer type */ if((datalink = pcap_datalink(pd)) < 0) printf("pcap_datalink error: %s\n", pcap_geterr(pd)); /* determine the header length of the link layer encapsulation */ hdrlen = find_header_length(datalink); /* get network address and subnet mask */ if((pcap_lookupnet(devstr, &localnet, &netmask, errbuf)) < 0){ localnet = netmask = 0; printf("pcap_lookupnet error: %s\n", errbuf); } /* setup out filter */ if (ignore) { sprintf(filterstr, FILTERNOT, port, ignorestr); } else { sprintf(filterstr, FILTER, port); } if((pcap_compile(pd, &filter, filterstr, 1, netmask)) < 0) printf("pcap_compile error: %s\n", pcap_geterr(pd)); /* set the filter program */ if((pcap_setfilter(pd, &filter)) < 0) printf("pcap_setfilter error: %s\n", pcap_geterr(pd)); /* open our logfile if neccessary */ if(fflag){ logfd = open(logfile, O_WRONLY|O_APPEND|O_CREAT); if(debug){ errstr = (char *) strerror(errno); printf("open return %d: %s\n", logfd, errstr); } } /* set up our signal handler - we respond to SIGTERM and cleanly */ /* close our logfile (if logging to a file) and all that other */ /* good stuff */ signal(SIGTERM, sighandle); /* collect and process packets infinite loop */ if((pcap_loop(pd, -1, callback, NULL))) printf("pcap_loop error: %s\n", pcap_geterr(pd)); return 0; }