/*
passlogd - passive syslog capture daemon
copyright (c) 2005 - christian void <cvoid@morphine.com>
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 <stdio.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#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 <cvoid@morphine.com>\n\n");
printf("usage: passlogd [-hvsr][-f<filename>]\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<ipaddr> ignore packets from <ipaddr>\n");
printf(" -p<port> listen for syslog packets to <port> (default: 514)\n");
printf(" -e<interface> set the interface to listen on\n");
printf(" -f<filename> log to <filename> (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;
}
syntax highlighted by Code2HTML, v. 0.9.1