xref: /aosp_15_r20/external/openthread/src/posix/platform/daemon.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2021, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker #include "posix/platform/daemon.hpp"
30*cfb92d14SAndroid Build Coastguard Worker 
31*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_ANDROID_ENABLE
32*cfb92d14SAndroid Build Coastguard Worker #include <cutils/sockets.h>
33*cfb92d14SAndroid Build Coastguard Worker #endif
34*cfb92d14SAndroid Build Coastguard Worker #include <fcntl.h>
35*cfb92d14SAndroid Build Coastguard Worker #include <signal.h>
36*cfb92d14SAndroid Build Coastguard Worker #include <stdarg.h>
37*cfb92d14SAndroid Build Coastguard Worker #include <string.h>
38*cfb92d14SAndroid Build Coastguard Worker #include <sys/file.h>
39*cfb92d14SAndroid Build Coastguard Worker #include <sys/socket.h>
40*cfb92d14SAndroid Build Coastguard Worker #include <sys/stat.h>
41*cfb92d14SAndroid Build Coastguard Worker #include <sys/types.h>
42*cfb92d14SAndroid Build Coastguard Worker #include <sys/un.h>
43*cfb92d14SAndroid Build Coastguard Worker #include <unistd.h>
44*cfb92d14SAndroid Build Coastguard Worker 
45*cfb92d14SAndroid Build Coastguard Worker #include <openthread/cli.h>
46*cfb92d14SAndroid Build Coastguard Worker 
47*cfb92d14SAndroid Build Coastguard Worker #include "cli/cli_config.h"
48*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
49*cfb92d14SAndroid Build Coastguard Worker #include "posix/platform/platform-posix.h"
50*cfb92d14SAndroid Build Coastguard Worker 
51*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
52*cfb92d14SAndroid Build Coastguard Worker 
53*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME ".lock"
54*cfb92d14SAndroid Build Coastguard Worker static_assert(sizeof(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME) < sizeof(sockaddr_un::sun_path),
55*cfb92d14SAndroid Build Coastguard Worker               "OpenThread daemon socket name too long!");
56*cfb92d14SAndroid Build Coastguard Worker 
57*cfb92d14SAndroid Build Coastguard Worker namespace ot {
58*cfb92d14SAndroid Build Coastguard Worker namespace Posix {
59*cfb92d14SAndroid Build Coastguard Worker 
60*cfb92d14SAndroid Build Coastguard Worker namespace {
61*cfb92d14SAndroid Build Coastguard Worker 
62*cfb92d14SAndroid Build Coastguard Worker typedef char(Filename)[sizeof(sockaddr_un::sun_path)];
63*cfb92d14SAndroid Build Coastguard Worker 
GetFilename(Filename & aFilename,const char * aPattern)64*cfb92d14SAndroid Build Coastguard Worker void GetFilename(Filename &aFilename, const char *aPattern)
65*cfb92d14SAndroid Build Coastguard Worker {
66*cfb92d14SAndroid Build Coastguard Worker     int         rval;
67*cfb92d14SAndroid Build Coastguard Worker     const char *netIfName = strlen(gNetifName) > 0 ? gNetifName : OPENTHREAD_POSIX_CONFIG_THREAD_NETIF_DEFAULT_NAME;
68*cfb92d14SAndroid Build Coastguard Worker 
69*cfb92d14SAndroid Build Coastguard Worker     rval = snprintf(aFilename, sizeof(aFilename), aPattern, netIfName);
70*cfb92d14SAndroid Build Coastguard Worker     if (rval < 0 && static_cast<size_t>(rval) >= sizeof(aFilename))
71*cfb92d14SAndroid Build Coastguard Worker     {
72*cfb92d14SAndroid Build Coastguard Worker         DieNow(OT_EXIT_INVALID_ARGUMENTS);
73*cfb92d14SAndroid Build Coastguard Worker     }
74*cfb92d14SAndroid Build Coastguard Worker }
75*cfb92d14SAndroid Build Coastguard Worker 
76*cfb92d14SAndroid Build Coastguard Worker } // namespace
77*cfb92d14SAndroid Build Coastguard Worker 
78*cfb92d14SAndroid Build Coastguard Worker const char Daemon::kLogModuleName[] = "Daemon";
79*cfb92d14SAndroid Build Coastguard Worker 
OutputFormat(const char * aFormat,...)80*cfb92d14SAndroid Build Coastguard Worker int Daemon::OutputFormat(const char *aFormat, ...)
81*cfb92d14SAndroid Build Coastguard Worker {
82*cfb92d14SAndroid Build Coastguard Worker     int     ret;
83*cfb92d14SAndroid Build Coastguard Worker     va_list ap;
84*cfb92d14SAndroid Build Coastguard Worker 
85*cfb92d14SAndroid Build Coastguard Worker     va_start(ap, aFormat);
86*cfb92d14SAndroid Build Coastguard Worker     ret = OutputFormatV(aFormat, ap);
87*cfb92d14SAndroid Build Coastguard Worker     va_end(ap);
88*cfb92d14SAndroid Build Coastguard Worker 
89*cfb92d14SAndroid Build Coastguard Worker     return ret;
90*cfb92d14SAndroid Build Coastguard Worker }
91*cfb92d14SAndroid Build Coastguard Worker 
OutputFormatV(const char * aFormat,va_list aArguments)92*cfb92d14SAndroid Build Coastguard Worker int Daemon::OutputFormatV(const char *aFormat, va_list aArguments)
93*cfb92d14SAndroid Build Coastguard Worker {
94*cfb92d14SAndroid Build Coastguard Worker     static constexpr char truncatedMsg[] = "(truncated ...)";
95*cfb92d14SAndroid Build Coastguard Worker     char                  buf[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH];
96*cfb92d14SAndroid Build Coastguard Worker     int                   rval;
97*cfb92d14SAndroid Build Coastguard Worker 
98*cfb92d14SAndroid Build Coastguard Worker     static_assert(sizeof(truncatedMsg) < OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH,
99*cfb92d14SAndroid Build Coastguard Worker                   "OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH is too short!");
100*cfb92d14SAndroid Build Coastguard Worker 
101*cfb92d14SAndroid Build Coastguard Worker     rval = vsnprintf(buf, sizeof(buf), aFormat, aArguments);
102*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(rval >= 0, LogWarn("Failed to format CLI output: %s", strerror(errno)));
103*cfb92d14SAndroid Build Coastguard Worker 
104*cfb92d14SAndroid Build Coastguard Worker     if (rval >= static_cast<int>(sizeof(buf)))
105*cfb92d14SAndroid Build Coastguard Worker     {
106*cfb92d14SAndroid Build Coastguard Worker         rval = static_cast<int>(sizeof(buf) - 1);
107*cfb92d14SAndroid Build Coastguard Worker         memcpy(buf + sizeof(buf) - sizeof(truncatedMsg), truncatedMsg, sizeof(truncatedMsg));
108*cfb92d14SAndroid Build Coastguard Worker     }
109*cfb92d14SAndroid Build Coastguard Worker 
110*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mSessionSocket != -1);
111*cfb92d14SAndroid Build Coastguard Worker 
112*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
113*cfb92d14SAndroid Build Coastguard Worker     // Don't die on SIGPIPE
114*cfb92d14SAndroid Build Coastguard Worker     rval = send(mSessionSocket, buf, static_cast<size_t>(rval), MSG_NOSIGNAL);
115*cfb92d14SAndroid Build Coastguard Worker #else
116*cfb92d14SAndroid Build Coastguard Worker     rval = static_cast<int>(write(mSessionSocket, buf, static_cast<size_t>(rval)));
117*cfb92d14SAndroid Build Coastguard Worker #endif
118*cfb92d14SAndroid Build Coastguard Worker 
119*cfb92d14SAndroid Build Coastguard Worker     if (rval < 0)
120*cfb92d14SAndroid Build Coastguard Worker     {
121*cfb92d14SAndroid Build Coastguard Worker         LogWarn("Failed to write CLI output: %s", strerror(errno));
122*cfb92d14SAndroid Build Coastguard Worker         close(mSessionSocket);
123*cfb92d14SAndroid Build Coastguard Worker         mSessionSocket = -1;
124*cfb92d14SAndroid Build Coastguard Worker     }
125*cfb92d14SAndroid Build Coastguard Worker 
126*cfb92d14SAndroid Build Coastguard Worker exit:
127*cfb92d14SAndroid Build Coastguard Worker     return rval;
128*cfb92d14SAndroid Build Coastguard Worker }
129*cfb92d14SAndroid Build Coastguard Worker 
InitializeSessionSocket(void)130*cfb92d14SAndroid Build Coastguard Worker void Daemon::InitializeSessionSocket(void)
131*cfb92d14SAndroid Build Coastguard Worker {
132*cfb92d14SAndroid Build Coastguard Worker     int newSessionSocket;
133*cfb92d14SAndroid Build Coastguard Worker     int rval;
134*cfb92d14SAndroid Build Coastguard Worker 
135*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit((newSessionSocket = accept(mListenSocket, nullptr, nullptr)) != -1, rval = -1);
136*cfb92d14SAndroid Build Coastguard Worker 
137*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit((rval = fcntl(newSessionSocket, F_GETFD, 0)) != -1);
138*cfb92d14SAndroid Build Coastguard Worker 
139*cfb92d14SAndroid Build Coastguard Worker     rval |= FD_CLOEXEC;
140*cfb92d14SAndroid Build Coastguard Worker 
141*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit((rval = fcntl(newSessionSocket, F_SETFD, rval)) != -1);
142*cfb92d14SAndroid Build Coastguard Worker 
143*cfb92d14SAndroid Build Coastguard Worker #ifndef __linux__
144*cfb92d14SAndroid Build Coastguard Worker     // some platforms (macOS, Solaris) don't have MSG_NOSIGNAL
145*cfb92d14SAndroid Build Coastguard Worker     // SOME of those (macOS, but NOT Solaris) support SO_NOSIGPIPE
146*cfb92d14SAndroid Build Coastguard Worker     // if we have SO_NOSIGPIPE, then set it. Otherwise, we're going
147*cfb92d14SAndroid Build Coastguard Worker     // to simply ignore it.
148*cfb92d14SAndroid Build Coastguard Worker #if defined(SO_NOSIGPIPE)
149*cfb92d14SAndroid Build Coastguard Worker     rval = setsockopt(newSessionSocket, SOL_SOCKET, SO_NOSIGPIPE, &rval, sizeof(rval));
150*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(rval != -1);
151*cfb92d14SAndroid Build Coastguard Worker #else
152*cfb92d14SAndroid Build Coastguard Worker #warning "no support for MSG_NOSIGNAL or SO_NOSIGPIPE"
153*cfb92d14SAndroid Build Coastguard Worker #endif
154*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
155*cfb92d14SAndroid Build Coastguard Worker 
156*cfb92d14SAndroid Build Coastguard Worker     if (mSessionSocket != -1)
157*cfb92d14SAndroid Build Coastguard Worker     {
158*cfb92d14SAndroid Build Coastguard Worker         close(mSessionSocket);
159*cfb92d14SAndroid Build Coastguard Worker     }
160*cfb92d14SAndroid Build Coastguard Worker     mSessionSocket = newSessionSocket;
161*cfb92d14SAndroid Build Coastguard Worker 
162*cfb92d14SAndroid Build Coastguard Worker exit:
163*cfb92d14SAndroid Build Coastguard Worker     if (rval == -1)
164*cfb92d14SAndroid Build Coastguard Worker     {
165*cfb92d14SAndroid Build Coastguard Worker         LogWarn("Failed to initialize session socket: %s", strerror(errno));
166*cfb92d14SAndroid Build Coastguard Worker         if (newSessionSocket != -1)
167*cfb92d14SAndroid Build Coastguard Worker         {
168*cfb92d14SAndroid Build Coastguard Worker             close(newSessionSocket);
169*cfb92d14SAndroid Build Coastguard Worker         }
170*cfb92d14SAndroid Build Coastguard Worker     }
171*cfb92d14SAndroid Build Coastguard Worker     else
172*cfb92d14SAndroid Build Coastguard Worker     {
173*cfb92d14SAndroid Build Coastguard Worker         LogInfo("Session socket is ready");
174*cfb92d14SAndroid Build Coastguard Worker     }
175*cfb92d14SAndroid Build Coastguard Worker }
176*cfb92d14SAndroid Build Coastguard Worker 
177*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_ANDROID_ENABLE
createListenSocketOrDie(void)178*cfb92d14SAndroid Build Coastguard Worker void Daemon::createListenSocketOrDie(void)
179*cfb92d14SAndroid Build Coastguard Worker {
180*cfb92d14SAndroid Build Coastguard Worker     Filename socketFile;
181*cfb92d14SAndroid Build Coastguard Worker 
182*cfb92d14SAndroid Build Coastguard Worker     // Don't use OPENTHREAD_POSIX_DAEMON_SOCKET_NAME because android_get_control_socket
183*cfb92d14SAndroid Build Coastguard Worker     // below already assumes parent /dev/socket dir
184*cfb92d14SAndroid Build Coastguard Worker     GetFilename(socketFile, "ot-daemon/%s.sock");
185*cfb92d14SAndroid Build Coastguard Worker 
186*cfb92d14SAndroid Build Coastguard Worker     // This returns the init-managed stream socket which is already bind to
187*cfb92d14SAndroid Build Coastguard Worker     // /dev/socket/ot-daemon/<interface-name>.sock
188*cfb92d14SAndroid Build Coastguard Worker     mListenSocket = android_get_control_socket(socketFile);
189*cfb92d14SAndroid Build Coastguard Worker 
190*cfb92d14SAndroid Build Coastguard Worker     if (mListenSocket == -1)
191*cfb92d14SAndroid Build Coastguard Worker     {
192*cfb92d14SAndroid Build Coastguard Worker         DieNowWithMessage("android_get_control_socket", OT_EXIT_ERROR_ERRNO);
193*cfb92d14SAndroid Build Coastguard Worker     }
194*cfb92d14SAndroid Build Coastguard Worker }
195*cfb92d14SAndroid Build Coastguard Worker #else
createListenSocketOrDie(void)196*cfb92d14SAndroid Build Coastguard Worker void Daemon::createListenSocketOrDie(void)
197*cfb92d14SAndroid Build Coastguard Worker {
198*cfb92d14SAndroid Build Coastguard Worker     struct sockaddr_un sockname;
199*cfb92d14SAndroid Build Coastguard Worker     int ret;
200*cfb92d14SAndroid Build Coastguard Worker 
201*cfb92d14SAndroid Build Coastguard Worker     class AllowAllGuard
202*cfb92d14SAndroid Build Coastguard Worker     {
203*cfb92d14SAndroid Build Coastguard Worker     public:
204*cfb92d14SAndroid Build Coastguard Worker         AllowAllGuard(void)
205*cfb92d14SAndroid Build Coastguard Worker         {
206*cfb92d14SAndroid Build Coastguard Worker             const char *allowAll = getenv("OT_DAEMON_ALLOW_ALL");
207*cfb92d14SAndroid Build Coastguard Worker             mAllowAll = (allowAll != nullptr && strcmp("1", allowAll) == 0);
208*cfb92d14SAndroid Build Coastguard Worker 
209*cfb92d14SAndroid Build Coastguard Worker             if (mAllowAll)
210*cfb92d14SAndroid Build Coastguard Worker             {
211*cfb92d14SAndroid Build Coastguard Worker                 mMode = umask(0);
212*cfb92d14SAndroid Build Coastguard Worker             }
213*cfb92d14SAndroid Build Coastguard Worker         }
214*cfb92d14SAndroid Build Coastguard Worker         ~AllowAllGuard(void)
215*cfb92d14SAndroid Build Coastguard Worker         {
216*cfb92d14SAndroid Build Coastguard Worker             if (mAllowAll)
217*cfb92d14SAndroid Build Coastguard Worker             {
218*cfb92d14SAndroid Build Coastguard Worker                 umask(mMode);
219*cfb92d14SAndroid Build Coastguard Worker             }
220*cfb92d14SAndroid Build Coastguard Worker         }
221*cfb92d14SAndroid Build Coastguard Worker 
222*cfb92d14SAndroid Build Coastguard Worker     private:
223*cfb92d14SAndroid Build Coastguard Worker         bool mAllowAll = false;
224*cfb92d14SAndroid Build Coastguard Worker         mode_t mMode = 0;
225*cfb92d14SAndroid Build Coastguard Worker     };
226*cfb92d14SAndroid Build Coastguard Worker 
227*cfb92d14SAndroid Build Coastguard Worker     mListenSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0, kSocketNonBlock);
228*cfb92d14SAndroid Build Coastguard Worker 
229*cfb92d14SAndroid Build Coastguard Worker     if (mListenSocket == -1)
230*cfb92d14SAndroid Build Coastguard Worker     {
231*cfb92d14SAndroid Build Coastguard Worker         DieNow(OT_EXIT_FAILURE);
232*cfb92d14SAndroid Build Coastguard Worker     }
233*cfb92d14SAndroid Build Coastguard Worker 
234*cfb92d14SAndroid Build Coastguard Worker     {
235*cfb92d14SAndroid Build Coastguard Worker         static_assert(sizeof(OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK) == sizeof(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME),
236*cfb92d14SAndroid Build Coastguard Worker                       "sock and lock file name pattern should have the same length!");
237*cfb92d14SAndroid Build Coastguard Worker         Filename lockfile;
238*cfb92d14SAndroid Build Coastguard Worker 
239*cfb92d14SAndroid Build Coastguard Worker         GetFilename(lockfile, OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK);
240*cfb92d14SAndroid Build Coastguard Worker 
241*cfb92d14SAndroid Build Coastguard Worker         mDaemonLock = open(lockfile, O_CREAT | O_RDONLY | O_CLOEXEC, 0600);
242*cfb92d14SAndroid Build Coastguard Worker     }
243*cfb92d14SAndroid Build Coastguard Worker 
244*cfb92d14SAndroid Build Coastguard Worker     if (mDaemonLock == -1)
245*cfb92d14SAndroid Build Coastguard Worker     {
246*cfb92d14SAndroid Build Coastguard Worker         DieNowWithMessage("open", OT_EXIT_ERROR_ERRNO);
247*cfb92d14SAndroid Build Coastguard Worker     }
248*cfb92d14SAndroid Build Coastguard Worker 
249*cfb92d14SAndroid Build Coastguard Worker     if (flock(mDaemonLock, LOCK_EX | LOCK_NB) == -1)
250*cfb92d14SAndroid Build Coastguard Worker     {
251*cfb92d14SAndroid Build Coastguard Worker         DieNowWithMessage("flock", OT_EXIT_ERROR_ERRNO);
252*cfb92d14SAndroid Build Coastguard Worker     }
253*cfb92d14SAndroid Build Coastguard Worker 
254*cfb92d14SAndroid Build Coastguard Worker     memset(&sockname, 0, sizeof(struct sockaddr_un));
255*cfb92d14SAndroid Build Coastguard Worker 
256*cfb92d14SAndroid Build Coastguard Worker     sockname.sun_family = AF_UNIX;
257*cfb92d14SAndroid Build Coastguard Worker     GetFilename(sockname.sun_path, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
258*cfb92d14SAndroid Build Coastguard Worker     (void)unlink(sockname.sun_path);
259*cfb92d14SAndroid Build Coastguard Worker 
260*cfb92d14SAndroid Build Coastguard Worker     {
261*cfb92d14SAndroid Build Coastguard Worker         AllowAllGuard allowAllGuard;
262*cfb92d14SAndroid Build Coastguard Worker 
263*cfb92d14SAndroid Build Coastguard Worker         ret = bind(mListenSocket, reinterpret_cast<const struct sockaddr *>(&sockname), sizeof(struct sockaddr_un));
264*cfb92d14SAndroid Build Coastguard Worker     }
265*cfb92d14SAndroid Build Coastguard Worker 
266*cfb92d14SAndroid Build Coastguard Worker     if (ret == -1)
267*cfb92d14SAndroid Build Coastguard Worker     {
268*cfb92d14SAndroid Build Coastguard Worker         DieNowWithMessage("bind", OT_EXIT_ERROR_ERRNO);
269*cfb92d14SAndroid Build Coastguard Worker     }
270*cfb92d14SAndroid Build Coastguard Worker }
271*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_POSIX_CONFIG_ANDROID_ENABLE
272*cfb92d14SAndroid Build Coastguard Worker 
SetUp(void)273*cfb92d14SAndroid Build Coastguard Worker void Daemon::SetUp(void)
274*cfb92d14SAndroid Build Coastguard Worker {
275*cfb92d14SAndroid Build Coastguard Worker     int ret;
276*cfb92d14SAndroid Build Coastguard Worker 
277*cfb92d14SAndroid Build Coastguard Worker     // This allows implementing pseudo reset.
278*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mListenSocket == -1);
279*cfb92d14SAndroid Build Coastguard Worker     createListenSocketOrDie();
280*cfb92d14SAndroid Build Coastguard Worker 
281*cfb92d14SAndroid Build Coastguard Worker     //
282*cfb92d14SAndroid Build Coastguard Worker     // only accept 1 connection.
283*cfb92d14SAndroid Build Coastguard Worker     //
284*cfb92d14SAndroid Build Coastguard Worker     ret = listen(mListenSocket, 1);
285*cfb92d14SAndroid Build Coastguard Worker     if (ret == -1)
286*cfb92d14SAndroid Build Coastguard Worker     {
287*cfb92d14SAndroid Build Coastguard Worker         DieNowWithMessage("listen", OT_EXIT_ERROR_ERRNO);
288*cfb92d14SAndroid Build Coastguard Worker     }
289*cfb92d14SAndroid Build Coastguard Worker 
290*cfb92d14SAndroid Build Coastguard Worker exit:
291*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE
292*cfb92d14SAndroid Build Coastguard Worker     otSysCliInitUsingDaemon(gInstance);
293*cfb92d14SAndroid Build Coastguard Worker #endif
294*cfb92d14SAndroid Build Coastguard Worker 
295*cfb92d14SAndroid Build Coastguard Worker     Mainloop::Manager::Get().Add(*this);
296*cfb92d14SAndroid Build Coastguard Worker 
297*cfb92d14SAndroid Build Coastguard Worker     return;
298*cfb92d14SAndroid Build Coastguard Worker }
299*cfb92d14SAndroid Build Coastguard Worker 
TearDown(void)300*cfb92d14SAndroid Build Coastguard Worker void Daemon::TearDown(void)
301*cfb92d14SAndroid Build Coastguard Worker {
302*cfb92d14SAndroid Build Coastguard Worker     Mainloop::Manager::Get().Remove(*this);
303*cfb92d14SAndroid Build Coastguard Worker 
304*cfb92d14SAndroid Build Coastguard Worker     if (mSessionSocket != -1)
305*cfb92d14SAndroid Build Coastguard Worker     {
306*cfb92d14SAndroid Build Coastguard Worker         close(mSessionSocket);
307*cfb92d14SAndroid Build Coastguard Worker         mSessionSocket = -1;
308*cfb92d14SAndroid Build Coastguard Worker     }
309*cfb92d14SAndroid Build Coastguard Worker 
310*cfb92d14SAndroid Build Coastguard Worker #if !OPENTHREAD_POSIX_CONFIG_ANDROID_ENABLE
311*cfb92d14SAndroid Build Coastguard Worker     // The `mListenSocket` is managed by `init` on Android
312*cfb92d14SAndroid Build Coastguard Worker     if (mListenSocket != -1)
313*cfb92d14SAndroid Build Coastguard Worker     {
314*cfb92d14SAndroid Build Coastguard Worker         close(mListenSocket);
315*cfb92d14SAndroid Build Coastguard Worker         mListenSocket = -1;
316*cfb92d14SAndroid Build Coastguard Worker     }
317*cfb92d14SAndroid Build Coastguard Worker 
318*cfb92d14SAndroid Build Coastguard Worker     if (gPlatResetReason != OT_PLAT_RESET_REASON_SOFTWARE)
319*cfb92d14SAndroid Build Coastguard Worker     {
320*cfb92d14SAndroid Build Coastguard Worker         Filename sockfile;
321*cfb92d14SAndroid Build Coastguard Worker 
322*cfb92d14SAndroid Build Coastguard Worker         GetFilename(sockfile, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
323*cfb92d14SAndroid Build Coastguard Worker         LogDebg("Removing daemon socket: %s", sockfile);
324*cfb92d14SAndroid Build Coastguard Worker         (void)unlink(sockfile);
325*cfb92d14SAndroid Build Coastguard Worker     }
326*cfb92d14SAndroid Build Coastguard Worker 
327*cfb92d14SAndroid Build Coastguard Worker     if (mDaemonLock != -1)
328*cfb92d14SAndroid Build Coastguard Worker     {
329*cfb92d14SAndroid Build Coastguard Worker         (void)flock(mDaemonLock, LOCK_UN);
330*cfb92d14SAndroid Build Coastguard Worker         close(mDaemonLock);
331*cfb92d14SAndroid Build Coastguard Worker         mDaemonLock = -1;
332*cfb92d14SAndroid Build Coastguard Worker     }
333*cfb92d14SAndroid Build Coastguard Worker #endif
334*cfb92d14SAndroid Build Coastguard Worker }
335*cfb92d14SAndroid Build Coastguard Worker 
Update(otSysMainloopContext & aContext)336*cfb92d14SAndroid Build Coastguard Worker void Daemon::Update(otSysMainloopContext &aContext)
337*cfb92d14SAndroid Build Coastguard Worker {
338*cfb92d14SAndroid Build Coastguard Worker     if (mListenSocket != -1)
339*cfb92d14SAndroid Build Coastguard Worker     {
340*cfb92d14SAndroid Build Coastguard Worker         FD_SET(mListenSocket, &aContext.mReadFdSet);
341*cfb92d14SAndroid Build Coastguard Worker         FD_SET(mListenSocket, &aContext.mErrorFdSet);
342*cfb92d14SAndroid Build Coastguard Worker 
343*cfb92d14SAndroid Build Coastguard Worker         if (aContext.mMaxFd < mListenSocket)
344*cfb92d14SAndroid Build Coastguard Worker         {
345*cfb92d14SAndroid Build Coastguard Worker             aContext.mMaxFd = mListenSocket;
346*cfb92d14SAndroid Build Coastguard Worker         }
347*cfb92d14SAndroid Build Coastguard Worker     }
348*cfb92d14SAndroid Build Coastguard Worker 
349*cfb92d14SAndroid Build Coastguard Worker     if (mSessionSocket != -1)
350*cfb92d14SAndroid Build Coastguard Worker     {
351*cfb92d14SAndroid Build Coastguard Worker         FD_SET(mSessionSocket, &aContext.mReadFdSet);
352*cfb92d14SAndroid Build Coastguard Worker         FD_SET(mSessionSocket, &aContext.mErrorFdSet);
353*cfb92d14SAndroid Build Coastguard Worker 
354*cfb92d14SAndroid Build Coastguard Worker         if (aContext.mMaxFd < mSessionSocket)
355*cfb92d14SAndroid Build Coastguard Worker         {
356*cfb92d14SAndroid Build Coastguard Worker             aContext.mMaxFd = mSessionSocket;
357*cfb92d14SAndroid Build Coastguard Worker         }
358*cfb92d14SAndroid Build Coastguard Worker     }
359*cfb92d14SAndroid Build Coastguard Worker 
360*cfb92d14SAndroid Build Coastguard Worker     return;
361*cfb92d14SAndroid Build Coastguard Worker }
362*cfb92d14SAndroid Build Coastguard Worker 
Process(const otSysMainloopContext & aContext)363*cfb92d14SAndroid Build Coastguard Worker void Daemon::Process(const otSysMainloopContext &aContext)
364*cfb92d14SAndroid Build Coastguard Worker {
365*cfb92d14SAndroid Build Coastguard Worker     ssize_t rval;
366*cfb92d14SAndroid Build Coastguard Worker 
367*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mListenSocket != -1);
368*cfb92d14SAndroid Build Coastguard Worker 
369*cfb92d14SAndroid Build Coastguard Worker     if (FD_ISSET(mListenSocket, &aContext.mErrorFdSet))
370*cfb92d14SAndroid Build Coastguard Worker     {
371*cfb92d14SAndroid Build Coastguard Worker         DieNowWithMessage("daemon socket error", OT_EXIT_FAILURE);
372*cfb92d14SAndroid Build Coastguard Worker     }
373*cfb92d14SAndroid Build Coastguard Worker     else if (FD_ISSET(mListenSocket, &aContext.mReadFdSet))
374*cfb92d14SAndroid Build Coastguard Worker     {
375*cfb92d14SAndroid Build Coastguard Worker         InitializeSessionSocket();
376*cfb92d14SAndroid Build Coastguard Worker     }
377*cfb92d14SAndroid Build Coastguard Worker 
378*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mSessionSocket != -1);
379*cfb92d14SAndroid Build Coastguard Worker 
380*cfb92d14SAndroid Build Coastguard Worker     if (FD_ISSET(mSessionSocket, &aContext.mErrorFdSet))
381*cfb92d14SAndroid Build Coastguard Worker     {
382*cfb92d14SAndroid Build Coastguard Worker         close(mSessionSocket);
383*cfb92d14SAndroid Build Coastguard Worker         mSessionSocket = -1;
384*cfb92d14SAndroid Build Coastguard Worker     }
385*cfb92d14SAndroid Build Coastguard Worker     else if (FD_ISSET(mSessionSocket, &aContext.mReadFdSet))
386*cfb92d14SAndroid Build Coastguard Worker     {
387*cfb92d14SAndroid Build Coastguard Worker         uint8_t buffer[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH];
388*cfb92d14SAndroid Build Coastguard Worker 
389*cfb92d14SAndroid Build Coastguard Worker         // leave 1 byte for the null terminator
390*cfb92d14SAndroid Build Coastguard Worker         rval = read(mSessionSocket, buffer, sizeof(buffer) - 1);
391*cfb92d14SAndroid Build Coastguard Worker 
392*cfb92d14SAndroid Build Coastguard Worker         if (rval > 0)
393*cfb92d14SAndroid Build Coastguard Worker         {
394*cfb92d14SAndroid Build Coastguard Worker             buffer[rval] = '\0';
395*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE
396*cfb92d14SAndroid Build Coastguard Worker             otCliInputLine(reinterpret_cast<char *>(buffer));
397*cfb92d14SAndroid Build Coastguard Worker #else
398*cfb92d14SAndroid Build Coastguard Worker             OutputFormat("Error: CLI is disabled!\n");
399*cfb92d14SAndroid Build Coastguard Worker #endif
400*cfb92d14SAndroid Build Coastguard Worker         }
401*cfb92d14SAndroid Build Coastguard Worker         else
402*cfb92d14SAndroid Build Coastguard Worker         {
403*cfb92d14SAndroid Build Coastguard Worker             if (rval < 0)
404*cfb92d14SAndroid Build Coastguard Worker             {
405*cfb92d14SAndroid Build Coastguard Worker                 LogWarn("Daemon read: %s", strerror(errno));
406*cfb92d14SAndroid Build Coastguard Worker             }
407*cfb92d14SAndroid Build Coastguard Worker             close(mSessionSocket);
408*cfb92d14SAndroid Build Coastguard Worker             mSessionSocket = -1;
409*cfb92d14SAndroid Build Coastguard Worker         }
410*cfb92d14SAndroid Build Coastguard Worker     }
411*cfb92d14SAndroid Build Coastguard Worker 
412*cfb92d14SAndroid Build Coastguard Worker exit:
413*cfb92d14SAndroid Build Coastguard Worker     return;
414*cfb92d14SAndroid Build Coastguard Worker }
415*cfb92d14SAndroid Build Coastguard Worker 
Get(void)416*cfb92d14SAndroid Build Coastguard Worker Daemon &Daemon::Get(void)
417*cfb92d14SAndroid Build Coastguard Worker {
418*cfb92d14SAndroid Build Coastguard Worker     static Daemon sInstance;
419*cfb92d14SAndroid Build Coastguard Worker 
420*cfb92d14SAndroid Build Coastguard Worker     return sInstance;
421*cfb92d14SAndroid Build Coastguard Worker }
422*cfb92d14SAndroid Build Coastguard Worker 
423*cfb92d14SAndroid Build Coastguard Worker } // namespace Posix
424*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
425*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
426