6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2003,2006 FreeRADIUS Project, http://www.freeradius.org/
21 * Copyright 2003 Edwin Groothuis, edwin@mavetju.org
22 * Permission from Edwin Groothuis for release under GPL is archived here:
23 * http://lists.cistron.nl/archives/freeradius-devel/2003/09/frm00247.html
28 The original license follows. This license applies to the tarball at
29 http://www.mavetju.org/unix/general.php
31 Copyright 2003 by Edwin Groothuis, edwin@mavetju.org
34 Redistribution and use in source and binary forms, with or without
35 modification, are permitted provided that the following conditions
37 1. Redistributions of source code must retain the above copyright
38 notice, this list of conditions and the following disclaimer.
39 2. Redistributions in binary form must reproduce the above copyright
40 notice, this list of conditions and the following disclaimer in the
41 documentation and/or other materials provided with the distribution.
43 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 #include <freeradius-devel/ident.h>
59 #include <freeradius-devel/libradius.h>
62 #include "../../include/md5.h"
74 typedef struct ippool_info {
82 #define MAX_NAS_NAME_SIZE 64
83 typedef struct old_ippool_key {
84 char nas[MAX_NAS_NAME_SIZE];
87 typedef struct ippool_key {
91 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
92 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
94 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport,int old);
95 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old);
96 void tonewformat(char *sessiondbname,char *newsessiondbname);
97 void usage(char *argv0);
99 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport, int old) {
102 datum key_datum,data_datum,save_datum;
105 old_ippool_key old_key;
107 struct in_addr ipaddr;
112 int mode=GDBM_WRITER;
119 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
120 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
122 if (inet_aton(ipaddress, &ipaddr) == 0)
124 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
130 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
136 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
140 port = strtoul(NASport,NULL,0);
142 /* Basically from rlm_ippool.c */
145 strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
147 key_datum.dptr = (char *) &old_key;
148 key_datum.dsize = sizeof(old_ippool_key);
151 char md5_input_str[MAX_STRING_LEN];
152 FR_MD5_CTX md5_context;
154 snprintf(md5_input_str,MAX_STRING_LEN, "%s %s",NASname,NASport);
155 fr_MD5Init(&md5_context);
156 fr_MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
157 fr_MD5Final(key_str, &md5_context);
158 memcpy(key.key,key_str,16);
159 fr_bin2hex(key_str,hex_str,16);
161 key_datum.dptr = (char *) &key;
162 key_datum.dsize = sizeof(ippool_key);
166 data_datum = gdbm_fetch(sessiondb, key_datum);
167 if (data_datum.dptr != NULL){
169 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
170 free(data_datum.dptr);
173 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
176 printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
178 save_datum.dptr = key_datum.dptr;
179 save_datum.dsize = key_datum.dsize;
181 data_datum.dptr = (char*) &entry;
182 data_datum.dsize = sizeof(ippool_info);
184 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
186 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
187 sessiondbname, gdbm_strerror(gdbm_errno));
189 gdbm_close(sessiondb);
193 key_datum.dptr = (char *) &entry.ipaddr;
194 key_datum.dsize = sizeof(uint32_t);
195 data_datum = gdbm_fetch(indexdb, key_datum);
196 if (data_datum.dptr != NULL) {
197 memcpy(&num, data_datum.dptr, sizeof(int));
198 free(data_datum.dptr);
201 data_datum.dptr = (char *) #
202 data_datum.dsize = sizeof(int);
203 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
205 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
206 indexdbname, gdbm_strerror(gdbm_errno));
208 gdbm_close(sessiondb);
211 if (num > 0 && entry.extra == 1) {
212 gdbm_delete(sessiondb, save_datum);
218 key_datum.dptr = NULL;
220 if (key_datum.dptr == NULL) {
221 key_datum = gdbm_firstkey(sessiondb);
222 while (key_datum.dptr) {
223 data_datum = gdbm_fetch(sessiondb, key_datum);
224 if (data_datum.dptr != NULL) {
225 memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
226 free(data_datum.dptr);
228 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
230 tmp.dptr = (char *) &entry.ipaddr;
231 tmp.dsize = sizeof(uint32_t);
232 data_datum = gdbm_fetch(indexdb, tmp);
233 if (data_datum.dptr){
234 memcpy(&num, data_datum.dptr, sizeof(int));
235 free(data_datum.dptr);
246 nextkey = gdbm_nextkey(sessiondb, key_datum);
247 free(key_datum.dptr);
253 if (found && ! mppp){
254 datum key_datum_tmp,data_datum_tmp;
255 old_ippool_key old_key_tmp;
258 strlcpy(old_key_tmp.nas,NASname,
259 sizeof(old_key_tmp.nas));
260 old_key_tmp.port=port;
261 key_datum_tmp.dptr = (char *) &old_key_tmp;
262 key_datum_tmp.dsize = sizeof(old_ippool_key);
265 memcpy(key_tmp.key,key_str,16);
266 key_datum_tmp.dptr = (char *) &key_tmp;
267 key_datum_tmp.dsize = sizeof(ippool_key);
269 data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
270 if (data_datum_tmp.dptr != NULL) {
271 rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
273 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
274 sessiondbname, gdbm_strerror(gdbm_errno));
276 gdbm_close(sessiondb);
279 free(data_datum_tmp.dptr);
283 gdbm_delete(sessiondb, key_datum);
289 printf("Error in if statements!!!\n");
293 free(key_datum.dptr);
297 data_datum.dptr = (char *) &entry;
298 data_datum.dsize = sizeof(ippool_info);
301 strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
303 key_datum.dptr = (char *) &old_key;
304 key_datum.dsize = sizeof(old_ippool_key);
305 printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",old_key.nas,old_key.port);
308 memcpy(key.key,key_str,16);
309 key_datum.dptr = (char *) &key;
310 key_datum.dsize = sizeof(ippool_key);
311 printf("rlm_ippool_tool: Allocating ip to key: '%s'\n",hex_str);
313 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
315 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
316 sessiondbname, gdbm_strerror(gdbm_errno));
318 gdbm_close(sessiondb);
322 /* Increase the ip index count */
323 key_datum.dptr = (char *) &entry.ipaddr;
324 key_datum.dsize = sizeof(uint32_t);
325 data_datum = gdbm_fetch(indexdb, key_datum);
326 if (data_datum.dptr){
327 memcpy(&num,data_datum.dptr,sizeof(int));
328 free(data_datum.dptr);
332 printf("rlm_ippool_tool: num: %d\n",num);
333 data_datum.dptr = (char *) #
334 data_datum.dsize = sizeof(int);
335 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
337 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
338 indexdbname, gdbm_strerror(gdbm_errno));
340 gdbm_close(sessiondb);
345 printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
346 ipaddress, old_key.nas,port);
348 printf("rlm_ippool_tool: Allocated ip %s to key '%s'\n",ipaddress,hex_str);
352 gdbm_close(sessiondb);
354 void tonewformat(char *sessiondbname,char *newsessiondbname){
356 GDBM_FILE newsessiondb;
357 datum key_datum,keynext_datum,data_datum,newkey_datum;
358 old_ippool_key old_key;
364 sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
365 newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
367 if (sessiondb==NULL || newsessiondb==NULL) return;
369 memset(key_str,0,17);
371 key_datum=gdbm_firstkey(sessiondb);
372 while (key_datum.dptr) {
373 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
374 if (key_datum.dsize==sizeof(struct old_ippool_key)) {
375 char md5_input_str[MAX_STRING_LEN];
376 FR_MD5_CTX md5_context;
378 memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
379 snprintf(md5_input_str,MAX_STRING_LEN, "%s %d",old_key.nas,old_key.port);
380 fr_MD5Init(&md5_context);
381 fr_MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
382 fr_MD5Final(key_str, &md5_context);
383 memcpy(key.key,key_str,16);
384 fr_bin2hex(key_str,hex_str,16);
386 printf("rlm_ippool_tool: Transforming pair nas/port (%s/%d) to md5 '%s'\n",
387 old_key.nas,old_key.port,hex_str);
388 newkey_datum.dptr = (char *) &key;
389 newkey_datum.dsize = sizeof(ippool_key);
390 data_datum=gdbm_fetch(sessiondb,key_datum);
391 if (data_datum.dptr!=NULL){
392 rcode=gdbm_store(newsessiondb,newkey_datum,data_datum,GDBM_REPLACE);
394 printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
395 gdbm_close(newsessiondb);
396 gdbm_close(sessiondb);
401 key_datum=keynext_datum;
403 gdbm_close(newsessiondb);
404 gdbm_close(sessiondb);
407 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
410 datum key_datum,keynext_datum,data_datum,save_datum;
411 old_ippool_key old_key;
414 struct in_addr ipaddr;
419 int mode=GDBM_READER;
422 if (rflag) mode=GDBM_WRITER;
423 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
424 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
426 if (sessiondb==NULL || indexdb==NULL) return;
428 memset(key_str,0,17);
430 key_datum=gdbm_firstkey(sessiondb);
431 while (key_datum.dptr) {
432 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
433 if (key_datum.dsize==sizeof(struct ippool_key) || key_datum.dsize==sizeof(struct old_ippool_key)) {
435 memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
437 memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
439 data_datum=gdbm_fetch(sessiondb,key_datum);
440 if (data_datum.dptr!=NULL) {
442 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
443 memcpy(&ipaddr,&info.ipaddr,4);
444 ip=inet_ntoa(ipaddr);
446 if (info.active) active++;
447 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
449 printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
451 memcpy(key_str,key.key,16);
452 fr_bin2hex(key_str,hex_str,16);
454 printf("KEY: '%s' - ",hex_str);
457 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
459 else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
460 printf("ipaddr:%s active:%d cli:%s",
461 inet_ntoa(ipaddr),info.active,info.cli);
464 * algorythm copied from rlm_ippool.c:
465 * - set active to zero
466 * - set number of sessions to zero
468 if (rflag && MATCH_IP(ipaddress,ip)) {
470 save_datum.dptr = key_datum.dptr;
471 save_datum.dsize = key_datum.dsize;
472 data_datum.dptr = (char *) &info;
473 data_datum.dsize = sizeof(ippool_info);
474 rcode=gdbm_store(sessiondb,key_datum,data_datum,GDBM_REPLACE);
476 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
478 gdbm_close(sessiondb);
481 key_datum.dptr=(char *)&info.ipaddr;
482 key_datum.dsize = sizeof(uint32_t);
483 data_datum=gdbm_fetch(indexdb,key_datum);
484 if (data_datum.dptr!=NULL) {
485 memcpy(&num, data_datum.dptr, sizeof(int));
488 data_datum.dptr = (char *) #
489 data_datum.dsize = sizeof(int);
490 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
492 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
494 gdbm_close(sessiondb);
497 if (num > 0 && info.extra == 1) {
498 gdbm_delete(sessiondb, save_datum);
504 key_datum.dptr=(char *)&info.ipaddr;
505 key_datum.dsize = sizeof(uint32_t);
506 data_datum=gdbm_fetch(indexdb,key_datum);
507 if (data_datum.dptr!=NULL) {
508 memcpy(&num, data_datum.dptr, sizeof(int));
509 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
510 printf(" num:%d",num);
512 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
515 if (vflag && ipaddress==NULL){
517 printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
519 memcpy(key_str,key.key,16);
520 fr_bin2hex(key_str,hex_str,16);
522 printf("KEY: '%s' - ",hex_str);
526 key_datum=keynext_datum;
529 gdbm_close(sessiondb);
532 void NEVER_RETURNS usage(char *argv0) {
533 printf("Usage: %s [-a] [-c] [-o] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
534 printf("-a: print all active entries\n");
535 printf("-c: report number of active entries\n");
536 printf("-r: remove active entries\n");
537 printf("-v: verbose report of all entries\n");
538 printf("-o: Assume old database format (nas/port pair, not md5 output)\n");
539 printf("If an ipaddress is specified then that address is used to\n");
540 printf("limit the actions or output.\n");
541 printf("Usage: %s -n <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
542 printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
543 printf("Usage: %s -u <session-db> <new-session-db>\n",argv0);
544 printf("-u: Update old format database to new.\n");
548 int main(int argc,char **argv) {
552 while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
554 case 'a': aflag++;break;
555 case 'c': cflag++;break;
556 case 'r': rflag++;break;
557 case 'v': vflag=1;break;
558 case 'n': nflag=1;break;
559 case 'o': oflag=1;break;
560 case 'u': uflag=1;break;
561 default: usage(argv0);
566 if ((argc==2 || argc==3) && !nflag && !uflag) {
567 viewdb(argv[0],argv[1],argv[2],oflag);
568 if (cflag) printf("%d\n",active);
570 if (argc==5 && nflag)
571 addip(argv[0],argv[1],argv[2],argv[3],argv[4],oflag);
572 else if (argc==2 && uflag)
573 tonewformat(argv[0],argv[1]);