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