]> git.proxmox.com Git - pmg-log-tracker.git/blobdiff - pmg-log-tracker.c
use CLIENT instead of CONNECT
[pmg-log-tracker.git] / pmg-log-tracker.c
index d1fbc145a3a58a5c692de57b7151bcb57b9a6c9d..9a6a881f473b963e0e0a94653fc1c3271b476fa3 100644 (file)
@@ -57,7 +57,7 @@
 //#define EPOOL_MAX_SIZE 128
 #define EPOOL_BLOCK_SIZE 2048
 #define EPOOL_MAX_SIZE 128
-#define MAX_LOGFILES 31
+#define MAX_LOGFILES 32
 //#define EPOOL_DEBUG 
 //#define DEBUG
 
@@ -85,6 +85,18 @@ struct _TOList {
   TOList *next;
 };
 
+#define MatchTypeQID 1
+#define MatchTypeRelLineNr 2
+
+typedef struct _MatchList MatchList;
+struct _MatchList {
+  unsigned int mtype;
+  char *id;
+  time_t ltime;
+  unsigned long rel_line_nr;
+  MatchList *next;
+};
+
 #ifdef DEBUG
   GHashTable *smtpd_debug_alloc;
   GHashTable *qmgr_debug_alloc;
@@ -125,9 +137,9 @@ typedef struct {
   time_t start;
   time_t end;
   time_t ctime;
+  MatchList *match_list;
   char *server;
   char *msgid;
-  char *qid;
   char *strmatch;
   unsigned long limit;
   unsigned long count;
@@ -145,6 +157,7 @@ typedef struct _LogList LogList;
 
 struct _LogEntry {
   const char *text;
+  unsigned long linenr;
   LogEntry *next;
 };
 
@@ -168,6 +181,10 @@ struct _SEntry {
 
   char *connect;
 
+ // time,rel_line_nr is used as cursor/ID
+  time_t ltime;
+  unsigned long rel_line_nr;
+
   //unsigned int external:1;        // not from local host
   unsigned int disconnect:1;
   unsigned int strmatch:1;
@@ -227,10 +244,10 @@ char     *epool_strndup0 (EPool *ep, const char *s, int len);
 char     *epool_strdup (EPool *ep, const char *s);
 
 void      loglist_print (LogList *loglist);
-void      loglist_add (EPool *ep, LogList *loglist, const char *text, int len);
+void      loglist_add (EPool *ep, LogList *loglist, const char *text, int len, unsigned long linenr);
 
-SEntry   *sentry_new (int pid);
-SEntry   *sentry_get (LParser *parser, int pid);
+SEntry   *sentry_new (int pid, time_t ltime, unsigned long rel_line_nr);
+SEntry   *sentry_get (LParser *parser, int pid, time_t ltime, unsigned long rel_line_nr);
 void      sentry_ref_add (SEntry *sentry, QEntry *qentry);
 int       sentry_ref_del (SEntry *sentry, QEntry *qentry);
 void      sentry_ref_finalize (LParser *parser, SEntry *sentry);
@@ -275,7 +292,7 @@ void      parser_free (LParser *parser);
 
 //#define LOGPATH "./log/"
 #define LOGPATH "/var/log/"
-//#define LOGPATH "/var/log5/"
+//#define LOGPATH "/root/testlog/"
 
 static const char *logfiles[] = {
   LOGPATH "syslog",
@@ -468,14 +485,14 @@ loglist_print (LogList *loglist)
 {
   LogEntry *log = loglist->log;
   while (log) {
-    printf ("%s", log->text);
+    printf ("L%08X %s", log->linenr, log->text);
     log = log->next;
   }
 }
 
 
 void
-loglist_add (EPool *ep, LogList *loglist, const char *text, int len)
+loglist_add (EPool *ep, LogList *loglist, const char *text, int len, unsigned long linenr)
 {
   LogEntry *log;
 
@@ -492,6 +509,7 @@ loglist_add (EPool *ep, LogList *loglist, const char *text, int len)
   log = epool_alloc (ep, sizeof (LogEntry));
 
   log->text = epool_strndup (ep, text, len);
+  log->linenr = linenr;
   log->next = NULL;
 
   if (loglist->logs_last) {
@@ -506,7 +524,7 @@ loglist_add (EPool *ep, LogList *loglist, const char *text, int len)
 }
 
 SEntry*
-sentry_new (int pid)
+sentry_new (int pid, time_t ltime, unsigned long rel_line_nr)
 {
   SEntry *sentry;
   SList *blocks;
@@ -514,6 +532,8 @@ sentry_new (int pid)
 
   sentry = (SEntry *)g_slice_alloc0(EPOOL_BLOCK_SIZE);
   sentry->pid = pid;
+  sentry->ltime = ltime;
+  sentry->rel_line_nr = rel_line_nr;
 
 #ifdef EPOOL_DEBUG
   sentry->ep.allocated += EPOOL_BLOCK_SIZE;
@@ -548,7 +568,7 @@ sentry_new (int pid)
 }
 
 SEntry *
-sentry_get (LParser *parser, int pid
+sentry_get (LParser *parser, int pid, time_t ltime, unsigned long rel_line_nr)
 {
   SEntry *sentry;
 
@@ -556,7 +576,7 @@ sentry_get (LParser *parser, int pid)
     return sentry;
   } else {
 
-    if ((sentry = sentry_new (pid))) {
+    if ((sentry = sentry_new (pid, ltime, rel_line_nr))) {
       g_hash_table_insert (parser->smtpd_h, &sentry->pid, sentry);
     }
 
@@ -702,13 +722,32 @@ sentry_print (LParser *parser, SEntry *sentry)
 {
   NQList *nq;
 
-  if (parser->msgid || parser->qid) return;
+  if (parser->msgid) return;
 
   if (parser->server) {
     if (!sentry->connect) return;
     if (!strcasestr (sentry->connect, parser->server)) return;
   }
 
+  MatchList *match = parser->match_list;
+  if (match) {
+    int found = 0;
+    while(match) {
+      if (match->mtype == MatchTypeQID) {
+       return;
+      } else if (match->mtype == MatchTypeRelLineNr) {
+       if (match->ltime == sentry->ltime && match->rel_line_nr == sentry->rel_line_nr) {
+         found = 1;
+         break;
+       }
+      } else {
+       g_error("implement me");
+      }
+      match = match->next;
+    }
+    if (!found) return;
+  }
+
   if (parser->from || parser->to || 
       parser->exclude_greylist || parser->exclude_ndrs) {
     nq = sentry->nqlist;
@@ -741,11 +780,11 @@ sentry_print (LParser *parser, SEntry *sentry)
 
   if (parser->verbose) {
 
-    printf ("SMTPD:\n");
+    printf ("SMTPD: T%08lXL%08lX\n", sentry->ltime, sentry->rel_line_nr);
 
     printf ("CTIME: %08lX\n", parser->ctime);
 
-    if (sentry->connect) { printf ("CONNECT: %s\n", sentry->connect); }
+    if (sentry->connect) { printf ("CLIENT: %s\n", sentry->connect); }
     //printf ("EXTERNAL: %d\n", sentry->external);
 
   }
@@ -753,18 +792,23 @@ sentry_print (LParser *parser, SEntry *sentry)
   nq = sentry->nqlist;
   while (nq) {
     if (nq->from && nq->to && nq->dstatus) {
-      printf ("TO:%08lX:00000000000:%c: from <%s> to <%s>\n", nq->ltime, nq->dstatus, nq->from, nq->to);
+      printf ("TO:%08lX:T%08lXL%08lX:%c: from <%s> to <%s>\n", nq->ltime,
+             sentry->ltime, sentry->rel_line_nr, nq->dstatus,
+             nq->from, nq->to);
       parser->count++;
     }
     nq = nq->next;
   }
 
-  if (parser->verbose) {
+  if (!parser->verbose)  { fflush (stdout); return; }
+
+  if (parser->verbose > 1) {
     printf ("LOGS:\n");
     loglist_print (&sentry->loglist);
-    printf ("\n");
   }
 
+  printf ("\n");
+
   fflush (stdout);
 }
 
@@ -979,12 +1023,27 @@ qentry_print (LParser *parser, QEntry *qentry)
     if (strcasecmp (parser->msgid, qentry->msgid)) return;
   }
 
-  if (parser->qid) {
+  MatchList *match = parser->match_list;
+  if (match) {
     int found = 0;
-    if (fe && !strcmp (fe->logid, parser->qid)) found = 1;
-    if (!strcmp (qentry->qid, parser->qid)) found = 1;
-
-    if (!found) return;    
+    while(match) {
+      if (match->mtype == MatchTypeQID) {
+       if ((fe && !strcmp (fe->logid, match->id)) ||
+           (!strcmp (qentry->qid, match->id))) {
+         found = 1;
+         break;
+       }
+      } else if (match->mtype == MatchTypeRelLineNr) {
+       if (se && match->ltime == se->ltime && match->rel_line_nr == se->rel_line_nr) {
+         found = 1;
+         break;
+       }
+      } else {
+       g_error("implement me");
+      }
+      match = match->next;
+    }
+    if (!found) return;
   }
 
   if (parser->server) {
@@ -1032,7 +1091,11 @@ qentry_print (LParser *parser, QEntry *qentry)
     printf ("CTIME: %08lX\n", parser->ctime);
     printf ("SIZE: %u\n", qentry->size);
 
-    if (qentry->client) { printf ("CLIENT: %s\n", qentry->client); }
+    if (qentry->client) {
+      printf ("CLIENT: %s\n", qentry->client);
+    } else if (se && se->connect) {
+      printf ("CLIENT: %s\n", se->connect);
+    }
 
     if (qentry->msgid) { printf ("MSGID: %s\n", qentry->msgid); }
 
@@ -1075,24 +1138,22 @@ qentry_print (LParser *parser, QEntry *qentry)
 
   if (!parser->verbose)  { fflush (stdout); return; }
 
-  if (se) {
+  if (parser->verbose > 1) {
 
-    if (se->loglist.log) {
+    if (se && se->loglist.log) {
       printf ("SMTP:\n");
       loglist_print (&se->loglist);
     }
-  }
 
-  if (fe) {
-    if (fe->loglist.log) {
-       printf ("FILTER: %s\n", fe->logid);
-       loglist_print (&fe->loglist);
-     }
-  }
+    if (fe && fe->loglist.log) {
+      printf ("FILTER: %s\n", fe->logid);
+      loglist_print (&fe->loglist);
+    }
 
-  if (qentry->loglist.log) {
-    printf ("QMGR:\n");
-    loglist_print (&qentry->loglist);
+    if (qentry->loglist.log) {
+      printf ("QMGR:\n");
+      loglist_print (&qentry->loglist);
+    }
   }
 
   printf ("\n");
@@ -1476,7 +1537,7 @@ parse_time (const char **text, int len)
 
   // parse month
   int csum = (line[0]<<16) + (line[1]<<8) + line[2];
-      
+
   switch (csum) {
   case 4874606: mon = 0; break;
   case 4613474: mon = 1; break;
@@ -1591,7 +1652,7 @@ parser_count_files (LParser *parser)
   const char *line;
   gzFile stream;
 
-  for (i = 0; i < MAX_LOGFILES; i++) {
+  for (i = 0; i < (MAX_LOGFILES - 1); i++) {
     cur_year = parser->year[i];
     cur_month = 0;
 
@@ -1645,10 +1706,14 @@ print_usage (const char *name)
   fprintf (stderr, "\t-e END         end time (YYYY-MM-DD HH:MM:SS)\n");
   fprintf (stderr, "\t               or seconds since epoch\n");
   fprintf (stderr, "\t-m MSGID       message ID (exact match)\n");
-  fprintf (stderr, "\t-q QID         queue ID (exact match)\n");
+  fprintf (stderr, "\t-q QID         queue ID (exact match), can be\n");
+  fprintf (stderr, "\t               specified multiple times.\n");
   fprintf (stderr, "\t-x STRING      search for strings\n");
   fprintf (stderr, "\t-l LIMIT       print max limit entries\n");
-  fprintf (stderr, "\t-v             verbose output\n");
+  fprintf (stderr, "\t-g             exclude greylist entries\n");
+  fprintf (stderr, "\t-n             exclude NDR entries\n");
+  fprintf (stderr, "\t-v             verbose output (no logs)\n");
+  fprintf (stderr, "\t-vv            verbose output with logs\n");
 }
 
 
@@ -1709,13 +1774,14 @@ main (int argc, char * const argv[])
   const char *cpos;
   int found = 0;
   int csum_prog;
-  int lines = 0;
+  unsigned long lines = 0;
+  unsigned long rel_line_nr = 0;
   char qidbuf[30];
   int i;
 
   struct tm *ltime;
   struct timeval tv;
-  time_t ctime, start, end;
+  time_t ctime, next_ctime, start, end;
 
   LParser *parser;
   int opt;
@@ -1740,7 +1806,7 @@ main (int argc, char * const argv[])
     } else if (opt == 't') {
       parser->to = epool_strdup (&parser->ep, optarg);
     } else if (opt == 'v') {
-      parser->verbose = 1;
+      parser->verbose += 1;
     } else if (opt == 'g') {
       parser->exclude_greylist = 1;
     } else if (opt == 'n') {
@@ -1752,7 +1818,21 @@ main (int argc, char * const argv[])
     } else if (opt == 'm') {
       parser->msgid = epool_strdup (&parser->ep, optarg);
     } else if (opt == 'q') {
-      parser->qid = epool_strdup (&parser->ep, optarg);
+      time_t ltime;
+      unsigned long rel_line_nr;
+      MatchList *match = (MatchList *)epool_alloc(&parser->ep, sizeof(MatchList));
+      if (sscanf(optarg, "T%08lXL%08lX", &ltime, &rel_line_nr) == 2) {
+       match->mtype = MatchTypeRelLineNr;
+       match->ltime = ltime;
+       match->rel_line_nr = rel_line_nr;
+       match->next = parser->match_list;
+       parser->match_list = match;
+      } else {
+       match->mtype = MatchTypeQID;
+       match->id = epool_strdup(&parser->ep, optarg);
+       match->next = parser->match_list;
+       parser->match_list = match;
+      }
     } else if (opt == 'x') {
       parser->strmatch = epool_strdup (&parser->ep, optarg);
     } else if (opt == 'l') {
@@ -1850,7 +1930,19 @@ main (int argc, char * const argv[])
   if (parser->to) printf ("# Recipient: %s\n", parser->to);
   if (parser->server) printf ("# Server:    %s\n", parser->server);
   if (parser->msgid) printf ("# MsgID:     %s\n", parser->msgid);
-  if (parser->qid) printf ("# QID:       %s\n", parser->qid);
+
+  MatchList *match = parser->match_list;
+  while (match) {
+    if (match->mtype == MatchTypeQID) {
+      printf ("# QID:       %s\n", match->id);
+    } else if (match->mtype == MatchTypeRelLineNr) {
+      printf ("# QID:       T%08lXL%08lX\n", match->ltime, match->rel_line_nr);
+    } else {
+      g_error("internal error - unknown match type %d\n", match->mtype);
+    }
+    match = match->next;
+  }
+
   if (parser->strmatch) printf ("# Match:     %s\n", parser->strmatch);
 
   strftime (linebuf, 256, "%F %T", gmtime (&parser->start));
@@ -1899,9 +1991,20 @@ main (int argc, char * const argv[])
       int pid = 0;
 
       cpos = line;
-      if (!(ctime = parse_time (&cpos, len))) {
+
+      next_ctime = parse_time (&cpos, len);
+
+      if (!next_ctime) {
        continue;
-      } 
+      }
+
+      if (next_ctime != ctime) {
+       rel_line_nr = 0;
+      } else {
+       rel_line_nr++;
+      }
+
+      ctime = next_ctime;
 
       if (ctime < start) continue;
       if (ctime > end) break;
@@ -1973,7 +2076,8 @@ main (int argc, char * const argv[])
        strmatch = 1;
       }
 
-      if (csum_prog == 0x6C746572) { // pmg-smtp-filter
+      if ((csum_prog == 0x70726F78) ||// proxprox
+         (csum_prog == 0x6C746572)) { // pmg-smtp-filter
 
        if ((idx1 = parse_qid (&cpos, qidbuf, ':', 25))) {
 
@@ -1983,7 +2087,7 @@ main (int argc, char * const argv[])
            continue;
          }
 
-         loglist_add (&fe->ep, &fe->loglist, line, len);
+         loglist_add (&fe->ep, &fe->loglist, line, len, lines);
 
          if (strmatch) fe->strmatch = 1;
 
@@ -2099,13 +2203,13 @@ main (int argc, char * const argv[])
          
                      if (*cpos != '>') continue;
 
-                     if (!(se = sentry_get (parser, pid))) {
+                     if (!(se = sentry_get (parser, pid, ctime, rel_line_nr))) {
                              continue;
                      }
 
                      if (strmatch) se->strmatch = 1;
 
-                     loglist_add (&se->ep, &se->loglist, line, len);
+                     loglist_add (&se->ep, &se->loglist, line, len, lines);
 
                      sentry_nqlist_add (se, ctime, from, idx1 - from, to, cpos - to, 'N');
 
@@ -2133,7 +2237,7 @@ main (int argc, char * const argv[])
 
          qe->cleanup = 1;      
 
-         loglist_add (&qe->ep, &qe->loglist, line, len);
+         loglist_add (&qe->ep, &qe->loglist, line, len, lines);
        
          if ((*idx2 == 'f') && !strncmp (idx2, "from=<", 6)) {
 
@@ -2185,7 +2289,7 @@ main (int argc, char * const argv[])
 
          qe->cleanup = 1;      
 
-         loglist_add (&qe->ep, &qe->loglist, line, len);
+         loglist_add (&qe->ep, &qe->loglist, line, len, lines);
 
          if (strncmp (cpos, "to=<", 4)) continue;
          cpos += 4;
@@ -2261,13 +2365,13 @@ main (int argc, char * const argv[])
          continue;
        }
 
-       if (!(se = sentry_get (parser, pid))) {
+       if (!(se = sentry_get (parser, pid, ctime, rel_line_nr))) {
          continue;
        }
 
        if (strmatch) se->strmatch = 1;
 
-       loglist_add (&se->ep, &se->loglist, line, len);
+       loglist_add (&se->ep, &se->loglist, line, len, lines);
 
        if ((*text == 'c') && !strncmp (text, "connect from ", 13)) {
        
@@ -2370,7 +2474,7 @@ main (int argc, char * const argv[])
 
            if (strmatch) qe->strmatch = 1;
 
-           loglist_add (&qe->ep, &qe->loglist, line, len);
+           loglist_add (&qe->ep, &qe->loglist, line, len, lines);
 
            if ((*idx2 == 'm') && !strncmp (idx2, "message-id=", 11)) {