coroipcc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. /*
  2. * vi: set autoindent tabstop=4 shiftwidth=4 :
  3. *
  4. * Copyright (c) 2002-2006 MontaVista Software, Inc.
  5. * Copyright (c) 2006-2009 Red Hat, Inc.
  6. *
  7. * All rights reserved.
  8. *
  9. * Author: Steven Dake (sdake@redhat.com)
  10. *
  11. * This software licensed under BSD license, the text of which follows:
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. * - Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  22. * contributors may be used to endorse or promote products derived from this
  23. * software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  35. * THE POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include <config.h>
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <unistd.h>
  41. #include <errno.h>
  42. #include <string.h>
  43. #include <fcntl.h>
  44. #include <sys/ioctl.h>
  45. #include <sys/types.h>
  46. #include <sys/uio.h>
  47. #include <sys/socket.h>
  48. #include <sys/select.h>
  49. #include <sys/time.h>
  50. #include <sys/un.h>
  51. #include <net/if.h>
  52. #include <arpa/inet.h>
  53. #include <netinet/in.h>
  54. #include <assert.h>
  55. #include <sys/shm.h>
  56. #include <sys/sem.h>
  57. #include <sys/mman.h>
  58. #include <corosync/corotypes.h>
  59. #include <corosync/coroipc_types.h>
  60. #include <corosync/coroipc_ipc.h>
  61. #include <corosync/coroipcc.h>
  62. struct ipc_segment {
  63. int fd;
  64. int shmid;
  65. int semid;
  66. int flow_control_state;
  67. struct control_buffer *control_buffer;
  68. char *request_buffer;
  69. char *response_buffer;
  70. char *dispatch_buffer;
  71. size_t control_size;
  72. size_t request_size;
  73. size_t response_size;
  74. size_t dispatch_size;
  75. uid_t euid;
  76. };
  77. #if defined(COROSYNC_LINUX)
  78. /* SUN_LEN is broken for abstract namespace
  79. */
  80. #define AIS_SUN_LEN(a) sizeof(*(a))
  81. #else
  82. #define AIS_SUN_LEN(a) SUN_LEN(a)
  83. #endif
  84. #ifdef SO_NOSIGPIPE
  85. void socket_nosigpipe(int s)
  86. {
  87. int on = 1;
  88. setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
  89. }
  90. #endif
  91. #ifndef MSG_NOSIGNAL
  92. #define MSG_NOSIGNAL 0
  93. #endif
  94. static int
  95. coroipcc_send (
  96. int s,
  97. void *msg,
  98. size_t len)
  99. {
  100. int result;
  101. struct msghdr msg_send;
  102. struct iovec iov_send;
  103. char *rbuf = msg;
  104. int processed = 0;
  105. msg_send.msg_iov = &iov_send;
  106. msg_send.msg_iovlen = 1;
  107. msg_send.msg_name = 0;
  108. msg_send.msg_namelen = 0;
  109. msg_send.msg_control = 0;
  110. msg_send.msg_controllen = 0;
  111. msg_send.msg_flags = 0;
  112. retry_send:
  113. iov_send.iov_base = &rbuf[processed];
  114. iov_send.iov_len = len - processed;
  115. result = sendmsg (s, &msg_send, MSG_NOSIGNAL);
  116. /*
  117. * return immediately on any kind of syscall error that maps to
  118. * CS_ERR if no part of message has been sent
  119. */
  120. if (result == -1 && processed == 0) {
  121. if (errno == EINTR) {
  122. goto error_exit;
  123. }
  124. if (errno == EAGAIN) {
  125. goto error_exit;
  126. }
  127. if (errno == EFAULT) {
  128. goto error_exit;
  129. }
  130. }
  131. /*
  132. * retry read operations that are already started except
  133. * for fault in that case, return ERR_LIBRARY
  134. */
  135. if (result == -1 && processed > 0) {
  136. if (errno == EINTR) {
  137. goto retry_send;
  138. }
  139. if (errno == EAGAIN) {
  140. goto retry_send;
  141. }
  142. if (errno == EFAULT) {
  143. goto error_exit;
  144. }
  145. }
  146. /*
  147. * return ERR_LIBRARY on any other syscall error
  148. */
  149. if (result == -1) {
  150. goto error_exit;
  151. }
  152. processed += result;
  153. if (processed != len) {
  154. goto retry_send;
  155. }
  156. return (0);
  157. error_exit:
  158. return (-1);
  159. }
  160. static int
  161. coroipcc_recv (
  162. int s,
  163. void *msg,
  164. size_t len)
  165. {
  166. int error = 0;
  167. int result;
  168. struct msghdr msg_recv;
  169. struct iovec iov_recv;
  170. char *rbuf = msg;
  171. int processed = 0;
  172. msg_recv.msg_iov = &iov_recv;
  173. msg_recv.msg_iovlen = 1;
  174. msg_recv.msg_name = 0;
  175. msg_recv.msg_namelen = 0;
  176. msg_recv.msg_control = 0;
  177. msg_recv.msg_controllen = 0;
  178. msg_recv.msg_flags = 0;
  179. retry_recv:
  180. iov_recv.iov_base = (void *)&rbuf[processed];
  181. iov_recv.iov_len = len - processed;
  182. result = recvmsg (s, &msg_recv, MSG_NOSIGNAL|MSG_WAITALL);
  183. if (result == -1 && errno == EINTR) {
  184. goto retry_recv;
  185. }
  186. if (result == -1 && errno == EAGAIN) {
  187. goto retry_recv;
  188. }
  189. #if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
  190. /* On many OS poll never return POLLHUP or POLLERR.
  191. * EOF is detected when recvmsg return 0.
  192. */
  193. if (result == 0) {
  194. error = -1;
  195. goto error_exit;
  196. }
  197. #endif
  198. if (result == -1 || result == 0) {
  199. error = -1;
  200. goto error_exit;
  201. }
  202. processed += result;
  203. if (processed != len) {
  204. goto retry_recv;
  205. }
  206. assert (processed == len);
  207. error_exit:
  208. return (0);
  209. }
  210. static int
  211. priv_change_send (struct ipc_segment *ipc_segment)
  212. {
  213. char buf_req;
  214. mar_req_priv_change req_priv_change;
  215. unsigned int res;
  216. req_priv_change.euid = geteuid();
  217. /*
  218. * Don't resend request unless euid has changed
  219. */
  220. if (ipc_segment->euid == req_priv_change.euid) {
  221. return (0);
  222. }
  223. req_priv_change.egid = getegid();
  224. buf_req = MESSAGE_REQ_CHANGE_EUID;
  225. res = coroipcc_send (ipc_segment->fd, &buf_req, 1);
  226. if (res == -1) {
  227. return (-1);
  228. }
  229. res = coroipcc_send (ipc_segment->fd, &req_priv_change,
  230. sizeof (req_priv_change));
  231. if (res == -1) {
  232. return (-1);
  233. }
  234. ipc_segment->euid = req_priv_change.euid;
  235. return (0);
  236. }
  237. #if defined(_SEM_SEMUN_UNDEFINED)
  238. union semun {
  239. int val;
  240. struct semid_ds *buf;
  241. unsigned short int *array;
  242. struct seminfo *__buf;
  243. };
  244. #endif
  245. static int
  246. circular_memory_map (char *path, const char *file, void **buf, size_t bytes)
  247. {
  248. int fd;
  249. void *addr_orig;
  250. void *addr;
  251. int res;
  252. sprintf (path, "/dev/shm/%s", file);
  253. fd = mkstemp (path);
  254. if (fd == -1) {
  255. sprintf (path, LOCALSTATEDIR "/run/%s", file);
  256. fd = mkstemp (path);
  257. if (fd == -1) {
  258. return (-1);
  259. }
  260. }
  261. res = ftruncate (fd, bytes);
  262. addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
  263. MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  264. if (addr_orig == MAP_FAILED) {
  265. return (-1);
  266. }
  267. addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
  268. MAP_FIXED | MAP_SHARED, fd, 0);
  269. if (addr != addr_orig) {
  270. return (-1);
  271. }
  272. addr = mmap (((char *)addr_orig) + bytes,
  273. bytes, PROT_READ | PROT_WRITE,
  274. MAP_FIXED | MAP_SHARED, fd, 0);
  275. res = close (fd);
  276. if (res) {
  277. return (-1);
  278. }
  279. *buf = addr_orig;
  280. return (0);
  281. }
  282. static void
  283. memory_unmap (void *addr, size_t bytes)
  284. {
  285. int res;
  286. res = munmap (addr, bytes);
  287. }
  288. static int
  289. memory_map (char *path, const char *file, void **buf, size_t bytes)
  290. {
  291. int fd;
  292. void *addr_orig;
  293. void *addr;
  294. int res;
  295. sprintf (path, "/dev/shm/%s", file);
  296. fd = mkstemp (path);
  297. if (fd == -1) {
  298. sprintf (path, LOCALSTATEDIR "/run/%s", file);
  299. fd = mkstemp (path);
  300. if (fd == -1) {
  301. return (-1);
  302. }
  303. }
  304. res = ftruncate (fd, bytes);
  305. addr_orig = mmap (NULL, bytes, PROT_NONE,
  306. MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  307. if (addr_orig == MAP_FAILED) {
  308. return (-1);
  309. }
  310. addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
  311. MAP_FIXED | MAP_SHARED, fd, 0);
  312. if (addr != addr_orig) {
  313. return (-1);
  314. }
  315. res = close (fd);
  316. if (res) {
  317. return (-1);
  318. }
  319. *buf = addr_orig;
  320. return (0);
  321. }
  322. extern cs_error_t
  323. coroipcc_service_connect (
  324. const char *socket_name,
  325. unsigned int service,
  326. size_t request_size,
  327. size_t response_size,
  328. size_t dispatch_size,
  329. void **ipc_context)
  330. {
  331. int request_fd;
  332. struct sockaddr_un address;
  333. cs_error_t error;
  334. struct ipc_segment *ipc_segment;
  335. key_t semkey = 0;
  336. int res;
  337. mar_req_setup_t req_setup;
  338. mar_res_setup_t res_setup;
  339. union semun semun;
  340. char control_map_path[128];
  341. char request_map_path[128];
  342. char response_map_path[128];
  343. char dispatch_map_path[128];
  344. res_setup.error = CS_ERR_LIBRARY;
  345. request_fd = socket (PF_UNIX, SOCK_STREAM, 0);
  346. if (request_fd == -1) {
  347. return (-1);
  348. }
  349. memset (&address, 0, sizeof (struct sockaddr_un));
  350. #if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
  351. address.sun_len = sizeof(struct sockaddr_un);
  352. #endif
  353. address.sun_family = PF_UNIX;
  354. #if defined(COROSYNC_LINUX)
  355. sprintf (address.sun_path + 1, "%s", socket_name);
  356. #else
  357. sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name);
  358. #endif
  359. res = connect (request_fd, (struct sockaddr *)&address,
  360. AIS_SUN_LEN(&address));
  361. if (res == -1) {
  362. close (request_fd);
  363. return (CS_ERR_TRY_AGAIN);
  364. }
  365. ipc_segment = malloc (sizeof (struct ipc_segment));
  366. if (ipc_segment == NULL) {
  367. close (request_fd);
  368. return (-1);
  369. }
  370. bzero (ipc_segment, sizeof (struct ipc_segment));
  371. /*
  372. * Allocate a semaphore segment
  373. */
  374. while (1) {
  375. semkey = random();
  376. ipc_segment->euid = geteuid ();
  377. if ((ipc_segment->semid
  378. = semget (semkey, 3, IPC_CREAT|IPC_EXCL|0600)) != -1) {
  379. break;
  380. }
  381. if (errno != EEXIST) {
  382. goto error_exit;
  383. }
  384. }
  385. semun.val = 0;
  386. res = semctl (ipc_segment->semid, 0, SETVAL, semun);
  387. if (res != 0) {
  388. goto error_exit;
  389. }
  390. res = semctl (ipc_segment->semid, 1, SETVAL, semun);
  391. if (res != 0) {
  392. goto error_exit;
  393. }
  394. res = memory_map (
  395. control_map_path,
  396. "control_buffer-XXXXXX",
  397. (void *)&ipc_segment->control_buffer,
  398. 8192);
  399. res = memory_map (
  400. request_map_path,
  401. "request_buffer-XXXXXX",
  402. (void *)&ipc_segment->request_buffer,
  403. request_size);
  404. res = memory_map (
  405. response_map_path,
  406. "response_buffer-XXXXXX",
  407. (void *)&ipc_segment->response_buffer,
  408. response_size);
  409. res = circular_memory_map (
  410. dispatch_map_path,
  411. "dispatch_buffer-XXXXXX",
  412. (void *)&ipc_segment->dispatch_buffer,
  413. dispatch_size);
  414. /*
  415. * Initialize IPC setup message
  416. */
  417. req_setup.service = service;
  418. strcpy (req_setup.control_file, control_map_path);
  419. strcpy (req_setup.request_file, request_map_path);
  420. strcpy (req_setup.response_file, response_map_path);
  421. strcpy (req_setup.dispatch_file, dispatch_map_path);
  422. req_setup.control_size = 8192;
  423. req_setup.request_size = request_size;
  424. req_setup.response_size = response_size;
  425. req_setup.dispatch_size = dispatch_size;
  426. req_setup.semkey = semkey;
  427. error = coroipcc_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
  428. if (error != 0) {
  429. goto error_exit;
  430. }
  431. error = coroipcc_recv (request_fd, &res_setup, sizeof (mar_res_setup_t));
  432. if (error != 0) {
  433. goto error_exit;
  434. }
  435. ipc_segment->fd = request_fd;
  436. ipc_segment->flow_control_state = 0;
  437. if (res_setup.error == CS_ERR_TRY_AGAIN) {
  438. goto error_exit;
  439. }
  440. ipc_segment->control_size = 8192;
  441. ipc_segment->request_size = request_size;
  442. ipc_segment->response_size = response_size;
  443. ipc_segment->dispatch_size = dispatch_size;
  444. *ipc_context = ipc_segment;
  445. return (res_setup.error);
  446. error_exit:
  447. close (request_fd);
  448. if (ipc_segment->semid > 0)
  449. semctl (ipc_segment->semid, 0, IPC_RMID);
  450. return (res_setup.error);
  451. }
  452. cs_error_t
  453. coroipcc_service_disconnect (
  454. void *ipc_context)
  455. {
  456. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  457. shutdown (ipc_segment->fd, SHUT_RDWR);
  458. close (ipc_segment->fd);
  459. /*
  460. * << 1 (or multiplied by 2) because this is a wrapped memory buffer
  461. */
  462. memory_unmap (ipc_segment->control_buffer, ipc_segment->control_size);
  463. memory_unmap (ipc_segment->request_buffer, ipc_segment->request_size);
  464. memory_unmap (ipc_segment->response_buffer, ipc_segment->response_size);
  465. memory_unmap (ipc_segment->dispatch_buffer, (ipc_segment->dispatch_size) << 1);
  466. free (ipc_segment);
  467. return (CS_OK);
  468. }
  469. int
  470. coroipcc_dispatch_flow_control_get (
  471. void *ipc_context)
  472. {
  473. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  474. return (ipc_segment->flow_control_state);
  475. }
  476. int
  477. coroipcc_fd_get (void *ipc_ctx)
  478. {
  479. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
  480. return (ipc_segment->fd);
  481. }
  482. int
  483. coroipcc_dispatch_get (void *ipc_ctx, void **data, int timeout)
  484. {
  485. struct pollfd ufds;
  486. int poll_events;
  487. char buf;
  488. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
  489. int res;
  490. char buf_two = 1;
  491. char *data_addr;
  492. ufds.fd = ipc_segment->fd;
  493. ufds.events = POLLIN;
  494. ufds.revents = 0;
  495. retry_poll:
  496. poll_events = poll (&ufds, 1, timeout);
  497. if (poll_events == -1 && errno == EINTR) {
  498. goto retry_poll;
  499. } else
  500. if (poll_events == -1) {
  501. return (-1);
  502. } else
  503. if (poll_events == 0) {
  504. return (0);
  505. }
  506. if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) {
  507. return (-1);
  508. }
  509. retry_recv:
  510. res = recv (ipc_segment->fd, &buf, 1, 0);
  511. if (res == -1 && errno == EINTR) {
  512. goto retry_recv;
  513. } else
  514. if (res == -1) {
  515. return (-1);
  516. }
  517. if (res == 0) {
  518. return (-1);
  519. }
  520. ipc_segment->flow_control_state = 0;
  521. if (buf == 1 || buf == 2) {
  522. ipc_segment->flow_control_state = 1;
  523. }
  524. /*
  525. * Notify executive to flush any pending dispatch messages
  526. */
  527. if (ipc_segment->flow_control_state) {
  528. buf_two = MESSAGE_REQ_OUTQ_FLUSH;
  529. res = coroipcc_send (ipc_segment->fd, &buf_two, 1);
  530. assert (res == 0); //TODO
  531. }
  532. /*
  533. * This is just a notification of flow control starting at the addition
  534. * of a new pending message, not a message to dispatch
  535. */
  536. if (buf == 2) {
  537. return (0);
  538. }
  539. if (buf == 3) {
  540. return (0);
  541. }
  542. data_addr = ipc_segment->dispatch_buffer;
  543. data_addr = &data_addr[ipc_segment->control_buffer->read];
  544. *data = (void *)data_addr;
  545. return (1);
  546. }
  547. int
  548. coroipcc_dispatch_put (void *ipc_ctx)
  549. {
  550. struct sembuf sop;
  551. coroipc_response_header_t *header;
  552. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
  553. int res;
  554. char *addr;
  555. unsigned int read_idx;
  556. sop.sem_num = 2;
  557. sop.sem_op = -1;
  558. sop.sem_flg = 0;
  559. retry_semop:
  560. res = semop (ipc_segment->semid, &sop, 1);
  561. if (res == -1 && errno == EINTR) {
  562. goto retry_semop;
  563. } else
  564. if (res == -1 && errno == EACCES) {
  565. priv_change_send (ipc_segment);
  566. goto retry_semop;
  567. } else
  568. if (res == -1) {
  569. return (-1);
  570. }
  571. addr = ipc_segment->dispatch_buffer;
  572. read_idx = ipc_segment->control_buffer->read;
  573. header = (coroipc_response_header_t *) &addr[read_idx];
  574. ipc_segment->control_buffer->read =
  575. (read_idx + header->size) % ipc_segment->dispatch_size;
  576. return (0);
  577. }
  578. static cs_error_t
  579. coroipcc_msg_send (
  580. void *ipc_context,
  581. const struct iovec *iov,
  582. unsigned int iov_len)
  583. {
  584. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  585. struct sembuf sop;
  586. int i;
  587. int res;
  588. int req_buffer_idx = 0;
  589. for (i = 0; i < iov_len; i++) {
  590. memcpy (&ipc_segment->request_buffer[req_buffer_idx],
  591. iov[i].iov_base,
  592. iov[i].iov_len);
  593. req_buffer_idx += iov[i].iov_len;
  594. }
  595. /*
  596. * Signal semaphore #0 indicting a new message from client
  597. * to server request queue
  598. */
  599. sop.sem_num = 0;
  600. sop.sem_op = 1;
  601. sop.sem_flg = 0;
  602. retry_semop:
  603. res = semop (ipc_segment->semid, &sop, 1);
  604. if (res == -1 && errno == EINTR) {
  605. goto retry_semop;
  606. } else
  607. if (res == -1 && errno == EACCES) {
  608. priv_change_send (ipc_segment);
  609. goto retry_semop;
  610. } else
  611. if (res == -1) {
  612. return (CS_ERR_LIBRARY);
  613. }
  614. return (CS_OK);
  615. }
  616. static cs_error_t
  617. coroipcc_reply_receive (
  618. void *ipc_context,
  619. void *res_msg,
  620. size_t res_len)
  621. {
  622. struct sembuf sop;
  623. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  624. coroipc_response_header_t *response_header;
  625. int res;
  626. /*
  627. * Wait for semaphore #1 indicating a new message from server
  628. * to client in the response queue
  629. */
  630. sop.sem_num = 1;
  631. sop.sem_op = -1;
  632. sop.sem_flg = 0;
  633. retry_semop:
  634. res = semop (ipc_segment->semid, &sop, 1);
  635. if (res == -1 && errno == EINTR) {
  636. goto retry_semop;
  637. } else
  638. if (res == -1 && errno == EACCES) {
  639. priv_change_send (ipc_segment);
  640. goto retry_semop;
  641. } else
  642. if (res == -1) {
  643. return (CS_ERR_LIBRARY);
  644. }
  645. response_header = (coroipc_response_header_t *)ipc_segment->response_buffer;
  646. if (response_header->error == CS_ERR_TRY_AGAIN) {
  647. return (CS_ERR_TRY_AGAIN);
  648. }
  649. memcpy (res_msg, ipc_segment->response_buffer, res_len);
  650. return (CS_OK);
  651. }
  652. static cs_error_t
  653. coroipcc_reply_receive_in_buf (
  654. void *ipc_context,
  655. void **res_msg)
  656. {
  657. struct sembuf sop;
  658. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  659. int res;
  660. /*
  661. * Wait for semaphore #1 indicating a new message from server
  662. * to client in the response queue
  663. */
  664. sop.sem_num = 1;
  665. sop.sem_op = -1;
  666. sop.sem_flg = 0;
  667. retry_semop:
  668. res = semop (ipc_segment->semid, &sop, 1);
  669. if (res == -1 && errno == EINTR) {
  670. goto retry_semop;
  671. } else
  672. if (res == -1 && errno == EACCES) {
  673. priv_change_send (ipc_segment);
  674. goto retry_semop;
  675. } else
  676. if (res == -1) {
  677. return (CS_ERR_LIBRARY);
  678. }
  679. *res_msg = (char *)ipc_segment->response_buffer;
  680. return (CS_OK);
  681. }
  682. cs_error_t
  683. coroipcc_msg_send_reply_receive (
  684. void *ipc_context,
  685. const struct iovec *iov,
  686. unsigned int iov_len,
  687. void *res_msg,
  688. size_t res_len)
  689. {
  690. cs_error_t res;
  691. res = coroipcc_msg_send (ipc_context, iov, iov_len);
  692. if (res != CS_OK) {
  693. return (res);
  694. }
  695. res = coroipcc_reply_receive (ipc_context, res_msg, res_len);
  696. if (res != CS_OK) {
  697. return (res);
  698. }
  699. return (CS_OK);
  700. }
  701. cs_error_t
  702. coroipcc_msg_send_reply_receive_in_buf (
  703. void *ipc_context,
  704. const struct iovec *iov,
  705. unsigned int iov_len,
  706. void **res_msg)
  707. {
  708. unsigned int res;
  709. res = coroipcc_msg_send (ipc_context, iov, iov_len);
  710. if (res != CS_OK) {
  711. return (res);
  712. }
  713. res = coroipcc_reply_receive_in_buf (ipc_context, res_msg);
  714. if (res != CS_OK) {
  715. return (res);
  716. }
  717. return (CS_OK);
  718. }
  719. cs_error_t
  720. coroipcc_zcb_alloc (
  721. void *ipc_context,
  722. void **buffer,
  723. size_t size,
  724. size_t header_size)
  725. {
  726. void *buf = NULL;
  727. char path[128];
  728. unsigned int res;
  729. mar_req_coroipcc_zc_alloc_t req_coroipcc_zc_alloc;
  730. coroipc_response_header_t res_coroipcs_zc_alloc;
  731. size_t map_size;
  732. struct iovec iovec;
  733. struct coroipcs_zc_header *hdr;
  734. map_size = size + header_size + sizeof (struct coroipcs_zc_header);
  735. res = memory_map (path, "cpg_zc-XXXXXX", &buf, size);
  736. assert (res != -1);
  737. req_coroipcc_zc_alloc.header.size = sizeof (mar_req_coroipcc_zc_alloc_t);
  738. req_coroipcc_zc_alloc.header.id = ZC_ALLOC_HEADER;
  739. req_coroipcc_zc_alloc.map_size = map_size;
  740. strcpy (req_coroipcc_zc_alloc.path_to_file, path);
  741. iovec.iov_base = &req_coroipcc_zc_alloc;
  742. iovec.iov_len = sizeof (mar_req_coroipcc_zc_alloc_t);
  743. res = coroipcc_msg_send_reply_receive (
  744. ipc_context,
  745. &iovec,
  746. 1,
  747. &res_coroipcs_zc_alloc,
  748. sizeof (coroipc_response_header_t));
  749. hdr = (struct coroipcs_zc_header *)buf;
  750. hdr->map_size = map_size;
  751. *buffer = ((char *)buf) + sizeof (struct coroipcs_zc_header);
  752. return (CS_OK);
  753. }
  754. cs_error_t
  755. coroipcc_zcb_free (
  756. void *ipc_context,
  757. void *buffer)
  758. {
  759. mar_req_coroipcc_zc_free_t req_coroipcc_zc_free;
  760. coroipc_response_header_t res_coroipcs_zc_free;
  761. struct iovec iovec;
  762. unsigned int res;
  763. struct coroipcs_zc_header *header = (struct coroipcs_zc_header *)((char *)buffer - sizeof (struct coroipcs_zc_header));
  764. req_coroipcc_zc_free.header.size = sizeof (mar_req_coroipcc_zc_free_t);
  765. req_coroipcc_zc_free.header.id = ZC_FREE_HEADER;
  766. req_coroipcc_zc_free.map_size = header->map_size;
  767. req_coroipcc_zc_free.server_address = header->server_address;
  768. iovec.iov_base = &req_coroipcc_zc_free;
  769. iovec.iov_len = sizeof (mar_req_coroipcc_zc_free_t);
  770. res = coroipcc_msg_send_reply_receive (
  771. ipc_context,
  772. &iovec,
  773. 1,
  774. &res_coroipcs_zc_free,
  775. sizeof (coroipc_response_header_t));
  776. munmap (header, header->map_size);
  777. return (CS_OK);
  778. }
  779. cs_error_t
  780. coroipcc_zcb_msg_send_reply_receive (
  781. void *ipc_context,
  782. void *msg,
  783. void *res_msg,
  784. size_t res_len)
  785. {
  786. mar_req_coroipcc_zc_execute_t req_coroipcc_zc_execute;
  787. struct coroipcs_zc_header *hdr;
  788. struct iovec iovec;
  789. cs_error_t res;
  790. hdr = (struct coroipcs_zc_header *)(((char *)msg) - sizeof (struct coroipcs_zc_header));
  791. req_coroipcc_zc_execute.header.size = sizeof (mar_req_coroipcc_zc_execute_t);
  792. req_coroipcc_zc_execute.header.id = ZC_EXECUTE_HEADER;
  793. req_coroipcc_zc_execute.server_address = hdr->server_address;
  794. iovec.iov_base = &req_coroipcc_zc_execute;
  795. iovec.iov_len = sizeof (mar_req_coroipcc_zc_execute_t);
  796. res = coroipcc_msg_send_reply_receive (
  797. ipc_context,
  798. &iovec,
  799. 1,
  800. res_msg,
  801. res_len);
  802. return (res);
  803. }