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 $
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
22 #include "pptp_callmgr.h"
23 #include "pptp_ctrl.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
{
52 struct local_conninfo
{
58 void call_callback(PPTP_CONN
*conn
, PPTP_CALL
*call
, enum call_state state
)
60 struct local_callinfo
*lci
;
61 struct local_conninfo
*conninfo
;
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
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. */
76 /* don't need to do anything here, except make sure tables
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
);
91 log("Unhandled call callback state [%d].", (int) state
);
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
;
112 volatile int first
= 1;
115 char * volatile phonenr
;
116 /* Step 0: Check arguments */
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. */
129 case 0: /* child. stick around. */
131 case -1: /* failure. Fatal. */
132 fatal("Could not fork.");
133 default: /* Parent. Return status to caller. */
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)
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
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.");
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 */
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
))
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. */
184 /* Step 5a: Handle INET events */
185 rc
= pptp_dispatch(conn
, &read_set
, &write_set
);
188 /* Step 5b: Handle new connection to UNIX socket */
189 if (FD_ISSET(unix_sock
, &read_set
)) {
191 struct sockaddr_un from
;
192 int len
= sizeof(from
);
194 struct local_callinfo
*lci
;
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
));
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
;
207 /* Give the initiator time to write the PIDs while we open
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
);
222 skip_accept
: /* Step 5c: Handle socket close */
223 for (i
= 0; i
< max_fd
+ 1; i
++)
224 if (FD_ISSET(i
, &read_set
)) {
227 retval
= vector_search(call_list
, i
, &call
);
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
);
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
);
242 } while (vector_size(call_list
) > 0 || first
);
246 fd_set read_set
, write_set
;
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 */
263 pptp_fd_set(conn
, &read_set
, &write_set
, &max_fd
);
266 select(max_fd
+ 1, &read_set
, &write_set
, NULL
, &tv
);
267 rc
= pptp_dispatch(conn
, &read_set
, &write_set
);
269 /* wait for a respond, a timeout because there might not be one */
272 pptp_fd_set(conn
, &read_set
, &write_set
, &max_fd
);
275 select(max_fd
+ 1, &read_set
, &write_set
, NULL
, &tv
);
276 rc
= pptp_dispatch(conn
, &read_set
, &write_set
);
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 */
284 pptp_fd_set(conn
, &read_set
, &write_set
, &max_fd
);
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
);
297 signal(SIGINT
, callmgr_do_nothing
);
298 signal(SIGTERM
, callmgr_do_nothing
);
299 close_inetsock(inet_sock
, inetaddr
);
300 close_unixsock(unix_sock
, inetaddr
);
304 /*** open_inetsock ************************************************************/
305 int open_inetsock(struct in_addr inetaddr
)
307 struct sockaddr_in dest
, src
;
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
));
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
));
325 if (connect(s
, (struct sockaddr
*) &dest
, sizeof(dest
)) < 0) {
326 warn("connect: %s", strerror(errno
));
332 /*** open_unixsock ************************************************************/
333 int open_unixsock(struct in_addr inetaddr
)
335 struct sockaddr_un where
;
339 if ((s
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
340 warn("socket: %s", strerror(errno
));
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
));
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
));
353 if (bind(s
, (struct sockaddr
*) &where
, sizeof(where
)) < 0) {
354 warn("bind: %s", strerror(errno
));
357 chmod(where
.sun_path
, 0777);
362 /*** close_inetsock ***********************************************************/
363 void close_inetsock(int fd
, struct in_addr inetaddr
)
368 /*** close_unixsock ***********************************************************/
369 void close_unixsock(int fd
, struct in_addr inetaddr
)
371 struct sockaddr_un where
;
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
);