ctl.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2006 iptelorg GmbH
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. */
  27. /* History:
  28. * --------
  29. * 2006-02-08 created by andrei
  30. * 2007-01-18 use PROC_RPC rank when forking (andrei)
  31. */
  32. #include "../../sr_module.h"
  33. #include "../../ut.h"
  34. #include "../../dprint.h"
  35. #include "../../pt.h"
  36. #include "../../cfg/cfg_struct.h"
  37. #include "ctrl_socks.h"
  38. #include "io_listener.h"
  39. #include <sys/types.h>
  40. #include <sys/socket.h> /* socketpair */
  41. #include <unistd.h> /* close, fork, getpid */
  42. #include <stdio.h> /* snprintf */
  43. #include <string.h> /* strerror */
  44. #include <errno.h>
  45. MODULE_VERSION
  46. #include "ctl_defaults.h"
  47. #ifdef USE_FIFO
  48. #include "fifo_server.h"
  49. #endif
  50. static int mod_init(void);
  51. static int mod_child(int rank);
  52. static void mod_destroy(void);
  53. static cmd_export_t cmds[]={
  54. {0,0,0,0,0}
  55. };
  56. static int usock_mode=0600; /* permissions, default rw-------*/
  57. static int usock_uid=-1; /* username and group for the unix sockets*/
  58. static int usock_gid=-1;
  59. /* if set try to automatically convert values to the requested type in
  60. rpc->scan (default: not set) */
  61. extern int autoconvert;
  62. static int add_binrpc_socket(modparam_t type, void * val);
  63. #ifdef USE_FIFO
  64. static int add_fifo_socket(modparam_t type, void * val);
  65. #endif
  66. static int fix_user(modparam_t type, void * val);
  67. static int fix_group(modparam_t type, void * val);
  68. static void ctrl_listen_ls_rpc(rpc_t* rpc, void* ctx);
  69. void io_listen_who_rpc(rpc_t* rpc, void* ctx);
  70. void io_listen_conn_rpc(rpc_t* rpc, void* ctx);
  71. static char* io_listen_who_doc[]={ "list open connections", 0 };
  72. static char* io_listen_conn_doc[]={ "returns number of open connections", 0 };
  73. static char* ctl_listen_ls_doc[]={ "list ctl listen sockets", 0 };
  74. static rpc_export_t ctl_rpc[]={
  75. {"ctl.who", io_listen_who_rpc, (const char**)io_listen_who_doc, 0},
  76. {"ctl.connections", io_listen_conn_rpc,(const char**)io_listen_conn_doc,0},
  77. {"ctl.listen", ctrl_listen_ls_rpc,(const char**)ctl_listen_ls_doc, 0},
  78. { 0, 0, 0, 0}
  79. };
  80. static param_export_t params[]={
  81. #ifdef USE_FIFO
  82. {"fifo", PARAM_STRING|PARAM_USE_FUNC, (void*) add_fifo_socket },
  83. #endif
  84. {"binrpc", PARAM_STRING|PARAM_USE_FUNC, (void*) add_binrpc_socket},
  85. {"mode", PARAM_INT, &usock_mode },
  86. {"user", PARAM_STRING|PARAM_USE_FUNC, fix_user },
  87. {"group", PARAM_STRING|PARAM_USE_FUNC, fix_group },
  88. {"autoconversion", PARAM_INT, &autoconvert },
  89. {0,0,0}
  90. }; /* no params */
  91. struct module_exports exports= {
  92. "ctl",
  93. cmds,
  94. ctl_rpc, /* RPC methods */
  95. params,
  96. mod_init, /* module initialization function */
  97. 0, /* response function */
  98. mod_destroy, /* destroy function */
  99. 0, /* on_cancel function */
  100. mod_child, /* per-child init function */
  101. };
  102. static struct id_list* listen_lst=0; /* binrpc sockets name list */
  103. static struct ctrl_socket* ctrl_sock_lst=0;
  104. static int fd_no=0; /* number of fd used */
  105. static int add_binrpc_socket(modparam_t type, void * val)
  106. {
  107. char *s;
  108. struct id_list* id;
  109. if ((type & PARAM_STRING)==0){
  110. LOG(L_CRIT, "BUG: ctl: add_binrpc_socket: bad parameter type %d\n",
  111. type);
  112. goto error;
  113. }
  114. s=(char*)val;
  115. id=parse_listen_id(s, strlen(s), UDP_SOCK); /* default udp proto */
  116. if (id==0){
  117. LOG(L_ERR, "ERROR: ctl: bad listen socket: \"%s\"\n", s);
  118. goto error;
  119. }
  120. id->data_proto=P_BINRPC;
  121. id->next=listen_lst;
  122. listen_lst=id;
  123. return 0;
  124. error:
  125. return -1;
  126. }
  127. #ifdef USE_FIFO
  128. static int add_fifo_socket(modparam_t type, void * val)
  129. {
  130. char *s;
  131. struct id_list* id;
  132. if ((type & PARAM_STRING)==0){
  133. LOG(L_CRIT, "BUG: ctl: add_fifo: bad parameter type %d\n",
  134. type);
  135. goto error;
  136. }
  137. s=(char*)val;
  138. id=parse_listen_id(s, strlen(s), FIFO_SOCK); /* default udp proto */
  139. if (id==0){
  140. LOG(L_ERR, "ERROR: ctl: bad fifo: \"%s\"\n", s);
  141. goto error;
  142. }
  143. id->data_proto=P_FIFO;
  144. id->next=listen_lst;
  145. listen_lst=id;
  146. return 0;
  147. error:
  148. return -1;
  149. }
  150. #endif
  151. static int fix_user(modparam_t type, void * val)
  152. {
  153. char* s;
  154. if ((type & PARAM_STRING)==0){
  155. LOG(L_CRIT, "BUG: ctl: fix_user: bad parameter type %d\n",
  156. type);
  157. goto error;
  158. }
  159. s=(char*)val;
  160. if (user2uid(&usock_uid, 0, s)<0){
  161. LOG(L_ERR, "ERROR: ctl: bad user name/uid number %s\n", s);
  162. goto error;
  163. }
  164. return 0;
  165. error:
  166. return -1;
  167. }
  168. static int fix_group(modparam_t type, void * val)
  169. {
  170. char* s;
  171. if ((type & PARAM_STRING)==0){
  172. LOG(L_CRIT, "BUG: ctl: fix_group: bad parameter type %d\n",
  173. type);
  174. goto error;
  175. }
  176. s=(char*)val;
  177. if (group2gid(&usock_gid, s)<0){
  178. LOG(L_ERR, "ERROR: ctl: bad group name/gid number %s\n", s);
  179. goto error;
  180. }
  181. return 0;
  182. error:
  183. return -1;
  184. }
  185. static int mod_init(void)
  186. {
  187. struct id_list* l;
  188. if (listen_lst==0) {
  189. add_binrpc_socket(PARAM_STRING, DEFAULT_CTL_SOCKET);
  190. }
  191. DBG("listening on:\n");
  192. for (l=listen_lst; l; l=l->next){
  193. fd_no++;
  194. switch(l->proto){
  195. case UNIXD_SOCK:
  196. DBG(" [%s:unix dgram] %s\n",
  197. payload_proto_name(l->data_proto), l->name);
  198. break;
  199. case UNIXS_SOCK:
  200. DBG(" [%s:unix stream] %s\n",
  201. payload_proto_name(l->data_proto), l->name);
  202. break;
  203. case UDP_SOCK:
  204. DBG(" [%s:udp] %s:%d\n",
  205. payload_proto_name(l->data_proto), l->name,
  206. l->port?l->port:DEFAULT_CTL_PORT);
  207. break;
  208. case TCP_SOCK:
  209. DBG(" [%s:tcp] %s:%d\n",
  210. payload_proto_name(l->data_proto), l->name,
  211. l->port?l->port:DEFAULT_CTL_PORT);
  212. break;
  213. #ifdef USE_FIFO
  214. case FIFO_SOCK:
  215. DBG(" [%s:fifo] %s\n",
  216. payload_proto_name(l->data_proto), l->name);
  217. fd_no++; /* fifos use 2 fds */
  218. break;
  219. #endif
  220. default:
  221. LOG(L_CRIT, "BUG: ctrl: listen protocol %d not supported\n",
  222. l->proto);
  223. goto error;
  224. }
  225. }
  226. /* open socket now, before suid */
  227. if (init_ctrl_sockets(&ctrl_sock_lst, listen_lst, DEFAULT_CTL_PORT,
  228. usock_mode, usock_uid, usock_gid)<0){
  229. LOG(L_ERR, "ERROR: ctl: mod_init: init ctrl. sockets failed\n");
  230. goto error;
  231. }
  232. if (ctrl_sock_lst){
  233. /* we will fork */
  234. register_procs(1); /* we will be creating an extra process */
  235. register_fds(fd_no);
  236. /* The child process will keep updating its local configuration */
  237. cfg_register_child(1);
  238. }
  239. #ifdef USE_FIFO
  240. fifo_rpc_init();
  241. #endif
  242. return 0;
  243. error:
  244. return -1;
  245. }
  246. static int mod_child(int rank)
  247. {
  248. int pid;
  249. struct ctrl_socket* cs;
  250. static int rpc_handler=0;
  251. /* do nothing from PROC_INIT, is the same as PROC_MAIN */
  252. if (rank==PROC_INIT)
  253. return 0;
  254. /* we want to fork(), but only from one process */
  255. if ((rank == PROC_MAIN ) && (ctrl_sock_lst)){ /* FIXME: no fork ?? */
  256. DBG("ctl: mod_child(%d), ctrl_sock_lst=%p\n", rank, ctrl_sock_lst);
  257. /* fork, but make sure we know not to close our own sockets when
  258. * ctl child_init will be called for the new child */
  259. rpc_handler=1;
  260. /* child should start with a correct estimated used fds number*/
  261. register_fds(MAX_IO_READ_CONNECTIONS);
  262. pid=fork_process(PROC_RPC, "ctl handler", 1);
  263. DBG("ctl: mod_child(%d), fork_process=%d, csl=%p\n",
  264. rank, pid, ctrl_sock_lst);
  265. if (pid<0){
  266. goto error;
  267. }
  268. if (pid == 0){ /* child */
  269. is_main=0;
  270. DBG("ctl: %d io_listen_loop(%d, %p)\n",
  271. rank, fd_no, ctrl_sock_lst);
  272. io_listen_loop(fd_no, ctrl_sock_lst);
  273. }else{ /* parent */
  274. /* not used in parent */
  275. register_fds(-MAX_IO_READ_CONNECTIONS);
  276. rpc_handler=0;
  277. }
  278. }
  279. if (rank!=PROC_RPC || !rpc_handler){
  280. /* close all the opened fds, we don't need them here */
  281. for (cs=ctrl_sock_lst; cs; cs=cs->next){
  282. close(cs->fd);
  283. cs->fd=-1;
  284. if (cs->write_fd!=-1){
  285. close(cs->write_fd);
  286. cs->write_fd=-1;
  287. }
  288. }
  289. if (rank!=PROC_MAIN){ /* we need the lists in main for on_exit cleanup,
  290. see mod_destroy */
  291. /* free memory, we don't need the lists anymore */
  292. free_ctrl_socket_list(ctrl_sock_lst);
  293. ctrl_sock_lst=0;
  294. free_id_list(listen_lst);
  295. listen_lst=0;
  296. }
  297. }
  298. return 0;
  299. error:
  300. return -1;
  301. }
  302. static void mod_destroy(void)
  303. {
  304. struct ctrl_socket* cs;
  305. /* close all the opened fds & unlink the files */
  306. for (cs=ctrl_sock_lst; cs; cs=cs->next){
  307. switch(cs->transport){
  308. case UNIXS_SOCK:
  309. case UNIXD_SOCK:
  310. close(cs->fd);
  311. cs->fd=-1;
  312. if (cs->write_fd!=-1){
  313. close(cs->write_fd);
  314. cs->write_fd=-1;
  315. }
  316. if (cs->name){
  317. if (unlink(cs->name)<0){
  318. LOG(L_ERR, "ERROR: ctl: could not delete unix"
  319. " socket %s: %s (%d)\n",
  320. cs->name, strerror(errno), errno);
  321. }
  322. }
  323. break;
  324. #ifdef USE_FIFO
  325. case FIFO_SOCK:
  326. destroy_fifo(cs->fd, cs->write_fd, cs->name);
  327. break;
  328. #endif
  329. default:
  330. close(cs->fd);
  331. cs->fd=-1;
  332. if (cs->write_fd!=-1){
  333. close(cs->write_fd);
  334. cs->write_fd=-1;
  335. }
  336. }
  337. }
  338. if (listen_lst){
  339. free_id_list(listen_lst);
  340. listen_lst=0;
  341. }
  342. if (ctrl_sock_lst){
  343. free_ctrl_socket_list(ctrl_sock_lst);
  344. ctrl_sock_lst=0;
  345. }
  346. }
  347. static void ctrl_listen_ls_rpc(rpc_t* rpc, void* ctx)
  348. {
  349. struct ctrl_socket* cs;
  350. for (cs=ctrl_sock_lst; cs; cs=cs->next){
  351. rpc->add(ctx, "ssss", payload_proto_name(cs->p_proto),
  352. socket_proto_name(cs->transport),
  353. cs->name, (cs->port)?int2str(cs->port, 0):"");
  354. }
  355. }