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