Update the GPL boilerplate with the new address of the FSF.
[freeradius.git] / src / modules / rlm_ippool / rlm_ippool_tool.c
1 /*
2  * rlm_ippool_tool.c
3  *
4  * Version:  $Id$
5  *
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.
10  *
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.
15  *
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
19  *
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
24  *
25  */
26
27 /*
28  The original license follows. This license applies to the tarball at
29  http://www.mavetju.org/unix/general.php
30
31  Copyright 2003 by Edwin Groothuis, edwin@mavetju.org
32  All rights reserved.
33
34  Redistribution and use in source and binary forms, with or without
35  modification, are permitted provided that the following conditions
36  are met:
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.
42
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
53  SUCH DAMAGE.
54 */
55
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>
61 #include <stdio.h>
62 #include <fcntl.h>
63 #include <gdbm.h>
64 #include <unistd.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include "../../include/md5.h"
68 #include <freeradius-devel/missing.h>
69 #include <freeradius-devel/libradius.h>
70
71 int active=0;
72
73 int aflag=0;
74 int cflag=0;
75 int rflag=0;
76 int vflag=0;
77 int nflag=0;
78 int oflag=0;
79 int uflag=0;
80
81 typedef struct ippool_info {
82     uint32_t        ipaddr;
83     char            active;
84     char            cli[32];
85         char                    extra;
86 } ippool_info;
87
88
89 #define MAX_NAS_NAME_SIZE 64
90 typedef struct old_ippool_key {
91     char nas[MAX_NAS_NAME_SIZE];
92     unsigned int port;
93 } old_ippool_key;
94 typedef struct ippool_key {
95     char key[16];
96 } ippool_key;
97
98 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
99 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
100
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);
105
106 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport, int old) {
107     GDBM_FILE sessiondb;
108     GDBM_FILE indexdb;
109     datum key_datum,data_datum,save_datum;
110         datum nextkey;
111     ippool_key key;
112     old_ippool_key old_key;
113     ippool_info entry;
114     struct in_addr ipaddr;
115     char key_str[17];
116     char hex_str[35];
117     int num=0;
118         int mppp=0;
119     int mode=GDBM_WRITER;
120     signed int rcode;
121         char *cli = NULL;
122         int delete = 0;
123         int port;
124         int extra = 0;
125         int found = 0;
126
127     sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
128     indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
129
130         if (inet_aton(ipaddress, &ipaddr) == 0)
131         {
132                 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
133                 return;
134         }
135
136     if (sessiondb==NULL)
137         {
138                 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
139                 return;
140         }
141
142     if (indexdb==NULL)
143         {
144                 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
145                 return;
146         }
147
148         port = strtoul(NASport,NULL,0);
149
150         /* Basically from rlm_ippool.c */
151
152         if (old){
153                 memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
154                 strncpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
155                 old_key.port = port;
156                 key_datum.dptr = (char *) &old_key;
157                 key_datum.dsize = sizeof(old_ippool_key);
158         }
159         else{
160                 char md5_input_str[MAX_STRING_LEN];
161                 MD5_CTX md5_context;
162
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);
169                 hex_str[32] = '\0';
170                 key_datum.dptr = (char *) &key;
171                 key_datum.dsize = sizeof(ippool_key);
172         }
173                 
174
175         data_datum = gdbm_fetch(sessiondb, key_datum);
176         if (data_datum.dptr != NULL){
177                 found = 1;
178                 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
179                 free(data_datum.dptr);
180                 if (entry.active){
181                         if (old)
182                                 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
183                                         ipaddress, port);
184                         else
185                                 printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
186                         entry.active = 0;
187                         save_datum.dptr = key_datum.dptr;
188                         save_datum.dsize = key_datum.dsize;
189
190                         data_datum.dptr = (char*) &entry;
191                         data_datum.dsize = sizeof(ippool_info);
192
193                         rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
194                         if (rcode < 0) {
195                                 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
196                                         sessiondbname, gdbm_strerror(gdbm_errno));
197                                 gdbm_close(indexdb);
198                                 gdbm_close(sessiondb);
199                                 return;
200                         }
201
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);
208                                 if (num > 0) {
209                                         num--;
210                                         data_datum.dptr = (char *) &num;
211                                         data_datum.dsize = sizeof(int);
212                                         rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
213                                         if (rcode < 0) {
214                                                 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
215                                                         indexdbname, gdbm_strerror(gdbm_errno));
216                                                 gdbm_close(indexdb);
217                                                 gdbm_close(sessiondb);
218                                                 return;
219                                         }
220                                         if (num > 0 && entry.extra == 1) {
221                                                 gdbm_delete(sessiondb, save_datum);
222                                         }
223                                 }
224                         }
225                 }
226         }
227         key_datum.dptr = NULL;
228
229         if (cli != 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);
236                                 /*
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.
239                                 */
240                                 if (strcmp(entry.cli,cli) == 0 && entry.active){
241                                         if (old){
242                                                 memcpy(&old_key,key_datum.dptr,sizeof(ippool_key));
243                                                 if (!strcmp(old_key.nas,NASname)){
244                                                         mppp = 1;
245                                                         break;
246                                                 }
247                                         }
248                                         else{
249                                                 mppp = 1;
250                                                 break;
251                                         }
252                                 }
253                         }
254                         nextkey = gdbm_nextkey(sessiondb, key_datum);
255                         free(key_datum.dptr);
256                         key_datum = nextkey;
257                 }
258         }
259
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);
267
268                                 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
269                                         datum tmp;
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);
276                                                 if (num == 0){
277                                                         delete = 1;
278                                                         break;
279                                                 }
280                                         } else {
281                                                 delete = 1;
282                                                 break;
283                                         }
284                                 }
285                         }
286                         nextkey = gdbm_nextkey(sessiondb, key_datum);
287                         free(key_datum.dptr);
288                         key_datum = nextkey;
289                 }
290         }
291
292         if (key_datum.dptr){
293                 if (found && ! mppp){
294                         datum key_datum_tmp,data_datum_tmp;
295                         old_ippool_key old_key_tmp;
296                         ippool_key key_tmp;
297                         if (old){
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);
303                         }
304                         else{
305                                 memcpy(key_tmp.key,key_str,16);
306                                 key_datum_tmp.dptr = (char *) &key_tmp;
307                                 key_datum_tmp.dsize = sizeof(ippool_key);
308                         }
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);
312                                 if (rcode < 0) {
313                                         printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
314                                                 sessiondbname, gdbm_strerror(gdbm_errno));
315                                                 gdbm_close(indexdb);
316                                                 gdbm_close(sessiondb);
317                                         return;
318                                 }
319                                 free(data_datum_tmp.dptr);
320                         }
321                 } else {
322                         if (delete)
323                                 gdbm_delete(sessiondb, key_datum);
324                         else {
325                                 if (mppp)
326                                         extra = 1;
327 #if 0
328                                 if (!mppp)
329                                         printf("Error in if statements!!!\n");
330 #endif
331                         }
332                 }
333                 free(key_datum.dptr);
334                 entry.active=1;
335                 if (extra)
336                         entry.extra=1;
337                 data_datum.dptr = (char *) &entry;
338                 data_datum.dsize = sizeof(ippool_info);
339
340                 if (old){
341                         memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
342                         strncpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
343                         old_key.port = port;
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);
347                 }
348                 else{
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);
353                 }
354                 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
355                 if (rcode < 0) {
356                         printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
357                                 sessiondbname, gdbm_strerror(gdbm_errno));
358                         gdbm_close(indexdb);
359                         gdbm_close(sessiondb);
360                         return;
361                 }
362
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);
370                 } else
371                         num = 0;
372                 num++;
373                 printf("rlm_ippool_tool: num: %d\n",num);
374                 data_datum.dptr = (char *) &num;
375                 data_datum.dsize = sizeof(int);
376                 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
377                 if (rcode < 0) {
378                         printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
379                                 indexdbname, gdbm_strerror(gdbm_errno));
380                         gdbm_close(indexdb);
381                         gdbm_close(sessiondb);
382                         return;
383                 }
384
385                 if (old)
386                         printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
387                                 ipaddress, old_key.nas,port);
388                 else
389                         printf("rlm_ippool_tool: Allocated ip %s to key  '%s'\n",ipaddress,hex_str);
390
391         }
392     gdbm_close(indexdb);
393     gdbm_close(sessiondb);
394 }
395 void tonewformat(char *sessiondbname,char *newsessiondbname){
396     GDBM_FILE sessiondb;
397     GDBM_FILE newsessiondb;
398     datum key_datum,keynext_datum,data_datum,newkey_datum;
399     old_ippool_key old_key;
400     ippool_key key;
401     char key_str[17];
402     char hex_str[35];
403     int rcode;
404
405     sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
406     newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
407
408     if (sessiondb==NULL || newsessiondb==NULL) return;
409
410     memset(key_str,0,17);
411
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];
417                 MD5_CTX md5_context;
418
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);
426                 hex_str[32] = '\0';
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);
434                     if (rcode < 0) {
435                                 printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
436                                 gdbm_close(newsessiondb);
437                                 gdbm_close(sessiondb);
438                                 return;
439                         }
440                 }
441         }
442         key_datum=keynext_datum;
443     }
444     gdbm_close(newsessiondb);
445     gdbm_close(sessiondb);
446 }
447
448 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
449     GDBM_FILE sessiondb;
450     GDBM_FILE indexdb;
451     datum key_datum,keynext_datum,data_datum,save_datum;
452     old_ippool_key old_key;
453     ippool_key key;
454     ippool_info info;
455     struct in_addr ipaddr;
456     int num;
457     char key_str[17];
458     char hex_str[35];
459     char *ip;
460     int mode=GDBM_READER;
461     int rcode;
462
463     if (rflag) mode=GDBM_WRITER;
464     sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
465     indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
466
467     if (sessiondb==NULL || indexdb==NULL) return;
468
469     memset(key_str,0,17);
470
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)) {
475             if (old)
476                  memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
477             else
478                  memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
479
480             data_datum=gdbm_fetch(sessiondb,key_datum);
481             if (data_datum.dptr!=NULL) {
482
483                 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
484                 memcpy(&ipaddr,&info.ipaddr,4);
485                 ip=inet_ntoa(ipaddr);
486
487                 if (info.active) active++;
488                 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
489                     if (old)
490                         printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
491                     else{
492                         memcpy(key_str,key.key,16);
493                         lrad_bin2hex(key_str,hex_str,16);
494                         hex_str[32] = '\0';
495                         printf("KEY: '%s' - ",hex_str);
496                     }
497                 }
498                 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
499                     printf("%s\n",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);
503
504                 /*
505                  * algorythm copied from rlm_ippool.c:
506                  * - set active to zero
507                  * - set number of sessions to zero
508                  */
509                 if (rflag && MATCH_IP(ipaddress,ip)) {
510                     info.active=0;
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);
516                     if (rcode < 0) {
517                                 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
518                                 gdbm_close(indexdb);
519                                 gdbm_close(sessiondb);
520                                 return;
521                         }
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));
527                                 if (num>0) {
528                                         num--;
529                                         data_datum.dptr = (char *) &num;
530                                         data_datum.dsize = sizeof(int);
531                                         rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
532                                         if (rcode < 0) {
533                                                 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
534                                                 gdbm_close(indexdb);
535                                                 gdbm_close(sessiondb);
536                                                 return;
537                                         }
538                                         if (num > 0 && info.extra == 1) {
539                                                 gdbm_delete(sessiondb, save_datum);
540                                         }
541                                 }
542                     }
543                 }
544
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);
552                 }
553                 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
554                     printf("\n");
555             } else
556                 if (vflag && ipaddress==NULL){
557                     if (old)
558                         printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
559                     else{
560                         memcpy(key_str,key.key,16);
561                         lrad_bin2hex(key_str,hex_str,16);
562                         hex_str[32] = '\0';
563                         printf("KEY: '%s' - ",hex_str);
564                     }
565                 }
566         }
567         key_datum=keynext_datum;
568     }
569     gdbm_close(indexdb);
570     gdbm_close(sessiondb);
571 }
572
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");
586     exit(0);
587 }
588
589 int main(int argc,char **argv) {
590     int ch;
591     char *argv0=argv[0];
592
593     while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
594         switch (ch) {
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);
603         }
604     argc -= optind;
605     argv += optind;
606
607     if ((argc==2 || argc==3) && !nflag && !uflag) {
608                 viewdb(argv[0],argv[1],argv[2],oflag);
609                 if (cflag) printf("%d\n",active);
610         } else
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]);
615                 else
616                         usage(argv0);
617     return 0;
618 }