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:
gardners 2012-02-05 16:15:19 +10:30
parent 8a24fb95b1
commit 5cc6079c0f
7 changed files with 196 additions and 65 deletions

View File

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

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

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

View File

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

View File

@ -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)
{
/*

View File

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

@ -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");