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;
120 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
121 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
123 if (inet_aton(ipaddress, &ipaddr) == 0)
125 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
131 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
137 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
141 port = strtoul(NASport,NULL,0);
143 /* Basically from rlm_ippool.c */
146 strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
148 key_datum.dptr = (char *) &old_key;
149 key_datum.dsize = sizeof(old_ippool_key);
152 char md5_input_str[MAX_STRING_LEN];
153 FR_MD5_CTX md5_context;
155 snprintf(md5_input_str,MAX_STRING_LEN, "%s %s",NASname,NASport);
156 fr_MD5Init(&md5_context);
157 fr_MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
158 fr_MD5Final(key_str, &md5_context);
159 memcpy(key.key,key_str,16);
160 fr_bin2hex(key_str,hex_str,16);
162 key_datum.dptr = (char *) &key;
163 key_datum.dsize = sizeof(ippool_key);
167 data_datum = gdbm_fetch(sessiondb, key_datum);
168 if (data_datum.dptr != NULL){
170 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
171 free(data_datum.dptr);
174 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
177 printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
179 save_datum.dptr = key_datum.dptr;
180 save_datum.dsize = key_datum.dsize;
182 data_datum.dptr = (char*) &entry;
183 data_datum.dsize = sizeof(ippool_info);
185 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
187 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
188 sessiondbname, gdbm_strerror(gdbm_errno));
190 gdbm_close(sessiondb);
194 key_datum.dptr = (char *) &entry.ipaddr;
195 key_datum.dsize = sizeof(uint32_t);
196 data_datum = gdbm_fetch(indexdb, key_datum);
197 if (data_datum.dptr != NULL) {
198 memcpy(&num, data_datum.dptr, sizeof(int));
199 free(data_datum.dptr);
202 data_datum.dptr = (char *) #
203 data_datum.dsize = sizeof(int);
204 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
206 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
207 indexdbname, gdbm_strerror(gdbm_errno));
209 gdbm_close(sessiondb);
212 if (num > 0 && entry.extra == 1) {
213 gdbm_delete(sessiondb, save_datum);
219 key_datum.dptr = NULL;
222 key_datum = gdbm_firstkey(sessiondb);
223 while(key_datum.dptr){
224 data_datum = gdbm_fetch(sessiondb, key_datum);
225 if (data_datum.dptr){
226 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
227 free(data_datum.dptr);
229 * If we find an entry for the same caller-id and nas with active=1
230 * then we use that for multilink (MPPP) to work properly.
232 if (strcmp(entry.cli,cli) == 0 && entry.active){
234 memcpy(&old_key,key_datum.dptr,sizeof(ippool_key));
235 if (!strcmp(old_key.nas,NASname)){
246 nextkey = gdbm_nextkey(sessiondb, key_datum);
247 free(key_datum.dptr);
252 if (key_datum.dptr == NULL) {
253 key_datum = gdbm_firstkey(sessiondb);
254 while (key_datum.dptr) {
255 data_datum = gdbm_fetch(sessiondb, key_datum);
256 if (data_datum.dptr != NULL) {
257 memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
258 free(data_datum.dptr);
260 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
262 tmp.dptr = (char *) &entry.ipaddr;
263 tmp.dsize = sizeof(uint32_t);
264 data_datum = gdbm_fetch(indexdb, tmp);
265 if (data_datum.dptr){
266 memcpy(&num, data_datum.dptr, sizeof(int));
267 free(data_datum.dptr);
278 nextkey = gdbm_nextkey(sessiondb, key_datum);
279 free(key_datum.dptr);
285 if (found && ! mppp){
286 datum key_datum_tmp,data_datum_tmp;
287 old_ippool_key old_key_tmp;
290 strlcpy(old_key_tmp.nas,NASname,
291 sizeof(old_key_tmp.nas));
292 old_key_tmp.port=port;
293 key_datum_tmp.dptr = (char *) &old_key_tmp;
294 key_datum_tmp.dsize = sizeof(old_ippool_key);
297 memcpy(key_tmp.key,key_str,16);
298 key_datum_tmp.dptr = (char *) &key_tmp;
299 key_datum_tmp.dsize = sizeof(ippool_key);
301 data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
302 if (data_datum_tmp.dptr != NULL) {
303 rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
305 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
306 sessiondbname, gdbm_strerror(gdbm_errno));
308 gdbm_close(sessiondb);
311 free(data_datum_tmp.dptr);
315 gdbm_delete(sessiondb, key_datum);
321 printf("Error in if statements!!!\n");
325 free(key_datum.dptr);
329 data_datum.dptr = (char *) &entry;
330 data_datum.dsize = sizeof(ippool_info);
333 strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
335 key_datum.dptr = (char *) &old_key;
336 key_datum.dsize = sizeof(old_ippool_key);
337 printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",old_key.nas,old_key.port);
340 memcpy(key.key,key_str,16);
341 key_datum.dptr = (char *) &key;
342 key_datum.dsize = sizeof(ippool_key);
343 printf("rlm_ippool_tool: Allocating ip to key: '%s'\n",hex_str);
345 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
347 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
348 sessiondbname, gdbm_strerror(gdbm_errno));
350 gdbm_close(sessiondb);
354 /* Increase the ip index count */
355 key_datum.dptr = (char *) &entry.ipaddr;
356 key_datum.dsize = sizeof(uint32_t);
357 data_datum = gdbm_fetch(indexdb, key_datum);
358 if (data_datum.dptr){
359 memcpy(&num,data_datum.dptr,sizeof(int));
360 free(data_datum.dptr);
364 printf("rlm_ippool_tool: num: %d\n",num);
365 data_datum.dptr = (char *) #
366 data_datum.dsize = sizeof(int);
367 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
369 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
370 indexdbname, gdbm_strerror(gdbm_errno));
372 gdbm_close(sessiondb);
377 printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
378 ipaddress, old_key.nas,port);
380 printf("rlm_ippool_tool: Allocated ip %s to key '%s'\n",ipaddress,hex_str);
384 gdbm_close(sessiondb);
386 void tonewformat(char *sessiondbname,char *newsessiondbname){
388 GDBM_FILE newsessiondb;
389 datum key_datum,keynext_datum,data_datum,newkey_datum;
390 old_ippool_key old_key;
396 sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
397 newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
399 if (sessiondb==NULL || newsessiondb==NULL) return;
401 memset(key_str,0,17);
403 key_datum=gdbm_firstkey(sessiondb);
404 while (key_datum.dptr) {
405 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
406 if (key_datum.dsize==sizeof(struct old_ippool_key)) {
407 char md5_input_str[MAX_STRING_LEN];
408 FR_MD5_CTX md5_context;
410 memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
411 snprintf(md5_input_str,MAX_STRING_LEN, "%s %d",old_key.nas,old_key.port);
412 fr_MD5Init(&md5_context);
413 fr_MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
414 fr_MD5Final(key_str, &md5_context);
415 memcpy(key.key,key_str,16);
416 fr_bin2hex(key_str,hex_str,16);
418 printf("rlm_ippool_tool: Transforming pair nas/port (%s/%d) to md5 '%s'\n",
419 old_key.nas,old_key.port,hex_str);
420 newkey_datum.dptr = (char *) &key;
421 newkey_datum.dsize = sizeof(ippool_key);
422 data_datum=gdbm_fetch(sessiondb,key_datum);
423 if (data_datum.dptr!=NULL){
424 rcode=gdbm_store(newsessiondb,newkey_datum,data_datum,GDBM_REPLACE);
426 printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
427 gdbm_close(newsessiondb);
428 gdbm_close(sessiondb);
433 key_datum=keynext_datum;
435 gdbm_close(newsessiondb);
436 gdbm_close(sessiondb);
439 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
442 datum key_datum,keynext_datum,data_datum,save_datum;
443 old_ippool_key old_key;
446 struct in_addr ipaddr;
451 int mode=GDBM_READER;
454 if (rflag) mode=GDBM_WRITER;
455 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
456 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
458 if (sessiondb==NULL || indexdb==NULL) return;
460 memset(key_str,0,17);
462 key_datum=gdbm_firstkey(sessiondb);
463 while (key_datum.dptr) {
464 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
465 if (key_datum.dsize==sizeof(struct ippool_key) || key_datum.dsize==sizeof(struct old_ippool_key)) {
467 memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
469 memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
471 data_datum=gdbm_fetch(sessiondb,key_datum);
472 if (data_datum.dptr!=NULL) {
474 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
475 memcpy(&ipaddr,&info.ipaddr,4);
476 ip=inet_ntoa(ipaddr);
478 if (info.active) active++;
479 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
481 printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
483 memcpy(key_str,key.key,16);
484 fr_bin2hex(key_str,hex_str,16);
486 printf("KEY: '%s' - ",hex_str);
489 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
491 else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
492 printf("ipaddr:%s active:%d cli:%s",
493 inet_ntoa(ipaddr),info.active,info.cli);
496 * algorythm copied from rlm_ippool.c:
497 * - set active to zero
498 * - set number of sessions to zero
500 if (rflag && MATCH_IP(ipaddress,ip)) {
502 save_datum.dptr = key_datum.dptr;
503 save_datum.dsize = key_datum.dsize;
504 data_datum.dptr = (char *) &info;
505 data_datum.dsize = sizeof(ippool_info);
506 rcode=gdbm_store(sessiondb,key_datum,data_datum,GDBM_REPLACE);
508 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
510 gdbm_close(sessiondb);
513 key_datum.dptr=(char *)&info.ipaddr;
514 key_datum.dsize = sizeof(uint32_t);
515 data_datum=gdbm_fetch(indexdb,key_datum);
516 if (data_datum.dptr!=NULL) {
517 memcpy(&num, data_datum.dptr, sizeof(int));
520 data_datum.dptr = (char *) #
521 data_datum.dsize = sizeof(int);
522 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
524 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
526 gdbm_close(sessiondb);
529 if (num > 0 && info.extra == 1) {
530 gdbm_delete(sessiondb, save_datum);
536 key_datum.dptr=(char *)&info.ipaddr;
537 key_datum.dsize = sizeof(uint32_t);
538 data_datum=gdbm_fetch(indexdb,key_datum);
539 if (data_datum.dptr!=NULL) {
540 memcpy(&num, data_datum.dptr, sizeof(int));
541 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
542 printf(" num:%d",num);
544 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
547 if (vflag && ipaddress==NULL){
549 printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
551 memcpy(key_str,key.key,16);
552 fr_bin2hex(key_str,hex_str,16);
554 printf("KEY: '%s' - ",hex_str);
558 key_datum=keynext_datum;
561 gdbm_close(sessiondb);
564 void NEVER_RETURNS usage(char *argv0) {
565 printf("Usage: %s [-a] [-c] [-o] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
566 printf("-a: print all active entries\n");
567 printf("-c: report number of active entries\n");
568 printf("-r: remove active entries\n");
569 printf("-v: verbose report of all entries\n");
570 printf("-o: Assume old database format (nas/port pair, not md5 output)\n");
571 printf("If an ipaddress is specified then that address is used to\n");
572 printf("limit the actions or output.\n");
573 printf("Usage: %s -n <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
574 printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
575 printf("Usage: %s -u <session-db> <new-session-db>\n",argv0);
576 printf("-u: Update old format database to new.\n");
580 int main(int argc,char **argv) {
584 while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
586 case 'a': aflag++;break;
587 case 'c': cflag++;break;
588 case 'r': rflag++;break;
589 case 'v': vflag=1;break;
590 case 'n': nflag=1;break;
591 case 'o': oflag=1;break;
592 case 'u': uflag=1;break;
593 default: usage(argv0);
598 if ((argc==2 || argc==3) && !nflag && !uflag) {
599 viewdb(argv[0],argv[1],argv[2],oflag);
600 if (cflag) printf("%d\n",active);
602 if (argc==5 && nflag)
603 addip(argv[0],argv[1],argv[2],argv[3],argv[4],oflag);
604 else if (argc==2 && uflag)
605 tonewformat(argv[0],argv[1]);