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 FD_ZERO (&write_set); 182 if (pptp_conn_established(conn)) { 183 FD_SET (unix_sock, &read_set); 184 if (unix_sock > max_fd) max_fd = unix_sock; 185 } 186 pptp_fd_set(conn, &read_set, &write_set, &max_fd); 187 for (; max_fd > 0 ; max_fd--) { 188 if (FD_ISSET (max_fd, &read_set) || 189 FD_ISSET (max_fd, &write_set)) 190 break; 191 } 192 /* Step 4: Wait on INET or UNIX event */ 193 if ((rc = select(max_fd + 1, &read_set, &write_set, NULL, NULL)) <0) { 194 if (errno == EBADF) break; 195 /* a signal or somesuch. */ 196 continue; 197 } 198 /* Step 5a: Handle INET events */ 199 rc = pptp_dispatch(conn, &read_set, &write_set); 200 if (rc < 0) 201 break; 202 /* Step 5b: Handle new connection to UNIX socket */ 203 if (FD_ISSET(unix_sock, &read_set)) { 204 /* New call! */ 205 struct sockaddr_un from; 206 int len = sizeof(from); 207 PPTP_CALL * call; 208 struct local_callinfo *lci; 209 int s; 210 /* Accept the socket */ 211 FD_CLR (unix_sock, &read_set); 212 if ((s = accept(unix_sock, (struct sockaddr *) &from, &len)) < 0) { 213 warn("Socket not accepted: %s", strerror(errno)); 214 goto skip_accept; 215 } 216 /* Allocate memory for local call information structure. */ 217 if ((lci = malloc(sizeof(*lci))) == NULL) { 218 warn("Out of memory."); close(s); goto skip_accept; 219 } 220 lci->unix_sock = s; 221 /* Give the initiator time to write the PIDs while we open 222 * the call */ 223 call = pptp_call_open(conn, call_ID,call_callback, phonenr,window); 224 /* Read and store the associated pids */ 225 read(s, &lci->pid[0], sizeof(lci->pid[0])); 226 read(s, &lci->pid[1], sizeof(lci->pid[1])); 227 /* associate the local information with the call */ 228 pptp_call_closure_put(conn, call, (void *) lci); 229 /* The rest is done on callback. */ 230 /* Keep alive; wait for close */ 231 retval = vector_insert(call_list, s, call); assert(retval); 232 if (s > max_fd) max_fd = s; 233 FD_SET(s, &call_set); 234 first = 0; 235 } 236skip_accept: /* Step 5c: Handle socket close */ 237 for (i = 0; i < max_fd + 1; i++) 238 if (FD_ISSET(i, &read_set)) { 239 /* close it */ 240 PPTP_CALL * call; 241 retval = vector_search(call_list, i, &call); 242 if (retval) { 243 struct local_callinfo *lci = 244 pptp_call_closure_get(conn, call); 245 log("Closing connection (unhandled)"); 246 //if(lci->pid[0] > 1) kill(lci->pid[0], SIGTERM); 247 //if(lci->pid[1] > 1) kill(lci->pid[1], SIGTERM); 248 free(lci); 249 /* soft shutdown. Callback will do hard shutdown later */ 250 pptp_call_close(conn, call); 251 vector_remove(call_list, i); 252 } 253 FD_CLR(i, &call_set); 254 close(i); 255 } 256 } while (vector_size(call_list) > 0 || first); 257shutdown: 258 { 259 int rc; 260 fd_set read_set, write_set; 261 struct timeval tv; 262 signal(SIGINT, callmgr_do_nothing); 263 signal(SIGTERM, callmgr_do_nothing); 264 /* warn("Shutdown"); */ 265 /* kill all open calls */ 266 for (i = 0; i < vector_size(call_list); i++) { 267 PPTP_CALL *call = vector_get_Nth(call_list, i); 268 //struct local_callinfo *lci = pptp_call_closure_get(conn, call); 269 log("Closing connection (shutdown)"); 270 pptp_call_close(conn, call); 271 //if(lci->pid[0] > 1) kill(lci->pid[0], SIGTERM); 272 //if(lci->pid[1] > 1) kill(lci->pid[1], SIGTERM); 273 } 274 /* attempt to dispatch these messages */ 275 FD_ZERO(&read_set); 276 FD_ZERO(&write_set); 277 pptp_fd_set(conn, &read_set, &write_set, &max_fd); 278 tv.tv_sec = 0; 279 tv.tv_usec = 0; 280 select(max_fd + 1, &read_set, &write_set, NULL, &tv); 281 rc = pptp_dispatch(conn, &read_set, &write_set); 282 if (rc > 0) { 283 /* wait for a respond, a timeout because there might not be one */ 284 FD_ZERO(&read_set); 285 FD_ZERO(&write_set); 286 pptp_fd_set(conn, &read_set, &write_set, &max_fd); 287 tv.tv_sec = 2; 288 tv.tv_usec = 0; 289 select(max_fd + 1, &read_set, &write_set, NULL, &tv); 290 rc = pptp_dispatch(conn, &read_set, &write_set); 291 if (rc > 0) { 292 if (i > 0) sleep(2); 293 /* no more open calls. Close the connection. */ 294 pptp_conn_close(conn, PPTP_STOP_LOCAL_SHUTDOWN); 295 /* wait for a respond, a timeout because there might not be one */ 296 FD_ZERO(&read_set); 297 FD_ZERO(&write_set); 298 pptp_fd_set(conn, &read_set, &write_set, &max_fd); 299 tv.tv_sec = 2; 300 tv.tv_usec = 0; 301 select(max_fd + 1, &read_set, &write_set, NULL, &tv); 302 pptp_dispatch(conn, &read_set, &write_set); 303 if (rc > 0) sleep(2); 304 } 305 } 306 /* with extreme prejudice */ 307 pptp_conn_destroy(conn); 308 vector_destroy(call_list); 309 } 310cleanup: 311 signal(SIGINT, callmgr_do_nothing); 312 signal(SIGTERM, callmgr_do_nothing); 313 close_inetsock(inet_sock, inetaddr); 314 close_unixsock(unix_sock, inetaddr); 315 return 0; 316} 317 318/*** open_inetsock ************************************************************/ 319int open_inetsock(struct in_addr inetaddr) 320{ 321 struct sockaddr_in dest, src; 322 int s; 323 dest.sin_family = AF_INET; 324 dest.sin_port = htons(PPTP_PORT); 325 dest.sin_addr = inetaddr; 326 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 327 warn("socket: %s", strerror(errno)); 328 return s; 329 } 330 if (localbind.s_addr != INADDR_NONE) { 331 bzero(&src, sizeof(src)); 332 src.sin_family = AF_INET; 333 src.sin_addr = localbind; 334 if (bind(s, (struct sockaddr *) &src, sizeof(src)) != 0) { 335 warn("bind: %s", strerror(errno)); 336 close(s); return -1; 337 } 338 } 339 if (connect(s, (struct sockaddr *) &dest, sizeof(dest)) < 0) { 340 warn("connect: %s", strerror(errno)); 341 close(s); return -1; 342 } 343 return s; 344} 345 346/*** open_unixsock ************************************************************/ 347int open_unixsock(struct in_addr inetaddr) 348{ 349 struct sockaddr_un where; 350 struct stat st; 351 char *dir; 352 int s; 353 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { 354 warn("socket: %s", strerror(errno)); 355 return s; 356 } 357 callmgr_name_unixsock( &where, inetaddr, localbind); 358 if (stat(where.sun_path, &st) >= 0) 359 { 360 warn("Call manager for %s is already running.", inet_ntoa(inetaddr)); 361 close(s); return -1; 362 } 363 /* Make sure path is valid. */ 364 dir = dirnamex(where.sun_path); 365 if (!make_valid_path(dir, 0770)) 366 fatal("Could not make path to %s: %s", where.sun_path, strerror(errno)); 367 free(dir); 368 if (bind(s, (struct sockaddr *) &where, sizeof(where)) < 0) { 369 warn("bind: %s", strerror(errno)); 370 close(s); return -1; 371 } 372 chmod(where.sun_path, 0777); 373 listen(s, 127); 374 return s; 375} 376 377/*** close_inetsock ***********************************************************/ 378void close_inetsock(int fd, struct in_addr inetaddr) 379{ 380 close(fd); 381} 382 383/*** close_unixsock ***********************************************************/ 384void close_unixsock(int fd, struct in_addr inetaddr) 385{ 386 struct sockaddr_un where; 387 close(fd); 388 callmgr_name_unixsock(&where, inetaddr, localbind); 389 unlink(where.sun_path); 390} 391 392/*** make a unix socket address ***********************************************/ 393void callmgr_name_unixsock(struct sockaddr_un *where, 394 struct in_addr inetaddr, 395 struct in_addr localbind) 396{ 397 char localaddr[16], remoteaddr[16]; 398 where->sun_family = AF_UNIX; 399 strncpy(localaddr, inet_ntoa(localbind), 16); 400 strncpy(remoteaddr, inet_ntoa(inetaddr), 16); 401 snprintf(where->sun_path, sizeof(where->sun_path), 402 PPTP_SOCKET_PREFIX "%s:%i", remoteaddr,call_ID); 403} 404