Refactor socket name and address length handling

This commit is contained in:
Jeremy Lakeman 2013-11-25 12:15:20 +10:30
parent 5ea19ab538
commit 0d5d878521
20 changed files with 874 additions and 541 deletions

View File

@ -931,9 +931,6 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
int64_t interval_ms = 1000; int64_t interval_ms = 1000;
str_to_uint64_interval_ms(opt_interval, &interval_ms, NULL); str_to_uint64_interval_ms(opt_interval, &interval_ms, NULL);
overlay_mdp_frame mdp;
bzero(&mdp, sizeof(overlay_mdp_frame));
/* First sequence number in the echo frames */ /* First sequence number in the echo frames */
unsigned int firstSeq=random(); unsigned int firstSeq=random();
unsigned int sequence_number=firstSeq; unsigned int sequence_number=firstSeq;
@ -941,22 +938,23 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
int broadcast = is_sid_t_broadcast(ping_sid); int broadcast = is_sid_t_broadcast(ping_sid);
/* Bind to MDP socket and await confirmation */ /* Bind to MDP socket and await confirmation */
if ((mdp_sockfd = overlay_mdp_client_socket()) < 0) if ((mdp_sockfd = mdp_socket()) < 0)
return WHY("Cannot create MDP socket"); return WHY("Cannot create MDP socket");
sid_t srcsid; struct mdp_header mdp_header;
mdp_port_t port=32768+(random()&32767); bzero(&mdp_header, sizeof(mdp_header));
if (overlay_mdp_getmyaddr(mdp_sockfd, 0, &srcsid)) {
overlay_mdp_client_close(mdp_sockfd); mdp_header.local.sid = BIND_PRIMARY;
return WHY("Could not get local address"); mdp_header.remote.sid = ping_sid;
} mdp_header.remote.port = MDP_PORT_ECHO;
if (overlay_mdp_bind(mdp_sockfd, &srcsid, port)) { mdp_header.qos = OQ_MESH_MANAGEMENT;
overlay_mdp_client_close(mdp_sockfd); mdp_header.ttl = PAYLOAD_TTL_DEFAULT;
return WHY("Could not bind to MDP socket"); mdp_header.flags = MDP_FLAG_BIND;
} if (broadcast)
mdp_header.flags |= MDP_FLAG_NO_CRYPT;
/* TODO Eventually we should try to resolve SID to phone number and vice versa */ /* TODO Eventually we should try to resolve SID to phone number and vice versa */
cli_printf(context, "MDP PING %s (%s): 12 data bytes", alloca_tohex_sid_t(ping_sid), alloca_tohex_sid_t(ping_sid)); cli_printf(context, "MDP PING %s: 12 data bytes", alloca_tohex_sid_t(ping_sid));
cli_delim(context, "\n"); cli_delim(context, "\n");
cli_flush(context); cli_flush(context);
@ -968,31 +966,22 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
if (broadcast) if (broadcast)
WARN("broadcast ping packets will not be encrypted"); WARN("broadcast ping packets will not be encrypted");
for (; icount==0 || tx_count<icount; ++sequence_number) {
/* Now send the ping packets */
mdp.packetTypeAndFlags=MDP_TX;
if (broadcast) mdp.packetTypeAndFlags|=MDP_NOCRYPT;
mdp.out.src.port=port;
mdp.out.src.sid = srcsid;
mdp.out.dst.sid = ping_sid;
mdp.out.queue=OQ_MESH_MANAGEMENT;
/* Set port to well known echo port */
mdp.out.dst.port=MDP_PORT_ECHO;
mdp.out.payload_length=4+8;
int *seq=(int *)&mdp.out.payload;
*seq=sequence_number;
write_uint64(&mdp.out.payload[4], gettime_ms());
int res=overlay_mdp_send(mdp_sockfd, &mdp, 0, 0); for (; icount==0 || tx_count<icount; ++sequence_number) {
if (res) {
WHYF("could not dispatch PING frame #%d (error %d)%s%s", // send a ping packet
sequence_number - firstSeq, {
res, uint8_t payload[12];
mdp.packetTypeAndFlags == MDP_ERROR ? ": " : "", int *seq=(int *)payload;
mdp.packetTypeAndFlags == MDP_ERROR ? mdp.error.message : "" *seq=sequence_number;
); write_uint64(&payload[4], gettime_ms());
} else
int r = mdp_send(mdp_sockfd, &mdp_header, payload, sizeof(payload));
if (r<0)
WHY_perror("mdp_send");
else
tx_count++; tx_count++;
}
/* Now look for replies until one second has passed, and print any replies /* Now look for replies until one second has passed, and print any replies
with appropriate information as required */ with appropriate information as required */
@ -1000,29 +989,56 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
time_ms_t finish = now + (tx_count < icount?interval_ms:timeout_ms); time_ms_t finish = now + (tx_count < icount?interval_ms:timeout_ms);
for (; !servalShutdown && now < finish; now = gettime_ms()) { for (; !servalShutdown && now < finish; now = gettime_ms()) {
time_ms_t poll_timeout_ms = finish - gettime_ms(); time_ms_t poll_timeout_ms = finish - gettime_ms();
int result = overlay_mdp_client_poll(mdp_sockfd, poll_timeout_ms);
if (result>0) { if (mdp_poll(mdp_sockfd, poll_timeout_ms)<=0)
int ttl=-1; continue;
if (overlay_mdp_recv(mdp_sockfd, &mdp, port, &ttl)==0) {
switch(mdp.packetTypeAndFlags&MDP_TYPE_MASK) { struct mdp_header mdp_recv_header;
case MDP_ERROR: uint8_t recv_payload[12];
WHYF("mdpping: overlay_mdp_recv: %s (code %d)", mdp.error.message, mdp.error.error); ssize_t len = mdp_recv(mdp_sockfd, &mdp_recv_header, recv_payload, sizeof(recv_payload));
if (len<0){
WHY_perror("mdp_recv");
break; break;
case MDP_TX: }
{
int *rxseq=(int *)&mdp.in.payload; if (mdp_recv_header.flags & MDP_FLAG_ERROR){
time_ms_t txtime = read_uint64(&mdp.in.payload[4]); WHY("Serval daemon reported an error, please check the log for more information");
int hop_count = 64 - mdp.in.ttl; break;
}
if (mdp_recv_header.flags & MDP_FLAG_BIND){
// received port binding confirmation
mdp_header.local = mdp_recv_header.local;
mdp_header.flags &= ~MDP_FLAG_BIND;
DEBUGF("Bound to %s:%d", alloca_tohex_sid_t(mdp_header.local.sid), mdp_header.local.port);
continue;
}
if (len<sizeof(recv_payload)){
DEBUGF("Ignoring ping response as it is too short");
continue;
}
int *rxseq=(int *)&recv_payload;
time_ms_t txtime = read_uint64(&recv_payload[4]);
int hop_count = 64 - mdp_recv_header.ttl;
time_ms_t delay = gettime_ms() - txtime; time_ms_t delay = gettime_ms() - txtime;
cli_printf(context, "%s: seq=%d time=%"PRId64"ms hops=%d %s%s",
alloca_tohex_sid_t(mdp.in.src.sid), cli_put_hexvalue(context, mdp_recv_header.remote.sid.binary, SID_SIZE, ": seq=");
(*rxseq)-firstSeq+1, cli_put_long(context, (*rxseq)-firstSeq+1, " time=");
(int64_t)delay, cli_put_long(context, delay, "ms hops=");
hop_count, cli_put_long(context, hop_count, "");
mdp.packetTypeAndFlags&MDP_NOCRYPT?"":" ENCRYPTED",
mdp.packetTypeAndFlags&MDP_NOSIGN?"":" SIGNED"); if (mdp_recv_header.flags&MDP_FLAG_NO_CRYPT)
cli_delim(context, "\n"); cli_put_string(context, "", "");
else
cli_put_string(context, " ENCRYPTED", "");
if (mdp_recv_header.flags&MDP_FLAG_NO_SIGN)
cli_put_string(context, "", "\n");
else
cli_put_string(context, " SIGNED", "\n");
cli_flush(context); cli_flush(context);
// TODO Put duplicate pong detection here so that stats work properly. // TODO Put duplicate pong detection here so that stats work properly.
rx_count++; rx_count++;
@ -1032,17 +1048,9 @@ int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
if (delay>rx_maxtime) rx_maxtime=delay; if (delay>rx_maxtime) rx_maxtime=delay;
rx_times[rx_count%1024]=delay; rx_times[rx_count%1024]=delay;
} }
break;
default:
WHYF("mdpping: overlay_mdp_recv: Unexpected MDP frame type 0x%x", mdp.packetTypeAndFlags);
break;
}
}
}
}
} }
overlay_mdp_client_close(mdp_sockfd); mdp_close(mdp_sockfd);
{ {
float rx_stddev=0; float rx_stddev=0;
@ -2264,7 +2272,7 @@ static int handle_pins(const struct cli_parsed *parsed, struct cli_context *cont
WHYF("Timeout while waiting for response"); WHYF("Timeout while waiting for response");
break; break;
} }
if (rev_header.flags & MDP_FLAG_OK){ if (rev_header.flags & MDP_FLAG_CLOSE){
ret=0; ret=0;
break; break;
} }
@ -2334,7 +2342,7 @@ int app_id_list(const struct cli_parsed *parsed, struct cli_context *context)
// TODO receive and decode other details about this identity // TODO receive and decode other details about this identity
} }
if (rev_header.flags & MDP_FLAG_OK){ if (rev_header.flags & MDP_FLAG_CLOSE){
ret=0; ret=0;
break; break;
} }

View File

@ -52,7 +52,7 @@ static void directory_send(struct subscriber *directory_service, const sid_t *si
// Used by tests // Used by tests
INFOF("Sending directory registration for %s*, %s, %s to %s*", INFOF("Sending directory registration for %s*, %s, %s to %s*",
alloca_tohex_sid_t_trunc(*sidp, 14), did, name, alloca_tohex_sid_t_trunc(directory_service->sid, 14)); alloca_tohex_sid_t_trunc(*sidp, 14), did, name, alloca_tohex_sid_t_trunc(directory_service->sid, 14));
overlay_mdp_dispatch(&request, 0, NULL, 0); overlay_mdp_dispatch(&request, NULL);
} }
// send a registration packet for each unlocked identity // send a registration packet for each unlocked identity

View File

@ -6,6 +6,7 @@ HDRS= fifo.h \
rhizome.h \ rhizome.h \
serval.h \ serval.h \
keyring.h \ keyring.h \
socket.h \
cli.h \ cli.h \
str.h \ str.h \
rotbuf.h \ rotbuf.h \

View File

@ -1764,7 +1764,7 @@ static int keyring_respond_sas(keyring_file *k, overlay_mdp_frame *req)
alloca_tohex_sid_t(req->out.src.sid), req->out.src.port, alloca_tohex_sid_t(req->out.src.sid), req->out.src.port,
alloca_tohex_sid_t(req->out.dst.sid), req->out.dst.port alloca_tohex_sid_t(req->out.dst.sid), req->out.dst.port
); );
return overlay_mdp_dispatch(req,0,NULL,0); return overlay_mdp_dispatch(req, NULL);
} }
// someone else is claiming to be me on this network // someone else is claiming to be me on this network
@ -1790,7 +1790,7 @@ int keyring_send_unlock(struct subscriber *subscriber)
if (crypto_sign_message(subscriber, mdp.out.payload, sizeof(mdp.out.payload), &len)) if (crypto_sign_message(subscriber, mdp.out.payload, sizeof(mdp.out.payload), &len))
return -1; return -1;
mdp.out.payload_length=len; mdp.out.payload_length=len;
return overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0); return overlay_mdp_dispatch(&mdp, NULL);
} }
static int keyring_send_challenge(struct subscriber *source, struct subscriber *dest) static int keyring_send_challenge(struct subscriber *source, struct subscriber *dest)
@ -1815,7 +1815,7 @@ static int keyring_send_challenge(struct subscriber *source, struct subscriber *
bcopy(source->identity->challenge, &mdp.out.payload[1], sizeof(source->identity->challenge)); bcopy(source->identity->challenge, &mdp.out.payload[1], sizeof(source->identity->challenge));
mdp.out.payload_length+=sizeof(source->identity->challenge); mdp.out.payload_length+=sizeof(source->identity->challenge);
return overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0); return overlay_mdp_dispatch(&mdp, NULL);
} }
static int keyring_respond_challenge(struct subscriber *subscriber, overlay_mdp_frame *req) static int keyring_respond_challenge(struct subscriber *subscriber, overlay_mdp_frame *req)
@ -1839,7 +1839,7 @@ static int keyring_respond_challenge(struct subscriber *subscriber, overlay_mdp_
if (crypto_sign_message(subscriber, mdp.out.payload, sizeof(mdp.out.payload), &len)) if (crypto_sign_message(subscriber, mdp.out.payload, sizeof(mdp.out.payload), &len))
return -1; return -1;
mdp.out.payload_length=len; mdp.out.payload_length=len;
return overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0); return overlay_mdp_dispatch(&mdp, NULL);
} }
static int keyring_process_challenge(keyring_file *k, struct subscriber *subscriber, overlay_mdp_frame *req) static int keyring_process_challenge(keyring_file *k, struct subscriber *subscriber, overlay_mdp_frame *req)
@ -1925,7 +1925,7 @@ int keyring_send_sas_request(struct subscriber *subscriber){
mdp.out.payload_length=1; mdp.out.payload_length=1;
mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN; mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN;
if (overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0)) if (overlay_mdp_dispatch(&mdp, NULL))
return WHY("Failed to send SAS resolution request"); return WHY("Failed to send SAS resolution request");
if (config.debug.keyring) if (config.debug.keyring)
DEBUGF("Dispatched SAS resolution request"); DEBUGF("Dispatched SAS resolution request");

View File

@ -27,6 +27,7 @@
#include "overlay_address.h" #include "overlay_address.h"
#include "overlay_packet.h" #include "overlay_packet.h"
#include "mdp_client.h" #include "mdp_client.h"
#include "socket.h"
int mdp_socket(void) int mdp_socket(void)
{ {
@ -34,20 +35,46 @@ int mdp_socket(void)
return overlay_mdp_client_socket(); return overlay_mdp_client_socket();
} }
int mdp_close(int socket) static void mdp_unlink(int mdp_sock)
{ {
// use the same process for closing sockets, though this will need to change once bind is implemented // get the socket name and unlink it from the filesystem if not abstract
return overlay_mdp_client_close(socket); struct socket_address addr;
addr.addrlen = sizeof addr.store;
if (getsockname(mdp_sock, &addr.addr, &addr.addrlen))
WHYF_perror("getsockname(%d)", mdp_sock);
else if (addr.addr.sa_family==AF_UNIX
&& addr.addrlen > sizeof addr.addr_un.sun_family
&& addr.addrlen <= sizeof addr.addr_un && addr.addr_un.sun_path[0] != '\0') {
if (unlink(addr.addr_un.sun_path) == -1)
WARNF_perror("unlink(%s)", alloca_str_toprint(addr.addr_un.sun_path));
}
close(mdp_sock);
} }
int mdp_send(int socket, const struct mdp_header *header, const unsigned char *payload, ssize_t len) int mdp_close(int socket)
{ {
struct sockaddr_un addr; // tell the daemon to drop all bindings
socklen_t addrlen; struct mdp_header header={
if (make_local_sockaddr(&addr, &addrlen, "mdp.2.socket") == -1) .flags = MDP_FLAG_CLOSE,
.local.port = 0,
};
mdp_send(socket, &header, NULL, 0);
// remove socket
mdp_unlink(socket);
return 0;
}
int mdp_send(int socket, const struct mdp_header *header, const uint8_t *payload, size_t len)
{
struct socket_address addr;
if (make_local_sockaddr(&addr, "mdp.2.socket") == -1)
return -1; return -1;
struct iovec iov[]={ struct fragmented_data data={
.fragment_count=2,
.iov={
{ {
.iov_base = (void*)header, .iov_base = (void*)header,
.iov_len = sizeof(struct mdp_header) .iov_len = sizeof(struct mdp_header)
@ -56,27 +83,22 @@ int mdp_send(int socket, const struct mdp_header *header, const unsigned char *p
.iov_base = (void*)payload, .iov_base = (void*)payload,
.iov_len = len .iov_len = len
} }
}
}; };
struct msghdr hdr={
.msg_name=&addr,
.msg_namelen=addrlen,
.msg_iov=iov,
.msg_iovlen=2,
};
return sendmsg(socket, &hdr, 0); return send_message(socket, &addr, &data);
} }
ssize_t mdp_recv(int socket, struct mdp_header *header, unsigned char *payload, ssize_t max_len) ssize_t mdp_recv(int socket, struct mdp_header *header, uint8_t *payload, ssize_t max_len)
{ {
/* Construct name of socket to receive from. */ /* Construct name of socket to receive from. */
struct sockaddr_un mdp_addr; errno=0;
socklen_t mdp_addrlen; struct socket_address mdp_addr;
if (make_local_sockaddr(&mdp_addr, &mdp_addrlen, "mdp.2.socket") == -1) if (make_local_sockaddr(&mdp_addr, "mdp.2.socket") == -1)
return -1; return WHY("Failed to build socket address");
struct sockaddr_un addr; struct socket_address addr;
struct iovec iov[]={ struct iovec iov[]={
{ {
.iov_base = (void *)header, .iov_base = (void *)header,
@ -89,25 +111,26 @@ ssize_t mdp_recv(int socket, struct mdp_header *header, unsigned char *payload,
}; };
struct msghdr hdr={ struct msghdr hdr={
.msg_name=&addr, .msg_name=&addr.addr,
.msg_namelen=sizeof(struct sockaddr_un), .msg_namelen=sizeof(addr.store),
.msg_iov=iov, .msg_iov=iov,
.msg_iovlen=2, .msg_iovlen=2,
}; };
ssize_t len = recvmsg(socket, &hdr, 0); ssize_t len = recvmsg(socket, &hdr, 0);
if (len<sizeof(struct mdp_header)) if (len<sizeof(struct mdp_header))
return -1; return WHYF("Received message is too short (%d)", (int)len);
addr.addrlen=hdr.msg_namelen;
// double check that the incoming address matches the servald daemon // double check that the incoming address matches the servald daemon
if (cmp_sockaddr((struct sockaddr *)&addr, hdr.msg_namelen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0 if (cmp_sockaddr(&addr, &mdp_addr) != 0
&& ( addr.sun_family != AF_UNIX && ( addr.addr_un.sun_family != AF_UNIX
|| real_sockaddr(&addr, hdr.msg_namelen, &addr, &hdr.msg_namelen) <= 0 || real_sockaddr(&addr, &addr) <= 0
|| cmp_sockaddr((struct sockaddr *)&addr, hdr.msg_namelen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0 || cmp_sockaddr(&addr, &mdp_addr) != 0
) )
) )
return -1; return WHYF("Received message came from %s instead of %s?",
alloca_socket_address(&addr),
alloca_socket_address(&mdp_addr));
return len - sizeof(struct mdp_header); return len - sizeof(struct mdp_header);
} }
@ -125,19 +148,18 @@ int overlay_mdp_send(int mdp_sockfd, overlay_mdp_frame *mdp, int flags, int time
if (len == -1) if (len == -1)
return WHY("MDP frame invalid (could not compute length)"); return WHY("MDP frame invalid (could not compute length)");
/* Construct name of socket to send to. */ /* Construct name of socket to send to. */
struct sockaddr_un addr; struct socket_address addr;
socklen_t addrlen; if (make_local_sockaddr(&addr, "mdp.socket") == -1)
if (make_local_sockaddr(&addr, &addrlen, "mdp.socket") == -1)
return -1; return -1;
// Send to that socket // Send to that socket
set_nonblock(mdp_sockfd); set_nonblock(mdp_sockfd);
ssize_t result = sendto(mdp_sockfd, mdp, (size_t)len, 0, (struct sockaddr *)&addr, addrlen); ssize_t result = sendto(mdp_sockfd, mdp, (size_t)len, 0, &addr.addr, addr.addrlen);
set_block(mdp_sockfd); set_block(mdp_sockfd);
if ((size_t)result != (size_t)len) { if ((size_t)result != (size_t)len) {
if (result == -1) if (result == -1)
WHYF_perror("sendto(fd=%d,len=%zu,addr=%s)", mdp_sockfd, (size_t)len, alloca_sockaddr(&addr, addrlen)); WHYF_perror("sendto(fd=%d,len=%zu,addr=%s)", mdp_sockfd, (size_t)len, alloca_socket_address(&addr));
else else
WHYF("sendto() sent %zu bytes of MDP reply (%zu) to socket=%d", (size_t)result, (size_t)len, mdp_sockfd); WHYF("sendto() sent %zu bytes of MDP reply (%zu) to %s", (size_t)result, (size_t)len, alloca_socket_address(&addr));
mdp->packetTypeAndFlags=MDP_ERROR; mdp->packetTypeAndFlags=MDP_ERROR;
mdp->error.error=1; mdp->error.error=1;
snprintf(mdp->error.message,128,"Error sending frame to MDP server."); snprintf(mdp->error.message,128,"Error sending frame to MDP server.");
@ -181,16 +203,15 @@ int overlay_mdp_client_socket(void)
{ {
/* Create local per-client socket to MDP server (connection is always local) */ /* Create local per-client socket to MDP server (connection is always local) */
int mdp_sockfd; int mdp_sockfd;
struct sockaddr_un addr; struct socket_address addr;
socklen_t addrlen;
uint32_t random_value; uint32_t random_value;
if (urandombytes((unsigned char *)&random_value, sizeof random_value) == -1) if (urandombytes((unsigned char *)&random_value, sizeof random_value) == -1)
return WHY("urandombytes() failed"); return WHY("urandombytes() failed");
if (make_local_sockaddr(&addr, &addrlen, "mdp.client.%u.%08lx.socket", getpid(), (unsigned long)random_value) == -1) if (make_local_sockaddr(&addr, "mdp.client.%u.%08lx.socket", getpid(), (unsigned long)random_value) == -1)
return -1; return -1;
if ((mdp_sockfd = esocket(AF_UNIX, SOCK_DGRAM, 0)) == -1) if ((mdp_sockfd = esocket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
return -1; return -1;
if (socket_bind(mdp_sockfd, (struct sockaddr *)&addr, addrlen) == -1) { if (socket_bind(mdp_sockfd, &addr.addr, addr.addrlen) == -1) {
close(mdp_sockfd); close(mdp_sockfd);
return -1; return -1;
} }
@ -204,16 +225,8 @@ int overlay_mdp_client_close(int mdp_sockfd)
overlay_mdp_frame mdp; overlay_mdp_frame mdp;
mdp.packetTypeAndFlags = MDP_GOODBYE; mdp.packetTypeAndFlags = MDP_GOODBYE;
overlay_mdp_send(mdp_sockfd, &mdp, 0, 0); overlay_mdp_send(mdp_sockfd, &mdp, 0, 0);
// get the socket name and unlink it from the filesystem if not abstract
struct sockaddr_un addr; mdp_unlink(mdp_sockfd);
socklen_t addrlen = sizeof addr;
if (getsockname(mdp_sockfd, (struct sockaddr *)&addr, &addrlen))
WHYF_perror("getsockname(%d)", mdp_sockfd);
else if (addrlen > sizeof addr.sun_family && addrlen <= sizeof addr && addr.sun_path[0] != '\0') {
if (unlink(addr.sun_path) == -1)
WARNF_perror("unlink(%s)", alloca_str_toprint(addr.sun_path));
}
close(mdp_sockfd);
return 0; return 0;
} }
@ -236,36 +249,35 @@ int overlay_mdp_client_poll(int mdp_sockfd, time_ms_t timeout_ms)
int overlay_mdp_recv(int mdp_sockfd, overlay_mdp_frame *mdp, mdp_port_t port, int *ttl) int overlay_mdp_recv(int mdp_sockfd, overlay_mdp_frame *mdp, mdp_port_t port, int *ttl)
{ {
/* Construct name of socket to receive from. */ /* Construct name of socket to receive from. */
struct sockaddr_un mdp_addr; struct socket_address mdp_addr;
socklen_t mdp_addrlen; if (make_local_sockaddr(&mdp_addr, "mdp.socket") == -1)
if (make_local_sockaddr(&mdp_addr, &mdp_addrlen, "mdp.socket") == -1)
return -1; return -1;
/* Check if reply available */ /* Check if reply available */
struct sockaddr_un recvaddr; struct socket_address recvaddr;
socklen_t recvaddrlen = sizeof recvaddr; recvaddr.addrlen = sizeof recvaddr.store;
ssize_t len; ssize_t len;
mdp->packetTypeAndFlags = 0; mdp->packetTypeAndFlags = 0;
set_nonblock(mdp_sockfd); set_nonblock(mdp_sockfd);
len = recvwithttl(mdp_sockfd, (unsigned char *)mdp, sizeof(overlay_mdp_frame), ttl, (struct sockaddr *)&recvaddr, &recvaddrlen); len = recvwithttl(mdp_sockfd, (unsigned char *)mdp, sizeof(overlay_mdp_frame), ttl, &recvaddr.addr, &recvaddr.addrlen);
set_block(mdp_sockfd); set_block(mdp_sockfd);
if (len <= 0) if (len <= 0)
return -1; // no packet received return -1; // no packet received
// If the received address overflowed the buffer, then it cannot have come from the server, whose // If the received address overflowed the buffer, then it cannot have come from the server, whose
// address must always fit within a struct sockaddr_un. // address must always fit within a struct sockaddr_un.
if (recvaddrlen > sizeof recvaddr) if (recvaddr.addrlen > sizeof recvaddr.store)
return WHY("reply did not come from server: address overrun"); return WHY("reply did not come from server: address overrun");
// Compare the address of the sender with the address of our server, to ensure they are the same. // Compare the address of the sender with the address of our server, to ensure they are the same.
// If the comparison fails, then try using realpath(3) on the sender address and compare again. // If the comparison fails, then try using realpath(3) on the sender address and compare again.
if ( cmp_sockaddr((struct sockaddr *)&recvaddr, recvaddrlen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0 if ( cmp_sockaddr(&recvaddr, &mdp_addr) != 0
&& ( recvaddr.sun_family != AF_UNIX && ( recvaddr.addr_un.sun_family != AF_UNIX
|| real_sockaddr(&recvaddr, recvaddrlen, &recvaddr, &recvaddrlen) <= 0 || real_sockaddr(&recvaddr, &recvaddr) <= 0
|| cmp_sockaddr((struct sockaddr *)&recvaddr, recvaddrlen, (struct sockaddr *)&mdp_addr, mdp_addrlen) != 0 || cmp_sockaddr(&recvaddr, &mdp_addr) != 0
) )
) )
return WHYF("reply did not come from server: %s", alloca_sockaddr(&recvaddr, recvaddrlen)); return WHYF("reply did not come from server: %s", alloca_socket_address(&recvaddr));
// silently drop incoming packets for the wrong port number // silently drop incoming packets for the wrong port number
if (port>0 && port != mdp->in.dst.port){ if (port>0 && port != mdp->in.dst.port){

View File

@ -31,8 +31,9 @@ struct mdp_sockaddr {
#define MDP_FLAG_NO_CRYPT (1<<0) #define MDP_FLAG_NO_CRYPT (1<<0)
#define MDP_FLAG_NO_SIGN (1<<1) #define MDP_FLAG_NO_SIGN (1<<1)
#define MDP_FLAG_BIND_ALL (1<<2) #define MDP_FLAG_BIND (1<<2)
#define MDP_FLAG_OK (1<<3)
#define MDP_FLAG_CLOSE (1<<3)
#define MDP_FLAG_ERROR (1<<4) #define MDP_FLAG_ERROR (1<<4)
struct mdp_header { struct mdp_header {
@ -43,6 +44,9 @@ struct mdp_header {
uint8_t ttl; uint8_t ttl;
}; };
#define BIND_PRIMARY SID_ANY
#define BIND_ALL SID_BROADCAST
#define TYPE_SID 1 #define TYPE_SID 1
#define TYPE_PIN 2 #define TYPE_PIN 2
#define ACTION_LOCK 1 #define ACTION_LOCK 1
@ -50,6 +54,7 @@ struct mdp_header {
/* Port numbers for commands sent to the local daemon*/ /* Port numbers for commands sent to the local daemon*/
#define MDP_LISTEN 0
/* lock and unlock identities from the local keyring /* lock and unlock identities from the local keyring
* Requests start with an mdp_identity_request structure followed by a list of pins or SIDs * Requests start with an mdp_identity_request structure followed by a list of pins or SIDs
*/ */
@ -82,13 +87,15 @@ struct overlay_mdp_scan{
struct in_addr addr; struct in_addr addr;
}; };
/* V2 interface */ /* low level V2 mdp interface */
int mdp_socket(void); int mdp_socket(void);
int mdp_close(int socket); int mdp_close(int socket);
int mdp_send(int socket, const struct mdp_header *header, const unsigned char *payload, ssize_t len); int mdp_send(int socket, const struct mdp_header *header, const uint8_t *payload, size_t len);
ssize_t mdp_recv(int socket, struct mdp_header *header, unsigned char *payload, ssize_t max_len); ssize_t mdp_recv(int socket, struct mdp_header *header, uint8_t *payload, ssize_t max_len);
int mdp_poll(int socket, time_ms_t timeout_ms); int mdp_poll(int socket, time_ms_t timeout_ms);
/* Client-side MDP function */ /* Client-side MDP function */
int overlay_mdp_client_socket(void); int overlay_mdp_client_socket(void);
int overlay_mdp_client_close(int mdp_sockfd); int overlay_mdp_client_close(int mdp_sockfd);

View File

@ -36,15 +36,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#endif #endif
#include <sys/un.h> #include <sys/un.h>
#include <fcntl.h> #include <fcntl.h>
#include <ctype.h>
#include "constants.h" #include "constants.h"
#include "conf.h" #include "conf.h"
#include "log.h" #include "log.h"
#include "str.h" #include "str.h"
#include "strbuf_helpers.h" #include "strbuf_helpers.h"
#include "socket.h"
#include "monitor-client.h" #include "monitor-client.h"
#include <ctype.h>
#define STATE_INIT 0 #define STATE_INIT 0
#define STATE_DATA 1 #define STATE_DATA 1
@ -72,12 +72,11 @@ int monitor_client_open(struct monitor_state **res)
int fd; int fd;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return WHYF_perror("socket(AF_UNIX, SOCK_STREAM, 0)"); return WHYF_perror("socket(AF_UNIX, SOCK_STREAM, 0)");
struct sockaddr_un addr; struct socket_address addr;
socklen_t addrlen; if (make_local_sockaddr(&addr, "monitor.socket") == -1)
if (make_local_sockaddr(&addr, &addrlen, "monitor.socket") == -1)
return -1; return -1;
INFOF("Attempting to connect to %s", alloca_sockaddr(&addr, addrlen)); INFOF("Attempting to connect to %s", alloca_socket_address(&addr));
if (socket_connect(fd, (struct sockaddr*)&addr, addrlen) == -1) { if (socket_connect(fd, &addr.addr, addr.addrlen) == -1) {
close(fd); close(fd);
return -1; return -1;
} }

View File

@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "strbuf_helpers.h" #include "strbuf_helpers.h"
#include "overlay_address.h" #include "overlay_address.h"
#include "monitor-client.h" #include "monitor-client.h"
#include "socket.h"
#ifdef HAVE_UCRED_H #ifdef HAVE_UCRED_H
#include <ucred.h> #include <ucred.h>
@ -80,11 +81,10 @@ int monitor_setup_sockets()
int sock = -1; int sock = -1;
if ((sock = esocket(AF_UNIX, SOCK_STREAM, 0)) == -1) if ((sock = esocket(AF_UNIX, SOCK_STREAM, 0)) == -1)
goto error; goto error;
struct sockaddr_un addr; struct socket_address addr;
socklen_t addrlen; if (make_local_sockaddr(&addr, "monitor.socket") == -1)
if (make_local_sockaddr(&addr, &addrlen, "monitor.socket") == -1)
goto error; goto error;
if (socket_bind(sock, (struct sockaddr*)&addr, addrlen) == -1) if (socket_bind(sock, &addr.addr, addr.addrlen) == -1)
goto error; goto error;
if (socket_listen(sock, MAX_MONITOR_SOCKETS) == -1) if (socket_listen(sock, MAX_MONITOR_SOCKETS) == -1)
goto error; goto error;
@ -97,7 +97,7 @@ int monitor_setup_sockets()
named_socket.poll.fd=sock; named_socket.poll.fd=sock;
named_socket.poll.events=POLLIN; named_socket.poll.events=POLLIN;
watch(&named_socket); watch(&named_socket);
INFOF("Monitor socket: fd=%d %s", sock, alloca_sockaddr(&addr, addrlen)); INFOF("Monitor socket: fd=%d %s", sock, alloca_socket_address(&addr));
return 0; return 0;
error: error:

View File

@ -313,7 +313,7 @@ int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp)
if (reply.out.payload_length){ if (reply.out.payload_length){
if (config.debug.overlayrouting) if (config.debug.overlayrouting)
DEBUGF("Sending reply"); DEBUGF("Sending reply");
overlay_mdp_dispatch(&reply,0 /* system generated */, NULL,0); overlay_mdp_dispatch(&reply, NULL);
} }
ob_free(replypayload); ob_free(replypayload);
ob_free(payload); ob_free(payload);
@ -387,7 +387,7 @@ int overlay_send_stun_request(struct subscriber *server, struct subscriber *requ
mdp.out.payload_length=ob_position(payload); mdp.out.payload_length=ob_position(payload);
if (config.debug.overlayrouting) if (config.debug.overlayrouting)
DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid)); DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid));
overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL,0); overlay_mdp_dispatch(&mdp, NULL);
} }
ob_free(payload); ob_free(payload);
return 0; return 0;

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,7 @@ int rhizome_mdp_send_block(struct subscriber *dest, const rhizome_bid_t *bid, ui
reply.out.payload[0]='T'; reply.out.payload[0]='T';
// send packet // send packet
if (overlay_mdp_dispatch(&reply,0 /* system generated */, NULL,0)) if (overlay_mdp_dispatch(&reply, NULL))
break; break;
} }
@ -252,8 +252,7 @@ int overlay_mdp_service_echo(overlay_mdp_frame *mdp)
mdp->packetTypeAndFlags&=~(MDP_NOCRYPT|MDP_NOSIGN); mdp->packetTypeAndFlags&=~(MDP_NOCRYPT|MDP_NOSIGN);
/* queue frame for delivery */ /* queue frame for delivery */
overlay_mdp_dispatch(mdp,0 /* system generated */, overlay_mdp_dispatch(mdp, NULL);
NULL,0);
mdp->packetTypeAndFlags=preserved; mdp->packetTypeAndFlags=preserved;
/* and switch addresses back around in case the caller was planning on /* and switch addresses back around in case the caller was planning on
@ -342,20 +341,20 @@ static int overlay_mdp_service_trace(overlay_mdp_frame *mdp){
mdp->out.payload_length = ob_position(b); mdp->out.payload_length = ob_position(b);
mdp->out.src.sid = my_subscriber->sid; mdp->out.src.sid = my_subscriber->sid;
mdp->out.dst.sid = next->sid; mdp->out.dst.sid = next->sid;
ret = overlay_mdp_dispatch(mdp, 0, NULL, 0); ret = overlay_mdp_dispatch(mdp, NULL);
end: end:
ob_free(b); ob_free(b);
RETURN(ret); RETURN(ret);
} }
static int overlay_mdp_service_manifest_requests(struct overlay_frame *frame, overlay_mdp_frame *mdp) static int overlay_mdp_service_manifest_requests(struct overlay_frame *frame, const uint8_t *payload, size_t len)
{ {
int offset=0; int offset=0;
while (offset<mdp->out.payload_length) { while (offset<len) {
rhizome_manifest *m = rhizome_new_manifest(); rhizome_manifest *m = rhizome_new_manifest();
if (!m) if (!m)
return WHY("Unable to allocate manifest"); return WHY("Unable to allocate manifest");
unsigned char *bar = &mdp->out.payload[offset]; const unsigned char *bar = &payload[offset];
if (!rhizome_retrieve_manifest_by_prefix(&bar[RHIZOME_BAR_PREFIX_OFFSET], RHIZOME_BAR_PREFIX_BYTES, m)){ if (!rhizome_retrieve_manifest_by_prefix(&bar[RHIZOME_BAR_PREFIX_OFFSET], RHIZOME_BAR_PREFIX_BYTES, m)){
rhizome_advertise_manifest(frame->source, m); rhizome_advertise_manifest(frame->source, m);
// pre-emptively send the payload if it will fit in a single packet // pre-emptively send the payload if it will fit in a single packet
@ -368,7 +367,7 @@ static int overlay_mdp_service_manifest_requests(struct overlay_frame *frame, ov
return 0; return 0;
} }
int overlay_mdp_try_interal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp) int overlay_mdp_try_internal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp)
{ {
IN(); IN();
switch(mdp->out.dst.port) { switch(mdp->out.dst.port) {
@ -383,7 +382,7 @@ int overlay_mdp_try_interal_services(struct overlay_frame *frame, overlay_mdp_fr
case MDP_PORT_STUN: RETURN(overlay_mdp_service_stun(mdp)); case MDP_PORT_STUN: RETURN(overlay_mdp_service_stun(mdp));
case MDP_PORT_RHIZOME_REQUEST: RETURN(overlay_mdp_service_rhizomerequest(frame, mdp)); case MDP_PORT_RHIZOME_REQUEST: RETURN(overlay_mdp_service_rhizomerequest(frame, mdp));
case MDP_PORT_RHIZOME_RESPONSE: RETURN(overlay_mdp_service_rhizomeresponse(mdp)); case MDP_PORT_RHIZOME_RESPONSE: RETURN(overlay_mdp_service_rhizomeresponse(mdp));
case MDP_PORT_RHIZOME_MANIFEST_REQUEST: RETURN(overlay_mdp_service_manifest_requests(frame, mdp)); case MDP_PORT_RHIZOME_MANIFEST_REQUEST: RETURN(overlay_mdp_service_manifest_requests(frame, mdp->out.payload, mdp->out.payload_length));
case MDP_PORT_RHIZOME_SYNC: RETURN(overlay_mdp_service_rhizome_sync(frame, mdp)); case MDP_PORT_RHIZOME_SYNC: RETURN(overlay_mdp_service_rhizome_sync(frame, mdp));
} }

View File

@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "str.h" #include "str.h"
#include "strbuf_helpers.h" #include "strbuf_helpers.h"
#include "overlay_address.h" #include "overlay_address.h"
#include "socket.h"
/* Represents a queued fetch of a bundle payload, for which the manifest is already known. /* Represents a queued fetch of a bundle payload, for which the manifest is already known.
*/ */
@ -1122,7 +1123,7 @@ static int rhizome_fetch_mdp_requestblocks(struct rhizome_fetch_slot *slot)
slot->write_state.file_offset, slot->write_state.file_offset,
slot->bidVersion); slot->bidVersion);
overlay_mdp_dispatch(&mdp,0 /* system generated */,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
// remember when we sent the request so that we can adjust the inter-request // remember when we sent the request so that we can adjust the inter-request
// interval based on how fast the packets arrive. // interval based on how fast the packets arrive.

View File

@ -482,7 +482,7 @@ next:
lookup_time = (end_time - start_time); lookup_time = (end_time - start_time);
if (mdp.out.payload_length>0) if (mdp.out.payload_length>0)
overlay_mdp_dispatch(&mdp,0 /* system generated */,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
end: end:
sqlite_set_tracefunc(oldfunc); sqlite_set_tracefunc(oldfunc);

View File

@ -93,7 +93,7 @@ static void rhizome_sync_request(struct subscriber *subscriber, uint64_t token,
mdp.out.payload_length = ob_position(b); mdp.out.payload_length = ob_position(b);
if (config.debug.rhizome) if (config.debug.rhizome)
DEBUGF("Sending request to %s for BARs from %"PRIu64" %s", alloca_tohex_sid_t(subscriber->sid), token, forwards?"forwards":"backwards"); DEBUGF("Sending request to %s for BARs from %"PRIu64" %s", alloca_tohex_sid_t(subscriber->sid), token, forwards?"forwards":"backwards");
overlay_mdp_dispatch(&mdp,0,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
ob_free(b); ob_free(b);
} }
@ -147,7 +147,7 @@ static void rhizome_sync_send_requests(struct subscriber *subscriber, struct rhi
break; break;
} }
if (mdp.out.payload_length!=0) if (mdp.out.payload_length!=0)
overlay_mdp_dispatch(&mdp,0,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
// send request for more bars if we have room to cache them // send request for more bars if we have room to cache them
if (state->bar_count >= CACHE_BARS) if (state->bar_count >= CACHE_BARS)
@ -440,7 +440,7 @@ static void sync_send_response(struct subscriber *dest, int forwards, uint64_t t
mdp.out.payload_length = ob_position(b); mdp.out.payload_length = ob_position(b);
if (config.debug.rhizome_ads) if (config.debug.rhizome_ads)
DEBUGF("Sending %d BARs from %"PRIu64" to %"PRIu64, count, token, last); DEBUGF("Sending %d BARs from %"PRIu64" to %"PRIu64, count, token, last);
overlay_mdp_dispatch(&mdp,0,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
} }
ob_free(b); ob_free(b);
OUT(); OUT();

View File

@ -195,28 +195,6 @@ int formf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, con
int vformf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, va_list); int vformf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, va_list);
void serval_setinstancepath(const char *instancepath); void serval_setinstancepath(const char *instancepath);
/* Basic socket operations.
*/
int _make_local_sockaddr(struct __sourceloc, struct sockaddr_un *sockname, socklen_t *addrlen, const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
int _esocket(struct __sourceloc, int domain, int type, int protocol);
int _socket_bind(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_connect(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_listen(struct __sourceloc, int sock, int backlog);
int _socket_set_reuseaddr(struct __sourceloc, int sock, int reuseP);
int _socket_set_rcvbufsize(struct __sourceloc, int sock, unsigned buffer_size);
#define make_local_sockaddr(sockname, addrlenp, fmt,...) _make_local_sockaddr(__WHENCE__, (sockname), (addrlenp), (fmt), ##__VA_ARGS__)
#define esocket(domain, type, protocol) _esocket(__WHENCE__, (domain), (type), (protocol))
#define socket_bind(sock, addr, addrlen) _socket_bind(__WHENCE__, (sock), (addr), (addrlen))
#define socket_connect(sock, addr, addrlen) _socket_connect(__WHENCE__, (sock), (addr), (addrlen))
#define socket_listen(sock, backlog) _socket_listen(__WHENCE__, (sock), (backlog))
#define socket_set_reuseaddr(sock, reuseP) _socket_set_reuseaddr(__WHENCE__, (sock), (reuseP))
#define socket_set_rcvbufsize(sock, buffer_size) _socket_set_rcvbufsize(__WHENCE__, (sock), (buffer_size))
int real_sockaddr(const struct sockaddr_un *src_addr, socklen_t src_addrlen, struct sockaddr_un *dst_addr, socklen_t *dst_addrlen);
int cmp_sockaddr(const struct sockaddr *, socklen_t, const struct sockaddr *, socklen_t);
#define SERVER_CONFIG_RELOAD_INTERVAL_MS 1000 #define SERVER_CONFIG_RELOAD_INTERVAL_MS 1000
struct cli_parsed; struct cli_parsed;
@ -508,9 +486,6 @@ int rhizome_opendb();
int parseCommandLine(struct cli_context *context, const char *argv0, int argc, const char *const *argv); int parseCommandLine(struct cli_context *context, const char *argv0, int argc, const char *const *argv);
int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax); int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax);
int overlay_mdp_reply_error(int sock,
struct sockaddr_un *recvaddr, socklen_t recvaddrlen,
int error_number,char *message);
typedef uint32_t mdp_port_t; typedef uint32_t mdp_port_t;
#define PRImdp_port_t "#08" PRIx32 #define PRImdp_port_t "#08" PRIx32
@ -572,10 +547,8 @@ typedef struct overlay_mdp_frame {
/* Server-side MDP functions */ /* Server-side MDP functions */
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp); int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp);
int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr, socklen_t recvaddrlen, struct socket_address;
overlay_mdp_frame *mdpreply); int overlay_mdp_dispatch(overlay_mdp_frame *mdp, struct socket_address *client);
int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
struct sockaddr_un *recvaddr, socklen_t recvaddrlen);
void overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port); void overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port);
int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const sid_t *resolved_sidp, const char *uri, const char *did, const char *name); int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const sid_t *resolved_sidp, const char *uri, const char *did, const char *name);
@ -688,7 +661,7 @@ int overlay_packetradio_tx_packet(struct overlay_frame *frame);
void overlay_dummy_poll(struct sched_ent *alarm); void overlay_dummy_poll(struct sched_ent *alarm);
void server_config_reload(struct sched_ent *alarm); void server_config_reload(struct sched_ent *alarm);
void server_shutdown_check(struct sched_ent *alarm); void server_shutdown_check(struct sched_ent *alarm);
int overlay_mdp_try_interal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp); int overlay_mdp_try_internal_services(struct overlay_frame *frame, overlay_mdp_frame *mdp);
int overlay_send_probe(struct subscriber *peer, struct network_destination *destination, int queue); int overlay_send_probe(struct subscriber *peer, struct network_destination *destination, int queue);
int overlay_send_stun_request(struct subscriber *server, struct subscriber *request); int overlay_send_stun_request(struct subscriber *server, struct subscriber *request);
void fd_periodicstats(struct sched_ent *alarm); void fd_periodicstats(struct sched_ent *alarm);

118
socket.c
View File

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "conf.h" #include "conf.h"
#include "log.h" #include "log.h"
#include "strbuf_helpers.h" #include "strbuf_helpers.h"
#include "socket.h"
/* Form the name of an AF_UNIX (local) socket in the instance directory as an absolute path. /* Form the name of an AF_UNIX (local) socket in the instance directory as an absolute path.
* Under Linux, this will create a socket name in the abstract namespace. This permits us to use * Under Linux, this will create a socket name in the abstract namespace. This permits us to use
@ -40,25 +41,28 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
* @author Daniel O'Connor <daniel@servalproject.com> * @author Daniel O'Connor <daniel@servalproject.com>
*/ */
int _make_local_sockaddr(struct __sourceloc __whence, struct sockaddr_un *addr, socklen_t *addrlen, const char *fmt, ...) int _make_local_sockaddr(struct __sourceloc __whence, struct socket_address *addr, const char *fmt, ...)
{ {
bzero(addr, sizeof(*addr)); bzero(addr, sizeof(*addr));
addr->addr_un.sun_family = AF_UNIX;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
int r = vformf_serval_instance_path(__WHENCE__, addr->sun_path, sizeof addr->sun_path, fmt, ap); int r = vformf_serval_instance_path(__WHENCE__, addr->addr_un.sun_path, sizeof addr->addr_un.sun_path, fmt, ap);
va_end(ap); va_end(ap);
if (!r) if (!r)
return WHY("socket name overflow"); return WHY("socket name overflow");
if (real_sockaddr(addr, sizeof addr->sun_family + strlen(addr->sun_path) + 1, addr, addrlen) == -1) addr->addrlen=sizeof addr->addr_un.sun_family + strlen(addr->addr_un.sun_path) + 1;
return -1; // TODO perform real path transformation in making the serval instance path
// if (real_sockaddr(addr, addr) == -1)
// return -1;
#ifdef USE_ABSTRACT_NAMESPACE #ifdef USE_ABSTRACT_NAMESPACE
// For the abstract name we use the absolute path name with the initial '/' replaced by the // For the abstract name we use the absolute path name with the initial '/' replaced by the
// leading nul. This ensures that different instances of the Serval daemon have different socket // leading nul. This ensures that different instances of the Serval daemon have different socket
// names. // names.
addr->sun_path[0] = '\0'; // mark as Linux abstract socket addr->addr_un.sun_path[0] = '\0'; // mark as Linux abstract socket
--*addrlen; // do not count trailing nul in abstract socket name --addr->addrlen; // do not count trailing nul in abstract socket name
#endif // USE_ABSTRACT_NAMESPACE #endif // USE_ABSTRACT_NAMESPACE
addr->sun_family = AF_UNIX;
return 0; return 0;
} }
@ -74,31 +78,33 @@ int _make_local_sockaddr(struct __sourceloc __whence, struct sockaddr_un *addr,
* *
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
*/ */
int real_sockaddr(const struct sockaddr_un *src_addr, socklen_t src_addrlen, struct sockaddr_un *dst_addr, socklen_t *dst_addrlen) int real_sockaddr(const struct socket_address *src_addr, struct socket_address *dst_addr)
{ {
int src_path_len = src_addrlen - sizeof src_addr->sun_family; int src_path_len = src_addr->addrlen - sizeof src_addr->addr_un.sun_family;
if ( src_addrlen >= sizeof src_addr->sun_family + 1 if ( src_addr->addrlen >= sizeof src_addr->addr_un.sun_family + 1
&& src_addr->sun_family == AF_UNIX && src_addr->addr_un.sun_family == AF_UNIX
&& src_addr->sun_path[0] != '\0' && src_addr->addr_un.sun_path[0] != '\0'
&& src_addr->sun_path[src_path_len - 1] == '\0' && src_addr->addr_un.sun_path[src_path_len - 1] == '\0'
) { ) {
char real_path[PATH_MAX]; char real_path[PATH_MAX];
size_t real_path_len; size_t real_path_len;
if (realpath(src_addr->sun_path, real_path) == NULL) if (realpath(src_addr->addr_un.sun_path, real_path) == NULL)
return WHYF_perror("realpath(%s)", alloca_str_toprint(src_addr->sun_path)); return WHYF_perror("realpath(%s)", alloca_str_toprint(src_addr->addr_un.sun_path));
else if ((real_path_len = strlen(real_path) + 1) > sizeof dst_addr->sun_path) else if ((real_path_len = strlen(real_path) + 1) > sizeof dst_addr->addr_un.sun_path)
return WHYF("sockaddr overrun: realpath(%s) returned %s", alloca_str_toprint(src_addr->sun_path), alloca_str_toprint(real_path)); return WHYF("sockaddr overrun: realpath(%s) returned %s",
alloca_str_toprint(src_addr->addr_un.sun_path), alloca_str_toprint(real_path));
else if ( real_path_len != src_path_len else if ( real_path_len != src_path_len
|| memcmp(real_path, src_addr->sun_path, src_path_len) != 0 || memcmp(real_path, src_addr->addr_un.sun_path, src_path_len) != 0
) { ) {
memcpy(dst_addr->sun_path, real_path, real_path_len); memcpy(dst_addr->addr_un.sun_path, real_path, real_path_len);
*dst_addrlen = real_path_len + sizeof dst_addr->sun_family; dst_addr->addrlen = real_path_len + sizeof dst_addr->addr_un.sun_family;
return 1; return 1;
} }
} }
if (dst_addr != src_addr) if (dst_addr != src_addr){
memcpy(dst_addr, src_addr, src_addrlen); memcpy(&dst_addr->addr, &src_addr->addr, src_addr->addrlen);
*dst_addrlen = src_addrlen; dst_addr->addrlen = src_addr->addrlen;
}
return 0; return 0;
} }
@ -107,43 +113,43 @@ int real_sockaddr(const struct sockaddr_un *src_addr, socklen_t src_addrlen, str
* *
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
*/ */
int cmp_sockaddr(const struct sockaddr *addrA, socklen_t addrlenA, const struct sockaddr *addrB, socklen_t addrlenB) int cmp_sockaddr(const struct socket_address *addrA, const struct socket_address *addrB)
{ {
// Two zero-length sockaddrs are equal. // Two zero-length sockaddrs are equal.
if (addrlenA == 0 && addrlenB == 0) if (addrA->addrlen == 0 && addrB->addrlen == 0)
return 0; return 0;
// If either sockaddr is truncated, then we compare the bytes we have. // If either sockaddr is truncated, then we compare the bytes we have.
if (addrlenA < sizeof addrA->sa_family || addrlenB < sizeof addrB->sa_family) { if (addrA->addrlen < sizeof addrA->addr.sa_family || addrB->addrlen < sizeof addrB->addr.sa_family) {
int c = memcmp(addrA, addrB, addrlenA < addrlenB ? addrlenA : addrlenB); int c = memcmp(addrA, addrB, addrA->addrlen < addrB->addrlen ? addrA->addrlen : addrB->addrlen);
if (c == 0) if (c == 0)
c = addrlenA < addrlenB ? -1 : addrlenA > addrlenB ? 1 : 0; c = addrA->addrlen < addrB->addrlen ? -1 : addrA->addrlen > addrB->addrlen ? 1 : 0;
return c; return c;
} }
// Order first by address family. // Order first by address family.
if (addrA->sa_family < addrB->sa_family) if (addrA->addr.sa_family < addrB->addr.sa_family)
return -1; return -1;
if (addrA->sa_family > addrB->sa_family) if (addrA->addr.sa_family > addrB->addr.sa_family)
return 1; return 1;
// Both addresses are in the same family... // Both addresses are in the same family...
switch (addrA->sa_family) { switch (addrA->addr.sa_family) {
case AF_UNIX: { case AF_UNIX: {
unsigned pathlenA = addrlenA - sizeof ((const struct sockaddr_un *)addrA)->sun_family; unsigned pathlenA = addrA->addrlen - sizeof (addrA->addr_un.sun_family);
unsigned pathlenB = addrlenB - sizeof ((const struct sockaddr_un *)addrB)->sun_family; unsigned pathlenB = addrB->addrlen - sizeof (addrB->addr_un.sun_family);
int c; int c;
if ( pathlenA > 1 && pathlenB > 1 if ( pathlenA > 1 && pathlenB > 1
&& ((const struct sockaddr_un *)addrA)->sun_path[0] == '\0' && addrA->addr_un.sun_path[0] == '\0'
&& ((const struct sockaddr_un *)addrB)->sun_path[0] == '\0' && addrB->addr_un.sun_path[0] == '\0'
) { ) {
// Both abstract sockets - just compare names, nul bytes are not terminators. // Both abstract sockets - just compare names, nul bytes are not terminators.
c = memcmp(&((const struct sockaddr_un *)addrA)->sun_path[1], c = memcmp(&addrA->addr_un.sun_path[1],
&((const struct sockaddr_un *)addrB)->sun_path[1], &addrB->addr_un.sun_path[1],
(pathlenA < pathlenB ? pathlenA : pathlenB) - 1); (pathlenA < pathlenB ? pathlenA : pathlenB) - 1);
} else { } else {
// Either or both are named local file sockets. If the file names are identical up to the // Either or both are named local file sockets. If the file names are identical up to the
// first nul, then the addresses are equal. This collates abstract socket names, whose first // first nul, then the addresses are equal. This collates abstract socket names, whose first
// character is a nul, ahead of all non-empty file socket names. // character is a nul, ahead of all non-empty file socket names.
c = strncmp(((const struct sockaddr_un *)addrA)->sun_path, c = strncmp(addrA->addr_un.sun_path,
((const struct sockaddr_un *)addrB)->sun_path, addrB->addr_un.sun_path,
(pathlenA < pathlenB ? pathlenA : pathlenB)); (pathlenA < pathlenB ? pathlenA : pathlenB));
} }
if (c == 0) if (c == 0)
@ -153,9 +159,10 @@ int cmp_sockaddr(const struct sockaddr *addrA, socklen_t addrlenA, const struct
break; break;
} }
// Fall back to comparing raw data bytes. // Fall back to comparing raw data bytes.
int c = memcmp(addrA->sa_data, addrB->sa_data, (addrlenA < addrlenB ? addrlenA : addrlenB) - sizeof addrA->sa_family); int c = memcmp(addrA->addr.sa_data, addrB->addr.sa_data,
(addrA->addrlen < addrB->addrlen ? addrA->addrlen : addrB->addrlen) - sizeof addrA->addr.sa_family);
if (c == 0) if (c == 0)
c = addrlenA < addrlenB ? -1 : addrlenA > addrlenB ? 1 : 0; c = addrA->addrlen < addrB->addrlen ? -1 : addrA->addrlen > addrB->addrlen ? 1 : 0;
return c; return c;
} }
@ -225,3 +232,32 @@ int _socket_set_rcvbufsize(struct __sourceloc __whence, int sock, unsigned buffe
DEBUGF("setsockopt(%d, SOL_SOCKET, SO_RCVBUF, &%u, %u)", sock, buffer_size, (unsigned)sizeof buffer_size); DEBUGF("setsockopt(%d, SOL_SOCKET, SO_RCVBUF, &%u, %u)", sock, buffer_size, (unsigned)sizeof buffer_size);
return 0; return 0;
} }
ssize_t _send_message(struct __sourceloc __whence, int fd, const struct socket_address *address, const struct fragmented_data *data)
{
struct msghdr hdr={
.msg_name=(void *)&address->addr,
.msg_namelen=address->addrlen,
.msg_iov=(struct iovec*)data->iov,
.msg_iovlen=data->fragment_count,
};
ssize_t ret = sendmsg(fd, &hdr, 0);
if (ret==-1)
WHYF_perror("sendmsg(%d,%s,%lu)", fd, alloca_socket_address(address), (unsigned long)address->addrlen);
return ret;
}
ssize_t _recv_message(struct __sourceloc __whence, int fd, struct socket_address *address, struct fragmented_data *data)
{
struct msghdr hdr={
.msg_name=(void *)&address->addr,
.msg_namelen=address->addrlen,
.msg_iov=data->iov,
.msg_iovlen=data->fragment_count,
};
ssize_t ret = recvmsg(fd, &hdr, 0);
if (ret==-1)
WHYF_perror("recvmsg(%d,%s,%lu)", fd, alloca_socket_address(address), (unsigned long)address->addrlen);
return ret;
}

56
socket.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef __SERVALD_SOCKET_H
#define __SERVALD_SOCKET_H
#ifndef WIN32
#include <sys/un.h>
#endif
struct socket_address{
socklen_t addrlen;
union{
struct sockaddr addr;
struct sockaddr_un addr_un;
struct sockaddr_storage store;
};
};
/* Basic socket operations.
*/
int _make_local_sockaddr(struct __sourceloc, struct socket_address *addr, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
int _esocket(struct __sourceloc, int domain, int type, int protocol);
int _socket_bind(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_connect(struct __sourceloc, int sock, const struct sockaddr *addr, socklen_t addrlen);
int _socket_listen(struct __sourceloc, int sock, int backlog);
int _socket_set_reuseaddr(struct __sourceloc, int sock, int reuseP);
int _socket_set_rcvbufsize(struct __sourceloc, int sock, unsigned buffer_size);
#define make_local_sockaddr(sockname, fmt,...) _make_local_sockaddr(__WHENCE__, (sockname), (fmt), ##__VA_ARGS__)
#define esocket(domain, type, protocol) _esocket(__WHENCE__, (domain), (type), (protocol))
#define socket_bind(sock, addr, addrlen) _socket_bind(__WHENCE__, (sock), (addr), (addrlen))
#define socket_connect(sock, addr, addrlen) _socket_connect(__WHENCE__, (sock), (addr), (addrlen))
#define socket_listen(sock, backlog) _socket_listen(__WHENCE__, (sock), (backlog))
#define socket_set_reuseaddr(sock, reuseP) _socket_set_reuseaddr(__WHENCE__, (sock), (reuseP))
#define socket_set_rcvbufsize(sock, buffer_size) _socket_set_rcvbufsize(__WHENCE__, (sock), (buffer_size))
int real_sockaddr(const struct socket_address *src_addr, struct socket_address *dst_addr);
int cmp_sockaddr(const struct socket_address *addrA, const struct socket_address *addrB);
// helper functions for manipulating fragmented packet data
#define MAX_FRAGMENTS 8
struct fragmented_data{
int fragment_count;
struct iovec iov[MAX_FRAGMENTS];
};
int prepend_fragment(struct fragmented_data *data, const uint8_t *payload, size_t len);
int append_fragment(struct fragmented_data *data, const uint8_t *payload, size_t len);
size_t copy_fragment(struct fragmented_data *src, uint8_t *dest, size_t length);
ssize_t _send_message(struct __sourceloc, int fd, const struct socket_address *address, const struct fragmented_data *data);
ssize_t _recv_message(struct __sourceloc, int fd, struct socket_address *address, struct fragmented_data *data);
#define send_message(fd, address, data) _send_message(__WHENCE__, (fd), (address), (data))
#define recv_message(fd, address, data) _recv_message(__WHENCE__, (fd), (address), (data))
#endif

View File

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "http_server.h" #include "http_server.h"
#include "strbuf_helpers.h" #include "strbuf_helpers.h"
#include "str.h" #include "str.h"
#include "socket.h"
static inline strbuf _toprint(strbuf sb, char c) static inline strbuf _toprint(strbuf sb, char c)
{ {
@ -374,6 +375,11 @@ strbuf strbuf_append_sockaddr(strbuf sb, const struct sockaddr *addr, socklen_t
return sb; return sb;
} }
strbuf strbuf_append_socket_address(strbuf sb, const struct socket_address *addr)
{
return strbuf_append_sockaddr(sb, &addr->addr, addr->addrlen);
}
strbuf strbuf_append_strftime(strbuf sb, const char *format, const struct tm *tm) strbuf strbuf_append_strftime(strbuf sb, const char *format, const struct tm *tm)
{ {
// First, try calling strftime(3) directly on the buffer in the strbuf, if there is one and it // First, try calling strftime(3) directly on the buffer in the strbuf, if there is one and it

View File

@ -139,6 +139,10 @@ struct sockaddr;
strbuf strbuf_append_sockaddr(strbuf sb, const struct sockaddr *addr, socklen_t addrlen); strbuf strbuf_append_sockaddr(strbuf sb, const struct sockaddr *addr, socklen_t addrlen);
#define alloca_sockaddr(addr, addrlen) strbuf_str(strbuf_append_sockaddr(strbuf_alloca(200), (const struct sockaddr *)(addr), (addrlen))) #define alloca_sockaddr(addr, addrlen) strbuf_str(strbuf_append_sockaddr(strbuf_alloca(200), (const struct sockaddr *)(addr), (addrlen)))
struct socket_address;
strbuf strbuf_append_socket_address(strbuf sb, const struct socket_address *addr);
#define alloca_socket_address(addr) strbuf_str(strbuf_append_socket_address(strbuf_alloca(200), (addr)))
/* Append a strftime(3) string. /* Append a strftime(3) string.
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
*/ */

4
vomp.c
View File

@ -523,7 +523,7 @@ static int vomp_send_status_remote(struct vomp_call_state *call)
call->local.sequence++; call->local.sequence++;
overlay_mdp_dispatch(&mdp,0,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
return 0; return 0;
} }
@ -561,7 +561,7 @@ int vomp_received_audio(struct vomp_call_state *call, int audio_codec, int time,
mdp.out.queue=OQ_ISOCHRONOUS_VOICE; mdp.out.queue=OQ_ISOCHRONOUS_VOICE;
overlay_mdp_dispatch(&mdp,0,NULL,0); overlay_mdp_dispatch(&mdp, NULL);
return 0; return 0;
} }