Kea 3.1.5
unix_control_client.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <gtest/gtest.h>
11#include <util/ready_check.h>
12#include <unistd.h>
13#include <sys/socket.h>
14#include <sys/un.h>
15#include <errno.h>
16#include <string.h>
17
18namespace isc {
19namespace dhcp {
20namespace test {
21
25
29
32 if (socket_fd_ >= 0) {
33 static_cast<void>(close(socket_fd_));
34 socket_fd_ = -1;
35 }
36}
37
38bool UnixControlClient::connectToServer(const std::string& socket_path) {
39 // Create UNIX socket
40 socket_fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
41 if (socket_fd_ < 0) {
42 const char* errmsg = strerror(errno);
43 ADD_FAILURE() << "Failed to open unix stream socket: " << errmsg;
44 return (false);
45 }
46
47 struct sockaddr_un srv_addr;
48 if (socket_path.size() > sizeof(srv_addr.sun_path) - 1) {
49 ADD_FAILURE() << "Socket path specified (" << socket_path
50 << ") is larger than " << (sizeof(srv_addr.sun_path) - 1)
51 << " allowed.";
53 return (false);
54 }
55
56 // Prepare socket address
57 memset(&srv_addr, 0, sizeof(srv_addr));
58 srv_addr.sun_family = AF_UNIX;
59 strncpy(srv_addr.sun_path, socket_path.c_str(),
60 sizeof(srv_addr.sun_path) - 1);
61 socklen_t len = sizeof(srv_addr);
62
63 // Connect to the specified UNIX socket
64 int status = connect(socket_fd_, (struct sockaddr*)&srv_addr, len);
65 if (status == -1) {
66 const char* errmsg = strerror(errno);
67 ADD_FAILURE() << "Failed to connect unix socket: fd=" << socket_fd_
68 << ", path=" << socket_path << " : " << errmsg;
70 return (false);
71 }
72
73 return (true);
74}
75
76bool UnixControlClient::sendCommand(const std::string& command) {
77 if (socket_fd_ < 0) {
78 ADD_FAILURE() << "send command with closed socket";
79 return (false);
80 }
81 // Send command
82 int bytes_sent = send(socket_fd_, command.c_str(), command.length(), 0);
83 if (bytes_sent < static_cast<int>(command.length())) {
84 const char* errmsg = strerror(errno);
85 ADD_FAILURE() << "Failed to send " << command.length()
86 << " bytes, send() returned " << bytes_sent
87 << " : " << errmsg;
88 return (false);
89 }
90
91 return (true);
92}
93
94bool UnixControlClient::getResponse(std::string& response,
95 const unsigned int timeout_sec) {
96 // Receive response
97 char buf[65536];
98 memset(buf, 0, sizeof(buf));
99 switch (selectCheck(timeout_sec)) {
100 case -1: {
101 const char* errmsg = strerror(errno);
102 ADD_FAILURE() << "getResponse - select failed: " << errmsg;
103 return (false);
104 }
105 case 0:
106 return (false);
107
108 default:
109 break;
110 }
111
112 int bytes_rcvd = recv(socket_fd_, buf, sizeof(buf), 0);
113 if (bytes_rcvd < 0) {
114 const char* errmsg = strerror(errno);
115 ADD_FAILURE() << "Failed to receive a response. recv() returned "
116 << bytes_rcvd << " : " << errmsg;
117 return (false);
118 }
119
120 // Convert the response to a string
121 response = std::string(buf, bytes_rcvd);
122 return (true);
123}
124
125int UnixControlClient::selectCheck(const unsigned int timeout_sec) {
126 if (socket_fd_ < 0) {
127 ADD_FAILURE() << "select check with closed socket";
128 return (-1);
129 }
130 if (socket_fd_ >= FD_SETSIZE) {
131 ADD_FAILURE() << "select check with out of bound socket";
132 return (-1);
133 }
134
135 return (util::selectCheck(socket_fd_, timeout_sec));
136}
137
138}
139}
140}
void disconnectFromServer()
Closes the Control Channel socket.
int socket_fd_
Retains the fd of the open socket.
bool getResponse(std::string &response, const unsigned int timeout_sec=0)
Reads the response text from the open Control Channel.
int selectCheck(const unsigned int timeout_sec)
Uses select to poll the Control Channel for data waiting.
bool sendCommand(const std::string &command)
Sends the given command across the open Control Channel.
bool connectToServer(const std::string &socket_path)
Connects to a Unix socket at the given path.
int selectCheck(const int fd_to_check, const unsigned int timeout_sec)
Defines the logger used by the top-level component of kea-lfc.