Fix some compiler warnings.
[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,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
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/ident.h>
57 RCSID("$Id$")
58
59 #include <freeradius-devel/libradius.h>
60 #include <fcntl.h>
61 #include <gdbm.h>
62 #include "../../include/md5.h"
63
64 int active=0;
65
66 int aflag=0;
67 int cflag=0;
68 int rflag=0;
69 int vflag=0;
70 int nflag=0;
71 int oflag=0;
72 int uflag=0;
73
74 typedef struct ippool_info {
75     uint32_t        ipaddr;
76     char            active;
77     char            cli[32];
78         char                    extra;
79 } ippool_info;
80
81
82 #define MAX_NAS_NAME_SIZE 64
83 typedef struct old_ippool_key {
84     char nas[MAX_NAS_NAME_SIZE];
85     unsigned int port;
86 } old_ippool_key;
87 typedef struct ippool_key {
88     char key[16];
89 } ippool_key;
90
91 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
92 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
93
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);
98
99 void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport, int old) {
100     GDBM_FILE sessiondb;
101     GDBM_FILE indexdb;
102     datum key_datum,data_datum,save_datum;
103         datum nextkey;
104     ippool_key key;
105     old_ippool_key old_key;
106     ippool_info entry;
107     struct in_addr ipaddr;
108     uint8_t key_str[17];
109     char hex_str[35];
110     int num=0;
111         int mppp=0;
112     int mode=GDBM_WRITER;
113     signed int rcode;
114         char *cli = NULL;
115         int delete = 0;
116         int port;
117         int extra = 0;
118         int found = 0;
119
120     sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
121     indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
122
123         if (inet_aton(ipaddress, &ipaddr) == 0)
124         {
125                 printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress);
126                 return;
127         }
128
129     if (sessiondb==NULL)
130         {
131                 printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname);
132                 return;
133         }
134
135     if (indexdb==NULL)
136         {
137                 printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname);
138                 return;
139         }
140
141         port = strtoul(NASport,NULL,0);
142
143         /* Basically from rlm_ippool.c */
144
145         if (old){
146                 strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
147                 old_key.port = port;
148                 key_datum.dptr = (char *) &old_key;
149                 key_datum.dsize = sizeof(old_ippool_key);
150         }
151         else{
152                 char md5_input_str[MAX_STRING_LEN];
153                 FR_MD5_CTX md5_context;
154
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);
161                 hex_str[32] = '\0';
162                 key_datum.dptr = (char *) &key;
163                 key_datum.dsize = sizeof(ippool_key);
164         }
165
166
167         data_datum = gdbm_fetch(sessiondb, key_datum);
168         if (data_datum.dptr != NULL){
169                 found = 1;
170                 memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
171                 free(data_datum.dptr);
172                 if (entry.active){
173                         if (old)
174                                 printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
175                                         ipaddress, port);
176                         else
177                                 printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
178                         entry.active = 0;
179                         save_datum.dptr = key_datum.dptr;
180                         save_datum.dsize = key_datum.dsize;
181
182                         data_datum.dptr = (char*) &entry;
183                         data_datum.dsize = sizeof(ippool_info);
184
185                         rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
186                         if (rcode < 0) {
187                                 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
188                                         sessiondbname, gdbm_strerror(gdbm_errno));
189                                 gdbm_close(indexdb);
190                                 gdbm_close(sessiondb);
191                                 return;
192                         }
193
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);
200                                 if (num > 0) {
201                                         num--;
202                                         data_datum.dptr = (char *) &num;
203                                         data_datum.dsize = sizeof(int);
204                                         rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
205                                         if (rcode < 0) {
206                                                 printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
207                                                         indexdbname, gdbm_strerror(gdbm_errno));
208                                                 gdbm_close(indexdb);
209                                                 gdbm_close(sessiondb);
210                                                 return;
211                                         }
212                                         if (num > 0 && entry.extra == 1) {
213                                                 gdbm_delete(sessiondb, save_datum);
214                                         }
215                                 }
216                         }
217                 }
218         }
219         key_datum.dptr = NULL;
220
221         if (cli != 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);
228                                 /*
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.
231                                 */
232                                 if (strcmp(entry.cli,cli) == 0 && entry.active){
233                                         if (old){
234                                                 memcpy(&old_key,key_datum.dptr,sizeof(ippool_key));
235                                                 if (!strcmp(old_key.nas,NASname)){
236                                                         mppp = 1;
237                                                         break;
238                                                 }
239                                         }
240                                         else{
241                                                 mppp = 1;
242                                                 break;
243                                         }
244                                 }
245                         }
246                         nextkey = gdbm_nextkey(sessiondb, key_datum);
247                         free(key_datum.dptr);
248                         key_datum = nextkey;
249                 }
250         }
251
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);
259
260                                 if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) {
261                                         datum tmp;
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);
268                                                 if (num == 0){
269                                                         delete = 1;
270                                                         break;
271                                                 }
272                                         } else {
273                                                 delete = 1;
274                                                 break;
275                                         }
276                                 }
277                         }
278                         nextkey = gdbm_nextkey(sessiondb, key_datum);
279                         free(key_datum.dptr);
280                         key_datum = nextkey;
281                 }
282         }
283
284         if (key_datum.dptr){
285                 if (found && ! mppp){
286                         datum key_datum_tmp,data_datum_tmp;
287                         old_ippool_key old_key_tmp;
288                         ippool_key key_tmp;
289                         if (old){
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);
295                         }
296                         else{
297                                 memcpy(key_tmp.key,key_str,16);
298                                 key_datum_tmp.dptr = (char *) &key_tmp;
299                                 key_datum_tmp.dsize = sizeof(ippool_key);
300                         }
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);
304                                 if (rcode < 0) {
305                                         printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
306                                                 sessiondbname, gdbm_strerror(gdbm_errno));
307                                                 gdbm_close(indexdb);
308                                                 gdbm_close(sessiondb);
309                                         return;
310                                 }
311                                 free(data_datum_tmp.dptr);
312                         }
313                 } else {
314                         if (delete)
315                                 gdbm_delete(sessiondb, key_datum);
316                         else {
317                                 if (mppp)
318                                         extra = 1;
319 #if 0
320                                 if (!mppp)
321                                         printf("Error in if statements!!!\n");
322 #endif
323                         }
324                 }
325                 free(key_datum.dptr);
326                 entry.active=1;
327                 if (extra)
328                         entry.extra=1;
329                 data_datum.dptr = (char *) &entry;
330                 data_datum.dsize = sizeof(ippool_info);
331
332                 if (old){
333                         strlcpy(old_key.nas,NASname,sizeof(old_key.nas));
334                         old_key.port = port;
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);
338                 }
339                 else{
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);
344                 }
345                 rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
346                 if (rcode < 0) {
347                         printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
348                                 sessiondbname, gdbm_strerror(gdbm_errno));
349                         gdbm_close(indexdb);
350                         gdbm_close(sessiondb);
351                         return;
352                 }
353
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);
361                 } else
362                         num = 0;
363                 num++;
364                 printf("rlm_ippool_tool: num: %d\n",num);
365                 data_datum.dptr = (char *) &num;
366                 data_datum.dsize = sizeof(int);
367                 rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
368                 if (rcode < 0) {
369                         printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
370                                 indexdbname, gdbm_strerror(gdbm_errno));
371                         gdbm_close(indexdb);
372                         gdbm_close(sessiondb);
373                         return;
374                 }
375
376                 if (old)
377                         printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
378                                 ipaddress, old_key.nas,port);
379                 else
380                         printf("rlm_ippool_tool: Allocated ip %s to key  '%s'\n",ipaddress,hex_str);
381
382         }
383     gdbm_close(indexdb);
384     gdbm_close(sessiondb);
385 }
386 void tonewformat(char *sessiondbname,char *newsessiondbname){
387     GDBM_FILE sessiondb;
388     GDBM_FILE newsessiondb;
389     datum key_datum,keynext_datum,data_datum,newkey_datum;
390     old_ippool_key old_key;
391     ippool_key key;
392     uint8_t key_str[17];
393     char hex_str[35];
394     int rcode;
395
396     sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
397     newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
398
399     if (sessiondb==NULL || newsessiondb==NULL) return;
400
401     memset(key_str,0,17);
402
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;
409
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);
417                 hex_str[32] = '\0';
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);
425                     if (rcode < 0) {
426                                 printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
427                                 gdbm_close(newsessiondb);
428                                 gdbm_close(sessiondb);
429                                 return;
430                         }
431                 }
432         }
433         key_datum=keynext_datum;
434     }
435     gdbm_close(newsessiondb);
436     gdbm_close(sessiondb);
437 }
438
439 void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
440     GDBM_FILE sessiondb;
441     GDBM_FILE indexdb;
442     datum key_datum,keynext_datum,data_datum,save_datum;
443     old_ippool_key old_key;
444     ippool_key key;
445     ippool_info info;
446     struct in_addr ipaddr;
447     int num;
448     uint8_t key_str[17];
449     char hex_str[35];
450     char *ip;
451     int mode=GDBM_READER;
452     int rcode;
453
454     if (rflag) mode=GDBM_WRITER;
455     sessiondb=gdbm_open(sessiondbname,512,mode,0,NULL);
456     indexdb=gdbm_open(indexdbname,512,mode,0,NULL);
457
458     if (sessiondb==NULL || indexdb==NULL) return;
459
460     memset(key_str,0,17);
461
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)) {
466             if (old)
467                  memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
468             else
469                  memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
470
471             data_datum=gdbm_fetch(sessiondb,key_datum);
472             if (data_datum.dptr!=NULL) {
473
474                 memcpy(&info,data_datum.dptr,sizeof(struct ippool_info));
475                 memcpy(&ipaddr,&info.ipaddr,4);
476                 ip=inet_ntoa(ipaddr);
477
478                 if (info.active) active++;
479                 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
480                     if (old)
481                         printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
482                     else{
483                         memcpy(key_str,key.key,16);
484                         fr_bin2hex(key_str,hex_str,16);
485                         hex_str[32] = '\0';
486                         printf("KEY: '%s' - ",hex_str);
487                     }
488                 }
489                 if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
490                     printf("%s\n",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);
494
495                 /*
496                  * algorythm copied from rlm_ippool.c:
497                  * - set active to zero
498                  * - set number of sessions to zero
499                  */
500                 if (rflag && MATCH_IP(ipaddress,ip)) {
501                     info.active=0;
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);
507                     if (rcode < 0) {
508                                 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
509                                 gdbm_close(indexdb);
510                                 gdbm_close(sessiondb);
511                                 return;
512                         }
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));
518                                 if (num>0) {
519                                         num--;
520                                         data_datum.dptr = (char *) &num;
521                                         data_datum.dsize = sizeof(int);
522                                         rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE);
523                                         if (rcode < 0) {
524                                                 printf("Failed to update %s: %s\n",ip,gdbm_strerror(gdbm_errno));
525                                                 gdbm_close(indexdb);
526                                                 gdbm_close(sessiondb);
527                                                 return;
528                                         }
529                                         if (num > 0 && info.extra == 1) {
530                                                 gdbm_delete(sessiondb, save_datum);
531                                         }
532                                 }
533                     }
534                 }
535
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);
543                 }
544                 if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
545                     printf("\n");
546             } else
547                 if (vflag && ipaddress==NULL){
548                     if (old)
549                         printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
550                     else{
551                         memcpy(key_str,key.key,16);
552                         fr_bin2hex(key_str,hex_str,16);
553                         hex_str[32] = '\0';
554                         printf("KEY: '%s' - ",hex_str);
555                     }
556                 }
557         }
558         key_datum=keynext_datum;
559     }
560     gdbm_close(indexdb);
561     gdbm_close(sessiondb);
562 }
563
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");
577     exit(0);
578 }
579
580 int main(int argc,char **argv) {
581     int ch;
582     char *argv0=argv[0];
583
584     while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
585         switch (ch) {
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);
594         }
595     argc -= optind;
596     argv += optind;
597
598     if ((argc==2 || argc==3) && !nflag && !uflag) {
599                 viewdb(argv[0],argv[1],argv[2],oflag);
600                 if (cflag) printf("%d\n",active);
601         } else
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]);
606                 else
607                         usage(argv0);
608     return 0;
609 }