1/* 2 * pptpctrl.c 3 * 4 * PPTP control connection between PAC-PNS pair 5 * 6 * $Id: pptpctrl.c,v 1.19 2005/10/30 22:40:41 quozl Exp $ 7 * 8 * 24.02.2008 Bugs fixed by Serbulov D. (SDY) 9 * + added SIGCHLD control 10 * + added PPPD kill on stop ses 11 * + correct exit on duplicate connection 12 * 13 */ 14 15#ifdef HAVE_CONFIG_H 16#include "config.h" 17#endif 18 19#ifdef __linux__ 20#define _GNU_SOURCE 1 /* kill() prototype, broken arpa/inet.h */ 21#endif 22 23#include "our_syslog.h" 24 25#include <fcntl.h> 26#include <errno.h> 27#include <signal.h> 28#include <unistd.h> 29#include <string.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <time.h> 33#include <sys/time.h> 34#include <dirent.h> 35#include <sys/types.h> 36#include <sys/wait.h> 37#include <sys/socket.h> 38#include <sys/ioctl.h> 39#include <netinet/in.h> 40#include <arpa/inet.h> 41#ifdef HAVE_OPENPTY 42#ifdef HAVE_PTY_H 43#include <pty.h> 44#endif 45#ifdef HAVE_LIBUTIL_H 46#include <libutil.h> 47#endif 48#endif 49 50#ifdef __UCLIBC__ 51#define socklen_t int 52#endif 53 54#include "compat.h" 55#include "pptpctrl.h" 56#include "pptpdefs.h" 57#include "ctrlpacket.h" 58#include "defaults.h" 59// placing net/if.h here fixes build on Solaris 60#include <net/if.h> 61#include <net/ethernet.h> 62//#include "if_pppox.h" //Yau del 63#include <linux/if_pppox.h> 64 65static char *ppp_binary = PPP_BINARY; 66static int pptp_logwtmp; 67static int noipparam; /* if true, don't send ipparam to ppp */ 68static char speed[32]; 69static char pppdxfig[256]; 70static pid_t pppfork; /* so we can kill it after disconnect */ 71 72/* 73 * Global to handle dying 74 * 75 * I'd be nice if someone could figure out a way to do it 76 * without the global, but i don't think you can.. -tmk 77 */ 78#define clientSocket 0 /* in case it changes back to a variable */ 79static u_int32_t call_id_pair; /* call id (to terminate call) */ 80int window=10; 81int pptp_sock=-1; 82struct in_addr inetaddrs[2]; 83 84/* Needed by this and ctrlpacket.c */ 85int pptpctrl_debug = 0; /* specifies if debugging is on or off */ 86uint16_t unique_call_id = 0xFFFF; /* Start value for our call IDs on this TCP link */ 87int pptp_timeout=1000000; 88 89int gargc; /* Command line argument count */ 90char **gargv; /* Command line argument vector */ 91 92/* Local function prototypes */ 93static void bail(int sigraised); 94static void pptp_handle_ctrl_connection(char **pppaddrs, struct in_addr *inetaddrs); 95 96static int startCall(char **pppaddrs, struct in_addr *inetaddrs); 97static void launch_pppd(char **pppaddrs, struct in_addr *inetaddrs); 98 99/* Oh the horror.. lets hope this covers all the ones we have to handle */ 100#if defined(O_NONBLOCK) && !defined(__sun__) && !defined(__sun) 101#define OUR_NB_MODE O_NONBLOCK 102#else 103#define OUR_NB_MODE O_NDELAY 104#endif 105 106/* read a command line argument, a flag alone */ 107#define GETARG_INT(X) \ 108 X = atoi(argv[arg++]) 109 110/* read a command line argument, a string alone */ 111#define GETARG_STRING(X) \ 112 X = strdup(argv[arg++]) 113 114/* read a command line argument, a presence flag followed by string */ 115#define GETARG_VALUE(X) \ 116 if(atoi(argv[arg++]) != 0) \ 117 strlcpy(X, argv[arg++], sizeof(X)); \ 118 else \ 119 *X = '\0' 120 121int main(int argc, char **argv) 122{ 123 char pppLocal[16]; /* local IP to pass to pppd */ 124 char pppRemote[16]; /* remote IP address to pass to pppd */ 125 struct sockaddr_in addr; /* client address */ 126 socklen_t addrlen; 127 int arg = 1; 128 int flags; 129 char *pppaddrs[2] = { pppLocal, pppRemote }; 130 131 gargc = argc; 132 gargv = argv; 133 134 /* fail if argument count invalid */ 135 if (argc < 7) { 136 fprintf(stderr, "pptpctrl: insufficient arguments, see man pptpctrl\n"); 137 exit(2); 138 } 139 140 /* open a connection to the syslog daemon */ 141 openlog("pptpd", LOG_PID, PPTP_FACILITY); 142 143 /* autoreap if supported */ 144 signal(SIGCHLD, SIG_IGN); 145 146 /* note: update pptpctrl.8 if the argument list format is changed */ 147 GETARG_INT(pptpctrl_debug); 148 GETARG_INT(noipparam); 149 GETARG_VALUE(pppdxfig); 150 GETARG_VALUE(speed); 151 GETARG_VALUE(pppLocal); 152 GETARG_VALUE(pppRemote); 153 if (arg < argc) GETARG_INT(pptp_timeout); 154 if (arg < argc) GETARG_STRING(ppp_binary); 155 if (arg < argc) GETARG_INT(pptp_logwtmp); 156 157 if (pptpctrl_debug) { 158 if (*pppLocal) 159 syslog(LOG_DEBUG, "CTRL: local address = %s", pppLocal); 160 if (*pppRemote) 161 syslog(LOG_DEBUG, "CTRL: remote address = %s", pppRemote); 162 if (*speed) 163 syslog(LOG_DEBUG, "CTRL: pppd speed = %s", speed); 164 if (*pppdxfig) 165 syslog(LOG_DEBUG, "CTRL: pppd options file = %s", pppdxfig); 166 } 167 168 addrlen = sizeof(addr); 169 if (getsockname(clientSocket, (struct sockaddr *) &addr, &addrlen) != 0) { 170 syslog(LOG_ERR, "CTRL: getsockname() failed"); 171 syslog_perror("getsockname"); 172 close(clientSocket); 173 bail(0); /* NORETURN */ 174 } 175 inetaddrs[0] = addr.sin_addr; 176 177 addrlen = sizeof(addr); 178 if (getpeername(clientSocket, (struct sockaddr *) &addr, &addrlen) != 0) { 179 syslog(LOG_ERR, "CTRL: getpeername() failed"); 180 syslog_perror("getpeername"); 181 close(clientSocket); 182 bail(0); /* NORETURN */ 183 } 184 inetaddrs[1] = addr.sin_addr; 185 186 /* Set non-blocking */ 187 if ((flags = fcntl(clientSocket, F_GETFL, arg /* ignored */)) == -1 || 188 fcntl(clientSocket, F_SETFL, flags|OUR_NB_MODE) == -1) { 189 syslog(LOG_ERR, "CTRL: Failed to set client socket non-blocking"); 190 syslog_perror("fcntl"); 191 close(clientSocket); 192 bail(0); /* NORETURN */ 193 } 194 195 196 /* Fiddle with argv */ 197 my_setproctitle(gargc, gargv, "pptpd [%s]%20c", 198 inet_ntoa(addr.sin_addr), ' '); 199 200 /* be ready for a grisly death */ 201 sigpipe_create(); 202 sigpipe_assign(SIGCHLD); 203 sigpipe_assign(SIGTERM); 204 NOTE_VALUE(PAC, call_id_pair, htons(-1)); 205 NOTE_VALUE(PNS, call_id_pair, htons(-1)); 206 207 syslog(LOG_INFO, "CTRL: Client %s control connection started", inet_ntoa(addr.sin_addr)); 208 pptp_handle_ctrl_connection(pppaddrs, inetaddrs); 209 210 syslog(LOG_DEBUG, "CTRL: Reaping child PPP[%i]", pppfork); 211 bail(0); /* NORETURN */ 212 syslog(LOG_INFO, "CTRL: Client %s control connection finished", inet_ntoa(addr.sin_addr)); 213 return 1; /* make gcc happy */ 214} 215 216//SDY special for prevent pppd session stay on air then need to stop 217void waitclosefork(int sigraised) 218{ 219 //SDY senf term to fork(); 220 if (pppfork > 0) 221 { 222 if (sigraised != SIGCHLD) { 223 syslog(LOG_INFO, "CTRL: Client pppd TERM sending"); 224 kill(pppfork,SIGTERM); 225 } 226 syslog(LOG_INFO, "CTRL: Client pppd finish wait"); 227 waitpid(pppfork, NULL, 0); 228 } 229} 230 231/* 232 * Local functions only below 233 */ 234 235/* 236 * pptp_handle_ctrl_connection 237 * 238 * 1. read a packet (should be start_ctrl_conn_rqst) 239 * 2. reply to packet (send a start_ctrl_conn_rply) 240 * 3. proceed with GRE and CTRL connections 241 * 242 * args: pppaddrs - ppp local and remote addresses (strings) 243 * inetaddrs - local and client socket address 244 * retn: 0 success, -1 failure 245 */ 246static void pptp_handle_ctrl_connection(char **pppaddrs, struct in_addr *inetaddrs) 247{ 248 249 /* For echo requests used to check link is alive */ 250 int echo_wait = FALSE; /* Waiting for echo? */ 251 u_int32_t echo_count = 0; /* Sequence # of echo */ 252 time_t echo_time = 0; /* Time last echo req sent */ 253 struct timeval idleTime; /* How long to select() */ 254 255 /* General local variables */ 256 ssize_t rply_size; /* Reply packet size */ 257 fd_set fds; /* For select() */ 258 int maxfd = clientSocket; /* For select() */ 259 int send_packet; /* Send a packet this time? */ 260#if BSDUSER_PPP || SLIRP 261/* not needed by stuff which uses socketpair() in startCall() */ 262#define init 1 263#else 264 int init = 0; /* Has pppd initialized the pty? */ 265#endif 266 int sig_fd = sigpipe_fd(); /* Signal pipe descriptor */ 267 268 unsigned char packet[PPTP_MAX_CTRL_PCKT_SIZE]; 269 unsigned char rply_packet[PPTP_MAX_CTRL_PCKT_SIZE]; 270 271 struct sockaddr_pppox dst_addr; 272 273 for (;;) { 274 275 FD_ZERO(&fds); 276 FD_SET(sig_fd, &fds); 277 FD_SET(clientSocket, &fds); 278 279 /* set timeout */ 280 idleTime.tv_sec = IDLE_WAIT; 281 idleTime.tv_usec = 0; 282 283 /* default: do nothing */ 284 send_packet = FALSE; 285 286 switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) { 287 case -1: /* Error with select() */ 288 if (errno != EINTR) 289 syslog(LOG_ERR, "CTRL: Error with select(), quitting"); 290 goto leave_clear_call; 291 292 case 0: 293 if (echo_wait != TRUE) { 294 /* Timeout. Start idle link detection. */ 295 echo_count++; 296 if (pptpctrl_debug) 297 syslog(LOG_DEBUG, "CTRL: Sending ECHO REQ id %d", echo_count); 298 time(&echo_time); 299 make_echo_req_packet(rply_packet, &rply_size, echo_count); 300 echo_wait = TRUE; 301 send_packet = TRUE; 302 } 303 break; 304 305 default: 306 break; 307 } 308 309 /* check for pending SIGTERM delivery */ 310 if (FD_ISSET(sig_fd, &fds)) { 311 int signum = sigpipe_read(); 312 if (signum == SIGCHLD) 313 bail(SIGCHLD); 314 else if (signum == SIGTERM) 315 bail(SIGTERM); 316 } 317 318 /* handle control messages */ 319 320 if (FD_ISSET(clientSocket, &fds)) { 321 send_packet = TRUE; 322 switch (read_pptp_packet(clientSocket, packet, rply_packet, &rply_size)) { 323 case 0: 324 syslog(LOG_ERR, "CTRL: CTRL read failed"); 325 goto leave_drop_call; 326 327 case -1: 328 send_packet = FALSE; 329 break; 330 331 case STOP_CTRL_CONN_RQST: 332 if (pptpctrl_debug) 333 syslog(LOG_DEBUG, "CTRL: Received STOP CTRL CONN request (disconnecting)"); 334 send_pptp_packet(clientSocket, rply_packet, rply_size); 335 goto leave_drop_call; 336 337 case CALL_CLR_RQST: 338 if(pptpctrl_debug) 339 syslog(LOG_DEBUG, "CTRL: Received CALL CLR request (closing call)"); 340 /* violating RFC */ 341 goto leave_drop_call; 342 343 case OUT_CALL_RQST: 344 /* for killing off the link later (ugly) */ 345 NOTE_VALUE(PAC, call_id_pair, ((struct pptp_out_call_rply *) (rply_packet))->call_id); 346 NOTE_VALUE(PNS, call_id_pair, ((struct pptp_out_call_rply *) (rply_packet))->call_id_peer); 347 348 dst_addr.sa_family=AF_PPPOX; 349 dst_addr.sa_protocol=PX_PROTO_PPTP; 350 dst_addr.sa_addr.pptp.call_id=htons(((struct pptp_out_call_rply *) (rply_packet))->call_id_peer); 351 dst_addr.sa_addr.pptp.sin_addr=inetaddrs[1]; 352 353 if (connect(pptp_sock,(struct sockaddr*)&dst_addr,sizeof(dst_addr))){ 354 syslog(LOG_INFO,"CTRL: failed to connect PPTP socket (%s)\n",strerror(errno)); 355 goto leave_drop_call; //SDY close on correct! 356 break; 357 } 358 359 360 /* change process title for accounting and status scripts */ 361 my_setproctitle(gargc, gargv, 362 "pptpd [%s:%04X - %04X]", 363 inet_ntoa(inetaddrs[1]), 364 ntohs(((struct pptp_out_call_rply *) (rply_packet))->call_id_peer), 365 ntohs(((struct pptp_out_call_rply *) (rply_packet))->call_id)); 366 /* start the call, by launching pppd */ 367 syslog(LOG_INFO, "CTRL: Starting call (launching pppd, opening GRE)"); 368 startCall(pppaddrs, inetaddrs); 369 close(pptp_sock); 370 pptp_sock=-1; 371 break; 372 373 case ECHO_RPLY: 374 if (echo_wait == TRUE && ((struct pptp_echo_rply *) (packet))->identifier == echo_count) 375 echo_wait = FALSE; 376 else 377 syslog(LOG_WARNING, "CTRL: Unexpected ECHO REPLY packet"); 378 /* FALLTHRU */ 379 case SET_LINK_INFO: 380 send_packet = FALSE; 381 break; 382 383#ifdef PNS_MODE 384 case IN_CALL_RQST: 385 case IN_CALL_RPLY: 386 case IN_CALL_CONN: 387#endif 388 389 case CALL_DISCONN_NTFY: 390 case STOP_CTRL_CONN_RPLY: 391 /* These don't generate replies. Also they come from things we don't send in this section. */ 392 syslog(LOG_WARNING, "CTRL: Got a reply to a packet we didn't send"); 393 send_packet = FALSE; 394 break; 395 396 /* Otherwise, the already-formed reply will do fine, so send it */ 397 } 398 } 399 400 /* send reply packet - this may block, but it should be very rare */ 401 if (send_packet == TRUE && send_pptp_packet(clientSocket, rply_packet, rply_size) < 0) { 402 syslog(LOG_ERR, "CTRL: Error sending GRE, aborting call"); 403 goto leave_clear_call; 404 } 405 406 /* waiting for echo reply and curtime - echo_time > max wait */ 407 if (echo_wait == TRUE && (time(NULL) - echo_time) > MAX_ECHO_WAIT) { 408 syslog(LOG_INFO, "CTRL: Session timed out, ending call"); 409 goto leave_clear_call; 410 } 411 } 412 /* Finished! :-) */ 413leave_drop_call: 414 NOTE_VALUE(PAC, call_id_pair, htons(-1)); 415 NOTE_VALUE(PNS, call_id_pair, htons(-1)); 416 close(clientSocket); 417leave_clear_call: 418 return; 419#ifdef init 420#undef init 421#endif 422} 423 424 425/* 426 * This is the custom exit() for this program. 427 * 428 * Updated to also be the default SIGTERM handler, and if 429 * the link is going down for unnatural reasons, we will close it 430 * right now, it's only been tested for win98, other tests would be nice 431 * -tmk 432 */ 433static void bail(int sigraised) 434{ 435 if (sigraised) 436 syslog(LOG_INFO, "CTRL: Exiting on signal %d", sigraised); 437 438 waitclosefork(sigraised); 439 440 /* send a disconnect to the other end */ 441 /* ignore any errors */ 442 if (GET_VALUE(PAC, call_id_pair) != htons(-1)) { 443 fd_set connSet; /* fd_set for select() */ 444 struct timeval tv; /* time to wait for reply */ 445 unsigned char packet[PPTP_MAX_CTRL_PCKT_SIZE]; 446 unsigned char rply_packet[PPTP_MAX_CTRL_PCKT_SIZE]; 447 ssize_t rply_size; /* reply packet size */ 448 int pkt; 449 int retry = 0; 450 451 if (pptpctrl_debug) 452 syslog(LOG_DEBUG, "CTRL: Exiting with active call"); 453 454 make_call_admin_shutdown(rply_packet, &rply_size); 455 if(send_pptp_packet(clientSocket, rply_packet, rply_size) < 0) 456 goto skip; 457 458 make_stop_ctrl_req(rply_packet, &rply_size); 459 if(send_pptp_packet(clientSocket, rply_packet, rply_size) < 0) 460 goto skip; 461 462 FD_ZERO(&connSet); 463 FD_SET(clientSocket, &connSet); 464 tv.tv_sec = 5; /* wait 5 secs for a reply then quit */ 465 tv.tv_usec = 0; 466 467 /* Wait for STOP CTRL CONN RQST or RPLY */ 468 while (select(clientSocket + 1, &connSet, NULL, NULL, &tv) == 1) { 469 switch((pkt = read_pptp_packet(clientSocket, packet, rply_packet, &rply_size))) { 470 case STOP_CTRL_CONN_RQST: 471 send_pptp_packet(clientSocket, rply_packet, rply_size); 472 goto skip; 473 case CALL_CLR_RQST: 474 syslog(LOG_WARNING, "CTRL: Got call clear request after call manually shutdown - buggy client"); 475 break; 476 case STOP_CTRL_CONN_RPLY: 477 goto skip; 478 case -1: 479 syslog(LOG_WARNING, "CTRL: Retryable error in disconnect sequence"); 480 retry++; 481 break; 482 case 0: 483 syslog(LOG_WARNING, "CTRL: Fatal error reading control message in disconnect sequence"); 484 goto skip; 485 default: 486 syslog(LOG_WARNING, "CTRL: Unexpected control message %d in disconnect sequence", pkt); 487 retry++; 488 break; 489 } 490 tv.tv_sec = 5; /* wait 5 secs for another reply then quit */ 491 tv.tv_usec = 0; 492 if (retry > 100) { 493 syslog(LOG_WARNING, "CTRL: Too many retries (%d) - giving up", retry); 494 break; 495 } 496 } 497 498 skip: 499 NOTE_VALUE(PAC, call_id_pair, htons(-1)); 500 NOTE_VALUE(PNS, call_id_pair, htons(-1)); 501 close(clientSocket); 502 } 503 504 if (pptpctrl_debug) 505 syslog(LOG_DEBUG, "CTRL: Exiting now"); 506} 507 508/* 509 * startCall 510 * 511 * Launches PPPD for the call. 512 * 513 * args: pppaddrs - local/remote IPs or "" for either/both if none 514 * retn: pty file descriptor 515 * 516 */ 517static int startCall(char **pppaddrs, struct in_addr *inetaddrs) 518{ 519 /* Launch the PPPD */ 520#ifndef HAVE_FORK 521 switch(pppfork=vfork()){ 522#else 523 switch(pppfork=fork()){ 524#endif 525 case -1: /* fork() error */ 526 syslog(LOG_ERR, "CTRL: Error forking to exec pppd"); 527 _exit(1); 528 529 case 0: /* child */ 530/* In case we move clientSocket back off stdin */ 531#ifndef clientSocket 532 if (clientSocket > 1) 533 close(clientSocket); 534#elif clientSocket > 1 535 close(clientSocket); 536#endif 537 launch_pppd(pppaddrs, inetaddrs); 538 syslog(LOG_ERR, "CTRL: PPPD launch failed! (launch_pppd did not fork)"); 539 _exit(1); 540 } 541 542 return -1; 543} 544 545/* 546 * launch_pppd 547 * 548 * Launches the PPP daemon. The PPP daemon is responsible for assigning the 549 * PPTP client its IP address.. These values are assigned via the command 550 * line. 551 * 552 * Add return of connected ppp interface 553 * 554 * retn: 0 on success, -1 on failure. 555 * 556 */ 557static void launch_pppd(char **pppaddrs, struct in_addr *inetaddrs) 558{ 559 char *pppd_argv[25]; 560 int an = 0; 561 sigset_t sigs; 562 char tmp[128]; 563 564 pppd_argv[an++] = ppp_binary; 565 566 if (pptpctrl_debug) { 567 syslog(LOG_DEBUG, 568 "CTRL (PPPD Launcher): program binary = %s", 569 pppd_argv[an - 1]); 570 } 571 572#if BSDUSER_PPP 573 574 /* The way that Brian Somers' user-land ppp works is to use the 575 * system name as a reference for most of the useful options. Hence 576 * most things can't be defined on the command line. On OpenBSD at 577 * least the file used for the systems is /etc/ppp/ppp.conf, where 578 * the pptp stanza should look something like: 579 580 pptp: 581 set speed sync 582 enable pap 583 enable chap 584 set dns a.a.a.a b.b.b.b 585 set ndbs x.x.x.x y.y.y.y 586 accept dns 587 add 10.0.0/24 588 589 * To be honest, at the time of writing, I haven't had the thing 590 * working enough to understand :) I will update this comment and 591 * make a sample config available when I get there. 592 */ 593 594 /* options for BSDUSER_PPP 595 * 596 * ignores IP addresses, config file option, speed 597 * fix usage info in pptpd.c and configure script if this changes 598 * 599 * IP addresses can be specified in /etc/ppp/ppp.secret per user 600 */ 601 pppd_argv[an++] = "-direct"; 602 pppd_argv[an++] = "pptp"; /* XXX this is the system name */ 603 /* should be dynamic - PMG */ 604 605#elif SLIRP 606 607 /* options for SLIRP 608 * 609 * ignores IP addresses from config - SLIRP handles this 610 */ 611 pppd_argv[an++] = "-P"; 612 pppd_argv[an++] = "+chap"; 613 pppd_argv[an++] = "-b"; 614 615 /* If a speed has been specified, use it 616 * if not, use "smart" default (defaults.h) 617 */ 618 if (*speed) { 619 pppd_argv[an++] = speed; 620 } else { 621 pppd_argv[an++] = PPP_SPEED_DEFAULT; 622 } 623 624 if (*pppdxfig) { 625 pppd_argv[an++] = "-f"; 626 pppd_argv[an++] = pppdxfig; 627 } 628 629 if (pptpctrl_debug) { 630 syslog(LOG_DEBUG, "CTRL (PPPD Launcher): Connection speed = %s", pppd_argv[an - 1]); 631 } 632#else 633 634 /* options for 'normal' pppd */ 635 636 pppd_argv[an++] = "local"; 637 638 /* If a pppd option file is specified, use it 639 * if not, pppd will default to /etc/ppp/options 640 */ 641 if (*pppdxfig) { 642 pppd_argv[an++] = "file"; 643 pppd_argv[an++] = pppdxfig; 644 } 645 646 /* If a speed has been specified, use it 647 * if not, use "smart" default (defaults.h) 648 */ 649 if (*speed) { 650 pppd_argv[an++] = speed; 651 } else { 652 pppd_argv[an++] = PPP_SPEED_DEFAULT; 653 } 654 655 if (pptpctrl_debug) { 656 if (*pppaddrs[0]) 657 syslog(LOG_DEBUG, "CTRL (PPPD Launcher): local address = %s", pppaddrs[0]); 658 if (*pppaddrs[1]) 659 syslog(LOG_DEBUG, "CTRL (PPPD Launcher): remote address = %s", pppaddrs[1]); 660 } 661 662 if (*pppaddrs[0] || *pppaddrs[1]) { 663 char pppInterfaceIPs[33]; 664 sprintf(pppInterfaceIPs, "%s:%s", pppaddrs[0], pppaddrs[1]); 665 pppd_argv[an++] = pppInterfaceIPs; 666 } 667#endif 668 669 if (!noipparam) { 670 pppd_argv[an++] = "ipparam"; 671 pppd_argv[an++] = inet_ntoa(inetaddrs[1]); 672 } 673 674 if (pptp_logwtmp) { 675 pppd_argv[an++] = "plugin"; 676 pppd_argv[an++] = "/usr/lib/pptpd/pptpd-logwtmp.so"; 677 pppd_argv[an++] = "pptpd-original-ip"; 678 pppd_argv[an++] = inet_ntoa(inetaddrs[1]); 679 } 680 681 pppd_argv[an++] = "plugin"; 682 pppd_argv[an++] = "pptp.so"; 683 pppd_argv[an++] = "pptp_client"; 684 strcpy(tmp,inet_ntoa(inetaddrs[1])); 685 pppd_argv[an++] = strdup(tmp); 686 pppd_argv[an++] = "pptp_sock"; 687 sprintf(tmp,"%u",pptp_sock); 688 pppd_argv[an++] = strdup(tmp); 689 pppd_argv[an++] = "nodetach"; 690 691 /* argv arrays must always be NULL terminated */ 692 pppd_argv[an++] = NULL; 693 /* make sure SIGCHLD is unblocked, pppd does not expect it */ 694 sigfillset(&sigs); 695 sigprocmask(SIG_UNBLOCK, &sigs, NULL); 696 /* run pppd now */ 697 execvp(pppd_argv[0], pppd_argv); 698 /* execvp() failed */ 699 syslog(LOG_ERR, 700 "CTRL (PPPD Launcher): Failed to launch PPP daemon. %s", 701 strerror(errno)); 702} 703