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:
gardners 2012-04-13 09:29:43 +09:30
parent 5ac83f9ca1
commit 6f93d7a48d
4 changed files with 2 additions and 841 deletions

View File

@ -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 \

View File

@ -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
View File

@ -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
View File

@ -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;
}