From 6483d9e0ae1af58f3717577cca570439281812eb Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Fri, 14 Sep 2012 11:47:48 +0930 Subject: [PATCH] Split client mdp functions so they can be built separately --- Android.mk | 1 + Makefile.in | 12 ++ commandline.c | 1 + keyring.c | 35 ------ mdp_client.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++ mdp_client.h | 33 ++++++ monitor-client.h | 5 + net.c | 97 +++++++++++++++ overlay_mdp.c | 276 +------------------------------------------ serval.h | 9 -- server.c | 69 +---------- 11 files changed, 453 insertions(+), 385 deletions(-) mode change 100755 => 100644 Makefile.in create mode 100644 mdp_client.c create mode 100644 mdp_client.h diff --git a/Android.mk b/Android.mk index 6da7ae71..f829caef 100644 --- a/Android.mk +++ b/Android.mk @@ -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 \ diff --git a/Makefile.in b/Makefile.in old mode 100755 new mode 100644 index bca8b29c..23d0e45b --- a/Makefile.in +++ b/Makefile.in @@ -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@ diff --git a/commandline.c b/commandline.c index 0608fa6e..385eb391 100644 --- a/commandline.c +++ b/commandline.c @@ -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 .\n"); diff --git a/keyring.c b/keyring.c index 04043d30..b3aef6ef 100644 --- a/keyring.c +++ b/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. */ diff --git a/mdp_client.c b/mdp_client.c new file mode 100644 index 00000000..969010f2 --- /dev/null +++ b/mdp_client.c @@ -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 +#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; +} diff --git a/mdp_client.h b/mdp_client.h new file mode 100644 index 00000000..4d743c80 --- /dev/null +++ b/mdp_client.h @@ -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 \ No newline at end of file diff --git a/monitor-client.h b/monitor-client.h index 2e9601fe..f7bb602d 100644 --- a/monitor-client.h +++ b/monitor-client.h @@ -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 \ No newline at end of file diff --git a/net.c b/net.c index bca4d3c7..24b5fb81 100644 --- a/net.c +++ b/net.c @@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include +#include +#include #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; +} + diff --git a/overlay_mdp.c b/overlay_mdp.c index e5dea9d6..13fde0ea 100644 --- a/overlay_mdp.c +++ b/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; -} - diff --git a/serval.h b/serval.h index 054c76d2..5d703923 100644 --- a/serval.h +++ b/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); diff --git a/server.c b/server.c index 23c8fef1..f80664b1 100644 --- a/server.c +++ b/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(); }