mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
Split client mdp functions so they can be built separately
This commit is contained in:
parent
a73b9ee7f7
commit
6483d9e0ae
@ -19,6 +19,7 @@ SERVALD_SRC_FILES = \
|
||||
serval-dna/xprintf.c \
|
||||
serval-dna/log.c \
|
||||
serval-dna/net.c \
|
||||
serval-dna/mdp_client.c \
|
||||
serval-dna/mkdir.c \
|
||||
serval-dna/strbuf.c \
|
||||
serval-dna/strbuf_helpers.c \
|
||||
|
12
Makefile.in
Executable file → Normal file
12
Makefile.in
Executable file → Normal file
@ -20,6 +20,7 @@ SRCS= \
|
||||
log.c \
|
||||
lsif.c \
|
||||
main.c \
|
||||
mdp_client.c \
|
||||
mkdir.c \
|
||||
monitor.c \
|
||||
monitor-cli.c \
|
||||
@ -69,6 +70,15 @@ MONITORCLIENTSRCS=conf.c \
|
||||
strbuf.c \
|
||||
strbuf_helpers.c
|
||||
|
||||
MDPCLIENTSRCS=conf.c \
|
||||
mkdir.c \
|
||||
log.c \
|
||||
mdp_client.c \
|
||||
net.c \
|
||||
str.c \
|
||||
strbuf.c \
|
||||
strbuf_helpers.c
|
||||
|
||||
HAVE_VOIPTEST= @HAVE_VOIPTEST@
|
||||
ifeq ($(HAVE_VOIPTEST), 1)
|
||||
SRCS+= pa_phone.c
|
||||
@ -78,6 +88,7 @@ endif
|
||||
OBJS= $(SRCS:.c=.o)
|
||||
|
||||
MONITORCLIENTOBJS= $(MONITORCLIENTSRCS:.c=.o)
|
||||
MDPCLIENTOBJS= $(MDPCLIENTSRCS:.c=.o)
|
||||
|
||||
HDRS= fifo.h \
|
||||
Makefile \
|
||||
@ -95,6 +106,7 @@ HDRS= fifo.h \
|
||||
xprintf.h \
|
||||
constants.h \
|
||||
monitor-client.h \
|
||||
mdp_client.h \
|
||||
sqlite-amalgamation-3070900/sqlite3.h
|
||||
|
||||
LDFLAGS=@LDFLAGS@ @PORTAUDIO_LIBS@ @SRC_LIBS@ @SPANDSP_LIBS@ @CODEC2_LIBS@ @PTHREAD_LIBS@
|
||||
|
@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "serval.h"
|
||||
#include "rhizome.h"
|
||||
#include "strbuf.h"
|
||||
#include "mdp_client.h"
|
||||
|
||||
int cli_usage() {
|
||||
printf("Serval Mesh version <version>.\n");
|
||||
|
35
keyring.c
35
keyring.c
@ -20,41 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "nacl.h"
|
||||
#include "overlay_address.h"
|
||||
|
||||
static int urandomfd = -1;
|
||||
|
||||
int urandombytes(unsigned char *x, unsigned long long xlen)
|
||||
{
|
||||
int tries = 0;
|
||||
if (urandomfd == -1) {
|
||||
for (tries = 0; tries < 4; ++tries) {
|
||||
urandomfd = open("/dev/urandom",O_RDONLY);
|
||||
if (urandomfd != -1) break;
|
||||
sleep(1);
|
||||
}
|
||||
if (urandomfd == -1) {
|
||||
WHY_perror("open(/dev/urandom)");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
tries = 0;
|
||||
while (xlen > 0) {
|
||||
int i = (xlen < 1048576) ? xlen : 1048576;
|
||||
i = read(urandomfd, x, i);
|
||||
if (i == -1) {
|
||||
if (++tries > 4) {
|
||||
WHY_perror("read(/dev/urandom)");
|
||||
return -1;
|
||||
}
|
||||
sleep(1);
|
||||
} else {
|
||||
tries = 0;
|
||||
x += i;
|
||||
xlen -= i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Open keyring file, read BAM and create initial context using the
|
||||
stored salt. */
|
||||
|
300
mdp_client.c
Normal file
300
mdp_client.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
Copyright (C) 2010-2012 Paul Gardner-Stephen, Serval Project.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "serval.h"
|
||||
#include "strbuf.h"
|
||||
#include "overlay_buffer.h"
|
||||
#include "overlay_address.h"
|
||||
#include "overlay_packet.h"
|
||||
#include "mdp_client.h"
|
||||
|
||||
int mdp_client_socket=-1;
|
||||
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
|
||||
{
|
||||
int len=4;
|
||||
|
||||
if (mdp_client_socket==-1)
|
||||
if (overlay_mdp_client_init() != 0)
|
||||
return -1;
|
||||
|
||||
/* Minimise frame length to save work and prevent accidental disclosure of
|
||||
memory contents. */
|
||||
len=overlay_mdp_relevant_bytes(mdp);
|
||||
if (len<0) return WHY("MDP frame invalid (could not compute length)");
|
||||
|
||||
/* Construct name of socket to send to. */
|
||||
struct sockaddr_un name;
|
||||
name.sun_family = AF_UNIX;
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(name.sun_path, "mdp.socket"))
|
||||
return -1;
|
||||
|
||||
set_nonblock(mdp_client_socket);
|
||||
int result=sendto(mdp_client_socket, mdp, len, 0,
|
||||
(struct sockaddr *)&name, sizeof(struct sockaddr_un));
|
||||
set_block(mdp_client_socket);
|
||||
if (result<0) {
|
||||
mdp->packetTypeAndFlags=MDP_ERROR;
|
||||
mdp->error.error=1;
|
||||
snprintf(mdp->error.message,128,"Error sending frame to MDP server.");
|
||||
return WHY_perror("sendto(f)");
|
||||
} else {
|
||||
if (!(flags&MDP_AWAITREPLY)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay_mdp_client_poll(timeout_ms)<=0){
|
||||
/* Timeout */
|
||||
mdp->packetTypeAndFlags=MDP_ERROR;
|
||||
mdp->error.error=1;
|
||||
snprintf(mdp->error.message,128,"Timeout waiting for reply to MDP packet (packet was successfully sent).");
|
||||
return -1; /* WHY("Timeout waiting for server response"); */
|
||||
}
|
||||
|
||||
int ttl=-1;
|
||||
if (!overlay_mdp_recv(mdp,&ttl)) {
|
||||
/* If all is well, examine result and return error code provided */
|
||||
if ((mdp->packetTypeAndFlags&MDP_TYPE_MASK)==MDP_ERROR)
|
||||
return mdp->error.error;
|
||||
else
|
||||
/* Something other than an error has been returned */
|
||||
return 0;
|
||||
} else {
|
||||
/* poll() said that there was data, but there isn't.
|
||||
So we will abort. */
|
||||
return WHY("poll() aborted");
|
||||
}
|
||||
}
|
||||
|
||||
char overlay_mdp_client_socket_path[1024];
|
||||
int overlay_mdp_client_socket_path_len=-1;
|
||||
|
||||
int overlay_mdp_client_init()
|
||||
{
|
||||
if (mdp_client_socket==-1) {
|
||||
/* Open socket to MDP server (thus connection is always local) */
|
||||
if (0) WHY("Use of abstract name space socket for Linux not implemented");
|
||||
|
||||
mdp_client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (mdp_client_socket < 0) {
|
||||
WHY_perror("socket");
|
||||
return WHY("Could not open socket to MDP server");
|
||||
}
|
||||
|
||||
/* We must bind to a temporary file name */
|
||||
struct sockaddr_un name;
|
||||
unsigned int random_value;
|
||||
if (urandombytes((unsigned char *)&random_value,sizeof(int)))
|
||||
return WHY("urandombytes() failed");
|
||||
name.sun_family = AF_UNIX;
|
||||
if (overlay_mdp_client_socket_path_len==-1) {
|
||||
char fmt[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(fmt, "mdp-client-%d-%08x.socket"))
|
||||
return WHY("Could not form MDP client socket name");
|
||||
snprintf(overlay_mdp_client_socket_path,1024,fmt,getpid(),random_value);
|
||||
overlay_mdp_client_socket_path_len=strlen(overlay_mdp_client_socket_path)+1;
|
||||
if(debug&DEBUG_IO) DEBUGF("MDP client socket name='%s'",overlay_mdp_client_socket_path);
|
||||
}
|
||||
if (overlay_mdp_client_socket_path_len > 104 - 1)
|
||||
FATALF("MDP socket path too long (%d > %d)", overlay_mdp_client_socket_path_len, 104 - 1);
|
||||
|
||||
bcopy(overlay_mdp_client_socket_path,name.sun_path,
|
||||
overlay_mdp_client_socket_path_len);
|
||||
unlink(name.sun_path);
|
||||
int len = 1 + strlen(name.sun_path) + sizeof(name.sun_family) + 1;
|
||||
int r=bind(mdp_client_socket, (struct sockaddr *)&name, len);
|
||||
if (r) {
|
||||
WHY_perror("bind");
|
||||
return WHY("Could not bind MDP client socket to file name");
|
||||
}
|
||||
|
||||
int send_buffer_size=128*1024;
|
||||
if (setsockopt(mdp_client_socket, SOL_SOCKET, SO_RCVBUF,
|
||||
&send_buffer_size, sizeof(send_buffer_size)) == -1)
|
||||
WARN_perror("setsockopt");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_client_done()
|
||||
{
|
||||
if (mdp_client_socket!=-1) {
|
||||
/* Tell MDP server to release all our bindings */
|
||||
overlay_mdp_frame mdp;
|
||||
mdp.packetTypeAndFlags=MDP_GOODBYE;
|
||||
overlay_mdp_send(&mdp,0,0);
|
||||
}
|
||||
|
||||
if (overlay_mdp_client_socket_path_len>-1)
|
||||
unlink(overlay_mdp_client_socket_path);
|
||||
if (mdp_client_socket!=-1)
|
||||
close(mdp_client_socket);
|
||||
mdp_client_socket=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_client_poll(time_ms_t timeout_ms)
|
||||
{
|
||||
fd_set r;
|
||||
int ret;
|
||||
FD_ZERO(&r);
|
||||
FD_SET(mdp_client_socket,&r);
|
||||
if (timeout_ms<0) timeout_ms=0;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
if (timeout_ms>=0) {
|
||||
tv.tv_sec=timeout_ms/1000;
|
||||
tv.tv_usec=(timeout_ms%1000)*1000;
|
||||
ret=select(mdp_client_socket+1,&r,NULL,&r,&tv);
|
||||
}
|
||||
else
|
||||
ret=select(mdp_client_socket+1,&r,NULL,&r,NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl)
|
||||
{
|
||||
char mdp_socket_name[101];
|
||||
unsigned char recvaddrbuffer[1024];
|
||||
struct sockaddr *recvaddr=(struct sockaddr *)recvaddrbuffer;
|
||||
unsigned int recvaddrlen=sizeof(recvaddrbuffer);
|
||||
struct sockaddr_un *recvaddr_un;
|
||||
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(mdp_socket_name, "mdp.socket"))
|
||||
return WHY("Could not find mdp socket");
|
||||
mdp->packetTypeAndFlags=0;
|
||||
|
||||
/* Check if reply available */
|
||||
set_nonblock(mdp_client_socket);
|
||||
ssize_t len = recvwithttl(mdp_client_socket,(unsigned char *)mdp, sizeof(overlay_mdp_frame),ttl,recvaddr,&recvaddrlen);
|
||||
set_block(mdp_client_socket);
|
||||
|
||||
recvaddr_un=(struct sockaddr_un *)recvaddr;
|
||||
/* Null terminate received address so that the stat() call below can succeed */
|
||||
if (recvaddrlen<1024) recvaddrbuffer[recvaddrlen]=0;
|
||||
if (len>0) {
|
||||
/* Make sure recvaddr matches who we sent it to */
|
||||
if (strncmp(mdp_socket_name, recvaddr_un->sun_path, sizeof(recvaddr_un->sun_path))) {
|
||||
/* Okay, reply was PROBABLY not from the server, but on OSX if the path
|
||||
has a symlink in it, it is resolved in the reply path, but might not
|
||||
be in the request path (mdp_socket_name), thus we need to stat() and
|
||||
compare inode numbers etc */
|
||||
struct stat sb1,sb2;
|
||||
if (stat(mdp_socket_name,&sb1)) return WHY("stat(mdp_socket_name) failed, so could not verify that reply came from MDP server");
|
||||
if (stat(recvaddr_un->sun_path,&sb2)) return WHY("stat(ra->sun_path) failed, so could not verify that reply came from MDP server");
|
||||
if ((sb1.st_ino!=sb2.st_ino)||(sb1.st_dev!=sb2.st_dev))
|
||||
return WHY("Reply did not come from server");
|
||||
}
|
||||
|
||||
int expected_len = overlay_mdp_relevant_bytes(mdp);
|
||||
|
||||
if (len < expected_len){
|
||||
return WHYF("Expected packet length of %d, received only %lld bytes", expected_len, (long long) len);
|
||||
}
|
||||
/* Valid packet received */
|
||||
return 0;
|
||||
} else
|
||||
/* no packet received */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
// send a request to servald deamon to add a port binding
|
||||
int overlay_mdp_bind(unsigned char *localaddr,int port)
|
||||
{
|
||||
overlay_mdp_frame mdp;
|
||||
mdp.packetTypeAndFlags=MDP_BIND|MDP_FORCE;
|
||||
bcopy(localaddr,mdp.bind.sid,SID_SIZE);
|
||||
mdp.bind.port_number=port;
|
||||
int result=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
|
||||
if (result) {
|
||||
if (mdp.packetTypeAndFlags==MDP_ERROR)
|
||||
WHYF("Could not bind to MDP port %d: error=%d, message='%s'",
|
||||
port,mdp.error.error,mdp.error.message);
|
||||
else
|
||||
WHYF("Could not bind to MDP port %d (no reason given)",port);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_getmyaddr(int index,unsigned char *sid)
|
||||
{
|
||||
overlay_mdp_frame a;
|
||||
memset(&a, 0, sizeof(a));
|
||||
|
||||
a.packetTypeAndFlags=MDP_GETADDRS;
|
||||
a.addrlist.mode = MDP_ADDRLIST_MODE_SELF;
|
||||
a.addrlist.first_sid=index;
|
||||
a.addrlist.last_sid=0x7fffffff;
|
||||
a.addrlist.frame_sid_count=MDP_MAX_SID_REQUEST;
|
||||
int result=overlay_mdp_send(&a,MDP_AWAITREPLY,5000);
|
||||
if (result) {
|
||||
if (a.packetTypeAndFlags == MDP_ERROR)
|
||||
DEBUGF("MDP Server error #%d: '%s'", a.error.error, a.error.message);
|
||||
return WHY("Failed to get local address list");
|
||||
}
|
||||
if ((a.packetTypeAndFlags&MDP_TYPE_MASK)!=MDP_ADDRLIST)
|
||||
return WHY("MDP Server returned something other than an address list");
|
||||
if (0) DEBUGF("local addr 0 = %s",alloca_tohex_sid(a.addrlist.sids[0]));
|
||||
bcopy(&a.addrlist.sids[0][0],sid,SID_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp)
|
||||
{
|
||||
int len=4;
|
||||
switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK)
|
||||
{
|
||||
case MDP_GOODBYE:
|
||||
/* no arguments for saying goodbye */
|
||||
break;
|
||||
case MDP_ADDRLIST:
|
||||
len=&mdp->addrlist.sids[0][0]-(unsigned char *)mdp;
|
||||
len+=mdp->addrlist.frame_sid_count*SID_SIZE;
|
||||
break;
|
||||
case MDP_GETADDRS:
|
||||
len=&mdp->addrlist.sids[0][0]-(unsigned char *)mdp;
|
||||
break;
|
||||
case MDP_TX:
|
||||
len=&mdp->out.payload[0]-(unsigned char *)mdp;
|
||||
len+=mdp->out.payload_length;
|
||||
break;
|
||||
case MDP_BIND:
|
||||
len=&mdp->bind.sid[SID_SIZE]-(unsigned char *)mdp;
|
||||
break;
|
||||
case MDP_ERROR:
|
||||
/* This formulation is used so that we don't copy any bytes after the
|
||||
end of the string, to avoid information leaks */
|
||||
len=&mdp->error.message[0]-(char *)mdp;
|
||||
len+=strlen(mdp->error.message)+1;
|
||||
if (mdp->error.error) INFOF("mdp return/error code: %d:%s",mdp->error.error,mdp->error.message);
|
||||
break;
|
||||
case MDP_NODEINFO:
|
||||
/* XXX problems with calculating this due to structure padding,
|
||||
so doubled required space, and now it works. */
|
||||
len=sizeof(overlay_mdp_nodeinfo)*2;
|
||||
break;
|
||||
default:
|
||||
return WHY("Illegal MDP frame type.");
|
||||
}
|
||||
return len;
|
||||
}
|
33
mdp_client.h
Normal file
33
mdp_client.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 2012 Serval Project.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SERVALD_MDP_CLIENT_H
|
||||
#define __SERVALD_MDP_CLIENT_H
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
/* Client-side MDP function */
|
||||
extern int mdp_client_socket;
|
||||
int overlay_mdp_client_init();
|
||||
int overlay_mdp_client_done();
|
||||
int overlay_mdp_client_poll(time_ms_t timeout_ms);
|
||||
int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl);
|
||||
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms);
|
||||
int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp);
|
||||
|
||||
#endif
|
@ -16,6 +16,9 @@ along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SERVALD_MONITOR_CLIENT_H
|
||||
#define __SERVALD_MONITOR_CLIENT_H
|
||||
|
||||
struct monitor_state;
|
||||
|
||||
struct monitor_command_handler{
|
||||
@ -29,3 +32,5 @@ int monitor_client_writeline(int fd,char *fmt, ...);
|
||||
int monitor_client_writeline_and_data(int fd,unsigned char *data,int bytes,char *fmt,...);
|
||||
int monitor_client_read(int fd, struct monitor_state *res, struct monitor_command_handler *handlers, int handler_count);
|
||||
int monitor_client_close(int fd, struct monitor_state *res);
|
||||
|
||||
#endif
|
97
net.c
97
net.c
@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include "net.h"
|
||||
|
||||
int _set_nonblock(int fd, struct __sourceloc where)
|
||||
@ -124,3 +126,98 @@ ssize_t _write_str_nonblock(int fd, const char *str, struct __sourceloc where)
|
||||
{
|
||||
return _write_all_nonblock(fd, str, strlen(str), where);
|
||||
}
|
||||
|
||||
ssize_t recvwithttl(int sock,unsigned char *buffer, size_t bufferlen,int *ttl,
|
||||
struct sockaddr *recvaddr, socklen_t *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;
|
||||
|
||||
ssize_t len = recvmsg(sock,&msg,0);
|
||||
if (len == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
return WHY_perror("recvmsg");
|
||||
|
||||
if (0&&debug&DEBUG_PACKETRX) {
|
||||
DEBUGF("recvmsg returned %lld (flags=%d, msg_controllen=%d)", (long long) len, msg.msg_flags, msg.msg_controllen);
|
||||
dump("received data", buffer, len);
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg;
|
||||
if (len>0)
|
||||
{
|
||||
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_type == IP_TTL))
|
||||
&&(cmsg->cmsg_len) ){
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
DEBUGF(" TTL (%p) data location resolves to %p", ttl,CMSG_DATA(cmsg));
|
||||
if (CMSG_DATA(cmsg)) {
|
||||
*ttl = *(unsigned char *) CMSG_DATA(cmsg);
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
DEBUGF(" TTL of packet is %d", *ttl);
|
||||
}
|
||||
} else {
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
DEBUGF("I didn't expect to see level=%02x, type=%02x",
|
||||
cmsg->cmsg_level,cmsg->cmsg_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
*recvaddrlen=msg.msg_namelen;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int urandombytes(unsigned char *x, unsigned long long xlen)
|
||||
{
|
||||
static int urandomfd = -1;
|
||||
int tries = 0;
|
||||
if (urandomfd == -1) {
|
||||
for (tries = 0; tries < 4; ++tries) {
|
||||
urandomfd = open("/dev/urandom",O_RDONLY);
|
||||
if (urandomfd != -1) break;
|
||||
sleep(1);
|
||||
}
|
||||
if (urandomfd == -1) {
|
||||
WHY_perror("open(/dev/urandom)");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
tries = 0;
|
||||
while (xlen > 0) {
|
||||
int i = (xlen < 1048576) ? xlen : 1048576;
|
||||
i = read(urandomfd, x, i);
|
||||
if (i == -1) {
|
||||
if (++tries > 4) {
|
||||
WHY_perror("read(/dev/urandom)");
|
||||
return -1;
|
||||
}
|
||||
sleep(1);
|
||||
} else {
|
||||
tries = 0;
|
||||
x += i;
|
||||
xlen -= i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
276
overlay_mdp.c
276
overlay_mdp.c
@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "overlay_buffer.h"
|
||||
#include "overlay_address.h"
|
||||
#include "overlay_packet.h"
|
||||
#include "mdp_client.h"
|
||||
|
||||
struct profile_total mdp_stats={.name="overlay_mdp_poll"};
|
||||
|
||||
@ -1116,278 +1117,3 @@ void overlay_mdp_poll(struct sched_ent *alarm)
|
||||
return;
|
||||
}
|
||||
|
||||
int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp)
|
||||
{
|
||||
int len=4;
|
||||
switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK)
|
||||
{
|
||||
case MDP_GOODBYE:
|
||||
/* no arguments for saying goodbye */
|
||||
break;
|
||||
case MDP_ADDRLIST:
|
||||
len=&mdp->addrlist.sids[0][0]-(unsigned char *)mdp;
|
||||
len+=mdp->addrlist.frame_sid_count*SID_SIZE;
|
||||
break;
|
||||
case MDP_GETADDRS:
|
||||
len=&mdp->addrlist.sids[0][0]-(unsigned char *)mdp;
|
||||
break;
|
||||
case MDP_TX:
|
||||
len=&mdp->out.payload[0]-(unsigned char *)mdp;
|
||||
len+=mdp->out.payload_length;
|
||||
break;
|
||||
case MDP_BIND:
|
||||
len=&mdp->bind.sid[SID_SIZE]-(unsigned char *)mdp;
|
||||
break;
|
||||
case MDP_ERROR:
|
||||
/* This formulation is used so that we don't copy any bytes after the
|
||||
end of the string, to avoid information leaks */
|
||||
len=&mdp->error.message[0]-(char *)mdp;
|
||||
len+=strlen(mdp->error.message)+1;
|
||||
if (mdp->error.error) INFOF("mdp return/error code: %d:%s",mdp->error.error,mdp->error.message);
|
||||
break;
|
||||
case MDP_NODEINFO:
|
||||
/* XXX problems with calculating this due to structure padding,
|
||||
so doubled required space, and now it works. */
|
||||
len=sizeof(overlay_mdp_nodeinfo)*2;
|
||||
break;
|
||||
default:
|
||||
return WHY("Illegal MDP frame type.");
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int mdp_client_socket=-1;
|
||||
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
|
||||
{
|
||||
int len=4;
|
||||
|
||||
if (mdp_client_socket==-1)
|
||||
if (overlay_mdp_client_init() != 0)
|
||||
return -1;
|
||||
|
||||
/* Minimise frame length to save work and prevent accidental disclosure of
|
||||
memory contents. */
|
||||
len=overlay_mdp_relevant_bytes(mdp);
|
||||
if (len<0) return WHY("MDP frame invalid (could not compute length)");
|
||||
|
||||
/* Construct name of socket to send to. */
|
||||
struct sockaddr_un name;
|
||||
name.sun_family = AF_UNIX;
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(name.sun_path, "mdp.socket"))
|
||||
return -1;
|
||||
|
||||
set_nonblock(mdp_client_socket);
|
||||
int result=sendto(mdp_client_socket, mdp, len, 0,
|
||||
(struct sockaddr *)&name, sizeof(struct sockaddr_un));
|
||||
set_block(mdp_client_socket);
|
||||
if (result<0) {
|
||||
mdp->packetTypeAndFlags=MDP_ERROR;
|
||||
mdp->error.error=1;
|
||||
snprintf(mdp->error.message,128,"Error sending frame to MDP server.");
|
||||
return WHY_perror("sendto(f)");
|
||||
} else {
|
||||
if (!(flags&MDP_AWAITREPLY)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay_mdp_client_poll(timeout_ms)<=0){
|
||||
/* Timeout */
|
||||
mdp->packetTypeAndFlags=MDP_ERROR;
|
||||
mdp->error.error=1;
|
||||
snprintf(mdp->error.message,128,"Timeout waiting for reply to MDP packet (packet was successfully sent).");
|
||||
return -1; /* WHY("Timeout waiting for server response"); */
|
||||
}
|
||||
|
||||
int ttl=-1;
|
||||
if (!overlay_mdp_recv(mdp,&ttl)) {
|
||||
/* If all is well, examine result and return error code provided */
|
||||
if ((mdp->packetTypeAndFlags&MDP_TYPE_MASK)==MDP_ERROR)
|
||||
return mdp->error.error;
|
||||
else
|
||||
/* Something other than an error has been returned */
|
||||
return 0;
|
||||
} else {
|
||||
/* poll() said that there was data, but there isn't.
|
||||
So we will abort. */
|
||||
return WHY("poll() aborted");
|
||||
}
|
||||
}
|
||||
|
||||
char overlay_mdp_client_socket_path[1024];
|
||||
int overlay_mdp_client_socket_path_len=-1;
|
||||
|
||||
int overlay_mdp_client_init()
|
||||
{
|
||||
if (mdp_client_socket==-1) {
|
||||
/* Open socket to MDP server (thus connection is always local) */
|
||||
if (0) WHY("Use of abstract name space socket for Linux not implemented");
|
||||
|
||||
mdp_client_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (mdp_client_socket < 0) {
|
||||
WHY_perror("socket");
|
||||
return WHY("Could not open socket to MDP server");
|
||||
}
|
||||
|
||||
/* We must bind to a temporary file name */
|
||||
struct sockaddr_un name;
|
||||
unsigned int random_value;
|
||||
if (urandombytes((unsigned char *)&random_value,sizeof(int)))
|
||||
return WHY("urandombytes() failed");
|
||||
name.sun_family = AF_UNIX;
|
||||
if (overlay_mdp_client_socket_path_len==-1) {
|
||||
char fmt[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(fmt, "mdp-client-%d-%08x.socket"))
|
||||
return WHY("Could not form MDP client socket name");
|
||||
snprintf(overlay_mdp_client_socket_path,1024,fmt,getpid(),random_value);
|
||||
overlay_mdp_client_socket_path_len=strlen(overlay_mdp_client_socket_path)+1;
|
||||
if(debug&DEBUG_IO) DEBUGF("MDP client socket name='%s'",overlay_mdp_client_socket_path);
|
||||
}
|
||||
if (overlay_mdp_client_socket_path_len > 104 - 1)
|
||||
FATALF("MDP socket path too long (%d > %d)", overlay_mdp_client_socket_path_len, 104 - 1);
|
||||
|
||||
bcopy(overlay_mdp_client_socket_path,name.sun_path,
|
||||
overlay_mdp_client_socket_path_len);
|
||||
unlink(name.sun_path);
|
||||
int len = 1 + strlen(name.sun_path) + sizeof(name.sun_family) + 1;
|
||||
int r=bind(mdp_client_socket, (struct sockaddr *)&name, len);
|
||||
if (r) {
|
||||
WHY_perror("bind");
|
||||
return WHY("Could not bind MDP client socket to file name");
|
||||
}
|
||||
|
||||
int send_buffer_size=128*1024;
|
||||
if (setsockopt(mdp_client_socket, SOL_SOCKET, SO_RCVBUF,
|
||||
&send_buffer_size, sizeof(send_buffer_size)) == -1)
|
||||
WARN_perror("setsockopt");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_client_done()
|
||||
{
|
||||
if (mdp_client_socket!=-1) {
|
||||
/* Tell MDP server to release all our bindings */
|
||||
overlay_mdp_frame mdp;
|
||||
mdp.packetTypeAndFlags=MDP_GOODBYE;
|
||||
overlay_mdp_send(&mdp,0,0);
|
||||
}
|
||||
|
||||
if (overlay_mdp_client_socket_path_len>-1)
|
||||
unlink(overlay_mdp_client_socket_path);
|
||||
if (mdp_client_socket!=-1)
|
||||
close(mdp_client_socket);
|
||||
mdp_client_socket=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_client_poll(time_ms_t timeout_ms)
|
||||
{
|
||||
fd_set r;
|
||||
int ret;
|
||||
IN();
|
||||
FD_ZERO(&r);
|
||||
FD_SET(mdp_client_socket,&r);
|
||||
if (timeout_ms<0) timeout_ms=0;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
if (timeout_ms>=0) {
|
||||
tv.tv_sec=timeout_ms/1000;
|
||||
tv.tv_usec=(timeout_ms%1000)*1000;
|
||||
ret=select(mdp_client_socket+1,&r,NULL,&r,&tv);
|
||||
}
|
||||
else
|
||||
ret=select(mdp_client_socket+1,&r,NULL,&r,NULL);
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl)
|
||||
{
|
||||
char mdp_socket_name[101];
|
||||
unsigned char recvaddrbuffer[1024];
|
||||
struct sockaddr *recvaddr=(struct sockaddr *)recvaddrbuffer;
|
||||
unsigned int recvaddrlen=sizeof(recvaddrbuffer);
|
||||
struct sockaddr_un *recvaddr_un;
|
||||
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(mdp_socket_name, "mdp.socket"))
|
||||
return WHY("Could not find mdp socket");
|
||||
mdp->packetTypeAndFlags=0;
|
||||
|
||||
/* Check if reply available */
|
||||
set_nonblock(mdp_client_socket);
|
||||
ssize_t len = recvwithttl(mdp_client_socket,(unsigned char *)mdp, sizeof(overlay_mdp_frame),ttl,recvaddr,&recvaddrlen);
|
||||
set_block(mdp_client_socket);
|
||||
|
||||
recvaddr_un=(struct sockaddr_un *)recvaddr;
|
||||
/* Null terminate received address so that the stat() call below can succeed */
|
||||
if (recvaddrlen<1024) recvaddrbuffer[recvaddrlen]=0;
|
||||
if (len>0) {
|
||||
/* Make sure recvaddr matches who we sent it to */
|
||||
if (strncmp(mdp_socket_name, recvaddr_un->sun_path, sizeof(recvaddr_un->sun_path))) {
|
||||
/* Okay, reply was PROBABLY not from the server, but on OSX if the path
|
||||
has a symlink in it, it is resolved in the reply path, but might not
|
||||
be in the request path (mdp_socket_name), thus we need to stat() and
|
||||
compare inode numbers etc */
|
||||
struct stat sb1,sb2;
|
||||
if (stat(mdp_socket_name,&sb1)) return WHY("stat(mdp_socket_name) failed, so could not verify that reply came from MDP server");
|
||||
if (stat(recvaddr_un->sun_path,&sb2)) return WHY("stat(ra->sun_path) failed, so could not verify that reply came from MDP server");
|
||||
if ((sb1.st_ino!=sb2.st_ino)||(sb1.st_dev!=sb2.st_dev))
|
||||
return WHY("Reply did not come from server");
|
||||
}
|
||||
|
||||
int expected_len = overlay_mdp_relevant_bytes(mdp);
|
||||
|
||||
if (len < expected_len){
|
||||
return WHYF("Expected packet length of %d, received only %lld bytes", expected_len, (long long) len);
|
||||
}
|
||||
/* Valid packet received */
|
||||
return 0;
|
||||
} else
|
||||
/* no packet received */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int overlay_mdp_bind(unsigned char *localaddr,int port)
|
||||
{
|
||||
overlay_mdp_frame mdp;
|
||||
mdp.packetTypeAndFlags=MDP_BIND|MDP_FORCE;
|
||||
bcopy(localaddr,mdp.bind.sid,SID_SIZE);
|
||||
mdp.bind.port_number=port;
|
||||
int result=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
|
||||
if (result) {
|
||||
if (mdp.packetTypeAndFlags==MDP_ERROR)
|
||||
WHYF("Could not bind to MDP port %d: error=%d, message='%s'",
|
||||
port,mdp.error.error,mdp.error.message);
|
||||
else
|
||||
WHYF("Could not bind to MDP port %d (no reason given)",port);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_mdp_getmyaddr(int index,unsigned char *sid)
|
||||
{
|
||||
overlay_mdp_frame a;
|
||||
memset(&a, 0, sizeof(a));
|
||||
|
||||
a.packetTypeAndFlags=MDP_GETADDRS;
|
||||
a.addrlist.mode = MDP_ADDRLIST_MODE_SELF;
|
||||
a.addrlist.first_sid=index;
|
||||
a.addrlist.last_sid=0x7fffffff;
|
||||
a.addrlist.frame_sid_count=MDP_MAX_SID_REQUEST;
|
||||
int result=overlay_mdp_send(&a,MDP_AWAITREPLY,5000);
|
||||
if (result) {
|
||||
if (a.packetTypeAndFlags == MDP_ERROR)
|
||||
DEBUGF("MDP Server error #%d: '%s'", a.error.error, a.error.message);
|
||||
return WHY("Failed to get local address list");
|
||||
}
|
||||
if ((a.packetTypeAndFlags&MDP_TYPE_MASK)!=MDP_ADDRLIST)
|
||||
return WHY("MDP Server returned something other than an address list");
|
||||
if (0) DEBUGF("local addr 0 = %s",alloca_tohex_sid(a.addrlist.sids[0]));
|
||||
bcopy(&a.addrlist.sids[0][0],sid,SID_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
9
serval.h
9
serval.h
@ -799,20 +799,11 @@ typedef struct overlay_mdp_frame {
|
||||
|
||||
int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req);
|
||||
|
||||
/* Client-side MDP function */
|
||||
extern int mdp_client_socket;
|
||||
int overlay_mdp_client_init();
|
||||
int overlay_mdp_client_done();
|
||||
int overlay_mdp_client_poll(time_ms_t timeout_ms);
|
||||
int overlay_mdp_recv(overlay_mdp_frame *mdp,int *ttl);
|
||||
int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms);
|
||||
|
||||
/* Server-side MDP functions */
|
||||
int overlay_saw_mdp_frame(overlay_mdp_frame *mdp, time_ms_t now);
|
||||
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp);
|
||||
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,int userGeneratedFrameP,
|
||||
struct sockaddr_un *recvaddr,int recvaddlen);
|
||||
int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const unsigned char *resolved_sid, const char *uri, const char *did, const char *name);
|
||||
|
69
server.c
69
server.c
@ -52,66 +52,6 @@ void crash_handler(int signal);
|
||||
int getKeyring(char *s);
|
||||
int createServerSocket();
|
||||
|
||||
ssize_t recvwithttl(int sock,unsigned char *buffer, size_t bufferlen,int *ttl,
|
||||
struct sockaddr *recvaddr, socklen_t *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;
|
||||
|
||||
ssize_t len = recvmsg(sock,&msg,0);
|
||||
if (len == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
return WHY_perror("recvmsg");
|
||||
|
||||
if (0&&debug&DEBUG_PACKETRX) {
|
||||
DEBUGF("recvmsg returned %lld (flags=%d, msg_controllen=%d)", (long long) len, msg.msg_flags, msg.msg_controllen);
|
||||
dump("received data", buffer, len);
|
||||
}
|
||||
|
||||
struct cmsghdr *cmsg;
|
||||
if (len>0)
|
||||
{
|
||||
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_type == IP_TTL))
|
||||
&&(cmsg->cmsg_len) ){
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
DEBUGF(" TTL (%p) data location resolves to %p", ttl,CMSG_DATA(cmsg));
|
||||
if (CMSG_DATA(cmsg)) {
|
||||
*ttl = *(unsigned char *) CMSG_DATA(cmsg);
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
DEBUGF(" TTL of packet is %d", *ttl);
|
||||
}
|
||||
} else {
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
DEBUGF("I didn't expect to see level=%02x, type=%02x",
|
||||
cmsg->cmsg_level,cmsg->cmsg_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
*recvaddrlen=msg.msg_namelen;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
time_ms_t gettime_ms()
|
||||
{
|
||||
struct timeval nowtv;
|
||||
@ -321,12 +261,9 @@ void serverCleanUp()
|
||||
char filename[1024];
|
||||
if (FORM_SERVAL_INSTANCE_PATH(filename, PIDFILE_NAME))
|
||||
unlink(filename);
|
||||
if (mdp_client_socket==-1) {
|
||||
if (FORM_SERVAL_INSTANCE_PATH(filename, "mdp.socket")) {
|
||||
unlink(filename);
|
||||
}
|
||||
} else {
|
||||
overlay_mdp_client_done();
|
||||
|
||||
if (FORM_SERVAL_INSTANCE_PATH(filename, "mdp.socket")) {
|
||||
unlink(filename);
|
||||
}
|
||||
dna_helper_shutdown();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user