[PATCH] Trafficaccounting in a mysql db

Christian Schulte cs at schulte.it
Wed Apr 23 14:44:59 EDT 2003


Much more efficient in high-load situations and completely configurable 
in imapd.conf now!

Do a cvs checkout of 2.2 of the date of the writing of this email. Copy 
the attached patch into the toplevel-directory and do patch -p0 < 
patchfile. After that do a cvs update to get the current versions and 
check for conflicts with the patch which must be corrected afterwards. Than

LIBS="-lmysqlclient" ./configure --...;make;make install

After make install completes successfully read imapd.conf manpage.

--Christian--
-------------- next part --------------
Index: imap/backend.c
===================================================================
RCS file: /cvs/src/cyrus/imap/backend.c,v
retrieving revision 1.7.6.17
diff -u -r1.7.6.17 backend.c
--- imap/backend.c	24 Feb 2003 17:01:15 -0000	1.7.6.17
+++ imap/backend.c	23 Apr 2003 18:38:00 -0000
@@ -259,6 +259,10 @@
     }
 
     /* r == SASL_OK on success */
+
+    prot_setlogin(s->in, userid);
+    prot_setlogin(s->out, userid);
+ 
     return r;
 }
 
@@ -308,8 +312,24 @@
     memcpy(&ret->addr, res->ai_addr, res->ai_addrlen);
     freeaddrinfo(res0);    
 
-    ret->in = prot_new(sock, 0);
-    ret->out = prot_new(sock, 1);
+    ret->in = prot_new(sock,
+                       0,
+                       "BACKEND",
+                       config_getstring(IMAPOPT_MYSQL_HOST),
+                       config_getstring(IMAPOPT_MYSQL_USER),
+                       config_getstring(IMAPOPT_MYSQL_PASS),
+                       config_getstring(IMAPOPT_MYSQL_DB),
+                       config_getstring(IMAPOPT_MYSQL_TABLE),
+                       config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    ret->out = prot_new(sock,
+                        1,
+                        "BACKEND",
+                        config_getstring(IMAPOPT_MYSQL_HOST),  
+                        config_getstring(IMAPOPT_MYSQL_USER),  
+                        config_getstring(IMAPOPT_MYSQL_PASS),  
+                        config_getstring(IMAPOPT_MYSQL_DB),  
+                        config_getstring(IMAPOPT_MYSQL_TABLE),  
+                        config_getswitch(IMAPOPT_MYSQLLOGGING) );
     ret->sock = sock;
     prot_setflushonread(ret->in, ret->out);
     
Index: imap/deliver.c
===================================================================
RCS file: /cvs/src/cyrus/imap/deliver.c,v
retrieving revision 1.164.4.7
diff -u -r1.164.4.7 deliver.c
--- imap/deliver.c	17 Apr 2003 17:00:55 -0000	1.164.4.7
+++ imap/deliver.c	23 Apr 2003 18:38:01 -0000
@@ -266,8 +266,24 @@
 	}
     }
 
-    deliver_in = prot_new(0, 0);
-    deliver_out = prot_new(1, 1);
+    deliver_in = prot_new(0,
+                          0,
+                          "DELIVER",
+                          config_getstring(IMAPOPT_MYSQL_HOST),  
+                          config_getstring(IMAPOPT_MYSQL_USER),  
+                          config_getstring(IMAPOPT_MYSQL_PASS),  
+                          config_getstring(IMAPOPT_MYSQL_DB),  
+                          config_getstring(IMAPOPT_MYSQL_TABLE),  
+                          config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    deliver_out = prot_new(1,
+                           1,
+                           "DELIVER",
+                           config_getstring(IMAPOPT_MYSQL_HOST),  
+                           config_getstring(IMAPOPT_MYSQL_USER),  
+                           config_getstring(IMAPOPT_MYSQL_PASS),  
+                           config_getstring(IMAPOPT_MYSQL_DB),  
+                           config_getstring(IMAPOPT_MYSQL_TABLE),  
+                           config_getswitch(IMAPOPT_MYSQLLOGGING) );
     prot_setflushonread(deliver_in, deliver_out);
     prot_settimeout(deliver_in, 300);
 
Index: imap/imapd.c
===================================================================
RCS file: /cvs/src/cyrus/imap/imapd.c,v
retrieving revision 1.398.2.72
diff -u -r1.398.2.72 imapd.c
--- imap/imapd.c	22 Apr 2003 15:55:13 -0000	1.398.2.72
+++ imap/imapd.c	23 Apr 2003 18:38:09 -0000
@@ -503,8 +503,24 @@
     id_getcmdline(argc, argv);
 #endif
 
-    imapd_in = prot_new(0, 0);
-    imapd_out = prot_new(1, 1);
+    imapd_in = prot_new(0,
+                        0,
+                        "IMAP",
+                        config_getstring(IMAPOPT_MYSQL_HOST),  
+                        config_getstring(IMAPOPT_MYSQL_USER),  
+                        config_getstring(IMAPOPT_MYSQL_PASS),  
+                        config_getstring(IMAPOPT_MYSQL_DB),  
+                        config_getstring(IMAPOPT_MYSQL_TABLE),  
+                        config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    imapd_out = prot_new(1,
+                         1,
+                         "IMAP",
+                         config_getstring(IMAPOPT_MYSQL_HOST),  
+                         config_getstring(IMAPOPT_MYSQL_USER),  
+                         config_getstring(IMAPOPT_MYSQL_PASS),  
+                         config_getstring(IMAPOPT_MYSQL_DB),  
+                         config_getstring(IMAPOPT_MYSQL_TABLE),  
+                         config_getswitch(IMAPOPT_MYSQLLOGGING) );
 
     /* Find out name of client host */
     salen = sizeof(imapd_remoteaddr);
@@ -597,7 +613,15 @@
     char buf[1024];
     char *p;
 
-    motd_in = prot_new(fd, 0);
+    motd_in = prot_new(fd,
+                       0,
+                       "MOTD_FILE",
+                       config_getstring(IMAPOPT_MYSQL_HOST),  
+                       config_getstring(IMAPOPT_MYSQL_USER),  
+                       config_getstring(IMAPOPT_MYSQL_PASS),  
+                       config_getstring(IMAPOPT_MYSQL_DB),  
+                       config_getstring(IMAPOPT_MYSQL_TABLE),  
+                       config_getswitch(IMAPOPT_MYSQLLOGGING) );
 
     prot_fgets(buf, sizeof(buf), motd_in);
     if ((p = strchr(buf, '\r'))!=NULL) *p = 0;
@@ -1607,6 +1631,10 @@
 		   imapd_clienthost, passwd);
 	    reply = "Anonymous access granted";
 	    imapd_userid = xstrdup("anonymous");
+
+            prot_setlogin(imapd_in, imapd_userid);
+            prot_setlogin(imapd_out, imapd_userid);
+
 	}
 	else {
 	    syslog(LOG_NOTICE, "badlogin: %s anonymous login refused",
@@ -1642,6 +1670,10 @@
     }
     else {
 	imapd_userid = xstrdup(canon_user);
+
+        prot_setlogin(imapd_in, imapd_userid);
+        prot_setlogin(imapd_out, imapd_userid);
+
 	snmp_increment_args(AUTHENTICATION_YES, 1,
 			    VARIABLE_AUTH, 0 /*hash_simple("LOGIN") */, 
 			    VARIABLE_LISTEND);
@@ -1756,6 +1788,9 @@
     }
 
     proc_register("imapd", imapd_clienthost, imapd_userid, (char *)0);
+
+    prot_setlogin(imapd_in, imapd_userid);
+    prot_setlogin(imapd_out, imapd_userid);
 
     syslog(LOG_NOTICE, "login: %s %s %s%s %s", imapd_clienthost, imapd_userid,
 	   authtype, imapd_starttls_done ? "+TLS" : "", "User logged in");
Index: imap/lmtpd.c
===================================================================
RCS file: /cvs/src/cyrus/imap/lmtpd.c,v
retrieving revision 1.99.2.30
diff -u -r1.99.2.30 lmtpd.c
--- imap/lmtpd.c	21 Apr 2003 15:49:56 -0000	1.99.2.30
+++ imap/lmtpd.c	23 Apr 2003 18:38:11 -0000
@@ -250,8 +250,24 @@
 {
     int opt;
 
-    deliver_in = prot_new(0, 0);
-    deliver_out = prot_new(1, 1);
+    deliver_in = prot_new(0,
+                          0,
+                          "LMTP",
+                          config_getstring(IMAPOPT_MYSQL_HOST),  
+                          config_getstring(IMAPOPT_MYSQL_USER),  
+                          config_getstring(IMAPOPT_MYSQL_PASS),  
+                          config_getstring(IMAPOPT_MYSQL_DB),  
+                          config_getstring(IMAPOPT_MYSQL_TABLE),  
+                          config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    deliver_out = prot_new(1,
+                           1,
+                           "LMTP",
+                           config_getstring(IMAPOPT_MYSQL_HOST),  
+                           config_getstring(IMAPOPT_MYSQL_USER),  
+                           config_getstring(IMAPOPT_MYSQL_PASS),  
+                           config_getstring(IMAPOPT_MYSQL_DB),  
+                           config_getstring(IMAPOPT_MYSQL_TABLE),  
+                           config_getswitch(IMAPOPT_MYSQLLOGGING) );
     prot_setflushonread(deliver_in, deliver_out);
     prot_settimeout(deliver_in, 360);
 
Index: imap/lmtpengine.c
===================================================================
RCS file: /cvs/src/cyrus/imap/lmtpengine.c,v
retrieving revision 1.75.4.20
diff -u -r1.75.4.20 lmtpengine.c
--- imap/lmtpengine.c	10 Apr 2003 17:55:17 -0000	1.75.4.20
+++ imap/lmtpengine.c	23 Apr 2003 18:38:13 -0000
@@ -726,7 +726,15 @@
     }
     m->size = sbuf.st_size;
     m->f = f;
-    m->data = prot_new(fileno(f), 0);
+    m->data = prot_new(fileno(f),
+                       0,
+                       "LMTP_SPOOL",
+                       config_getstring(IMAPOPT_MYSQL_HOST),  
+                       config_getstring(IMAPOPT_MYSQL_USER),  
+                       config_getstring(IMAPOPT_MYSQL_PASS),  
+                       config_getstring(IMAPOPT_MYSQL_DB),  
+                       config_getstring(IMAPOPT_MYSQL_TABLE),  
+                       config_getswitch(IMAPOPT_MYSQLLOGGING) );
 
     return 0;
 }
@@ -955,6 +963,10 @@
 						   the AUTH command */
 	ssf = 2;
 	auth_id = "postman";
+
+        prot_setlogin(pin, auth_id);
+        prot_setlogin(pout, auth_id);
+
 	sasl_setprop(cd.conn, SASL_SSF_EXTERNAL, &ssf);
 	sasl_setprop(cd.conn, SASL_AUTH_EXTERNAL, auth_id);
     } else {
@@ -1097,6 +1109,9 @@
 	      authenticated += 2;
 	      prot_printf(pout, "235 Authenticated!\r\n");
 
+              prot_setlogin(pin, user);
+              prot_setlogin(pout, user);
+
 	      /* set protection layers */
 	      prot_setsasl(pin,  cd.conn);
 	      prot_setsasl(pout, cd.conn);
@@ -1892,8 +1907,24 @@
     conn->mechs = NULL;
     conn->saslconn = NULL;
     /* setup prot layers */
-    conn->pin = prot_new(sock, 0);
-    conn->pout = prot_new(sock, 1);
+    conn->pin = prot_new(sock,
+                         0,
+                         "LMTP",
+                         config_getstring(IMAPOPT_MYSQL_HOST),  
+                         config_getstring(IMAPOPT_MYSQL_USER),  
+                         config_getstring(IMAPOPT_MYSQL_PASS),  
+                         config_getstring(IMAPOPT_MYSQL_DB),  
+                         config_getstring(IMAPOPT_MYSQL_TABLE),  
+                         config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    conn->pout = prot_new(sock,
+                          1,
+                          "LMTP",
+                          config_getstring(IMAPOPT_MYSQL_HOST),  
+                          config_getstring(IMAPOPT_MYSQL_USER),  
+                          config_getstring(IMAPOPT_MYSQL_PASS),  
+                          config_getstring(IMAPOPT_MYSQL_DB),  
+                          config_getstring(IMAPOPT_MYSQL_TABLE),  
+                          config_getswitch(IMAPOPT_MYSQLLOGGING) );
     prot_setflushonread(conn->pin, conn->pout);
 
     /* read greeting */
Index: imap/mupdate-client.c
===================================================================
RCS file: /cvs/src/cyrus/imap/mupdate-client.c,v
retrieving revision 1.32.4.12
diff -u -r1.32.4.12 mupdate-client.c
--- imap/mupdate-client.c	27 Feb 2003 18:39:43 -0000	1.32.4.12
+++ imap/mupdate-client.c	23 Apr 2003 18:38:14 -0000
@@ -201,8 +201,24 @@
     free(secprops);
 
     /* create protstream */
-    h->pin = prot_new(h->sock, 0);
-    h->pout = prot_new(h->sock, 1);
+    h->pin = prot_new(h->sock,
+                      0,
+                      "MUPDATE",
+                      config_getstring(IMAPOPT_MYSQL_HOST),  
+                      config_getstring(IMAPOPT_MYSQL_USER),  
+                      config_getstring(IMAPOPT_MYSQL_PASS),  
+                      config_getstring(IMAPOPT_MYSQL_DB),  
+                      config_getstring(IMAPOPT_MYSQL_TABLE),  
+                      config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    h->pout = prot_new(h->sock,
+                       1,
+                       "MUPDATE",
+                       config_getstring(IMAPOPT_MYSQL_HOST),  
+                       config_getstring(IMAPOPT_MYSQL_USER),  
+                       config_getstring(IMAPOPT_MYSQL_PASS),  
+                       config_getstring(IMAPOPT_MYSQL_DB),  
+                       config_getstring(IMAPOPT_MYSQL_TABLE),  
+                       config_getswitch(IMAPOPT_MYSQLLOGGING) );
 
     prot_setflushonread(h->pin, h->pout);
     prot_settimeout(h->pin, 30*60);
Index: imap/pop3d.c
===================================================================
RCS file: /cvs/src/cyrus/imap/pop3d.c,v
retrieving revision 1.122.4.30
diff -u -r1.122.4.30 pop3d.c
--- imap/pop3d.c	22 Apr 2003 15:55:15 -0000	1.122.4.30
+++ imap/pop3d.c	23 Apr 2003 18:38:16 -0000
@@ -341,8 +341,24 @@
 
     signals_poll();
 
-    popd_in = prot_new(0, 0);
-    popd_out = prot_new(1, 1);
+    popd_in = prot_new(0,
+                       0,
+                       "POP",
+                       config_getstring(IMAPOPT_MYSQL_HOST),  
+                       config_getstring(IMAPOPT_MYSQL_USER),  
+                       config_getstring(IMAPOPT_MYSQL_PASS),  
+                       config_getstring(IMAPOPT_MYSQL_DB),  
+                       config_getstring(IMAPOPT_MYSQL_TABLE),  
+                       config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    popd_out = prot_new(1,
+                        1,
+                        "POP",
+                        config_getstring(IMAPOPT_MYSQL_HOST),  
+                        config_getstring(IMAPOPT_MYSQL_USER),  
+                        config_getstring(IMAPOPT_MYSQL_PASS),  
+                        config_getstring(IMAPOPT_MYSQL_DB),  
+                        config_getstring(IMAPOPT_MYSQL_TABLE),  
+                        config_getswitch(IMAPOPT_MYSQLLOGGING) );
 
     /* Find out name of client host */
     salen = sizeof(popd_remoteaddr);
@@ -1042,6 +1058,8 @@
     syslog(LOG_NOTICE, "login: %s %s APOP %s",
 	   popd_clienthost, popd_userid, "User logged in");
 
+    prot_setlogin(popd_in, popd_userid);
+    prot_setlogin(popd_out, popd_userid);
     popd_auth_done = 1;
     openinbox();
 }
@@ -1076,6 +1094,10 @@
     }
     else {
 	popd_userid = xstrdup(p);
+
+        prot_setlogin(popd_in, popd_userid);
+        prot_setlogin(popd_out, popd_userid);
+
 	prot_printf(popd_out, "+OK Name is a valid mailbox\r\n");
     }
 }
@@ -1304,6 +1326,9 @@
     
     syslog(LOG_NOTICE, "login: %s %s %s %s", popd_clienthost, popd_userid,
 	   authtype, "User logged in");
+
+    prot_setlogin(popd_in, popd_userid);
+    prot_setlogin(popd_out, popd_userid);
 
     popd_auth_done = 1;
     openinbox();
Index: imtest/imtest.c
===================================================================
RCS file: /cvs/src/cyrus/imtest/imtest.c,v
retrieving revision 1.82.2.16
diff -u -r1.82.2.16 imtest.c
--- imtest/imtest.c	19 Apr 2003 02:01:45 -0000	1.82.2.16
+++ imtest/imtest.c	23 Apr 2003 18:38:19 -0000
@@ -2443,8 +2443,24 @@
 	}
 	
 	/* set up the prot layer */
-	pin = prot_new(sock, 0);
-	pout = prot_new(sock, 1); 
+	pin = prot_new(sock,
+                       0,
+                       "IMTEST",
+                       NULL,  
+                       NULL,  
+                       NULL,  
+                       NULL,  
+                       NULL,  
+                       0);
+	pout = prot_new(sock,
+                        1,
+                        "IMTEST",
+                        NULL,  
+                        NULL,  
+                        NULL,  
+                        NULL,  
+                        NULL,  
+                        0);
 	
 #ifdef HAVE_SSL
 	if (dossl==1) {
Index: lib/imapoptions
===================================================================
RCS file: /cvs/src/cyrus/lib/Attic/imapoptions,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 imapoptions
--- lib/imapoptions	19 Mar 2003 19:00:39 -0000	1.1.2.5
+++ lib/imapoptions	23 Apr 2003 18:38:20 -0000
@@ -574,7 +574,102 @@
 { "virtdomains", 0, SWITCH }
 /* Enable virtual domain support */
 
-/*
+{ "mysqllogging", 0, SWITCH }
+/* Enable accounting into a mysql db */
+
+{ "mysql_host", "localhost", STRING }
+/* The mysql host to connect to:
+.br
+   For every service-connection to cyrus at least 4 queries
+   to the db will be made each with theire own db connection.
+   If a user authenticates to a service two more queries are
+   done setting the provided login.
+.br
+   Example of db connection liftimes  for a typical imap
+   session:
+.br
+   1. Client establishes the IMAP connection to cyrus
+.br
+   imapd connects to mysql, issues an INSERT query for the
+   input stream and disconnects from mysql
+.br
+   imapd connects to mysql, issues an INSERT query for the
+   output stream and disconnects from mysql
+.br
+   imapd does not have any active mysql connections after that
+.br
+  2. Client authenticates successfully
+.br
+  imapd connects to mysql, issues an UPDATE query setting the
+  successfully authenticated user for the input stream and
+  disconnects from mysql
+.br
+  imapd connects to mysql, issues an UPDATE query setting the
+  successfully authenticated user for the output stream and
+  disconnects from mysql
+.br
+  imapd does not have any active mysql connections after that
+.br
+  3. Client disconnects
+.br
+  imapd connects to mysql, issues an UPDATE query setting the
+  disconnect_time and the amount of transferred bytes for the
+  input stream and disconnects from mysql
+.br
+  imapd connects to mysql, issues an UPDATE query setting the
+  disconnect_time and the amount of transferred bytes for the
+  output stream and disconnects from mysql
+.br
+  imapd terminates
+.br
+.br
+  So a typical IMAP session leads to 6 database connections.
+  Because an IMAP connection can be active for very long time,
+  the last update queries during disconnection could be done
+  hours after the first insert queries during connecting.
+  You should set a default value for the disconnect_time
+  field as an indicator for currently active connections!
+  The disconnect_time field will only be used in the last
+  query during disconnecting and so a row containing your
+  default value will indicate a currently active connection! */ 
+  
+  
+{ "mysql_user", NULL, STRING } 
+/* The mysql user to connect with */
+
+{ "mysql_pass", NULL, STRING }
+/* The mysql password to use. Defaults to no password */
+
+{ "mysql_db", "cyrus", STRING }
+/* The database to use */
+
+{ "mysql_table", "cyrus_accounting", STRING }
+/* The table to use in mysql_db. Fieldnames are hardcoded:
+.br
+.br
+   id int(11) NOT NULL auto_increment
+.br
+   login varchar(128) NOT NULL default ''
+.br
+   service varchar(30) NOT NULL default ''
+.br 
+   bytes double NOT NULL default '0'
+.br
+   type enum('IN','OUT','UNSPECIFIED') NOT NULL default 'UNSPECIFIED'
+.br
+   connect_time datetime default NULL
+.br
+   disconnect_time datetime NOT NULL default '0000-00-00 00:00:00'
+.br
+   PRIMARY KEY  (id)
+.br
+   KEY connect_time (connect_time)
+.br
+   KEY login (login)
+.br
+   KEY disconnect_time (disconnect_time)
+.br */
+
 .SH SEE ALSO
 .PP
 \fBimapd(8)\fR, \fBpop3d(8)\fR, \fBlmtpd(8)\fR, \fBtimsieved(8)\fR,
Index: lib/prot.c
===================================================================
RCS file: /cvs/src/cyrus/lib/prot.c,v
retrieving revision 1.72.4.17
diff -u -r1.72.4.17 prot.c
--- lib/prot.c	31 Mar 2003 21:48:25 -0000	1.72.4.17
+++ lib/prot.c	23 Apr 2003 18:38:22 -0000
@@ -73,6 +73,8 @@
 #include "util.h"
 #include "xmalloc.h"
 
+char buf[1024];
+
 /* Transparant protgroup structure */
 struct protgroup
 {
@@ -81,19 +83,45 @@
     struct protstream **group;
 };
 
+/* Added by mysql-accounting.patch by <cs at schulte.it>
+ * perform a mysql query
+ *
+ * store = 1: set to update the protstream->primkey member
+ * store = 0: just execute the query and log all errors which occure
+ */
+void _query_mysql(struct protstream *s, const char *query, int store) {
+    if(! mysql_init(&s->mysql) ) {
+        sprintf(buf, "MYSQL: mysql_init() failed:%s", mysql_error(&s->mysql));
+        syslog(LOG_ERR, buf);
+    }
+    else
+        if(! mysql_connect(&s->mysql, s->mysql_host, s->mysql_user, s->mysql_pass) ) {
+            sprintf(buf, "MYSQL: mysql_connect() failed:%s", mysql_error(&s->mysql));
+            syslog(LOG_ERR, buf);
+        }
+        else
+            if( mysql_query(&s->mysql, query) ) {
+                syslog(LOG_ERR, buf);
+                sprintf(buf, "MYSQL: mysql_query() failed:%s", mysql_error(&s->mysql));
+                syslog(LOG_ERR, buf);
+            }
+            else
+                if(store)
+                    s->primkey=(unsigned long)mysql_insert_id(&s->mysql);
+    mysql_close(&s->mysql);
+}
+
+
 /*
  * Create a new protection stream for file descriptor 'fd'.  Stream
  * will be used for writing iff 'write' is nonzero.
  */
-struct protstream *prot_new(fd, write)
-int fd;
-int write;
+struct protstream *prot_new(int fd,int write,const char *service,const char *mysql_host,const char *mysql_user,const char *mysql_pass,const char *mysql_db,const char *mysql_table,int mysqllogging)
 {
     struct protstream *newstream;
 
     newstream = (struct protstream *) xzmalloc(sizeof(struct protstream));
-    newstream->buf = (unsigned char *) 
-	xmalloc(sizeof(char) * (PROT_BUFSIZE));
+    newstream->buf = (unsigned char *) xmalloc(sizeof(char) * (PROT_BUFSIZE));
     newstream->buf_size = PROT_BUFSIZE;
     newstream->ptr = newstream->buf;
     newstream->maxplain = PROT_BUFSIZE;
@@ -101,9 +129,25 @@
     newstream->write = write;
     newstream->logfd = PROT_NO_FD;
     newstream->big_buffer = PROT_NO_FD;
+    newstream->bytes=0;
+    newstream->primkey=0;
+    newstream->mysql_host = mysql_host;
+    newstream->mysql_user = mysql_user;
+    newstream->mysql_pass = mysql_pass;
+    newstream->mysql_db = mysql_db;
+    newstream->mysql_table = mysql_table;
+    newstream->mysqllogging = mysqllogging;
     if(write)
 	newstream->cnt = PROT_BUFSIZE;
-
+    if(mysqllogging) {
+        sprintf(buf, "INSERT INTO %s.%s (service, bytes, type, connect_time) VALUES ('%s',%d,'%s',SYSDATE())",
+                        newstream->mysql_db,
+                        newstream->mysql_table,
+                        service,
+                        0,
+                        write ? "OUT" : "IN");
+	_query_mysql(newstream, buf, 1);
+    }
     return newstream;
 }
 
@@ -112,6 +156,7 @@
  */
 int prot_free(struct protstream *s)
 {
+
     if (s->error) free(s->error);
     free(s->buf);
 
@@ -119,9 +164,19 @@
 	map_free(&(s->bigbuf_base), &(s->bigbuf_siz));
 	close(s->big_buffer);
     }
-
+    if( s->mysqllogging ) {
+        if(s->primkey != 0) {
+            sprintf(buf,
+                    "UPDATE %s.%s SET disconnect_time=SYSDATE(),bytes=%lu WHERE id=%lu",
+                    s->mysql_db,
+                    s->mysql_table,
+                    s->bytes, s->primkey);
+	    _query_mysql(s, buf, 0);
+        }
+        else
+	    syslog(LOG_ERR, "prot_free did not have a primary db key to update the row");
+    }
     free((char*)s);
-
     return 0;
 }
 
@@ -134,6 +189,28 @@
     return 0;
 }
 
+/*
+ * Set the the authenticated userid if it is known'.
+ */
+void prot_setlogin(struct protstream *s, const char *userid)
+{
+    if( s->mysqllogging ) {
+        if( s->primkey==0 ) {
+            syslog(LOG_ERR, "prot_setlogin did not have a primary db key to update the row");
+        }
+        else {
+            sprintf(buf,
+                    "UPDATE %s.%s SET login='%s' WHERE id=%lu",
+                    s->mysql_db,
+                    s->mysql_table,
+                    userid,
+                    s->primkey);
+            _query_mysql(s, buf, 0);
+        }
+    }
+}
+
+
 #ifdef HAVE_SSL
 
 /*
@@ -499,8 +576,9 @@
 	    s->ptr = s->buf+1;
 	    s->cnt = n;
 	}
-	
+
 	if (s->cnt > 0) {
+            s->bytes+=s->cnt;
 	    if (s->logfd != -1) {
 		time_t newtime;
 		char timebuf[20];
@@ -534,6 +612,7 @@
  */
 int prot_flush(struct protstream *s) 
 {
+    s->bytes+=strlen(s->buf);
     return prot_flush_internal(s, 1);
 }
 
@@ -832,7 +911,8 @@
     assert(s->write);
     if(s->error || s->eof) return EOF;
     if(len == 0) return 0;
-    
+   
+    s->bytes+=len; 
     while (len >= s->cnt) {
 	/* XXX can we manage to write data from 'buf' without copying it
 	   to s->ptr ? */
@@ -1246,6 +1326,7 @@
     assert(s->write);
     assert(s->cnt > 0);
 
+    s->bytes+=1;
     *s->ptr++ = c;
     if (--s->cnt == 0) {
 	return prot_flush_internal(s,0);
Index: lib/prot.h
===================================================================
RCS file: /cvs/src/cyrus/lib/prot.h,v
retrieving revision 1.35.4.7
diff -u -r1.35.4.7 prot.h
--- lib/prot.h	13 Feb 2003 20:33:14 -0000	1.35.4.7
+++ lib/prot.h	23 Apr 2003 18:38:23 -0000
@@ -51,6 +51,7 @@
 #include <stdlib.h>
 
 #include <sasl/sasl.h>
+#include <mysql/mysql.h>
 
 #ifdef HAVE_SSL
 #include <openssl/ssl.h>
@@ -111,6 +112,16 @@
 
     /* For use by applications */
     void *userdata;
+
+    unsigned long primkey;
+    unsigned long bytes;
+    MYSQL mysql;
+    const char *mysql_host;
+    const char *mysql_user;
+    const char *mysql_pass;
+    const char *mysql_db;
+    const char *mysql_table;
+    int mysqllogging;
 };
 
 typedef struct prot_waitevent *prot_waiteventcallback_t(struct protstream *s,
@@ -160,11 +171,15 @@
 #define prot_IS_BLOCKING(s) ((s)->dontblock == 0)
 
 /* Allocate/free the protstream structure */
-extern struct protstream *prot_new(int fd, int write);
+extern struct protstream *prot_new(int fd,int write,const char *service,const char *mysql_host,const char *mysql_user,const char *mysql_pass,const char *mysql_db,const char *mysql_table,int mysqllogging);
+
 extern int prot_free(struct protstream *s);
 
 /* Set the telemetry logfile for a given protstream */
 extern int prot_setlog(struct protstream *s, int fd);
+
+/* Set the userid of this stream for storage in MySQL db */
+extern void prot_setlogin(struct protstream *s, const char *userid);
 
 /* Set the SASL options for a protstream (requires authentication to
  * be complete for the given sasl_conn_t */
Index: perl/sieve/lib/isieve.c
===================================================================
RCS file: /cvs/src/cyrus/perl/sieve/lib/isieve.c,v
retrieving revision 1.24.4.4
diff -u -r1.24.4.4 isieve.c
--- perl/sieve/lib/isieve.c	13 Feb 2003 20:33:28 -0000	1.24.4.4
+++ perl/sieve/lib/isieve.c	23 Apr 2003 18:38:24 -0000
@@ -151,8 +151,24 @@
   (*obj)->port = port;
 
   /* set up the prot layer */
-  (*obj)->pin = prot_new(sock, 0);
-  (*obj)->pout = prot_new(sock, 1); 
+  (*obj)->pin = prot_new(sock,
+                         0,
+                         "SIEVE",
+                         NULL,  
+                         NULL,  
+                         NULL,  
+                         NULL,  
+                         NULL,  
+                         0);
+  (*obj)->pout = prot_new(sock,
+                          1,
+                          "SIEVE",
+                          NULL,
+                          NULL,
+                          NULL,
+                          NULL,
+                          NULL,
+                          0); 
 
   return 0;
 }
Index: timsieved/parser.c
===================================================================
RCS file: /cvs/src/cyrus/timsieved/parser.c,v
retrieving revision 1.20.4.10
diff -u -r1.20.4.10 parser.c
--- timsieved/parser.c	13 Feb 2003 20:33:36 -0000	1.20.4.10
+++ timsieved/parser.c	23 Apr 2003 18:38:25 -0000
@@ -636,6 +636,9 @@
   }
   username = xstrdup(canon_user);
 
+  prot_setlogin(sieved_in, username);
+  prot_setlogin(sieved_out, username);
+
   verify_only = !strcmp(username, "anonymous");
 
   if (!verify_only) {
Index: timsieved/timsieved.c
===================================================================
RCS file: /cvs/src/cyrus/timsieved/timsieved.c,v
retrieving revision 1.40.4.12
diff -u -r1.40.4.12 timsieved.c
--- timsieved/timsieved.c	13 Feb 2003 20:33:36 -0000	1.40.4.12
+++ timsieved/timsieved.c	23 Apr 2003 18:38:26 -0000
@@ -217,8 +217,24 @@
     char hbuf[NI_MAXHOST];
 
     /* set up the prot streams */
-    sieved_in = prot_new(0, 0);
-    sieved_out = prot_new(1, 1);
+    sieved_in = prot_new(0,
+                         0,
+                         "SIEVE",
+                         config_getstring(IMAPOPT_MYSQL_HOST),
+                         config_getstring(IMAPOPT_MYSQL_USER),
+                         config_getstring(IMAPOPT_MYSQL_PASS),
+                         config_getstring(IMAPOPT_MYSQL_DB),
+                         config_getstring(IMAPOPT_MYSQL_TABLE),
+                         config_getswitch(IMAPOPT_MYSQLLOGGING) );
+    sieved_out = prot_new(1,
+                          1,
+                          "SIEVE",
+                          config_getstring(IMAPOPT_MYSQL_HOST),
+                          config_getstring(IMAPOPT_MYSQL_USER),
+                          config_getstring(IMAPOPT_MYSQL_PASS),
+                          config_getstring(IMAPOPT_MYSQL_DB),
+                          config_getstring(IMAPOPT_MYSQL_TABLE),
+                          config_getswitch(IMAPOPT_MYSQLLOGGING) );
 
     timeout = config_getint(IMAPOPT_TIMEOUT);
     if (timeout < 10) timeout = 10;


More information about the Info-cyrus mailing list