main.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. /*
  2. * Copyright (c) 2002-2004 MontaVista Software, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Steven Dake (sdake@mvista.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <assert.h>
  35. #include <pwd.h>
  36. #include <grp.h>
  37. #include <sys/types.h>
  38. #include <sys/poll.h>
  39. #include <sys/uio.h>
  40. #include <sys/mman.h>
  41. #include <sys/socket.h>
  42. #include <sys/un.h>
  43. #include <sys/sysinfo.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #include <unistd.h>
  47. #include <fcntl.h>
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #include <errno.h>
  51. #include <signal.h>
  52. #include <sched.h>
  53. #include <time.h>
  54. #include "../include/ais_types.h"
  55. #include "../include/ais_msg.h"
  56. #include "../include/list.h"
  57. #include "../include/queue.h"
  58. #include "poll.h"
  59. #include "gmi.h"
  60. #include "mempool.h"
  61. #include "parse.h"
  62. #include "main.h"
  63. #include "handlers.h"
  64. #include "evs.h"
  65. #include "clm.h"
  66. #include "amf.h"
  67. #include "ckpt.h"
  68. #include "evt.h"
  69. #include "print.h"
  70. #define SERVER_BACKLOG 5
  71. int ais_uid = 0;
  72. int gid_valid = 0;
  73. struct gmi_groupname aisexec_groupname = { "0123" };
  74. /*
  75. * All service handlers in the AIS
  76. */
  77. struct service_handler *ais_service_handlers[] = {
  78. &evs_service_handler,
  79. &clm_service_handler,
  80. &amf_service_handler,
  81. &ckpt_service_handler,
  82. &ckpt_checkpoint_service_handler,
  83. &ckpt_sectioniterator_service_handler,
  84. &evt_service_handler
  85. };
  86. #define AIS_SERVICE_HANDLERS_COUNT 7
  87. #define AIS_SERVICE_HANDLER_AISEXEC_FUNCTIONS_MAX 40
  88. static int poll_handler_libais_deliver (poll_handle handle, int fd, int revent, void *data, unsigned int *prio);
  89. enum e_ais_done {
  90. AIS_DONE_EXIT = -1,
  91. AIS_DONE_UID_DETERMINE = -2,
  92. AIS_DONE_GID_DETERMINE = -3,
  93. AIS_DONE_MEMPOOL_INIT = -4,
  94. AIS_DONE_FORK = -5,
  95. AIS_DONE_LIBAIS_SOCKET = -6,
  96. AIS_DONE_LIBAIS_BIND = -7,
  97. AIS_DONE_READKEY = -8,
  98. AIS_DONE_READNETWORK = -9,
  99. AIS_DONE_READGROUPS = -10,
  100. };
  101. static inline void ais_done (enum e_ais_done err)
  102. {
  103. log_printf (LOG_LEVEL_ERROR, "AIS Executive exiting.\n");
  104. poll_destroy (aisexec_poll_handle);
  105. exit (1);
  106. }
  107. static inline struct conn_info *conn_info_create (int fd) {
  108. struct conn_info *conn_info;
  109. int res;
  110. conn_info = malloc (sizeof (struct conn_info));
  111. if (conn_info == 0) {
  112. return (0);
  113. }
  114. memset (conn_info, 0, sizeof (struct conn_info));
  115. res = queue_init (&conn_info->outq, SIZEQUEUE,
  116. sizeof (struct outq_item));
  117. if (res != 0) {
  118. free (conn_info);
  119. return (0);
  120. }
  121. conn_info->inb = malloc (sizeof (char) * SIZEINB);
  122. if (conn_info->inb == 0) {
  123. queue_free (&conn_info->outq);
  124. free (conn_info);
  125. return (0);
  126. }
  127. conn_info->state = CONN_STATE_ACTIVE;
  128. conn_info->fd = fd;
  129. conn_info->service = SOCKET_SERVICE_INIT;
  130. return (conn_info);
  131. }
  132. static void sigusr2_handler (int num)
  133. {
  134. int i;
  135. for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) {
  136. if (ais_service_handlers[i]->exec_dump_fn) {
  137. ais_service_handlers[i]->exec_dump_fn ();
  138. }
  139. }
  140. signal (SIGUSR2 ,sigusr2_handler);
  141. return;
  142. }
  143. struct sockaddr_in this_ip;
  144. #define LOCALHOST_IP inet_addr("127.0.0.1")
  145. char *socketname = "libais.socket";
  146. static int libais_connection_active (struct conn_info *conn_info)
  147. {
  148. return (conn_info->state == CONN_STATE_ACTIVE);
  149. }
  150. static void libais_disconnect_delayed (struct conn_info *conn_info)
  151. {
  152. conn_info->state = CONN_STATE_DISCONNECTING_DELAYED;
  153. }
  154. static int libais_disconnect (struct conn_info *conn_info)
  155. {
  156. int res = 0;
  157. struct outq_item *outq_item;
  158. if (ais_service_handlers[conn_info->service - 1]->libais_exit_fn) {
  159. res = ais_service_handlers[conn_info->service - 1]->libais_exit_fn (conn_info);
  160. }
  161. /*
  162. * Close the library connection and free its
  163. * data if it hasn't already been freed
  164. */
  165. if (conn_info->state != CONN_STATE_DISCONNECTING) {
  166. conn_info->state = CONN_STATE_DISCONNECTING;
  167. close (conn_info->fd);
  168. /*
  169. * Free the outq queued items
  170. */
  171. while (!queue_is_empty (&conn_info->outq)) {
  172. outq_item = queue_item_get (&conn_info->outq);
  173. free (outq_item->msg);
  174. queue_item_remove (&conn_info->outq);
  175. }
  176. queue_free (&conn_info->outq);
  177. free (conn_info->inb);
  178. }
  179. /*
  180. * If exit_fn didn't request a retry,
  181. * free the conn_info structure
  182. */
  183. if (res != -1) {
  184. free (conn_info);
  185. }
  186. /*
  187. * Inverse res from libais exit fn handler
  188. */
  189. return (res != -1 ? -1 : 0);
  190. }
  191. static int cleanup_send_response (struct conn_info *conn_info) {
  192. struct queue *outq;
  193. int res = 0;
  194. struct outq_item *queue_item;
  195. struct msghdr msg_send;
  196. struct iovec iov_send;
  197. char *msg_addr;
  198. if (!libais_connection_active (conn_info)) {
  199. return (-1);
  200. }
  201. outq = &conn_info->outq;
  202. msg_send.msg_iov = &iov_send;
  203. msg_send.msg_name = 0;
  204. msg_send.msg_namelen = 0;
  205. msg_send.msg_iovlen = 1;
  206. msg_send.msg_control = 0;
  207. msg_send.msg_controllen = 0;
  208. msg_send.msg_flags = 0;
  209. while (!queue_is_empty (outq)) {
  210. queue_item = queue_item_get (outq);
  211. msg_addr = (char *)queue_item->msg;
  212. msg_addr = &msg_addr[conn_info->byte_start];
  213. iov_send.iov_base = msg_addr;
  214. iov_send.iov_len = queue_item->mlen - conn_info->byte_start;
  215. retry_sendmsg:
  216. res = sendmsg (conn_info->fd, &msg_send, MSG_DONTWAIT | MSG_NOSIGNAL);
  217. if (res == -1 && errno == EINTR) {
  218. goto retry_sendmsg;
  219. }
  220. if (res == -1 && errno == EAGAIN) {
  221. break; /* outgoing kernel queue full */
  222. }
  223. if (res == -1) {
  224. return (-1); /* message couldn't be sent */
  225. }
  226. if (res + conn_info->byte_start != queue_item->mlen) {
  227. conn_info->byte_start += res;
  228. break;
  229. }
  230. /*
  231. * Message sent, try sending another message
  232. */
  233. queue_item_remove (outq);
  234. conn_info->byte_start = 0;
  235. free (queue_item->msg);
  236. } /* while queue not empty */
  237. if (queue_is_empty (outq)) {
  238. poll_dispatch_modify (aisexec_poll_handle, conn_info->fd,
  239. POLLIN|POLLNVAL, poll_handler_libais_deliver, 0);
  240. }
  241. return (0);
  242. }
  243. extern int libais_send_response (struct conn_info *conn_info,
  244. void *msg, int mlen)
  245. {
  246. struct queue *outq;
  247. char *cmsg;
  248. int res = 0;
  249. int queue_empty;
  250. struct outq_item *queue_item;
  251. struct outq_item queue_item_out;
  252. struct msghdr msg_send;
  253. struct iovec iov_send;
  254. char *msg_addr;
  255. if (!libais_connection_active (conn_info)) {
  256. return (-1);
  257. }
  258. outq = &conn_info->outq;
  259. msg_send.msg_iov = &iov_send;
  260. msg_send.msg_name = 0;
  261. msg_send.msg_namelen = 0;
  262. msg_send.msg_iovlen = 1;
  263. msg_send.msg_control = 0;
  264. msg_send.msg_controllen = 0;
  265. msg_send.msg_flags = 0;
  266. if (queue_is_full (outq)) {
  267. /*
  268. * Start a disconnect if we have not already started one
  269. * and report that the outgoing queue is full
  270. */
  271. log_printf (LOG_LEVEL_ERROR, "Library queue is full, disconnecting library connection.\n");
  272. libais_disconnect_delayed (conn_info);
  273. return (-1);
  274. }
  275. while (!queue_is_empty (outq)) {
  276. queue_item = queue_item_get (outq);
  277. msg_addr = (char *)queue_item->msg;
  278. msg_addr = &msg_addr[conn_info->byte_start];
  279. iov_send.iov_base = msg_addr;
  280. iov_send.iov_len = queue_item->mlen - conn_info->byte_start;
  281. retry_sendmsg:
  282. res = sendmsg (conn_info->fd, &msg_send, MSG_DONTWAIT | MSG_NOSIGNAL);
  283. if (res == -1 && errno == EINTR) {
  284. goto retry_sendmsg;
  285. }
  286. if (res == -1 && errno == EAGAIN) {
  287. break; /* outgoing kernel queue full */
  288. }
  289. if (res == -1) {
  290. break; /* some other error, stop trying to send message */
  291. }
  292. if (res + conn_info->byte_start != queue_item->mlen) {
  293. conn_info->byte_start += res;
  294. break;
  295. }
  296. /*
  297. * Message sent, try sending another message
  298. */
  299. queue_item_remove (outq);
  300. conn_info->byte_start = 0;
  301. free (queue_item->msg);
  302. } /* while queue not empty */
  303. res = -1;
  304. queue_empty = queue_is_empty (outq);
  305. /*
  306. * Send requested message
  307. */
  308. if (queue_empty) {
  309. iov_send.iov_base = msg;
  310. iov_send.iov_len = mlen;
  311. retry_sendmsg_two:
  312. res = sendmsg (conn_info->fd, &msg_send, MSG_DONTWAIT | MSG_NOSIGNAL);
  313. if (res == -1 && errno == EINTR) {
  314. goto retry_sendmsg_two;
  315. }
  316. if (res == -1 && errno == EAGAIN) {
  317. conn_info->byte_start = 0;
  318. poll_dispatch_modify (aisexec_poll_handle, conn_info->fd,
  319. POLLIN|POLLNVAL, poll_handler_libais_deliver, 0);
  320. }
  321. if (res != -1) {
  322. if (res + conn_info->byte_start != mlen) {
  323. conn_info->byte_start += res;
  324. res = -1;
  325. } else {
  326. conn_info->byte_start = 0;
  327. poll_dispatch_modify (aisexec_poll_handle, conn_info->fd,
  328. POLLIN|POLLNVAL, poll_handler_libais_deliver, 0);
  329. }
  330. }
  331. }
  332. /*
  333. * If res == -1 , errrno == EAGAIN which means kernel queue full
  334. */
  335. if (res == -1) {
  336. cmsg = malloc (mlen);
  337. if (cmsg == 0) {
  338. log_printf (LOG_LEVEL_ERROR, "Library queue couldn't allocate a message, disconnecting library connection.\n");
  339. libais_disconnect_delayed (conn_info);
  340. return (-1);
  341. }
  342. queue_item_out.msg = cmsg;
  343. queue_item_out.mlen = mlen;
  344. memcpy (cmsg, msg, mlen);
  345. queue_item_add (outq, &queue_item_out);
  346. poll_dispatch_modify (aisexec_poll_handle, conn_info->fd,
  347. POLLOUT|POLLIN|POLLNVAL, poll_handler_libais_deliver, 0);
  348. }
  349. return (0);
  350. }
  351. static int poll_handler_libais_accept (
  352. poll_handle handle,
  353. int fd,
  354. int revent,
  355. void *data,
  356. unsigned int *prio)
  357. {
  358. socklen_t addrlen;
  359. struct conn_info *conn_info;
  360. struct sockaddr_un un_addr;
  361. int new_fd;
  362. int on = 1;
  363. addrlen = sizeof (struct sockaddr_un);
  364. retry_accept:
  365. new_fd = accept (fd, (struct sockaddr *)&un_addr, &addrlen);
  366. if (new_fd == -1 && errno == EINTR) {
  367. goto retry_accept;
  368. }
  369. if (new_fd == -1) {
  370. log_printf (LOG_LEVEL_ERROR, "ERROR: Could not accept Library connection: %s\n", strerror (errno));
  371. return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
  372. }
  373. /*
  374. * Valid accept
  375. */
  376. /*
  377. * Request credentials of sender provided by kernel
  378. */
  379. setsockopt(new_fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
  380. log_printf (LOG_LEVEL_DEBUG, "connection received from libais client %d.\n", new_fd);
  381. conn_info = conn_info_create (new_fd);
  382. if (conn_info == 0) {
  383. close (new_fd);
  384. return (0); /* This is an error, but -1 would indicate disconnect from poll */
  385. }
  386. poll_dispatch_add (aisexec_poll_handle, new_fd, POLLIN|POLLNVAL, conn_info,
  387. poll_handler_libais_deliver, 0);
  388. // TODO is this needed, or shouldn't it be in conn_info_create ?
  389. memcpy (&conn_info->ais_ci.un_addr, &un_addr, sizeof (struct sockaddr_un));
  390. return (0);
  391. }
  392. struct message_overlay {
  393. struct res_header header;
  394. char buf[4096];
  395. };
  396. static int poll_handler_libais_deliver (poll_handle handle, int fd, int revent, void *data, unsigned int *prio)
  397. {
  398. int res;
  399. struct conn_info *conn_info = (struct conn_info *)data;
  400. struct req_header *header;
  401. int service;
  402. struct msghdr msg_recv;
  403. struct iovec iov_recv;
  404. struct cmsghdr *cmsg;
  405. char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))];
  406. struct ucred *cred;
  407. int on = 0;
  408. int send_ok = 0;
  409. struct message_overlay msg_overlay;
  410. msg_recv.msg_iov = &iov_recv;
  411. msg_recv.msg_iovlen = 1;
  412. msg_recv.msg_name = 0;
  413. msg_recv.msg_namelen = 0;
  414. msg_recv.msg_flags = 0;
  415. if (revent & POLLOUT) {
  416. cleanup_send_response (conn_info);
  417. }
  418. if ((revent & POLLIN) == 0) {
  419. return (0);
  420. }
  421. /*
  422. * Handle delayed disconnections
  423. */
  424. if (conn_info->state != CONN_STATE_ACTIVE) {
  425. res = libais_disconnect (conn_info);
  426. return (res);
  427. }
  428. if (conn_info->authenticated) {
  429. msg_recv.msg_control = 0;
  430. msg_recv.msg_controllen = 0;
  431. } else {
  432. msg_recv.msg_control = (void *)cmsg_cred;
  433. msg_recv.msg_controllen = sizeof (cmsg_cred);
  434. }
  435. iov_recv.iov_base = &conn_info->inb[conn_info->inb_start];
  436. iov_recv.iov_len = (SIZEINB) - conn_info->inb_start;
  437. assert (iov_recv.iov_len != 0);
  438. retry_recv:
  439. res = recvmsg (fd, &msg_recv, MSG_DONTWAIT | MSG_NOSIGNAL);
  440. if (res == -1 && errno == EINTR) {
  441. goto retry_recv;
  442. } else
  443. if (res == -1 && errno != EAGAIN) {
  444. goto error_disconnect;
  445. } else
  446. if (res == 0) {
  447. goto error_disconnect;
  448. return (-1);
  449. }
  450. /*
  451. * Authenticate if this connection has not been authenticated
  452. */
  453. if (conn_info->authenticated == 0) {
  454. cmsg = CMSG_FIRSTHDR (&msg_recv);
  455. cred = (struct ucred *)CMSG_DATA (cmsg);
  456. if (cred) {
  457. if (cred->uid == 0 || cred->gid == gid_valid) {
  458. setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
  459. conn_info->authenticated = 1;
  460. }
  461. }
  462. if (conn_info->authenticated == 0) {
  463. log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", cred->gid, gid_valid);
  464. }
  465. }
  466. /*
  467. * Dispatch all messages received in recvmsg that can be dispatched
  468. * sizeof (struct req_header) needed at minimum to do any processing
  469. */
  470. conn_info->inb_inuse += res;
  471. conn_info->inb_start += res;
  472. while (conn_info->inb_inuse >= sizeof (struct req_header) && res != -1) {
  473. header = (struct req_header *)&conn_info->inb[conn_info->inb_start - conn_info->inb_inuse];
  474. if (header->size > conn_info->inb_inuse) {
  475. break;
  476. }
  477. service = conn_info->service;
  478. /*
  479. * If this service is in init phase, initialize service
  480. * else handle message using service handlers
  481. */
  482. if (service == SOCKET_SERVICE_INIT) {
  483. /*
  484. * Initializing service
  485. */
  486. res = ais_service_handlers[header->id]->libais_init_fn (conn_info, header);
  487. } else {
  488. /*
  489. * Not an init service, but a standard service
  490. */
  491. if (header->id < 0 || header->id > ais_service_handlers[service - 1]->libais_handlers_count) {
  492. log_printf (LOG_LEVEL_SECURITY, "Invalid header id is %d min 0 max %d\n",
  493. header->id, ais_service_handlers[service - 1]->libais_handlers_count);
  494. res = -1;
  495. goto error_disconnect;
  496. }
  497. /*
  498. * Determine if a message can be queued with gmi and if so
  499. * deliver it, otherwise tell the library we are too busy
  500. */
  501. send_ok = gmi_send_ok (ais_service_handlers[service - 1]->libais_handlers[header->id].gmi_prio, 1000 + header->size);
  502. if (send_ok) {
  503. *prio = 0;
  504. res = ais_service_handlers[service - 1]->libais_handlers[header->id].libais_handler_fn(conn_info, header);
  505. } else {
  506. *prio = (*prio) + 1;
  507. /*
  508. * Overload, tell library to retry
  509. */
  510. msg_overlay.header.size =
  511. ais_service_handlers[service - 1]->libais_handlers[header->id].response_size;
  512. msg_overlay.header.id =
  513. ais_service_handlers[service - 1]->libais_handlers[header->id].response_id;
  514. msg_overlay.header.error = SA_ERR_TRY_AGAIN;
  515. libais_send_response (conn_info, &msg_overlay,
  516. msg_overlay.header.size);
  517. }
  518. }
  519. conn_info->inb_inuse -= header->size;
  520. } /* while */
  521. if (conn_info->inb_inuse == 0) {
  522. conn_info->inb_start = 0;
  523. } else
  524. // BUG if (connections[fd].inb_start + connections[fd].inb_inuse >= SIZEINB) {
  525. if (conn_info->inb_start >= SIZEINB) {
  526. /*
  527. * If in buffer is full, move it back to start
  528. */
  529. memmove (conn_info->inb,
  530. &conn_info->inb[conn_info->inb_start - conn_info->inb_inuse],
  531. sizeof (char) * conn_info->inb_inuse);
  532. conn_info->inb_start = conn_info->inb_inuse;
  533. }
  534. return (res);
  535. error_disconnect:
  536. res = libais_disconnect (conn_info);
  537. return (res);
  538. }
  539. extern void print_stats (void);
  540. void sigintr_handler (int signum)
  541. {
  542. #ifdef DEBUG_MEMPOOL
  543. int stats_inuse[MEMPOOL_GROUP_SIZE];
  544. int stats_avail[MEMPOOL_GROUP_SIZE];
  545. int stats_memoryused[MEMPOOL_GROUP_SIZE];
  546. int i;
  547. mempool_getstats (stats_inuse, stats_avail, stats_memoryused);
  548. log_printf (LOG_LEVEL_DEBUG, "Memory pools:\n");
  549. for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
  550. log_printf (LOG_LEVEL_DEBUG, "order %d size %d inuse %d avail %d memory used %d\n",
  551. i, 1<<i, stats_inuse[i], stats_avail[i], stats_memoryused[i]);
  552. }
  553. #endif
  554. print_stats ();
  555. ais_done (AIS_DONE_EXIT);
  556. }
  557. static struct sched_param sched_param = {
  558. sched_priority: 99
  559. };
  560. static int pool_sizes[] = { 0, 0, 0, 0, 0, 4096, 0, 1, 0, /* 256 */
  561. 1024, 0, 1, 4096, 0, 0, 0, 0, /* 65536 */
  562. 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  563. static int (*aisexec_handler_fns[AIS_SERVICE_HANDLER_AISEXEC_FUNCTIONS_MAX]) (void *msg, struct in_addr source_addr);
  564. static int aisexec_handler_fns_count = 0;
  565. /*
  566. * Builds the handler table as an optimization
  567. */
  568. static void aisexec_handler_fns_build (void)
  569. {
  570. int i, j;
  571. for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) {
  572. for (j = 0; j < ais_service_handlers[i]->aisexec_handler_fns_count; j++) {
  573. aisexec_handler_fns[aisexec_handler_fns_count++] =
  574. ais_service_handlers[i]->aisexec_handler_fns[j];
  575. }
  576. }
  577. log_printf (LOG_LEVEL_DEBUG, "built %d handler functions\n", aisexec_handler_fns_count);
  578. }
  579. char delivery_data[MESSAGE_SIZE_MAX];
  580. static void deliver_fn (
  581. struct gmi_groupname *groupname,
  582. struct in_addr source_addr,
  583. struct iovec *iovec,
  584. int iov_len)
  585. {
  586. struct req_header *header;
  587. int res;
  588. int pos = 0;
  589. int i;
  590. /*
  591. * Build buffer without iovecs to make processing easier
  592. * This is only used for messages which are multicast with iovecs
  593. * and self-delivered. All other mechanisms avoid the copy.
  594. */
  595. if (iov_len > 1) {
  596. for (i = 0; i < iov_len; i++) {
  597. memcpy (&delivery_data[pos], iovec[i].iov_base, iovec[i].iov_len);
  598. pos += iovec[i].iov_len;
  599. assert (pos < MESSAGE_SIZE_MAX);
  600. }
  601. header = (struct req_header *)delivery_data;
  602. } else {
  603. header = (struct req_header *)iovec[0].iov_base;
  604. }
  605. res = aisexec_handler_fns[header->id](header, source_addr);
  606. }
  607. static void confchg_fn (
  608. enum gmi_configuration_type configuration_type,
  609. struct sockaddr_in *member_list, int member_list_entries,
  610. struct sockaddr_in *left_list, int left_list_entries,
  611. struct sockaddr_in *joined_list, int joined_list_entries)
  612. {
  613. int i;
  614. /*
  615. * Call configure change for all APIs
  616. */
  617. for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) {
  618. if (ais_service_handlers[i]->confchg_fn) {
  619. ais_service_handlers[i]->confchg_fn (configuration_type,
  620. member_list, member_list_entries,
  621. left_list, left_list_entries,
  622. joined_list, joined_list_entries);
  623. }
  624. }
  625. }
  626. static void aisexec_uid_determine (void)
  627. {
  628. struct passwd *passwd;
  629. passwd = getpwnam("ais");
  630. if (passwd == 0) {
  631. log_printf (LOG_LEVEL_ERROR, "ERROR: The 'ais' user is not found in /etc/passwd, please read the documentation.\n");
  632. ais_done (AIS_DONE_UID_DETERMINE);
  633. }
  634. ais_uid = passwd->pw_uid;
  635. }
  636. static void aisexec_gid_determine (void)
  637. {
  638. struct group *group;
  639. group = getgrnam ("ais");
  640. if (group == 0) {
  641. log_printf (LOG_LEVEL_ERROR, "ERROR: The 'ais' group is not found in /etc/group, please read the documentation.\n");
  642. ais_done (AIS_DONE_GID_DETERMINE);
  643. }
  644. gid_valid = group->gr_gid;
  645. }
  646. static void aisexec_priv_drop (void)
  647. {
  648. setuid (ais_uid);
  649. setegid (ais_uid);
  650. }
  651. static void aisexec_mempool_init (void)
  652. {
  653. int res;
  654. res = mempool_init (pool_sizes);
  655. if (res == ENOMEM) {
  656. log_printf (LOG_LEVEL_ERROR, "Couldn't allocate memory pools, not enough memory");
  657. ais_done (AIS_DONE_MEMPOOL_INIT);
  658. }
  659. }
  660. static void aisexec_tty_detach (void)
  661. {
  662. #define DEBUG
  663. #ifndef DEBUG
  664. /*
  665. * Disconnect from TTY if this is not a debug run
  666. */
  667. switch (fork ()) {
  668. case -1:
  669. ais_done (AIS_DONE_FORK);
  670. break;
  671. case 0:
  672. /*
  673. * child which is disconnected, run this process
  674. */
  675. break;
  676. default:
  677. exit (0);
  678. break;
  679. }
  680. #endif
  681. #undef DEBUG
  682. }
  683. static void aisexec_service_handlers_init (void)
  684. {
  685. int i;
  686. /*
  687. * Initialize all services
  688. */
  689. for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) {
  690. if (ais_service_handlers[i]->exec_init_fn) {
  691. if (!ais_service_handlers[i]->exec_init_fn) {
  692. continue;
  693. }
  694. ais_service_handlers[i]->exec_init_fn ();
  695. }
  696. }
  697. }
  698. static void aisexec_libais_bind (int *server_fd)
  699. {
  700. int libais_server_fd;
  701. struct sockaddr_un un_addr;
  702. int res;
  703. /*
  704. * Create socket for libais clients, name socket, listen for connections
  705. */
  706. libais_server_fd = socket (PF_UNIX, SOCK_STREAM, 0);
  707. if (libais_server_fd == -1) {
  708. log_printf (LOG_LEVEL_ERROR ,"Cannot create libais client connections socket.\n");
  709. ais_done (AIS_DONE_LIBAIS_SOCKET);
  710. };
  711. memset (&un_addr, 0, sizeof (struct sockaddr_un));
  712. un_addr.sun_family = AF_UNIX;
  713. strcpy (un_addr.sun_path + 1, socketname);
  714. res = bind (libais_server_fd, (struct sockaddr *)&un_addr, sizeof (struct sockaddr_un));
  715. if (res) {
  716. log_printf (LOG_LEVEL_ERROR, "ERROR: Could not bind AF_UNIX: %s.\n", strerror (errno));
  717. ais_done (AIS_DONE_LIBAIS_BIND);
  718. }
  719. listen (libais_server_fd, SERVER_BACKLOG);
  720. *server_fd = libais_server_fd;
  721. }
  722. static void aisexec_setscheduler (void)
  723. {
  724. int res;
  725. return;
  726. res = sched_setscheduler (0, SCHED_RR, &sched_param);
  727. if (res == -1) {
  728. log_printf (LOG_LEVEL_WARNING, "Could not set SCHED_RR at priority 99: %s\n", strerror (errno));
  729. }
  730. }
  731. static void aisexec_mlockall (void)
  732. {
  733. int res;
  734. res = mlockall (MCL_CURRENT | MCL_FUTURE);
  735. if (res == -1) {
  736. log_printf (LOG_LEVEL_WARNING, "Could not lock memory of service to avoid page faults: %s\n", strerror (errno));
  737. };
  738. }
  739. void aisexec_keyread (unsigned char *key)
  740. {
  741. int fd;
  742. int res;
  743. fd = open ("/etc/ais/authkey", O_RDONLY);
  744. if (fd == -1) {
  745. log_printf (LOG_LEVEL_ERROR, "Could not open /etc/ais/authkey: %s\n", strerror (errno));
  746. ais_done (AIS_DONE_READKEY);
  747. }
  748. res = read (fd, key, 128);
  749. if (res == -1) {
  750. log_printf (LOG_LEVEL_ERROR, "Could not read /etc/ais/authkey: %s\n", strerror (errno));
  751. ais_done (AIS_DONE_READKEY);
  752. }
  753. if (res != 128) {
  754. log_printf (LOG_LEVEL_ERROR, "Could only read %d bits of 1024 bits from /etc/ais/authkey.\n", res * 8);
  755. ais_done (AIS_DONE_READKEY);
  756. }
  757. close (fd);
  758. }
  759. int main (int argc, char **argv)
  760. {
  761. int libais_server_fd;
  762. int res;
  763. struct sockaddr_in sockaddr_in_mcast;
  764. gmi_join_handle handle;
  765. unsigned char private_key[128];
  766. struct gmi_interface gmi_interfaces[2];
  767. char *error_string;
  768. log_printf (LOG_LEVEL_NOTICE, "AIS Executive Service: Copyright (C) 2002-2004 MontaVista Software, Inc.\n");
  769. aisexec_uid_determine ();
  770. aisexec_gid_determine ();
  771. aisexec_poll_handle = poll_create ();
  772. signal (SIGUSR2, sigusr2_handler);
  773. /*
  774. * if gmi_init doesn't have root priveleges, it cannot
  775. * bind to a specific interface. This only matters if
  776. * there is more then one interface in a system, so
  777. * in this case, only a warning is printed
  778. */
  779. /*
  780. * Initialize group messaging interface with multicast address
  781. */
  782. res = readNetwork (&error_string, &sockaddr_in_mcast, gmi_interfaces, 1);
  783. if (res == -1) {
  784. log_printf (LOG_LEVEL_ERROR, error_string);
  785. ais_done (AIS_DONE_READNETWORK);
  786. }
  787. /*
  788. * Set round robin realtime scheduling with priority 99
  789. * Lock all memory to avoid page faults which may interrupt
  790. * application healthchecking
  791. */
  792. aisexec_setscheduler ();
  793. aisexec_mlockall ();
  794. aisexec_keyread (private_key);
  795. gmi_log_printf_init (internal_log_printf_checkdebug,
  796. LOG_LEVEL_SECURITY, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING,
  797. LOG_LEVEL_NOTICE, LOG_LEVEL_DEBUG);
  798. gmi_init (&sockaddr_in_mcast, gmi_interfaces, 1,
  799. &aisexec_poll_handle,
  800. private_key,
  801. sizeof (private_key));
  802. memcpy (&this_ip, &gmi_interfaces->boundto, sizeof (struct sockaddr_in));
  803. /*
  804. * Drop root privleges to user 'ais'
  805. * TODO: Don't really need full root capabilities;
  806. * needed capabilities are:
  807. * CAP_NET_RAW (bindtodevice)
  808. * CAP_SYS_NICE (setscheduler)
  809. * CAP_IPC_LOCK (mlockall)
  810. */
  811. aisexec_priv_drop ();
  812. aisexec_handler_fns_build ();
  813. aisexec_mempool_init ();
  814. res = amfReadGroups(&error_string);
  815. if (res == -1) {
  816. log_printf (LOG_LEVEL_ERROR, error_string);
  817. ais_done (AIS_DONE_READGROUPS);
  818. }
  819. aisexec_tty_detach ();
  820. signal (SIGINT, sigintr_handler);
  821. aisexec_service_handlers_init ();
  822. aisexec_libais_bind (&libais_server_fd);
  823. log_printf (LOG_LEVEL_NOTICE, "AIS Executive Service: started and ready to receive connections.\n");
  824. /*
  825. * Setup libais connection dispatch routine
  826. */
  827. poll_dispatch_add (aisexec_poll_handle, libais_server_fd,
  828. POLLIN, 0, poll_handler_libais_accept, 0);
  829. /*
  830. * Join multicast group and setup delivery
  831. * and configuration change functions
  832. */
  833. gmi_join (0, deliver_fn, confchg_fn, &handle);
  834. /*
  835. * Start main processing loop
  836. */
  837. poll_run (aisexec_poll_handle);
  838. return (0);
  839. }