mixmaster

mixmaster 3.0 patched for libressl
git clone git://parazyd.org/mixmaster.git
Log | Files | Refs | README

stats.c (11869B)


      1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
      2 
      3    Mixmaster may be redistributed and modified under certain conditions.
      4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
      5    ANY KIND, either express or implied. See the file COPYRIGHT for
      6    details.
      7 
      8    Remailer statistics
      9    $Id: stats.c 934 2006-06-24 13:40:39Z rabbi $ */
     10 
     11 
     12 #include "mix3.h"
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <time.h>
     16 
     17 /* log that a message of type t has been received. Statistics for type 2
     18    messages are taken from the IDLOG instead of calling this function */
     19 int stats_log(int t)
     20 {
     21   FILE *f;
     22 
     23   f = mix_openfile(STATS, "a");
     24   if (f == NULL) {
     25     errlog(ERRORMSG, "Can't open %s!\n", STATS);
     26     return (-1);
     27   }
     28   lock(f);
     29   fprintf(f, "%d 1 %ld\n", t, (long) time(NULL));
     30   unlock(f);
     31   fclose(f);
     32   return (0);
     33 }
     34 
     35 /* log the current pool size after sending messages */
     36 int stats_out(int pool)
     37 {
     38   FILE *f;
     39 
     40   if (REMAIL == 0)
     41     return (0); /* don't keep statistics for the client */
     42 
     43   f = mix_openfile(STATS, "a");
     44   if (f == NULL) {
     45     errlog(ERRORMSG, "Can't open %s!\n", STATS);
     46     return (-1);
     47   }
     48   lock(f);
     49   fprintf(f, "p 1 %d %ld\n", pool, (long) time(NULL));
     50   unlock(f);
     51   fclose(f);
     52   return (0);
     53 }
     54 
     55 int stats(BUFFER *b)
     56 {
     57   FILE *s, *f;
     58   char line[LINELEN];
     59   long now, today, then;
     60   time_t t;
     61   long updated = 0, havestats = 0;
     62   int msgd[7][24], msg[7][80];
     63   /* 0 .. Unencrypted
     64    * 1 .. Type I PGP
     65    * 2 .. Mix
     66    *
     67    * 3 .. intermediate
     68    * 4 .. final hop mail
     69    * 5 .. final hop news
     70    * 6 .. randhopped (will get counted in intermediate again)
     71    */
     72   int poold[2][24], pool[2][80];
     73   int i, num, type, assigned, daysum;
     74   char c;
     75   idlog_t idbuf;
     76 
     77   now = (time(NULL) / (60 * 60) + 1) * 60 * 60;
     78   today = (now / SECONDSPERDAY) * SECONDSPERDAY;
     79 
     80   for (i = 0; i < 24; i++)
     81     msgd[0][i] = msgd[1][i] = msgd[2][i] = msgd[3][i] = msgd[4][i] = msgd[5][i] = msgd[6][i]= poold[0][i] = poold[1][i] = 0;
     82   for (i = 0; i < 80; i++)
     83     msg[0][i] = msg[1][i] = msg[2][i] = msg[3][i] = msg[4][i] = msg[5][i] = msg[6][i] = pool[0][i] = pool[1][i] = 0;
     84 
     85   s = mix_openfile(STATS, "r");
     86   if (s != NULL) {
     87     lock(s);
     88     fscanf(s, "%ld", &updated);
     89     while (fgets(line, sizeof(line), s) != NULL) {
     90       switch (line[0]) {
     91       case '0':
     92       case '1':
     93       case '2':
     94       case '3':
     95       case '4':
     96       case '5':
     97       case '6':
     98 	c = '\0';
     99 	assigned = sscanf(line, "%d %d %ld %c", &type, &num, &then, &c);
    100 	daysum = (assigned == 4 && c == 'd');
    101 
    102 	if (now - then < 0 || (daysum && today - then < 0))
    103 	  break;		/* keep memory consistent even if the time
    104 				   suddenly goes backwards :) */
    105 	if (now - then < SECONDSPERDAY && !daysum)
    106 	  msgd[type][(now - then) / (60 * 60)] += num;
    107 	else if (today - then < 80 * SECONDSPERDAY)
    108 	  msg[type][(today - then) / SECONDSPERDAY] += num;
    109 	if (havestats == 0 || then < havestats)
    110 	  havestats = then;
    111 	break;
    112       case 'p':
    113 	c = '\0';
    114 	assigned = sscanf(line, "p %d %d %ld %c", &num, &i, &then, &c);
    115 	daysum = (assigned == 4 && c == 'd');
    116 
    117 	if (now - then < 0 || (daysum && today - then < 0))
    118 	  break;
    119 	if (now - then < SECONDSPERDAY && !daysum) {
    120 	  poold[0][(now - then) / (60 * 60)] += num;
    121 	  poold[1][(now - then) / (60 * 60)] += i;
    122 	} else if (today - then < 80 * SECONDSPERDAY) {
    123 	  pool[0][(today - then) / (24 * 60 * 60)] += num;
    124 	  pool[1][(today - then) / (24 * 60 * 60)] += i;
    125 	}
    126 	if (havestats == 0 || then < havestats)
    127 	  havestats = then;
    128 	break;
    129       }
    130     }
    131     unlock(s);
    132     fclose(s);
    133   }
    134   f = mix_openfile(IDLOG, "rb");
    135   if (f != NULL) {
    136     while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
    137       then = idbuf.time;
    138       if (then < updated || now - then < 0)
    139 	continue;
    140       if (now - then < SECONDSPERDAY)
    141 	msgd[2][(now - then) / (60 * 60)]++;
    142       else if (today - then < 80 * SECONDSPERDAY)
    143 	msg[2][(today - then) / SECONDSPERDAY]++;
    144       if (havestats == 0 || then < havestats)
    145 	havestats = then;
    146     }
    147     fclose(f);
    148   }
    149   if (havestats == 0) {
    150     if (b != NULL)
    151       errlog(NOTICE, "No statistics available.\n");
    152     return (-1);
    153   }
    154   s = mix_openfile(STATS, "w");
    155   if (s == NULL) {
    156     errlog(ERRORMSG, "Can't create %s!\n", STATS);
    157     return (-1);
    158   }
    159   lock(s);
    160   fprintf(s, "%ld\n", (long) time(NULL));	/* time of stats.log update */
    161   for (i = 0; i < 24; i++) {
    162     for (type = 0; type < 7; type++)
    163       if (msgd[type][i] > 0)
    164 	fprintf(s, "%d %d %ld\n", type, msgd[type][i], now - i * 60 * 60);
    165     if (poold[0][i] > 0)
    166       fprintf(s, "p %d %d %ld\n", poold[0][i], poold[1][i], now - i * 60 * 60);
    167   }
    168   for (i = 0; i < 80; i++) {
    169     for (type = 0; type < 7; type++)
    170       if (msg[type][i] > 0)
    171 	fprintf(s, "%d %d %ld d\n", type, msg[type][i],
    172 		today - i * 24 * 60 * 60);
    173     if (pool[0][i] > 0)
    174       fprintf(s, "p %d %d %ld d\n", pool[0][i], pool[1][i],
    175 	      today - i * 24 * 60 * 60);
    176   }
    177   unlock(s);
    178   fclose(s);
    179   if (b != NULL) {
    180     struct tm *gt;
    181 
    182     buf_sets(b, "Subject: Statistics for the ");
    183     buf_appends(b, SHORTNAME);
    184     buf_appends(b, " remailer\n\n");
    185 
    186     buf_appends(b, "Number of messages in the past 24 hours:\n");
    187     t = now;
    188     gt = gmtime(&t);
    189     for (i = 23; i >= 0; i--) {
    190       buf_appendf(b, "   %2dh: ", (24 + gt->tm_hour - i) % 24);
    191       if (MIX) {
    192 	if (PGP || UNENCRYPTED)
    193 	  buf_appends(b, "   Mix:");
    194 	buf_appendf(b, "%4d", msgd[2][i]);
    195       }
    196       if (PGP)
    197 	buf_appendf(b, "     PGP: %4d", msgd[1][i]);
    198       if (UNENCRYPTED)
    199 	buf_appendf(b, "     Unencrypted:%4d", msgd[0][i]);
    200       if (poold[0][i] > 0)
    201 	buf_appendf(b, "  [Pool size:%4d]", poold[1][i] / poold[0][i]);
    202 #if 0
    203       else
    204 	buf_appends(b, "  [ no remailing ]");
    205 #endif /* 0 */
    206       buf_nl(b);
    207     }
    208     if ((today - havestats) / SECONDSPERDAY >= 1)
    209       buf_appends(b, "\nNumber of messages per day:\n");
    210     for ((i = (today - havestats) / SECONDSPERDAY) > 79 ? 79 : i;
    211 	 i >= 1; i--) {
    212       t = now - i * SECONDSPERDAY;
    213       gt = gmtime(&t);
    214       strftime(line, LINELEN, "%d %b: ", gt);
    215       buf_appends(b, line);
    216 
    217       if (MIX) {
    218 	if (PGP || UNENCRYPTED)
    219 	  buf_appends(b, "   Mix:");
    220 	buf_appendf(b, "%4d", msg[2][i]);
    221       }
    222       if (PGP)
    223 	buf_appendf(b, "     PGP: %4d", msg[1][i]);
    224       if (UNENCRYPTED)
    225 	buf_appendf(b, "     Unencrypted:%4d", msg[0][i]);
    226       if (STATSDETAILS) {
    227 	buf_appendf(b, "  Intermediate:%4d", msg[3][i]);
    228 	buf_appendf(b, "  Mail:%4d", msg[4][i]);
    229 	buf_appendf(b, "  Postings:%4d", msg[5][i]);
    230 	if (MIDDLEMAN)
    231 	  buf_appendf(b, "  Randhopped:%4d", msg[6][i]);
    232       }
    233       if (pool[0][i] > 0)
    234 	buf_appendf(b, "  [Pool size:%4d]", pool[1][i] / pool[0][i]);
    235 #if 0
    236       else
    237 	buf_appends(b, "  [ no remailing ]");
    238 #endif /* 0 */
    239       buf_nl(b);
    240     }
    241   }
    242   return (0);
    243 }
    244 
    245 int conf(BUFFER *out)
    246 {
    247   FILE *f;
    248   BUFFER *b, *line;
    249   int flag = 0;
    250   REMAILER remailer[MAXREM];
    251   int pgpkeyid[MAXREM];
    252   int i, num;
    253   char tmpline[LINELEN];
    254 
    255   b = buf_new();
    256   line = buf_new();
    257 
    258   buf_sets(out, "Subject: Capabilities of the ");
    259   buf_appends(out, SHORTNAME);
    260   buf_appends(out, " remailer\n\n");
    261   buf_appends(out, remailer_type);
    262   buf_appends(out, VERSION);
    263   buf_nl(out);
    264 
    265   if (MIX + PGP + UNENCRYPTED == 1)
    266     buf_appends(out, "Supported format:");
    267   else
    268     buf_appends(out, "Supported formats:\n");
    269   if (MIX)
    270     buf_appends(out, "   Mixmaster\n");
    271   if (PGP)
    272     buf_appends(out, "   Cypherpunk with PGP encryption\n");
    273   if (UNENCRYPTED)
    274     buf_appends(out, "   Cypherpunk (unencrypted)\n");
    275 
    276   buf_appendf(out, "Pool size: %d\n", POOLSIZE);
    277   if (SIZELIMIT)
    278     buf_appendf(out, "Maximum message size: %d kB\n", SIZELIMIT);
    279 
    280   /* display destinations to which delivery is explicitly permitted
    281      when in middleman mode (contents of DESTALLOW file.)  */
    282 
    283   if (MIDDLEMAN) {
    284     f = mix_openfile(DESTALLOW, "r");
    285     if (f != NULL) {
    286       buf_read(b, f);
    287       fclose(f);
    288       while(buf_getline(b, line) != -1) {
    289 	if (line->length > 0 && line->data[0] != '#') {
    290 	  if (flag == 0) {
    291 	    buf_appends(out, "In addition to other remailers, this remailer also sends mail to these\n addresses directly:\n");
    292 	    flag = 1;
    293 	  }
    294 	  buf_appendf(out, "   %b\n", line);
    295 	}
    296       }
    297     }
    298   }
    299 
    300   flag = 0;
    301   f = mix_openfile(HDRFILTER, "r");
    302   if (f != NULL) {
    303     buf_read(b, f);
    304     fclose(f);
    305     while(buf_getline(b, line) != -1)
    306       if (line->length > 0 && line->data[0] != '#') {
    307 	if (flag == 0) {
    308 	  buf_appends(out, "The following header lines will be filtered:\n");
    309 	  flag = 1;
    310 	}
    311 	buf_appends(out, "   ");
    312 	if (line->length > 3 && streq(line->data + line->length - 2, "/q")) {
    313 	  buf_append(out, line->data, line->length - 1);
    314 	  buf_appends(out, " => delete message");
    315 	}
    316 	else
    317 	  buf_cat(out, line);
    318 	buf_nl(out);
    319       }
    320     buf_free(b);
    321   }
    322   flag = 0;
    323   b = readdestblk( );
    324   if ( b != NULL ) {
    325     while(buf_getline(b, line) != -1)
    326       if (line->length > 0 && !bufleft(line, "#") && !buffind(line, "@")) {
    327 	/* mail addresses are not listed */
    328 	if (flag == 0) {
    329 	  if (NEWS[0])
    330 	    buf_appends(out,
    331 			"The following newsgroups/domains are blocked:\n");
    332 	  else
    333 	    buf_appends(out, "The following domains are blocked:\n");
    334 	  flag = 1;
    335 	}
    336 	buf_appendf(out, "   %b\n", line);
    337       }
    338     if (flag == 0 && NEWS[0])
    339       buf_appends(out, "Note that other newsgroups may be unavailable at the remailer's news server.\n");
    340   }
    341 
    342   buf_nl(out);
    343   conf_premail(out);
    344 
    345   if (LISTSUPPORTED) {
    346    /* SUPPORTED CPUNK (TYPE I) REMAILERS
    347     * 0xDC7532F9	"Heex Remailer <remailer@xmailer.ods.org>"
    348     * 0x759ED311	"znar <ka5tkn@cox-internet.com>"
    349     *
    350     * SUPPORTED MIXMASTER (TYPE II) REMAILERS
    351     * aarg remailer@aarg.net 475f3f9fe8da22896c10082695a92c2d 2.9b33 C
    352     * anon mixmaster@anon.978.org 7384ba1eec585bfd7d2b0e9b307f0b1d 2.9b36 MCNm
    353     */
    354 
    355     buf_nl(out);
    356 #ifdef USE_PGP
    357     if (PGP) {
    358       buf_appends(out, "SUPPORTED CPUNK (TYPE I) REMAILERS\n");
    359       num = t1_rlist(remailer, NULL);
    360       pgp_rkeylist(remailer, pgpkeyid, num);
    361       for (i=1; i<=num; i++) {
    362 	if (remailer[i].flags.pgp) {
    363 	  snprintf(tmpline, LINELEN, "0x%08X	\"%s <%s>\"\n", pgpkeyid[i], remailer[i].name, remailer[i].addr);
    364 	  tmpline[LINELEN-1] = '\0';
    365 	  buf_appends(out, tmpline);
    366 	}
    367       }
    368       buf_nl(out);
    369     }
    370 #endif /* USE_PGP */
    371     if (MIX) {
    372       buf_appends(out, "SUPPORTED MIXMASTER (TYPE II) REMAILERS\n");
    373       prepare_type2list(out);
    374       buf_nl(out);
    375     }
    376   }
    377 
    378 
    379   if ( b ) buf_free(b);
    380   buf_free(line);
    381   return (0);
    382 }
    383 
    384 void conf_premail(BUFFER *out)
    385 {
    386   buf_appends(out, "$remailer{\"");
    387   buf_appends(out, SHORTNAME);
    388   buf_appends(out, "\"} = \"<");
    389   buf_appends(out, REMAILERADDR);
    390   buf_appendc(out, '>');
    391   if (PGP || UNENCRYPTED)
    392     buf_appends(out, " cpunk max");
    393   if (MIX)
    394     buf_appends(out, " mix");
    395   if (MIDDLEMAN)
    396     buf_appends(out, " middle");
    397   if (PGP)
    398     buf_appends(out, " pgp");
    399   if (PGP && !UNENCRYPTED)
    400     buf_appends(out, " pgponly");
    401   if (PGP && REPGP) {
    402     if (REMIX == 1)
    403       buf_appends(out, " repgp");
    404     else
    405       buf_appends(out, " repgp2");
    406   }
    407   if (REMIX == 1)
    408     buf_appends(out, " remix");
    409   else if (REMIX)
    410     buf_appends(out, " remix2");
    411   if (PGP || UNENCRYPTED)
    412     buf_appends(out, " latent hash cut test");
    413   if (PGP) {
    414 #ifdef USE_IDEA
    415     buf_appends(out, " ek");
    416 #endif /* USE_IDEA */
    417     buf_appends(out, " ekx");
    418   }
    419 #ifdef USE_IDEA
    420   buf_appends(out, " esub");
    421 #endif /* USE_IDEA */
    422 #if 0				/* obsolete */
    423 #ifdef USE_NSUB
    424   buf_appends(out, " nsub");
    425 #else /* end of USE_NSUB */
    426   buf_appends(out, " ksub");
    427 #endif /* else if not USE_NSUB */
    428 #endif /* 0 */
    429   if (INFLATEMAX)
    430     buf_appendf(out, " inflt%d", INFLATEMAX);
    431   if (MAXRANDHOPS)
    432     buf_appendf(out, " rhop%d", MAXRANDHOPS);
    433   if (POOLSIZE >= 5)
    434     buf_appends(out, " reord");
    435   if (NEWS[0])
    436     buf_appends(out, " post");
    437   if (SIZELIMIT)
    438     buf_appendf(out, " klen%d", SIZELIMIT);
    439   if (EXTFLAGS[0])
    440     buf_appendf(out, " %s", EXTFLAGS);
    441   buf_appends(out, "\";\n");
    442 }