hal-ipc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. // SPDX-License-Identifier: Apache-2.0
  2. /*
  3. * Copyright (C) 2013 Intel Corporation
  4. *
  5. */
  6. #include <pthread.h>
  7. #include <errno.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10. #include <stdbool.h>
  11. #include <poll.h>
  12. #include <unistd.h>
  13. #include <stdint.h>
  14. #include <stdlib.h>
  15. #include <cutils/properties.h>
  16. #include "hal.h"
  17. #include "hal-msg.h"
  18. #include "hal-log.h"
  19. #include "ipc-common.h"
  20. #include "hal-ipc.h"
  21. #define CONNECT_TIMEOUT (10 * 1000)
  22. static int listen_sk = -1;
  23. static int cmd_sk = -1;
  24. static int notif_sk = -1;
  25. static pthread_mutex_t cmd_sk_mutex = PTHREAD_MUTEX_INITIALIZER;
  26. static pthread_t notif_th = 0;
  27. struct service_handler {
  28. const struct hal_ipc_handler *handler;
  29. uint8_t size;
  30. };
  31. static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
  32. void hal_ipc_register(uint8_t service, const struct hal_ipc_handler *handlers,
  33. uint8_t size)
  34. {
  35. services[service].handler = handlers;
  36. services[service].size = size;
  37. }
  38. void hal_ipc_unregister(uint8_t service)
  39. {
  40. services[service].handler = NULL;
  41. services[service].size = 0;
  42. }
  43. static bool handle_msg(void *buf, ssize_t len, int fd)
  44. {
  45. struct ipc_hdr *msg = buf;
  46. const struct hal_ipc_handler *handler;
  47. uint8_t opcode;
  48. if (len < (ssize_t) sizeof(*msg)) {
  49. error("IPC: message too small (%zd bytes)", len);
  50. return false;
  51. }
  52. if (len != (ssize_t) (sizeof(*msg) + msg->len)) {
  53. error("IPC: message malformed (%zd bytes)", len);
  54. return false;
  55. }
  56. /* if service is valid */
  57. if (msg->service_id > HAL_SERVICE_ID_MAX) {
  58. error("IPC: unknown service (0x%x)", msg->service_id);
  59. return false;
  60. }
  61. /* if service is registered */
  62. if (!services[msg->service_id].handler) {
  63. error("IPC: unregistered service (0x%x)", msg->service_id);
  64. return false;
  65. }
  66. /* if opcode fit valid range */
  67. if (msg->opcode < HAL_MINIMUM_EVENT) {
  68. error("IPC: invalid opcode for service 0x%x (0x%x)",
  69. msg->service_id, msg->opcode);
  70. return false;
  71. }
  72. /*
  73. * opcode is used as table offset and must be adjusted as events start
  74. * with HAL_MINIMUM_EVENT offset
  75. */
  76. opcode = msg->opcode - HAL_MINIMUM_EVENT;
  77. /* if opcode is valid */
  78. if (opcode >= services[msg->service_id].size) {
  79. error("IPC: invalid opcode for service 0x%x (0x%x)",
  80. msg->service_id, msg->opcode);
  81. return false;
  82. }
  83. handler = &services[msg->service_id].handler[opcode];
  84. /* if payload size is valid */
  85. if ((handler->var_len && handler->data_len > msg->len) ||
  86. (!handler->var_len && handler->data_len != msg->len)) {
  87. error("IPC: message size invalid for service 0x%x opcode 0x%x "
  88. "(%u bytes)",
  89. msg->service_id, msg->opcode, msg->len);
  90. return false;
  91. }
  92. handler->handler(msg->payload, msg->len, fd);
  93. return true;
  94. }
  95. static void *notification_handler(void *data)
  96. {
  97. struct msghdr msg;
  98. struct iovec iv;
  99. struct cmsghdr *cmsg;
  100. char cmsgbuf[CMSG_SPACE(sizeof(int))];
  101. char buf[IPC_MTU];
  102. ssize_t ret;
  103. int fd;
  104. bt_thread_associate();
  105. while (true) {
  106. memset(&msg, 0, sizeof(msg));
  107. memset(buf, 0, sizeof(buf));
  108. memset(cmsgbuf, 0, sizeof(cmsgbuf));
  109. iv.iov_base = buf;
  110. iv.iov_len = sizeof(buf);
  111. msg.msg_iov = &iv;
  112. msg.msg_iovlen = 1;
  113. msg.msg_control = cmsgbuf;
  114. msg.msg_controllen = sizeof(cmsgbuf);
  115. ret = recvmsg(notif_sk, &msg, 0);
  116. if (ret < 0) {
  117. error("Receiving notifications failed: %s",
  118. strerror(errno));
  119. goto failed;
  120. }
  121. /* socket was shutdown */
  122. if (ret == 0) {
  123. pthread_mutex_lock(&cmd_sk_mutex);
  124. if (cmd_sk == -1) {
  125. pthread_mutex_unlock(&cmd_sk_mutex);
  126. break;
  127. }
  128. pthread_mutex_unlock(&cmd_sk_mutex);
  129. error("Notification socket closed");
  130. goto failed;
  131. }
  132. fd = -1;
  133. /* Receive auxiliary data in msg */
  134. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
  135. cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  136. if (cmsg->cmsg_level == SOL_SOCKET
  137. && cmsg->cmsg_type == SCM_RIGHTS) {
  138. memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
  139. break;
  140. }
  141. }
  142. if (!handle_msg(buf, ret, fd))
  143. goto failed;
  144. }
  145. close(notif_sk);
  146. notif_sk = -1;
  147. bt_thread_disassociate();
  148. DBG("exit");
  149. return NULL;
  150. failed:
  151. exit(EXIT_FAILURE);
  152. }
  153. static int accept_connection(int sk)
  154. {
  155. int err;
  156. struct pollfd pfd;
  157. int new_sk;
  158. memset(&pfd, 0 , sizeof(pfd));
  159. pfd.fd = sk;
  160. pfd.events = POLLIN;
  161. err = poll(&pfd, 1, CONNECT_TIMEOUT);
  162. if (err < 0) {
  163. err = errno;
  164. error("Failed to poll: %d (%s)", err, strerror(err));
  165. return -1;
  166. }
  167. if (err == 0) {
  168. error("bluetoothd connect timeout");
  169. return -1;
  170. }
  171. new_sk = accept(sk, NULL, NULL);
  172. if (new_sk < 0) {
  173. err = errno;
  174. error("Failed to accept socket: %d (%s)", err, strerror(err));
  175. return -1;
  176. }
  177. return new_sk;
  178. }
  179. bool hal_ipc_accept(void)
  180. {
  181. int err;
  182. cmd_sk = accept_connection(listen_sk);
  183. if (cmd_sk < 0)
  184. return false;
  185. notif_sk = accept_connection(listen_sk);
  186. if (notif_sk < 0) {
  187. close(cmd_sk);
  188. cmd_sk = -1;
  189. return false;
  190. }
  191. err = pthread_create(&notif_th, NULL, notification_handler, NULL);
  192. if (err) {
  193. notif_th = 0;
  194. error("Failed to start notification thread: %d (%s)", err,
  195. strerror(err));
  196. close(cmd_sk);
  197. cmd_sk = -1;
  198. close(notif_sk);
  199. notif_sk = -1;
  200. return false;
  201. }
  202. info("IPC connected");
  203. return true;
  204. }
  205. bool hal_ipc_init(const char *path, size_t size)
  206. {
  207. struct sockaddr_un addr;
  208. int sk;
  209. int err;
  210. sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
  211. if (sk < 0) {
  212. err = errno;
  213. error("Failed to create socket: %d (%s)", err,
  214. strerror(err));
  215. return false;
  216. }
  217. memset(&addr, 0, sizeof(addr));
  218. addr.sun_family = AF_UNIX;
  219. memcpy(addr.sun_path, path, size);
  220. if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  221. err = errno;
  222. error("Failed to bind socket: %d (%s)", err, strerror(err));
  223. close(sk);
  224. return false;
  225. }
  226. if (listen(sk, 2) < 0) {
  227. err = errno;
  228. error("Failed to listen on socket: %d (%s)", err,
  229. strerror(err));
  230. close(sk);
  231. return false;
  232. }
  233. listen_sk = sk;
  234. return true;
  235. }
  236. void hal_ipc_cleanup(void)
  237. {
  238. close(listen_sk);
  239. listen_sk = -1;
  240. pthread_mutex_lock(&cmd_sk_mutex);
  241. if (cmd_sk >= 0) {
  242. close(cmd_sk);
  243. cmd_sk = -1;
  244. }
  245. pthread_mutex_unlock(&cmd_sk_mutex);
  246. if (notif_sk < 0)
  247. return;
  248. shutdown(notif_sk, SHUT_RD);
  249. pthread_join(notif_th, NULL);
  250. notif_th = 0;
  251. }
  252. int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param,
  253. size_t *rsp_len, void *rsp, int *fd)
  254. {
  255. ssize_t ret;
  256. struct msghdr msg;
  257. struct iovec iv[2];
  258. struct ipc_hdr cmd;
  259. char cmsgbuf[CMSG_SPACE(sizeof(int))];
  260. struct ipc_status s;
  261. size_t s_len = sizeof(s);
  262. if (cmd_sk < 0) {
  263. error("Invalid cmd socket passed to hal_ipc_cmd");
  264. goto failed;
  265. }
  266. if (!rsp || !rsp_len) {
  267. memset(&s, 0, s_len);
  268. rsp_len = &s_len;
  269. rsp = &s;
  270. }
  271. memset(&msg, 0, sizeof(msg));
  272. memset(&cmd, 0, sizeof(cmd));
  273. cmd.service_id = service_id;
  274. cmd.opcode = opcode;
  275. cmd.len = len;
  276. iv[0].iov_base = &cmd;
  277. iv[0].iov_len = sizeof(cmd);
  278. iv[1].iov_base = param;
  279. iv[1].iov_len = len;
  280. msg.msg_iov = iv;
  281. msg.msg_iovlen = 2;
  282. pthread_mutex_lock(&cmd_sk_mutex);
  283. ret = sendmsg(cmd_sk, &msg, 0);
  284. if (ret < 0) {
  285. error("Sending command failed:%s", strerror(errno));
  286. pthread_mutex_unlock(&cmd_sk_mutex);
  287. goto failed;
  288. }
  289. /* socket was shutdown */
  290. if (ret == 0) {
  291. error("Command socket closed");
  292. pthread_mutex_unlock(&cmd_sk_mutex);
  293. goto failed;
  294. }
  295. memset(&msg, 0, sizeof(msg));
  296. memset(&cmd, 0, sizeof(cmd));
  297. iv[0].iov_base = &cmd;
  298. iv[0].iov_len = sizeof(cmd);
  299. iv[1].iov_base = rsp;
  300. iv[1].iov_len = *rsp_len;
  301. msg.msg_iov = iv;
  302. msg.msg_iovlen = 2;
  303. if (fd) {
  304. memset(cmsgbuf, 0, sizeof(cmsgbuf));
  305. msg.msg_control = cmsgbuf;
  306. msg.msg_controllen = sizeof(cmsgbuf);
  307. }
  308. ret = recvmsg(cmd_sk, &msg, 0);
  309. pthread_mutex_unlock(&cmd_sk_mutex);
  310. if (ret < 0) {
  311. error("Receiving command response failed: %s", strerror(errno));
  312. goto failed;
  313. }
  314. if (ret < (ssize_t) sizeof(cmd)) {
  315. error("Too small response received(%zd bytes)", ret);
  316. goto failed;
  317. }
  318. if (cmd.service_id != service_id) {
  319. error("Invalid service id (0x%x vs 0x%x)",
  320. cmd.service_id, service_id);
  321. goto failed;
  322. }
  323. if (ret != (ssize_t) (sizeof(cmd) + cmd.len)) {
  324. error("Malformed response received(%zd bytes)", ret);
  325. goto failed;
  326. }
  327. if (cmd.opcode != opcode && cmd.opcode != HAL_OP_STATUS) {
  328. error("Invalid opcode received (0x%x vs 0x%x)",
  329. cmd.opcode, opcode);
  330. goto failed;
  331. }
  332. if (cmd.opcode == HAL_OP_STATUS) {
  333. struct ipc_status *s = rsp;
  334. if (sizeof(*s) != cmd.len) {
  335. error("Invalid status length");
  336. goto failed;
  337. }
  338. if (s->code == HAL_STATUS_SUCCESS) {
  339. error("Invalid success status response");
  340. goto failed;
  341. }
  342. return s->code;
  343. }
  344. /* Receive auxiliary data in msg */
  345. if (fd) {
  346. struct cmsghdr *cmsg;
  347. *fd = -1;
  348. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
  349. cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  350. if (cmsg->cmsg_level == SOL_SOCKET
  351. && cmsg->cmsg_type == SCM_RIGHTS) {
  352. memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
  353. break;
  354. }
  355. }
  356. }
  357. *rsp_len = cmd.len;
  358. return BT_STATUS_SUCCESS;
  359. failed:
  360. exit(EXIT_FAILURE);
  361. }