Split client mdp functions so they can be built separately

This commit is contained in:
Jeremy Lakeman 2012-09-14 11:47:48 +09:30
parent a73b9ee7f7
commit 6483d9e0ae
11 changed files with 453 additions and 385 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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