PageRenderTime 25ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/release/src/router/pptp-client/pptp_callmgr.c

https://gitlab.com/envieidoc/advancedtomato2
C | 388 lines | 315 code | 15 blank | 58 comment | 59 complexity | 848e9a27e332c81e322bbcaae67b300c MD5 | raw file
  1. /* pptp_callmgr.c ... Call manager for PPTP connections.
  2. * Handles TCP port 1723 protocol.
  3. * C. Scott Ananian <cananian@alumni.princeton.edu>
  4. *
  5. * $Id: pptp_callmgr.c,v 1.20 2005/03/31 07:42:39 quozl Exp $
  6. */
  7. #include <signal.h>
  8. #include <sys/time.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #include <sys/un.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <assert.h>
  19. #include <setjmp.h>
  20. #include <stdio.h>
  21. #include <errno.h>
  22. #include "pptp_callmgr.h"
  23. #include "pptp_ctrl.h"
  24. #include "pptp_msg.h"
  25. #include "dirutil.h"
  26. #include "vector.h"
  27. #include "util.h"
  28. extern struct in_addr localbind; /* from pptp.c */
  29. int open_inetsock(struct in_addr inetaddr);
  30. int open_unixsock(struct in_addr inetaddr);
  31. void close_inetsock(int fd, struct in_addr inetaddr);
  32. void close_unixsock(int fd, struct in_addr inetaddr);
  33. sigjmp_buf callmgr_env;
  34. void callmgr_sighandler(int sig) {
  35. /* TODO: according to signal(2), siglongjmp() is unsafe used here */
  36. siglongjmp (callmgr_env, 1);
  37. }
  38. void callmgr_do_nothing(int sig) {
  39. /* do nothing signal handler */
  40. }
  41. struct local_callinfo {
  42. int unix_sock;
  43. pid_t pid[2];
  44. };
  45. struct local_conninfo {
  46. VECTOR * call_list;
  47. fd_set * call_set;
  48. };
  49. /* Call callback */
  50. void call_callback(PPTP_CONN *conn, PPTP_CALL *call, enum call_state state)
  51. {
  52. struct local_callinfo *lci;
  53. struct local_conninfo *conninfo;
  54. u_int16_t call_id[2];
  55. switch(state) {
  56. case CALL_OPEN_DONE:
  57. /* okey dokey. This means that the call_id and peer_call_id are
  58. * now valid, so lets send them on to our friends who requested
  59. * this call. */
  60. lci = pptp_call_closure_get(conn, call); assert(lci != NULL);
  61. pptp_call_get_ids(conn, call, &call_id[0], &call_id[1]);
  62. write(lci->unix_sock, &call_id, sizeof(call_id));
  63. /* Our duty to the fatherland is now complete. */
  64. break;
  65. case CALL_OPEN_FAIL:
  66. case CALL_CLOSE_RQST:
  67. case CALL_CLOSE_DONE:
  68. /* don't need to do anything here, except make sure tables
  69. * are sync'ed */
  70. log("Closing connection (call state)");
  71. conninfo = pptp_conn_closure_get(conn);
  72. lci = pptp_call_closure_get(conn, call);
  73. assert(lci != NULL && conninfo != NULL);
  74. if (vector_contains(conninfo->call_list, lci->unix_sock)) {
  75. vector_remove(conninfo->call_list, lci->unix_sock);
  76. close(lci->unix_sock);
  77. FD_CLR(lci->unix_sock, conninfo->call_set);
  78. if(lci->pid[0] > 1) kill(lci->pid[0], SIGTERM);
  79. if(lci->pid[1] > 1) kill(lci->pid[1], SIGTERM);
  80. }
  81. break;
  82. default:
  83. log("Unhandled call callback state [%d].", (int) state);
  84. break;
  85. }
  86. }
  87. /******************************************************************************
  88. * NOTE ABOUT 'VOLATILE':
  89. * several variables here get a volatile qualifier to silence warnings
  90. * from older (before 3.0) gccs. if the longjmp stuff is removed,
  91. * the volatile qualifiers should be removed as well.
  92. *****************************************************************************/
  93. /*** Call Manager *************************************************************/
  94. int callmgr_main(int argc, char **argv, char **envp)
  95. {
  96. struct in_addr inetaddr;
  97. int inet_sock, unix_sock;
  98. fd_set call_set;
  99. PPTP_CONN * conn;
  100. VECTOR * call_list;
  101. int max_fd = 0;
  102. volatile int first = 1;
  103. int retval;
  104. int i;
  105. char * volatile phonenr;
  106. /* Step 0: Check arguments */
  107. if (argc < 2)
  108. fatal("Usage: %s ip.add.ress.here [--phone <phone number>]", argv[0]);
  109. phonenr = argc == 3 ? argv[2] : NULL;
  110. if (inet_aton(argv[1], &inetaddr) == 0)
  111. fatal("Invalid IP address: %s", argv[1]);
  112. /* Step 1: Open sockets. */
  113. if ((inet_sock = open_inetsock(inetaddr)) < 0)
  114. fatal("Could not open control connection to %s", argv[1]);
  115. if ((unix_sock = open_unixsock(inetaddr)) < 0)
  116. fatal("Could not open unix socket for %s", argv[1]);
  117. /* Step 1b: FORK and return status to calling process. */
  118. switch (fork()) {
  119. case 0: /* child. stick around. */
  120. break;
  121. case -1: /* failure. Fatal. */
  122. fatal("Could not fork.");
  123. default: /* Parent. Return status to caller. */
  124. exit(0);
  125. }
  126. /* re-open stderr as /dev/null to release it */
  127. file2fd("/dev/null", "wb", STDERR_FILENO);
  128. /* Step 1c: Clean up unix socket on TERM */
  129. if (sigsetjmp(callmgr_env, 1) != 0)
  130. goto cleanup;
  131. signal(SIGINT, callmgr_sighandler);
  132. signal(SIGTERM, callmgr_sighandler);
  133. signal(SIGPIPE, callmgr_do_nothing);
  134. signal(SIGUSR1, callmgr_do_nothing); /* signal state change
  135. wake up accept */
  136. /* Step 2: Open control connection and register callback */
  137. if ((conn = pptp_conn_open(inet_sock, 1, NULL/* callback */)) == NULL) {
  138. close(unix_sock); close(inet_sock); fatal("Could not open connection.");
  139. }
  140. FD_ZERO(&call_set);
  141. call_list = vector_create();
  142. {
  143. struct local_conninfo *conninfo = malloc(sizeof(*conninfo));
  144. if (conninfo == NULL) {
  145. close(unix_sock); close(inet_sock); fatal("No memory.");
  146. }
  147. conninfo->call_list = call_list;
  148. conninfo->call_set = &call_set;
  149. pptp_conn_closure_put(conn, conninfo);
  150. }
  151. if (sigsetjmp(callmgr_env, 1) != 0) goto shutdown;
  152. /* Step 3: Get FD_SETs */
  153. max_fd = unix_sock;
  154. do {
  155. int rc;
  156. fd_set read_set = call_set, write_set;
  157. FD_ZERO (&write_set);
  158. if (pptp_conn_established(conn)) {
  159. FD_SET (unix_sock, &read_set);
  160. if (unix_sock > max_fd) max_fd = unix_sock;
  161. }
  162. pptp_fd_set(conn, &read_set, &write_set, &max_fd);
  163. for (; max_fd > 0 ; max_fd--) {
  164. if (FD_ISSET (max_fd, &read_set) ||
  165. FD_ISSET (max_fd, &write_set))
  166. break;
  167. }
  168. /* Step 4: Wait on INET or UNIX event */
  169. if ((rc = select(max_fd + 1, &read_set, &write_set, NULL, NULL)) <0) {
  170. if (errno == EBADF) break;
  171. /* a signal or somesuch. */
  172. continue;
  173. }
  174. /* Step 5a: Handle INET events */
  175. rc = pptp_dispatch(conn, &read_set, &write_set);
  176. if (rc < 0)
  177. break;
  178. /* Step 5b: Handle new connection to UNIX socket */
  179. if (FD_ISSET(unix_sock, &read_set)) {
  180. /* New call! */
  181. struct sockaddr_un from;
  182. int len = sizeof(from);
  183. PPTP_CALL * call;
  184. struct local_callinfo *lci;
  185. int s;
  186. /* Accept the socket */
  187. FD_CLR (unix_sock, &read_set);
  188. if ((s = accept(unix_sock, (struct sockaddr *) &from, &len)) < 0) {
  189. warn("Socket not accepted: %s", strerror(errno));
  190. goto skip_accept;
  191. }
  192. /* Allocate memory for local call information structure. */
  193. if ((lci = malloc(sizeof(*lci))) == NULL) {
  194. warn("Out of memory."); close(s); goto skip_accept;
  195. }
  196. lci->unix_sock = s;
  197. /* Give the initiator time to write the PIDs while we open
  198. * the call */
  199. call = pptp_call_open(conn, call_callback, phonenr);
  200. /* Read and store the associated pids */
  201. read(s, &lci->pid[0], sizeof(lci->pid[0]));
  202. read(s, &lci->pid[1], sizeof(lci->pid[1]));
  203. /* associate the local information with the call */
  204. pptp_call_closure_put(conn, call, (void *) lci);
  205. /* The rest is done on callback. */
  206. /* Keep alive; wait for close */
  207. retval = vector_insert(call_list, s, call); assert(retval);
  208. if (s > max_fd) max_fd = s;
  209. FD_SET(s, &call_set);
  210. first = 0;
  211. }
  212. skip_accept: /* Step 5c: Handle socket close */
  213. for (i = 0; i < max_fd + 1; i++)
  214. if (FD_ISSET(i, &read_set)) {
  215. /* close it */
  216. PPTP_CALL * call;
  217. retval = vector_search(call_list, i, &call);
  218. if (retval) {
  219. struct local_callinfo *lci =
  220. pptp_call_closure_get(conn, call);
  221. log("Closing connection (unhandled)");
  222. if(lci->pid[0] > 1) kill(lci->pid[0], SIGTERM);
  223. if(lci->pid[1] > 1) kill(lci->pid[1], SIGTERM);
  224. free(lci);
  225. /* soft shutdown. Callback will do hard shutdown later */
  226. pptp_call_close(conn, call);
  227. vector_remove(call_list, i);
  228. }
  229. FD_CLR(i, &call_set);
  230. close(i);
  231. }
  232. } while (vector_size(call_list) > 0 || first);
  233. shutdown:
  234. {
  235. int rc;
  236. fd_set read_set, write_set;
  237. struct timeval tv;
  238. signal(SIGINT, callmgr_do_nothing);
  239. signal(SIGTERM, callmgr_do_nothing);
  240. /* warn("Shutdown"); */
  241. /* kill all open calls */
  242. for (i = 0; i < vector_size(call_list); i++) {
  243. PPTP_CALL *call = vector_get_Nth(call_list, i);
  244. struct local_callinfo *lci = pptp_call_closure_get(conn, call);
  245. log("Closing connection (shutdown)");
  246. pptp_call_close(conn, call);
  247. if(lci->pid[0] > 1) kill(lci->pid[0], SIGTERM);
  248. if(lci->pid[1] > 1) kill(lci->pid[1], SIGTERM);
  249. }
  250. /* attempt to dispatch these messages */
  251. FD_ZERO(&read_set);
  252. FD_ZERO(&write_set);
  253. pptp_fd_set(conn, &read_set, &write_set, &max_fd);
  254. tv.tv_sec = 0;
  255. tv.tv_usec = 0;
  256. select(max_fd + 1, &read_set, &write_set, NULL, &tv);
  257. rc = pptp_dispatch(conn, &read_set, &write_set);
  258. if (rc > 0) {
  259. /* wait for a respond, a timeout because there might not be one */
  260. FD_ZERO(&read_set);
  261. FD_ZERO(&write_set);
  262. pptp_fd_set(conn, &read_set, &write_set, &max_fd);
  263. tv.tv_sec = 2;
  264. tv.tv_usec = 0;
  265. select(max_fd + 1, &read_set, &write_set, NULL, &tv);
  266. rc = pptp_dispatch(conn, &read_set, &write_set);
  267. if (rc > 0) {
  268. if (i > 0) sleep(2);
  269. /* no more open calls. Close the connection. */
  270. pptp_conn_close(conn, PPTP_STOP_LOCAL_SHUTDOWN);
  271. /* wait for a respond, a timeout because there might not be one */
  272. FD_ZERO(&read_set);
  273. FD_ZERO(&write_set);
  274. pptp_fd_set(conn, &read_set, &write_set, &max_fd);
  275. tv.tv_sec = 2;
  276. tv.tv_usec = 0;
  277. select(max_fd + 1, &read_set, &write_set, NULL, &tv);
  278. pptp_dispatch(conn, &read_set, &write_set);
  279. if (rc > 0) sleep(2);
  280. }
  281. }
  282. /* with extreme prejudice */
  283. pptp_conn_destroy(conn);
  284. vector_destroy(call_list);
  285. }
  286. cleanup:
  287. signal(SIGINT, callmgr_do_nothing);
  288. signal(SIGTERM, callmgr_do_nothing);
  289. close_inetsock(inet_sock, inetaddr);
  290. close_unixsock(unix_sock, inetaddr);
  291. return 0;
  292. }
  293. /*** open_inetsock ************************************************************/
  294. int open_inetsock(struct in_addr inetaddr)
  295. {
  296. struct sockaddr_in dest, src;
  297. int s;
  298. dest.sin_family = AF_INET;
  299. dest.sin_port = htons(PPTP_PORT);
  300. dest.sin_addr = inetaddr;
  301. if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  302. warn("socket: %s", strerror(errno));
  303. return s;
  304. }
  305. if (localbind.s_addr != INADDR_NONE) {
  306. bzero(&src, sizeof(src));
  307. src.sin_family = AF_INET;
  308. src.sin_addr = localbind;
  309. if (bind(s, (struct sockaddr *) &src, sizeof(src)) != 0) {
  310. warn("bind: %s", strerror(errno));
  311. close(s); return -1;
  312. }
  313. }
  314. if (connect(s, (struct sockaddr *) &dest, sizeof(dest)) < 0) {
  315. warn("connect: %s", strerror(errno));
  316. close(s); return -1;
  317. }
  318. return s;
  319. }
  320. /*** open_unixsock ************************************************************/
  321. int open_unixsock(struct in_addr inetaddr)
  322. {
  323. struct sockaddr_un where;
  324. struct stat st;
  325. char *dir;
  326. int s;
  327. if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
  328. warn("socket: %s", strerror(errno));
  329. return s;
  330. }
  331. callmgr_name_unixsock( &where, inetaddr, localbind);
  332. if (stat(where.sun_path, &st) >= 0) {
  333. warn("Call manager for %s is already running.", inet_ntoa(inetaddr));
  334. close(s); return -1;
  335. }
  336. /* Make sure path is valid. */
  337. dir = dirname(where.sun_path);
  338. if (!make_valid_path(dir, 0770))
  339. fatal("Could not make path to %s: %s", where.sun_path, strerror(errno));
  340. free(dir);
  341. if (bind(s, (struct sockaddr *) &where, sizeof(where)) < 0) {
  342. warn("bind: %s", strerror(errno));
  343. close(s); return -1;
  344. }
  345. chmod(where.sun_path, 0777);
  346. listen(s, 127);
  347. return s;
  348. }
  349. /*** close_inetsock ***********************************************************/
  350. void close_inetsock(int fd, struct in_addr inetaddr)
  351. {
  352. close(fd);
  353. }
  354. /*** close_unixsock ***********************************************************/
  355. void close_unixsock(int fd, struct in_addr inetaddr)
  356. {
  357. struct sockaddr_un where;
  358. close(fd);
  359. callmgr_name_unixsock(&where, inetaddr, localbind);
  360. unlink(where.sun_path);
  361. }
  362. /*** make a unix socket address ***********************************************/
  363. void callmgr_name_unixsock(struct sockaddr_un *where,
  364. struct in_addr inetaddr,
  365. struct in_addr localbind)
  366. {
  367. char localaddr[16], remoteaddr[16];
  368. where->sun_family = AF_UNIX;
  369. strncpy(localaddr, inet_ntoa(localbind), 16);
  370. strncpy(remoteaddr, inet_ntoa(inetaddr), 16);
  371. snprintf(where->sun_path, sizeof(where->sun_path),
  372. PPTP_SOCKET_PREFIX "%s:%s", localaddr, remoteaddr);
  373. }