/* 

passlogd - passive syslog capture daemon
copyright (c) 2005 - christian void <cvoid@morphine.com>

file: parse.c

history: 

11feb05 cvoid: fixed problem with -e crashing
11feb05 cvoid: fixed -e to allow 'all'
02apr03 cvoid: fixed 3 buffer overflow conditions in the parser.
07jun01 cvoid: added syslog-like output format.
07jun01 cvoid: added short packet syslog notification.
07jun01 cvoid: added call to sanitize_buffer() just in case. 
07jun01 cvoid: miscellaneous parser fixes.
04jun01 cvoid: created.

*/

#include "passlog.h"

/* globals */
extern int debug;
extern int vflag;
extern int sflag;
extern int rflag;
extern int fflag;
extern int dflag;
extern int logfd;
extern int conflag;

/* pcap callback routine for parsing packets */
/* warning: this definately needs to be rewritten */

void sl_parse(char *user, struct pcap_pkthdr *pkthdr, u_char *pkt)
{
  int i, j, wb;
  char *timestr;
  time_t curtime;
  int err = 0;
  char *errstr;
  char srcip[255];
  char dstip[255];
  char level[5];
  char message[1024];
  char buffer[4096];
  int  syslev;
  int z=0;

  /* initialize our buffers - this just has to be expensive as fuck */
  init_buf(srcip, sizeof(srcip));
  init_buf(dstip, sizeof(dstip));
  init_buf(level, sizeof(level));
  init_buf(message, sizeof(message));
  init_buf(buffer, sizeof(buffer));
  
  i = 26;
  
  if (pkthdr->caplen > 32)
    {
      sprintf(srcip, "%d.%d.%d.%d", pkt[i], pkt[i+1], pkt[i+2], pkt[i+3]);
      i=i+4;
      sprintf(dstip, "%d.%d.%d.%d", pkt[i], pkt[i+1], pkt[i+2], pkt[i+3]);
      i=i+4;
    }
  else
    {
      if(debug)
	printf("packet too short!\n");
      openlog("passlogd", 0, LOG_DAEMON);
      syslog(LOG_INFO, "received %d byte packet (too short)", pkthdr->caplen);
      closelog();
      return;
    }
  
  i=i+9;
  j=0;
  
  while(pkt[i] != '>'){
    if(j==sizeof(level)-1)
    {
	/* not ideal - we should log this */
	break;
    }
    level[j] = pkt[i];
    i++;
    j++;
  }
  i++;
 
  if(debug)
	printf("caplen: %d len: %d\n", pkthdr->caplen, pkthdr->len);
 
  while(pkt[i] != '\n' && pkt[i] != '\r' && i < (pkthdr->caplen - 1)){
	if(debug)
		printf("at byte %d of %d\n", i, pkthdr->caplen - 1);
    if(z==sizeof(message)-1)
    {
	/* not ideal - we should log this */
	break;
    }
    message[z] = pkt[i];
    i++;
    z++;
  }

  if(rflag){
    /* reverse lookup the ip addresses */
    err = reverse_lookup(srcip);
    if(debug)printf("reverse: %d\n", err);
    reverse_lookup(dstip);
    if(debug)printf("reverse: %d\n", err);
  }

  /* built the logstring */
  if(dflag){
    snprintf(buffer, sizeof(buffer)-1, "%s %s\n", srcip, message);
  }
  else {
    snprintf(buffer, sizeof(buffer)-1, "%s to %s: <%s> %s\n", srcip, dstip, level, message);
  }

  if(debug){
    wb = write(logfd, "\n\nRAW PACKET:\n", 14);
    wb = write(logfd, pkt, pkthdr->caplen - 1);
    wb = write(logfd, "\n\nPARSED PACKET:\n", 17); 
  }    

  /* sanitize the buffer */
  sanitize_buffer(buffer, sizeof(buffer));

  if(sflag){
    /* log to syslog */
    /* break out facility and priority  */
    syslev = atoi(level);
    openlog("passlogd", 0, LOG_DAEMON);
    syslog(syslev, "%s", buffer);
    closelog();
  }

  /* get current time */
  err = gettimeofday((void *) &curtime, NULL);
  timestr = ctime(&curtime);
  timestr[strlen(timestr)-1]=0x20;

  /* dump to stdio */
  if(conflag){
    printf("%s", timestr);
    printf("%s", buffer);	
  }

  if(fflag){
    /* log to logfile */
    wb = write(logfd, timestr, strlen(timestr));
    wb = write(logfd, buffer, strlen(buffer));

    if(debug){
      errstr = (char *) strerror(errno);
      printf("wrote %d bytes to logfile\n", wb);
      printf("write() returned: %s\n", errstr);
    }
  }
}


syntax highlighted by Code2HTML, v. 0.9.1