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
27 // The original license follows. This license applies to the tarball at
28 // http://www.mavetju.org/unix/general.php
30 // Copyright 2003 by Edwin Groothuis, edwin@mavetju.org
31 // All rights reserved.
33 // Redistribution and use in source and binary forms, with or without
34 // modification, are permitted provided that the following conditions
36 // 1. Redistributions of source code must retain the above copyright
37 // notice, this list of conditions and the following disclaimer.
38 // 2. Redistributions in binary form must reproduce the above copyright
39 // notice, this list of conditions and the following disclaimer in the
40 // documentation and/or other materials provided with the distribution.
42 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <netinet/in.h>
57 #include <arpa/inet.h>
73 typedef struct ippool_info {
81 #define MAX_NAS_NAME_SIZE 64
82 typedef struct ippool_key {
83 char nas[MAX_NAS_NAME_SIZE];
87 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
88 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
90 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport);
91 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress);
92 void usage(char *argv0);
94 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport) {
97 datum key_datum,data_datum,save_datum;
101 struct in_addr ipaddr;
104 int mode=GDBM_WRITER;
112 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
113 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
115 if (inet_aton(ipaddress, &ipaddr) == 0)
117 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
123 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
129 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
133 port = strtoul(NASport,NULL,0);
135 /* Basically from rlm_ippool.c */
137 memset(key.nas,0,MAX_NAS_NAME_SIZE);
138 strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
140 key_datum.dptr = (char *) &key;
141 key_datum.dsize = sizeof(ippool_key);
143 data_datum = gdbm_fetch(sessiondb, key_datum);
144 if (data_datum.dptr != NULL){
146 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
147 free(data_datum.dptr);
149 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
152 save_datum.dptr = key_datum.dptr;
153 save_datum.dsize = key_datum.dsize;
155 data_datum.dptr = (char*) &entry;
156 data_datum.dsize = sizeof(ippool_info);
158 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
160 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
161 sessiondbname, gdbm_strerror(gdbm_errno));
163 gdbm_close(sessiondb);
167 key_datum.dptr = (char *) &entry.ipaddr;
168 key_datum.dsize = sizeof(uint32_t);
169 data_datum = gdbm_fetch(indexdb, key_datum);
170 if (data_datum.dptr != NULL) {
171 memcpy(&num, data_datum.dptr, sizeof(int));
172 free(data_datum.dptr);
175 data_datum.dptr = (char *) #
176 data_datum.dsize = sizeof(int);
177 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
179 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
180 indexdbname, gdbm_strerror(gdbm_errno));
182 gdbm_close(sessiondb);
185 if (num > 0 && entry.extra == 1) {
186 gdbm_delete(sessiondb, save_datum);
192 key_datum.dptr = NULL;
195 key_datum = gdbm_firstkey(sessiondb);
196 while(key_datum.dptr){
197 data_datum = gdbm_fetch(sessiondb, key_datum);
198 if (data_datum.dptr){
199 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
200 free(data_datum.dptr);
202 * If we find an entry for the same caller-id and nas with active=1
203 * then we use that for multilink (MPPP) to work properly.
205 if (strcmp(entry.cli,cli) == 0 && entry.active){
206 memcpy(&key,key_datum.dptr,sizeof(ippool_key));
207 if (!strcmp(key.nas,NASname)){
213 nextkey = gdbm_nextkey(sessiondb, key_datum);
214 free(key_datum.dptr);
219 if (key_datum.dptr == NULL) {
220 key_datum = gdbm_firstkey(sessiondb);
221 while (key_datum.dptr) {
222 data_datum = gdbm_fetch(sessiondb, key_datum);
223 if (data_datum.dptr != NULL) {
224 memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
225 free(data_datum.dptr);
227 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
229 tmp.dptr = (char *) &entry.ipaddr;
230 tmp.dsize = sizeof(uint32_t);
231 data_datum = gdbm_fetch(indexdb, tmp);
232 if (data_datum.dptr){
233 memcpy(&num, data_datum.dptr, sizeof(int));
234 free(data_datum.dptr);
245 nextkey = gdbm_nextkey(sessiondb, key_datum);
246 free(key_datum.dptr);
252 if (found && ! mppp){
253 datum key_datum_tmp,data_datum_tmp;
255 memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);
256 strncpy(key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
258 key_datum_tmp.dptr = (char *) &key_tmp;
259 key_datum_tmp.dsize = sizeof(ippool_key);
261 data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
262 if (data_datum_tmp.dptr != NULL) {
263 rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
265 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
266 sessiondbname, gdbm_strerror(gdbm_errno));
268 gdbm_close(sessiondb);
271 free(data_datum_tmp.dptr);
275 gdbm_delete(sessiondb, key_datum);
280 // printf("Error in if statements!!!\n");
283 free(key_datum.dptr);
287 data_datum.dptr = (char *) &entry;
288 data_datum.dsize = sizeof(ippool_info);
289 memset(key.nas,0,MAX_NAS_NAME_SIZE);
290 strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
292 key_datum.dptr = (char *) &key;
293 key_datum.dsize = sizeof(ippool_key);
294 printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",key.nas,key.port);
295 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
297 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
298 sessiondbname, gdbm_strerror(gdbm_errno));
300 gdbm_close(sessiondb);
304 /* Increase the ip index count */
305 key_datum.dptr = (char *) &entry.ipaddr;
306 key_datum.dsize = sizeof(uint32_t);
307 data_datum = gdbm_fetch(indexdb, key_datum);
308 if (data_datum.dptr){
309 memcpy(&num,data_datum.dptr,sizeof(int));
310 free(data_datum.dptr);
314 printf("rlm_ippool_tool: num: %d\n",num);
315 data_datum.dptr = (char *) #
316 data_datum.dsize = sizeof(int);
317 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
319 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
320 indexdbname, gdbm_strerror(gdbm_errno));
322 gdbm_close(sessiondb);
326 printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
327 ipaddress, key.nas,port);
331 gdbm_close(sessiondb);
334 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
337 datum key_datum,keynext_datum,data_datum,save_datum;
340 struct in_addr ipaddr;
343 int mode=GDBM_READER;
346 if (rflag) mode=GDBM_WRITER;
347 sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
348 indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
350 if (sessiondb==NULL || indexdb==NULL) return;
352 key_datum=gdbm_firstkey(sessiondb);
353 while (key_datum.dptr) {
354 keynext_datum=gdbm_nextkey(sessiondb,key_datum);
355 if (key_datum.dsize==sizeof(struct ippool_key)) {
356 memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
358 data_datum=gdbm_fetch(sessiondb,key_datum);
359 if (data_datum.dptr!=NULL) {
361 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
362 memcpy(&ipaddr,&info.ipaddr,4);
363 ip=inet_ntoa(ipaddr);
365 if (info.active) active++;
366 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
367 printf("NAS:%s port:0x%x - ",key.nas,key.port);
368 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
370 else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
371 printf("ipaddr:%s active:%d cli:%s",
372 inet_ntoa(ipaddr),info.active,info.cli);
375 // algorythm copied from rlm_ippool.c:
376 // - set active to zero
377 // - set number of sessions to zero
379 if (rflag && MATCH_IP(ipaddress,ip)) {
381 save_datum.dptr = key_datum.dptr;
382 save_datum.dsize = key_datum.dsize;
383 data_datum.dptr = (char *) &info;
384 data_datum.dsize = sizeof(ippool_info);
385 rcode=gdbm_store(sessiondb,key_datum,data_datum,GDBM_REPLACE);
387 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
389 gdbm_close(sessiondb);
392 key_datum.dptr=(char *)&info.ipaddr;
393 key_datum.dsize = sizeof(uint32_t);
394 data_datum=gdbm_fetch(indexdb,key_datum);
395 if (data_datum.dptr!=NULL) {
396 memcpy(&num, data_datum.dptr, sizeof(int));
399 data_datum.dptr = (char *) #
400 data_datum.dsize = sizeof(int);
401 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
403 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
405 gdbm_close(sessiondb);
408 if (num > 0 && info.extra == 1) {
409 gdbm_delete(sessiondb, save_datum);
415 key_datum.dptr=(char *)&info.ipaddr;
416 key_datum.dsize = sizeof(uint32_t);
417 data_datum=gdbm_fetch(indexdb,key_datum);
418 if (data_datum.dptr!=NULL) {
419 memcpy(&num, data_datum.dptr, sizeof(int));
420 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
421 printf(" num:%d",num);
423 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
426 if (vflag && ipaddress==NULL)
427 printf("NAS:%s port:0x%x\n",key.nas,key.port);
429 key_datum=keynext_datum;
432 gdbm_close(sessiondb);
435 void usage(char *argv0) {
436 printf("Usage: %s [-a] [-c] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
437 printf("-a: print all active entries\n");
438 printf("-c: report number of active entries\n");
439 printf("-r: remove active entries\n");
440 printf("-v: verbose report of all entries\n");
441 printf("If an ipaddress is specified then that address is used to\n");
442 printf("limit the actions or output.\n");
443 printf("Usage: %s -n <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
444 printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
448 int main(int argc,char **argv) {
452 while ((ch=getopt(argc,argv,"acrvn"))!=-1)
454 case 'a': aflag++;break;
455 case 'c': cflag++;break;
456 case 'r': rflag++;break;
457 case 'v': vflag=1;break;
458 case 'n': nflag=1;break;
459 default: usage(argv0);
464 if ((argc==2 || argc==3) && !nflag) {
465 viewdb(argv[0],argv[1],argv[2]);
466 if (cflag) printf("%d\n",active);
468 if (argc==5 && nflag)
469 addip(argv[0],argv[1],argv[2],argv[3],argv[4]);