2011-12-21 09:55:05 +00:00
/*
Serval Distributed Numbering Architecture ( DNA )
Copyright ( C ) 2010 Paul Gardner - Stephen
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
of the License , 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 . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
2011-05-06 02:27:33 +00:00
/*
Export the contents of an binary formatted HLR into plain text .
*/
2012-02-23 02:15:42 +00:00
# include "serval.h"
2011-05-06 02:27:33 +00:00
int nyblValue ( int c )
{
if ( c > = ' 0 ' & & c < = ' 9 ' ) return c - ' 0 ' ;
if ( c > = ' A ' & & c < = ' F ' ) return c - ' A ' + 10 ;
if ( c > = ' a ' & & c < = ' f ' ) return c - ' a ' + 10 ;
exit ( setReason ( " Illegal character `%c' in hexadecimal value. " , c ) ) ;
}
int importHlr ( char * textfile )
{
int j ;
FILE * i ;
unsigned char line [ 1024 ] ;
char sid [ 128 ] ;
int state = 0 ;
int hofs = - 1 ;
int varinst ;
int varid ;
int varlen ;
unsigned char data [ 65536 ] ;
int dlen = 0 ;
int linenum = 0 ;
if ( ! strcmp ( " - " , textfile ) ) i = stdin ;
else
if ( ( i = fopen ( textfile , " r " ) ) = = NULL ) exit ( setReason ( " Could not open import file `%s' " ) ) ;
line [ 0 ] = 0 ; fgets ( ( char * ) line , 1024 , i ) ;
while ( ! feof ( i ) )
{
int l = strlen ( ( char * ) line ) ;
linenum + + ;
/* Strip CR/LFs */
while ( l > 0 & & ( line [ l - 1 ] = = ' \n ' | | line [ l - 1 ] = = ' \r ' ) ) l - - ; line [ l ] = 0 ;
/* Sanity check line */
for ( j = 0 ; j < l ; j + + ) if ( ( line [ j ] < ' ' ) | | ( ( line [ j ] > 0x7f ) & & line [ j ] ! = ' \n ' ) ) {
exit ( setReason ( " Illegal character 0x%02x encountered in line %d of HLR import file. " , line [ j ] , linenum ) ) ;
}
if ( line [ 0 ] ! = ' # ' )
{
/* Deal with line */
switch ( state )
{
case 0 : /* looking for a control line */
if ( ! strncmp ( " sid= " , ( char * ) line , 4 ) ) {
/* Read SID, and create HLR record for it if one doesn't already exist */
2012-03-13 08:01:29 +00:00
if ( l ! = 4 + SID_STRLEN )
2011-05-06 02:27:33 +00:00
exit ( setReason ( " Malformed sid= line encountered in line %d of HLR import file. " , linenum ) ) ;
/* Extract SID */
2012-03-13 08:01:29 +00:00
for ( j = 0 ; j < SID_STRLEN ; j + + ) sid [ j ] = line [ 4 + j ] ; sid [ SID_STRLEN ] = 0 ;
2011-05-06 02:27:33 +00:00
/* Find or Create HLR Record */
if ( findHlr ( hlr , & hofs , sid , NULL ) )
{
/* Have found HLR record for this SID, so no need to create */
}
else
{
/* No matching HLR record, so create one.
Actually , we can ' t create it until we have the first DID for it ,
so set hofs to - 1 to remind us to do that . */
hofs = - 1 ;
}
/* Note that now we are looking for record contents */
state = 1 ;
} else {
exit ( setReason ( " Unexpected line encountered in line %d of HLR import file -- was looking for a sid= line. " , linenum ) ) ;
}
break ;
case 1 : /* Reading a HLR record set of values */
if ( ! strcmp ( " eor " , ( char * ) line ) )
{
state = 0 ;
if ( hofs = = - 1 )
{
/* whoops, we never got around to creating this record because it didn't contain any DIDs.
This is something that should probably be complained about .
It could also potentially arise when importing an export from an unhappy HLR , but because of the way
that we enforce the presense of at least on DID when creating an HLR entry , this should not occur in
normal operations . */
exit ( setReason ( " Encountered end of exported record at line %d without seeing a DID assignment. This is bad. \n "
" sid= should be followed by a var=80:00 line. " , linenum ) ) ;
}
}
else if ( sscanf ( ( char * ) line , " var=%02x:%02x len=%d " , & varid , & varinst , & varlen ) = = 3 ) {
if ( varid < 0x80 | | varid > 0xff )
exit ( setReason ( " %s:%d var= line contains illegal variable ID. "
" Multi-value variables must be in the range 80-ff (hexadecimal) " , textfile , linenum ) ) ;
if ( varinst < 0 | | varinst > 0xff )
exit ( setReason ( " %s:%d var= line contains illegal variable instance number. Must be in the range 00-ff (hexadecimal) " ,
textfile , linenum ) ) ;
if ( varlen < 1 | | varlen > 65534 )
exit ( setReason ( " %s:%d var= line contains illegal length. Must be in the range 1-65534. " , textfile , linenum ) ) ;
/* Okay, we have a valid variable, lets switch to accumulating its value */
dlen = 0 ;
state = 2 ;
}
else if ( sscanf ( ( char * ) line , " var=%02x len=%d " , & varid , & varlen ) = = 2 ) {
if ( varid > 0x7f | | varid < 0 )
exit ( setReason ( " %s:%d var= line contains illegal variable ID. "
" Single-value variables must be in the range 00-7f (hexadecimal) " , textfile , linenum ) ) ;
varinst = 0 ;
if ( varlen < 1 | | varlen > 65534 )
exit ( setReason ( " %s:%d var= line contains illegal length. Must be in the range 1-65534. " , textfile , linenum ) ) ;
/* Okay, we have a valid variable, lets switch to accumulating its value */
dlen = 0 ;
state = 2 ;
} else {
exit ( setReason ( " %s:%d Syntax error in HLR record. " , textfile , linenum ) ) ;
}
break ;
case 2 : /* Reading a variable value */
/* Read line of data */
for ( j = 0 ; j < l ; )
{
if ( dlen > = varlen )
exit ( setReason ( " %s:%d Variable value data exceeds stated length. \n This is what was left after I had taken all I needed: `%s'. " , textfile , linenum , & line [ j ] ) ) ;
switch ( line [ j ] )
{
case ' \\ ' :
j + + ;
switch ( line [ j ] )
{
case ' n ' : data [ dlen + + ] = ' \n ' ; break ;
case ' r ' : data [ dlen + + ] = ' \r ' ; break ;
case ' x ' : data [ dlen + + ] = ( hexvalue ( line [ j + 1 ] ) < < 4 ) + hexvalue ( line [ j + 2 ] ) ; j + = 2 ; break ;
default :
exit ( setReason ( " %s:%d Illegal \\ sequence ` \\ %c' encountered in variable value. Only \\ r, \\ n and \\ x are accepted. " , textfile , linenum , line [ j ] ) ) ;
}
break ;
default :
data [ dlen + + ] = line [ j ] ;
}
j + + ;
}
if ( dlen = = varlen ) {
state = 1 ;
if ( hofs = = - 1 ) {
if ( varid ! = VAR_DIDS | | varinst ! = 0 )
{
/* This variable instance is not the first DID, but we still need to create the HLR record.
This is naughty . The first var = line after a sid = line MUST be var = 80 : 00 to specify the first DID . */
exit ( setReason ( " %s:%d The first var= line after a sid= line MUST be var=80:00 to specify the first DID. " , textfile , linenum ) ) ;
}
else
{
/* Okay, this is the first DID, so now we can create the HLR record.
But first , we need to unpack the DID into ascii */
char did [ SIDDIDFIELD_LEN + 1 ] ;
int zero = 0 ;
extractDid ( data , & zero , did ) ;
printf ( " DID=%s \n " , did ) ;
if ( createHlr ( ( char * ) did , sid ) )
exit ( setReason ( " %s:%d createHlr() failed. " , textfile , linenum ) ) ;
hofs = 0 ;
findHlr ( hlr , & hofs , NULL , did ) ;
if ( hofs < 0 )
exit ( setReason ( " %s:%d Could not find created HLR record. " , textfile , linenum ) ) ;
}
}
}
}
}
line [ 0 ] = 0 ; fgets ( ( char * ) line , 1024 , i ) ;
}
fclose ( i ) ;
return 0 ;
}
int exportHlr ( unsigned char * hlr_file , char * text )
{
FILE * o ;
int ofs = 0 , i ;
if ( openHlrFile ( ( char * ) hlr_file , - 1 ) ) exit ( setReason ( " Could not open HLR database " ) ) ;
if ( ! strcmp ( " - " , text ) ) o = stdout ;
else
if ( ( o = fopen ( text , " w " ) ) = = NULL ) exit ( setReason ( " Could not create export file " ) ) ;
while ( findHlr ( hlr , & ofs , NULL , NULL ) )
{
int hofs = ofs ;
fprintf ( o , " # HLR Record at 0x%08x \n " , ofs ) ;
/* Output SID for this record */
fprintf ( o , " sid= " ) ;
for ( i = 0 ; i < 32 ; i + + ) fprintf ( o , " %02x " , hlr [ hofs + 4 + i ] ) ;
fprintf ( o , " \n " ) ;
struct hlrentry_handle * h = openhlrentry ( hlr , hofs ) ;
while ( h )
{
int cols ;
if ( h - > var_id = = 0 & & h - > value_len = = 0 ) break ;
fprintf ( o , " var=%02x " , h - > var_id ) ;
if ( h - > var_id & 0x80 ) fprintf ( o , " :%02x " , h - > var_instance ) ;
fprintf ( o , " len=%d " , h - > value_len ) ;
for ( i = 0 ; vars [ i ] . name ; i + + ) if ( vars [ i ] . id = = h - > var_id ) { fprintf ( o , " name=%s " , vars [ i ] . name ) ; break ; }
fprintf ( o , " \n " ) ;
cols = 0 ;
for ( i = 0 ; i < h - > value_len ; i + + )
{
2012-03-13 01:19:09 +00:00
if ( h - > value [ i ] > = ' ' & & h - > value [ i ] < 0x7f & & h - > value [ i ] ! = ' \\ ' & & ( cols | | h - > value [ i ] ! = ' # ' ) )
2011-05-06 02:27:33 +00:00
{
fprintf ( o , " %c " , h - > value [ i ] ) ;
cols + + ;
}
else
{
switch ( h - > value [ i ] ) {
case ' \r ' : fprintf ( o , " \\ r " ) ; cols + = 2 ; break ;
case ' \n ' : fprintf ( o , " \\ n " ) ; cols + = 2 ; break ;
default :
fprintf ( o , " \\ x%02x " , ( unsigned char ) h - > value [ i ] ) ; cols + = 4 ;
}
if ( cols > 75 ) { fprintf ( o , " \n " ) ; cols = 0 ; }
}
}
if ( cols ) { fprintf ( o , " \n " ) ; cols = 0 ; }
h = hlrentrygetent ( h ) ;
}
/* Mark the end of the record
( as much to make life easier for the import parser as anything ) */
fprintf ( o , " eor \n " ) ;
/* Advance to next record and keep searching */
if ( nextHlr ( hlr , & ofs ) ) break ;
}
return 0 ;
}