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