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