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 
16 #include "dbinder_stub.h"
17 
18 #include <stdbool.h>
19 
20 #include "dbinder_service_inner.h"
21 #include "ipc_process_skeleton.h"
22 #include "ipc_skeleton.h"
23 #include "ipc_thread_pool.h"
24 #include "rpc_errno.h"
25 #include "rpc_log.h"
26 #include "securec.h"
27 
28 #define IPC_INVALID_HANDLE (-1)
29 
GetDigits(int32_t number)30 static int32_t GetDigits(int32_t number)
31 {
32     int32_t n = 0;
33     while (number > 0) {
34         n++;
35         number /= ID_DIGITS;
36     }
37     if (n == 0) {
38         n++;
39     }
40     return n;
41 }
42 
CreateDatabusName(void)43 static char *CreateDatabusName(void)
44 {
45     int32_t pid = (int32_t)GetCallingPid();
46     int32_t pidLen = GetDigits(pid);
47     int32_t uid = (int32_t)GetCallingUid();
48     int32_t uidLen = GetDigits(uid);
49 
50     uint32_t sessionNameLen = SESSION_NAME_LEGNTH + pidLen + uidLen;
51     char *sessionName = (char *)malloc(sessionNameLen + 1);
52     if (sessionName == NULL) {
53         RPC_LOG_ERROR("sessionName mallo failed");
54         return NULL;
55     }
56     if (sprintf_s(sessionName, sessionNameLen + 1, "DBinder%d_%d", uid, pid) == -1) {
57         RPC_LOG_ERROR("sessionName sprintf failed");
58         free(sessionName);
59         return NULL;
60     }
61     return sessionName;
62 }
63 
ProcessProto(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption * option)64 static int32_t ProcessProto(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption *option)
65 {
66     int32_t result = ERR_NONE;
67     ThreadContext *threadContext = GetCurrentThreadContext();
68     if (threadContext == NULL) {
69         RPC_LOG_ERROR("ProcessProto threadContext is null");
70         return ERR_FAILED;
71     }
72 
73     SessionInfo *session = QuerySessionObject((uintptr_t)threadContext->objectStub);
74     if (session == NULL) {
75         RPC_LOG_ERROR("client find session is null");
76         return ERR_FAILED;
77     }
78     const char *localBusName = CreateDatabusName();
79     if (localBusName == NULL) {
80         RPC_LOG_ERROR("ProcessProto CreateDatabusName failed");
81         return ERR_FAILED;
82     }
83 
84     switch (session->type) {
85         case DATABUS_TYPE: {
86             WriteUint32(reply, IF_PROT_DATABUS);
87             WriteUint64(reply, session->stubIndex);
88             WriteString(reply, session->serviceName);
89             WriteString(reply, session->deviceIdInfo.toDeviceId);
90             WriteString(reply, session->deviceIdInfo.fromDeviceId);
91             WriteString(reply, localBusName);
92             break;
93         }
94         default: {
95             result = ERR_FAILED;
96             break;
97         }
98     }
99     free((void *)localBusName);
100     return result;
101 }
102 
DBinderRemoteRequest(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption * option)103 static int32_t DBinderRemoteRequest(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption *option)
104 {
105     int32_t ret = -1;
106     switch (code) {
107         case GET_PROTO_INFO: {
108             ret = ProcessProto(code, data, reply, option);
109             break;
110         }
111         default: {
112             RPC_LOG_ERROR("unknown dbinder code %u", code);
113             break;
114         }
115     }
116     return ret;
117 }
118 
GetDBinderStub(const char * serviceName,const char * deviceID,uintptr_t binderObject,DBinderServiceStub * dBinderServiceStub)119 int32_t GetDBinderStub(const char *serviceName, const char *deviceID,
120     uintptr_t binderObject, DBinderServiceStub *dBinderServiceStub)
121 {
122     if (strcpy_s(dBinderServiceStub->serviceName, SERVICENAME_LENGTH + 1, serviceName) != EOK
123         || strcpy_s(dBinderServiceStub->deviceID, DEVICEID_LENGTH + 1, deviceID) != EOK) {
124         RPC_LOG_ERROR("dBinderServiceStub string copy failed");
125         return ERR_FAILED;
126     }
127 
128     IpcObjectStub *objectStub = (IpcObjectStub *)malloc(sizeof(IpcObjectStub));
129     if (objectStub == NULL) {
130         RPC_LOG_ERROR("objectStub malloc failed");
131         return ERR_FAILED;
132     }
133     objectStub->func = (OnRemoteRequest)DBinderRemoteRequest;
134     objectStub->isRemote = true;
135 
136     dBinderServiceStub->binderObject = binderObject;
137     dBinderServiceStub->svc.handle = IPC_INVALID_HANDLE;
138     dBinderServiceStub->svc.token = (uintptr_t)objectStub;
139     dBinderServiceStub->svc.cookie = (uintptr_t)objectStub;
140     return ERR_NONE;
141 }
142