coroipcc.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  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/ipc_gen.h>
  60. #include <corosync/coroipcc.h>
  61. enum SA_HANDLE_STATE {
  62. SA_HANDLE_STATE_EMPTY,
  63. SA_HANDLE_STATE_PENDINGREMOVAL,
  64. SA_HANDLE_STATE_ACTIVE
  65. };
  66. struct saHandle {
  67. int state;
  68. void *instance;
  69. int refCount;
  70. uint32_t check;
  71. };
  72. struct ipc_segment {
  73. int fd;
  74. int shmid;
  75. int semid;
  76. int flow_control_state;
  77. struct control_buffer *control_buffer;
  78. char *request_buffer;
  79. char *response_buffer;
  80. char *dispatch_buffer;
  81. size_t control_size;
  82. size_t request_size;
  83. size_t response_size;
  84. size_t dispatch_size;
  85. uid_t euid;
  86. };
  87. #if defined(COROSYNC_LINUX)
  88. /* SUN_LEN is broken for abstract namespace
  89. */
  90. #define AIS_SUN_LEN(a) sizeof(*(a))
  91. #else
  92. #define AIS_SUN_LEN(a) SUN_LEN(a)
  93. #endif
  94. #ifdef SO_NOSIGPIPE
  95. void socket_nosigpipe(int s)
  96. {
  97. int on = 1;
  98. setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
  99. }
  100. #endif
  101. #ifndef MSG_NOSIGNAL
  102. #define MSG_NOSIGNAL 0
  103. #endif
  104. static int
  105. coroipcc_send (
  106. int s,
  107. void *msg,
  108. size_t len)
  109. {
  110. int result;
  111. struct msghdr msg_send;
  112. struct iovec iov_send;
  113. char *rbuf = msg;
  114. int processed = 0;
  115. msg_send.msg_iov = &iov_send;
  116. msg_send.msg_iovlen = 1;
  117. msg_send.msg_name = 0;
  118. msg_send.msg_namelen = 0;
  119. msg_send.msg_control = 0;
  120. msg_send.msg_controllen = 0;
  121. msg_send.msg_flags = 0;
  122. retry_send:
  123. iov_send.iov_base = &rbuf[processed];
  124. iov_send.iov_len = len - processed;
  125. result = sendmsg (s, &msg_send, MSG_NOSIGNAL);
  126. /*
  127. * return immediately on any kind of syscall error that maps to
  128. * CS_ERR if no part of message has been sent
  129. */
  130. if (result == -1 && processed == 0) {
  131. if (errno == EINTR) {
  132. goto error_exit;
  133. }
  134. if (errno == EAGAIN) {
  135. goto error_exit;
  136. }
  137. if (errno == EFAULT) {
  138. goto error_exit;
  139. }
  140. }
  141. /*
  142. * retry read operations that are already started except
  143. * for fault in that case, return ERR_LIBRARY
  144. */
  145. if (result == -1 && processed > 0) {
  146. if (errno == EINTR) {
  147. goto retry_send;
  148. }
  149. if (errno == EAGAIN) {
  150. goto retry_send;
  151. }
  152. if (errno == EFAULT) {
  153. goto error_exit;
  154. }
  155. }
  156. /*
  157. * return ERR_LIBRARY on any other syscall error
  158. */
  159. if (result == -1) {
  160. goto error_exit;
  161. }
  162. processed += result;
  163. if (processed != len) {
  164. goto retry_send;
  165. }
  166. return (0);
  167. error_exit:
  168. return (-1);
  169. }
  170. static int
  171. coroipcc_recv (
  172. int s,
  173. void *msg,
  174. size_t len)
  175. {
  176. int error = 0;
  177. int result;
  178. struct msghdr msg_recv;
  179. struct iovec iov_recv;
  180. char *rbuf = msg;
  181. int processed = 0;
  182. msg_recv.msg_iov = &iov_recv;
  183. msg_recv.msg_iovlen = 1;
  184. msg_recv.msg_name = 0;
  185. msg_recv.msg_namelen = 0;
  186. msg_recv.msg_control = 0;
  187. msg_recv.msg_controllen = 0;
  188. msg_recv.msg_flags = 0;
  189. retry_recv:
  190. iov_recv.iov_base = (void *)&rbuf[processed];
  191. iov_recv.iov_len = len - processed;
  192. result = recvmsg (s, &msg_recv, MSG_NOSIGNAL|MSG_WAITALL);
  193. if (result == -1 && errno == EINTR) {
  194. goto retry_recv;
  195. }
  196. if (result == -1 && errno == EAGAIN) {
  197. goto retry_recv;
  198. }
  199. #if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
  200. /* On many OS poll never return POLLHUP or POLLERR.
  201. * EOF is detected when recvmsg return 0.
  202. */
  203. if (result == 0) {
  204. error = -1;
  205. goto error_exit;
  206. }
  207. #endif
  208. if (result == -1 || result == 0) {
  209. error = -1;
  210. goto error_exit;
  211. }
  212. processed += result;
  213. if (processed != len) {
  214. goto retry_recv;
  215. }
  216. assert (processed == len);
  217. error_exit:
  218. return (0);
  219. }
  220. static int
  221. priv_change_send (struct ipc_segment *ipc_segment)
  222. {
  223. char buf_req;
  224. mar_req_priv_change req_priv_change;
  225. unsigned int res;
  226. req_priv_change.euid = geteuid();
  227. /*
  228. * Don't resend request unless euid has changed
  229. */
  230. if (ipc_segment->euid == req_priv_change.euid) {
  231. return (0);
  232. }
  233. req_priv_change.egid = getegid();
  234. buf_req = MESSAGE_REQ_CHANGE_EUID;
  235. res = coroipcc_send (ipc_segment->fd, &buf_req, 1);
  236. if (res == -1) {
  237. return (-1);
  238. }
  239. res = coroipcc_send (ipc_segment->fd, &req_priv_change,
  240. sizeof (req_priv_change));
  241. if (res == -1) {
  242. return (-1);
  243. }
  244. ipc_segment->euid = req_priv_change.euid;
  245. return (0);
  246. }
  247. #if defined(_SEM_SEMUN_UNDEFINED)
  248. union semun {
  249. int val;
  250. struct semid_ds *buf;
  251. unsigned short int *array;
  252. struct seminfo *__buf;
  253. };
  254. #endif
  255. static int
  256. circular_memory_map (char *path, const char *file, void **buf, size_t bytes)
  257. {
  258. int fd;
  259. void *addr_orig;
  260. void *addr;
  261. int res;
  262. sprintf (path, "/dev/shm/%s", file);
  263. fd = mkstemp (path);
  264. if (fd == -1) {
  265. sprintf (path, "/var/run/%s", file);
  266. fd = mkstemp (path);
  267. if (fd == -1) {
  268. return (-1);
  269. }
  270. }
  271. res = ftruncate (fd, bytes);
  272. addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
  273. MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  274. if (addr_orig == MAP_FAILED) {
  275. return (-1);
  276. }
  277. addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
  278. MAP_FIXED | MAP_SHARED, fd, 0);
  279. if (addr != addr_orig) {
  280. return (-1);
  281. }
  282. addr = mmap (((char *)addr_orig) + bytes,
  283. bytes, PROT_READ | PROT_WRITE,
  284. MAP_FIXED | MAP_SHARED, fd, 0);
  285. res = close (fd);
  286. if (res) {
  287. return (-1);
  288. }
  289. *buf = addr_orig;
  290. return (0);
  291. }
  292. static void
  293. memory_unmap (void *addr, size_t bytes)
  294. {
  295. int res;
  296. res = munmap (addr, bytes);
  297. }
  298. static int
  299. memory_map (char *path, const char *file, void **buf, size_t bytes)
  300. {
  301. int fd;
  302. void *addr_orig;
  303. void *addr;
  304. int res;
  305. sprintf (path, "/dev/shm/%s", file);
  306. fd = mkstemp (path);
  307. if (fd == -1) {
  308. sprintf (path, "/var/run/%s", file);
  309. fd = mkstemp (path);
  310. if (fd == -1) {
  311. return (-1);
  312. }
  313. }
  314. res = ftruncate (fd, bytes);
  315. addr_orig = mmap (NULL, bytes, PROT_NONE,
  316. MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  317. if (addr_orig == MAP_FAILED) {
  318. return (-1);
  319. }
  320. addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
  321. MAP_FIXED | MAP_SHARED, fd, 0);
  322. if (addr != addr_orig) {
  323. return (-1);
  324. }
  325. res = close (fd);
  326. if (res) {
  327. return (-1);
  328. }
  329. *buf = addr_orig;
  330. return (0);
  331. }
  332. extern cs_error_t
  333. coroipcc_service_connect (
  334. const char *socket_name,
  335. unsigned int service,
  336. size_t request_size,
  337. size_t response_size,
  338. size_t dispatch_size,
  339. void **ipc_context)
  340. {
  341. int request_fd;
  342. struct sockaddr_un address;
  343. cs_error_t error;
  344. struct ipc_segment *ipc_segment;
  345. key_t semkey = 0;
  346. int res;
  347. mar_req_setup_t req_setup;
  348. mar_res_setup_t res_setup;
  349. union semun semun;
  350. char control_map_path[128];
  351. char request_map_path[128];
  352. char response_map_path[128];
  353. char dispatch_map_path[128];
  354. res_setup.error = CS_ERR_LIBRARY;
  355. request_fd = socket (PF_UNIX, SOCK_STREAM, 0);
  356. if (request_fd == -1) {
  357. return (-1);
  358. }
  359. memset (&address, 0, sizeof (struct sockaddr_un));
  360. #if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
  361. address.sun_len = sizeof(struct sockaddr_un);
  362. #endif
  363. address.sun_family = PF_UNIX;
  364. #if defined(COROSYNC_LINUX)
  365. sprintf (address.sun_path + 1, "%s", socket_name);
  366. #else
  367. sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name);
  368. #endif
  369. res = connect (request_fd, (struct sockaddr *)&address,
  370. AIS_SUN_LEN(&address));
  371. if (res == -1) {
  372. close (request_fd);
  373. return (CS_ERR_TRY_AGAIN);
  374. }
  375. ipc_segment = malloc (sizeof (struct ipc_segment));
  376. if (ipc_segment == NULL) {
  377. close (request_fd);
  378. return (-1);
  379. }
  380. bzero (ipc_segment, sizeof (struct ipc_segment));
  381. /*
  382. * Allocate a semaphore segment
  383. */
  384. while (1) {
  385. semkey = random();
  386. ipc_segment->euid = geteuid ();
  387. if ((ipc_segment->semid
  388. = semget (semkey, 3, IPC_CREAT|IPC_EXCL|0600)) != -1) {
  389. break;
  390. }
  391. if (errno != EEXIST) {
  392. goto error_exit;
  393. }
  394. }
  395. semun.val = 0;
  396. res = semctl (ipc_segment->semid, 0, SETVAL, semun);
  397. if (res != 0) {
  398. goto error_exit;
  399. }
  400. res = semctl (ipc_segment->semid, 1, SETVAL, semun);
  401. if (res != 0) {
  402. goto error_exit;
  403. }
  404. res = memory_map (
  405. control_map_path,
  406. "control_buffer-XXXXXX",
  407. (void *)&ipc_segment->control_buffer,
  408. 8192);
  409. res = memory_map (
  410. request_map_path,
  411. "request_buffer-XXXXXX",
  412. (void *)&ipc_segment->request_buffer,
  413. request_size);
  414. res = memory_map (
  415. response_map_path,
  416. "response_buffer-XXXXXX",
  417. (void *)&ipc_segment->response_buffer,
  418. response_size);
  419. res = circular_memory_map (
  420. dispatch_map_path,
  421. "dispatch_buffer-XXXXXX",
  422. (void *)&ipc_segment->dispatch_buffer,
  423. dispatch_size);
  424. /*
  425. * Initialize IPC setup message
  426. */
  427. req_setup.service = service;
  428. strcpy (req_setup.control_file, control_map_path);
  429. strcpy (req_setup.request_file, request_map_path);
  430. strcpy (req_setup.response_file, response_map_path);
  431. strcpy (req_setup.dispatch_file, dispatch_map_path);
  432. req_setup.control_size = 8192;
  433. req_setup.request_size = request_size;
  434. req_setup.response_size = response_size;
  435. req_setup.dispatch_size = dispatch_size;
  436. req_setup.semkey = semkey;
  437. error = coroipcc_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
  438. if (error != 0) {
  439. goto error_exit;
  440. }
  441. error = coroipcc_recv (request_fd, &res_setup, sizeof (mar_res_setup_t));
  442. if (error != 0) {
  443. goto error_exit;
  444. }
  445. ipc_segment->fd = request_fd;
  446. ipc_segment->flow_control_state = 0;
  447. if (res_setup.error == CS_ERR_TRY_AGAIN) {
  448. goto error_exit;
  449. }
  450. ipc_segment->control_size = 8192;
  451. ipc_segment->request_size = request_size;
  452. ipc_segment->response_size = response_size;
  453. ipc_segment->dispatch_size = dispatch_size;
  454. *ipc_context = ipc_segment;
  455. return (res_setup.error);
  456. error_exit:
  457. close (request_fd);
  458. if (ipc_segment->semid > 0)
  459. semctl (ipc_segment->semid, 0, IPC_RMID);
  460. return (res_setup.error);
  461. }
  462. cs_error_t
  463. coroipcc_service_disconnect (
  464. void *ipc_context)
  465. {
  466. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  467. shutdown (ipc_segment->fd, SHUT_RDWR);
  468. close (ipc_segment->fd);
  469. /*
  470. * << 1 (or multiplied by 2) because this is a wrapped memory buffer
  471. */
  472. memory_unmap (ipc_segment->control_buffer, ipc_segment->control_size);
  473. memory_unmap (ipc_segment->request_buffer, ipc_segment->request_size);
  474. memory_unmap (ipc_segment->response_buffer, ipc_segment->response_size);
  475. memory_unmap (ipc_segment->dispatch_buffer, (ipc_segment->dispatch_size) << 1);
  476. free (ipc_segment);
  477. return (CS_OK);
  478. }
  479. int
  480. coroipcc_dispatch_flow_control_get (
  481. void *ipc_context)
  482. {
  483. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  484. return (ipc_segment->flow_control_state);
  485. }
  486. int
  487. coroipcc_fd_get (void *ipc_ctx)
  488. {
  489. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
  490. return (ipc_segment->fd);
  491. }
  492. int
  493. coroipcc_dispatch_get (void *ipc_ctx, void **data, int timeout)
  494. {
  495. struct pollfd ufds;
  496. int poll_events;
  497. char buf;
  498. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
  499. int res;
  500. char buf_two = 1;
  501. char *data_addr;
  502. ufds.fd = ipc_segment->fd;
  503. ufds.events = POLLIN;
  504. ufds.revents = 0;
  505. retry_poll:
  506. poll_events = poll (&ufds, 1, timeout);
  507. if (poll_events == -1 && errno == EINTR) {
  508. goto retry_poll;
  509. } else
  510. if (poll_events == -1) {
  511. return (-1);
  512. } else
  513. if (poll_events == 0) {
  514. return (0);
  515. }
  516. if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) {
  517. return (-1);
  518. }
  519. retry_recv:
  520. res = recv (ipc_segment->fd, &buf, 1, 0);
  521. if (res == -1 && errno == EINTR) {
  522. goto retry_recv;
  523. } else
  524. if (res == -1) {
  525. return (-1);
  526. }
  527. if (res == 0) {
  528. return (-1);
  529. }
  530. ipc_segment->flow_control_state = 0;
  531. if (buf == 1 || buf == 2) {
  532. ipc_segment->flow_control_state = 1;
  533. }
  534. /*
  535. * Notify executive to flush any pending dispatch messages
  536. */
  537. if (ipc_segment->flow_control_state) {
  538. buf_two = MESSAGE_REQ_OUTQ_FLUSH;
  539. res = coroipcc_send (ipc_segment->fd, &buf_two, 1);
  540. assert (res == 0); //TODO
  541. }
  542. /*
  543. * This is just a notification of flow control starting at the addition
  544. * of a new pending message, not a message to dispatch
  545. */
  546. if (buf == 2) {
  547. return (0);
  548. }
  549. if (buf == 3) {
  550. return (0);
  551. }
  552. data_addr = ipc_segment->dispatch_buffer;
  553. data_addr = &data_addr[ipc_segment->control_buffer->read];
  554. *data = (void *)data_addr;
  555. return (1);
  556. }
  557. int
  558. coroipcc_dispatch_put (void *ipc_ctx)
  559. {
  560. struct sembuf sop;
  561. mar_res_header_t *header;
  562. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
  563. int res;
  564. char *addr;
  565. unsigned int read_idx;
  566. sop.sem_num = 2;
  567. sop.sem_op = -1;
  568. sop.sem_flg = 0;
  569. retry_semop:
  570. res = semop (ipc_segment->semid, &sop, 1);
  571. if (res == -1 && errno == EINTR) {
  572. goto retry_semop;
  573. } else
  574. if (res == -1 && errno == EACCES) {
  575. priv_change_send (ipc_segment);
  576. goto retry_semop;
  577. } else
  578. if (res == -1) {
  579. return (-1);
  580. }
  581. addr = ipc_segment->dispatch_buffer;
  582. read_idx = ipc_segment->control_buffer->read;
  583. header = (mar_res_header_t *) &addr[read_idx];
  584. ipc_segment->control_buffer->read =
  585. (read_idx + header->size) % ipc_segment->dispatch_size;
  586. return (0);
  587. }
  588. static cs_error_t
  589. coroipcc_msg_send (
  590. void *ipc_context,
  591. const struct iovec *iov,
  592. unsigned int iov_len)
  593. {
  594. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  595. struct sembuf sop;
  596. int i;
  597. int res;
  598. int req_buffer_idx = 0;
  599. for (i = 0; i < iov_len; i++) {
  600. memcpy (&ipc_segment->request_buffer[req_buffer_idx],
  601. iov[i].iov_base,
  602. iov[i].iov_len);
  603. req_buffer_idx += iov[i].iov_len;
  604. }
  605. /*
  606. * Signal semaphore #0 indicting a new message from client
  607. * to server request queue
  608. */
  609. sop.sem_num = 0;
  610. sop.sem_op = 1;
  611. sop.sem_flg = 0;
  612. retry_semop:
  613. res = semop (ipc_segment->semid, &sop, 1);
  614. if (res == -1 && errno == EINTR) {
  615. goto retry_semop;
  616. } else
  617. if (res == -1 && errno == EACCES) {
  618. priv_change_send (ipc_segment);
  619. goto retry_semop;
  620. } else
  621. if (res == -1) {
  622. return (CS_ERR_LIBRARY);
  623. }
  624. return (CS_OK);
  625. }
  626. static cs_error_t
  627. coroipcc_reply_receive (
  628. void *ipc_context,
  629. void *res_msg, size_t res_len)
  630. {
  631. struct sembuf sop;
  632. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  633. int res;
  634. /*
  635. * Wait for semaphore #1 indicating a new message from server
  636. * to client in the response queue
  637. */
  638. sop.sem_num = 1;
  639. sop.sem_op = -1;
  640. sop.sem_flg = 0;
  641. retry_semop:
  642. res = semop (ipc_segment->semid, &sop, 1);
  643. if (res == -1 && errno == EINTR) {
  644. goto retry_semop;
  645. } else
  646. if (res == -1 && errno == EACCES) {
  647. priv_change_send (ipc_segment);
  648. goto retry_semop;
  649. } else
  650. if (res == -1) {
  651. return (CS_ERR_LIBRARY);
  652. }
  653. memcpy (res_msg, ipc_segment->response_buffer, res_len);
  654. return (CS_OK);
  655. }
  656. static cs_error_t
  657. coroipcc_reply_receive_in_buf (
  658. void *ipc_context,
  659. void **res_msg)
  660. {
  661. struct sembuf sop;
  662. struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
  663. int res;
  664. /*
  665. * Wait for semaphore #1 indicating a new message from server
  666. * to client in the response queue
  667. */
  668. sop.sem_num = 1;
  669. sop.sem_op = -1;
  670. sop.sem_flg = 0;
  671. retry_semop:
  672. res = semop (ipc_segment->semid, &sop, 1);
  673. if (res == -1 && errno == EINTR) {
  674. goto retry_semop;
  675. } else
  676. if (res == -1 && errno == EACCES) {
  677. priv_change_send (ipc_segment);
  678. goto retry_semop;
  679. } else
  680. if (res == -1) {
  681. return (CS_ERR_LIBRARY);
  682. }
  683. *res_msg = (char *)ipc_segment->response_buffer;
  684. return (CS_OK);
  685. }
  686. cs_error_t
  687. coroipcc_msg_send_reply_receive (
  688. void *ipc_context,
  689. const struct iovec *iov,
  690. unsigned int iov_len,
  691. void *res_msg,
  692. size_t res_len)
  693. {
  694. cs_error_t res;
  695. res = coroipcc_msg_send (ipc_context, iov, iov_len);
  696. if (res != CS_OK) {
  697. return (res);
  698. }
  699. res = coroipcc_reply_receive (ipc_context, res_msg, res_len);
  700. if (res != CS_OK) {
  701. return (res);
  702. }
  703. return (CS_OK);
  704. }
  705. cs_error_t
  706. coroipcc_msg_send_reply_receive_in_buf (
  707. void *ipc_context,
  708. const struct iovec *iov,
  709. unsigned int iov_len,
  710. void **res_msg)
  711. {
  712. unsigned int res;
  713. res = coroipcc_msg_send (ipc_context, iov, iov_len);
  714. if (res != CS_OK) {
  715. return (res);
  716. }
  717. res = coroipcc_reply_receive_in_buf (ipc_context, res_msg);
  718. if (res != CS_OK) {
  719. return (res);
  720. }
  721. return (CS_OK);
  722. }
  723. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  724. static void hdb_lock (struct saHandleDatabase *hdb)
  725. {
  726. pthread_spin_lock (&hdb->lock);
  727. }
  728. static void hdb_unlock (struct saHandleDatabase *hdb)
  729. {
  730. pthread_spin_unlock (&hdb->lock);
  731. }
  732. void saHandleDatabaseLock_init (struct saHandleDatabase *hdb)
  733. {
  734. pthread_spin_init (&hdb->lock, 0);
  735. }
  736. #else
  737. static void hdb_lock (struct saHandleDatabase *hdb)
  738. {
  739. pthread_mutex_lock (&hdb->lock);
  740. }
  741. static void hdb_unlock (struct saHandleDatabase *hdb)
  742. {
  743. pthread_mutex_unlock (&hdb->lock);
  744. }
  745. void saHandleDatabaseLock_init (struct saHandleDatabase *hdb)
  746. {
  747. pthread_mutex_init (&hdb->lock, NULL);
  748. }
  749. #endif
  750. cs_error_t
  751. coroipcc_zcb_alloc (
  752. void *ipc_context,
  753. void **buffer,
  754. size_t size,
  755. size_t header_size)
  756. {
  757. void *buf = NULL;
  758. char path[128];
  759. unsigned int res;
  760. mar_req_coroipcc_zc_alloc_t req_coroipcc_zc_alloc;
  761. mar_res_header_t res_coroipcs_zc_alloc;
  762. size_t map_size;
  763. struct iovec iovec;
  764. struct coroipcs_zc_header *hdr;
  765. map_size = size + header_size + sizeof (struct coroipcs_zc_header);
  766. res = memory_map (path, "cpg_zc-XXXXXX", &buf, size);
  767. assert (res != -1);
  768. req_coroipcc_zc_alloc.header.size = sizeof (mar_req_coroipcc_zc_alloc_t);
  769. req_coroipcc_zc_alloc.header.id = ZC_ALLOC_HEADER;
  770. req_coroipcc_zc_alloc.map_size = map_size;
  771. strcpy (req_coroipcc_zc_alloc.path_to_file, path);
  772. iovec.iov_base = &req_coroipcc_zc_alloc;
  773. iovec.iov_len = sizeof (mar_req_coroipcc_zc_alloc_t);
  774. res = coroipcc_msg_send_reply_receive (
  775. ipc_context,
  776. &iovec,
  777. 1,
  778. &res_coroipcs_zc_alloc,
  779. sizeof (mar_res_header_t));
  780. hdr = (struct coroipcs_zc_header *)buf;
  781. hdr->map_size = map_size;
  782. *buffer = ((char *)buf) + sizeof (struct coroipcs_zc_header);
  783. return (CS_OK);
  784. }
  785. cs_error_t
  786. coroipcc_zcb_free (
  787. void *ipc_context,
  788. void *buffer)
  789. {
  790. mar_req_coroipcc_zc_free_t req_coroipcc_zc_free;
  791. mar_res_header_t res_coroipcs_zc_free;
  792. struct iovec iovec;
  793. unsigned int res;
  794. struct coroipcs_zc_header *header = (struct coroipcs_zc_header *)((char *)buffer - sizeof (struct coroipcs_zc_header));
  795. req_coroipcc_zc_free.header.size = sizeof (mar_req_coroipcc_zc_free_t);
  796. req_coroipcc_zc_free.header.id = ZC_FREE_HEADER;
  797. req_coroipcc_zc_free.map_size = header->map_size;
  798. req_coroipcc_zc_free.server_address = header->server_address;
  799. iovec.iov_base = &req_coroipcc_zc_free;
  800. iovec.iov_len = sizeof (mar_req_coroipcc_zc_free_t);
  801. res = coroipcc_msg_send_reply_receive (
  802. ipc_context,
  803. &iovec,
  804. 1,
  805. &res_coroipcs_zc_free,
  806. sizeof (mar_res_header_t));
  807. munmap (header, header->map_size);
  808. return (CS_OK);
  809. }
  810. cs_error_t
  811. coroipcc_zcb_msg_send_reply_receive (
  812. void *ipc_context,
  813. void *msg,
  814. void *res_msg,
  815. size_t res_len)
  816. {
  817. mar_req_coroipcc_zc_execute_t req_coroipcc_zc_execute;
  818. struct coroipcs_zc_header *hdr;
  819. struct iovec iovec;
  820. cs_error_t res;
  821. hdr = (struct coroipcs_zc_header *)(((char *)msg) - sizeof (struct coroipcs_zc_header));
  822. req_coroipcc_zc_execute.header.size = sizeof (mar_req_coroipcc_zc_execute_t);
  823. req_coroipcc_zc_execute.header.id = ZC_EXECUTE_HEADER;
  824. req_coroipcc_zc_execute.server_address = hdr->server_address;
  825. iovec.iov_base = &req_coroipcc_zc_execute;
  826. iovec.iov_len = sizeof (mar_req_coroipcc_zc_execute_t);
  827. res = coroipcc_msg_send_reply_receive (
  828. ipc_context,
  829. &iovec,
  830. 1,
  831. res_msg,
  832. res_len);
  833. return (res);
  834. }
  835. cs_error_t
  836. saHandleCreate (
  837. struct saHandleDatabase *handleDatabase,
  838. int instanceSize,
  839. uint64_t *handleOut)
  840. {
  841. uint32_t handle;
  842. uint32_t check;
  843. void *newHandles = NULL;
  844. int found = 0;
  845. void *instance;
  846. int i;
  847. hdb_lock (handleDatabase);
  848. for (handle = 0; handle < handleDatabase->handleCount; handle++) {
  849. if (handleDatabase->handles[handle].state == SA_HANDLE_STATE_EMPTY) {
  850. found = 1;
  851. break;
  852. }
  853. }
  854. if (found == 0) {
  855. handleDatabase->handleCount += 1;
  856. newHandles = (struct saHandle *)realloc (handleDatabase->handles,
  857. sizeof (struct saHandle) * handleDatabase->handleCount);
  858. if (newHandles == NULL) {
  859. hdb_unlock (handleDatabase);
  860. return (CS_ERR_NO_MEMORY);
  861. }
  862. handleDatabase->handles = newHandles;
  863. }
  864. instance = malloc (instanceSize);
  865. if (instance == 0) {
  866. free (newHandles);
  867. hdb_unlock (handleDatabase);
  868. return (CS_ERR_NO_MEMORY);
  869. }
  870. /*
  871. * This code makes sure the random number isn't zero
  872. * We use 0 to specify an invalid handle out of the 1^64 address space
  873. * If we get 0 200 times in a row, the RNG may be broken
  874. */
  875. for (i = 0; i < 200; i++) {
  876. check = random();
  877. if (check != 0) {
  878. break;
  879. }
  880. }
  881. memset (instance, 0, instanceSize);
  882. handleDatabase->handles[handle].state = SA_HANDLE_STATE_ACTIVE;
  883. handleDatabase->handles[handle].instance = instance;
  884. handleDatabase->handles[handle].refCount = 1;
  885. handleDatabase->handles[handle].check = check;
  886. *handleOut = (uint64_t)((uint64_t)check << 32 | handle);
  887. hdb_unlock (handleDatabase);
  888. return (CS_OK);
  889. }
  890. cs_error_t
  891. saHandleDestroy (
  892. struct saHandleDatabase *handleDatabase,
  893. uint64_t inHandle)
  894. {
  895. cs_error_t error = CS_OK;
  896. uint32_t check = inHandle >> 32;
  897. uint32_t handle = inHandle & 0xffffffff;
  898. hdb_lock (handleDatabase);
  899. if (check != handleDatabase->handles[handle].check) {
  900. hdb_unlock (handleDatabase);
  901. error = CS_ERR_BAD_HANDLE;
  902. return (error);
  903. }
  904. handleDatabase->handles[handle].state = SA_HANDLE_STATE_PENDINGREMOVAL;
  905. hdb_unlock (handleDatabase);
  906. saHandleInstancePut (handleDatabase, inHandle);
  907. return (error);
  908. }
  909. cs_error_t
  910. saHandleInstanceGet (
  911. struct saHandleDatabase *handleDatabase,
  912. uint64_t inHandle,
  913. void **instance)
  914. {
  915. uint32_t check = inHandle >> 32;
  916. uint32_t handle = inHandle & 0xffffffff;
  917. cs_error_t error = CS_OK;
  918. hdb_lock (handleDatabase);
  919. if (handle >= (uint64_t)handleDatabase->handleCount) {
  920. error = CS_ERR_BAD_HANDLE;
  921. goto error_exit;
  922. }
  923. if (handleDatabase->handles[handle].state != SA_HANDLE_STATE_ACTIVE) {
  924. error = CS_ERR_BAD_HANDLE;
  925. goto error_exit;
  926. }
  927. if (check != handleDatabase->handles[handle].check) {
  928. error = CS_ERR_BAD_HANDLE;
  929. goto error_exit;
  930. }
  931. *instance = handleDatabase->handles[handle].instance;
  932. handleDatabase->handles[handle].refCount += 1;
  933. error_exit:
  934. hdb_unlock (handleDatabase);
  935. return (error);
  936. }
  937. cs_error_t
  938. saHandleInstancePut (
  939. struct saHandleDatabase *handleDatabase,
  940. uint64_t inHandle)
  941. {
  942. void *instance;
  943. cs_error_t error = CS_OK;
  944. uint32_t check = inHandle >> 32;
  945. uint32_t handle = inHandle & 0xffffffff;
  946. hdb_lock (handleDatabase);
  947. if (check != handleDatabase->handles[handle].check) {
  948. error = CS_ERR_BAD_HANDLE;
  949. goto error_exit;
  950. }
  951. handleDatabase->handles[handle].refCount -= 1;
  952. assert (handleDatabase->handles[handle].refCount >= 0);
  953. if (handleDatabase->handles[handle].refCount == 0) {
  954. instance = (handleDatabase->handles[handle].instance);
  955. handleDatabase->handleInstanceDestructor (instance);
  956. free (instance);
  957. memset (&handleDatabase->handles[handle], 0, sizeof (struct saHandle));
  958. }
  959. error_exit:
  960. hdb_unlock (handleDatabase);
  961. return (error);
  962. }