]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/admin_socket_client.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / common / admin_socket_client.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
91327a77
AA
15#include <arpa/inet.h>
16#include <fcntl.h>
17#include <sys/socket.h>
18#include <sys/un.h>
f67539c2 19#include <unistd.h>
91327a77 20
7c673cae 21#include "common/admin_socket.h"
7c673cae
FG
22#include "common/errno.h"
23#include "common/safe_io.h"
24#include "common/admin_socket_client.h"
25
91327a77
AA
26#include "include/compat.h"
27#include "include/sock_compat.h"
7c673cae
FG
28
29using std::ostringstream;
30
31const char* get_rand_socket_path()
32{
33 static char *g_socket_path = NULL;
34
35 if (g_socket_path == NULL) {
36 char buf[512];
37 const char *tdir = getenv("TMPDIR");
f67539c2
TL
38 #ifdef _WIN32
39 if (tdir == NULL) {
40 tdir = getenv("TEMP");
41 }
42 #endif /* _WIN32 */
7c673cae
FG
43 if (tdir == NULL) {
44 tdir = "/tmp";
45 }
46 snprintf(buf, sizeof(((struct sockaddr_un*)0)->sun_path),
47 "%s/perfcounters_test_socket.%ld.%ld",
48 tdir, (long int)getpid(), time(NULL));
49 g_socket_path = (char*)strdup(buf);
50 }
51 return g_socket_path;
52}
53
54static std::string asok_connect(const std::string &path, int *fd)
55{
91327a77 56 int socket_fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
7c673cae 57 if(socket_fd < 0) {
f67539c2 58 int err = ceph_sock_errno();
7c673cae
FG
59 ostringstream oss;
60 oss << "socket(PF_UNIX, SOCK_STREAM, 0) failed: " << cpp_strerror(err);
61 return oss.str();
62 }
63
64 struct sockaddr_un address;
92f5a8d4 65 // FIPS zeroization audit 20191115: this memset is fine.
7c673cae
FG
66 memset(&address, 0, sizeof(struct sockaddr_un));
67 address.sun_family = AF_UNIX;
68 snprintf(address.sun_path, sizeof(address.sun_path), "%s", path.c_str());
69
70 if (::connect(socket_fd, (struct sockaddr *) &address,
71 sizeof(struct sockaddr_un)) != 0) {
f67539c2 72 int err = ceph_sock_errno();
7c673cae
FG
73 ostringstream oss;
74 oss << "connect(" << socket_fd << ") failed: " << cpp_strerror(err);
f67539c2 75 compat_closesocket(socket_fd);
7c673cae
FG
76 return oss.str();
77 }
78
79 struct timeval timer;
92f5a8d4 80 timer.tv_sec = 10;
7c673cae 81 timer.tv_usec = 0;
f67539c2
TL
82 if (::setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (SOCKOPT_VAL_TYPE)&timer, sizeof(timer))) {
83 int err = ceph_sock_errno();
7c673cae
FG
84 ostringstream oss;
85 oss << "setsockopt(" << socket_fd << ", SO_RCVTIMEO) failed: "
86 << cpp_strerror(err);
f67539c2 87 compat_closesocket(socket_fd);
7c673cae
FG
88 return oss.str();
89 }
92f5a8d4 90 timer.tv_sec = 10;
7c673cae 91 timer.tv_usec = 0;
f67539c2
TL
92 if (::setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, (SOCKOPT_VAL_TYPE)&timer, sizeof(timer))) {
93 int err = ceph_sock_errno();
7c673cae
FG
94 ostringstream oss;
95 oss << "setsockopt(" << socket_fd << ", SO_SNDTIMEO) failed: "
96 << cpp_strerror(err);
f67539c2 97 compat_closesocket(socket_fd);
7c673cae
FG
98 return oss.str();
99 }
100
101 *fd = socket_fd;
102 return "";
103}
104
105static std::string asok_request(int socket_fd, std::string request)
106{
f67539c2 107 ssize_t res = safe_send(socket_fd, request.c_str(), request.length() + 1);
7c673cae
FG
108 if (res < 0) {
109 int err = res;
110 ostringstream oss;
111 oss << "safe_write(" << socket_fd << ") failed to write request code: "
112 << cpp_strerror(err);
113 return oss.str();
114 }
115 return "";
116}
117
118AdminSocketClient::
119AdminSocketClient(const std::string &path)
120 : m_path(path)
121{
122}
123
124std::string AdminSocketClient::ping(bool *ok)
125{
126 std::string version;
127 std::string result = do_request("{\"prefix\":\"0\"}", &version);
128 *ok = result == "" && version.length() == 1;
129 return result;
130}
131
132std::string AdminSocketClient::do_request(std::string request, std::string *result)
133{
134 int socket_fd = 0, res;
135 std::string buffer;
136 uint32_t message_size_raw, message_size;
137
138 std::string err = asok_connect(m_path, &socket_fd);
139 if (!err.empty()) {
140 goto out;
141 }
142 err = asok_request(socket_fd, request);
143 if (!err.empty()) {
144 goto done;
145 }
f67539c2 146 res = safe_recv_exact(socket_fd, &message_size_raw,
7c673cae
FG
147 sizeof(message_size_raw));
148 if (res < 0) {
149 int e = res;
150 ostringstream oss;
f67539c2 151 oss << "safe_recv(" << socket_fd << ") failed to read message size: "
7c673cae
FG
152 << cpp_strerror(e);
153 err = oss.str();
154 goto done;
155 }
156 message_size = ntohl(message_size_raw);
157 buffer.resize(message_size, 0);
f67539c2 158 res = safe_recv_exact(socket_fd, &buffer[0], message_size);
7c673cae
FG
159 if (res < 0) {
160 int e = res;
161 ostringstream oss;
f67539c2 162 oss << "safe_recv(" << socket_fd << ") failed: " << cpp_strerror(e);
7c673cae
FG
163 err = oss.str();
164 goto done;
165 }
166 //printf("MESSAGE FROM SERVER: %s\n", buffer.c_str());
167 std::swap(*result, buffer);
168done:
f67539c2 169 compat_closesocket(socket_fd);
7c673cae
FG
170 out:
171 return err;
172}