• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2025, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #define OTBR_LOG_TAG "CLI_DAEMON"
30 
31 #include "cli_daemon.hpp"
32 
33 #include <fcntl.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <sys/file.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/un.h>
42 #include <unistd.h>
43 
44 #include <openthread/cli.h>
45 
46 #include "utils/socket_utils.hpp"
47 
48 namespace otbr {
49 
50 static constexpr char kDefaultNetIfName[] = "wpan0";
51 static constexpr char kSocketBaseName[]   = "/run/openthread-";
52 static constexpr char kSocketSuffix[]     = ".sock";
53 static constexpr char kSocketLockSuffix[] = ".lock";
54 
55 static constexpr size_t kMaxSocketFilenameLength = sizeof(sockaddr_un::sun_path) - 1;
56 
GetSocketFilename(const char * aSuffix) const57 std::string CliDaemon::GetSocketFilename(const char *aSuffix) const
58 {
59     std::string fileName;
60     std::string netIfName = mNetifName.empty() ? kDefaultNetIfName : mNetifName;
61 
62     fileName = kSocketBaseName + netIfName + aSuffix;
63     VerifyOrDie(fileName.size() <= kMaxSocketFilenameLength, otbrErrorString(OTBR_ERROR_INVALID_ARGS));
64 
65     return fileName;
66 }
67 
CliDaemon(void)68 CliDaemon::CliDaemon(void)
69     : mListenSocket(-1)
70     , mDaemonLock(-1)
71 {
72 }
73 
CreateListenSocketOrDie(void)74 void CliDaemon::CreateListenSocketOrDie(void)
75 {
76     struct sockaddr_un sockname;
77 
78     mListenSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0, kSocketNonBlock);
79     VerifyOrDie(mListenSocket != -1, strerror(errno));
80 
81     std::string lockfile = GetSocketFilename(kSocketLockSuffix);
82     mDaemonLock          = open(lockfile.c_str(), O_CREAT | O_RDONLY | O_CLOEXEC, 0600);
83     VerifyOrDie(mDaemonLock != -1, strerror(errno));
84 
85     VerifyOrDie(flock(mDaemonLock, LOCK_EX | LOCK_NB) != -1, strerror(errno));
86 
87     std::string socketfile = GetSocketFilename(kSocketSuffix);
88     memset(&sockname, 0, sizeof(struct sockaddr_un));
89 
90     sockname.sun_family = AF_UNIX;
91     strncpy(sockname.sun_path, socketfile.c_str(), sizeof(sockname.sun_path) - 1);
92     OTBR_UNUSED_VARIABLE(unlink(sockname.sun_path));
93 
94     VerifyOrDie(bind(mListenSocket, reinterpret_cast<const struct sockaddr *>(&sockname), sizeof(struct sockaddr_un)) !=
95                     -1,
96                 strerror(errno));
97 }
98 
Init(const std::string & aNetIfName)99 void CliDaemon::Init(const std::string &aNetIfName)
100 {
101     // This allows implementing pseudo reset.
102     VerifyOrExit(mListenSocket == -1);
103 
104     mNetifName = aNetIfName;
105     CreateListenSocketOrDie();
106 
107     //
108     // only accept 1 connection.
109     //
110     VerifyOrDie(listen(mListenSocket, 1) != -1, strerror(errno));
111 
112 exit:
113     return;
114 }
115 
116 } // namespace otbr
117