mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
added code to time various servald functions and report periodic
statistics. Handles nested calls to correctly aportion call time among children.
This commit is contained in:
parent
fb7397a51b
commit
97cd8f5255
59
fdqueue.c
59
fdqueue.c
@ -252,6 +252,19 @@ func_descriptions func_names[]={
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
#define MAX_FUNCS 1024
|
||||
struct callback_stats called_funcs[MAX_FUNCS];
|
||||
const char *called_func_names[MAX_FUNCS];
|
||||
int func_count=0;
|
||||
|
||||
#define MAX_CALL_DEPTH 128
|
||||
struct {
|
||||
int func_id;
|
||||
int enter_time;
|
||||
int child_time;
|
||||
} call_stack[MAX_CALL_DEPTH];
|
||||
int call_stack_depth=0;
|
||||
|
||||
char *fd_funcname(void *addr)
|
||||
{
|
||||
int j;
|
||||
@ -299,7 +312,7 @@ int fd_tallystats(struct callback_stats *total,struct callback_stats *a)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_showstat(struct callback_stats *total, struct callback_stats *a, char *msg)
|
||||
int fd_showstat(struct callback_stats *total, struct callback_stats *a, const char *msg)
|
||||
{
|
||||
WHYF("%lldms (%2.1f%%) in %d calls (max %lldms, avg %.1fms) : %s",
|
||||
a->total_time,a->total_time*100.0/total->total_time,
|
||||
@ -325,6 +338,9 @@ int fd_clearstats()
|
||||
fd_clearstat(&alarms[i].stats);
|
||||
for(i=0;i<fdcount;i++)
|
||||
fd_clearstat(&fd_stats[fds[i].fd]);
|
||||
for(i=0;i<func_count;i++)
|
||||
fd_clearstat(&called_funcs[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -355,6 +371,10 @@ int fd_showstats()
|
||||
fd_showstat(&total,&fd_stats[fds[i].fd],desc);
|
||||
}
|
||||
fd_showstat(&total,&total,"TOTAL");
|
||||
INFOF("servald function time statistics:");
|
||||
for(i=0;i<func_count;i++)
|
||||
fd_showstat(&total,&called_funcs[i],called_func_names[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -363,3 +383,40 @@ void fd_periodicstats()
|
||||
fd_showstats();
|
||||
fd_clearstats();
|
||||
}
|
||||
|
||||
int fd_next_funcid(const char *funcname)
|
||||
{
|
||||
if (func_count>=MAX_FUNCS) return MAX_FUNCS-1;
|
||||
fd_clearstat(&called_funcs[func_count]);
|
||||
called_func_names[func_count]=funcname;
|
||||
return func_count++;
|
||||
}
|
||||
|
||||
int fd_func_enter(int funcid)
|
||||
{
|
||||
if (call_stack_depth>=MAX_CALL_DEPTH) return 0;
|
||||
call_stack[call_stack_depth].func_id=funcid;
|
||||
call_stack[call_stack_depth].enter_time=overlay_gettime_ms();
|
||||
call_stack[call_stack_depth].child_time=0;
|
||||
call_stack_depth++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_func_exit(int funcid)
|
||||
{
|
||||
if (funcid!=call_stack[call_stack_depth-1].func_id)
|
||||
exit(WHYF("func_id mismatch: entered through %s(), but exited through %s()",
|
||||
called_func_names[call_stack[call_stack_depth-1].func_id],
|
||||
called_func_names[funcid]));
|
||||
|
||||
long long elapsed=overlay_gettime_ms()-call_stack[call_stack_depth-1].enter_time;
|
||||
long long self_elapsed=elapsed-call_stack[call_stack_depth-1].child_time;
|
||||
if (call_stack_depth>1) {
|
||||
int d=call_stack_depth-2;
|
||||
call_stack[d].child_time+=elapsed;
|
||||
}
|
||||
fd_update_stats(&called_funcs[funcid],self_elapsed);
|
||||
call_stack_depth--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
53
keyring.c
53
keyring.c
@ -1118,10 +1118,12 @@ int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp)
|
||||
unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid,
|
||||
unsigned char **sas_public)
|
||||
{
|
||||
IN();
|
||||
int cn=0,in=0,kp=0;
|
||||
|
||||
if (!keyring_find_sid(k,&cn,&in,&kp,sid))
|
||||
return WHYNULL("Could not find SID in keyring, so can't find SAS");
|
||||
if (!keyring_find_sid(k,&cn,&in,&kp,sid)) {
|
||||
RETURN(WHYNULL("Could not find SID in keyring, so can't find SAS"));
|
||||
}
|
||||
|
||||
for(kp=0;kp<k->contexts[cn]->identities[in]->keypair_count;kp++)
|
||||
if (k->contexts[cn]->identities[in]->keypairs[kp]->type==KEYTYPE_CRYPTOSIGN)
|
||||
@ -1129,10 +1131,11 @@ unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid,
|
||||
if (sas_public)
|
||||
*sas_public=
|
||||
k->contexts[cn]->identities[in]->keypairs[kp]->public_key;
|
||||
return k->contexts[cn]->identities[in]->keypairs[kp]->private_key;
|
||||
WHYF("Found SAS entry for %s*",overlay_render_sid_prefix(sid,7));
|
||||
RETURN(k->contexts[cn]->identities[in]->keypairs[kp]->private_key);
|
||||
}
|
||||
|
||||
return WHYNULL("Identity lacks SAS");
|
||||
RETURN(WHYNULL("Identity lacks SAS"));
|
||||
}
|
||||
|
||||
struct sid_sas_mapping {
|
||||
@ -1182,6 +1185,8 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
|
||||
if (crypto_sign_edwards25519sha512batch
|
||||
(&req->out.payload[1+keybytes],&slen,req->out.dst.sid,SID_SIZE,sas_priv))
|
||||
return WHY("crypto_sign() failed");
|
||||
dump("SAS reply before compaction",
|
||||
&req->out.payload[1+keybytes],slen);
|
||||
/* chop the SID out of the signature, since it can be reinserted on reception */
|
||||
bcopy(&req->out.payload[1+keybytes+32+SID_SIZE],
|
||||
&req->out.payload[1+keybytes+32],sigbytes-32);
|
||||
@ -1201,6 +1206,8 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
|
||||
return overlay_mdp_dispatch(req,1,NULL,0);
|
||||
} else {
|
||||
/* It's probably a response. */
|
||||
WHYF("Received %d byte key mapping response",
|
||||
req->out.payload_length);
|
||||
switch(req->out.payload[0]) {
|
||||
case KEYTYPE_CRYPTOSIGN:
|
||||
{
|
||||
@ -1219,6 +1226,9 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
|
||||
bcopy(&compactsignature[0],&signature[0],32);
|
||||
bcopy(&req->out.src.sid[0],&signature[32],SID_SIZE);
|
||||
bcopy(&compactsignature[32],&signature[32+SID_SIZE],32);
|
||||
dump("SAS reply after decompaction",
|
||||
signature,siglen);
|
||||
|
||||
int r=crypto_sign_edwards25519sha512batch_open(plain,&plain_len,
|
||||
signature,siglen,
|
||||
sas_public);
|
||||
@ -1276,19 +1286,25 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
|
||||
For now we will just use a non-persistent cache for safety (and it happens
|
||||
to be easy to implement as well :)
|
||||
*/
|
||||
IN();
|
||||
int i;
|
||||
long long now=overlay_gettime_ms();
|
||||
for(i=0;i<sid_sas_mapping_count;i++)
|
||||
{
|
||||
if (memcmp(sid,sid_sas_mappings[i].sid,SID_SIZE)) continue;
|
||||
if (sid_sas_mappings[i].validP) return sid_sas_mappings[i].sas_public;
|
||||
if (sid_sas_mappings[i].validP)
|
||||
{ WHYF("Found SAS public entry for %s*",overlay_render_sid_prefix(sid,7));
|
||||
RETURN(sid_sas_mappings[i].sas_public); }
|
||||
/* Don't flood the network with mapping requests */
|
||||
if ((now-sid_sas_mappings[i].last_request_time_in_ms)<1000) return NULL;
|
||||
if (((now-sid_sas_mappings[i].last_request_time_in_ms)<1000)
|
||||
&&((now-sid_sas_mappings[i].last_request_time_in_ms)>=0))
|
||||
{ WHYF("Too soon to ask for SAS mapping again."); RETURN(NULL); }
|
||||
/* we can request again, so fall out to where we do that.
|
||||
i is set to this mapping, so the request process will update this
|
||||
record. */
|
||||
break;
|
||||
}
|
||||
WHYF("Asking for SAS mapping for %s",overlay_render_sid(sid));
|
||||
|
||||
/* allocate mapping slot or replace one at random, depending on how full things
|
||||
are */
|
||||
@ -1304,7 +1320,7 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
|
||||
sid_sas_mappings[i].validP=0;
|
||||
sid_sas_mappings[i].last_request_time_in_ms=now;
|
||||
|
||||
/* request mapping. */
|
||||
/* request mapping (send request auth-crypted). */
|
||||
overlay_mdp_frame mdp;
|
||||
mdp.packetTypeAndFlags=MDP_TX;
|
||||
bcopy(&sid[0],&mdp.out.dst.sid[0],SID_SIZE);
|
||||
@ -1316,12 +1332,14 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
|
||||
==KEYTYPE_CRYPTOBOX)
|
||||
bcopy(keyring->contexts[0]->identities[0]->keypairs[0]->public_key,
|
||||
mdp.out.src.sid,SID_SIZE);
|
||||
else return WHYNULL("couldn't request SAS (I don't know who I am)");
|
||||
else { RETURN(WHYNULL("couldn't request SAS (I don't know who I am)")); }
|
||||
mdp.out.payload_length=1;
|
||||
mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN;
|
||||
overlay_mdp_dispatch(&mdp,0 /* system generated */,
|
||||
NULL,0);
|
||||
return NULL;
|
||||
if (overlay_mdp_dispatch(&mdp,0 /* system generated */,
|
||||
NULL,0))
|
||||
{ RETURN(WHYNULL("Failed to send SAS resolution request")); }
|
||||
WHYF("Dispatched SAS resolution request");
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
int keyring_find_sid(const keyring_file *k,int *cn,int *in,int *kp, const unsigned char *sid)
|
||||
@ -1434,9 +1452,10 @@ struct nm_record nm_cache[NM_CACHE_SLOTS];
|
||||
|
||||
unsigned char *keyring_get_nm_bytes(sockaddr_mdp *known,sockaddr_mdp *unknown)
|
||||
{
|
||||
if (!known) return WHYNULL("known pub key is null");
|
||||
if (!unknown) return WHYNULL("unknown pub key is null");
|
||||
if (!keyring) return WHYNULL("keyring is null");
|
||||
IN();
|
||||
if (!known) { RETURN(WHYNULL("known pub key is null")); }
|
||||
if (!unknown) { RETURN(WHYNULL("unknown pub key is null")); }
|
||||
if (!keyring) { RETURN(WHYNULL("keyring is null")); }
|
||||
|
||||
int i;
|
||||
|
||||
@ -1447,14 +1466,14 @@ unsigned char *keyring_get_nm_bytes(sockaddr_mdp *known,sockaddr_mdp *unknown)
|
||||
crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)) continue;
|
||||
if (memcmp(nm_cache[i].unknown_key,unknown->sid,
|
||||
crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)) continue;
|
||||
return nm_cache[i].nm_bytes;
|
||||
{ RETURN(nm_cache[i].nm_bytes); }
|
||||
}
|
||||
|
||||
/* Not in the cache, so prepare to cache it (or return failure if known is not
|
||||
in fact a known key */
|
||||
int cn=0,in=0,kp=0;
|
||||
if (!keyring_find_sid(keyring,&cn,&in,&kp,known->sid))
|
||||
return WHYNULL("known key is not in fact known.");
|
||||
{ RETURN(WHYNULL("known key is not in fact known.")); }
|
||||
|
||||
/* work out where to store it */
|
||||
if (nm_slots_used<NM_CACHE_SLOTS) {
|
||||
@ -1475,5 +1494,5 @@ unsigned char *keyring_get_nm_bytes(sockaddr_mdp *known,sockaddr_mdp *unknown)
|
||||
->identities[in]
|
||||
->keypairs[kp]->private_key);
|
||||
|
||||
return nm_cache[i].nm_bytes;
|
||||
RETURN(nm_cache[i].nm_bytes);
|
||||
}
|
||||
|
31
overlay.c
31
overlay.c
@ -154,12 +154,13 @@ int overlayServerMode()
|
||||
|
||||
int overlay_frame_process(int interface,overlay_frame *f)
|
||||
{
|
||||
if (!f) return WHY("f==NULL");
|
||||
IN();
|
||||
if (!f) RETURN(WHY("f==NULL"));
|
||||
|
||||
long long now=overlay_gettime_ms();
|
||||
|
||||
if (f->source_address_status==OA_RESOLVED&&overlay_address_is_local(f->source))
|
||||
return WHY("Dropping frame claiming to come from myself.");
|
||||
RETURN(WHY("Dropping frame claiming to come from myself."));
|
||||
|
||||
if (debug&DEBUG_OVERLAYFRAMES) fprintf(stderr,">>> Received frame (type=%02x, bytes=%d)\n",f->type,f->payload?f->payload->length:-1);
|
||||
|
||||
@ -176,13 +177,13 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
{
|
||||
case OA_UNINITIALISED:
|
||||
/* Um? Right. */
|
||||
return WHY("frame passed with ununitialised nexthop address");
|
||||
RETURN(WHY("frame passed with ununitialised nexthop address"));
|
||||
break;
|
||||
case OA_RESOLVED:
|
||||
/* Great, we have the address, so we can get on with things */
|
||||
break;
|
||||
case OA_PLEASEEXPLAIN:
|
||||
return -1; // WHY("Address cannot be resolved -- aborting packet processing.");
|
||||
RETURN(-1); // WHY("Address cannot be resolved -- aborting packet processing.");
|
||||
/* XXX Should send a please explain to get this address resolved. */
|
||||
break;
|
||||
case OA_UNSUPPORTED:
|
||||
@ -194,7 +195,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
to itself. */
|
||||
WHY("Packet with unsupported address format");
|
||||
overlay_interface_repeat_abbreviation_policy[interface]=1;
|
||||
return -1;
|
||||
RETURN(-1);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -214,7 +215,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
if (forMe) {
|
||||
/* It's for us, so resolve the addresses */
|
||||
if (overlay_frame_resolve_addresses(interface,f))
|
||||
return WHY("Failed to resolve destination and sender addresses in frame");
|
||||
RETURN(WHY("Failed to resolve destination and sender addresses in frame"));
|
||||
broadcast=overlay_address_is_broadcast(f->destination);
|
||||
if (debug&DEBUG_OVERLAYFRAMES) {
|
||||
fprintf(stderr,"Destination for this frame is (resolve code=%d): ",f->destination_address_status);
|
||||
@ -227,7 +228,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
|
||||
if (f->source_address_status!=OA_RESOLVED) {
|
||||
if (debug&DEBUG_OVERLAYFRAMES) WHY("Source address could not be resolved, so dropping frame.");
|
||||
return -1;
|
||||
RETURN(-1);
|
||||
}
|
||||
if (overlay_address_is_local(f->source))
|
||||
{
|
||||
@ -235,7 +236,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
you hear everything you send. */
|
||||
if (debug&DEBUG_OVERLAYROUTING)
|
||||
WHY("Dropping frame claiming to come from myself.");
|
||||
return -1;
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
if (f->destination_address_status==OA_RESOLVED) {
|
||||
@ -244,7 +245,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
if (overlay_address_is_local(f->destination)) ultimatelyForMe=1;
|
||||
} else {
|
||||
if (debug&DEBUG_OVERLAYFRAMES) WHY("Destination address could not be resolved, so dropping frame.");
|
||||
return WHY("could not resolve destination address");
|
||||
RETURN(WHY("could not resolve destination address"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,12 +258,12 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
|
||||
if (duplicateBroadcast) {
|
||||
if (0) WHY("Packet is duplicate broadcast");
|
||||
return 0;
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
/* Not for us? Then just ignore it */
|
||||
if (!forMe) {
|
||||
return 0;
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
/* Is this a frame we have to forward on? */
|
||||
@ -318,7 +319,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
printf("reject nexthop is %s\n",overlay_render_sid(f->nexthop));
|
||||
printf("reject destination is %s\n",
|
||||
overlay_render_sid(f->destination));
|
||||
return WHY("Not forwarding or reading duplicate broadcast");
|
||||
RETURN(WHY("Not forwarding or reading duplicate broadcast"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +351,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
/* If the frame was a broadcast frame, then we need to hang around
|
||||
so that we can process it, since we are one of the recipients.
|
||||
Otherwise, return triumphant. */
|
||||
if (!broadcast) return 0;
|
||||
if (!broadcast) RETURN(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,10 +384,10 @@ int overlay_frame_process(int interface,overlay_frame *f)
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unsupported f->type=0x%x\n",f->type);
|
||||
return WHY("Support for that f->type not yet implemented");
|
||||
RETURN(WHY("Support for that f->type not yet implemented"));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
|
169
overlay_mdp.c
169
overlay_mdp.c
@ -273,58 +273,49 @@ int overlay_mdp_process_bind_request(int sock,overlay_mdp_frame *mdp,
|
||||
return overlay_mdp_reply_ok(sock,recvaddr,recvaddrlen,"Port bound");
|
||||
}
|
||||
|
||||
int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long now)
|
||||
unsigned char *overlay_mdp_decrypt(overlay_frame *f,overlay_mdp_frame *mdp,
|
||||
int *len)
|
||||
{
|
||||
/* Take frame source and destination and use them to populate mdp->in->{src,dst}
|
||||
SIDs.
|
||||
Take ports from mdp frame itself.
|
||||
Take payload from mdp frame itself.
|
||||
*/
|
||||
overlay_mdp_frame mdp;
|
||||
IN();
|
||||
|
||||
/* Get source and destination addresses */
|
||||
bcopy(&f->destination[0],&mdp.in.dst.sid[0],SID_SIZE);
|
||||
bcopy(&f->source[0],&mdp.in.src.sid[0],SID_SIZE);
|
||||
|
||||
int len=f->payload->length;
|
||||
*len=f->payload->length;
|
||||
unsigned char *b = NULL;
|
||||
unsigned char plain_block[len+16];
|
||||
unsigned char plain_block[(*len)+16];
|
||||
|
||||
if (len<10) return WHY("Invalid MDP frame");
|
||||
|
||||
/* copy crypto flags from frame so that we know if we need to decrypt or verify it */
|
||||
switch(f->modifiers&OF_CRYPTO_BITS) {
|
||||
case 0:
|
||||
/* get payload */
|
||||
b=&f->payload->bytes[0];
|
||||
len=f->payload->length;
|
||||
mdp.packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN; break;
|
||||
*len=f->payload->length;
|
||||
mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN; break;
|
||||
case OF_CRYPTO_CIPHERED:
|
||||
return WHY("decryption not implemented");
|
||||
mdp.packetTypeAndFlags|=MDP_NOSIGN; break;
|
||||
WHY("decryption not implemented");
|
||||
RETURN(NULL);
|
||||
mdp->packetTypeAndFlags|=MDP_NOSIGN; break;
|
||||
case OF_CRYPTO_SIGNED:
|
||||
{
|
||||
/* This call below will dispatch the request for the SAS if we don't
|
||||
already have it. In the meantime, we just drop the frame if the SAS
|
||||
is not available. */
|
||||
unsigned char *key=keyring_find_sas_public(keyring,mdp.out.src.sid);
|
||||
if (!key) return WHY("SAS key not currently on record, so cannot verify");
|
||||
unsigned char *key=keyring_find_sas_public(keyring,mdp->out.src.sid);
|
||||
if (!key) { WHY("SAS key not currently on record, so cannot verify");
|
||||
RETURN(NULL); }
|
||||
|
||||
/* get payload and following compacted signature */
|
||||
b=&f->payload->bytes[0];
|
||||
len=f->payload->length-crypto_sign_edwards25519sha512batch_BYTES;
|
||||
*len=f->payload->length-crypto_sign_edwards25519sha512batch_BYTES;
|
||||
|
||||
/* get hash */
|
||||
unsigned char hash[crypto_hash_sha512_BYTES];
|
||||
crypto_hash_sha512(hash,b,len);
|
||||
crypto_hash_sha512(hash,b,*len);
|
||||
|
||||
/* reconstitute signature by putting hash between two halves of signature */
|
||||
unsigned char signature[crypto_hash_sha512_BYTES
|
||||
+crypto_sign_edwards25519sha512batch_BYTES];
|
||||
bcopy(&b[len],&signature[0],32);
|
||||
crypto_hash_sha512(&signature[32],b,len);
|
||||
bcopy(&b[*len],&signature[0],32);
|
||||
crypto_hash_sha512(&signature[32],b,*len);
|
||||
if (0) dump("hash for verification",hash,crypto_hash_sha512_BYTES);
|
||||
bcopy(&b[len+32],&signature[32+crypto_hash_sha512_BYTES],32);
|
||||
bcopy(&b[(*len)+32],&signature[32+crypto_hash_sha512_BYTES],32);
|
||||
|
||||
/* verify signature */
|
||||
unsigned char m[crypto_hash_sha512_BYTES];
|
||||
@ -333,24 +324,27 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
|
||||
=crypto_sign_edwards25519sha512batch_open(m,&mlen,
|
||||
signature,sizeof(signature),
|
||||
key);
|
||||
if (result) return WHY("Signature verification failed: incorrect signature");
|
||||
else if (0) DEBUG("signature check passed");
|
||||
if (result) {
|
||||
WHY("Signature verification failed: incorrect signature");
|
||||
RETURN(NULL);
|
||||
} else if (1) DEBUG("signature check passed");
|
||||
}
|
||||
mdp.packetTypeAndFlags|=MDP_NOCRYPT; break;
|
||||
mdp->packetTypeAndFlags|=MDP_NOCRYPT; break;
|
||||
case OF_CRYPTO_CIPHERED|OF_CRYPTO_SIGNED:
|
||||
{
|
||||
if (0) {
|
||||
fflush(stderr);
|
||||
printf("crypted MDP frame for %s\n",
|
||||
overlay_render_sid(mdp.out.dst.sid));
|
||||
overlay_render_sid(mdp->out.dst.sid));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
unsigned char *k=keyring_get_nm_bytes(&mdp.out.dst,&mdp.out.src);
|
||||
unsigned char *k=keyring_get_nm_bytes(&mdp->out.dst,&mdp->out.src);
|
||||
unsigned char *nonce=&f->payload->bytes[0];
|
||||
int nb=crypto_box_curve25519xsalsa20poly1305_NONCEBYTES;
|
||||
int zb=crypto_box_curve25519xsalsa20poly1305_ZEROBYTES;
|
||||
if (!k) return WHY("I don't have the private key required to decrypt that");
|
||||
if (!k) { WHY("I don't have the private key required to decrypt that");
|
||||
RETURN(NULL); }
|
||||
bzero(&plain_block[0],crypto_box_curve25519xsalsa20poly1305_ZEROBYTES-16);
|
||||
int cipher_len=f->payload->length-nb;
|
||||
bcopy(&f->payload->bytes[nb],&plain_block[16],cipher_len);
|
||||
@ -360,17 +354,42 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
|
||||
dump("cipher block",&plain_block[16],cipher_len);
|
||||
}
|
||||
if (crypto_box_curve25519xsalsa20poly1305_open_afternm
|
||||
(plain_block,plain_block,cipher_len+16,nonce,k))
|
||||
return WHYF("crypto_box_open_afternm() failed (forged or corrupted packet of %d bytes)",cipher_len+16);
|
||||
(plain_block,plain_block,cipher_len+16,nonce,k)) {
|
||||
WHYF("crypto_box_open_afternm() failed (forged or corrupted packet of %d bytes)",cipher_len+16);
|
||||
RETURN(NULL);
|
||||
}
|
||||
if (0) dump("plain block",&plain_block[zb],cipher_len-16);
|
||||
b=&plain_block[zb];
|
||||
len=cipher_len-16;
|
||||
*len=cipher_len-16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RETURN(b);
|
||||
}
|
||||
|
||||
int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long now)
|
||||
{
|
||||
IN();
|
||||
/* Take frame source and destination and use them to populate mdp->in->{src,dst}
|
||||
SIDs.
|
||||
Take ports from mdp frame itself.
|
||||
Take payload from mdp frame itself.
|
||||
*/
|
||||
overlay_mdp_frame mdp;
|
||||
int len=f->payload->length;
|
||||
|
||||
/* Get source and destination addresses */
|
||||
bcopy(&f->destination[0],&mdp.in.dst.sid[0],SID_SIZE);
|
||||
bcopy(&f->source[0],&mdp.in.src.sid[0],SID_SIZE);
|
||||
|
||||
if (len<10) RETURN(WHY("Invalid MDP frame"));
|
||||
|
||||
/* copy crypto flags from frame so that we know if we need to decrypt or verify it */
|
||||
unsigned char *b = overlay_mdp_decrypt(f,&mdp,&len);
|
||||
if (!b) RETURN(-1);
|
||||
|
||||
int version=(b[0]<<8)+b[1];
|
||||
if (version!=0x0101) return WHY("Saw unsupported MDP frame version");
|
||||
if (version!=0x0101) RETURN(WHY("Saw unsupported MDP frame version"));
|
||||
|
||||
/* Indicate MDP message type */
|
||||
mdp.packetTypeAndFlags=MDP_TX;
|
||||
@ -385,7 +404,7 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
|
||||
bcopy(&b[10],&mdp.in.payload[0],mdp.in.payload_length);
|
||||
|
||||
/* and do something with it! */
|
||||
return overlay_saw_mdp_frame(interface,&mdp,now);
|
||||
RETURN(overlay_saw_mdp_frame(interface,&mdp,now));
|
||||
}
|
||||
|
||||
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp)
|
||||
@ -399,6 +418,7 @@ int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp)
|
||||
|
||||
int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
{
|
||||
IN();
|
||||
int i;
|
||||
int match=-1;
|
||||
|
||||
@ -419,7 +439,7 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
if ((!overlay_address_is_local(mdp->out.dst.sid))
|
||||
&&(!overlay_address_is_broadcast(mdp->out.dst.sid)))
|
||||
{
|
||||
return WHY("Asked to process an MDP packet that was not addressed to this node.");
|
||||
RETURN(WHY("Asked to process an MDP packet that was not addressed to this node."));
|
||||
}
|
||||
|
||||
for(i=0;i<MDP_MAX_BINDINGS;i++)
|
||||
@ -462,25 +482,26 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
int len=overlay_mdp_relevant_bytes(mdp);
|
||||
int r=sendto(mdp_named_socket,mdp,len,0,(struct sockaddr*)&addr,sizeof(addr));
|
||||
if (r==overlay_mdp_relevant_bytes(mdp)) {
|
||||
return 0;
|
||||
RETURN(0);
|
||||
}
|
||||
WHY("didn't send mdp packet");
|
||||
if (errno==ENOENT) {
|
||||
/* far-end of socket has died, so drop binding */
|
||||
printf("Closing dead MDP client '%s'\n",mdp_bindings_sockets[match]);
|
||||
overlay_mdp_releasebindings(&addr,mdp_bindings_socket_name_lengths[match]);
|
||||
}
|
||||
WHY_perror("sendto(e)");
|
||||
return WHY("Failed to pass received MDP frame to client");
|
||||
RETURN(WHY("Failed to pass received MDP frame to client"));
|
||||
} else {
|
||||
/* No socket is bound, ignore the packet ... except for magic sockets */
|
||||
switch(mdp->out.dst.port) {
|
||||
case MDP_PORT_VOMP:
|
||||
return vomp_mdp_received(mdp);
|
||||
RETURN(vomp_mdp_received(mdp));
|
||||
case MDP_PORT_KEYMAPREQUEST:
|
||||
/* Either respond with the appropriate SAS, or record this one if it
|
||||
verfies out okay. */
|
||||
DEBUG("key mapping request");
|
||||
return keyring_mapping_request(keyring,mdp);
|
||||
RETURN(keyring_mapping_request(keyring,mdp));
|
||||
case MDP_PORT_DNALOOKUP: /* attempt to resolve DID to SID */
|
||||
{
|
||||
int cn=0,in=0,kp=0;
|
||||
@ -488,8 +509,8 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
int pll=mdp->out.payload_length;
|
||||
if (pll>64) pll=64;
|
||||
/* get did from the packet */
|
||||
if (mdp->out.payload_length<1)
|
||||
return WHY("Empty DID in DNA resolution request");
|
||||
if (mdp->out.payload_length<1) {
|
||||
RETURN(WHY("Empty DID in DNA resolution request")); }
|
||||
bcopy(&mdp->out.payload[0],&did[0],pll);
|
||||
/* make sure it is null terminated */
|
||||
did[pll]=0;
|
||||
@ -553,7 +574,8 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
*/
|
||||
dna_helper_enqueue(did,mdp->out.src.sid);
|
||||
}
|
||||
return 0;
|
||||
RETURN(0);
|
||||
DEBUG("Got here");
|
||||
}
|
||||
break;
|
||||
case MDP_PORT_ECHO: /* well known ECHO port for TCP/UDP and now MDP */
|
||||
@ -564,7 +586,9 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
/* Swap addresses */
|
||||
overlay_mdp_swap_src_dst(mdp);
|
||||
|
||||
if (mdp->out.dst.port==MDP_PORT_ECHO) return WHY("echo loop averted");
|
||||
if (mdp->out.dst.port==MDP_PORT_ECHO) {
|
||||
RETURN(WHY("echo loop averted"));
|
||||
}
|
||||
/* If the packet was sent to broadcast, then replace broadcast address
|
||||
with our local address. For now just responds with first local address */
|
||||
if (overlay_address_is_broadcast(mdp->out.src.sid))
|
||||
@ -589,23 +613,23 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
and the frame needs sending on, as happens with broadcasts. MDP ping
|
||||
is a simple application where this occurs). */
|
||||
overlay_mdp_swap_src_dst(mdp);
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Unbound socket. We won't be sending ICMP style connection refused
|
||||
messages, partly because they are a waste of bandwidth. */
|
||||
return WHYF("Received packet for which no listening process exists (MDP ports: src=%d, dst=%d",
|
||||
mdp->out.src.port,mdp->out.dst.port);
|
||||
RETURN(WHYF("Received packet for which no listening process exists (MDP ports: src=%d, dst=%d",
|
||||
mdp->out.src.port,mdp->out.dst.port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return WHYF("We should only see MDP_TX frames here (MDP message type = 0x%x)",
|
||||
mdp->packetTypeAndFlags);
|
||||
RETURN(WHYF("We should only see MDP_TX frames here (MDP message type = 0x%x)",
|
||||
mdp->packetTypeAndFlags));
|
||||
}
|
||||
|
||||
return WHY("Not implemented");
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
int overlay_mdp_sanitytest_sourceaddr(sockaddr_mdp *src,int userGeneratedFrameP,
|
||||
@ -682,17 +706,18 @@ int overlay_mdp_sanitytest_sourceaddr(sockaddr_mdp *src,int userGeneratedFrameP,
|
||||
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
struct sockaddr_un *recvaddr,int recvaddrlen)
|
||||
{
|
||||
IN();
|
||||
/* Work out if destination is broadcast or not */
|
||||
int broadcast=1;
|
||||
|
||||
if (overlay_mdp_sanitytest_sourceaddr(&mdp->out.src,userGeneratedFrameP,
|
||||
recvaddr,recvaddrlen))
|
||||
return overlay_mdp_reply_error
|
||||
(mdp_named_socket,
|
||||
(struct sockaddr_un *)recvaddr,
|
||||
recvaddrlen,8,
|
||||
"Source address is invalid (you must bind to a source address before"
|
||||
" you can send packets");
|
||||
RETURN(overlay_mdp_reply_error
|
||||
(mdp_named_socket,
|
||||
(struct sockaddr_un *)recvaddr,
|
||||
recvaddrlen,8,
|
||||
"Source address is invalid (you must bind to a source address before"
|
||||
" you can send packets"));
|
||||
|
||||
if (!overlay_address_is_broadcast(mdp->out.dst.sid)) broadcast=0;
|
||||
|
||||
@ -704,7 +729,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
if (!broadcast) {
|
||||
/* Is local, and is not broadcast, so shouldn't get sent out
|
||||
on the wire. */
|
||||
return 0;
|
||||
RETURN(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,14 +738,14 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
NaCl cryptobox keys can be used for signing. */
|
||||
if (broadcast) {
|
||||
if (!(mdp->packetTypeAndFlags&MDP_NOCRYPT))
|
||||
return overlay_mdp_reply_error(mdp_named_socket,
|
||||
RETURN(overlay_mdp_reply_error(mdp_named_socket,
|
||||
recvaddr,recvaddrlen,5,
|
||||
"Broadcast packets cannot be encrypted "); }
|
||||
"Broadcast packets cannot be encrypted ")); }
|
||||
|
||||
/* Prepare the overlay frame for dispatch */
|
||||
struct overlay_frame *frame;
|
||||
frame=calloc(sizeof(overlay_frame),1);
|
||||
if (!frame) return WHY_perror("calloc");
|
||||
if (!frame) RETURN(WHY_perror("calloc"));
|
||||
/* give voice packets priority */
|
||||
if (mdp->out.dst.port==MDP_PORT_VOMP) frame->type=OF_TYPE_DATA_VOICE;
|
||||
else frame->type=OF_TYPE_DATA;
|
||||
@ -749,7 +774,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES];
|
||||
if (urandombytes(nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES)) {
|
||||
op_free(frame);
|
||||
return WHY("urandombytes() failed to generate nonce");
|
||||
RETURN(WHY("urandombytes() failed to generate nonce"));
|
||||
}
|
||||
fe|= ob_append_bytes(frame->payload,nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES);
|
||||
/* generate plain message with zero bytes and get ready to cipher it */
|
||||
@ -777,16 +802,16 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
/* get pre-computed PKxSK bytes (the slow part of auth-cryption that can be
|
||||
retained and reused, and use that to do the encryption quickly. */
|
||||
unsigned char *k=keyring_get_nm_bytes(&mdp->out.src,&mdp->out.dst);
|
||||
if (!k) { op_free(frame); return WHY("could not compute Curve25519(NxM)"); }
|
||||
if (!k) { op_free(frame); RETURN(WHY("could not compute Curve25519(NxM)")); }
|
||||
/* Get pointer to place in frame where the ciphered text needs to go */
|
||||
int cipher_offset=frame->payload->length;
|
||||
unsigned char *cipher_text=ob_append_space(frame->payload,cipher_len);
|
||||
if (fe||(!cipher_text))
|
||||
{ op_free(frame); return WHY("could not make space for ciphered text"); }
|
||||
{ op_free(frame); RETURN(WHY("could not make space for ciphered text")); }
|
||||
/* Actually authcrypt the payload */
|
||||
if (crypto_box_curve25519xsalsa20poly1305_afternm
|
||||
(cipher_text,plain,cipher_len,nonce,k))
|
||||
{ op_free(frame); return WHY("crypto_box_afternm() failed"); }
|
||||
{ op_free(frame); RETURN(WHY("crypto_box_afternm() failed")); }
|
||||
/* now shuffle down 16 bytes to get rid of the temporary space that crypto_box
|
||||
uses. */
|
||||
bcopy(&cipher_text[16],&cipher_text[0],cipher_len-16);
|
||||
@ -811,7 +836,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
*/
|
||||
frame->modifiers=OF_CRYPTO_CIPHERED;
|
||||
op_free(frame);
|
||||
return WHY("ciphered MDP packets not implemented");
|
||||
RETURN(WHY("ciphered MDP packets not implemented"));
|
||||
break;
|
||||
case MDP_NOCRYPT:
|
||||
/* Payload is sent unencrypted, but signed.
|
||||
@ -834,7 +859,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
+mdp->out.payload_length);
|
||||
{
|
||||
unsigned char *key=keyring_find_sas_private(keyring,mdp->out.src.sid,NULL);
|
||||
if (!key) { op_free(frame); return WHY("could not find signing key"); }
|
||||
if (!key) { op_free(frame); RETURN(WHY("could not find signing key")); }
|
||||
|
||||
/* Build plain-text that includes header and hash it so that
|
||||
we can sign that hash. */
|
||||
@ -864,7 +889,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
crypto_sign_edwards25519sha512batch(signature,&sig_len,
|
||||
hash,crypto_hash_sha512_BYTES,
|
||||
key);
|
||||
if (!sig_len) { op_free(frame); return WHY("Signing MDP frame failed"); }
|
||||
if (!sig_len) { op_free(frame); RETURN(WHY("Signing MDP frame failed")); }
|
||||
/* chop hash out of middle of signature since it has to be recomputed
|
||||
at the far end, anyway, as described above. */
|
||||
bcopy(&signature[32+64],&signature[32],32);
|
||||
@ -918,11 +943,11 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
|
||||
if (overlay_payload_enqueue(q,frame,0))
|
||||
{
|
||||
if (frame) op_free(frame);
|
||||
return WHY("Error enqueuing frame");
|
||||
RETURN(WHY("Error enqueuing frame"));
|
||||
}
|
||||
else {
|
||||
if (debug&DEBUG_OVERLAYINTERFACES) DEBUG("queued frame");
|
||||
return 0;
|
||||
RETURN(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
20
serval.h
20
serval.h
@ -1538,6 +1538,13 @@ void sigIoHandler(int signal);
|
||||
|
||||
#define WRITE_STR(fd, str) write(fd, str, strlen(str))
|
||||
|
||||
int rhizome_server_start();
|
||||
void rhizome_enqueue_suggestions();
|
||||
int overlay_mdp_setup_sockets();
|
||||
void overlay_interface_poll(int fd);
|
||||
void overlay_dummy_poll();
|
||||
void rhizome_client_poll(int fd);
|
||||
|
||||
/* Event queue handling functions */
|
||||
int fd_poll();
|
||||
int fd_checkalarms();
|
||||
@ -1548,10 +1555,11 @@ int fd_list();
|
||||
char *fd_funcname(void *addr);
|
||||
int fd_showstats();
|
||||
void fd_periodicstats();
|
||||
int fd_next_funcid();
|
||||
int fd_func_exit(int funcid);
|
||||
int fd_func_enter(int funcid);
|
||||
int fd_next_funcid(const char *funcname);
|
||||
|
||||
int rhizome_server_start();
|
||||
void rhizome_enqueue_suggestions();
|
||||
int overlay_mdp_setup_sockets();
|
||||
void overlay_interface_poll(int fd);
|
||||
void overlay_dummy_poll();
|
||||
void rhizome_client_poll(int fd);
|
||||
#define IN() static int _func_id=-1; if (_func_id<0) _func_id=fd_next_funcid(__FUNCTION__); fd_func_enter(_func_id);
|
||||
#define OUT() fd_func_exit(_func_id);
|
||||
#define RETURN(X) { OUT() return(X); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user