#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <freeradius-devel/libradius.h>
#include <fcntl.h>
#include <gdbm.h>
#include "../../include/md5.h"
int active=0;
int aflag=0;
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;
char active;
char cli[32];
char extra;
} ippool_info;
#define MAX_NAS_NAME_SIZE 64
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,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, 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;
uint8_t key_str[17];
char hex_str[35];
int num=0;
int mppp=0;
int mode=GDBM_WRITER;
signed int rcode;
int delete = 0;
int port;
int extra = 0;
int found = 0;
sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
if (inet_aton(ipaddress, &ipaddr) == 0)
{
printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
return;
}
if (sessiondb==NULL)
{
printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
return;
}
if (indexdb==NULL)
{
printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
return;
}
port = strtoul(NASport,NULL,0);
if (old){
strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
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];
FR_MD5_CTX md5_context;
snprintf(md5_input_str,MAX_STRING_LEN, "%s %s",NASname,NASport);
fr_MD5Init(&md5_context);
fr_MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
fr_MD5Final(key_str, &md5_context);
memcpy(key.key,key_str,16);
fr_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){
found = 1;
memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
free(data_datum.dptr);
if (entry.active){
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;
data_datum.dptr = (char*) &entry;
data_datum.dsize = sizeof(ippool_info);
rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
if (rcode < 0) {
printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
sessiondbname, gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
key_datum.dptr = (char *) &entry.ipaddr;
key_datum.dsize = sizeof(uint32_t);
data_datum = gdbm_fetch(indexdb, key_datum);
if (data_datum.dptr != NULL) {
memcpy(&num, data_datum.dptr, sizeof(int));
free(data_datum.dptr);
if (num > 0) {
num--;
data_datum.dptr = (char *) #
data_datum.dsize = sizeof(int);
rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
if (rcode < 0) {
printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
indexdbname, gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
if (num > 0 && entry.extra == 1) {
gdbm_delete(sessiondb, save_datum);
}
}
}
}
}
key_datum.dptr = NULL;
if (key_datum.dptr == NULL) {
key_datum = gdbm_firstkey(sessiondb);
while (key_datum.dptr) {
data_datum = gdbm_fetch(sessiondb, key_datum);
if (data_datum.dptr != NULL) {
memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
free(data_datum.dptr);
if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
datum tmp;
tmp.dptr = (char *) &entry.ipaddr;
tmp.dsize = sizeof(uint32_t);
data_datum = gdbm_fetch(indexdb, tmp);
if (data_datum.dptr){
memcpy(&num, data_datum.dptr, sizeof(int));
free(data_datum.dptr);
if (num == 0){
delete = 1;
break;
}
} else {
delete = 1;
break;
}
}
}
nextkey = gdbm_nextkey(sessiondb, key_datum);
free(key_datum.dptr);
key_datum = nextkey;
}
}
if (key_datum.dptr){
if (found && ! mppp){
datum key_datum_tmp,data_datum_tmp;
old_ippool_key old_key_tmp;
ippool_key key_tmp;
if (old){
strlcpy(old_key_tmp.nas,NASname,
sizeof(old_key_tmp.nas));
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);
if (rcode < 0) {
printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
sessiondbname, gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
free(data_datum_tmp.dptr);
}
} else {
if (delete)
gdbm_delete(sessiondb, key_datum);
else {
if (mppp)
extra = 1;
#if 0
if (!mppp)
printf("Error in if statements!!!\n");
#endif
}
}
free(key_datum.dptr);
entry.active=1;
if (extra)
entry.extra=1;
data_datum.dptr = (char *) &entry;
data_datum.dsize = sizeof(ippool_info);
if (old){
strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
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",
sessiondbname, gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
key_datum.dptr = (char *) &entry.ipaddr;
key_datum.dsize = sizeof(uint32_t);
data_datum = gdbm_fetch(indexdb, key_datum);
if (data_datum.dptr){
memcpy(&num,data_datum.dptr,sizeof(int));
free(data_datum.dptr);
} else
num = 0;
num++;
printf("rlm_ippool_tool: num: %d\n",num);
data_datum.dptr = (char *) #
data_datum.dsize = sizeof(int);
rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
if (rcode < 0) {
printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
indexdbname, gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
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;
uint8_t 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];
FR_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);
fr_MD5Init(&md5_context);
fr_MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
fr_MD5Final(key_str, &md5_context);
memcpy(key.key,key_str,16);
fr_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, 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;
uint8_t key_str[17];
char hex_str[35];
char *ip;
int mode=GDBM_READER;
int rcode;
if (rflag) mode=GDBM_WRITER;
sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
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) || 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) {
memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
memcpy(&ipaddr,&info.ipaddr,4);
ip=inet_ntoa(ipaddr);
if (info.active) active++;
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);
fr_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))
printf("ipaddr:%s active:%d cli:%s",
inet_ntoa(ipaddr),info.active,info.cli);
if (rflag && MATCH_IP(ipaddress,ip)) {
info.active=0;
save_datum.dptr = key_datum.dptr;
save_datum.dsize = key_datum.dsize;
data_datum.dptr = (char *) &info;
data_datum.dsize = sizeof(ippool_info);
rcode=gdbm_store(sessiondb,key_datum,data_datum,GDBM_REPLACE);
if (rcode < 0) {
printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
key_datum.dptr=(char *)&info.ipaddr;
key_datum.dsize = sizeof(uint32_t);
data_datum=gdbm_fetch(indexdb,key_datum);
if (data_datum.dptr!=NULL) {
memcpy(&num, data_datum.dptr, sizeof(int));
if (num>0) {
num--;
data_datum.dptr = (char *) #
data_datum.dsize = sizeof(int);
rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
if (rcode < 0) {
printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
gdbm_close(indexdb);
gdbm_close(sessiondb);
return;
}
if (num > 0 && info.extra == 1) {
gdbm_delete(sessiondb, save_datum);
}
}
}
}
key_datum.dptr=(char *)&info.ipaddr;
key_datum.dsize = sizeof(uint32_t);
data_datum=gdbm_fetch(indexdb,key_datum);
if (data_datum.dptr!=NULL) {
memcpy(&num, data_datum.dptr, sizeof(int));
if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
printf(" num:%d",num);
}
if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
printf("\n");
} else
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);
fr_bin2hex(key_str,hex_str,16);
hex_str[32] = '\0';
printf("KEY: '%s' - ",hex_str);
}
}
}
key_datum=keynext_datum;
}
gdbm_close(indexdb);
gdbm_close(sessiondb);
}
void NEVER_RETURNS usage(char *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);
}
int main(int argc,char **argv) {
int ch;
char *argv0=argv[0];
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 && !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],oflag);
else if (argc==2 && uflag)
tonewformat(argv[0],argv[1]);
else
usage(argv0);
return 0;
}