/* $Id: zone.c,v 1.23 2003/09/11 10:58:56 tobiasb Exp $ * * Zonenberechnung * * Copyright 1999 by Leopold Toetsch * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: zone.c,v $ * Revision 1.23 2003/09/11 10:58:56 tobiasb * Do not compute the zone with empty strings as input. * Empty areacodes will occur if the national areacodes are not included in * the destination database. Discovered by Markus Latzel, see article * <3f61378e.550970@n.avalon.psi.talypso.de> in de.comp.os.unix.linux.isdn. * * Revision 1.22 2001/10/15 11:35:46 leo * fixed cdb zonefiles * * Revision 1.21 2001/06/12 14:24:17 paul * zone.c and mkzonedb.c now understand filename "-" to mean stdin. * * Revision 1.20 2001/06/12 13:54:47 paul * zone files are now created byte-order independent, so: * - creating the zone files works on sparc * - CDB files created on e.g. intel can be used without problem om sparc * Our copy of CDB has also been modified for this. * * Revision 1.19 1999/11/07 13:29:29 akool * isdnlog-3.64 * - new "Sonderrufnummern" handling * * Revision 1.18 1999/10/25 18:30:04 akool * isdnlog-3.57 * WARNING: Experimental version! * Please use isdnlog-3.56 for production systems! * * Revision 1.17 1999/10/22 19:57:59 akool * isdnlog-3.56 (for Karsten) * * Revision 1.16 1999/07/31 09:25:49 akool * getRate() speedup * * Revision 1.15 1999/07/26 16:28:51 akool * getRate() speedup from Leo * * Revision 1.14 1999/07/25 15:58:13 akool * isdnlog-3.43 * added "telnum" module * * Revision 1.13 1999/07/10 21:38:54 akool * isdnlog-3.41 * rate-de.dat V:1.02-Germany [10-Jul-1999 23:32:27] * country-de.dat V:1.02-Germany [10-Jul-1999 23:32:36] * added all "zone-*" files in binary mode * * Revision 1.12 1999/07/07 19:44:20 akool * patches from Michael and Leo * * Revision 1.11 1999/07/01 20:44:07 akool * zone-1.12 * * Revision 1.10 1999/06/29 20:11:45 akool * now compiles with ndbm * (many thanks to Nima ) * * Revision 1.9 1999/06/26 12:25:54 akool * isdnlog Version 3.37 * fixed some warnings * * Revision 1.8 1999/06/26 10:12:14 akool * isdnlog Version 3.36 * - EGCS 1.1.2 bug correction from Nima * - zone-1.11 * * Revision 1.7 1999/06/22 19:41:28 akool * zone-1.1 fixes * * Revision 1.6 1999/06/22 16:31:15 akool * zone-1.10 * * Revision 1.4 1999/06/18 12:41:57 akool * zone V1.0 * * Revision 1.3 1999/06/15 20:05:25 akool * isdnlog Version 3.33 * - big step in using the new zone files * - *This*is*not*a*production*ready*isdnlog*!! * - Maybe the last release before the I4L meeting in Nuernberg * * Revision 1.2 1999/06/09 20:58:09 akool * CVS-Tags added * * * Interface: * * int initZone(int provider, char *path, char **msg) * initialize returns -1 on error, 0 if ok * * void exitZone(int provider) * deinitialize * * int getZone(int provider, char *from, char *to) * returns zone for provider, UNKNOWN on not found, -2 on error * * Changes: * * 1.24 1999.10.06 lt removed getAreacode * * 1.23 1999.10... lt switch to getDest * * 1.22 1999.07.26 lt bug fix, getZone returned junk, when diff. providers * used the same zone file * * 1.21 1999.07.22 lt fixed bug, were T was overwritten, when an 'A' * followed versio, occured w. DTAG * * 1.20 1999.07.08 lt added support for NL * * in NL areacode may be shorter than actual aeracodenumber * in this case \tLEN is appended to text * this version reads also datafiles V1.1 * */ #define _ZONE_C_ #ifdef STANDALONE #include #include #ifdef __GLIBC__ # define __USE_GNU /* for declaration of basename() */ #endif #include #include #include #include #include #include #if !defined(__GLIBC__) && !defined(basename) extern const char *basename (const char *name); #endif #else #include "isdnlog.h" #include "tools.h" #endif #include "zone.h" /* this config (from config.in) could go in global policy */ #include "zone/config.h" #include "zone/common.h" #include "zone/upack.h" #include struct sth { _DB fh; char *path; int provider; int used; int real; int *table; char pack_key, pack_table; int table_size; int oz; int numlen; int cc; } ; #ifdef STANDALONE #define min(a,b) (a) < (b) ? (a) : (b) #endif static struct sth *sthp; static int count; static char version[] = "1.25"; #define LINK 127 #define INFO_LEN 80 #define LENGTH 160 #define BUFSIZE 200 #ifdef STANDALONE #define UNKNOWN -1 #endif static void warning (char *file, char *fmt, ...) { va_list ap; char msg[BUFSIZ]; va_start (ap, fmt); vsnprintf (msg, BUFSIZ, fmt, ap); va_end (ap); #ifdef STANDALONE fprintf(stderr, "WARNING: %s %s\n", basename(file), msg); #else print_msg(PRT_NORMAL, "WARNING: %s %s\n", basename(file), msg); #endif } static void _exitZone(int provider); void exitZone(int provider) { int i; _exitZone(provider); for (i=0; i=10000) _exitZone(sthp[i].provider); } static void _exitZone(int provider) { int i; bool any = false; bool found = false; for (i=0; i= 0) sthp[sthp[i].real].used--; else if (sthp[i].path && sthp[i].used == 0) { free(sthp[i].path); sthp[i].path = 0; free(sthp[i].table); sthp[i].table = 0; CLOSE(sthp[i].fh); sthp[i].fh = 0; if (i == count-1) /* last released ? */ count--; } break; } if (!found) { warning(sthp[i].path ? sthp[i].path : sthp[sthp[i].real].path, "ExitZone for unknown provider %d", provider); } for (i=0; i 0) { if (msg) snprintf (message, LENGTH, "Zone V%s: Error: Provider %d File '%s': incompatible Dataversion %s", version, provider, path, dversion); exitZone(provider); return -1; } break; case 'K' : sthp[ocount].pack_key = *(++p); break; case 'C' : sthp[ocount].pack_table = *(++p); break; case 'N' : p++; csize = strtol(p, &p, 10); break; case 'T' : p++; tsize = strtol(p, &p, 10); break; case 'O' : p++; sthp[ocount].oz = strtol(p, &p, 10); break; case 'L' : p++; sthp[ocount].numlen = strtol(p, &p, 10); p--; /* get's incr after, so we miss 0x0*/ break; } } /* for */ if (*dbv == 'G') free (value.dptr); /* check it */ if (strlen(dversion) == 0 || sthp[ocount].pack_key == '\x0' || strchr("SL", sthp[ocount].pack_key) == 0 || sthp[ocount].pack_table == '\x0' || strchr("CSL", sthp[ocount].pack_table) == 0 || sthp[ocount].numlen == 0 || csize == 0 || tsize == 0) { if (msg) snprintf (message, LENGTH, "Zone V%s: Error: Provider %d File '%s' seems to be corrupted:\n%s", version, provider, path, value.dptr); exitZone(provider); return -1; } sthp[ocount].pack_table = sthp[ocount].pack_table == 'C' ? 1 : sthp[ocount].pack_table == 'S' ? 2 : 4; sthp[ocount].pack_key = sthp[ocount].pack_key == 'S' ? 2 : 4; if (area_only) { if (sthp[ocount].cc == 0) _exitZone(provider); /* discard this one */ return 0; } /* alloc & read table */ if ( (sthp[ocount].table = calloc(csize > 256 ? 256 : csize, sizeof(int)) ) == 0) { if (msg) snprintf (message, LENGTH, "Zone V%s: Error: Out of mem 3", version); exitZone(provider); return -1; } key.dptr = table; key.dsize = 7; value = FETCH(sthp[ocount].fh, key); if (value.dptr == 0) { if (msg) snprintf (message, LENGTH, "Zone V%s: Error: Provider %d File '%s': no NTable", version, provider, path); exitZone(provider); return -1; } for (p = value.dptr, i=0; i< (csize > 256 ? 256 : csize); i++) /* sthp[ocount].table[i] = sthp[ocount].pack_table == 1 ? (int)(UC)*((UC*)p)++ : sthp[ocount].pack_table == 2 ? (int)(US)*((US*)p)++ : (int)(UL)*((UL*)p)++; */ switch(sthp[ocount].pack_table) { case 1: sthp[ocount].table[i] = (int)(UC) *p; p++; break; case 2: sthp[ocount].table[i] = (int)tools_unpack16(p); p += 2; break; case 4: sthp[ocount].table[i] = (int)tools_unpack32(p); p += 4; break; } if (*dbv == 'G') free(value.dptr); if (msg) { snprintf (message, LENGTH, "Zone V%s: Provider %d File '%s' opened fine - " "V%s K%d C%d N%d T%d O%d L%d", version, provider, path, dversion, sthp[ocount].pack_key, sthp[ocount].pack_table, csize, tsize, sthp[ocount].oz, sthp[ocount].numlen); } } else { if (msg) #if 1 *message = 0; #else snprintf (message, LENGTH, "Zone V%s: Provider %d is open as '%s' for provider %d", version, provider, path, sthp[sthp[ocount].real].provider); #endif } return 0; } static int _getZ(struct sth *sthp, char *from, char *sto) { _DB fh = sthp->fh; datum key, value; static char newfrom[LENGTH]; bool found = false; char *temp; int res; if (!*from || !*sto) /* empty areacodes cannot be interpreted */ return UNKNOWN; if ((res=strcmp(from, sto)) == 0) return sthp->oz; else if (res > 0) { temp=from; from=sto; sto=temp; } strncpy(newfrom, from, LENGTH-1); while (strlen(newfrom)) { UL lifrom = (UL) atol(newfrom); /* keys could be long */ US ifrom = (US) lifrom; if (sthp->pack_key == 2) { key.dptr = (char *) &ifrom; key.dsize = sizeof(US); } else { key.dptr = (char *) &lifrom; key.dsize = sizeof(UL); } value = FETCH(fh, key); if (value.dptr) { char *p = value.dptr; char to[10]; US count; int ito; unsigned char z=0; if (sthp->cc) /* if areacodes */ /* here is since 1.00 a zero-terminated strring */ while (*p++); // count = *((US*)p)++; count = tools_unpack16(p); p+=2; while (count--) { bool ind = true; int len=1; z = *p++; if (z >= 128) { z -= 128; ind = false; len = sthp->pack_key; } /* ito = len==1 ? (int)*((UC*)p)++ : len==2 ? (int)*((US*)p)++ : (int)*((UL*)p)++; */ switch(len) { case 1: ito = (int)(UC) *p; p++; break; case 2: ito = (int)tools_unpack16(p); p += 2; break; case 4: ito = (int)tools_unpack32(p); p += 4; break; } if (ind) ito = sthp->table[ito]; if (z == LINK) { sprintf(newfrom, "%d", ito); if (*dbv == 'G') free(value.dptr); return _getZ(sthp, newfrom, sto); } else { sprintf(to, "%d", ito); if (memcmp(to, sto, strlen(to))==0) { found = true; break; } } } if (*dbv == 'G') free(value.dptr); if (found) return z; } /* if dptr */ newfrom[strlen(newfrom)-1] = '\0'; } return UNKNOWN; } int getZone(int provider, char *from, char *to) { int i; for (i=0; i