mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-22 14:32:25 +00:00
738b70b513
- refactor hlrSid() to not return pointer to static buffer, take 3rd arg instead - introduce SID_STRLEN macro constant, use it everywhere - reformat some code for readability
275 lines
8.4 KiB
C
275 lines
8.4 KiB
C
/*
|
|
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.
|
|
*/
|
|
|
|
/*
|
|
Export the contents of an binary formatted HLR into plain text.
|
|
|
|
*/
|
|
|
|
#include "serval.h"
|
|
|
|
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 */
|
|
if (l!=4+SID_STRLEN)
|
|
exit(setReason("Malformed sid= line encountered in line %d of HLR import file.",linenum));
|
|
|
|
/* Extract SID */
|
|
for(j=0;j<SID_STRLEN;j++) sid[j]=line[4+j]; sid[SID_STRLEN]=0;
|
|
|
|
/* 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.\nThis 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++)
|
|
{
|
|
if (h->value[i]>=' '&&h->value[i]<0x7f&&h->value[i]!='\\'&&(cols||h->value[i]!='#'))
|
|
{
|
|
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;
|
|
}
|