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