mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
More work on MDP.
Swapped functions of overlay_mdp_send() and overlay_mdp_dispatch() to match normal socket operations and thus avoid programmer confusion.
This commit is contained in:
parent
d3cd7714ac
commit
8fbbdc5087
@ -373,7 +373,7 @@ int app_mdp_ping(int argc,char **argv,struct command_line_option *o)
|
||||
mdp.addrlist.first_sid=-1;
|
||||
mdp.addrlist.last_sid=0x7fffffff;
|
||||
mdp.addrlist.frame_sid_count=MDP_MAX_SID_REQUEST;
|
||||
int result=overlay_mdp_dispatch(&mdp,MDP_AWAITREPLY,5000);
|
||||
int result=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
|
||||
if (result) {
|
||||
if (mdp.packetTypeAndFlags==MDP_ERROR)
|
||||
{
|
||||
@ -407,7 +407,7 @@ int app_mdp_ping(int argc,char **argv,struct command_line_option *o)
|
||||
unsigned char srcsid[SID_SIZE];
|
||||
bcopy(mdp.bind.sid,srcsid,SID_SIZE);
|
||||
mdp.bind.port_number=port;
|
||||
result=overlay_mdp_dispatch(&mdp,MDP_AWAITREPLY,5000);
|
||||
result=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
|
||||
if (result) {
|
||||
if (mdp.packetTypeAndFlags==MDP_ERROR)
|
||||
fprintf(stderr,"Could not bind to MDP port %d: error=%d, message='%s'\n",
|
||||
|
338
overlay_mdp.c
338
overlay_mdp.c
@ -276,6 +276,8 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
|
||||
|
||||
int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
{
|
||||
int i;
|
||||
int match=-1;
|
||||
printf("mdp frame type=0x%x\n",mdp->packetTypeAndFlags);
|
||||
|
||||
switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK) {
|
||||
@ -283,7 +285,77 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
/* Regular MDP frame addressed to us. Look for matching port binding,
|
||||
and if available, push to client. Else do nothing, or if we feel nice
|
||||
send back a connection refused type message? Silence is probably the
|
||||
more prudent path. */
|
||||
more prudent path. */
|
||||
if ((!overlay_address_is_local(mdp->out.dst.sid))
|
||||
&&(!overlay_address_is_broadcast(mdp->out.dst.sid)))
|
||||
{
|
||||
fprintf(stderr,"%s is not a local address\n",
|
||||
overlay_render_sid(mdp->out.dst.sid));
|
||||
return WHY("Asked to process an MDP packet that was not addressed to this node.");
|
||||
}
|
||||
|
||||
for(i=0;i<MDP_MAX_BINDINGS;i++)
|
||||
{
|
||||
if (!bcmp(&mdp->out.dst,&mdp_bindings[i],sizeof(sockaddr_mdp)))
|
||||
{ /* exact and specific match, so stop searching */
|
||||
match=i; break; }
|
||||
else {
|
||||
/* No exact match, so see if the port matches, and local-side address
|
||||
is the anonymous address (all zeroes), the destination address is
|
||||
a local address, and the ports match. This is to find matches to
|
||||
the mdp equivalent of a socket bound to 0.0.0.0:port in IPv4.
|
||||
|
||||
Just as with the IPv4 situation, we prioritise ports that are listening
|
||||
on a specific address over those with no address bound. Thus we only
|
||||
try to match these 0.0.0.0 style bindings if there is no specific
|
||||
binding, and we keep looking in case there is a more specific binding.
|
||||
|
||||
Because there is no concept of sub-nets in the Serval overlay mesh
|
||||
(since addresses are randomly allocated from the entire address
|
||||
space), we don't have to worry about a more structured heirarchy where
|
||||
more completely specified addresses take priority over less completely
|
||||
specified addresses.
|
||||
*/
|
||||
if (match==-1)
|
||||
if (mdp->out.dst.port==mdp_bindings[i].port)
|
||||
{
|
||||
int j;
|
||||
for(j=0;j<SID_SIZE;j++) if (mdp_bindings[i].sid[j]) break;
|
||||
if (j==SID_SIZE) match=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match>-1) {
|
||||
/* We now know the socket, and so we can pass the MDP_TX frame to the
|
||||
recipient. We do, however, translate it into an MDP_RX frame first,
|
||||
so that the recipient understands the context. */
|
||||
} else {
|
||||
/* No socket is bound, ignore the packet ... except for magic sockets */
|
||||
switch(mdp->out.dst.port) {
|
||||
case 7: /* well known ECHO port for TCP/UDP and now MDP */
|
||||
{
|
||||
/* Echo is easy: we swap the sender and receiver addresses (and thus port
|
||||
numbers) and send the frame back. */
|
||||
|
||||
/* Swap addresses */
|
||||
sockaddr_mdp temp;
|
||||
bcopy(&mdp->out.dst,&temp,sizeof(sockaddr_mdp));
|
||||
bcopy(&mdp->out.src,&mdp->out.dst,sizeof(sockaddr_mdp));
|
||||
bcopy(&temp,&mdp->out.src,sizeof(sockaddr_mdp));
|
||||
|
||||
/* queue frame for delivery */
|
||||
return
|
||||
overlay_saw_mdp_frame(-1 /* we don't know the originating interface */,
|
||||
mdp,overlay_gettime_ms());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Unbound socket. We won't be sending ICMP style connection refused
|
||||
messages, partly because they are a waste of bandwidth. */
|
||||
return WHY("Received packet for which no listening process exists");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return WHY("We should only see MDP_TX frames here");
|
||||
@ -334,6 +406,139 @@ int overlay_mdp_sanitytest_sourceaddr(sockaddr_mdp *src,
|
||||
return WHY("No such socket binding:unix domain socket tuple exists -- someone might be trying to spoof someone else's connection");
|
||||
}
|
||||
|
||||
/* Construct MDP packet frame from overlay_mdp_frame structure
|
||||
(need to add return address from bindings list, and copy
|
||||
payload etc).
|
||||
This is for use by the SERVER.
|
||||
Clients should use overlay_mdp_send()
|
||||
*/
|
||||
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,
|
||||
struct sockaddr_un *recvaddr,int recvaddrlen)
|
||||
{
|
||||
/* Work out if destination is broadcast or not */
|
||||
int broadcast=1;
|
||||
|
||||
if (overlay_mdp_sanitytest_sourceaddr(&mdp->out.src,
|
||||
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");
|
||||
|
||||
if (!overlay_address_is_broadcast(mdp->out.dst.sid)) broadcast=0;
|
||||
|
||||
if (overlay_address_is_local(mdp->out.dst.sid)||broadcast)
|
||||
{
|
||||
/* Packet is addressed such that we should process it. */
|
||||
overlay_saw_mdp_frame(-1 /* not received on a network interface */,
|
||||
mdp,overlay_gettime_ms());
|
||||
|
||||
if (!broadcast) {
|
||||
/* Is local, and is not broadcast, so shouldn't get sent out
|
||||
on the wire. */
|
||||
WHY("non-broadcast packet delivered locally");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* broadcast packets cannot be encrypted, so complain if MDP_NOCRYPT
|
||||
flag is not set. Also, MDP_NOSIGN must also be applied, until
|
||||
NaCl cryptobox keys can be used for signing. */
|
||||
if (broadcast) {
|
||||
if ((mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN))
|
||||
!=(MDP_NOCRYPT|MDP_NOSIGN))
|
||||
return overlay_mdp_reply_error(mdp_named_socket,
|
||||
recvaddr,recvaddrlen,5,
|
||||
"Broadcast packets cannot be encrypted "
|
||||
"or signed (signing will be possible in"
|
||||
" a future version).");
|
||||
}
|
||||
|
||||
/* Prepare the overlay frame for dispatch */
|
||||
struct overlay_frame *frame;
|
||||
frame=calloc(sizeof(overlay_frame),1);
|
||||
if (!frame) return WHY("calloc() failed to allocate overlay frame");
|
||||
frame->type=OF_TYPE_DATA;
|
||||
frame->prev=NULL;
|
||||
frame->next=NULL;
|
||||
|
||||
/* Work out the disposition of the frame. For now we are only worried
|
||||
about the crypto matters, and not compression that may be applied
|
||||
before encryption (since applying it after is useless as ciphered
|
||||
text should have maximum entropy). */
|
||||
switch(mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN)) {
|
||||
case 0: /* crypted and signed (using CryptBox authcryption primitive) */
|
||||
frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED;
|
||||
op_free(frame);
|
||||
return WHY("ciphered+signed MDP frames not implemented");
|
||||
break;
|
||||
case MDP_NOSIGN:
|
||||
/* ciphered, but not signed.
|
||||
This means we don't use CryptoBox, but rather a more compact means
|
||||
of representing the ciphered stream segment.
|
||||
*/
|
||||
frame->modifiers=OF_CRYPTO_CIPHERED;
|
||||
op_free(frame);
|
||||
return WHY("ciphered MDP packets not implemented");
|
||||
break;
|
||||
case MDP_NOCRYPT:
|
||||
/* clear text, but signed (need to think about how to implement this
|
||||
while NaCl cannot sign using CryptoBox keys. We could use a
|
||||
CryptoSign key, and allow queries as to the authenticity of said key
|
||||
via authcrypted channel between the parties. */
|
||||
frame->modifiers=OF_CRYPTO_SIGNED;
|
||||
op_free(frame);
|
||||
return WHY("signed MDP packets not implemented");
|
||||
break;
|
||||
case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */
|
||||
frame->modifiers=0;
|
||||
/* Copy payload body in */
|
||||
frame->payload=ob_new(1 /* frame type (MDP) */
|
||||
+1 /* MDP version */
|
||||
+4 /* dst port */
|
||||
+4 /* src port */
|
||||
+mdp->out.payload_length);
|
||||
/* MDP version 1 */
|
||||
ob_append_byte(frame->payload,0x01);
|
||||
ob_append_byte(frame->payload,0x01);
|
||||
/* Destination port */
|
||||
ob_append_int(frame->payload,mdp->out.dst.port);
|
||||
/* XXX we should probably pull the source port from the bindings
|
||||
On that note, when a binding is granted, we should probably
|
||||
provide a token that can be used to lookup the binding and
|
||||
indicate which binding the packet is for? */
|
||||
ob_append_int(frame->payload,0);
|
||||
ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length);
|
||||
break;
|
||||
}
|
||||
frame->ttl=64; /* normal TTL (XXX allow setting this would be a good idea) */
|
||||
/* set source to ourselves
|
||||
XXX should eventually honour binding, which should allow choosing which
|
||||
local identity. This will be required for openbts integration/SIP:MSIP
|
||||
gateways etc. */
|
||||
overlay_frame_set_me_as_source(frame);
|
||||
|
||||
/* Set destination address */
|
||||
if (broadcast)
|
||||
overlay_frame_set_broadcast_as_destination(frame);
|
||||
else{
|
||||
bcopy(&mdp->out.dst.sid[0],frame->destination,SID_SIZE);
|
||||
frame->destination_address_status=OA_RESOLVED;
|
||||
}
|
||||
|
||||
if (overlay_payload_enqueue(OQ_ORDINARY,frame))
|
||||
{
|
||||
if (frame) op_free(frame);
|
||||
return WHY("Error enqueuing frame");
|
||||
}
|
||||
else {
|
||||
WHY("queued frame");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int overlay_mdp_poll()
|
||||
{
|
||||
unsigned char buffer[16384];
|
||||
@ -395,134 +600,7 @@ int overlay_mdp_poll()
|
||||
}
|
||||
break;
|
||||
case MDP_TX: /* Send payload */
|
||||
/* Construct MDP packet frame from overlay_mdp_frame structure
|
||||
(need to add return address from bindings list, and copy
|
||||
payload etc). */
|
||||
{
|
||||
/* Work out if destination is broadcast or not */
|
||||
int broadcast=1;
|
||||
|
||||
if (overlay_mdp_sanitytest_sourceaddr(&mdp->out.src,
|
||||
(struct sockaddr_un *)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");
|
||||
|
||||
if (!overlay_address_is_broadcast(mdp->out.dst.sid)) broadcast=0;
|
||||
|
||||
if (overlay_address_is_local(mdp->out.dst.sid)||broadcast)
|
||||
{
|
||||
/* Packet is addressed such that we should process it. */
|
||||
overlay_saw_mdp_frame(-1 /* not received on a network interface */,
|
||||
mdp,overlay_gettime_ms());
|
||||
|
||||
if (!broadcast) {
|
||||
/* Is local, and is not broadcast, so shouldn't get sent out
|
||||
on the wire. */
|
||||
WHY("non-broadcast packet delivered locally");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* broadcast packets cannot be encrypted, so complain if MDP_NOCRYPT
|
||||
flag is not set. Also, MDP_NOSIGN must also be applied, until
|
||||
NaCl cryptobox keys can be used for signing. */
|
||||
if (broadcast) {
|
||||
if ((mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN))
|
||||
!=(MDP_NOCRYPT|MDP_NOSIGN))
|
||||
return overlay_mdp_reply_error(mdp_named_socket,
|
||||
recvaddr_un,recvaddrlen,5,
|
||||
"Broadcast packets cannot be encrypted "
|
||||
"or signed (signing will be possible in"
|
||||
" a future version).");
|
||||
}
|
||||
|
||||
/* Prepare the overlay frame for dispatch */
|
||||
struct overlay_frame *frame;
|
||||
frame=calloc(sizeof(overlay_frame),1);
|
||||
if (!frame) return WHY("calloc() failed to allocate overlay frame");
|
||||
frame->type=OF_TYPE_DATA;
|
||||
frame->prev=NULL;
|
||||
frame->next=NULL;
|
||||
|
||||
/* Work out the disposition of the frame. For now we are only worried
|
||||
about the crypto matters, and not compression that may be applied
|
||||
before encryption (since applying it after is useless as ciphered
|
||||
text should have maximum entropy). */
|
||||
switch(mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN)) {
|
||||
case 0: /* crypted and signed (using CryptBox authcryption primitive) */
|
||||
frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED;
|
||||
op_free(frame);
|
||||
return WHY("ciphered+signed MDP frames not implemented");
|
||||
break;
|
||||
case MDP_NOSIGN:
|
||||
/* ciphered, but not signed.
|
||||
This means we don't use CryptoBox, but rather a more compact means
|
||||
of representing the ciphered stream segment.
|
||||
*/
|
||||
frame->modifiers=OF_CRYPTO_CIPHERED;
|
||||
op_free(frame);
|
||||
return WHY("ciphered MDP packets not implemented");
|
||||
break;
|
||||
case MDP_NOCRYPT:
|
||||
/* clear text, but signed (need to think about how to implement this
|
||||
while NaCl cannot sign using CryptoBox keys. We could use a
|
||||
CryptoSign key, and allow queries as to the authenticity of said key
|
||||
via authcrypted channel between the parties. */
|
||||
frame->modifiers=OF_CRYPTO_SIGNED;
|
||||
op_free(frame);
|
||||
return WHY("signed MDP packets not implemented");
|
||||
break;
|
||||
case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */
|
||||
frame->modifiers=0;
|
||||
/* Copy payload body in */
|
||||
frame->payload=ob_new(1 /* frame type (MDP) */
|
||||
+1 /* MDP version */
|
||||
+4 /* dst port */
|
||||
+4 /* src port */
|
||||
+mdp->out.payload_length);
|
||||
/* MDP version 1 */
|
||||
ob_append_byte(frame->payload,0x01);
|
||||
ob_append_byte(frame->payload,0x01);
|
||||
/* Destination port */
|
||||
ob_append_int(frame->payload,mdp->out.dst.port);
|
||||
/* XXX we should probably pull the source port from the bindings
|
||||
On that note, when a binding is granted, we should probably
|
||||
provide a token that can be used to lookup the binding and
|
||||
indicate which binding the packet is for? */
|
||||
ob_append_int(frame->payload,0);
|
||||
ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length);
|
||||
break;
|
||||
}
|
||||
frame->ttl=64; /* normal TTL (XXX allow setting this would be a good idea) */
|
||||
/* set source to ourselves
|
||||
XXX should eventually honour binding, which should allow choosing which
|
||||
local identity. This will be required for openbts integration/SIP:MSIP
|
||||
gateways etc. */
|
||||
overlay_frame_set_me_as_source(frame);
|
||||
|
||||
/* Set destination address */
|
||||
if (broadcast)
|
||||
overlay_frame_set_broadcast_as_destination(frame);
|
||||
else{
|
||||
bcopy(&mdp->out.dst.sid[0],frame->destination,SID_SIZE);
|
||||
frame->destination_address_status=OA_RESOLVED;
|
||||
}
|
||||
|
||||
if (overlay_payload_enqueue(OQ_ORDINARY,frame))
|
||||
{
|
||||
if (frame) op_free(frame);
|
||||
return WHY("Error enqueuing frame");
|
||||
}
|
||||
else {
|
||||
WHY("queued frame");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return overlay_mdp_dispatch(mdp,(struct sockaddr_un*)recvaddr,recvaddrlen);
|
||||
break;
|
||||
case MDP_BIND: /* Bind to port */
|
||||
return overlay_mdp_process_bind_request(mdp_named_socket,mdp,
|
||||
@ -591,7 +669,7 @@ int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp)
|
||||
}
|
||||
|
||||
int mdp_client_socket=-1;
|
||||
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int flags,int timeout_ms)
|
||||
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
|
||||
{
|
||||
int len=4;
|
||||
|
||||
|
30
serval.h
30
serval.h
@ -1000,20 +1000,13 @@ typedef struct sockaddr_mdp {
|
||||
#define MDP_NOCRYPT 0x0200
|
||||
#define MDP_NOSIGN 0x0400
|
||||
#define MDP_TX 1
|
||||
#define MDP_RX 2
|
||||
typedef struct overlay_mdp_outgoing_frame {
|
||||
sockaddr_mdp src;
|
||||
sockaddr_mdp dst;
|
||||
unsigned short payload_length;
|
||||
unsigned char payload[1900];
|
||||
} overlay_mdp_outgoing_frame;
|
||||
|
||||
#define MDP_RX 2
|
||||
typedef struct overlay_mdp_incoming_frame {
|
||||
sockaddr_mdp dst;
|
||||
sockaddr_mdp src;
|
||||
unsigned short payload_length;
|
||||
unsigned char payload[1900];
|
||||
} overlay_mdp_incoming_frame;
|
||||
} overlay_mdp_data_frame;
|
||||
|
||||
#define MDP_BIND 3
|
||||
typedef struct overlay_mdp_bind_request {
|
||||
@ -1045,8 +1038,8 @@ typedef struct overlay_mdp_frame {
|
||||
#define MDP_AWAITREPLY 7
|
||||
unsigned int packetTypeAndFlags;
|
||||
union {
|
||||
overlay_mdp_outgoing_frame out;
|
||||
overlay_mdp_incoming_frame in;
|
||||
overlay_mdp_data_frame out;
|
||||
overlay_mdp_data_frame in;
|
||||
overlay_mdp_bind_request bind;
|
||||
overlay_mdp_addrlist addrlist;
|
||||
overlay_mdp_error error;
|
||||
@ -1056,20 +1049,23 @@ typedef struct overlay_mdp_frame {
|
||||
};
|
||||
} overlay_mdp_frame;
|
||||
|
||||
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int flags,int timeout_ms);
|
||||
int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now);
|
||||
|
||||
|
||||
int setVerbosity(char *optarg);
|
||||
|
||||
/* Client-side MDP function */
|
||||
extern int mdp_client_socket;
|
||||
int overlay_mdp_client_init();
|
||||
int overlay_mdp_client_done();
|
||||
int overlay_mdp_client_poll(long long timeout_ms);
|
||||
int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl);
|
||||
extern int mdp_client_socket;
|
||||
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms);
|
||||
|
||||
/* Server-side MDP functions */
|
||||
int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now);
|
||||
int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr,int recvaddrlen,
|
||||
overlay_mdp_frame *mdpreply);
|
||||
int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp);
|
||||
|
||||
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,
|
||||
struct sockaddr_un *recvaddr,int recvaddlen);
|
||||
|
||||
int ob_bcopy(overlay_buffer *b,int from, int to, int len);
|
||||
int ob_setbyte(overlay_buffer *b,int ofs,unsigned char value);
|
||||
|
Loading…
x
Reference in New Issue
Block a user