1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <assert.h>
17 #include <errno.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/uio.h>
23 #include <unistd.h>
24
25 #include <trusty/tipc.h>
26
27 #include "ipc.h"
28 #include "log.h"
29
30 #define MAX_RECONNECT_RETRY_COUNT 5
31 #define TRUSTY_RECONNECT_TIMEOUT_SEC 5
32
33 static int tipc_fd = -1;
34
ipc_connect(const char * device,const char * port)35 int ipc_connect(const char *device, const char *port)
36 {
37 int rc;
38 uint retry_cnt = 0;
39
40 assert(tipc_fd == -1);
41
42 while(true) {
43 rc = tipc_connect(device, port);
44 if (rc >= 0)
45 break;
46
47 ALOGE("failed (%d) to connect to storage server\n", rc);
48 if (++retry_cnt > MAX_RECONNECT_RETRY_COUNT) {
49 ALOGE("max number of reconnect retries (%d) has been reached\n",
50 retry_cnt);
51 return -1;
52 }
53 sleep(TRUSTY_RECONNECT_TIMEOUT_SEC);
54 }
55 tipc_fd = rc;
56 return 0;
57 }
58
ipc_disconnect(void)59 void ipc_disconnect(void)
60 {
61 assert(tipc_fd >= 0);
62
63 tipc_close(tipc_fd);
64 tipc_fd = -1;
65 }
66
ipc_get_msg(struct storage_msg * msg,void * req_buf,size_t req_buf_len)67 ssize_t ipc_get_msg(struct storage_msg *msg, void *req_buf, size_t req_buf_len)
68 {
69 ssize_t rc;
70 struct iovec iovs[2] = {{msg, sizeof(*msg)}, {req_buf, req_buf_len}};
71
72 assert(tipc_fd >= 0);
73
74 rc = readv(tipc_fd, iovs, 2);
75 if (rc < 0) {
76 ALOGE("failed to read request: %s\n", strerror(errno));
77 return rc;
78 }
79
80 /* check for minimum size */
81 if ((size_t)rc < sizeof(*msg)) {
82 ALOGE("message is too short (%zu bytes received)\n", rc);
83 return -1;
84 }
85
86 /* check for message completeness */
87 if (msg->size != (uint32_t)rc) {
88 ALOGE("inconsistent message size [cmd=%d] (%u != %u)\n",
89 msg->cmd, msg->size, (uint32_t)rc);
90 return -1;
91 }
92
93 return rc - sizeof(*msg);
94 }
95
ipc_respond(struct storage_msg * msg,void * out,size_t out_size)96 int ipc_respond(struct storage_msg *msg, void *out, size_t out_size)
97 {
98 ssize_t rc;
99 struct iovec iovs[2] = {{msg, sizeof(*msg)}, {out, out_size}};
100
101 assert(tipc_fd >= 0);
102
103 msg->cmd |= STORAGE_RESP_BIT;
104
105 rc = writev(tipc_fd, iovs, out ? 2 : 1);
106 if (rc < 0) {
107 ALOGE("error sending response 0x%x: %s\n",
108 msg->cmd, strerror(errno));
109 return -1;
110 }
111
112 return 0;
113 }
114
115
116