1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "samgr_ipc_adapter.h"
16 #include "samgr_server.h"
17 #include "dbinder_service.h"
18 static int Dispatch(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option);
19 static void HandleIpc(const Request *request, const Response *response);
20 static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum);
ClientRegisterRemoteEndpoint(SvcIdentity * identity,int token,const char * service,const char * feature)21 int ClientRegisterRemoteEndpoint(SvcIdentity *identity, int token, const char *service, const char *feature)
22 {
23     IpcObjectStub *objectStubOne = (IpcObjectStub *)calloc(1, sizeof(IpcObjectStub));
24     if (objectStubOne == NULL) {
25         return -1;
26     }
27     objectStubOne->func = Dispatch;
28     objectStubOne->isRemote = true;
29     // handle is used by rpc, should be bigger than 0
30     identity->handle = token + 1;
31     identity->cookie = objectStubOne;
32     // token is used by router index, should be itself, and save in SaNode
33     identity->token = token;
34     return AddEndpoint(*identity, service, feature);
35 }
36 
Listen(Endpoint * endpoint,int token,const char * service,const char * feature)37 void Listen(Endpoint *endpoint, int token, const char *service, const char *feature)
38 {
39     endpoint->registerEP(&endpoint->identity, token, service, feature);
40 }
41 
Dispatch(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)42 static int Dispatch(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
43 {
44     Endpoint *endpoint = g_remoteRegister.endpoint;
45     int token = GetRemoteToken(data);
46     if (token == EC_INVALID) {
47         goto ERROR;
48     }
49     if (TB_CheckMessage(&endpoint->bucket) == BUCKET_BUSY) {
50         HILOG_WARN(HILOG_MODULE_SAMGR, "Flow Control <%u> is NULL", token);
51         goto ERROR;
52     }
53 
54     Router *router = VECTOR_At(&endpoint->routers, token);
55     if (router == NULL) {
56         HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, token);
57         goto ERROR;
58     }
59     Response resp = {0};
60     resp.data = endpoint;
61     Request request = {0};
62     request.msgId = token;
63     request.data = data;
64     resp.reply = reply;
65     request.msgValue = code;
66     uint32 *ref = NULL;
67     int ret = SAMGR_SendSharedDirectRequest(&router->identity, &request, &resp, &ref, HandleIpc);
68     if (ret != EC_SUCCESS) {
69         HILOG_ERROR(HILOG_MODULE_SAMGR, "Router[%u] Service<%d, %d> is busy",
70                     token, router->identity.serviceId, router->identity.featureId);
71         goto ERROR;
72     }
73 
74     return EC_SUCCESS;
75 ERROR:
76     return EC_INVALID;
77 }
78 
HandleIpc(const Request * request,const Response * response)79 static void HandleIpc(const Request *request, const Response *response)
80 {
81     Endpoint *endpoint = (Endpoint *)response->data;
82     Router *router = VECTOR_At(&endpoint->routers, request->msgId);
83 
84     router->proxy->Invoke(router->proxy, request->msgValue, NULL, request->data, response->reply);
85 }
86 
RegisterIdentity(const SaName * saName,SvcIdentity * saInfo,PolicyTrans ** policy,uint32 * policyNum)87 int RegisterIdentity(const SaName *saName, SvcIdentity *saInfo, PolicyTrans **policy, uint32 *policyNum)
88 {
89     IpcIo req;
90     uint8 data[MAX_DATA_LEN];
91     IpcIoInit(&req, data, MAX_DATA_LEN, 0);
92     WriteUint32(&req, RES_FEATURE);
93     WriteUint32(&req, OP_PUT);
94     WriteString(&req, saName->service);
95     WriteBool(&req, saName->feature == NULL);
96     if (saName->feature != NULL) {
97         WriteBool(&req, saName->feature);
98     }
99     WriteUint32(&req, saInfo->token);
100     IpcIo reply;
101     void *replyBuf = NULL;
102     SvcIdentity *samgr = GetContextObject();
103     MessageOption option;
104     MessageOptionInit(&option);
105     int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply, option,
106                           (uintptr_t *)&replyBuf);
107     ret = -ret;
108     int32_t ipcRet = EC_FAILURE;
109     if (ret == EC_SUCCESS) {
110         ret = ReadInt32(&reply, &ipcRet);
111     }
112     if (ipcRet == EC_SUCCESS) {
113         SvcIdentity target;
114         (void)ReadRemoteObject(&reply, &target);
115         GetRemotePolicy(&reply, policy, policyNum);
116     }
117     if (replyBuf != NULL) {
118         FreeBuffer(replyBuf);
119     }
120     return ret;
121 }
122 
GetRemoteToken(IpcIo * data)123 int GetRemoteToken(IpcIo *data)
124 {
125     uintptr_t saId = 0;
126     ReadInt32(data, &saId);
127     SaNode *saNode = GetSaNodeBySaId(saId);
128     if (saNode == NULL) {
129         HILOG_WARN(HILOG_MODULE_SAMGR, "get sa node by sa id %d is NULL", saId);
130         return EC_INVALID;
131     }
132     return saNode->token;
133 }
134 
GetRemotePolicy(IpcIo * reply,PolicyTrans ** policy,uint32 * policyNum)135 static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum)
136 {
137     if (reply == NULL) {
138         return;
139     }
140     ReadUint32(reply, policyNum);
141     if (*policyNum > MAX_POLICY_NUM) {
142         *policyNum = MAX_POLICY_NUM;
143     }
144     SAMGR_Free(*policy);
145     if (*policyNum == 0) {
146         *policy = NULL;
147         return;
148     }
149     *policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * (*policyNum));
150     if (*policy == NULL) {
151         return;
152     }
153     for (uint32 i = 0; i < *policyNum; i++) {
154         if (!ReadInt32(reply, &(*policy)[i].type)) {
155             continue;
156         }
157         switch ((*policy)[i].type) {
158             case RANGE:
159                 ReadInt32(reply, &((*policy)[i].uidMin));
160                 ReadInt32(reply, &((*policy)[i].uidMax));
161                 break;
162             case FIXED:
163                 for (uint32 j = 0; j < UID_SIZE; j++) {
164                     ReadInt32(reply, &((*policy)[i].fixedUid[j]));
165                 }
166                 break;
167             case BUNDLENAME:
168                 ReadInt32(reply, &((*policy)[i].fixedUid[0]));
169                 break;
170             default:
171                 break;
172         }
173     }
174 }