1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "faultloggerd_socket.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <cstddef> 19800b99b8Sopenharmony_ci#include <cstdio> 20800b99b8Sopenharmony_ci#include <securec.h> 21800b99b8Sopenharmony_ci#include <string> 22800b99b8Sopenharmony_ci#include <unistd.h> 23800b99b8Sopenharmony_ci 24800b99b8Sopenharmony_ci#include <sys/socket.h> 25800b99b8Sopenharmony_ci#include <sys/stat.h> 26800b99b8Sopenharmony_ci#include <sys/time.h> 27800b99b8Sopenharmony_ci#include <sys/un.h> 28800b99b8Sopenharmony_ci 29800b99b8Sopenharmony_ci#include "dfx_define.h" 30800b99b8Sopenharmony_ci#include "dfx_log.h" 31800b99b8Sopenharmony_ci#include "init_socket.h" 32800b99b8Sopenharmony_ci 33800b99b8Sopenharmony_cibool StartConnect(int& sockfd, const char* path, const int timeout) 34800b99b8Sopenharmony_ci{ 35800b99b8Sopenharmony_ci bool ret = false; 36800b99b8Sopenharmony_ci if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { 37800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to socket, errno(%{public}d)", __func__, errno); 38800b99b8Sopenharmony_ci return ret; 39800b99b8Sopenharmony_ci } 40800b99b8Sopenharmony_ci 41800b99b8Sopenharmony_ci do { 42800b99b8Sopenharmony_ci if (timeout > 0) { 43800b99b8Sopenharmony_ci struct timeval timev = { 44800b99b8Sopenharmony_ci timeout, 45800b99b8Sopenharmony_ci 0 46800b99b8Sopenharmony_ci }; 47800b99b8Sopenharmony_ci void* pTimev = &timev; 48800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, \ 49800b99b8Sopenharmony_ci static_cast<const char*>(pTimev), sizeof(timev))) != 0) { 50800b99b8Sopenharmony_ci DFXLOGE("setsockopt(%{public}d) SO_RCVTIMEO error, errno(%{public}d).", sockfd, errno); 51800b99b8Sopenharmony_ci } 52800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, \ 53800b99b8Sopenharmony_ci static_cast<const char*>(pTimev), sizeof(timev))) != 0) { 54800b99b8Sopenharmony_ci DFXLOGE("setsockopt(%{public}d) SO_SNDTIMEO error, errno(%{public}d).", sockfd, errno); 55800b99b8Sopenharmony_ci } 56800b99b8Sopenharmony_ci } 57800b99b8Sopenharmony_ci 58800b99b8Sopenharmony_ci std::string fullPath = std::string(FAULTLOGGERD_SOCK_BASE_PATH) + std::string(path); 59800b99b8Sopenharmony_ci struct sockaddr_un server; 60800b99b8Sopenharmony_ci (void)memset_s(&server, sizeof(server), 0, sizeof(server)); 61800b99b8Sopenharmony_ci server.sun_family = AF_LOCAL; 62800b99b8Sopenharmony_ci errno_t err = strncpy_s(server.sun_path, sizeof(server.sun_path), fullPath.c_str(), 63800b99b8Sopenharmony_ci sizeof(server.sun_path) - 1); 64800b99b8Sopenharmony_ci if (err != EOK) { 65800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: strncpy failed, err = %{public}d.", __func__, (int)err); 66800b99b8Sopenharmony_ci break; 67800b99b8Sopenharmony_ci } 68800b99b8Sopenharmony_ci 69800b99b8Sopenharmony_ci int len = static_cast<int>(offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path) + 1); 70800b99b8Sopenharmony_ci int connected = OHOS_TEMP_FAILURE_RETRY(connect(sockfd, reinterpret_cast<struct sockaddr *>(&server), len)); 71800b99b8Sopenharmony_ci if (connected < 0) { 72800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: connect failed, errno = %{public}d.", __func__, errno); 73800b99b8Sopenharmony_ci break; 74800b99b8Sopenharmony_ci } 75800b99b8Sopenharmony_ci 76800b99b8Sopenharmony_ci ret = true; 77800b99b8Sopenharmony_ci } while (false); 78800b99b8Sopenharmony_ci 79800b99b8Sopenharmony_ci if (!ret) { 80800b99b8Sopenharmony_ci close(sockfd); 81800b99b8Sopenharmony_ci } 82800b99b8Sopenharmony_ci return ret; 83800b99b8Sopenharmony_ci} 84800b99b8Sopenharmony_ci 85800b99b8Sopenharmony_cistatic bool GetServerSocket(int& sockfd, const char* name) 86800b99b8Sopenharmony_ci{ 87800b99b8Sopenharmony_ci sockfd = OHOS_TEMP_FAILURE_RETRY(socket(AF_LOCAL, SOCK_STREAM, 0)); 88800b99b8Sopenharmony_ci if (sockfd < 0) { 89800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to create socket, errno(%{public}d)", __func__, errno); 90800b99b8Sopenharmony_ci return false; 91800b99b8Sopenharmony_ci } 92800b99b8Sopenharmony_ci 93800b99b8Sopenharmony_ci std::string path = std::string(FAULTLOGGERD_SOCK_BASE_PATH) + std::string(name); 94800b99b8Sopenharmony_ci struct sockaddr_un server; 95800b99b8Sopenharmony_ci (void)memset_s(&server, sizeof(server), 0, sizeof(server)); 96800b99b8Sopenharmony_ci server.sun_family = AF_LOCAL; 97800b99b8Sopenharmony_ci if (strncpy_s(server.sun_path, sizeof(server.sun_path), path.c_str(), sizeof(server.sun_path) - 1) != 0) { 98800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: strncpy failed.", __func__); 99800b99b8Sopenharmony_ci return false; 100800b99b8Sopenharmony_ci } 101800b99b8Sopenharmony_ci 102800b99b8Sopenharmony_ci chmod(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IWOTH); 103800b99b8Sopenharmony_ci unlink(path.c_str()); 104800b99b8Sopenharmony_ci 105800b99b8Sopenharmony_ci int optval = 1; 106800b99b8Sopenharmony_ci int ret = OHOS_TEMP_FAILURE_RETRY(setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval))); 107800b99b8Sopenharmony_ci if (ret < 0) { 108800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to set socket option, errno(%{public}d)", __func__, errno); 109800b99b8Sopenharmony_ci return false; 110800b99b8Sopenharmony_ci } 111800b99b8Sopenharmony_ci 112800b99b8Sopenharmony_ci if (bind(sockfd, reinterpret_cast<struct sockaddr *>(&server), 113800b99b8Sopenharmony_ci offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path)) < 0) { 114800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to bind socket, errno(%{public}d)", __func__, errno); 115800b99b8Sopenharmony_ci return false; 116800b99b8Sopenharmony_ci } 117800b99b8Sopenharmony_ci 118800b99b8Sopenharmony_ci return true; 119800b99b8Sopenharmony_ci} 120800b99b8Sopenharmony_ci 121800b99b8Sopenharmony_cibool StartListen(int& sockfd, const char* name, const int listenCnt) 122800b99b8Sopenharmony_ci{ 123800b99b8Sopenharmony_ci if (name == nullptr) { 124800b99b8Sopenharmony_ci return false; 125800b99b8Sopenharmony_ci } 126800b99b8Sopenharmony_ci sockfd = GetControlSocket(name); 127800b99b8Sopenharmony_ci if (sockfd < 0) { 128800b99b8Sopenharmony_ci DFXLOGW("%{public}s :: Failed to get socket fd by cfg", __func__); 129800b99b8Sopenharmony_ci if (GetServerSocket(sockfd, name) == false) { 130800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to get socket fd by path", __func__); 131800b99b8Sopenharmony_ci return false; 132800b99b8Sopenharmony_ci } 133800b99b8Sopenharmony_ci } 134800b99b8Sopenharmony_ci 135800b99b8Sopenharmony_ci if (listen(sockfd, listenCnt) < 0) { 136800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to listen socket, errno(%{public}d)", __func__, errno); 137800b99b8Sopenharmony_ci close(sockfd); 138800b99b8Sopenharmony_ci sockfd = -1; 139800b99b8Sopenharmony_ci return false; 140800b99b8Sopenharmony_ci } 141800b99b8Sopenharmony_ci 142800b99b8Sopenharmony_ci DFXLOGI("%{public}s :: success to listen socket", __func__); 143800b99b8Sopenharmony_ci return true; 144800b99b8Sopenharmony_ci} 145800b99b8Sopenharmony_ci 146800b99b8Sopenharmony_cistatic bool RecvMsgFromSocket(int sockfd, unsigned char* data, size_t& len) 147800b99b8Sopenharmony_ci{ 148800b99b8Sopenharmony_ci bool ret = false; 149800b99b8Sopenharmony_ci if ((sockfd < 0) || (data == nullptr)) { 150800b99b8Sopenharmony_ci return ret; 151800b99b8Sopenharmony_ci } 152800b99b8Sopenharmony_ci 153800b99b8Sopenharmony_ci do { 154800b99b8Sopenharmony_ci struct msghdr msgh; 155800b99b8Sopenharmony_ci (void)memset_s(&msgh, sizeof(msgh), 0, sizeof(msgh)); 156800b99b8Sopenharmony_ci char msgBuffer[SOCKET_BUFFER_SIZE] = { 0 }; 157800b99b8Sopenharmony_ci struct iovec iov = { 158800b99b8Sopenharmony_ci .iov_base = msgBuffer, 159800b99b8Sopenharmony_ci .iov_len = sizeof(msgBuffer) 160800b99b8Sopenharmony_ci }; 161800b99b8Sopenharmony_ci msgh.msg_iov = &iov; 162800b99b8Sopenharmony_ci msgh.msg_iovlen = 1; 163800b99b8Sopenharmony_ci 164800b99b8Sopenharmony_ci char ctlBuffer[SOCKET_BUFFER_SIZE] = { 0 }; 165800b99b8Sopenharmony_ci msgh.msg_control = ctlBuffer; 166800b99b8Sopenharmony_ci msgh.msg_controllen = sizeof(ctlBuffer); 167800b99b8Sopenharmony_ci 168800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(recvmsg(sockfd, &msgh, 0)) < 0) { 169800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to recv message, errno(%{public}d)", __func__, errno); 170800b99b8Sopenharmony_ci break; 171800b99b8Sopenharmony_ci } 172800b99b8Sopenharmony_ci 173800b99b8Sopenharmony_ci struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh); 174800b99b8Sopenharmony_ci if (cmsg == nullptr) { 175800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Invalid message", __func__); 176800b99b8Sopenharmony_ci break; 177800b99b8Sopenharmony_ci } 178800b99b8Sopenharmony_ci 179800b99b8Sopenharmony_ci len = cmsg->cmsg_len - sizeof(struct cmsghdr); 180800b99b8Sopenharmony_ci if (memcpy_s(data, len, CMSG_DATA(cmsg), len) != 0) { 181800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: memcpy error", __func__); 182800b99b8Sopenharmony_ci break; 183800b99b8Sopenharmony_ci } 184800b99b8Sopenharmony_ci 185800b99b8Sopenharmony_ci ret = true; 186800b99b8Sopenharmony_ci } while (false); 187800b99b8Sopenharmony_ci return ret; 188800b99b8Sopenharmony_ci} 189800b99b8Sopenharmony_ci 190800b99b8Sopenharmony_cibool RecvMsgCredFromSocket(int sockfd, struct ucred* pucred) 191800b99b8Sopenharmony_ci{ 192800b99b8Sopenharmony_ci bool ret = false; 193800b99b8Sopenharmony_ci if ((sockfd < 0) || (pucred == nullptr)) { 194800b99b8Sopenharmony_ci return ret; 195800b99b8Sopenharmony_ci } 196800b99b8Sopenharmony_ci 197800b99b8Sopenharmony_ci do { 198800b99b8Sopenharmony_ci struct msghdr msgh; 199800b99b8Sopenharmony_ci (void)memset_s(&msgh, sizeof(msgh), 0, sizeof(msgh)); 200800b99b8Sopenharmony_ci union { 201800b99b8Sopenharmony_ci char buf[CMSG_SPACE(sizeof(struct ucred))]; 202800b99b8Sopenharmony_ci 203800b99b8Sopenharmony_ci /* Space large enough to hold a 'ucred' structure */ 204800b99b8Sopenharmony_ci struct cmsghdr align; 205800b99b8Sopenharmony_ci } controlMsg; 206800b99b8Sopenharmony_ci 207800b99b8Sopenharmony_ci msgh.msg_name = nullptr; 208800b99b8Sopenharmony_ci msgh.msg_namelen = 0; 209800b99b8Sopenharmony_ci 210800b99b8Sopenharmony_ci int data; 211800b99b8Sopenharmony_ci struct iovec iov = { 212800b99b8Sopenharmony_ci .iov_base = &data, 213800b99b8Sopenharmony_ci .iov_len = sizeof(data) 214800b99b8Sopenharmony_ci }; 215800b99b8Sopenharmony_ci msgh.msg_iov = &iov; 216800b99b8Sopenharmony_ci msgh.msg_iovlen = 1; 217800b99b8Sopenharmony_ci 218800b99b8Sopenharmony_ci msgh.msg_control = controlMsg.buf; 219800b99b8Sopenharmony_ci msgh.msg_controllen = sizeof(controlMsg.buf); 220800b99b8Sopenharmony_ci 221800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(recvmsg(sockfd, &msgh, 0)) < 0) { 222800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to recv message, errno(%{public}d)", __func__, errno); 223800b99b8Sopenharmony_ci break; 224800b99b8Sopenharmony_ci } 225800b99b8Sopenharmony_ci 226800b99b8Sopenharmony_ci struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh); 227800b99b8Sopenharmony_ci if (cmsg == nullptr) { 228800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Invalid message", __func__); 229800b99b8Sopenharmony_ci break; 230800b99b8Sopenharmony_ci } 231800b99b8Sopenharmony_ci 232800b99b8Sopenharmony_ci if (memcpy_s(pucred, sizeof(struct ucred), CMSG_DATA(cmsg), sizeof(struct ucred)) != 0) { 233800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: memcpy error", __func__); 234800b99b8Sopenharmony_ci break; 235800b99b8Sopenharmony_ci } 236800b99b8Sopenharmony_ci 237800b99b8Sopenharmony_ci ret = true; 238800b99b8Sopenharmony_ci } while (false); 239800b99b8Sopenharmony_ci return ret; 240800b99b8Sopenharmony_ci} 241800b99b8Sopenharmony_ci 242800b99b8Sopenharmony_cibool SendMsgIovToSocket(int sockfd, void *iovBase, const int iovLen) 243800b99b8Sopenharmony_ci{ 244800b99b8Sopenharmony_ci if ((sockfd < 0) || (iovBase == nullptr) || (iovLen == 0)) { 245800b99b8Sopenharmony_ci return false; 246800b99b8Sopenharmony_ci } 247800b99b8Sopenharmony_ci 248800b99b8Sopenharmony_ci struct msghdr msgh; 249800b99b8Sopenharmony_ci (void)memset_s(&msgh, sizeof(msgh), 0, sizeof(msgh)); 250800b99b8Sopenharmony_ci msgh.msg_name = nullptr; 251800b99b8Sopenharmony_ci msgh.msg_namelen = 0; 252800b99b8Sopenharmony_ci 253800b99b8Sopenharmony_ci struct iovec iov; 254800b99b8Sopenharmony_ci iov.iov_base = iovBase; 255800b99b8Sopenharmony_ci iov.iov_len = iovLen; 256800b99b8Sopenharmony_ci msgh.msg_iov = &iov; 257800b99b8Sopenharmony_ci msgh.msg_iovlen = 1; 258800b99b8Sopenharmony_ci 259800b99b8Sopenharmony_ci msgh.msg_control = nullptr; 260800b99b8Sopenharmony_ci msgh.msg_controllen = 0; 261800b99b8Sopenharmony_ci 262800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(sendmsg(sockfd, &msgh, 0)) < 0) { 263800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to send message, errno(%{public}d).", __func__, errno); 264800b99b8Sopenharmony_ci return false; 265800b99b8Sopenharmony_ci } 266800b99b8Sopenharmony_ci return true; 267800b99b8Sopenharmony_ci} 268800b99b8Sopenharmony_ci 269800b99b8Sopenharmony_cistatic bool SendMsgCtlToSocket(int sockfd, const void *cmsg, const int cmsgLen) 270800b99b8Sopenharmony_ci{ 271800b99b8Sopenharmony_ci if ((sockfd < 0) || (cmsg == nullptr) || (cmsgLen == 0)) { 272800b99b8Sopenharmony_ci return false; 273800b99b8Sopenharmony_ci } 274800b99b8Sopenharmony_ci 275800b99b8Sopenharmony_ci struct msghdr msgh; 276800b99b8Sopenharmony_ci (void)memset_s(&msgh, sizeof(msgh), 0, sizeof(msgh)); 277800b99b8Sopenharmony_ci char iovBase[] = ""; 278800b99b8Sopenharmony_ci struct iovec iov = { 279800b99b8Sopenharmony_ci .iov_base = reinterpret_cast<void *>(iovBase), 280800b99b8Sopenharmony_ci .iov_len = 1 281800b99b8Sopenharmony_ci }; 282800b99b8Sopenharmony_ci msgh.msg_iov = &iov; 283800b99b8Sopenharmony_ci msgh.msg_iovlen = 1; 284800b99b8Sopenharmony_ci 285800b99b8Sopenharmony_ci int controlBufLen = CMSG_SPACE(static_cast<unsigned int>(cmsgLen)); 286800b99b8Sopenharmony_ci char controlBuf[controlBufLen]; 287800b99b8Sopenharmony_ci msgh.msg_control = controlBuf; 288800b99b8Sopenharmony_ci msgh.msg_controllen = sizeof(controlBuf); 289800b99b8Sopenharmony_ci 290800b99b8Sopenharmony_ci struct cmsghdr *cmsgh = CMSG_FIRSTHDR(&msgh); 291800b99b8Sopenharmony_ci if (cmsgh != nullptr) { 292800b99b8Sopenharmony_ci cmsgh->cmsg_level = SOL_SOCKET; 293800b99b8Sopenharmony_ci cmsgh->cmsg_type = SCM_RIGHTS; 294800b99b8Sopenharmony_ci cmsgh->cmsg_len = CMSG_LEN(cmsgLen); 295800b99b8Sopenharmony_ci } 296800b99b8Sopenharmony_ci if (memcpy_s(CMSG_DATA(cmsgh), cmsgLen, cmsg, cmsgLen) != 0) { 297800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: memcpy error", __func__); 298800b99b8Sopenharmony_ci } 299800b99b8Sopenharmony_ci 300800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(sendmsg(sockfd, &msgh, 0)) < 0) { 301800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to send message, errno(%{public}d)", __func__, errno); 302800b99b8Sopenharmony_ci return false; 303800b99b8Sopenharmony_ci } 304800b99b8Sopenharmony_ci return true; 305800b99b8Sopenharmony_ci} 306800b99b8Sopenharmony_ci 307800b99b8Sopenharmony_cibool SendFileDescriptorToSocket(int sockfd, int fd) 308800b99b8Sopenharmony_ci{ 309800b99b8Sopenharmony_ci return SendMsgCtlToSocket(sockfd, reinterpret_cast<void *>(&fd), sizeof(fd)); 310800b99b8Sopenharmony_ci} 311800b99b8Sopenharmony_ci 312800b99b8Sopenharmony_ciint ReadFileDescriptorFromSocket(int sockfd) 313800b99b8Sopenharmony_ci{ 314800b99b8Sopenharmony_ci size_t len = sizeof(int); 315800b99b8Sopenharmony_ci unsigned char data[len + 1]; 316800b99b8Sopenharmony_ci if (!RecvMsgFromSocket(sockfd, data, len)) { 317800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: Failed to recv message", __func__); 318800b99b8Sopenharmony_ci return -1; 319800b99b8Sopenharmony_ci } 320800b99b8Sopenharmony_ci 321800b99b8Sopenharmony_ci if (len != sizeof(int)) { 322800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: data is null or len is %{public}zu", __func__, len); 323800b99b8Sopenharmony_ci return -1; 324800b99b8Sopenharmony_ci } 325800b99b8Sopenharmony_ci int fd = *(reinterpret_cast<int *>(data)); 326800b99b8Sopenharmony_ci DFXLOGD("%{public}s :: fd: %{public}d", __func__, fd); 327800b99b8Sopenharmony_ci return fd; 328800b99b8Sopenharmony_ci}