From: Marc Lewis <marc@blarg.net>
Subject: MySQL patches for Cistron Radiusd
Date: 6 Aug 1998 23:26:45 +0200
Organization: Linux ISP List
Message-ID: <Pine.LNX.3.96.980806141823.773A-200000@fozzie.blarg.net>

Since I know of no mailing lists for the Cistron radiusd, I thought I would
share this with these lists, as I know there is a great deal of interest in
it.

This is a patch against radiusd-cistron-1.5.4.3 which adds MySQL support for
storing accounting records.

Follow the (brief) instructions in README.MySQL to set it up, and it should
be good to go.

I know that previously I had stated (on some list, somewhere) that I would
be making patches for the Livingston RADIUS 2.0 server, I will not be. 
Cistron radius has a couple of features that the Livingston server does not,
and we're going with the Cistron server.

Have fun with it...

 - Marc

-----------------------------+----------------------------------------------
Marc Lewis                   | "Skiers on crutches and chickens on springs."
System Administrator         | [whiffing sound of Gonzo arriving in a hurry]
Blarg! Online Services, Inc. | "These are a few of my favorite things!"
http://www.blarg.net         |        - Kermit the Frog and The Great Gonzo
-----------------------------+----------------------------------------------

diff -Nur radiusd-cistron-1.5.4.3-orig/README.MySQL radiusd-cistron-1.5.4.3/README.MySQL
--- radiusd-cistron-1.5.4.3-orig/README.MySQL	Wed Dec 31 16:00:00 1969
+++ radiusd-cistron-1.5.4.3/README.MySQL	Thu Aug  6 14:14:22 1998
@@ -0,0 +1,53 @@
+
+1998-08-06
+
+MySQL support is a quick hack that I had to implement for long term storage
+on an off-site database server that we use for billing purposes (measured
+service).  I'm only releasing this patch because some people want it (like
+myself).  I *will not* answer MySQL questions, Radius questions, or
+anything else relating to this patch.  This patch works for us, it may or
+may not work for you.  If it works, great.  If it doesn't, its up to you to
+find out why, I don't have the time to debug other people's setup.
+
+To include MySQL support, you first need to have a working MySQL setup, and
+the development libraries.  This patch assumes that you have installed the
+MySQL include files in $INCLUDE_PATH/mysql and the library files in
+$LIB_PATH/mysql.  Then you will need to uncomment the "MYSQL = 1" line in
+the main Makefile.  After that, "make" in the src directory should be all
+there is to it.
+
+The table layout:
+
+CREATE TABLE radacct (
+  InternalID bigint(21) DEFAULT '0' NOT NULL auto_increment,
+  AcctStatusType tinyint(4) DEFAULT '0' NOT NULL,
+  AcctSessionID char(32) DEFAULT '' NOT NULL,
+  UserName char(32) DEFAULT '' NOT NULL,
+  NASIPAddress char(24) DEFAULT '',
+  NASPortID int(11) DEFAULT '',
+  NASPortType int(11) DEFAULT '',
+  ConnectInfo char(32) DEFAULT '',
+  ServiceType int(11) DEFAULT '',
+  FramedProtocol int(11) DEFAULT '',
+  FramedIPAddress char(24) DEFAULT '',
+  AcctOutputOctets bigint(21),
+  AcctInputOctets bigint(21),
+  AcctTime timestamp,
+  PRIMARY KEY (InternalID)
+);
+
+
+A side note -- something strange I noticed while working on this patch was
+with PortSlave v1.16 that is distributed with the Linux Router Project.  If
+using the ctrlportslave to reset the line, the accounting information is
+stored correctly.  If the remote side disconnects, two stop records are
+recorded.  I don't know if this is a bug with PortSlave or with the Cistron
+radiusd package, and don't really have time to look.
+
+As I said previously, I don't support this or any other radius clients or
+servers.
+
+Good luck, and happy Radius Accounting.
+
+ - Marc Lewis
+   marc@blarg.net
diff -Nur radiusd-cistron-1.5.4.3-orig/src/Makefile radiusd-cistron-1.5.4.3/src/Makefile
--- radiusd-cistron-1.5.4.3-orig/src/Makefile	Sat Nov 22 06:51:42 1997
+++ radiusd-cistron-1.5.4.3/src/Makefile	Thu Aug  6 14:14:34 1998
@@ -27,4 +27,11 @@
 BINDIR  = /usr/local/bin
 SBINDIR = /usr/local/sbin
 
+# MYSQL   = 1
+
+ifdef MYSQL
+	CFLAGS	+= -DUSEMYSQL
+	LIBS	+= -lmysqlclient
+endif
+
 include Make.inc
diff -Nur radiusd-cistron-1.5.4.3-orig/src/acct.c radiusd-cistron-1.5.4.3/src/acct.c
--- radiusd-cistron-1.5.4.3-orig/src/acct.c	Tue Jun 23 07:13:24 1998
+++ radiusd-cistron-1.5.4.3/src/acct.c	Thu Aug  6 12:04:23 1998
@@ -25,6 +25,11 @@
 #include	<errno.h>
 #include	<sys/wait.h>
 
+#ifdef USEMYSQL
+#include	<mysql/mysql.h>
+#include	"conf.h"
+#endif
+
 #include	"radiusd.h"
 #include	"radutmp.h"
 
@@ -470,6 +475,29 @@
 	long		curtime;
 	int		ret = 0;
 	struct stat	st;
+	
+#ifdef USEMYSQL
+	MYSQL		*MySock = NULL;
+	MYSQL		MyConn;
+	char		querystr[2048];
+
+	
+	char			sqlTable[80];
+	int				sqlAcctStatusType = 0;
+	char			sqlSessionID[80] = "";
+	char			sqlUserName[80] = "";  
+	long			sqlNASIPAddress = 0;
+	int				sqlNASPortID = 0;
+	int				sqlNASPortType = 0;
+	char			sqlConnectInfo[80] = "";
+	int				sqlServiceType = 0;
+	int				sqlFramedProtocol = 0;
+	char			sqlFramedIPAddress[80] = "";
+	unsigned long	sqlAcctOutputOctets = 0;
+	unsigned long	sqlAcctInputOctets = 0;
+	char			sqlAcctTime[80] = "NULL";
+
+#endif
 
 	/*
 	 *	See if we have an accounting directory. If not,
@@ -512,6 +540,21 @@
 	/*
 	 *	Write Detail file.
 	 */
+
+	#ifdef USEMYSQL
+	if (!(MySock = mysql_connect(&MyConn, MYSQLHOST, MYSQLUSER, MYSQLPASS))) {
+		log(L_ERR, "Acct: Couldn't connect to MySQL server on %s as %s", MYSQLHOST, MYSQLUSER);
+		ret = -1;
+	} else {
+		/* Select the database */
+		if (mysql_select_db(MySock, MYSQLDBASE) == -1) {
+			log(L_ERR, "Acct: Couldn't select MySQL database %s", MYSQLDBASE);
+			mysql_close(MySock);
+			MySock = NULL;
+		}
+	}
+	#endif
+	
 	sprintf(buffer, "%s/%s/%s", radacct_dir, nasname, f ? f : "detail");
 	if((outfd = fopen(buffer, "a")) == (FILE *)NULL) {
 		log(L_ERR, "Acct: Couldn't open file %s", buffer);
@@ -529,6 +572,65 @@
 				fprint_attr_val(outfd, pair);
 				fputs("\n", outfd);
 			}
+
+			#ifdef USEMYSQL
+            /*
+             * Check the pairs to see if they are anything we are interested in.
+             */
+            switch(pair->attribute) {
+            	case PW_ACCT_STATUS_TYPE:
+            		sqlAcctStatusType = pair->lvalue;
+            		break;
+            
+                case PW_ACCT_SESSION_ID:
+                	strcpy(sqlSessionID, pair->strvalue);
+                	break;
+                	
+                case PW_USER_NAME:
+                	strcpy(sqlUserName, pair->strvalue);
+                	break;
+                	
+                case PW_NAS_IP_ADDRESS:
+                	sqlNASIPAddress = pair->lvalue;
+                	break;
+
+                case PW_NAS_PORT_ID:
+                	sqlNASPortID = pair->lvalue;
+                	break;
+
+                case PW_NAS_PORT_TYPE:
+                	sqlNASPortType = pair->lvalue;
+                	break;
+
+                case PW_CONNECT_INFO:
+                	strcpy(sqlConnectInfo, pair->strvalue);
+                	break;
+
+                case PW_SERVICE_TYPE:
+                	sqlServiceType = pair->lvalue;
+                	break;
+
+                case PW_FRAMED_PROTOCOL:
+                	sqlFramedProtocol = pair->lvalue;
+                	break;
+
+                case PW_FRAMED_IP_ADDRESS:
+                	ipaddr2str(sqlFramedIPAddress, pair->lvalue);
+                	break;
+
+                case PW_ACCT_INPUT_OCTETS:
+                	sqlAcctInputOctets = pair->lvalue;
+                	break;
+
+                case PW_ACCT_OUTPUT_OCTETS:
+                	sqlAcctOutputOctets = pair->lvalue;
+                	break;
+
+                default:
+                	break;
+            }
+            #endif
+
 			pair = pair->next;
 		}
 
@@ -551,6 +653,34 @@
 		}
 		fputs("\n", outfd);
 		fclose(outfd);
+
+		#ifdef USEMYSQL
+    	if (MySock != NULL) {
+    		strcpy(sqlTable, MYSQLTABLE);
+        	sprintf(querystr, "insert into %s values (0, %d, '%s', '%s', '%s', %d, %d, '%s', %d, %d, '%s', %ld, %ld, %s)",
+        	  sqlTable,
+        	  sqlAcctStatusType,
+        	  sqlSessionID,
+        	  sqlUserName,
+        	  nasname,
+        	  sqlNASPortID,
+        	  sqlNASPortType,
+        	  sqlConnectInfo,
+        	  sqlServiceType,
+        	  sqlFramedProtocol,
+        	  sqlFramedIPAddress,
+        	  sqlAcctOutputOctets,
+        	  sqlAcctInputOctets,
+        	  sqlAcctTime
+        	);
+        	/* log(L_ERR, "Attempting to insert record '%s'", querystr); */
+    		if (mysql_query(MySock, (const char *) querystr) < 0) {
+				log(L_ERR, "Acct: Couldn't insert SQL accounting record for record - '%s' - %s", querystr, mysql_error(MySock)); 
+    		}
+    		mysql_close(MySock);
+    	}
+		#endif
+
 	}
 
 	return ret;
diff -Nur radiusd-cistron-1.5.4.3-orig/src/conf.h radiusd-cistron-1.5.4.3/src/conf.h
--- radiusd-cistron-1.5.4.3-orig/src/conf.h	Thu Jun 18 06:05:10 1998
+++ radiusd-cistron-1.5.4.3/src/conf.h	Wed Aug  5 20:47:16 1998
@@ -40,3 +40,11 @@
 #define ASCEND_PORT_HACK
 #define ASCEND_CHANNELS_PER_LINE        23
 
+#ifdef USEMYSQL
+#define MYSQLHOST	"localhost"
+#define	MYSQLUSER	"root"
+#define	MYSQLPASS	""
+#define	MYSQLPORT	3306
+#define	MYSQLDBASE	"radacct"
+#define	MYSQLTABLE	"radacct"
+#endif
