client: convert to new socket API
This commit is contained in:
parent
c651ea9b6b
commit
bb1c02e9f5
2 changed files with 72 additions and 100 deletions
|
@ -42,7 +42,7 @@ OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \
|
||||||
EXTRA_OBJS=@EXTRA_OBJECTS@
|
EXTRA_OBJS=@EXTRA_OBJECTS@
|
||||||
|
|
||||||
CLI_OBJS = array.o client.o cmdparse.o getdate.o memory.o nameserv.o \
|
CLI_OBJS = array.o client.o cmdparse.o getdate.o memory.o nameserv.o \
|
||||||
pktlength.o util.o $(HASH_OBJ)
|
pktlength.o socket.o util.o $(HASH_OBJ)
|
||||||
|
|
||||||
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS)
|
ALL_OBJS = $(OBJS) $(EXTRA_OBJS) $(CLI_OBJS)
|
||||||
|
|
||||||
|
|
170
client.c
170
client.c
|
@ -39,6 +39,7 @@
|
||||||
#include "getdate.h"
|
#include "getdate.h"
|
||||||
#include "cmdparse.h"
|
#include "cmdparse.h"
|
||||||
#include "pktlength.h"
|
#include "pktlength.h"
|
||||||
|
#include "socket.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef FEAT_READLINE
|
#ifdef FEAT_READLINE
|
||||||
|
@ -52,16 +53,15 @@
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
union sockaddr_all {
|
struct Address {
|
||||||
struct sockaddr_in in4;
|
SCK_AddressType type;
|
||||||
#ifdef FEAT_IPV6
|
union {
|
||||||
struct sockaddr_in6 in6;
|
IPSockAddr ip;
|
||||||
#endif
|
char *path;
|
||||||
struct sockaddr_un un;
|
} addr;
|
||||||
struct sockaddr sa;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static ARR_Instance sockaddrs;
|
static ARR_Instance server_addresses;
|
||||||
|
|
||||||
static int sock_fd = -1;
|
static int sock_fd = -1;
|
||||||
|
|
||||||
|
@ -145,15 +145,15 @@ read_line(void)
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static ARR_Instance
|
static ARR_Instance
|
||||||
get_sockaddrs(const char *hostnames, int port)
|
get_addresses(const char *hostnames, int port)
|
||||||
{
|
{
|
||||||
|
struct Address *addr;
|
||||||
ARR_Instance addrs;
|
ARR_Instance addrs;
|
||||||
char *hostname, *s1, *s2;
|
char *hostname, *s1, *s2;
|
||||||
IPAddr ip_addrs[DNS_MAX_ADDRESSES];
|
IPAddr ip_addrs[DNS_MAX_ADDRESSES];
|
||||||
union sockaddr_all *addr;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
addrs = ARR_CreateInstance(sizeof (union sockaddr_all));
|
addrs = ARR_CreateInstance(sizeof (*addr));
|
||||||
s1 = Strdup(hostnames);
|
s1 = Strdup(hostnames);
|
||||||
|
|
||||||
/* Parse the comma-separated list of hostnames */
|
/* Parse the comma-separated list of hostnames */
|
||||||
|
@ -164,11 +164,9 @@ get_sockaddrs(const char *hostnames, int port)
|
||||||
|
|
||||||
/* hostname starting with / is considered a path of Unix domain socket */
|
/* hostname starting with / is considered a path of Unix domain socket */
|
||||||
if (hostname[0] == '/') {
|
if (hostname[0] == '/') {
|
||||||
addr = (union sockaddr_all *)ARR_GetNewElement(addrs);
|
addr = ARR_GetNewElement(addrs);
|
||||||
if (snprintf(addr->un.sun_path, sizeof (addr->un.sun_path), "%s", hostname) >=
|
addr->type = SCK_ADDR_UNIX;
|
||||||
sizeof (addr->un.sun_path))
|
addr->addr.path = Strdup(hostname);
|
||||||
LOG_FATAL("Unix socket path too long");
|
|
||||||
addr->un.sun_family = AF_UNIX;
|
|
||||||
} else {
|
} else {
|
||||||
if (DNS_Name2IPAddress(hostname, ip_addrs, DNS_MAX_ADDRESSES) != DNS_Success) {
|
if (DNS_Name2IPAddress(hostname, ip_addrs, DNS_MAX_ADDRESSES) != DNS_Success) {
|
||||||
DEBUG_LOG("Could not get IP address for %s", hostname);
|
DEBUG_LOG("Could not get IP address for %s", hostname);
|
||||||
|
@ -176,8 +174,10 @@ get_sockaddrs(const char *hostnames, int port)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < DNS_MAX_ADDRESSES && ip_addrs[i].family != IPADDR_UNSPEC; i++) {
|
for (i = 0; i < DNS_MAX_ADDRESSES && ip_addrs[i].family != IPADDR_UNSPEC; i++) {
|
||||||
addr = (union sockaddr_all *)ARR_GetNewElement(addrs);
|
addr = ARR_GetNewElement(addrs);
|
||||||
UTI_IPAndPortToSockaddr(&ip_addrs[i], port, (struct sockaddr *)addr);
|
addr->type = SCK_ADDR_IP;
|
||||||
|
addr->addr.ip.ip_addr = ip_addrs[i];
|
||||||
|
addr->addr.ip.port = port;
|
||||||
DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&ip_addrs[i]));
|
DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&ip_addrs[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,70 +187,60 @@ get_sockaddrs(const char *hostnames, int port)
|
||||||
return addrs;
|
return addrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_addresses(ARR_Instance addresses)
|
||||||
|
{
|
||||||
|
struct Address *addr;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARR_GetSize(addresses); i++) {
|
||||||
|
addr = ARR_GetElement(addresses, i);
|
||||||
|
|
||||||
|
if (addr->type == SCK_ADDR_UNIX)
|
||||||
|
Free(addr->addr.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ARR_DestroyInstance(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Initialise the socket used to talk to the daemon */
|
/* Initialise the socket used to talk to the daemon */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prepare_socket(union sockaddr_all *addr)
|
open_socket(struct Address *addr)
|
||||||
{
|
{
|
||||||
socklen_t addr_len;
|
char *dir, *local_addr;
|
||||||
char *dir;
|
size_t local_addr_len;
|
||||||
|
|
||||||
switch (addr->sa.sa_family) {
|
switch (addr->type) {
|
||||||
case AF_UNIX:
|
case SCK_ADDR_IP:
|
||||||
addr_len = sizeof (addr->un);
|
sock_fd = SCK_OpenUdpSocket(&addr->addr.ip, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case AF_INET:
|
case SCK_ADDR_UNIX:
|
||||||
addr_len = sizeof (addr->in4);
|
/* Construct path of our socket. Use the same directory as the server
|
||||||
|
socket and include our process ID to allow multiple chronyc instances
|
||||||
|
running at the same time. */
|
||||||
|
|
||||||
|
dir = UTI_PathToDir(addr->addr.path);
|
||||||
|
local_addr_len = strlen(dir) + 50;
|
||||||
|
local_addr = Malloc(local_addr_len);
|
||||||
|
|
||||||
|
snprintf(local_addr, local_addr_len, "%s/chronyc.%d.sock", dir, (int)getpid());
|
||||||
|
|
||||||
|
sock_fd = SCK_OpenUnixDatagramSocket(addr->addr.path, local_addr,
|
||||||
|
SCK_FLAG_ALL_PERMISSIONS);
|
||||||
|
Free(dir);
|
||||||
|
Free(local_addr);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#ifdef FEAT_IPV6
|
|
||||||
case AF_INET6:
|
|
||||||
addr_len = sizeof (addr->in6);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sock_fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
|
if (sock_fd < 0)
|
||||||
|
|
||||||
if (sock_fd < 0) {
|
|
||||||
DEBUG_LOG("Could not create socket : %s", strerror(errno));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_UNIX) {
|
|
||||||
struct sockaddr_un sa_un;
|
|
||||||
|
|
||||||
/* Construct path of our socket. Use the same directory as the server
|
|
||||||
socket and include our process ID to allow multiple chronyc instances
|
|
||||||
running at the same time. */
|
|
||||||
dir = UTI_PathToDir(addr->un.sun_path);
|
|
||||||
if (snprintf(sa_un.sun_path, sizeof (sa_un.sun_path),
|
|
||||||
"%s/chronyc.%d.sock", dir, (int)getpid()) >= sizeof (sa_un.sun_path))
|
|
||||||
LOG_FATAL("Unix socket path too long");
|
|
||||||
Free(dir);
|
|
||||||
|
|
||||||
sa_un.sun_family = AF_UNIX;
|
|
||||||
unlink(sa_un.sun_path);
|
|
||||||
|
|
||||||
/* Bind the socket to the path */
|
|
||||||
if (bind(sock_fd, (struct sockaddr *)&sa_un, sizeof (sa_un)) < 0) {
|
|
||||||
DEBUG_LOG("Could not bind socket : %s", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow server without root privileges to send replies to our socket */
|
|
||||||
if (chmod(sa_un.sun_path, 0666) < 0) {
|
|
||||||
DEBUG_LOG("Could not change socket permissions : %s", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connect(sock_fd, &addr->sa, addr_len) < 0) {
|
|
||||||
DEBUG_LOG("Could not connect socket : %s", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -260,20 +250,11 @@ prepare_socket(union sockaddr_all *addr)
|
||||||
static void
|
static void
|
||||||
close_io(void)
|
close_io(void)
|
||||||
{
|
{
|
||||||
union sockaddr_all addr;
|
|
||||||
socklen_t addr_len = sizeof (addr);
|
|
||||||
|
|
||||||
if (sock_fd < 0)
|
if (sock_fd < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Remove our Unix domain socket */
|
SCK_RemoveSocket(sock_fd);
|
||||||
if (getsockname(sock_fd, &addr.sa, &addr_len) < 0)
|
SCK_CloseSocket(sock_fd);
|
||||||
LOG_FATAL("getsockname() failed : %s", strerror(errno));
|
|
||||||
if (addr_len <= sizeof (addr) && addr_len > sizeof (addr.sa.sa_family) &&
|
|
||||||
addr.sa.sa_family == AF_UNIX)
|
|
||||||
unlink(addr.un.sun_path);
|
|
||||||
|
|
||||||
close(sock_fd);
|
|
||||||
sock_fd = -1;
|
sock_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +264,7 @@ static int
|
||||||
open_io(void)
|
open_io(void)
|
||||||
{
|
{
|
||||||
static unsigned int address_index = 0;
|
static unsigned int address_index = 0;
|
||||||
union sockaddr_all *addr;
|
struct Address *addr;
|
||||||
|
|
||||||
/* If a socket is already opened, close it and try the next address */
|
/* If a socket is already opened, close it and try the next address */
|
||||||
if (sock_fd >= 0) {
|
if (sock_fd >= 0) {
|
||||||
|
@ -292,11 +273,10 @@ open_io(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find an address for which a socket can be opened and connected */
|
/* Find an address for which a socket can be opened and connected */
|
||||||
for (; address_index < ARR_GetSize(sockaddrs); address_index++) {
|
for (; address_index < ARR_GetSize(server_addresses); address_index++) {
|
||||||
addr = (union sockaddr_all *)ARR_GetElement(sockaddrs, address_index);
|
addr = ARR_GetElement(server_addresses, address_index);
|
||||||
DEBUG_LOG("Opening connection to %s", UTI_SockaddrToString(&addr->sa));
|
|
||||||
|
|
||||||
if (prepare_socket(addr))
|
if (open_socket(addr))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
close_io();
|
close_io();
|
||||||
|
@ -1426,12 +1406,8 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send(sock_fd, (void *)request, command_length, 0) < 0) {
|
if (SCK_Send(sock_fd, (void *)request, command_length, 0) < 0)
|
||||||
DEBUG_LOG("Could not send %d bytes : %s", command_length, strerror(errno));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_LOG("Sent %d bytes", command_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UTI_TimevalToTimespec(&tv, &ts_now);
|
UTI_TimevalToTimespec(&tv, &ts_now);
|
||||||
|
@ -1467,16 +1443,11 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
/* Timeout must have elapsed, try a resend? */
|
/* Timeout must have elapsed, try a resend? */
|
||||||
new_attempt = 1;
|
new_attempt = 1;
|
||||||
} else {
|
} else {
|
||||||
recv_status = recv(sock_fd, (void *)reply, sizeof(CMD_Reply), 0);
|
recv_status = SCK_Receive(sock_fd, reply, sizeof (*reply), 0);
|
||||||
|
|
||||||
if (recv_status < 0) {
|
if (recv_status < 0) {
|
||||||
/* If we get connrefused here, it suggests the sendto is
|
|
||||||
going to a dead port */
|
|
||||||
DEBUG_LOG("Could not receive : %s", strerror(errno));
|
|
||||||
new_attempt = 1;
|
new_attempt = 1;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_LOG("Received %d bytes", recv_status);
|
|
||||||
|
|
||||||
read_length = recv_status;
|
read_length = recv_status;
|
||||||
|
|
||||||
/* Check if the header is valid */
|
/* Check if the header is valid */
|
||||||
|
@ -3261,7 +3232,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
UTI_SetQuitSignalsHandler(signal_handler, 0);
|
UTI_SetQuitSignalsHandler(signal_handler, 0);
|
||||||
|
|
||||||
sockaddrs = get_sockaddrs(hostnames, port);
|
SCK_Initialise();
|
||||||
|
server_addresses = get_addresses(hostnames, port);
|
||||||
|
|
||||||
if (!open_io())
|
if (!open_io())
|
||||||
LOG_FATAL("Could not open connection to daemon");
|
LOG_FATAL("Could not open connection to daemon");
|
||||||
|
@ -3281,8 +3253,8 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
close_io();
|
close_io();
|
||||||
|
free_addresses(server_addresses);
|
||||||
ARR_DestroyInstance(sockaddrs);
|
SCK_Finalise();
|
||||||
|
|
||||||
return !ret;
|
return !ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue