1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci* Copyright (c) 2021 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci* you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci* You may obtain a copy of the License at 6d9f0492fSopenharmony_ci* 7d9f0492fSopenharmony_ci* http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci* 9d9f0492fSopenharmony_ci* Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci* See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci* limitations under the License. 14d9f0492fSopenharmony_ci*/ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include "fd_holder.h" 17d9f0492fSopenharmony_ci#include <stdio.h> 18d9f0492fSopenharmony_ci#include <errno.h> 19d9f0492fSopenharmony_ci 20d9f0492fSopenharmony_ci#include "beget_ext.h" 21d9f0492fSopenharmony_ci#include "fd_holder_internal.h" 22d9f0492fSopenharmony_ci#include "init_utils.h" 23d9f0492fSopenharmony_ci#include "securec.h" 24d9f0492fSopenharmony_ci 25d9f0492fSopenharmony_cistatic int BuildClientSocket(void) 26d9f0492fSopenharmony_ci{ 27d9f0492fSopenharmony_ci int sockFd; 28d9f0492fSopenharmony_ci sockFd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); 29d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(sockFd >= 0, return -1, "Failed to build socket, err = %d", errno); 30d9f0492fSopenharmony_ci 31d9f0492fSopenharmony_ci struct sockaddr_un addr; 32d9f0492fSopenharmony_ci (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr)); 33d9f0492fSopenharmony_ci addr.sun_family = AF_UNIX; 34d9f0492fSopenharmony_ci int ret = strncpy_s(addr.sun_path, sizeof(addr.sun_path), INIT_HOLDER_SOCKET_PATH, 35d9f0492fSopenharmony_ci strlen(INIT_HOLDER_SOCKET_PATH)); 36d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret == 0, close(sockFd); 37d9f0492fSopenharmony_ci return -1, "Failed to build socket path"); 38d9f0492fSopenharmony_ci 39d9f0492fSopenharmony_ci socklen_t len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1); 40d9f0492fSopenharmony_ci 41d9f0492fSopenharmony_ci ret = connect(sockFd, (struct sockaddr *)&addr, len); 42d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret >= 0, close(sockFd); 43d9f0492fSopenharmony_ci return -1, "Failed to connect to socket, err = %d", errno); 44d9f0492fSopenharmony_ci return sockFd; 45d9f0492fSopenharmony_ci} 46d9f0492fSopenharmony_ci 47d9f0492fSopenharmony_ciSTATIC int BuildSendData(char *buffer, size_t size, const char *serviceName, bool hold, bool poll) 48d9f0492fSopenharmony_ci{ 49d9f0492fSopenharmony_ci if (buffer == NULL || size == 0 || serviceName == 0) { 50d9f0492fSopenharmony_ci return -1; 51d9f0492fSopenharmony_ci } 52d9f0492fSopenharmony_ci 53d9f0492fSopenharmony_ci if (!hold && poll) { 54d9f0492fSopenharmony_ci BEGET_LOGE("Get fd with poll set, invalid parameter"); 55d9f0492fSopenharmony_ci return -1; 56d9f0492fSopenharmony_ci } 57d9f0492fSopenharmony_ci 58d9f0492fSopenharmony_ci char *holdString = ACTION_HOLD; 59d9f0492fSopenharmony_ci if (!hold) { 60d9f0492fSopenharmony_ci holdString = ACTION_GET; 61d9f0492fSopenharmony_ci } 62d9f0492fSopenharmony_ci char *pollString = WITHPOLL; 63d9f0492fSopenharmony_ci if (!poll) { 64d9f0492fSopenharmony_ci pollString = WITHOUTPOLL; 65d9f0492fSopenharmony_ci } 66d9f0492fSopenharmony_ci 67d9f0492fSopenharmony_ci if (snprintf_s(buffer, size, size - 1, "%s|%s|%s", serviceName, holdString, pollString) == -1) { 68d9f0492fSopenharmony_ci BEGET_LOGE("Failed to build send data"); 69d9f0492fSopenharmony_ci return -1; 70d9f0492fSopenharmony_ci } 71d9f0492fSopenharmony_ci return 0; 72d9f0492fSopenharmony_ci} 73d9f0492fSopenharmony_ci 74d9f0492fSopenharmony_cistatic int ServiceSendFds(const char *serviceName, int *fds, int fdCount, bool doPoll) 75d9f0492fSopenharmony_ci{ 76d9f0492fSopenharmony_ci int sock = BuildClientSocket(); 77d9f0492fSopenharmony_ci BEGET_CHECK(sock >= 0, return -1); 78d9f0492fSopenharmony_ci 79d9f0492fSopenharmony_ci struct iovec iovec = {}; 80d9f0492fSopenharmony_ci struct msghdr msghdr = { 81d9f0492fSopenharmony_ci .msg_iov = &iovec, 82d9f0492fSopenharmony_ci .msg_iovlen = 1, 83d9f0492fSopenharmony_ci }; 84d9f0492fSopenharmony_ci 85d9f0492fSopenharmony_ci char sendBuffer[MAX_FD_HOLDER_BUFFER] = {}; 86d9f0492fSopenharmony_ci int ret = BuildSendData(sendBuffer, sizeof(sendBuffer), serviceName, true, doPoll); 87d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret >= 0, close(sock); 88d9f0492fSopenharmony_ci return -1, "Failed to build send data"); 89d9f0492fSopenharmony_ci 90d9f0492fSopenharmony_ci BEGET_LOGV("Send data: [%s]", sendBuffer); 91d9f0492fSopenharmony_ci iovec.iov_base = sendBuffer; 92d9f0492fSopenharmony_ci iovec.iov_len = strlen(sendBuffer); 93d9f0492fSopenharmony_ci 94d9f0492fSopenharmony_ci if (BuildControlMessage(&msghdr, fds, fdCount, true) < 0) { 95d9f0492fSopenharmony_ci BEGET_LOGE("Failed to build control message"); 96d9f0492fSopenharmony_ci if (msghdr.msg_control != NULL) { 97d9f0492fSopenharmony_ci free(msghdr.msg_control); 98d9f0492fSopenharmony_ci msghdr.msg_control = NULL; 99d9f0492fSopenharmony_ci } 100d9f0492fSopenharmony_ci msghdr.msg_controllen = 0; 101d9f0492fSopenharmony_ci close(sock); 102d9f0492fSopenharmony_ci return -1; 103d9f0492fSopenharmony_ci } 104d9f0492fSopenharmony_ci 105d9f0492fSopenharmony_ci if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) { 106d9f0492fSopenharmony_ci BEGET_LOGE("Failed to send fds to init, err = %d", errno); 107d9f0492fSopenharmony_ci if (msghdr.msg_control != NULL) { 108d9f0492fSopenharmony_ci free(msghdr.msg_control); 109d9f0492fSopenharmony_ci msghdr.msg_control = NULL; 110d9f0492fSopenharmony_ci } 111d9f0492fSopenharmony_ci msghdr.msg_controllen = 0; 112d9f0492fSopenharmony_ci close(sock); 113d9f0492fSopenharmony_ci return -1; 114d9f0492fSopenharmony_ci } 115d9f0492fSopenharmony_ci if (msghdr.msg_control != NULL) { 116d9f0492fSopenharmony_ci free(msghdr.msg_control); 117d9f0492fSopenharmony_ci msghdr.msg_control = NULL; 118d9f0492fSopenharmony_ci } 119d9f0492fSopenharmony_ci msghdr.msg_controllen = 0; 120d9f0492fSopenharmony_ci BEGET_LOGI("Send fds done"); 121d9f0492fSopenharmony_ci close(sock); 122d9f0492fSopenharmony_ci return 0; 123d9f0492fSopenharmony_ci} 124d9f0492fSopenharmony_ci 125d9f0492fSopenharmony_ciint ServiceSaveFd(const char *serviceName, int *fds, int fdCount) 126d9f0492fSopenharmony_ci{ 127d9f0492fSopenharmony_ci // Sanity checks 128d9f0492fSopenharmony_ci if (serviceName == NULL || fds == NULL || 129d9f0492fSopenharmony_ci fdCount < 0 || fdCount > MAX_HOLD_FDS) { 130d9f0492fSopenharmony_ci BEGET_LOGE("Invalid parameters"); 131d9f0492fSopenharmony_ci return -1; 132d9f0492fSopenharmony_ci } 133d9f0492fSopenharmony_ci return ServiceSendFds(serviceName, fds, fdCount, false); 134d9f0492fSopenharmony_ci} 135d9f0492fSopenharmony_ci 136d9f0492fSopenharmony_ciint ServiceSaveFdWithPoll(const char *serviceName, int *fds, int fdCount) 137d9f0492fSopenharmony_ci{ 138d9f0492fSopenharmony_ci // Sanity checks 139d9f0492fSopenharmony_ci if (serviceName == NULL || fds == NULL || 140d9f0492fSopenharmony_ci fdCount < 0 || fdCount > MAX_HOLD_FDS) { 141d9f0492fSopenharmony_ci BEGET_LOGE("Invalid parameters"); 142d9f0492fSopenharmony_ci return -1; 143d9f0492fSopenharmony_ci } 144d9f0492fSopenharmony_ci return ServiceSendFds(serviceName, fds, fdCount, true); 145d9f0492fSopenharmony_ci} 146d9f0492fSopenharmony_ci 147d9f0492fSopenharmony_ciint *ServiceGetFd(const char *serviceName, size_t *outfdCount) 148d9f0492fSopenharmony_ci{ 149d9f0492fSopenharmony_ci if (serviceName == NULL || outfdCount == NULL) { 150d9f0492fSopenharmony_ci BEGET_LOGE("Invalid parameters"); 151d9f0492fSopenharmony_ci return NULL; 152d9f0492fSopenharmony_ci } 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_ci char path[MAX_FD_HOLDER_BUFFER] = {}; 155d9f0492fSopenharmony_ci int ret = snprintf_s(path, MAX_FD_HOLDER_BUFFER, MAX_FD_HOLDER_BUFFER - 1, ENV_FD_HOLD_PREFIX"%s", serviceName); 156d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret > 0, return NULL, "Failed snprintf_s err=%d", errno); 157d9f0492fSopenharmony_ci const char *value = getenv(path); 158d9f0492fSopenharmony_ci if (value == NULL) { 159d9f0492fSopenharmony_ci BEGET_LOGE("Cannot get env %s\n", path); 160d9f0492fSopenharmony_ci return NULL; 161d9f0492fSopenharmony_ci } 162d9f0492fSopenharmony_ci 163d9f0492fSopenharmony_ci char fdBuffer[MAX_FD_HOLDER_BUFFER] = {}; 164d9f0492fSopenharmony_ci ret = strncpy_s(fdBuffer, MAX_FD_HOLDER_BUFFER - 1, value, strlen(value)); 165d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret == 0, return NULL, "Failed strncpy_s err=%d", errno); 166d9f0492fSopenharmony_ci BEGET_LOGV("fds = %s", fdBuffer); 167d9f0492fSopenharmony_ci int fdCount = 0; 168d9f0492fSopenharmony_ci char **fdList = SplitStringExt(fdBuffer, " ", &fdCount, MAX_HOLD_FDS); 169d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(fdList != NULL, return NULL, "Cannot get fd list"); 170d9f0492fSopenharmony_ci 171d9f0492fSopenharmony_ci int *fds = calloc((size_t)fdCount, sizeof(int)); 172d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(fds != NULL, FreeStringVector(fdList, fdCount); 173d9f0492fSopenharmony_ci *outfdCount = 0; 174d9f0492fSopenharmony_ci return NULL, 175d9f0492fSopenharmony_ci "Allocate memory for fd failed. err = %d", errno); 176d9f0492fSopenharmony_ci 177d9f0492fSopenharmony_ci bool encounterError = false; 178d9f0492fSopenharmony_ci for (int i = 0; i < fdCount; i++) { 179d9f0492fSopenharmony_ci errno = 0; 180d9f0492fSopenharmony_ci fds[i] = (int)strtol(fdList[i], NULL, DECIMAL_BASE); 181d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(errno == 0, encounterError = true; 182d9f0492fSopenharmony_ci break, "Failed to convert \' %s \' to fd number", fdList[i]); 183d9f0492fSopenharmony_ci } 184d9f0492fSopenharmony_ci 185d9f0492fSopenharmony_ci if (encounterError) { 186d9f0492fSopenharmony_ci free(fds); 187d9f0492fSopenharmony_ci fds = NULL; 188d9f0492fSopenharmony_ci fdCount = 0; 189d9f0492fSopenharmony_ci } 190d9f0492fSopenharmony_ci *outfdCount = fdCount; 191d9f0492fSopenharmony_ci FreeStringVector(fdList, fdCount); 192d9f0492fSopenharmony_ci return fds; 193d9f0492fSopenharmony_ci} 194