]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
client: convert to new socket API
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 17 Jul 2019 15:38:32 +0000 (17:38 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 18 Jul 2019 15:29:44 +0000 (17:29 +0200)
Makefile.in
client.c

index 07b06a72028174fbfff3afa98f9266d32a2d7c40..0d95aaa82a61f7358cc39d7c06c8a7d43304edb0 100644 (file)
@@ -42,7 +42,7 @@ OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \
 EXTRA_OBJS=@EXTRA_OBJECTS@
 
 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)
 
index fcaaf3ae82d749f2ddc525966be640da8dcff23d..56ac1bd10906d80b6423016bc777b949e47d95de 100644 (file)
--- a/client.c
+++ b/client.c
@@ -39,6 +39,7 @@
 #include "getdate.h"
 #include "cmdparse.h"
 #include "pktlength.h"
+#include "socket.h"
 #include "util.h"
 
 #ifdef FEAT_READLINE
 
 /* ================================================== */
 
-union sockaddr_all {
-  struct sockaddr_in in4;
-#ifdef FEAT_IPV6
-  struct sockaddr_in6 in6;
-#endif
-  struct sockaddr_un un;
-  struct sockaddr sa;
+struct Address {
+  SCK_AddressType type;
+  union {
+    IPSockAddr ip;
+    char *path;
+  } addr;
 };
 
-static ARR_Instance sockaddrs;
+static ARR_Instance server_addresses;
 
 static int sock_fd = -1;
 
@@ -145,15 +145,15 @@ read_line(void)
 /* ================================================== */
 
 static ARR_Instance
-get_sockaddrs(const char *hostnames, int port)
+get_addresses(const char *hostnames, int port)
 {
+  struct Address *addr;
   ARR_Instance addrs;
   char *hostname, *s1, *s2;
   IPAddr ip_addrs[DNS_MAX_ADDRESSES];
-  union sockaddr_all *addr;
   int i;
 
-  addrs = ARR_CreateInstance(sizeof (union sockaddr_all));
+  addrs = ARR_CreateInstance(sizeof (*addr));
   s1 = Strdup(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 */
     if (hostname[0] == '/') {
-      addr = (union sockaddr_all *)ARR_GetNewElement(addrs);
-      if (snprintf(addr->un.sun_path, sizeof (addr->un.sun_path), "%s", hostname) >=
-          sizeof (addr->un.sun_path))
-        LOG_FATAL("Unix socket path too long");
-      addr->un.sun_family = AF_UNIX;
+      addr = ARR_GetNewElement(addrs);
+      addr->type = SCK_ADDR_UNIX;
+      addr->addr.path = Strdup(hostname);
     } else {
       if (DNS_Name2IPAddress(hostname, ip_addrs, DNS_MAX_ADDRESSES) != DNS_Success) {
         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++) {
-        addr = (union sockaddr_all *)ARR_GetNewElement(addrs);
-        UTI_IPAndPortToSockaddr(&ip_addrs[i], port, (struct sockaddr *)addr);
+        addr = ARR_GetNewElement(addrs);
+        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]));
       }
     }
@@ -188,69 +188,59 @@ get_sockaddrs(const char *hostnames, int port)
 }
 
 /* ================================================== */
-/* Initialise the socket used to talk to the daemon */
 
-static int
-prepare_socket(union sockaddr_all *addr)
+static void
+free_addresses(ARR_Instance addresses)
 {
-  socklen_t addr_len;
-  char *dir;
+  struct Address *addr;
+  unsigned int i;
 
-  switch (addr->sa.sa_family) {
-    case AF_UNIX:
-      addr_len = sizeof (addr->un);
-      break;
-    case AF_INET:
-      addr_len = sizeof (addr->in4);
-      break;
-#ifdef FEAT_IPV6
-    case AF_INET6:
-      addr_len = sizeof (addr->in6);
-      break;
-#endif
-    default:
-      assert(0);
+  for (i = 0; i < ARR_GetSize(addresses); i++) {
+    addr = ARR_GetElement(addresses, i);
+
+    if (addr->type == SCK_ADDR_UNIX)
+      Free(addr->addr.path);
   }
 
-  sock_fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
+  ARR_DestroyInstance(addresses);
+}
 
-  if (sock_fd < 0) {
-    DEBUG_LOG("Could not create socket : %s", strerror(errno));
-    return 0;
-  }
+/* ================================================== */
+/* Initialise the socket used to talk to the daemon */
 
-  if (addr->sa.sa_family == AF_UNIX) {
-    struct sockaddr_un sa_un;
+static int
+open_socket(struct Address *addr)
+{
+  char *dir, *local_addr;
+  size_t local_addr_len;
 
-    /* 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);
+  switch (addr->type) {
+    case SCK_ADDR_IP:
+      sock_fd = SCK_OpenUdpSocket(&addr->addr.ip, NULL, 0);
+      break;
+    case SCK_ADDR_UNIX:
+      /* 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. */
 
-    sa_un.sun_family = AF_UNIX;
-    unlink(sa_un.sun_path);
+      dir = UTI_PathToDir(addr->addr.path);
+      local_addr_len = strlen(dir) + 50;
+      local_addr = Malloc(local_addr_len);
 
-    /* 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;
-    }
+      snprintf(local_addr, local_addr_len, "%s/chronyc.%d.sock", dir, (int)getpid());
 
-    /* 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;
-    }
+      sock_fd = SCK_OpenUnixDatagramSocket(addr->addr.path, local_addr,
+                                           SCK_FLAG_ALL_PERMISSIONS);
+      Free(dir);
+      Free(local_addr);
+
+      break;
+    default:
+      assert(0);
   }
 
-  if (connect(sock_fd, &addr->sa, addr_len) < 0) {
-    DEBUG_LOG("Could not connect socket : %s", strerror(errno));
+  if (sock_fd < 0)
     return 0;
-  }
 
   return 1;
 }
@@ -260,20 +250,11 @@ prepare_socket(union sockaddr_all *addr)
 static void
 close_io(void)
 {
-  union sockaddr_all addr;
-  socklen_t addr_len = sizeof (addr);
-
   if (sock_fd < 0)
     return;
 
-  /* Remove our Unix domain socket */
-  if (getsockname(sock_fd, &addr.sa, &addr_len) < 0)
-    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);
+  SCK_RemoveSocket(sock_fd);
+  SCK_CloseSocket(sock_fd);
   sock_fd = -1;
 }
 
@@ -283,7 +264,7 @@ static int
 open_io(void)
 {
   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 (sock_fd >= 0) {
@@ -292,11 +273,10 @@ open_io(void)
   }
 
   /* Find an address for which a socket can be opened and connected */
-  for (; address_index < ARR_GetSize(sockaddrs); address_index++) {
-    addr = (union sockaddr_all *)ARR_GetElement(sockaddrs, address_index);
-    DEBUG_LOG("Opening connection to %s", UTI_SockaddrToString(&addr->sa));
+  for (; address_index < ARR_GetSize(server_addresses); address_index++) {
+    addr = ARR_GetElement(server_addresses, address_index);
 
-    if (prepare_socket(addr))
+    if (open_socket(addr))
       return 1;
 
     close_io();
@@ -1426,12 +1406,8 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
         return 0;
       }
 
-      if (send(sock_fd, (void *)request, command_length, 0) < 0) {
-        DEBUG_LOG("Could not send %d bytes : %s", command_length, strerror(errno));
+      if (SCK_Send(sock_fd, (void *)request, command_length, 0) < 0)
         return 0;
-      }
-
-      DEBUG_LOG("Sent %d bytes", command_length);
     }
 
     UTI_TimevalToTimespec(&tv, &ts_now);
@@ -1467,16 +1443,11 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
       /* Timeout must have elapsed, try a resend? */
       new_attempt = 1;
     } 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 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;
       } else {
-        DEBUG_LOG("Received %d bytes", recv_status);
-        
         read_length = recv_status;
         
         /* Check if the header is valid */
@@ -3261,7 +3232,8 @@ main(int argc, char **argv)
 
   UTI_SetQuitSignalsHandler(signal_handler, 0);
 
-  sockaddrs = get_sockaddrs(hostnames, port);
+  SCK_Initialise();
+  server_addresses = get_addresses(hostnames, port);
 
   if (!open_io())
     LOG_FATAL("Could not open connection to daemon");
@@ -3281,8 +3253,8 @@ main(int argc, char **argv)
   }
 
   close_io();
-
-  ARR_DestroyInstance(sockaddrs);
+  free_addresses(server_addresses);
+  SCK_Finalise();
 
   return !ret;
 }