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