Instead of nas/port keep an MD5 of an xlated string as the key. Also update
authorkkalev <kkalev>
Fri, 8 Apr 2005 16:00:42 +0000 (16:00 +0000)
committerkkalev <kkalev>
Fri, 8 Apr 2005 16:00:42 +0000 (16:00 +0000)
rlm_ippool_tool to support the new format.
This closes Bug #42
Code changes were funded by Airdesk Inc.

src/modules/rlm_ippool/Makefile.in
src/modules/rlm_ippool/rlm_ippool.c
src/modules/rlm_ippool/rlm_ippool_tool.c

index e8572c5..81452f8 100644 (file)
@@ -9,7 +9,7 @@ RLM_INSTALL = @ippool_install@
 include ../rules.mak
 
 rlm_ippool_tool: rlm_ippool_tool.o
-       $(LIBTOOL) --mode=link $(CC) $^ $(LIBS) $(RLM_LIBS) -o $@
+       $(LIBTOOL) --mode=link $(CC) $^ $(LIBS) $(RLM_LIBS) -o $@ -L../../lib -lradius
 
 rlm_ippool_tool.8: rlm_ippool_tool.pod
        pod2man --release=" " --date="October 2nd, 2003" --center="FreeRADIUS Daemon" --section=8 rlm_ippool_tool.pod > rlm_ippool_tool.8
index 917d650..5d233f6 100644 (file)
@@ -51,6 +51,8 @@
  *   timeout configuration directive. If it is non zero then we also use that one to free entries.
  * Jul 2004, Kostas Kalevras <kkalev@noc.ntua.gr>
  * - If Pool-Name is set to DEFAULT then always run.
+ * Mar 2005, Kostas Kalevras <kkalev@noc.ntua.gr>
+ * - Make the key an MD5 of a configurable xlated string. This closes Bug #42
  */
 
 #include "config.h"
@@ -80,6 +82,7 @@
 #include "radiusd.h"
 #include "modules.h"
 #include "conffile.h"
+#include "../../include/md5.h"
 
 #include <gdbm.h>
 #include <time.h>
@@ -111,6 +114,7 @@ typedef struct rlm_ippool_t {
        char *session_db;
        char *ip_index;
        char *name;
+       char *key;
        uint32_t range_start;
        uint32_t range_stop;
        uint32_t netmask;
@@ -144,8 +148,7 @@ typedef struct ippool_info {
 } ippool_info;
 
 typedef struct ippool_key {
-       char nas[MAX_NAS_NAME_SIZE];
-       unsigned int port;
+       char key[16];
 } ippool_key;
 
 /*
@@ -160,6 +163,7 @@ typedef struct ippool_key {
 static CONF_PARSER module_config[] = {
   { "session-db", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,session_db), NULL, NULL },
   { "ip-index", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,ip_index), NULL, NULL },
+  { "key", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,key), NULL, "%{NAS-IP-Address} %{NAS-Port}" },
   { "range-start", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,range_start), NULL, "0" },
   { "range-stop", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,range_stop), NULL, "0" },
   { "netmask", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,netmask), NULL, "0" },
@@ -169,7 +173,6 @@ static CONF_PARSER module_config[] = {
   { NULL, -1, 0, NULL, NULL }
 };
 
-
 /*
  *     Do any per-module initialization that is separate to each
  *     configured instance of the module.  e.g. set up connections
@@ -261,7 +264,7 @@ static int ippool_instantiate(CONF_SECTION *conf, void **instance)
                int rcode;
                uint32_t or_result;
                char str[32];
-               const char *nas_init = "NOT_EXIST";
+               char init_str[17];
 
                DEBUG("rlm_ippool: Initializing database");
                for(i=data->range_start,j=~0;i<=data->range_stop;i++,j--){
@@ -278,8 +281,9 @@ static int ippool_instantiate(CONF_SECTION *conf, void **instance)
                                continue;
                        }
 
-                       strcpy(key.nas, nas_init);
-                       key.port = j;
+                       sprintf(init_str,"%016d",j);
+                       DEBUG("rlm_ippool: Initialized bucket: %s",init_str);
+                       memcpy(key.key, init_str,16);
                        key_datum.dptr = (char *) &key;
                        key_datum.dsize = sizeof(ippool_key);
 
@@ -331,14 +335,16 @@ static int ippool_accounting(void *instance, REQUEST *request)
        datum data_datum;
        datum save_datum;
        int acctstatustype = 0;
-       unsigned int port = ~0;
        int rcode;
-       char nas[MAX_NAS_NAME_SIZE];
        ippool_info entry;
        ippool_key key;
        int num = 0;
        VALUE_PAIR *vp;
        char str[32];
+       char key_str[17];
+       char hex_str[35];
+       char xlat_str[MAX_STRING_LEN];
+       MD5_CTX md5_context;
 
 
        if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL)
@@ -349,22 +355,18 @@ static int ippool_accounting(void *instance, REQUEST *request)
        }
        switch(acctstatustype){
                case PW_STATUS_STOP:
-                       if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)
-                               port = vp->lvalue;
-                       else {
-                               DEBUG("rlm_ippool: Could not find port number in packet. Return NOOP.");
+                       if (!radius_xlat(xlat_str,MAX_STRING_LEN,data->key, request, NULL)){
+                               DEBUG("rlm_ippool: xlat on the 'key' directive failed");
                                return RLM_MODULE_NOOP;
                        }
-                       if ((vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL)
-                               strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-                       else {
-                               if ((vp = pairfind(request->packet->vps, PW_NAS_IDENTIFIER)) != NULL)
-                                       strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-                               else {
-                                       DEBUG("rlm_ippool: Could not find nas information in packet. Return NOOP.");
-                                       return RLM_MODULE_NOOP;
-                               }
-                       }
+                       MD5Init(&md5_context);
+                       MD5Update(&md5_context, xlat_str, strlen(xlat_str));
+                       MD5Final(key_str, &md5_context);
+                       key_str[17] = '\0';
+                       lrad_bin2hex(key_str,hex_str,16);
+                       hex_str[32] = '\0';
+                       DEBUG("rlm_ippool: MD5 on 'key' directive maps to: %s",hex_str);
+                       memcpy(key.key,key_str,16);
                        break;
                default:
                        /* We don't care about any other accounting packet */
@@ -373,10 +375,7 @@ static int ippool_accounting(void *instance, REQUEST *request)
                        return RLM_MODULE_NOOP;
        }
 
-       memset(key.nas,0,MAX_NAS_NAME_SIZE);
-       strncpy(key.nas,nas,MAX_NAS_NAME_SIZE -1 );
-       key.port = port;
-       DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key.nas,key.port);
+       DEBUG("rlm_ippool: Searching for an entry for key: '%s'",xlat_str);
        key_datum.dptr = (char *) &key;
        key_datum.dsize = sizeof(ippool_key);
 
@@ -389,7 +388,7 @@ static int ippool_accounting(void *instance, REQUEST *request)
                 */
                memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
                free(data_datum.dptr);
-               DEBUG("rlm_ippool: Deallocated entry for ip/port: %s/%u",ip_ntoa(str,entry.ipaddr),port);
+               DEBUG("rlm_ippool: Deallocated entry for ip: %s",ip_ntoa(str,entry.ipaddr));
                entry.active = 0;
                entry.timestamp = 0;
                entry.timeout = 0;
@@ -455,14 +454,12 @@ static int ippool_accounting(void *instance, REQUEST *request)
 static int ippool_postauth(void *instance, REQUEST *request)
 {
        rlm_ippool_t *data = (rlm_ippool_t *) instance;
-       unsigned int port = 0;
        int delete = 0;
        int found = 0;
        int mppp = 0;
        int extra = 0;
        int rcode;
        int num = 0;
-       char nas[MAX_NAS_NAME_SIZE];
        datum key_datum;
        datum nextkey;
        datum data_datum;
@@ -472,6 +469,10 @@ static int ippool_postauth(void *instance, REQUEST *request)
        VALUE_PAIR *vp;
        char *cli = NULL;
        char str[32];
+       char key_str[17];
+       char hex_str[35];
+       char xlat_str[MAX_STRING_LEN];
+       MD5_CTX md5_context;
 
 
        /* quiet the compiler */
@@ -489,20 +490,6 @@ static int ippool_postauth(void *instance, REQUEST *request)
                return RLM_MODULE_NOOP;
        }
 
-       /*
-        * Get the nas ip address
-        * If not fail
-        */
-       if ((vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL)
-               strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-       else{
-               if ((vp = pairfind(request->packet->vps, PW_NAS_IDENTIFIER)) != NULL)
-                       strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-               else{
-                       DEBUG("rlm_ippool: Could not find nas information. Return NOOP.");
-                       return RLM_MODULE_NOOP;
-               }
-       }
 
        /*
         * Find the caller id
@@ -510,21 +497,21 @@ static int ippool_postauth(void *instance, REQUEST *request)
        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
                cli = vp->strvalue;
 
-       /*
-        * Find the port
-        * If not fail
-        */
-       if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)
-               port = vp->lvalue;
-       else{
-               DEBUG("rlm_ippool: Could not find nas port information. Return NOOP.");
+
+       if (!radius_xlat(xlat_str,MAX_STRING_LEN,data->key, request, NULL)){
+               DEBUG("rlm_ippool: xlat on the 'key' directive failed");
                return RLM_MODULE_NOOP;
        }
-
-       memset(key.nas,0,MAX_NAS_NAME_SIZE);
-       strncpy(key.nas,nas,MAX_NAS_NAME_SIZE -1 );
-       key.port = port;
-       DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key.nas,key.port);
+       MD5Init(&md5_context);
+       MD5Update(&md5_context, xlat_str, strlen(xlat_str));
+       MD5Final(key_str, &md5_context);
+       key_str[17] = '\0';
+       lrad_bin2hex(key_str,hex_str,16);
+       hex_str[32] = '\0';
+       DEBUG("rlm_ippool: MD5 on 'key' directive maps to: %s",hex_str);
+       memcpy(key.key,key_str,16);
+
+       DEBUG("rlm_ippool: Searching for an entry for key: '%s'",hex_str);
        key_datum.dptr = (char *) &key;
        key_datum.dsize = sizeof(ippool_key);
 
@@ -539,7 +526,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
                free(data_datum.dptr);
                if (entry.active){
-                       DEBUG("rlm_ippool: Found a stale entry for ip/port: %s/%u",ip_ntoa(str,entry.ipaddr),port);
+                       DEBUG("rlm_ippool: Found a stale entry for ip: %s",ip_ntoa(str,entry.ipaddr));
                        entry.active = 0;
                        entry.timestamp = 0;
                        entry.timeout = 0;
@@ -629,15 +616,12 @@ static int ippool_postauth(void *instance, REQUEST *request)
                                memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
                                free(data_datum.dptr);
                                /*
-                               * If we find an entry for the same caller-id and nas with active=1
+                               * If we find an entry for the same caller-id with active=1
                                * then we use that for multilink (MPPP) to work properly.
                                */
                                if (strcmp(entry.cli,cli) == 0 && entry.active){
-                                       memcpy(&key,key_datum.dptr,sizeof(ippool_key));
-                                       if (!strcmp(key.nas,nas)){
-                                               mppp = 1;
-                                               break;
-                                       }
+                                       mppp = 1;
+                                       break;
                                }
                        }
                        nextkey = gdbm_nextkey(data->gdbm, key_datum);
@@ -671,7 +655,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                                         * If we find an entry in the ip index and the number is zero (meaning
                                         * that we haven't allocated the same ip address to another nas/port pair)
                                         * or if we don't find an entry then delete the session entry so
-                                        * that we can change the key (nas/port)
+                                        * that we can change the key
                                         * Else we don't delete the session entry since we haven't yet deallocated the
                                         * corresponding ip address and we continue our search.
                                         */
@@ -720,10 +704,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                        datum data_datum_tmp;
                        ippool_key key_tmp;
 
-                       memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);
-                       strncpy(key_tmp.nas,nas,MAX_NAS_NAME_SIZE -1 );
-                       key_tmp.port = port;
-                       DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key_tmp.nas,key_tmp.port);
+                       memcpy(key_tmp.key,key_str,16);
                        key_datum_tmp.dptr = (char *) &key_tmp;
                        key_datum_tmp.dsize = sizeof(ippool_key);
 
@@ -778,13 +759,11 @@ static int ippool_postauth(void *instance, REQUEST *request)
                        entry.extra = 1;
                data_datum.dptr = (char *) &entry;
                data_datum.dsize = sizeof(ippool_info);
-               memset(key.nas,0,MAX_NAS_NAME_SIZE);
-               strncpy(key.nas,nas,MAX_NAS_NAME_SIZE - 1);
-               key.port = port;
+               memcpy(key.key, key_str, 16);
                key_datum.dptr = (char *) &key;
                key_datum.dsize = sizeof(ippool_key);
 
-               DEBUG2("rlm_ippool: Allocating ip to nas/port: %s/%u",key.nas,key.port);
+               DEBUG2("rlm_ippool: Allocating ip to key: '%s'",hex_str);
                rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);
                if (rcode < 0) {
                        radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
@@ -816,8 +795,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                pthread_mutex_unlock(&data->op_mutex);
 
 
-               DEBUG("rlm_ippool: Allocated ip %s to client on nas %s,port %u",ip_ntoa(str,entry.ipaddr),
-                               key.nas,port);
+               DEBUG("rlm_ippool: Allocated ip %s to client key: %s",ip_ntoa(str,entry.ipaddr),hex_str);
                if ((vp = paircreate(PW_FRAMED_IP_ADDRESS, PW_TYPE_IPADDR)) == NULL) {
                        radlog(L_ERR|L_CONS, "no memory");
                        return RLM_MODULE_FAIL;
@@ -857,6 +835,7 @@ static int ippool_detach(void *instance)
        gdbm_close(data->gdbm);
        gdbm_close(data->ip);
        free(data->session_db);
+       free(data->key);
        free(data->ip_index);
        pthread_mutex_destroy(&data->op_mutex);
 
index e6a1b75..99cfedc 100755 (executable)
@@ -53,6 +53,7 @@
  SUCH DAMAGE.
 */
 
+#include "libradius.h"
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -63,6 +64,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include "../../include/md5.h"
 
 int active=0;
 
@@ -71,6 +73,8 @@ int cflag=0;
 int rflag=0;
 int vflag=0;
 int nflag=0;
+int oflag=0;
+int uflag=0;
 
 typedef struct ippool_info {
     uint32_t        ipaddr;
@@ -81,26 +85,33 @@ typedef struct ippool_info {
 
 
 #define MAX_NAS_NAME_SIZE 64
-typedef struct ippool_key {
+typedef struct old_ippool_key {
     char nas[MAX_NAS_NAME_SIZE];
     unsigned int port;
+} old_ippool_key;
+typedef struct ippool_key {
+    char key[16];
 } ippool_key;
 
 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
 
-void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport);
-void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress);
+void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport,int old);
+void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old);
+void tonewformat(char *sessiondbname,char *newsessiondbname);
 void usage(char *argv0);
 
-void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport) {
+void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport, int old) {
     GDBM_FILE sessiondb;
     GDBM_FILE indexdb;
     datum key_datum,data_datum,save_datum;
        datum nextkey;
     ippool_key key;
+    old_ippool_key old_key;
     ippool_info entry;
     struct in_addr ipaddr;
+    char key_str[17];
+    char hex_str[35];
     int num=0;
        int mppp=0;
     int mode=GDBM_WRITER;
@@ -136,11 +147,28 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
 
        /* Basically from rlm_ippool.c */
 
-       memset(key.nas,0,MAX_NAS_NAME_SIZE);
-       strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
-       key.port = port;
-       key_datum.dptr = (char *) &key;
-       key_datum.dsize = sizeof(ippool_key);
+       if (old){
+               memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
+               strncpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
+               old_key.port = port;
+               key_datum.dptr = (char *) &old_key;
+               key_datum.dsize = sizeof(old_ippool_key);
+       }
+       else{
+               char md5_input_str[MAX_STRING_LEN];
+               MD5_CTX md5_context;
+
+               snprintf(md5_input_str,MAX_STRING_LEN, "%s %s",NASname,NASport);
+               MD5Init(&md5_context);
+               MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
+               MD5Final(key_str, &md5_context);
+               memcpy(key.key,key_str,16);
+               lrad_bin2hex(key_str,hex_str,16);
+               hex_str[32] = '\0';
+               key_datum.dptr = (char *) &key;
+               key_datum.dsize = sizeof(ippool_key);
+       }
+               
 
        data_datum = gdbm_fetch(sessiondb, key_datum);
        if (data_datum.dptr != NULL){
@@ -148,8 +176,11 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
                free(data_datum.dptr);
                if (entry.active){
-                       printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
+                       if (old)
+                               printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
                                        ipaddress, port);
+                       else
+                               printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
                        entry.active = 0;
                        save_datum.dptr = key_datum.dptr;
                        save_datum.dsize = key_datum.dsize;
@@ -205,8 +236,14 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                                * then we use that for multilink (MPPP) to work properly.
                                */
                                if (strcmp(entry.cli,cli) == 0 && entry.active){
-                                       memcpy(&key,key_datum.dptr,sizeof(ippool_key));
-                                       if (!strcmp(key.nas,NASname)){
+                                       if (old){
+                                               memcpy(&old_key,key_datum.dptr,sizeof(ippool_key));
+                                               if (!strcmp(old_key.nas,NASname)){
+                                                       mppp = 1;
+                                                       break;
+                                               }
+                                       }
+                                       else{
                                                mppp = 1;
                                                break;
                                        }
@@ -253,13 +290,20 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
        if (key_datum.dptr){
                if (found && ! mppp){
                        datum key_datum_tmp,data_datum_tmp;
+                       old_ippool_key old_key_tmp;
                        ippool_key key_tmp;
-                       memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);
-                       strncpy(key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
-                       key_tmp.port=port;
-                       key_datum_tmp.dptr = (char *) &key_tmp;
-                       key_datum_tmp.dsize = sizeof(ippool_key);
-
+                       if (old){
+                               memset(old_key_tmp.nas,0,MAX_NAS_NAME_SIZE);
+                               strncpy(old_key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
+                               old_key_tmp.port=port;
+                               key_datum_tmp.dptr = (char *) &old_key_tmp;
+                               key_datum_tmp.dsize = sizeof(old_ippool_key);
+                       }
+                       else{
+                               memcpy(key_tmp.key,key_str,16);
+                               key_datum_tmp.dptr = (char *) &key_tmp;
+                               key_datum_tmp.dsize = sizeof(ippool_key);
+                       }
                        data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
                        if (data_datum_tmp.dptr != NULL) {
                                rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
@@ -288,12 +332,21 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                        entry.extra=1;
                data_datum.dptr = (char *) &entry;
                data_datum.dsize = sizeof(ippool_info);
-               memset(key.nas,0,MAX_NAS_NAME_SIZE);
-               strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
-               key.port = port;
-               key_datum.dptr = (char *) &key;
-               key_datum.dsize = sizeof(ippool_key);
-               printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",key.nas,key.port);
+
+               if (old){
+                       memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
+                       strncpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
+                       old_key.port = port;
+                       key_datum.dptr = (char *) &old_key;
+                       key_datum.dsize = sizeof(old_ippool_key);
+                       printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",old_key.nas,old_key.port);
+               }
+               else{
+                       memcpy(key.key,key_str,16);
+                       key_datum.dptr = (char *) &key;
+                       key_datum.dsize = sizeof(ippool_key);
+                       printf("rlm_ippool_tool: Allocating ip to key: '%s'\n",hex_str);
+               }
                rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
                if (rcode < 0) {
                        printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
@@ -325,22 +378,80 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                        return;
                }
 
-               printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
-                               ipaddress, key.nas,port);
+               if (old)
+                       printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
+                               ipaddress, old_key.nas,port);
+               else
+                       printf("rlm_ippool_tool: Allocated ip %s to key  '%s'\n",ipaddress,hex_str);
 
        }
     gdbm_close(indexdb);
     gdbm_close(sessiondb);
 }
+void tonewformat(char *sessiondbname,char *newsessiondbname){
+    GDBM_FILE sessiondb;
+    GDBM_FILE newsessiondb;
+    datum key_datum,keynext_datum,data_datum,newkey_datum;
+    old_ippool_key old_key;
+    ippool_key key;
+    char key_str[17];
+    char hex_str[35];
+    int rcode;
+
+    sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
+    newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
+
+    if (sessiondb==NULL || newsessiondb==NULL) return;
+
+    memset(key_str,0,17);
+
+    key_datum=gdbm_firstkey(sessiondb);
+    while (key_datum.dptr) {
+       keynext_datum=gdbm_nextkey(sessiondb,key_datum);
+       if (key_datum.dsize==sizeof(struct old_ippool_key)) {
+               char md5_input_str[MAX_STRING_LEN];
+               MD5_CTX md5_context;
+
+               memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
+               snprintf(md5_input_str,MAX_STRING_LEN, "%s %d",old_key.nas,old_key.port);
+               MD5Init(&md5_context);
+               MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
+               MD5Final(key_str, &md5_context);
+               memcpy(key.key,key_str,16);
+               lrad_bin2hex(key_str,hex_str,16);
+               hex_str[32] = '\0';
+               printf("rlm_ippool_tool: Transforming pair nas/port (%s/%d) to md5 '%s'\n",
+                       old_key.nas,old_key.port,hex_str);
+               newkey_datum.dptr = (char *) &key;
+               newkey_datum.dsize = sizeof(ippool_key);
+               data_datum=gdbm_fetch(sessiondb,key_datum);
+               if (data_datum.dptr!=NULL){
+                   rcode=gdbm_store(newsessiondb,newkey_datum,data_datum,GDBM_REPLACE);
+                   if (rcode < 0) {
+                               printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
+                               gdbm_close(newsessiondb);
+                               gdbm_close(sessiondb);
+                               return;
+                       }
+               }
+       }
+       key_datum=keynext_datum;
+    }
+    gdbm_close(newsessiondb);
+    gdbm_close(sessiondb);
+}
 
-void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
+void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
     GDBM_FILE sessiondb;
     GDBM_FILE indexdb;
     datum key_datum,keynext_datum,data_datum,save_datum;
+    old_ippool_key old_key;
     ippool_key key;
     ippool_info info;
     struct in_addr ipaddr;
     int num;
+    char key_str[17];
+    char hex_str[35];
     char *ip;
     int mode=GDBM_READER;
     int rcode;
@@ -351,11 +462,16 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
 
     if (sessiondb==NULL || indexdb==NULL) return;
 
+    memset(key_str,0,17);
+
     key_datum=gdbm_firstkey(sessiondb);
     while (key_datum.dptr) {
        keynext_datum=gdbm_nextkey(sessiondb,key_datum);
-       if (key_datum.dsize==sizeof(struct ippool_key)) {
-           memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
+       if (key_datum.dsize==sizeof(struct ippool_key) || key_datum.dsize==sizeof(struct old_ippool_key)) {
+           if (old)
+                memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
+           else
+                memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
 
            data_datum=gdbm_fetch(sessiondb,key_datum);
            if (data_datum.dptr!=NULL) {
@@ -365,8 +481,16 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
                ip=inet_ntoa(ipaddr);
 
                if (info.active) active++;
-               if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
-                   printf("NAS:%s port:0x%x - ",key.nas,key.port);
+               if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
+                   if (old)
+                       printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
+                   else{
+                       memcpy(key_str,key.key,16);
+                       lrad_bin2hex(key_str,hex_str,16);
+                       hex_str[32] = '\0';
+                       printf("KEY: '%s' - ",hex_str);
+                   }
+               }
                if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
                    printf("%s\n",ip);
                else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
@@ -425,8 +549,16 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
                if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
                    printf("\n");
            } else
-               if (vflag && ipaddress==NULL)
-                   printf("NAS:%s port:0x%x\n",key.nas,key.port);
+               if (vflag && ipaddress==NULL){
+                   if (old)
+                       printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
+                   else{
+                       memcpy(key_str,key.key,16);
+                       lrad_bin2hex(key_str,hex_str,16);
+                       hex_str[32] = '\0';
+                       printf("KEY: '%s' - ",hex_str);
+                   }
+               }
        }
        key_datum=keynext_datum;
     }
@@ -435,15 +567,18 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
 }
 
 void usage(char *argv0) {
-    printf("Usage: %s [-a] [-c] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
+    printf("Usage: %s [-a] [-c] [-o] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
     printf("-a: print all active entries\n");
     printf("-c: report number of active entries\n");
     printf("-r: remove active entries\n");
     printf("-v: verbose report of all entries\n");
+    printf("-o: Assume old database format (nas/port pair, not md5 output)\n");
     printf("If an ipaddress is specified then that address is used to\n");
     printf("limit the actions or output.\n");
     printf("Usage: %s -n  <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
     printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
+    printf("Usage: %s -u <session-db> <new-session-db>\n",argv0);
+    printf("-u: Update old format database to new.\n");
     exit(0);
 }
 
@@ -451,24 +586,28 @@ int main(int argc,char **argv) {
     int ch;
     char *argv0=argv[0];
 
-    while ((ch=getopt(argc,argv,"acrvn"))!=-1)
+    while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
        switch (ch) {
        case 'a': aflag++;break;
        case 'c': cflag++;break;
        case 'r': rflag++;break;
        case 'v': vflag=1;break;
        case 'n': nflag=1;break;
+       case 'o': oflag=1;break;
+       case 'u': uflag=1;break;
        default: usage(argv0);
        }
     argc -= optind;
     argv += optind;
 
-    if ((argc==2 || argc==3) && !nflag) {
-               viewdb(argv[0],argv[1],argv[2]);
+    if ((argc==2 || argc==3) && !nflag && !uflag) {
+               viewdb(argv[0],argv[1],argv[2],oflag);
                if (cflag) printf("%d\n",active);
        } else
                if (argc==5 && nflag)
-                       addip(argv[0],argv[1],argv[2],argv[3],argv[4]);
+                       addip(argv[0],argv[1],argv[2],argv[3],argv[4],oflag);
+               else if (argc==2 && uflag)
+                       tonewformat(argv[0],argv[1]);
                else
                        usage(argv0);
     return 0;