mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
Move from recvfrom() to recvmsg() so that we can get packet TTLs on
reception. Other changes associated with overlay mesh.
This commit is contained in:
parent
8a24fb95b1
commit
5cc6079c0f
43
client.c
43
client.c
@ -79,7 +79,7 @@ int packetSendRequest(int method,unsigned char *packet,int packet_len,int batchP
|
||||
{
|
||||
int r;
|
||||
if (overlayMode)
|
||||
r=overlay_sendto(recvaddr,packet,packet_len);
|
||||
r=overlay_sendto((struct sockaddr_in *)recvaddr,packet,packet_len);
|
||||
else
|
||||
r=sendto(sock,packet,packet_len,0,recvaddr,sizeof(struct sockaddr_in));
|
||||
if (r<packet_len) {
|
||||
@ -210,7 +210,8 @@ int packetSendRequest(int method,unsigned char *packet,int packet_len,int batchP
|
||||
sendToPeers() does it that way. We just have to remember to
|
||||
ask for serialised attempts, rather than all at once.
|
||||
*/
|
||||
int requestNewHLR(char *did,char *pin,char *sid,struct sockaddr *recvaddr)
|
||||
int requestNewHLR(char *did,char *pin,char *sid,
|
||||
int recvttl,struct sockaddr *recvaddr)
|
||||
{
|
||||
unsigned char packet[8000];
|
||||
int packet_len=0;
|
||||
@ -224,11 +225,12 @@ int requestNewHLR(char *did,char *pin,char *sid,struct sockaddr *recvaddr)
|
||||
bcopy(&packet[OFS_TRANSIDFIELD],transaction_id,TRANSID_SIZE);
|
||||
if (packetSetDid(packet,8000,&packet_len,did)) return -1;
|
||||
if (packetAddHLRCreateRequest(packet,8000,&packet_len)) return -1;
|
||||
if (packetFinalise(packet,8000,&packet_len,CRYPT_PUBLIC)) return -1;
|
||||
if (packetFinalise(packet,8000,recvttl,&packet_len,CRYPT_PUBLIC)) return -1;
|
||||
|
||||
/* Send it to peers, starting with ourselves, one at a time until one succeeds.
|
||||
XXX - This could take a while if we have long timeouts for each. */
|
||||
if (packetSendRequest(REQ_SERIAL,packet,packet_len,NONBATCH,transaction_id,recvaddr,&responses)) return -1;
|
||||
if (packetSendRequest(REQ_SERIAL,packet,packet_len,NONBATCH,
|
||||
transaction_id,recvaddr,&responses)) return -1;
|
||||
|
||||
/* Extract response */
|
||||
if (debug&DEBUG_DNARESPONSES) dumpResponses(&responses);
|
||||
@ -344,9 +346,10 @@ int getReplyPackets(int method,int peer,int batchP,struct response_set *response
|
||||
|
||||
/* Use this temporary socket address structure if one was not supplied */
|
||||
struct sockaddr reply_recvaddr;
|
||||
int ttl=-1;
|
||||
if (!recvaddr) recvaddr=&reply_recvaddr;
|
||||
|
||||
len=recvfrom(sock,buffer,sizeof(buffer),0,recvaddr,&recvaddrlen);
|
||||
len=recvwithttl(sock,buffer,sizeof(buffer),&ttl,recvaddr,&recvaddrlen);
|
||||
if (len<=0) return setReason("Unable to receive packet.");
|
||||
|
||||
if (recvaddr) {
|
||||
@ -362,7 +365,7 @@ int getReplyPackets(int method,int peer,int batchP,struct response_set *response
|
||||
if (debug&DEBUG_SIMULATION) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n");
|
||||
continue;
|
||||
}
|
||||
if (!packetOk(-1,buffer,len,transaction_id,recvaddr,recvaddrlen,0)) {
|
||||
if (!packetOk(-1,buffer,len,transaction_id,ttl,recvaddr,recvaddrlen,0)) {
|
||||
/* Packet passes tests - extract responses and append them to the end of the response list */
|
||||
if (extractResponses(client_addr,buffer,len,responses))
|
||||
return setReason("Problem extracting response fields from reply packets");
|
||||
@ -393,7 +396,8 @@ int getReplyPackets(int method,int peer,int batchP,struct response_set *response
|
||||
}
|
||||
|
||||
int writeItem(char *sid,int var_id,int instance,unsigned char *value,
|
||||
int value_start,int value_length,int flags, struct sockaddr *recvaddr)
|
||||
int value_start,int value_length,int flags,
|
||||
int recvttl,struct sockaddr *recvaddr)
|
||||
{
|
||||
unsigned char packet[8000];
|
||||
int packet_len=0;
|
||||
@ -423,7 +427,7 @@ int writeItem(char *sid,int var_id,int instance,unsigned char *value,
|
||||
if (o+bytes>value_length) bytes=value_length-o;
|
||||
if (debug&DEBUG_DNAVARS) fprintf(stderr," writing [%d,%d)\n",o,o+bytes-1);
|
||||
if (writeItem(sid,var_id,instance,&value[o-value_start],o,bytes,
|
||||
flags|((o>value_start)?SET_FRAGMENT:0),NULL))
|
||||
flags|((o>value_start)?SET_FRAGMENT:0),recvttl,NULL))
|
||||
{
|
||||
if (debug&DEBUG_DNAVARS) fprintf(stderr," - writing installment failed\n");
|
||||
return setReason("Failure during multi-packet write of long-value");
|
||||
@ -439,7 +443,7 @@ int writeItem(char *sid,int var_id,int instance,unsigned char *value,
|
||||
if (packetSetSid(packet,8000,&packet_len,sid)) return -1;
|
||||
if (packetAddVariableWrite(packet,8000,&packet_len,var_id,instance,
|
||||
value,value_start,value_length,flags)) return -1;
|
||||
if (packetFinalise(packet,8000,&packet_len,CRYPT_SIGNED|CRYPT_CIPHERED)) return -1;
|
||||
if (packetFinalise(packet,8000,recvttl,&packet_len,CRYPT_SIGNED|CRYPT_CIPHERED)) return -1;
|
||||
|
||||
/* XXX should be able to target to the peer holding the SID, if we have it.
|
||||
In any case, we */
|
||||
@ -525,7 +529,7 @@ int peerAddress(char *did,char *sid,int flags)
|
||||
if (debug&DEBUG_DNAVARS) fprintf(stderr,"%s() failed at line %d\n",__FUNCTION__,__LINE__);
|
||||
return -1;
|
||||
}
|
||||
if (packetFinalise(packet,8000,&packet_len,CRYPT_PUBLIC)) {
|
||||
if (packetFinalise(packet,8000,-1,&packet_len,CRYPT_PUBLIC)) {
|
||||
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"%s() failed at line %d\n",__FUNCTION__,__LINE__);
|
||||
return -1;
|
||||
}
|
||||
@ -564,7 +568,8 @@ int peerAddress(char *did,char *sid,int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffer,int buffer_length,int *len,
|
||||
int requestItem(char *did,char *sid,char *item,int instance,
|
||||
unsigned char *buffer,int buffer_length,int *len,
|
||||
unsigned char *transaction_id)
|
||||
{
|
||||
unsigned char packet[8000];
|
||||
@ -606,7 +611,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"requestItem() failed at line %d\n",__LINE__);
|
||||
return -1;
|
||||
}
|
||||
if (packetFinalise(packet,8000,&packet_len,CRYPT_SIGNED|CRYPT_CIPHERED)) {
|
||||
if (packetFinalise(packet,8000,-1,&packet_len,CRYPT_SIGNED|CRYPT_CIPHERED)) {
|
||||
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"requestItem() failed at line %d\n",__LINE__);
|
||||
return -1;
|
||||
}
|
||||
@ -626,8 +631,8 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
extractSid(r->sid,&slen,sid);
|
||||
switch(r->code)
|
||||
{
|
||||
case ACTION_OKAY: printf("OK:%s\n",sid); if (buffer) {strcpy((char *)buffer,sid); *len=strlen(sid); } successes++; break;
|
||||
case ACTION_DECLINED: printf("DECLINED:%s\n",sid); errors++; break;
|
||||
case ACTION_OKAY: printf("OK:%s:%d\n",sid,r->recvttl); if (buffer) {strcpy((char *)buffer,sid); *len=strlen(sid); } successes++; break;
|
||||
case ACTION_DECLINED: printf("DECLINED:%s:%d\n",sid,r->recvttl); errors++; break;
|
||||
case ACTION_DATA:
|
||||
/* Display data.
|
||||
The trick is knowing the format of the data.
|
||||
@ -643,7 +648,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
int dlen=0;
|
||||
did[0]=0;
|
||||
extractDid(r->response,&dlen,did);
|
||||
printf("DIDS:%s:%d:%s\n",sid,r->var_instance,did);
|
||||
printf("DIDS:%s:%d:%d:%s\n",sid,r->recvttl,r->var_instance,did);
|
||||
if (buffer) {strcpy((char *)buffer,did); *len=strlen(did); }
|
||||
successes++;
|
||||
}
|
||||
@ -658,7 +663,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
while(vars[v].name&&vars[v].id!=r->var_id) v++;
|
||||
if (!vars[v].id) printf("0x%02x",r->var_id);
|
||||
while(vars[v].name[i]) fputc(toupper(vars[v].name[i++]),stdout);
|
||||
printf(":%s:%d:",sid,r->var_instance);
|
||||
printf(":%s:%d:%d:",sid,r->recvttl,r->var_instance);
|
||||
*len=r->value_len;
|
||||
|
||||
if (outputtemplate)
|
||||
@ -713,7 +718,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
/* Send accumulated request direct to the responder */
|
||||
if (packet_len>=MAX_DATA_BYTES)
|
||||
{
|
||||
if (packetFinalise(packet,8000,&packet_len,CRYPT_CIPHERED|CRYPT_SIGNED)) {
|
||||
if (packetFinalise(packet,8000,-1,&packet_len,CRYPT_CIPHERED|CRYPT_SIGNED)) {
|
||||
if (debug&DEBUG_DNAREQUESTS) fprintf(stderr,"requestItem() failed at line %d\n",__LINE__);
|
||||
return -1;
|
||||
}
|
||||
@ -745,7 +750,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
/* Send accumulated request direct to the responder */
|
||||
if (packet_len)
|
||||
{
|
||||
if (packetFinalise(packet,8000,&packet_len,CRYPT_SIGNED|CRYPT_CIPHERED)) {
|
||||
if (packetFinalise(packet,8000,-1,&packet_len,CRYPT_SIGNED|CRYPT_CIPHERED)) {
|
||||
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"requestItem() failed at line %d\n",__LINE__);
|
||||
return -1;
|
||||
}
|
||||
@ -797,7 +802,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
|
||||
}
|
||||
break;
|
||||
case ACTION_DONE:
|
||||
printf("DONE:%s:%d\n",sid,r->response[0]);
|
||||
printf("DONE:%s:%d:%d\n",sid,r->recvttl,r->response[0]);
|
||||
break;
|
||||
case ACTION_GET: printf("ERROR:You cant respond with GET\n"); break;
|
||||
case ACTION_SET: printf("ERROR:You cant respond with SET\n"); break;
|
||||
|
6
dna.c
6
dna.c
@ -462,7 +462,7 @@ int main(int argc,char **argv)
|
||||
int value_len=65535;
|
||||
if (parseAssignment((unsigned char *)optarg,&var_id,value,&value_len)) return -1;
|
||||
value[value_len]=0;
|
||||
return writeItem(did?did:sid,var_id,instance,value,0,value_len,SET_NOREPLACE,NULL);
|
||||
return writeItem(did?did:sid,var_id,instance,value,0,value_len,SET_NOREPLACE,-1,NULL);
|
||||
}
|
||||
break;
|
||||
case 'U': /* write or update a variable */
|
||||
@ -472,14 +472,14 @@ int main(int argc,char **argv)
|
||||
int value_len=65535;
|
||||
if (parseAssignment((unsigned char *)optarg,&var_id,value,&value_len)) return -1;
|
||||
value[value_len]=0;
|
||||
return writeItem(did?did:sid,var_id,instance,value,0,value_len,SET_REPLACE,NULL);
|
||||
return writeItem(did?did:sid,var_id,instance,value,0,value_len,SET_REPLACE,-1,NULL);
|
||||
}
|
||||
break;
|
||||
case 'C': /* create a new HLR entry */
|
||||
{
|
||||
if (optind<argc) usage("Extraneous options after HLR creation request");
|
||||
if ((!did)||(sid)) usage("Specify exactly one DID and no SID to create a new HLR entry");
|
||||
return requestNewHLR(did,pin,sid,NULL);
|
||||
return requestNewHLR(did,pin,sid,-1,NULL);
|
||||
}
|
||||
break;
|
||||
case 'O': /* output to templated files */
|
||||
|
28
mphlr.h
28
mphlr.h
@ -206,6 +206,7 @@ struct response {
|
||||
int code;
|
||||
unsigned char sid[32];
|
||||
struct in_addr sender;
|
||||
int recvttl;
|
||||
unsigned char *response;
|
||||
int response_len;
|
||||
int var_id;
|
||||
@ -283,6 +284,7 @@ extern struct mphlr_variable vars[];
|
||||
#define ACTION_WROTE 0x83
|
||||
|
||||
#define ACTION_XFER 0xf0
|
||||
#define ACTION_RECVTTL 0xfd
|
||||
#define ACTION_PAD 0xfe
|
||||
#define ACTION_EOT 0xff
|
||||
|
||||
@ -293,27 +295,33 @@ extern int hexdigit[16];
|
||||
|
||||
extern int sock;
|
||||
|
||||
int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
|
||||
struct sockaddr *recvaddr,unsigned int *recvaddrlen);
|
||||
int stowSid(unsigned char *packet,int ofs,char *sid);
|
||||
int stowDid(unsigned char *packet,int *ofs,char *did);
|
||||
int isFieldZeroP(unsigned char *packet,int start,int count);
|
||||
void srandomdev();
|
||||
int respondSimple(char *sid,int action,unsigned char *action_text,int action_len,
|
||||
unsigned char *transaction_id,struct sockaddr *recvaddr,int cryptoFlags);
|
||||
unsigned char *transaction_id,int recvttl,
|
||||
struct sockaddr *recvaddr,int cryptoFlags);
|
||||
int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffer,int buffer_length,int *len,
|
||||
unsigned char *transaction_id);
|
||||
int requestNewHLR(char *did,char *pin,char *sid,struct sockaddr *recvaddr);
|
||||
int requestNewHLR(char *did,char *pin,char *sid,int recvttl,struct sockaddr *recvaddr);
|
||||
int server(char *backing_file,int size,int foregroundMode);
|
||||
|
||||
int setReason(char *fmt, ...);
|
||||
int hexvalue(unsigned char c);
|
||||
int dump(char *name,unsigned char *addr,int len);
|
||||
int packetOk(int interface,unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
int packetOk(int interface,unsigned char *packet,int len,
|
||||
unsigned char *transaction_id, int recvttl,
|
||||
struct sockaddr *recvaddr,int recvaddrlen,int parseP);
|
||||
int process_packet(unsigned char *packet,int len,struct sockaddr *sender,int sender_len);
|
||||
int process_packet(unsigned char *packet,int len,
|
||||
int recvttl,struct sockaddr *sender,int sender_len);
|
||||
int packetMakeHeader(unsigned char *packet,int packet_maxlen,int *packet_len,unsigned char *transaction_id,int cryptoflags);
|
||||
int packetSetDid(unsigned char *packet,int packet_maxlen,int *packet_len,char *did);
|
||||
int packetSetSid(unsigned char *packet,int packet_maxlen,int *packet_len,char *sid);
|
||||
int packetFinalise(unsigned char *packet,int packet_maxlen,int *packet_len,int cryptoflags);
|
||||
int packetFinalise(unsigned char *packet,int packet_maxlen,int recvttl,
|
||||
int *packet_len,int cryptoflags);
|
||||
int packetAddHLRCreateRequest(unsigned char *packet,int packet_maxlen,int *packet_len);
|
||||
int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct response_set *responses);
|
||||
int packetAddVariableRequest(unsigned char *packet,int packet_maxlen,int *packet_len,
|
||||
@ -345,11 +353,12 @@ int extractDid(unsigned char *packet,int *ofs,char *did);
|
||||
char *hlrSid(unsigned char *hlr,int ofs);
|
||||
int parseAssignment(unsigned char *text,int *var_id,unsigned char *value,int *value_len);
|
||||
int writeItem(char *sid,int var_id,int instance,unsigned char *value,
|
||||
int value_start,int value_length,int flags, struct sockaddr *recvaddr);
|
||||
int value_start,int value_length,int flags,
|
||||
int recvttl,struct sockaddr *recvaddr);
|
||||
int packetAddVariableWrite(unsigned char *packet,int packet_maxlen,int *packet_len,
|
||||
int itemId,int instance,unsigned char *value,int start_offset,int value_len,int flags);
|
||||
int processRequest(unsigned char *packet,int len,struct sockaddr *sender,int sender_len,
|
||||
unsigned char *transaction_id,char *did,char *sid);
|
||||
unsigned char *transaction_id,int recvttl,char *did,char *sid);
|
||||
|
||||
int extractRequest(unsigned char *packet,int *packet_ofs,int packet_len,
|
||||
int *itemId,int *instance,unsigned char *value,
|
||||
@ -375,8 +384,9 @@ int openHlrFile(char *backing_file,int size);
|
||||
int runCommand(char *cmd);
|
||||
int asteriskObtainGateway(char *requestor_sid,char *did,char *uri_out);
|
||||
int packetOkDNA(unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
struct sockaddr *recvaddr,int recvaddrlen,int parseP);
|
||||
int packetOkOverlay(int interface,unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
int recvttl,struct sockaddr *recvaddr,int recvaddrlen,int parseP);
|
||||
int packetOkOverlay(int interface,unsigned char *packet,int len,
|
||||
unsigned char *transaction_id,int recvttl,
|
||||
struct sockaddr *recvaddr,int recvaddrlen,int parseP);
|
||||
int prepareGateway(char *gatewayspec);
|
||||
int packetSendRequest(int method,unsigned char *packet,int packet_len,int batchP,
|
||||
|
@ -319,7 +319,10 @@ int overlay_rx_messages()
|
||||
bzero(&transaction_id[0],8);
|
||||
bzero(&src_addr,sizeof(src_addr));
|
||||
if ((plen>=0)&&(packet[0]==0x01)&&!(packet[1]|packet[2]|packet[3])) {
|
||||
{ if (packetOk(i,&packet[128],plen,transaction_id,&src_addr,addrlen,1)) WHY("Malformed or unsupported packet from dummy interface (packetOK() failed)"); } }
|
||||
{ if (packetOk(i,&packet[128],plen,transaction_id,
|
||||
-1 /* fake TTL */,
|
||||
&src_addr,addrlen,1))
|
||||
WHY("Malformed or unsupported packet from dummy interface (packetOK() failed)"); } }
|
||||
else WHY("Invalid packet version in dummy interface");
|
||||
}
|
||||
else {
|
||||
@ -329,9 +332,9 @@ int overlay_rx_messages()
|
||||
}
|
||||
} else {
|
||||
/* Read from UDP socket */
|
||||
plen=recvfrom(overlay_interfaces[i].fd,packet,sizeof(packet),
|
||||
MSG_DONTWAIT,
|
||||
&src_addr,&addrlen);
|
||||
int recvttl=1;
|
||||
plen=recvwithttl(overlay_interfaces[i].fd,packet,sizeof(packet),
|
||||
&recvttl,&src_addr,&addrlen);
|
||||
if (plen<0) {
|
||||
c[i]=0; count--;
|
||||
} else {
|
||||
@ -341,7 +344,8 @@ int overlay_rx_messages()
|
||||
packet,plen);
|
||||
if (debug&DEBUG_OVERLAYINTERFACES)fprintf(stderr,"Received %d bytes on interface #%d (%s)\n",plen,i,overlay_interfaces[i].name);
|
||||
|
||||
if (packetOk(i,packet,plen,NULL,&src_addr,addrlen,1)) WHY("Malformed packet");
|
||||
if (packetOk(i,packet,plen,NULL,recvttl,&src_addr,addrlen,1))
|
||||
WHY("Malformed packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ struct sockaddr_in loopback = {
|
||||
.sin_addr.s_addr=0x0100007f
|
||||
};
|
||||
|
||||
int packetOkOverlay(int interface,unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
int packetOkOverlay(int interface,unsigned char *packet,int len,
|
||||
unsigned char *transaction_id,int recvttl,
|
||||
struct sockaddr *recvaddr,int recvaddrlen,int parseP)
|
||||
{
|
||||
/*
|
||||
|
@ -19,7 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "mphlr.h"
|
||||
|
||||
int process_packet(unsigned char *packet,int len,struct sockaddr *sender,int sender_len)
|
||||
int process_packet(unsigned char *packet,int len,
|
||||
int recvttl,struct sockaddr *sender,int sender_len)
|
||||
{
|
||||
int authenticatedP=0;
|
||||
char did[128];
|
||||
@ -52,26 +53,29 @@ int process_packet(unsigned char *packet,int len,struct sockaddr *sender,int sen
|
||||
if (debug&DEBUG_SECURITY) fprintf(stderr,"No PIN was supplied.\n");
|
||||
}
|
||||
|
||||
if (serverMode) return processRequest(packet,len,sender,sender_len,transaction_id,did,sid);
|
||||
if (serverMode) return processRequest(packet,len,sender,sender_len,transaction_id,
|
||||
recvttl,did,sid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int packetOk(int interface,unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
int packetOk(int interface,unsigned char *packet,int len,
|
||||
unsigned char *transaction_id,int ttl,
|
||||
struct sockaddr *recvaddr,int recvaddrlen,int parseP)
|
||||
{
|
||||
if (len<HEADERFIELDS_LEN) return setReason("Packet is too short");
|
||||
|
||||
if (packet[0]==0x41&&packet[1]==0x10)
|
||||
{
|
||||
return packetOkDNA(packet,len,transaction_id,recvaddr,recvaddrlen,parseP);
|
||||
return packetOkDNA(packet,len,transaction_id,ttl,recvaddr,recvaddrlen,parseP);
|
||||
}
|
||||
|
||||
if (packet[0]==0x4F&&packet[1]==0x10)
|
||||
{
|
||||
if (interface>-1)
|
||||
{
|
||||
return packetOkOverlay(interface,packet,len,transaction_id,recvaddr,recvaddrlen,parseP);
|
||||
return packetOkOverlay(interface,packet,len,transaction_id,ttl,
|
||||
recvaddr,recvaddrlen,parseP);
|
||||
}
|
||||
else
|
||||
/* We ignore overlay mesh packets in simple server mode, which is indicated by interface==-1 */
|
||||
@ -82,6 +86,7 @@ int packetOk(int interface,unsigned char *packet,int len,unsigned char *transact
|
||||
}
|
||||
|
||||
int packetOkDNA(unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
int recvttl,
|
||||
struct sockaddr *recvaddr,int recvaddrlen,int parseP)
|
||||
{
|
||||
/* Make sure that the packet is meant for us, and is not mal-formed */
|
||||
@ -123,7 +128,7 @@ int packetOkDNA(unsigned char *packet,int len,unsigned char *transaction_id,
|
||||
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"Packet passes sanity checks and is ready for decoding.\n");
|
||||
if (debug&DEBUG_PACKETFORMATS) dump("unrotated packet",packet,len);
|
||||
|
||||
if (parseP) return process_packet(packet,len,recvaddr,recvaddrlen); else return 0;
|
||||
if (parseP) return process_packet(packet,len,recvttl,recvaddr,recvaddrlen); else return 0;
|
||||
}
|
||||
|
||||
int packetMakeHeader(unsigned char *packet,int packet_maxlen,int *packet_len,
|
||||
@ -201,7 +206,8 @@ int packetSetSid(unsigned char *packet,int packet_maxlen,int *packet_len,char *s
|
||||
return stowSid(packet,ofs,sid);
|
||||
}
|
||||
|
||||
int packetFinalise(unsigned char *packet,int packet_maxlen,int *packet_len,int cryptoflags)
|
||||
int packetFinalise(unsigned char *packet,int packet_maxlen,int recvttl,
|
||||
int *packet_len,int cryptoflags)
|
||||
{
|
||||
/* Add any padding bytes and EOT to packet */
|
||||
int paddingBytes=rand()&0xf;
|
||||
@ -215,6 +221,15 @@ int packetFinalise(unsigned char *packet,int packet_maxlen,int *packet_len,int c
|
||||
while(paddingBytes--) packet[(*packet_len)++]=random()&0xff;
|
||||
}
|
||||
|
||||
/* tell requester what the ttl was when we received the packet */
|
||||
if (recvttl>-1) {
|
||||
CHECK_PACKET_LEN(2);
|
||||
packet[(*packet_len)++]=ACTION_RECVTTL;
|
||||
packet[(*packet_len)++]=recvttl;
|
||||
}
|
||||
|
||||
/* mark end of packet */
|
||||
CHECK_PACKET_LEN(1);
|
||||
packet[(*packet_len)++]=ACTION_EOT;
|
||||
|
||||
/* Set payload length */
|
||||
@ -390,6 +405,8 @@ int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct
|
||||
{
|
||||
int ofs=OFS_PAYLOAD;
|
||||
|
||||
struct response *first_response=NULL;
|
||||
|
||||
while(ofs<len)
|
||||
{
|
||||
/* XXX should allocate responses from a temporary and bounded slab of memory */
|
||||
@ -433,6 +450,18 @@ int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct
|
||||
unpackageVariableSegment(&buffer[ofs+1],len-ofs,WITHOUTDATA,r);
|
||||
r->response=NULL;
|
||||
break;
|
||||
case ACTION_RECVTTL:
|
||||
r->recvttl=buffer[ofs+1];
|
||||
r->response_len=1;
|
||||
/* Attach TTL to other responses from this packet */
|
||||
{
|
||||
struct response *rr=first_response;
|
||||
while(rr) {
|
||||
rr->recvttl=r->recvttl;
|
||||
rr=rr->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_SET:
|
||||
case ACTION_DEL:
|
||||
case ACTION_XFER:
|
||||
@ -472,6 +501,8 @@ int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct
|
||||
responses->last_response=r;
|
||||
responses->response_count++;
|
||||
|
||||
if (!first_response) first_response=r;
|
||||
|
||||
responseFromPeer(responses,r->peer_id);
|
||||
|
||||
if (debug&DEBUG_DNARESPONSES) dumpResponses(responses);
|
||||
|
122
server.c
122
server.c
@ -17,6 +17,9 @@ along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "mphlr.h"
|
||||
|
||||
unsigned char *hlr=NULL;
|
||||
@ -31,6 +34,57 @@ int getBackingStore(char *s,int size);
|
||||
int createServerSocket();
|
||||
int simpleServerMode();
|
||||
|
||||
int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
|
||||
struct sockaddr *recvaddr,unsigned int *recvaddrlen)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
|
||||
iov[0].iov_base=buffer;
|
||||
iov[0].iov_len=bufferlen;
|
||||
bzero(&msg,sizeof(msg));
|
||||
msg.msg_name = recvaddr;
|
||||
msg.msg_namelen = *recvaddrlen;
|
||||
msg.msg_iov = &iov[0];
|
||||
msg.msg_iovlen = 1;
|
||||
// setting the following makes the data end up in the wrong place
|
||||
// msg.msg_iov->iov_base=iov_buffer;
|
||||
// msg.msg_iov->iov_len=sizeof(iov_buffer);
|
||||
|
||||
struct cmsghdr cmsgcmsg[16];
|
||||
msg.msg_control = &cmsgcmsg[0];
|
||||
msg.msg_controllen = sizeof(struct cmsghdr)*16;
|
||||
msg.msg_flags = 0;
|
||||
|
||||
fcntl(sock,F_SETFL, O_NONBLOCK);
|
||||
|
||||
int len = recvmsg(sock,&msg,0);
|
||||
|
||||
fprintf(stderr,"recvmsg returned %d bytes (flags=%d,msg_controllen=%d)\n",
|
||||
len,msg.msg_flags,msg.msg_controllen);
|
||||
|
||||
if (len>0) {
|
||||
struct cmsghdr *cmsg;
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg,cmsg)) {
|
||||
|
||||
if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVTTL) &&
|
||||
(cmsg->cmsg_len) ){
|
||||
fprintf(stderr," TTL (%p) data location resolves to %p\n",
|
||||
ttl,CMSG_DATA(cmsg));
|
||||
if (CMSG_DATA(cmsg)) {
|
||||
*ttl = *(unsigned char *) CMSG_DATA(cmsg);
|
||||
fprintf(stderr," TTL of packet is %d\n",*ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*recvaddrlen=msg.msg_namelen;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int server(char *backing_file,int size,int foregroundMode)
|
||||
{
|
||||
@ -119,7 +173,7 @@ int getBackingStore(char *backing_file,int size)
|
||||
|
||||
int processRequest(unsigned char *packet,int len,
|
||||
struct sockaddr *sender,int sender_len,
|
||||
unsigned char *transaction_id,char *did,char *sid)
|
||||
unsigned char *transaction_id,int recvttl, char *did,char *sid)
|
||||
{
|
||||
/* Find HLR entry by DID or SID, unless creating */
|
||||
int ofs,rofs=0;
|
||||
@ -140,17 +194,19 @@ int processRequest(unsigned char *packet,int len,
|
||||
/* Creating an HLR requires an initial DID number and definately no SID -
|
||||
you can't choose a SID. */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Creating a new HLR record. did='%s', sid='%s'\n",did,sid);
|
||||
if (!did[0]) return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (sid[0]) return respondSimple(sid,ACTION_DECLINED,NULL,0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (!did[0]) return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (sid[0]) return respondSimple(sid,ACTION_DECLINED,NULL,0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Verified that create request supplies DID but not SID\n");
|
||||
|
||||
{
|
||||
char sid[128];
|
||||
/* make HLR with new random SID and initial DID */
|
||||
if (!createHlr(did,sid))
|
||||
return respondSimple(sid,ACTION_OKAY,NULL,0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
return respondSimple(sid,ACTION_OKAY,NULL,0,transaction_id,
|
||||
recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
else
|
||||
return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,
|
||||
recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
pofs+=1;
|
||||
pofs+=1+SID_SIZE;
|
||||
@ -214,7 +270,8 @@ int processRequest(unsigned char *packet,int len,
|
||||
sprintf(amCommand, "am broadcast -a org.servalproject.DT -e number \"%s\" -e content \"%s\"", emitterPhoneNumber, message);
|
||||
if (debug&DEBUG_DNAREQUESTS) fprintf(stderr,"Delivering DT message via intent: %s\n",amCommand);
|
||||
runCommand(amCommand);
|
||||
respondSimple(hlrSid(hlr, ofs),ACTION_OKAY,NULL,0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
respondSimple(hlrSid(hlr, ofs),ACTION_OKAY,NULL,0,transaction_id,
|
||||
recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -224,7 +281,9 @@ int processRequest(unsigned char *packet,int len,
|
||||
|
||||
if ((!sid)||(!sid[0])) {
|
||||
setReason("You can only set variables by SID");
|
||||
return respondSimple(NULL,ACTION_ERROR,(unsigned char *)"SET requires authentication by SID",0,transaction_id,
|
||||
return respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"SET requires authentication by SID",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
|
||||
@ -251,7 +310,9 @@ int processRequest(unsigned char *packet,int len,
|
||||
{
|
||||
setReason("Could not extract ACTION_SET request");
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,(unsigned char *)"Mal-formed SET request",0,transaction_id,
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Mal-formed SET request",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
|
||||
@ -266,7 +327,7 @@ int processRequest(unsigned char *packet,int len,
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Cannot SET NOCREATE/REPLACE a value that does not exist",
|
||||
0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
} else {
|
||||
if (flags==SET_NOREPLACE) {
|
||||
@ -275,7 +336,7 @@ int processRequest(unsigned char *packet,int len,
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Cannot SET NOREPLACE; a value exists",
|
||||
0,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
}
|
||||
/* Replace the changed portion of the stored value */
|
||||
@ -290,14 +351,17 @@ int processRequest(unsigned char *packet,int len,
|
||||
{
|
||||
setReason("Failed to write variable");
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,(unsigned char *)"Failed to SET variable",0,transaction_id,
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Failed to SET variable",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
if (debug&DEBUG_HLR) { fprintf(stderr,"HLR after writing:\n"); hlrDump(hlr,ofs); }
|
||||
|
||||
/* Reply that we wrote the fragment */
|
||||
respondSimple(sid,ACTION_WROTE,&packet[rofs],6,
|
||||
transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
/* Advance to next record and keep searching */
|
||||
if (nextHlr(hlr,&ofs)) break;
|
||||
}
|
||||
@ -361,7 +425,8 @@ int processRequest(unsigned char *packet,int len,
|
||||
|
||||
// only send each value when the *next* record is found, that way we can easily stamp the last response with DONE
|
||||
if (sendDone>0)
|
||||
respondSimple(hlr_sid,ACTION_DATA,data,dlen,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
respondSimple(hlr_sid,ACTION_DATA,data,dlen,
|
||||
transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
|
||||
dlen=0;
|
||||
|
||||
@ -388,7 +453,8 @@ int processRequest(unsigned char *packet,int len,
|
||||
{
|
||||
data[dlen++]=ACTION_DONE;
|
||||
data[dlen++]=sendDone&0xff;
|
||||
respondSimple(hlr_sid,ACTION_DATA,data,dlen,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
respondSimple(hlr_sid,ACTION_DATA,data,dlen,transaction_id,
|
||||
recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
if (gatewayspec&&(var_id==VAR_LOCATIONS)&&did&&strlen(did))
|
||||
{
|
||||
@ -413,7 +479,9 @@ int processRequest(unsigned char *packet,int len,
|
||||
if (packageVariableSegment(data,&dlen,&fake,offset,MAX_DATA_BYTES+16))
|
||||
return setReason("packageVariableSegment() of gateway URI failed.");
|
||||
|
||||
respondSimple(hlrSid(hlr,0),ACTION_DATA,data,dlen,transaction_id,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
respondSimple(hlrSid(hlr,0),ACTION_DATA,data,dlen,
|
||||
transaction_id,recvttl,sender,
|
||||
CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -438,7 +506,8 @@ int processRequest(unsigned char *packet,int len,
|
||||
}
|
||||
|
||||
int respondSimple(char *sid,int action,unsigned char *action_text,int action_len,
|
||||
unsigned char *transaction_id,struct sockaddr *recvaddr,int cryptoFlags)
|
||||
unsigned char *transaction_id,int recvttl,
|
||||
struct sockaddr *recvaddr,int cryptoFlags)
|
||||
{
|
||||
unsigned char packet[8000];
|
||||
int pl=0;
|
||||
@ -478,7 +547,7 @@ int respondSimple(char *sid,int action,unsigned char *action_text,int action_len
|
||||
|
||||
if (debug&DEBUG_DNARESPONSES) dump("Simple response octets",action_text,action_len);
|
||||
|
||||
if (packetFinalise(packet,8000,packet_len,cryptoFlags))
|
||||
if (packetFinalise(packet,8000,recvttl,packet_len,cryptoFlags))
|
||||
return WHY("packetFinalise() failed.");
|
||||
|
||||
if (debug&DEBUG_DNARESPONSES) fprintf(stderr,"Sending response of %d bytes.\n",*packet_len);
|
||||
@ -502,7 +571,14 @@ int createServerSocket()
|
||||
|
||||
int TRUE=1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &TRUE, sizeof(TRUE));
|
||||
|
||||
|
||||
errno=0;
|
||||
if(setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &TRUE,sizeof(TRUE))<0)
|
||||
perror("setsockopt(IP_RECVDSTADDR)");
|
||||
errno=0;
|
||||
if(setsockopt(sock, IPPROTO_IP, IP_RECVTTL, &TRUE,sizeof(TRUE))<0)
|
||||
perror("setsockopt(IP_RECVTTL)");
|
||||
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = htons( PORT_DNA );
|
||||
bind_addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
@ -519,7 +595,6 @@ extern int rhizome_server_socket;
|
||||
int simpleServerMode()
|
||||
{
|
||||
while(1) {
|
||||
unsigned char buffer[16384];
|
||||
struct sockaddr recvaddr;
|
||||
socklen_t recvaddrlen=sizeof(recvaddr);
|
||||
struct pollfd fds[128];
|
||||
@ -552,9 +627,14 @@ int simpleServerMode()
|
||||
}
|
||||
if (rhizome_datastore_path) rhizome_server_poll();
|
||||
|
||||
unsigned char buffer[16384];
|
||||
int ttl=-1; // unknown
|
||||
|
||||
if (fds[0].revents&POLLIN) {
|
||||
len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen);
|
||||
|
||||
len=recvwithttl(sock,buffer,sizeof(buffer),&ttl,&recvaddr,&recvaddrlen);
|
||||
|
||||
|
||||
client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
|
||||
client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr;
|
||||
|
||||
@ -566,7 +646,7 @@ int simpleServerMode()
|
||||
continue;
|
||||
}
|
||||
/* Simple server mode doesn't really use interface numbers, so lie and say interface -1 */
|
||||
if (packetOk(-1,buffer,len,NULL,&recvaddr,recvaddrlen,1)) {
|
||||
if (packetOk(-1,buffer,len,NULL,ttl,&recvaddr,recvaddrlen,1)) {
|
||||
if (debug&DEBUG_PACKETFORMATS) setReason("Ignoring invalid packet");
|
||||
}
|
||||
if (debug&DEBUG_PACKETXFER) fprintf(stderr,"Finished processing packet, waiting for next one.\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user