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 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/autoconf.h>
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
67 #include "../../include/md5.h"
68 #include <freeradius-devel/missing.h>
69 #include <freeradius-devel/libradius.h>
81 typedef struct ippool_info {
89 #define MAX_NAS_NAME_SIZE 64
90 typedef struct old_ippool_key {
91 char nas[MAX_NAS_NAME_SIZE];
94 typedef struct ippool_key {
98 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
99 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
101 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport,int old);
102 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old);
103 void tonewformat(char *sessiondbname,char *newsessiondbname);
104 void usage(char *argv0);
106 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport, int old) {
109 datum key_datum,data_datum,save_datum;
112 old_ippool_key old_key;
114 struct in_addr ipaddr;
119 int mode=GDBM_WRITER;
127 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
128 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
130 if (inet_aton(ipaddress, &ipaddr) == 0)
132 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
138 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
144 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
148 port = strtoul(NASport,NULL,0);
150 /* Basically from rlm_ippool.c */
153 memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
154 strncpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
156 key_datum.dptr = (char *) &old_key;
157 key_datum.dsize = sizeof(old_ippool_key);
160 char md5_input_str[MAX_STRING_LEN];
163 snprintf(md5_input_str,MAX_STRING_LEN, "%s %s",NASname,NASport);
164 MD5Init(&md5_context);
165 MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
166 MD5Final(key_str, &md5_context);
167 memcpy(key.key,key_str,16);
168 lrad_bin2hex(key_str,hex_str,16);
170 key_datum.dptr = (char *) &key;
171 key_datum.dsize = sizeof(ippool_key);
175 data_datum = gdbm_fetch(sessiondb, key_datum);
176 if (data_datum.dptr != NULL){
178 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
179 free(data_datum.dptr);
182 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
185 printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
187 save_datum.dptr = key_datum.dptr;
188 save_datum.dsize = key_datum.dsize;
190 data_datum.dptr = (char*) &entry;
191 data_datum.dsize = sizeof(ippool_info);
193 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
195 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
196 sessiondbname, gdbm_strerror(gdbm_errno));
198 gdbm_close(sessiondb);
202 key_datum.dptr = (char *) &entry.ipaddr;
203 key_datum.dsize = sizeof(uint32_t);
204 data_datum = gdbm_fetch(indexdb, key_datum);
205 if (data_datum.dptr != NULL) {
206 memcpy(&num, data_datum.dptr, sizeof(int));
207 free(data_datum.dptr);
210 data_datum.dptr = (char *) #
211 data_datum.dsize = sizeof(int);
212 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
214 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
215 indexdbname, gdbm_strerror(gdbm_errno));
217 gdbm_close(sessiondb);
220 if (num > 0 && entry.extra == 1) {
221 gdbm_delete(sessiondb, save_datum);
227 key_datum.dptr = NULL;
230 key_datum = gdbm_firstkey(sessiondb);
231 while(key_datum.dptr){
232 data_datum = gdbm_fetch(sessiondb, key_datum);
233 if (data_datum.dptr){
234 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
235 free(data_datum.dptr);
237 * If we find an entry for the same caller-id and nas with active=1
238 * then we use that for multilink (MPPP) to work properly.
240 if (strcmp(entry.cli,cli) == 0 && entry.active){
242 memcpy(&old_key,key_datum.dptr,sizeof(ippool_key));
243 if (!strcmp(old_key.nas,NASname)){
254 nextkey = gdbm_nextkey(sessiondb, key_datum);
255 free(key_datum.dptr);
260 if (key_datum.dptr == NULL) {
261 key_datum = gdbm_firstkey(sessiondb);
262 while (key_datum.dptr) {
263 data_datum = gdbm_fetch(sessiondb, key_datum);
264 if (data_datum.dptr != NULL) {
265 memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
266 free(data_datum.dptr);
268 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
270 tmp.dptr = (char *) &entry.ipaddr;
271 tmp.dsize = sizeof(uint32_t);
272 data_datum = gdbm_fetch(indexdb, tmp);
273 if (data_datum.dptr){
274 memcpy(&num, data_datum.dptr, sizeof(int));
275 free(data_datum.dptr);
286 nextkey = gdbm_nextkey(sessiondb, key_datum);
287 free(key_datum.dptr);
293 if (found && ! mppp){
294 datum key_datum_tmp,data_datum_tmp;
295 old_ippool_key old_key_tmp;
298 memset(old_key_tmp.nas,0,MAX_NAS_NAME_SIZE);
299 strncpy(old_key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
300 old_key_tmp.port=port;
301 key_datum_tmp.dptr = (char *) &old_key_tmp;
302 key_datum_tmp.dsize = sizeof(old_ippool_key);
305 memcpy(key_tmp.key,key_str,16);
306 key_datum_tmp.dptr = (char *) &key_tmp;
307 key_datum_tmp.dsize = sizeof(ippool_key);
309 data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
310 if (data_datum_tmp.dptr != NULL) {
311 rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
313 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
314 sessiondbname, gdbm_strerror(gdbm_errno));
316 gdbm_close(sessiondb);
319 free(data_datum_tmp.dptr);
323 gdbm_delete(sessiondb, key_datum);
329 printf("Error in if statements!!!\n");
333 free(key_datum.dptr);
337 data_datum.dptr = (char *) &entry;
338 data_datum.dsize = sizeof(ippool_info);
341 memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
342 strncpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
344 key_datum.dptr = (char *) &old_key;
345 key_datum.dsize = sizeof(old_ippool_key);
346 printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",old_key.nas,old_key.port);
349 memcpy(key.key,key_str,16);
350 key_datum.dptr = (char *) &key;
351 key_datum.dsize = sizeof(ippool_key);
352 printf("rlm_ippool_tool: Allocating ip to key: '%s'\n",hex_str);
354 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
356 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
357 sessiondbname, gdbm_strerror(gdbm_errno));
359 gdbm_close(sessiondb);
363 /* Increase the ip index count */
364 key_datum.dptr = (char *) &entry.ipaddr;
365 key_datum.dsize = sizeof(uint32_t);
366 data_datum = gdbm_fetch(indexdb, key_datum);
367 if (data_datum.dptr){
368 memcpy(&num,data_datum.dptr,sizeof(int));
369 free(data_datum.dptr);
373 printf("rlm_ippool_tool: num: %d\n",num);
374 data_datum.dptr = (char *) #
375 data_datum.dsize = sizeof(int);
376 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
378 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
379 indexdbname, gdbm_strerror(gdbm_errno));
381 gdbm_close(sessiondb);
386 printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
387 ipaddress, old_key.nas,port);
389 printf("rlm_ippool_tool: Allocated ip %s to key '%s'\n",ipaddress,hex_str);
393 gdbm_close(sessiondb);
395 void tonewformat(char *sessiondbname,char *newsessiondbname){
397 GDBM_FILE newsessiondb;
398 datum key_datum,keynext_datum,data_datum,newkey_datum;
399 old_ippool_key old_key;
405 sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
406 newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
408 if (sessiondb==NULL || newsessiondb==NULL) return;
410 memset(key_str,0,17);
412 key_datum=gdbm_firstkey(sessiondb);
413 while (key_datum.dptr) {
414 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
415 if (key_datum.dsize==sizeof(struct old_ippool_key)) {
416 char md5_input_str[MAX_STRING_LEN];
419 memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
420 snprintf(md5_input_str,MAX_STRING_LEN, "%s %d",old_key.nas,old_key.port);
421 MD5Init(&md5_context);
422 MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
423 MD5Final(key_str, &md5_context);
424 memcpy(key.key,key_str,16);
425 lrad_bin2hex(key_str,hex_str,16);
427 printf("rlm_ippool_tool: Transforming pair nas/port (%s/%d) to md5 '%s'\n",
428 old_key.nas,old_key.port,hex_str);
429 newkey_datum.dptr = (char *) &key;
430 newkey_datum.dsize = sizeof(ippool_key);
431 data_datum=gdbm_fetch(sessiondb,key_datum);
432 if (data_datum.dptr!=NULL){
433 rcode=gdbm_store(newsessiondb,newkey_datum,data_datum,GDBM_REPLACE);
435 printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
436 gdbm_close(newsessiondb);
437 gdbm_close(sessiondb);
442 key_datum=keynext_datum;
444 gdbm_close(newsessiondb);
445 gdbm_close(sessiondb);
448 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
451 datum key_datum,keynext_datum,data_datum,save_datum;
452 old_ippool_key old_key;
455 struct in_addr ipaddr;
460 int mode=GDBM_READER;
463 if (rflag) mode=GDBM_WRITER;
464 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
465 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
467 if (sessiondb==NULL || indexdb==NULL) return;
469 memset(key_str,0,17);
471 key_datum=gdbm_firstkey(sessiondb);
472 while (key_datum.dptr) {
473 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
474 if (key_datum.dsize==sizeof(struct ippool_key) || key_datum.dsize==sizeof(struct old_ippool_key)) {
476 memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
478 memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
480 data_datum=gdbm_fetch(sessiondb,key_datum);
481 if (data_datum.dptr!=NULL) {
483 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
484 memcpy(&ipaddr,&info.ipaddr,4);
485 ip=inet_ntoa(ipaddr);
487 if (info.active) active++;
488 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
490 printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
492 memcpy(key_str,key.key,16);
493 lrad_bin2hex(key_str,hex_str,16);
495 printf("KEY: '%s' - ",hex_str);
498 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
500 else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
501 printf("ipaddr:%s active:%d cli:%s",
502 inet_ntoa(ipaddr),info.active,info.cli);
505 * algorythm copied from rlm_ippool.c:
506 * - set active to zero
507 * - set number of sessions to zero
509 if (rflag && MATCH_IP(ipaddress,ip)) {
511 save_datum.dptr = key_datum.dptr;
512 save_datum.dsize = key_datum.dsize;
513 data_datum.dptr = (char *) &info;
514 data_datum.dsize = sizeof(ippool_info);
515 rcode=gdbm_store(sessiondb,key_datum,data_datum,GDBM_REPLACE);
517 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
519 gdbm_close(sessiondb);
522 key_datum.dptr=(char *)&info.ipaddr;
523 key_datum.dsize = sizeof(uint32_t);
524 data_datum=gdbm_fetch(indexdb,key_datum);
525 if (data_datum.dptr!=NULL) {
526 memcpy(&num, data_datum.dptr, sizeof(int));
529 data_datum.dptr = (char *) #
530 data_datum.dsize = sizeof(int);
531 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
533 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
535 gdbm_close(sessiondb);
538 if (num > 0 && info.extra == 1) {
539 gdbm_delete(sessiondb, save_datum);
545 key_datum.dptr=(char *)&info.ipaddr;
546 key_datum.dsize = sizeof(uint32_t);
547 data_datum=gdbm_fetch(indexdb,key_datum);
548 if (data_datum.dptr!=NULL) {
549 memcpy(&num, data_datum.dptr, sizeof(int));
550 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
551 printf(" num:%d",num);
553 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
556 if (vflag && ipaddress==NULL){
558 printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
560 memcpy(key_str,key.key,16);
561 lrad_bin2hex(key_str,hex_str,16);
563 printf("KEY: '%s' - ",hex_str);
567 key_datum=keynext_datum;
570 gdbm_close(sessiondb);
573 void NEVER_RETURNS usage(char *argv0) {
574 printf("Usage: %s [-a] [-c] [-o] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
575 printf("-a: print all active entries\n");
576 printf("-c: report number of active entries\n");
577 printf("-r: remove active entries\n");
578 printf("-v: verbose report of all entries\n");
579 printf("-o: Assume old database format (nas/port pair, not md5 output)\n");
580 printf("If an ipaddress is specified then that address is used to\n");
581 printf("limit the actions or output.\n");
582 printf("Usage: %s -n <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
583 printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
584 printf("Usage: %s -u <session-db> <new-session-db>\n",argv0);
585 printf("-u: Update old format database to new.\n");
589 int main(int argc,char **argv) {
593 while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
595 case 'a': aflag++;break;
596 case 'c': cflag++;break;
597 case 'r': rflag++;break;
598 case 'v': vflag=1;break;
599 case 'n': nflag=1;break;
600 case 'o': oflag=1;break;
601 case 'u': uflag=1;break;
602 default: usage(argv0);
607 if ((argc==2 || argc==3) && !nflag && !uflag) {
608 viewdb(argv[0],argv[1],argv[2],oflag);
609 if (cflag) printf("%d\n",active);
611 if (argc==5 && nflag)
612 addip(argv[0],argv[1],argv[2],argv[3],argv[4],oflag);
613 else if (argc==2 && uflag)
614 tonewformat(argv[0],argv[1]);