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#include <ctype.h> 16d9f0492fSopenharmony_ci#include <errno.h> 17d9f0492fSopenharmony_ci#include <stdio.h> 18d9f0492fSopenharmony_ci#include <string.h> 19d9f0492fSopenharmony_ci#include <sys/socket.h> 20d9f0492fSopenharmony_ci 21d9f0492fSopenharmony_ci#include "init_log.h" 22d9f0492fSopenharmony_ci#include "init_param.h" 23d9f0492fSopenharmony_ci#include "init_utils.h" 24d9f0492fSopenharmony_ci#include "loop_event.h" 25d9f0492fSopenharmony_ci#include "param_manager.h" 26d9f0492fSopenharmony_ci#include "param_message.h" 27d9f0492fSopenharmony_ci#include "trigger_manager.h" 28d9f0492fSopenharmony_ci#include "securec.h" 29d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 30d9f0492fSopenharmony_ci#include "selinux_parameter.h" 31d9f0492fSopenharmony_ci#include <policycoreutils.h> 32d9f0492fSopenharmony_ci#include <selinux/selinux.h> 33d9f0492fSopenharmony_ci#endif 34d9f0492fSopenharmony_ci 35d9f0492fSopenharmony_cistatic ParamService g_paramService = {}; 36d9f0492fSopenharmony_ci 37d9f0492fSopenharmony_ciPARAM_STATIC void OnClose(ParamTaskPtr client) 38d9f0492fSopenharmony_ci{ 39d9f0492fSopenharmony_ci ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(client); 40d9f0492fSopenharmony_ci if (client == g_paramService.watcherTask) { 41d9f0492fSopenharmony_ci ClearWatchTrigger(watcher, TRIGGER_PARAM_WATCH); 42d9f0492fSopenharmony_ci g_paramService.watcherTask = NULL; 43d9f0492fSopenharmony_ci } else { 44d9f0492fSopenharmony_ci ClearWatchTrigger(watcher, TRIGGER_PARAM_WAIT); 45d9f0492fSopenharmony_ci } 46d9f0492fSopenharmony_ci} 47d9f0492fSopenharmony_ci 48d9f0492fSopenharmony_cistatic void TimerCallback(const ParamTaskPtr timer, void *context) 49d9f0492fSopenharmony_ci{ 50d9f0492fSopenharmony_ci UNUSED(context); 51d9f0492fSopenharmony_ci UNUSED(timer); 52d9f0492fSopenharmony_ci int ret = CheckWatchTriggerTimeout(); 53d9f0492fSopenharmony_ci // no wait node 54d9f0492fSopenharmony_ci if (ret == 0 && g_paramService.timer != NULL) { 55d9f0492fSopenharmony_ci ParamTaskClose(g_paramService.timer); 56d9f0492fSopenharmony_ci g_paramService.timer = NULL; 57d9f0492fSopenharmony_ci } 58d9f0492fSopenharmony_ci} 59d9f0492fSopenharmony_ci 60d9f0492fSopenharmony_cistatic void CheckAndSendTrigger(uint32_t dataIndex, const char *name, const char *value) 61d9f0492fSopenharmony_ci{ 62d9f0492fSopenharmony_ci WorkSpace *workspace = GetWorkSpaceByName(name); 63d9f0492fSopenharmony_ci PARAM_CHECK(workspace != NULL, return, "Failed to get workspace %s ", name); 64d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workspace, dataIndex); 65d9f0492fSopenharmony_ci PARAM_CHECK(entry != NULL, return, "Failed to get data %s ", name); 66d9f0492fSopenharmony_ci uint32_t trigger = 1; 67d9f0492fSopenharmony_ci if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED) & PARAM_FLAGS_TRIGGED) != PARAM_FLAGS_TRIGGED) { 68d9f0492fSopenharmony_ci trigger = (CheckAndMarkTrigger(TRIGGER_PARAM, name) != 0) ? 1 : 0; 69d9f0492fSopenharmony_ci } 70d9f0492fSopenharmony_ci if (trigger) { 71d9f0492fSopenharmony_ci ATOMIC_SYNC_OR_AND_FETCH(&entry->commitId, PARAM_FLAGS_TRIGGED, MEMORY_ORDER_RELEASE); 72d9f0492fSopenharmony_ci // notify event to process trigger 73d9f0492fSopenharmony_ci PostParamTrigger(EVENT_TRIGGER_PARAM, name, value); 74d9f0492fSopenharmony_ci } 75d9f0492fSopenharmony_ci 76d9f0492fSopenharmony_ci int wait = 1; 77d9f0492fSopenharmony_ci if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED) & PARAM_FLAGS_WAITED) != PARAM_FLAGS_WAITED) { 78d9f0492fSopenharmony_ci wait = (CheckAndMarkTrigger(TRIGGER_PARAM_WAIT, name) != 0) ? 1 : 0; 79d9f0492fSopenharmony_ci } 80d9f0492fSopenharmony_ci if (wait) { 81d9f0492fSopenharmony_ci ATOMIC_SYNC_OR_AND_FETCH(&entry->commitId, PARAM_FLAGS_WAITED, MEMORY_ORDER_RELEASE); 82d9f0492fSopenharmony_ci PostParamTrigger(EVENT_TRIGGER_PARAM_WAIT, name, value); 83d9f0492fSopenharmony_ci } 84d9f0492fSopenharmony_ci PostParamTrigger(EVENT_TRIGGER_PARAM_WATCH, name, value); 85d9f0492fSopenharmony_ci} 86d9f0492fSopenharmony_ci 87d9f0492fSopenharmony_cistatic int SendResponseMsg(ParamTaskPtr worker, const ParamMessage *msg, int result) 88d9f0492fSopenharmony_ci{ 89d9f0492fSopenharmony_ci ParamResponseMessage *response = NULL; 90d9f0492fSopenharmony_ci response = (ParamResponseMessage *)CreateParamMessage(msg->type, msg->key, sizeof(ParamResponseMessage)); 91d9f0492fSopenharmony_ci PARAM_CHECK(response != NULL, return PARAM_CODE_ERROR, "Failed to alloc memory for response"); 92d9f0492fSopenharmony_ci response->msg.id.msgId = msg->id.msgId; 93d9f0492fSopenharmony_ci response->result = result; 94d9f0492fSopenharmony_ci response->msg.msgSize = sizeof(ParamResponseMessage); 95d9f0492fSopenharmony_ci ParamTaskSendMsg(worker, (ParamMessage *)response); 96d9f0492fSopenharmony_ci PARAM_LOGV("Send response msg msgId %d result %d", msg->id.msgId, result); 97d9f0492fSopenharmony_ci return 0; 98d9f0492fSopenharmony_ci} 99d9f0492fSopenharmony_ci 100d9f0492fSopenharmony_cistatic int SendWatcherNotifyMessage(const TriggerExtInfo *extData, const char *content, uint32_t size) 101d9f0492fSopenharmony_ci{ 102d9f0492fSopenharmony_ci PARAM_CHECK(content != NULL, return -1, "Invalid content"); 103d9f0492fSopenharmony_ci PARAM_CHECK(extData != NULL && extData->stream != NULL, return -1, "Invalid extData"); 104d9f0492fSopenharmony_ci uint32_t msgSize = sizeof(ParamMessage) + PARAM_ALIGN(strlen(content) + 1); 105d9f0492fSopenharmony_ci ParamMessage *msg = (ParamMessage *)CreateParamMessage(MSG_NOTIFY_PARAM, "*", msgSize); 106d9f0492fSopenharmony_ci PARAM_CHECK(msg != NULL, return -1, "Failed to create msg "); 107d9f0492fSopenharmony_ci 108d9f0492fSopenharmony_ci uint32_t offset = 0; 109d9f0492fSopenharmony_ci int ret; 110d9f0492fSopenharmony_ci char *tmp = strstr(content, "="); 111d9f0492fSopenharmony_ci if (tmp != NULL) { 112d9f0492fSopenharmony_ci ret = strncpy_s(msg->key, sizeof(msg->key) - 1, content, tmp - content); 113d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(msg); 114d9f0492fSopenharmony_ci return -1, "Failed to fill value"); 115d9f0492fSopenharmony_ci tmp++; 116d9f0492fSopenharmony_ci ret = FillParamMsgContent(msg, &offset, PARAM_VALUE, tmp, strlen(tmp)); 117d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(msg); 118d9f0492fSopenharmony_ci return -1, "Failed to fill value"); 119d9f0492fSopenharmony_ci } else if (content != NULL && strlen(content) > 0) { 120d9f0492fSopenharmony_ci ret = FillParamMsgContent(msg, &offset, PARAM_VALUE, content, strlen(content)); 121d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(msg); 122d9f0492fSopenharmony_ci return -1, "Failed to fill value"); 123d9f0492fSopenharmony_ci } 124d9f0492fSopenharmony_ci 125d9f0492fSopenharmony_ci msg->id.msgId = 0; 126d9f0492fSopenharmony_ci if (extData->type == TRIGGER_PARAM_WAIT) { 127d9f0492fSopenharmony_ci msg->id.msgId = extData->info.waitInfo.waitId; 128d9f0492fSopenharmony_ci } else { 129d9f0492fSopenharmony_ci msg->id.msgId = extData->info.watchInfo.watchId; 130d9f0492fSopenharmony_ci } 131d9f0492fSopenharmony_ci msg->msgSize = sizeof(ParamMessage) + offset; 132d9f0492fSopenharmony_ci PARAM_LOGV("SendWatcherNotifyMessage cmd %s, id %d msgSize %d para: %s", 133d9f0492fSopenharmony_ci (extData->type == TRIGGER_PARAM_WAIT) ? "wait" : "watcher", 134d9f0492fSopenharmony_ci msg->id.msgId, msg->msgSize, content); 135d9f0492fSopenharmony_ci ParamTaskSendMsg(extData->stream, msg); 136d9f0492fSopenharmony_ci return 0; 137d9f0492fSopenharmony_ci} 138d9f0492fSopenharmony_ci 139d9f0492fSopenharmony_cistatic int SystemSetParam(const char *name, const char *value, const ParamSecurityLabel *srcLabel) 140d9f0492fSopenharmony_ci{ 141d9f0492fSopenharmony_ci PARAM_LOGV("SystemWriteParam name %s value: %s", name, value); 142d9f0492fSopenharmony_ci int ctrlService = 0; 143d9f0492fSopenharmony_ci int ret = CheckParameterSet(name, value, srcLabel, &ctrlService); 144d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Forbid to set parameter %s", name); 145d9f0492fSopenharmony_ci 146d9f0492fSopenharmony_ci unsigned int mode = 0; 147d9f0492fSopenharmony_ci if (strncmp(name, PARAM_PERSIST_PREFIX, strlen(PARAM_PERSIST_PREFIX)) == 0) { 148d9f0492fSopenharmony_ci mode |= LOAD_PARAM_PERSIST; 149d9f0492fSopenharmony_ci } 150d9f0492fSopenharmony_ci if ((ctrlService & PARAM_CTRL_SERVICE) != PARAM_CTRL_SERVICE) { // ctrl param 151d9f0492fSopenharmony_ci uint32_t dataIndex = 0; 152d9f0492fSopenharmony_ci ret = WriteParam(name, value, &dataIndex, mode); 153d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value); 154d9f0492fSopenharmony_ci ret = WritePersistParam(name, value); 155d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name); 156d9f0492fSopenharmony_ci CheckAndSendTrigger(dataIndex, name, value); 157d9f0492fSopenharmony_ci } 158d9f0492fSopenharmony_ci return ret; 159d9f0492fSopenharmony_ci} 160d9f0492fSopenharmony_ci 161d9f0492fSopenharmony_cistatic int HandleParamSet(const ParamTaskPtr worker, const ParamMessage *msg) 162d9f0492fSopenharmony_ci{ 163d9f0492fSopenharmony_ci uint32_t offset = 0; 164d9f0492fSopenharmony_ci ParamMsgContent *valueContent = GetNextContent(msg, &offset); 165d9f0492fSopenharmony_ci PARAM_CHECK(valueContent != NULL, return -1, "Invalid msg for %s", msg->key); 166d9f0492fSopenharmony_ci ParamSecurityLabel srcLabel = {0}; 167d9f0492fSopenharmony_ci struct ucred cr = {-1, -1, -1}; 168d9f0492fSopenharmony_ci socklen_t crSize = sizeof(cr); 169d9f0492fSopenharmony_ci if (getsockopt(LE_GetSocketFd(worker), SOL_SOCKET, SO_PEERCRED, &cr, &crSize) < 0) { 170d9f0492fSopenharmony_ci PARAM_LOGE("Failed to get opt %d", errno); 171d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 172d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, -1); 173d9f0492fSopenharmony_ci#endif 174d9f0492fSopenharmony_ci } 175d9f0492fSopenharmony_ci srcLabel.sockFd = LE_GetSocketFd(worker); 176d9f0492fSopenharmony_ci srcLabel.cred.uid = cr.uid; 177d9f0492fSopenharmony_ci srcLabel.cred.pid = cr.pid; 178d9f0492fSopenharmony_ci srcLabel.cred.gid = cr.gid; 179d9f0492fSopenharmony_ci PARAM_LOGI("Handle set param msgId %d pid %d key: %s", msg->id.msgId, cr.pid, msg->key); 180d9f0492fSopenharmony_ci int ret = SystemSetParam(msg->key, valueContent->content, &srcLabel); 181d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, ret); 182d9f0492fSopenharmony_ci} 183d9f0492fSopenharmony_ci 184d9f0492fSopenharmony_cistatic int32_t AddWatchNode(struct tagTriggerNode_ *trigger, const struct TriggerExtInfo_ *extInfo) 185d9f0492fSopenharmony_ci{ 186d9f0492fSopenharmony_ci ParamWatcher *watcher = NULL; 187d9f0492fSopenharmony_ci if (extInfo != NULL && extInfo->stream != NULL) { 188d9f0492fSopenharmony_ci watcher = (ParamWatcher *)ParamGetTaskUserData(extInfo->stream); 189d9f0492fSopenharmony_ci } 190d9f0492fSopenharmony_ci PARAM_CHECK(watcher != NULL, return -1, "Failed to get param watcher data"); 191d9f0492fSopenharmony_ci if (extInfo->type == TRIGGER_PARAM_WAIT) { 192d9f0492fSopenharmony_ci WaitNode *node = (WaitNode *)trigger; 193d9f0492fSopenharmony_ci OH_ListInit(&node->item); 194d9f0492fSopenharmony_ci node->timeout = extInfo->info.waitInfo.timeout; 195d9f0492fSopenharmony_ci node->stream = extInfo->stream; 196d9f0492fSopenharmony_ci node->waitId = extInfo->info.waitInfo.waitId; 197d9f0492fSopenharmony_ci OH_ListAddTail(&watcher->triggerHead, &node->item); 198d9f0492fSopenharmony_ci } else { 199d9f0492fSopenharmony_ci WatchNode *node = (WatchNode *)trigger; 200d9f0492fSopenharmony_ci OH_ListInit(&node->item); 201d9f0492fSopenharmony_ci node->watchId = extInfo->info.watchInfo.watchId; 202d9f0492fSopenharmony_ci OH_ListAddTail(&watcher->triggerHead, &node->item); 203d9f0492fSopenharmony_ci } 204d9f0492fSopenharmony_ci return 0; 205d9f0492fSopenharmony_ci} 206d9f0492fSopenharmony_ci 207d9f0492fSopenharmony_cistatic TriggerNode *AddWatcherTrigger(int triggerType, const char *condition, const TriggerExtInfo *extData) 208d9f0492fSopenharmony_ci{ 209d9f0492fSopenharmony_ci TriggerWorkSpace *workSpace = GetTriggerWorkSpace(); 210d9f0492fSopenharmony_ci TriggerHeader *header = (TriggerHeader *)&workSpace->triggerHead[extData->type]; 211d9f0492fSopenharmony_ci return header->addTrigger(workSpace, condition, extData); 212d9f0492fSopenharmony_ci} 213d9f0492fSopenharmony_ci 214d9f0492fSopenharmony_cistatic int32_t ExecuteWatchTrigger_(const struct tagTriggerNode_ *trigger, const char *content, uint32_t size) 215d9f0492fSopenharmony_ci{ 216d9f0492fSopenharmony_ci TriggerExtInfo extData = {}; 217d9f0492fSopenharmony_ci extData.type = trigger->type; 218d9f0492fSopenharmony_ci if (trigger->type == TRIGGER_PARAM_WAIT) { 219d9f0492fSopenharmony_ci WaitNode *node = (WaitNode *)trigger; 220d9f0492fSopenharmony_ci extData.stream = node->stream; 221d9f0492fSopenharmony_ci extData.info.waitInfo.waitId = node->waitId; 222d9f0492fSopenharmony_ci extData.info.waitInfo.timeout = node->timeout; 223d9f0492fSopenharmony_ci } else { 224d9f0492fSopenharmony_ci WatchNode *node = (WatchNode *)trigger; 225d9f0492fSopenharmony_ci extData.stream = g_paramService.watcherTask; 226d9f0492fSopenharmony_ci extData.info.watchInfo.watchId = node->watchId; 227d9f0492fSopenharmony_ci } 228d9f0492fSopenharmony_ci if (content == NULL) { 229d9f0492fSopenharmony_ci return SendWatcherNotifyMessage(&extData, "", 0); 230d9f0492fSopenharmony_ci } 231d9f0492fSopenharmony_ci return SendWatcherNotifyMessage(&extData, content, size); 232d9f0492fSopenharmony_ci} 233d9f0492fSopenharmony_ci 234d9f0492fSopenharmony_cistatic int HandleParamWaitAdd(const ParamTaskPtr worker, const ParamMessage *msg) 235d9f0492fSopenharmony_ci{ 236d9f0492fSopenharmony_ci PARAM_CHECK(msg != NULL, return -1, "Invalid message"); 237d9f0492fSopenharmony_ci uint32_t offset = 0; 238d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 239d9f0492fSopenharmony_ci uint32_t timeout = DEFAULT_PARAM_WAIT_TIMEOUT; 240d9f0492fSopenharmony_ci#else 241d9f0492fSopenharmony_ci uint32_t timeout = 0; 242d9f0492fSopenharmony_ci#endif 243d9f0492fSopenharmony_ci ParamMsgContent *valueContent = GetNextContent(msg, &offset); 244d9f0492fSopenharmony_ci PARAM_CHECK(valueContent != NULL, return -1, "Invalid msg"); 245d9f0492fSopenharmony_ci PARAM_CHECK(valueContent->contentSize <= PARAM_CONST_VALUE_LEN_MAX, return -1, "Invalid msg"); 246d9f0492fSopenharmony_ci ParamMsgContent *timeoutContent = GetNextContent(msg, &offset); 247d9f0492fSopenharmony_ci if (timeoutContent != NULL) { 248d9f0492fSopenharmony_ci timeout = *((uint32_t *)(timeoutContent->content)); 249d9f0492fSopenharmony_ci } 250d9f0492fSopenharmony_ci 251d9f0492fSopenharmony_ci PARAM_LOGV("HandleParamWaitAdd name %s timeout %d", msg->key, timeout); 252d9f0492fSopenharmony_ci TriggerExtInfo extData = {}; 253d9f0492fSopenharmony_ci extData.addNode = AddWatchNode; 254d9f0492fSopenharmony_ci extData.type = TRIGGER_PARAM_WAIT; 255d9f0492fSopenharmony_ci extData.stream = worker; 256d9f0492fSopenharmony_ci extData.info.waitInfo.waitId = msg->id.watcherId; 257d9f0492fSopenharmony_ci extData.info.waitInfo.timeout = timeout; 258d9f0492fSopenharmony_ci // first check match, if match send response to client 259d9f0492fSopenharmony_ci ParamNode *param = SystemCheckMatchParamWait(msg->key, valueContent->content); 260d9f0492fSopenharmony_ci if (param != NULL) { 261d9f0492fSopenharmony_ci SendWatcherNotifyMessage(&extData, param->data, param->valueLength); 262d9f0492fSopenharmony_ci return 0; 263d9f0492fSopenharmony_ci } 264d9f0492fSopenharmony_ci 265d9f0492fSopenharmony_ci uint32_t buffSize = strlen(msg->key) + valueContent->contentSize + 1 + 1; 266d9f0492fSopenharmony_ci char *condition = calloc(1, buffSize); 267d9f0492fSopenharmony_ci PARAM_CHECK(condition != NULL, return -1, "Failed to create condition for %s", msg->key); 268d9f0492fSopenharmony_ci int ret = sprintf_s(condition, buffSize - 1, "%s=%s", msg->key, valueContent->content); 269d9f0492fSopenharmony_ci PARAM_CHECK(ret > EOK, free(condition); 270d9f0492fSopenharmony_ci return -1, "Failed to copy name for %s", msg->key); 271d9f0492fSopenharmony_ci TriggerNode *trigger = AddWatcherTrigger(TRIGGER_PARAM_WAIT, condition, &extData); 272d9f0492fSopenharmony_ci PARAM_CHECK(trigger != NULL, free(condition); 273d9f0492fSopenharmony_ci return -1, "Failed to add trigger for %s", msg->key); 274d9f0492fSopenharmony_ci free(condition); 275d9f0492fSopenharmony_ci if (g_paramService.timer == NULL) { 276d9f0492fSopenharmony_ci ret = ParamTimerCreate(&g_paramService.timer, TimerCallback, &g_paramService); 277d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return 0, "Failed to create timer %s", msg->key); 278d9f0492fSopenharmony_ci ret = ParamTimerStart(g_paramService.timer, MS_UNIT, (uint64_t)-1); 279d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, 280d9f0492fSopenharmony_ci ParamTaskClose(g_paramService.timer); 281d9f0492fSopenharmony_ci g_paramService.timer = NULL; 282d9f0492fSopenharmony_ci return 0, "Failed to set timer %s", msg->key); 283d9f0492fSopenharmony_ci } 284d9f0492fSopenharmony_ci return 0; 285d9f0492fSopenharmony_ci} 286d9f0492fSopenharmony_ci 287d9f0492fSopenharmony_cistatic int HandleParamWatcherAdd(const ParamTaskPtr worker, const ParamMessage *msg) 288d9f0492fSopenharmony_ci{ 289d9f0492fSopenharmony_ci PARAM_CHECK(msg != NULL, return -1, "Invalid message"); 290d9f0492fSopenharmony_ci PARAM_CHECK((g_paramService.watcherTask == NULL) || 291d9f0492fSopenharmony_ci (g_paramService.watcherTask == worker), return -1, "Invalid watcher worker"); 292d9f0492fSopenharmony_ci g_paramService.watcherTask = worker; 293d9f0492fSopenharmony_ci TriggerExtInfo extData = {}; 294d9f0492fSopenharmony_ci extData.type = TRIGGER_PARAM_WATCH; 295d9f0492fSopenharmony_ci extData.addNode = AddWatchNode; 296d9f0492fSopenharmony_ci extData.stream = worker; 297d9f0492fSopenharmony_ci extData.info.watchInfo.watchId = msg->id.watcherId; 298d9f0492fSopenharmony_ci TriggerNode *trigger = AddWatcherTrigger(TRIGGER_PARAM_WATCH, msg->key, &extData); 299d9f0492fSopenharmony_ci if (trigger == NULL) { 300d9f0492fSopenharmony_ci PARAM_LOGE("Failed to add trigger for %s", msg->key); 301d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, -1); 302d9f0492fSopenharmony_ci } 303d9f0492fSopenharmony_ci PARAM_LOGV("HandleParamWatcherAdd name %s watcher: %d", msg->key, msg->id.watcherId); 304d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, 0); 305d9f0492fSopenharmony_ci} 306d9f0492fSopenharmony_ci 307d9f0492fSopenharmony_cistatic int HandleParamWatcherDel(const ParamTaskPtr worker, const ParamMessage *msg) 308d9f0492fSopenharmony_ci{ 309d9f0492fSopenharmony_ci PARAM_CHECK(msg != NULL, return -1, "Invalid message"); 310d9f0492fSopenharmony_ci PARAM_LOGV("HandleParamWatcherDel name %s watcher: %d", msg->key, msg->id.watcherId); 311d9f0492fSopenharmony_ci DelWatchTrigger(TRIGGER_PARAM_WATCH, (const void *)&msg->id.watcherId); 312d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, 0); 313d9f0492fSopenharmony_ci} 314d9f0492fSopenharmony_ci 315d9f0492fSopenharmony_cistatic int HandleParamSave(const ParamTaskPtr worker, const ParamMessage *msg) 316d9f0492fSopenharmony_ci{ 317d9f0492fSopenharmony_ci PARAM_CHECK(msg != NULL, return -1, "Invalid message"); 318d9f0492fSopenharmony_ci struct ucred cr = {-1, -1, -1}; 319d9f0492fSopenharmony_ci socklen_t crSize = sizeof(cr); 320d9f0492fSopenharmony_ci if (getsockopt(LE_GetSocketFd(worker), SOL_SOCKET, SO_PEERCRED, &cr, &crSize) < 0) { 321d9f0492fSopenharmony_ci PARAM_LOGE("Failed to get opt %d", errno); 322d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 323d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, -1); 324d9f0492fSopenharmony_ci#endif 325d9f0492fSopenharmony_ci } 326d9f0492fSopenharmony_ci PARAM_LOGI("process info:pid = %d, uid = %d, gid = %d", cr.pid, cr.uid, cr.gid); 327d9f0492fSopenharmony_ci int ret = CheckIfUidInGroup(cr.uid, "servicectrl"); 328d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return SendResponseMsg(worker, msg, -1), "Failed to process save parameters : ret %d", ret); 329d9f0492fSopenharmony_ci CheckAndSavePersistParam(); 330d9f0492fSopenharmony_ci return SendResponseMsg(worker, msg, 0); 331d9f0492fSopenharmony_ci} 332d9f0492fSopenharmony_ci 333d9f0492fSopenharmony_ciPARAM_STATIC int ProcessMessage(const ParamTaskPtr worker, const ParamMessage *msg) 334d9f0492fSopenharmony_ci{ 335d9f0492fSopenharmony_ci PARAM_CHECK((msg != NULL) && (msg->msgSize >= sizeof(ParamMessage)), return -1, "Invalid msg"); 336d9f0492fSopenharmony_ci PARAM_CHECK(worker != NULL, return -1, "Invalid worker"); 337d9f0492fSopenharmony_ci int ret = PARAM_CODE_INVALID_PARAM; 338d9f0492fSopenharmony_ci switch (msg->type) { 339d9f0492fSopenharmony_ci case MSG_SET_PARAM: 340d9f0492fSopenharmony_ci ret = HandleParamSet(worker, msg); 341d9f0492fSopenharmony_ci break; 342d9f0492fSopenharmony_ci case MSG_WAIT_PARAM: 343d9f0492fSopenharmony_ci ret = HandleParamWaitAdd(worker, msg); 344d9f0492fSopenharmony_ci break; 345d9f0492fSopenharmony_ci case MSG_ADD_WATCHER: 346d9f0492fSopenharmony_ci ret = HandleParamWatcherAdd(worker, msg); 347d9f0492fSopenharmony_ci break; 348d9f0492fSopenharmony_ci case MSG_DEL_WATCHER: 349d9f0492fSopenharmony_ci ret = HandleParamWatcherDel(worker, msg); 350d9f0492fSopenharmony_ci break; 351d9f0492fSopenharmony_ci case MSG_SAVE_PARAM: 352d9f0492fSopenharmony_ci ret = HandleParamSave(worker, msg); 353d9f0492fSopenharmony_ci break; 354d9f0492fSopenharmony_ci default: 355d9f0492fSopenharmony_ci break; 356d9f0492fSopenharmony_ci } 357d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to process message ret %d", ret); 358d9f0492fSopenharmony_ci return 0; 359d9f0492fSopenharmony_ci} 360d9f0492fSopenharmony_ci 361d9f0492fSopenharmony_ciPARAM_STATIC int OnIncomingConnect(LoopHandle loop, TaskHandle server) 362d9f0492fSopenharmony_ci{ 363d9f0492fSopenharmony_ci ParamStreamInfo info = {}; 364d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 365d9f0492fSopenharmony_ci info.flags = PARAM_TEST_FLAGS; 366d9f0492fSopenharmony_ci#endif 367d9f0492fSopenharmony_ci info.server = NULL; 368d9f0492fSopenharmony_ci info.close = OnClose; 369d9f0492fSopenharmony_ci info.recvMessage = ProcessMessage; 370d9f0492fSopenharmony_ci info.incomingConnect = NULL; 371d9f0492fSopenharmony_ci ParamTaskPtr client = NULL; 372d9f0492fSopenharmony_ci int ret = ParamStreamCreate(&client, server, &info, sizeof(ParamWatcher)); 373d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to create client"); 374d9f0492fSopenharmony_ci 375d9f0492fSopenharmony_ci ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(client); 376d9f0492fSopenharmony_ci PARAM_CHECK(watcher != NULL, return -1, "Failed to get watcher"); 377d9f0492fSopenharmony_ci OH_ListInit(&watcher->triggerHead); 378d9f0492fSopenharmony_ci watcher->stream = client; 379d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 380d9f0492fSopenharmony_ci g_paramService.watcherTask = client; 381d9f0492fSopenharmony_ci#endif 382d9f0492fSopenharmony_ci return 0; 383d9f0492fSopenharmony_ci} 384d9f0492fSopenharmony_ci 385d9f0492fSopenharmony_cistatic void LoadSelinuxLabel(const char *op) 386d9f0492fSopenharmony_ci{ 387d9f0492fSopenharmony_ci // load security label 388d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 389d9f0492fSopenharmony_ci ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); 390d9f0492fSopenharmony_ci if (ops != NULL && ops->securityGetLabel != NULL) { 391d9f0492fSopenharmony_ci ops->securityGetLabel(op); 392d9f0492fSopenharmony_ci } 393d9f0492fSopenharmony_ci#endif 394d9f0492fSopenharmony_ci} 395d9f0492fSopenharmony_ci 396d9f0492fSopenharmony_ciint InitParamService(void) 397d9f0492fSopenharmony_ci{ 398d9f0492fSopenharmony_ci PARAM_LOGI("InitParamService pipe: %s.", PIPE_NAME); 399d9f0492fSopenharmony_ci CheckAndCreateDir(PIPE_NAME); 400d9f0492fSopenharmony_ci CheckAndCreateDir(PARAM_STORAGE_PATH"/"); 401d9f0492fSopenharmony_ci // param space 402d9f0492fSopenharmony_ci PARAM_WORKSPACE_OPS ops = {0}; 403d9f0492fSopenharmony_ci ops.updaterMode = InUpdaterMode(); 404d9f0492fSopenharmony_ci // init open log 405d9f0492fSopenharmony_ci ops.logFunc = InitLog; 406d9f0492fSopenharmony_ci ops.getServiceGroupIdByPid = GetServiceGroupIdByPid; 407d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 408d9f0492fSopenharmony_ci ops.setfilecon = setfilecon; 409d9f0492fSopenharmony_ci#endif 410d9f0492fSopenharmony_ci int ret = InitParamWorkSpace(0, &ops); 411d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Init parameter workspace fail"); 412d9f0492fSopenharmony_ci ret = InitPersistParamWorkSpace(); 413d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Init persist parameter workspace fail"); 414d9f0492fSopenharmony_ci // param server 415d9f0492fSopenharmony_ci if (g_paramService.serverTask == NULL) { 416d9f0492fSopenharmony_ci ParamStreamInfo info = {}; 417d9f0492fSopenharmony_ci info.server = PIPE_NAME; 418d9f0492fSopenharmony_ci info.close = NULL; 419d9f0492fSopenharmony_ci info.recvMessage = NULL; 420d9f0492fSopenharmony_ci info.incomingConnect = OnIncomingConnect; 421d9f0492fSopenharmony_ci ret = ParamServerCreate(&g_paramService.serverTask, &info); 422d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to create server"); 423d9f0492fSopenharmony_ci } 424d9f0492fSopenharmony_ci 425d9f0492fSopenharmony_ci // init trigger space 426d9f0492fSopenharmony_ci ret = InitTriggerWorkSpace(); 427d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to init trigger"); 428d9f0492fSopenharmony_ci RegisterTriggerExec(TRIGGER_PARAM_WAIT, ExecuteWatchTrigger_); 429d9f0492fSopenharmony_ci RegisterTriggerExec(TRIGGER_PARAM_WATCH, ExecuteWatchTrigger_); 430d9f0492fSopenharmony_ci 431d9f0492fSopenharmony_ci return 0; 432d9f0492fSopenharmony_ci} 433d9f0492fSopenharmony_ci 434d9f0492fSopenharmony_civoid LoadSpecialParam(void) 435d9f0492fSopenharmony_ci{ 436d9f0492fSopenharmony_ci // read param area size from cfg and save to dac 437d9f0492fSopenharmony_ci LoadParamAreaSize(); 438d9f0492fSopenharmony_ci // read selinux label 439d9f0492fSopenharmony_ci LoadSelinuxLabel("init"); 440d9f0492fSopenharmony_ci // from cmdline 441d9f0492fSopenharmony_ci LoadParamFromCmdLine(); 442d9f0492fSopenharmony_ci // from build 443d9f0492fSopenharmony_ci LoadParamFromBuild(); 444d9f0492fSopenharmony_ci} 445d9f0492fSopenharmony_ci 446d9f0492fSopenharmony_ciint StartParamService(void) 447d9f0492fSopenharmony_ci{ 448d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 449d9f0492fSopenharmony_ci return 0; 450d9f0492fSopenharmony_ci#endif 451d9f0492fSopenharmony_ci // read selinux label 452d9f0492fSopenharmony_ci LoadSelinuxLabel("permission"); 453d9f0492fSopenharmony_ci return ParamServiceStart(); 454d9f0492fSopenharmony_ci} 455d9f0492fSopenharmony_ci 456d9f0492fSopenharmony_civoid StopParamService(void) 457d9f0492fSopenharmony_ci{ 458d9f0492fSopenharmony_ci PARAM_LOGI("StopParamService."); 459d9f0492fSopenharmony_ci ClosePersistParamWorkSpace(); 460d9f0492fSopenharmony_ci CloseParamWorkSpace(); 461d9f0492fSopenharmony_ci CloseTriggerWorkSpace(); 462d9f0492fSopenharmony_ci ParamTaskClose(g_paramService.serverTask); 463d9f0492fSopenharmony_ci g_paramService.serverTask = NULL; 464d9f0492fSopenharmony_ci ParamServiceStop(); 465d9f0492fSopenharmony_ci} 466d9f0492fSopenharmony_ci 467d9f0492fSopenharmony_ciint SystemWriteParam(const char *name, const char *value) 468d9f0492fSopenharmony_ci{ 469d9f0492fSopenharmony_ci return SystemSetParam(name, value, GetParamSecurityLabel()); 470d9f0492fSopenharmony_ci} 471d9f0492fSopenharmony_ci 472d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 473d9f0492fSopenharmony_ciParamService *GetParamService() 474d9f0492fSopenharmony_ci{ 475d9f0492fSopenharmony_ci return &g_paramService; 476d9f0492fSopenharmony_ci} 477d9f0492fSopenharmony_ci#endif 478