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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <sys/types.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
75 typedef struct ippool_info {
83 #define MAX_NAS_NAME_SIZE 64
84 typedef struct ippool_key {
85 char nas[MAX_NAS_NAME_SIZE];
89 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
90 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
92 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport);
93 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress);
94 void usage(char *argv0);
96 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport) {
99 datum key_datum,data_datum,save_datum;
103 struct in_addr ipaddr;
106 int mode=GDBM_WRITER;
114 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
115 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
117 if (inet_aton(ipaddress, &ipaddr) == 0)
119 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
125 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
131 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
135 port = strtoul(NASport,NULL,0);
137 /* Basically from rlm_ippool.c */
139 memset(key.nas,0,MAX_NAS_NAME_SIZE);
140 strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
142 key_datum.dptr = (char *) &key;
143 key_datum.dsize = sizeof(ippool_key);
145 data_datum = gdbm_fetch(sessiondb, key_datum);
146 if (data_datum.dptr != NULL){
148 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
149 free(data_datum.dptr);
151 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
154 save_datum.dptr = key_datum.dptr;
155 save_datum.dsize = key_datum.dsize;
157 data_datum.dptr = (char*) &entry;
158 data_datum.dsize = sizeof(ippool_info);
160 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
162 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
163 sessiondbname, gdbm_strerror(gdbm_errno));
165 gdbm_close(sessiondb);
169 key_datum.dptr = (char *) &entry.ipaddr;
170 key_datum.dsize = sizeof(uint32_t);
171 data_datum = gdbm_fetch(indexdb, key_datum);
172 if (data_datum.dptr != NULL) {
173 memcpy(&num, data_datum.dptr, sizeof(int));
174 free(data_datum.dptr);
177 data_datum.dptr = (char *) #
178 data_datum.dsize = sizeof(int);
179 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
181 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
182 indexdbname, gdbm_strerror(gdbm_errno));
184 gdbm_close(sessiondb);
187 if (num > 0 && entry.extra == 1) {
188 gdbm_delete(sessiondb, save_datum);
194 key_datum.dptr = NULL;
197 key_datum = gdbm_firstkey(sessiondb);
198 while(key_datum.dptr){
199 data_datum = gdbm_fetch(sessiondb, key_datum);
200 if (data_datum.dptr){
201 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
202 free(data_datum.dptr);
204 * If we find an entry for the same caller-id and nas with active=1
205 * then we use that for multilink (MPPP) to work properly.
207 if (strcmp(entry.cli,cli) == 0 && entry.active){
208 memcpy(&key,key_datum.dptr,sizeof(ippool_key));
209 if (!strcmp(key.nas,NASname)){
215 nextkey = gdbm_nextkey(sessiondb, key_datum);
216 free(key_datum.dptr);
221 if (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 != NULL) {
226 memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
227 free(data_datum.dptr);
229 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
231 tmp.dptr = (char *) &entry.ipaddr;
232 tmp.dsize = sizeof(uint32_t);
233 data_datum = gdbm_fetch(indexdb, tmp);
234 if (data_datum.dptr){
235 memcpy(&num, data_datum.dptr, sizeof(int));
236 free(data_datum.dptr);
247 nextkey = gdbm_nextkey(sessiondb, key_datum);
248 free(key_datum.dptr);
254 if (found && ! mppp){
255 datum key_datum_tmp,data_datum_tmp;
257 memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);
258 strncpy(key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
260 key_datum_tmp.dptr = (char *) &key_tmp;
261 key_datum_tmp.dsize = sizeof(ippool_key);
263 data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
264 if (data_datum_tmp.dptr != NULL) {
265 rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
267 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
268 sessiondbname, gdbm_strerror(gdbm_errno));
270 gdbm_close(sessiondb);
273 free(data_datum_tmp.dptr);
277 gdbm_delete(sessiondb, key_datum);
282 // printf("Error in if statements!!!\n");
285 free(key_datum.dptr);
289 data_datum.dptr = (char *) &entry;
290 data_datum.dsize = sizeof(ippool_info);
291 memset(key.nas,0,MAX_NAS_NAME_SIZE);
292 strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
294 key_datum.dptr = (char *) &key;
295 key_datum.dsize = sizeof(ippool_key);
296 printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",key.nas,key.port);
297 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
299 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
300 sessiondbname, gdbm_strerror(gdbm_errno));
302 gdbm_close(sessiondb);
306 /* Increase the ip index count */
307 key_datum.dptr = (char *) &entry.ipaddr;
308 key_datum.dsize = sizeof(uint32_t);
309 data_datum = gdbm_fetch(indexdb, key_datum);
310 if (data_datum.dptr){
311 memcpy(&num,data_datum.dptr,sizeof(int));
312 free(data_datum.dptr);
316 printf("rlm_ippool_tool: num: %d\n",num);
317 data_datum.dptr = (char *) #
318 data_datum.dsize = sizeof(int);
319 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
321 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
322 indexdbname, gdbm_strerror(gdbm_errno));
324 gdbm_close(sessiondb);
328 printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
329 ipaddress, key.nas,port);
333 gdbm_close(sessiondb);
336 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
339 datum key_datum,keynext_datum,data_datum,save_datum;
342 struct in_addr ipaddr;
345 int mode=GDBM_READER;
348 if (rflag) mode=GDBM_WRITER;
349 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
350 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
352 if (sessiondb==NULL || indexdb==NULL) return;
354 key_datum=gdbm_firstkey(sessiondb);
355 while (key_datum.dptr) {
356 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
357 if (key_datum.dsize==sizeof(struct ippool_key)) {
358 memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
360 data_datum=gdbm_fetch(sessiondb,key_datum);
361 if (data_datum.dptr!=NULL) {
363 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
364 memcpy(&ipaddr,&info.ipaddr,4);
365 ip=inet_ntoa(ipaddr);
367 if (info.active) active++;
368 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
369 printf("NAS:%s port:0x%x - ",key.nas,key.port);
370 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
372 else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
373 printf("ipaddr:%s active:%d cli:%s",
374 inet_ntoa(ipaddr),info.active,info.cli);
377 // algorythm copied from rlm_ippool.c:
378 // - set active to zero
379 // - set number of sessions to zero
381 if (rflag && MATCH_IP(ipaddress,ip)) {
383 save_datum.dptr = key_datum.dptr;
384 save_datum.dsize = key_datum.dsize;
385 data_datum.dptr = (char *) &info;
386 data_datum.dsize = sizeof(ippool_info);
387 rcode=gdbm_store(sessiondb,key_datum,data_datum,GDBM_REPLACE);
389 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
391 gdbm_close(sessiondb);
394 key_datum.dptr=(char *)&info.ipaddr;
395 key_datum.dsize = sizeof(uint32_t);
396 data_datum=gdbm_fetch(indexdb,key_datum);
397 if (data_datum.dptr!=NULL) {
398 memcpy(&num, data_datum.dptr, sizeof(int));
401 data_datum.dptr = (char *) #
402 data_datum.dsize = sizeof(int);
403 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
405 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
407 gdbm_close(sessiondb);
410 if (num > 0 && info.extra == 1) {
411 gdbm_delete(sessiondb, save_datum);
417 key_datum.dptr=(char *)&info.ipaddr;
418 key_datum.dsize = sizeof(uint32_t);
419 data_datum=gdbm_fetch(indexdb,key_datum);
420 if (data_datum.dptr!=NULL) {
421 memcpy(&num, data_datum.dptr, sizeof(int));
422 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
423 printf(" num:%d",num);
425 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
428 if (vflag && ipaddress==NULL)
429 printf("NAS:%s port:0x%x\n",key.nas,key.port);
431 key_datum=keynext_datum;
434 gdbm_close(sessiondb);
437 void usage(char *argv0) {
438 printf("Usage: %s [-a] [-c] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
439 printf("-a: print all active entries\n");
440 printf("-c: report number of active entries\n");
441 printf("-r: remove active entries\n");
442 printf("-v: verbose report of all entries\n");
443 printf("If an ipaddress is specified then that address is used to\n");
444 printf("limit the actions or output.\n");
445 printf("Usage: %s -n <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
446 printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
450 int main(int argc,char **argv) {
454 while ((ch=getopt(argc,argv,"acrvn"))!=-1)
456 case 'a': aflag++;break;
457 case 'c': cflag++;break;
458 case 'r': rflag++;break;
459 case 'v': vflag=1;break;
460 case 'n': nflag=1;break;
461 default: usage(argv0);
466 if ((argc==2 || argc==3) && !nflag) {
467 viewdb(argv[0],argv[1],argv[2]);
468 if (cflag) printf("%d\n",active);
470 if (argc==5 && nflag)
471 addip(argv[0],argv[1],argv[2],argv[3],argv[4]);