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