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
29extern struct in_addr localbind; /* from pptp.c */
30
31int open_inetsock(struct in_addr inetaddr);
32int open_unixsock(struct in_addr inetaddr);
33void close_inetsock(int fd, struct in_addr inetaddr);
34void close_unixsock(int fd, struct in_addr inetaddr);
35
36sigjmp_buf callmgr_env;
37
38void callmgr_sighandler(int sig) {
39    /* TODO: according to signal(2), siglongjmp() is unsafe used here */
40    siglongjmp (callmgr_env, 1);
41}
42
43void callmgr_do_nothing(int sig) {
44    /* do nothing signal handler */
45}
46
47struct local_callinfo {
48    int unix_sock;
49    pid_t pid[2];
50};
51
52struct local_conninfo {
53    VECTOR * call_list;
54    fd_set * call_set;
55};
56
57/* Call callback */
58void call_callback(PPTP_CONN *conn, PPTP_CALL *call, enum call_state state)
59{
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);
88            }
89            break;
90        default:
91            log("Unhandled call callback state [%d].", (int) state);
92            break;
93    }
94}
95
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 *****************************************************************************/
102
103/*** Call Manager *************************************************************/
104int callmgr_main(int argc, char **argv, char **envp)
105{
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);
135    }
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.");
149    }
150    FD_ZERO(&call_set);
151    call_list = vector_create();
152    {
153        struct local_conninfo *conninfo = malloc(sizeof(*conninfo));
154        if (conninfo == NULL) {
155            close(unix_sock); close(inet_sock); fatal("No memory.");
156        }
157        conninfo->call_list = call_list;
158        conninfo->call_set  = &call_set;
159        pptp_conn_closure_put(conn, conninfo);
160    }
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;
171	}
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;
177        }
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;
183	}
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;
201            }
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;
205            }
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;
221        }
222skip_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);
238                }
239                FD_CLR(i, &call_set);
240                close(i);
241            }
242    } while (vector_size(call_list) > 0 || first);
243shutdown:
244    {
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);
259        }
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);
290	  }
291	}
292        /* with extreme prejudice */
293        pptp_conn_destroy(conn);
294        vector_destroy(call_list);
295    }
296cleanup:
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;
302}
303
304/*** open_inetsock ************************************************************/
305int open_inetsock(struct in_addr inetaddr)
306{
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;
315    }
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;
323        }
324    }
325    if (connect(s, (struct sockaddr *) &dest, sizeof(dest)) < 0) {
326        warn("connect: %s", strerror(errno));
327        close(s); return -1;
328    }
329    return s;
330}
331
332/*** open_unixsock ************************************************************/
333int open_unixsock(struct in_addr inetaddr)
334{
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;
342    }
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;
347    }
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;
356    }
357    chmod(where.sun_path, 0777);
358    listen(s, 127);
359    return s;
360}
361
362/*** close_inetsock ***********************************************************/
363void close_inetsock(int fd, struct in_addr inetaddr)
364{
365    close(fd);
366}
367
368/*** close_unixsock ***********************************************************/
369void close_unixsock(int fd, struct in_addr inetaddr)
370{
371    struct sockaddr_un where;
372    close(fd);
373    callmgr_name_unixsock(&where, inetaddr, localbind);
374    unlink(where.sun_path);
375}
376
377/*** make a unix socket address ***********************************************/
378void callmgr_name_unixsock(struct sockaddr_un *where,
379			   struct in_addr inetaddr,
380			   struct in_addr localbind)
381{
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);
388}
389