mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 02:39:44 +00:00
Updated build environment to leave out old HLR stuff that has
been deprecated in favour of the new keyring file.
This commit is contained in:
parent
5ac83f9ca1
commit
6f93d7a48d
@ -43,9 +43,7 @@ LOCAL_SRC_FILES:= \
|
||||
serval-dna/commandline.c \
|
||||
serval-dna/dataformats.c \
|
||||
serval-dna/dna.c \
|
||||
serval-dna/export.c \
|
||||
serval-dna/gateway.c \
|
||||
serval-dna/hlrdata.c \
|
||||
serval-dna/overlay.c \
|
||||
serval-dna/overlay_broadcast.c \
|
||||
serval-dna/packetformats.c \
|
||||
|
@ -1,5 +1,5 @@
|
||||
SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c dataformats.c \
|
||||
hlrdata.c srandomdev.c simulate.c batman.c export.c gateway.c \
|
||||
srandomdev.c simulate.c batman.c gateway.c \
|
||||
overlay.c overlay_buffer.c overlay_interface.c overlay_payload.c overlay_route.c \
|
||||
overlay_packetformats.c overlay_abbreviations.c overlay_advertise.c overlay_mdp.c \
|
||||
rhizome.c rhizome_http.c rhizome_bundle.c rhizome_database.c rhizome_crypto.c \
|
||||
@ -8,7 +8,7 @@ SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c data
|
||||
trans_cache.c keyring.c
|
||||
|
||||
OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \
|
||||
hlrdata.o srandomdev.o simulate.o batman.o export.o gateway.o \
|
||||
srandomdev.o simulate.o batman.o gateway.o \
|
||||
overlay.o overlay_buffer.o overlay_interface.o overlay_payload.o overlay_route.o \
|
||||
overlay_packetformats.o overlay_abbreviations.o overlay_advertise.o overlay_mdp.o \
|
||||
rhizome.o rhizome_http.o rhizome_bundle.o rhizome_database.o rhizome_crypto.o \
|
||||
|
274
export.c
274
export.c
@ -1,274 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
563
hlrdata.c
563
hlrdata.c
@ -1,563 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
int hlrGetRecordLength(unsigned char *hlr,int hofs);
|
||||
|
||||
int bcompare(unsigned char *a,unsigned char *b,size_t len)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<len;i++) if (a[i]<b[i]) return -1; else if (a[i]>b[i]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int seedHlr()
|
||||
{
|
||||
/* If HLR is empty, create a default entry */
|
||||
int offset=0;
|
||||
if (!nextHlr(hlr,&offset)) {
|
||||
/* There is an entry, so nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* There wasn't an entry, so make one.
|
||||
Pick a random SID (it will pick one for us).
|
||||
For completeness we will pick a random DID, which also makes life easier for us anyway
|
||||
by allowing the use of createHlr().
|
||||
*/
|
||||
{
|
||||
int i,ofs=0;
|
||||
char sid[SID_STRLEN+1];
|
||||
char did[65];
|
||||
/* Make DID start with 2 through 9, as 1 is special in many number spaces. */
|
||||
did[0]='2'+random()%8;
|
||||
/* Then add 10 more digits, which is what we do in the mobile phone software */
|
||||
for(i=1;i<11;i++) did[i]='0'+random()%10; did[11]=0;
|
||||
if (createHlr(did,sid)) return WHY("Failed to seed HLR with home entry");
|
||||
if (hlrSetVariable(hlr,ofs,VAR_LOCATIONS,0,(unsigned char *)"4000@",5)) return WHY("Could not set location while seeding HLR");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nextHlr(unsigned char *hlr,int *ofs)
|
||||
{
|
||||
int record_length;
|
||||
|
||||
if (!ofs) return setReason("nextHlr passed NULL pointer.");
|
||||
if (*ofs>=hlr_size) return -1;
|
||||
|
||||
/* Get length of this record */
|
||||
record_length =hlr[(*ofs)+3]<<0;
|
||||
record_length|=hlr[(*ofs)+2]<<8;
|
||||
record_length|=hlr[(*ofs)+1]<<16;
|
||||
record_length|=hlr[(*ofs)+0]<<24;
|
||||
|
||||
if (record_length<1) return -1;
|
||||
|
||||
(*ofs)+=record_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *hlrSid(unsigned char *hlr, int ofs, char *sid)
|
||||
{
|
||||
int o = ofs + 4;
|
||||
extractSid(hlr, &o, sid);
|
||||
return sid;
|
||||
}
|
||||
|
||||
int findHlr(unsigned char *hlr,int *ofs,char *sid,char *did)
|
||||
{
|
||||
unsigned int record_length;
|
||||
int match=0;
|
||||
int records_searched=0;
|
||||
int pid_len=0;
|
||||
unsigned char packed_id[40];
|
||||
|
||||
if ((*ofs)>=hlr_size) return 0;
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Searching for HLR record sid=[%s]/did=[%s]\n",sid?sid:"NULL",did?did:"NULL");
|
||||
|
||||
if (did&&did[0]) {
|
||||
/* Make packed version of DID so that we can compare faster with the DIDs in the HLR */
|
||||
if (stowDid(packed_id,&pid_len,did)) return setReason("DID appears to be invalid");
|
||||
/* Find significant length of packed DID */
|
||||
for(pid_len=0;pid_len<DID_MAXSIZE;pid_len++) if ((packed_id[pid_len]&0x0f)==0x0f) { pid_len++; break; }
|
||||
if (debug&DEBUG_HLR) dump("Searching for DID records that match",packed_id,pid_len);
|
||||
}
|
||||
|
||||
if (sid&&sid[0]) {
|
||||
/* Make packed version of SID for fast comparison */
|
||||
if (stowSid(packed_id,pid_len,sid)) return setReason("SID appears to be invalid");
|
||||
pid_len=SID_SIZE;
|
||||
}
|
||||
|
||||
while(!match)
|
||||
{
|
||||
/* Get length of this record */
|
||||
record_length =hlr[(*ofs)+3]<<0;
|
||||
record_length|=hlr[(*ofs)+2]<<8;
|
||||
record_length|=hlr[(*ofs)+1]<<16;
|
||||
record_length|=hlr[(*ofs)+0]<<24;
|
||||
|
||||
if (!record_length) return 0;
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Considering HLR entry @ 0x%x\n",*ofs);
|
||||
|
||||
records_searched++;
|
||||
|
||||
if (sid&&sid[0]) {
|
||||
/* Lookup by SID, so just see if it matches */
|
||||
if (!bcompare(packed_id,&hlr[(*ofs)+4],SID_SIZE)) {
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Found requested SID at address 0x%x.\n",*ofs);
|
||||
match=1;
|
||||
}
|
||||
}
|
||||
if (did&&did[0]) {
|
||||
/* Lookup by did, so see if there are any matching DID entries for this subscriber */
|
||||
int rofs=(*ofs);
|
||||
struct hlrentry_handle *h=openhlrentry(hlr,rofs);
|
||||
while(h)
|
||||
{
|
||||
/* Search through variables for matching DIDs */
|
||||
if (debug&DEBUG_HLR) {
|
||||
fprintf(stderr,"Considering variable 0x%02x, instance %d.\n",
|
||||
h->var_id,h->var_instance);
|
||||
dump("variable value",h->value,h->value_len);
|
||||
}
|
||||
if (h->var_id==VAR_DIDS) { /* DID entry */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Checking DID against record DID\n");
|
||||
if (!bcompare(packed_id,h->value,pid_len)) {
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Found matching DID in HLR record #%d\n",records_searched);
|
||||
match=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Skipping non-DID variable while searching for DID.\n");
|
||||
}
|
||||
h=hlrentrygetent(h);
|
||||
}
|
||||
}
|
||||
if ((!sid)&&(!did)) match=1;
|
||||
|
||||
/* For each match ... */
|
||||
if (match)
|
||||
{
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Returning HLR entry @ 0x%x\n",*ofs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Consider next record */
|
||||
(*ofs)+=record_length;
|
||||
|
||||
if ((*ofs)>=hlr_size) return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createHlr(char *did,char *sid) {
|
||||
int i;
|
||||
int record_offset=0;
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Asked to create a new HLR record\n");
|
||||
|
||||
/* Generate random SID */
|
||||
for (i = 1; i != SID_STRLEN; ++i)
|
||||
sid[i] = hexdigit[random() & 0xf];
|
||||
sid[SID_STRLEN]=0;
|
||||
/* But make sure first digit is non-zero as required by the overlay mesh */
|
||||
sid[0]=hexdigit[1+(random()&0xe)];
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Creating new HLR entry with sid %s\n",sid);
|
||||
|
||||
/* Find first free byte of HLR.
|
||||
Keep calling findHlr() until we find the end. */
|
||||
while((i=hlrGetRecordLength(hlr,record_offset))>0)
|
||||
{
|
||||
record_offset+=i;
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Skipping %d bytes to 0x%x\n",i,record_offset);
|
||||
}
|
||||
if (i<0) return setReason("Corrupt HLR: Negative length field encountered.");
|
||||
|
||||
if (record_offset>=hlr_size)
|
||||
{
|
||||
/* No space */
|
||||
return setReason("No space in HLR for a new record");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have found space, but is it enough? */
|
||||
int bytes=hlr_size-record_offset;
|
||||
if (bytes<1024) return setReason("<1KB space in HLR");
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Creating new HLR entry @ 0x%x\n",record_offset);
|
||||
|
||||
/* Write shiny fresh new record.
|
||||
32bit - record length
|
||||
32 bytes - SID
|
||||
Total length = 4+32=36 bytes.
|
||||
*/
|
||||
if (stowSid(hlr,record_offset+4,sid)) return setReason("Could not store SID in new HLR entry");
|
||||
|
||||
/* Write length last of all to make entry valid */
|
||||
hlr[record_offset]=0;
|
||||
hlr[record_offset+1]=0;
|
||||
hlr[record_offset+2]=0;
|
||||
hlr[record_offset+3]=36;
|
||||
|
||||
/* Store the DID */
|
||||
{
|
||||
unsigned char packeddid[DID_MAXSIZE];
|
||||
int pdidlen=0;
|
||||
stowDid(packeddid,&pdidlen,did);
|
||||
/* Work out reduced length of DID */
|
||||
for(pdidlen=1;pdidlen<DID_MAXSIZE;pdidlen++) if (packeddid[pdidlen-1]==0xff) break;
|
||||
hlrSetVariable(hlr,record_offset,VAR_DIDS,0x00,packeddid,pdidlen);
|
||||
}
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Created new 36 byte HLR record for DID=[%s] @ 0x%x with SID=[%s]\n",
|
||||
did,record_offset,sid);
|
||||
if (debug&DEBUG_HLR) dump("after HLR create",&hlr[0],256);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return setReason("Unreachable code turned out not to be");
|
||||
}
|
||||
|
||||
struct hlrentry_handle hlr_handle;
|
||||
|
||||
int hlrGetRecordLength(unsigned char *hlr,int hofs)
|
||||
{
|
||||
int record_length;
|
||||
record_length =hlr[hofs+3]<<0;
|
||||
record_length|=hlr[hofs+2]<<8;
|
||||
record_length|=hlr[hofs+1]<<16;
|
||||
record_length|=hlr[hofs+0]<<24;
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"HLR record @ 0x%x is %d bytes long.\n",hofs,record_length);
|
||||
|
||||
if (record_length<0) {
|
||||
// fix corrupt entries
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"HLR record @ 0x%x ZEROED.\n",hofs);
|
||||
hlr[hofs+3]=0;
|
||||
hlr[hofs+2]=0;
|
||||
hlr[hofs+1]=0;
|
||||
hlr[hofs+0]=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return record_length;
|
||||
}
|
||||
|
||||
int hlrSetRecordLength(unsigned char *hlr,int hofs,int length)
|
||||
{
|
||||
if (length<0) length=0;
|
||||
|
||||
hlr[hofs+3]=length&0xff;
|
||||
hlr[hofs+2]=(length>>8)&0xff;
|
||||
hlr[hofs+1]=(length>>16)&0xff;
|
||||
hlr[hofs+0]=(length>>24)&0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
XXX We could return a fancy struct, and maybe we should.
|
||||
But returning a long long and using the two 32bit halves is easy for now, and has a
|
||||
certain efficiency to it. */
|
||||
struct hlrentry_handle *openhlrentry(unsigned char *hlr,int hofs)
|
||||
{
|
||||
int record_length=hlrGetRecordLength(hlr,hofs);
|
||||
|
||||
/* If record has zero length, then open fails */
|
||||
if (record_length<1)
|
||||
{
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"HLR record is zero length -- aborting.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bzero(&hlr_handle,sizeof(hlr_handle));
|
||||
|
||||
hlr_handle.record_length=record_length;
|
||||
hlr_handle.hlr=hlr;
|
||||
hlr_handle.hlr_offset=hofs;
|
||||
hlr_handle.var_id=-1;
|
||||
hlr_handle.var_instance=-1;
|
||||
hlr_handle.value=NULL;
|
||||
hlr_handle.value_len=-1;
|
||||
hlr_handle.entry_offset=0;
|
||||
|
||||
/* Return offset of start of HLR entry and the offset of the first variable */
|
||||
return hlrentrygetent(&hlr_handle);
|
||||
}
|
||||
|
||||
struct hlrentry_handle *hlrentrygetent(struct hlrentry_handle *h)
|
||||
{
|
||||
int ptr;
|
||||
|
||||
if (!h) return NULL;
|
||||
|
||||
if (h->entry_offset==0)
|
||||
{
|
||||
/* First entry */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Considering first entry of HLR record.\n");
|
||||
h->entry_offset=HLR_RECORD_LEN_SIZE+SID_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* subsequent entry */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Considering entry @ 0x%x\n",h->entry_offset);
|
||||
h->entry_offset+=1+2+h->value_len+(h->var_id&0x80?1:0);
|
||||
}
|
||||
|
||||
/* XXX Check if end of record */
|
||||
if (h->entry_offset>=h->record_length) {
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Reached end of HLR record (%d>=%d).\n",h->entry_offset,h->record_length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX Extract variable */
|
||||
ptr=h->hlr_offset+h->entry_offset;
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Extracting HLR variable @ 0x%x\n",ptr);
|
||||
h->var_id=hlr[ptr];
|
||||
h->value_len=(hlr[ptr+1]<<8)+hlr[ptr+2];
|
||||
ptr+=3;
|
||||
if (h->var_id&0x80) h->var_instance=hlr[ptr++];
|
||||
h->value=&h->hlr[ptr];
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
int hlrGetVariable(unsigned char *hlr,int hofs,int varid,int varinstance,
|
||||
unsigned char *value,int *len)
|
||||
{
|
||||
struct hlrentry_handle *h;
|
||||
int hlr_offset=-1;
|
||||
|
||||
h=openhlrentry(hlr,hofs);
|
||||
|
||||
/* Find the place in the HLR record where this variable is */
|
||||
while(h)
|
||||
{
|
||||
if ((h->var_id<varid)
|
||||
||(h->var_id==varid&&h->var_instance<varinstance))
|
||||
hlr_offset=h->entry_offset;
|
||||
else
|
||||
{
|
||||
/* Value is here if anywhere */
|
||||
if (h->var_id>varid||h->var_instance>varinstance)
|
||||
return setReason("No such variable instance");
|
||||
if (h->value_len>*len) return setReason("Value too long for buffer");
|
||||
bcopy(h->value,value,h->value_len);
|
||||
*len=h->value_len;
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
h=hlrentrygetent(h);
|
||||
}
|
||||
|
||||
return setReason("No such variable instance");
|
||||
}
|
||||
|
||||
int hlrSetVariable(unsigned char *hlr,int hofs,int varid,int varinstance,
|
||||
unsigned char *value,int len)
|
||||
{
|
||||
/* hlr & hofs identify the start of a HLR entry. */
|
||||
|
||||
struct hlrentry_handle *h;
|
||||
int hlr_offset=-1;
|
||||
int hlr_size=hlrGetRecordLength(hlr,hofs);
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"hlrSetVariable(varid=%02x, instance=%02x, len=%d)\n",
|
||||
varid,varinstance,len);
|
||||
|
||||
h=openhlrentry(hlr,hofs);
|
||||
|
||||
/* Find the place in the HLR record where this variable should go */
|
||||
while(h)
|
||||
{
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"h->var_id=%02x, h->h->var_instance=%02x, h->entry_offset=%x\n",
|
||||
h->var_id,h->var_instance,h->entry_offset);
|
||||
if ((h->var_id<varid)
|
||||
||((h->var_id&0x80)&&(h->var_id==varid&&h->var_instance<varinstance)))
|
||||
{
|
||||
hlr_offset=h->entry_offset;
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Found variable instance prior: hlr_offset=%d.\n",hlr_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Value goes here */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Found variable instance to overwrite: hlr_offset=%d.\n",hlr_offset);
|
||||
hlr_offset=h->entry_offset;
|
||||
break;
|
||||
}
|
||||
h=hlrentrygetent(h);
|
||||
}
|
||||
|
||||
/* XXX Race condition: If power is lost half way through here, then it is possible for
|
||||
the record to be left in an inconsistent state */
|
||||
|
||||
if (h&&hlr_offset>-1)
|
||||
{
|
||||
if (debug&DEBUG_HLR) printf("hlr_offset=%d\n",hlr_offset);
|
||||
if (h&&h->var_id==varid&&((h->var_instance==varinstance)||(!(h->var_id&0x80))))
|
||||
{
|
||||
int existing_size;
|
||||
/* Replace existing value */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Replacing value in HLR:\n");
|
||||
existing_size=1+2+((h->var_id&0x80)?1:0)+h->value_len;
|
||||
hlrMakeSpace(hlr,hofs,hlr_offset,1+2+len+((varid&0x80)?1:0)-existing_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert value here */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Inserting value in HLR\n");
|
||||
hlrMakeSpace(hlr,hofs,hlr_offset,1+2+len+((varid&0x80)?1:0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HLR record has no entries, or this entry needs to go at the end,
|
||||
so insert value at end of the record */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Inserting value at end of HLR @ 0x%x\n",hlr_size);
|
||||
hlrMakeSpace(hlr,hofs,hlr_size,1+2+len+((varid&0x80)?1:0));
|
||||
hlr_offset=hlr_size;
|
||||
}
|
||||
|
||||
return hlrStowValue(hlr,hofs,hlr_offset,varid,varinstance,value,len);
|
||||
}
|
||||
|
||||
int hlrStowValue(unsigned char *hlr,int hofs,int hlr_offset,
|
||||
int varid,int varinstance,unsigned char *value,int len)
|
||||
{
|
||||
int ptr=hofs+hlr_offset;
|
||||
|
||||
hlr[ptr++]=varid;
|
||||
hlr[ptr++]=(len>>8)&0xff;
|
||||
hlr[ptr++]=len&0xff;
|
||||
if (varid&0x80) hlr[ptr++]=varinstance;
|
||||
bcopy(value,&hlr[ptr],len);
|
||||
ptr+=len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hlrMakeSpace(unsigned char *hlr,int hofs,int hlr_offset,int bytes)
|
||||
{
|
||||
int length;
|
||||
int shifted_bytes=hlr_size-(hofs+hlr_offset+bytes);
|
||||
/* Don't read past end of file */
|
||||
if (bytes<0) shifted_bytes+=bytes;
|
||||
|
||||
/* Deal with easy case first */
|
||||
if (!bytes) return 0;
|
||||
|
||||
if (debug&DEBUG_HLR) {
|
||||
fprintf(stderr,"hlrMakeSpace: Inserting %d bytes at offset %d with hofs=%d. shifted bytes=%d\n",
|
||||
bytes,hlr_offset,hofs,shifted_bytes);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
/* Shift rest of HLR up/down.
|
||||
If down, back-fill bytes with zeros. */
|
||||
bcopy(&hlr[hofs+hlr_offset],&hlr[hofs+hlr_offset+bytes],
|
||||
shifted_bytes);
|
||||
if (bytes<0) bzero(&hlr[hlr_size+bytes],0-bytes);
|
||||
|
||||
/* Update record length */
|
||||
length=hlrGetRecordLength(hlr,hofs);
|
||||
length+=bytes;
|
||||
hlrSetRecordLength(hlr,hofs,length);
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"hlrMakeSpace: HLR entry now %d bytes long.\n",length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hlrDump(unsigned char *hlr,int hofs)
|
||||
{
|
||||
struct hlrentry_handle *h=openhlrentry(hlr,hofs);
|
||||
|
||||
fprintf(stderr,"Dumping HLR entry @ 0x%x\n",hofs);
|
||||
while(h)
|
||||
{
|
||||
fprintf(stderr," var=%02x",h->var_id);
|
||||
if (h->var_id&0x80) fprintf(stderr,"/%02x",h->var_instance);
|
||||
fprintf(stderr," len=%d\n",h->value_len);
|
||||
h=hlrentrygetent(h);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openHlrFile(char *backing_file,int size)
|
||||
{
|
||||
/* Get backing store */
|
||||
if (!backing_file)
|
||||
{
|
||||
if (size<0) exit(setReason("You must provide an HLR file or size"));
|
||||
|
||||
/* transitory storage of HLR data, so just malloc() the memory */
|
||||
hlr=calloc(size,1);
|
||||
if (!hlr) exit(setReason("Failed to calloc() HLR database."));
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Allocated %d byte temporary HLR store\n",size);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char zero[8192];
|
||||
FILE *f=fopen(backing_file,"r+");
|
||||
if (!f) f=fopen(backing_file,"w+");
|
||||
if (!f) exit(setReason("Could not open backing file."));
|
||||
bzero(&zero[0],8192);
|
||||
fseek(f,0,SEEK_END);
|
||||
errno=0;
|
||||
|
||||
/* Obtain size from existing backing file */
|
||||
if (size<0) size=ftell(f);
|
||||
|
||||
while(ftell(f)<size)
|
||||
{
|
||||
int r;
|
||||
fseek(f,0,SEEK_END);
|
||||
if ((r=fwrite(zero,8192,1,f))!=1)
|
||||
{
|
||||
perror("fwrite");
|
||||
exit(setReason("Could not enlarge backing file to requested size (short write)"));
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
}
|
||||
|
||||
if (errno) perror("fseek");
|
||||
if (fwrite("",1,1,f)!=1)
|
||||
{
|
||||
fprintf(stderr,"Failed to set backing file size.\n");
|
||||
perror("fwrite");
|
||||
}
|
||||
hlr=(unsigned char *)mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fileno(f),0);
|
||||
if (hlr==MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(setReason("Memory mapping of HLR backing file failed."));
|
||||
}
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Allocated %d byte HLR store backed by file `%s'\n",
|
||||
size,backing_file);
|
||||
}
|
||||
hlr_size=size;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user