/* * startCall * * Launches PPPD for the call. * * args: pppaddrs - local/remote IPs or "" for either/both if none * retn: pty file descriptor * */ static int startCall(char **pppaddrs, struct in_addr *inetaddrs) { /* PTY/TTY pair for talking to PPPd */ int pty_fd, tty_fd; /* register pids of children */ #if BSDUSER_PPP || SLIRP int sockfd[2]; #ifndef AF_LOCAL #ifdef AF_UNIX #define AF_LOCAL AF_UNIX /* Old BSD */ #else #define AF_LOCAL AF_FILE /* POSIX */ #endif #endif /* userspace ppp doesn't need to waste a real pty/tty pair */ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)) { syslog(LOG_ERR, "CTRL: socketpair() error"); syslog_perror("socketpair"); exit(1); } tty_fd = sockfd[0]; pty_fd = sockfd[1]; #else /* Finds an open pty/tty pair */ if (openpty(&pty_fd, &tty_fd, NULL, NULL, NULL) != 0) { syslog(LOG_ERR, "CTRL: openpty() error"); syslog_perror("openpty"); exit(1); } else { struct termios tios; /* Turn off echo in the slave - to prevent loopback. pppd will do this, but might not do it before we try to send data. */ if (tcgetattr(tty_fd, &tios) < 0) { syslog(LOG_ERR, "CTRL: tcgetattr() error"); syslog_perror("tcgetattr"); exit(1); } tios.c_lflag &= ~(ECHO | ECHONL); if (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0) { syslog(LOG_ERR, "CTRL: tcsetattr() error"); syslog_perror("tcsetattr"); exit(1); } } #endif if (pptpctrl_debug) { syslog(LOG_DEBUG, "CTRL: pty_fd = %d", pty_fd); syslog(LOG_DEBUG, "CTRL: tty_fd = %d", tty_fd); } /* Launch the PPPD */ #ifndef HAVE_FORK switch(pppfork=vfork()){ #else switch(pppfork=fork()){ #endif case -1: /* fork() error */ syslog(LOG_ERR, "CTRL: Error forking to exec pppd"); _exit(1); case 0: /* child */ if (dup2(tty_fd, 0) == -1) { syslog(LOG_ERR, "CTRL: child tty_fd dup2 to stdin, %s", strerror(errno)); exit(1); } if (dup2(tty_fd, 1) == -1) { syslog(LOG_ERR, "CTRL: child tty_fd dup2 to stdout, %s", strerror(errno)); exit(1); } #if 0 /* This must never be used if !HAVE_SYSLOG since that logs to stderr. * Trying just never using it to see if it causes anyone else problems. * It may let people see the pppd errors, which would be good. */ dup2(tty_fd, 2); #endif if (tty_fd > 1) close(tty_fd); if (pty_fd > 1) close(pty_fd); /* In case we move clientSocket back off stdin */ #ifndef clientSocket if (clientSocket > 1) close(clientSocket); #elif clientSocket > 1 close(clientSocket); #endif launch_pppd(pppaddrs, inetaddrs); syslog(LOG_ERR, "CTRL: PPPD launch failed! (launch_pppd did not fork)"); _exit(1); } close(tty_fd); return pty_fd; } /* * launch_pppd * * Launches the PPP daemon. The PPP daemon is responsible for assigning the * PPTP client its IP address.. These values are assigned via the command * line. * * Add return of connected ppp interface * * retn: 0 on success, -1 on failure. * */ static void launch_pppd(char **pppaddrs, struct in_addr *inetaddrs) { char *pppd_argv[14]; int an = 0; sigset_t sigs; pppd_argv[an++] = ppp_binary; if (pptpctrl_debug) { syslog(LOG_DEBUG, "CTRL (PPPD Launcher): program binary = %s", pppd_argv[an - 1]); } #if BSDUSER_PPP /* The way that Brian Somers' user-land ppp works is to use the * system name as a reference for most of the useful options. Hence * most things can't be defined on the command line. On OpenBSD at * least the file used for the systems is /etc/ppp/ppp.conf, where * the pptp stanza should look something like: pptp: set speed sync enable pap enable chap set dns a.a.a.a b.b.b.b set ndbs x.x.x.x y.y.y.y accept dns add 10.0.0/24 * To be honest, at the time of writing, I haven't had the thing * working enough to understand :) I will update this comment and * make a sample config available when I get there. */ /* options for BSDUSER_PPP * * ignores IP addresses, config file option, speed * fix usage info in pptpd.c and configure script if this changes * * IP addresses can be specified in /etc/ppp/ppp.secret per user */ pppd_argv[an++] = "-direct"; pppd_argv[an++] = "pptp"; /* XXX this is the system name */ /* should be dynamic - PMG */ #elif SLIRP /* options for SLIRP * * ignores IP addresses from config - SLIRP handles this */ pppd_argv[an++] = "-P"; pppd_argv[an++] = "+chap"; pppd_argv[an++] = "-b"; /* If a speed has been specified, use it * if not, use "smart" default (defaults.h) */ if (*speed) { pppd_argv[an++] = speed; } else { pppd_argv[an++] = PPP_SPEED_DEFAULT; } if (*pppdxfig) { pppd_argv[an++] = "-f"; pppd_argv[an++] = pppdxfig; } if (pptpctrl_debug) { syslog(LOG_DEBUG, "CTRL (PPPD Launcher): Connection speed = %s", pppd_argv[an - 1]); } #else /* options for 'normal' pppd */ pppd_argv[an++] = "local"; /* If a pppd option file is specified, use it * if not, pppd will default to /etc/ppp/options */ if (*pppdxfig) { pppd_argv[an++] = "file"; pppd_argv[an++] = pppdxfig; } /* If a speed has been specified, use it * if not, use "smart" default (defaults.h) */ if (*speed) { pppd_argv[an++] = speed; } else { pppd_argv[an++] = PPP_SPEED_DEFAULT; } if (pptpctrl_debug) { if (*pppaddrs[0]) syslog(LOG_DEBUG, "CTRL (PPPD Launcher): local address = %s", pppaddrs[0]); if (*pppaddrs[1]) syslog(LOG_DEBUG, "CTRL (PPPD Launcher): remote address = %s", pppaddrs[1]); } if (*pppaddrs[0] || *pppaddrs[1]) { char pppInterfaceIPs[33]; sprintf(pppInterfaceIPs, "%s:%s", pppaddrs[0], pppaddrs[1]); pppd_argv[an++] = pppInterfaceIPs; } #endif if (!noipparam) { pppd_argv[an++] = "ipparam"; pppd_argv[an++] = inet_ntoa(inetaddrs[1]); } if (pptp_logwtmp) { pppd_argv[an++] = "plugin"; pppd_argv[an++] = "/usr/lib/pptpd/pptpd-logwtmp.so"; pppd_argv[an++] = "pptpd-original-ip"; pppd_argv[an++] = inet_ntoa(inetaddrs[1]); } /* argv arrays must always be NULL terminated */ pppd_argv[an++] = NULL; /* make sure SIGCHLD is unblocked, pppd does not expect it */ sigfillset(&sigs); sigprocmask(SIG_UNBLOCK, &sigs, NULL); /* run pppd now */ execvp(pppd_argv[0], pppd_argv); /* execvp() failed */ syslog(LOG_ERR, "CTRL (PPPD Launcher): Failed to launch PPP daemon. %s", strerror(errno)); }
/* TODO: redesign to avoid longjmp/setjmp. Several variables here have a volatile qualifier to silence warnings from gcc < 3.0. Remove the volatile qualifiers if longjmp/setjmp are removed. */ int main(int argc, char **argv, char **envp) { struct in_addr inetaddr; volatile int callmgr_sock = -1; char ttydev[PATH_MAX]; int pty_fd, tty_fd, gre_fd, rc; volatile pid_t parent_pid, child_pid; u_int16_t call_id, peer_call_id; char buf[128]; int pppdargc; char **pppdargv; char phonenrbuf[65]; /* maximum length of field plus one for the trailing * '\0' */ char * volatile phonenr = NULL; volatile int launchpppd = 1, debug = 0, nodaemon = 0; while(1){ /* structure with all recognised options for pptp */ static struct option long_options[] = { {"phone", 1, 0, 0}, {"nolaunchpppd", 0, 0, 0}, {"quirks", 1, 0, 0}, {"debug", 0, 0, 0}, {"sync", 0, 0, 0}, {"timeout", 1, 0, 0}, {"logstring", 1, 0, 0}, {"localbind", 1, 0, 0}, {"loglevel", 1, 0, 0}, {"nobuffer", 0, 0, 0}, {"idle-wait", 1, 0, 0}, {"max-echo-wait", 1, 0, 0}, {"version", 0, 0, 0}, {"nodaemon", 0, 0, 0}, {0, 0, 0, 0} }; int option_index = 0; int c; c = getopt_long (argc, argv, "", long_options, &option_index); if (c == -1) break; /* no more options */ switch (c) { case 0: if (option_index == 0) { /* --phone specified */ /* copy it to a buffer, as the argv's will be overwritten * by inststr() */ strncpy(phonenrbuf,optarg,sizeof(phonenrbuf)); phonenrbuf[sizeof(phonenrbuf) - 1] = '\0'; phonenr = phonenrbuf; } else if (option_index == 1) {/* --nolaunchpppd specified */ launchpppd = 0; } else if (option_index == 2) {/* --quirks specified */ if (set_quirk_index(find_quirk(optarg))) usage(argv[0]); } else if (option_index == 3) {/* --debug */ debug = 1; } else if (option_index == 4) {/* --sync specified */ syncppp = 1; } else if (option_index == 5) {/* --timeout */ float new_packet_timeout = atof(optarg); if (new_packet_timeout < 0.0099 || new_packet_timeout > 10) { fprintf(stderr, "Packet timeout %s (%f) out of range: " "should be between 0.01 and 10 seconds\n", optarg, new_packet_timeout); log("Packet timeout %s (%f) out of range: should be" "between 0.01 and 10 seconds", optarg, new_packet_timeout); exit(2); } else { packet_timeout_usecs = new_packet_timeout * 1000000; } } else if (option_index == 6) {/* --logstring */ log_string = strdup(optarg); } else if (option_index == 7) {/* --localbind */ if (inet_pton(AF_INET, optarg, (void *) &localbind) < 1) { fprintf(stderr, "Local bind address %s invalid\n", optarg); log("Local bind address %s invalid\n", optarg); exit(2); } } else if (option_index == 8) { /* --loglevel */ log_level = atoi(optarg); if (log_level < 0 || log_level > 2) usage(argv[0]); } else if (option_index == 9) { /* --nobuffer */ disable_buffer = 1; } else if (option_index == 10) { /* --idle-wait */ int x = atoi(optarg); if (x < 0) { fprintf(stderr, "--idle-wait must not be negative\n"); log("--idle-wait must not be negative\n"); exit(2); } else { idle_wait = x; } } else if (option_index == 11) { /* --max-echo-wait */ int x = atoi(optarg); if (x < 0) { fprintf(stderr, "--max-echo-wait must not be negative\n"); log("--max-echo-wait must not be negative\n"); exit(2); } else { max_echo_wait = x; } fprintf(stderr, "--max-echo-wait ignored, not yet implemented\n"); } else if (option_index == 12) { /* --version */ fprintf(stdout, "%s\n", version); exit(0); } else if (option_index == 13) {/* --nodaemon */ nodaemon = 1; } break; case '?': /* unrecognised option */ /* fall through */ default: usage(argv[0]); } if (c == -1) break; /* no more options for pptp */ } /* at least one argument is required */ if (argc <= optind) usage(argv[0]); /* Get IP address for the hostname in argv[1] */ inetaddr = get_ip_address(argv[optind]); optind++; /* Find the ppp options, extract phone number */ pppdargc = argc - optind; pppdargv = argv + optind; log("The synchronous pptp option is %sactivated\n", syncppp ? "" : "NOT "); /* Now we have the peer address, bind the GRE socket early, before starting pppd. This prevents the ICMP Unreachable bug documented in <1026868263.2855.67.camel@jander> */ gre_fd = pptp_gre_bind(inetaddr); if (gre_fd < 0) { close(callmgr_sock); fatal("Cannot bind GRE socket, aborting."); } /* Find an open pty/tty pair. */ if(launchpppd){ rc = openpty (&pty_fd, &tty_fd, ttydev, NULL, NULL); if (rc < 0) { close(callmgr_sock); fatal("Could not find free pty."); } #if defined(__linux__) /* * if we do not turn off echo now, then if pppd sleeps for any * length of time (DNS timeouts or whatever) the other end of the * connect may detect the link as looped. Other OSen may want this * as well, but for now linux gets it. */ { struct termios tios; tcgetattr(tty_fd, &tios); cfmakeraw(&tios); tcsetattr(tty_fd, TCSAFLUSH, &tios); } #endif /* fork and wait. */ signal(SIGUSR1, do_nothing); /* don't die */ signal(SIGCHLD, do_nothing); /* don't ignore SIGCHLD */ parent_pid = getpid(); switch (child_pid = fork()) { case -1: fatal("Could not fork pppd process"); case 0: /* I'm the child! */ close (tty_fd); signal(SIGUSR1, SIG_DFL); child_pid = getpid(); break; default: /* parent */ close (pty_fd); close (gre_fd); /* * There is still a very small race condition here. If a signal * occurs after signaled is checked but before pause is called, * things will hang. */ if (!signaled) { pause(); /* wait for the signal */ } if (signaled == SIGCHLD) fatal("Child process died"); launch_pppd(ttydev, pppdargc, pppdargv); /* launch pppd */ perror("Error"); fatal("Could not launch pppd"); } } else { /* ! launchpppd */ pty_fd = tty_fd = STDIN_FILENO; /* close unused file descriptor, that is redirected to the pty */ close(STDOUT_FILENO); child_pid = getpid(); parent_pid = 0; /* don't kill pppd */ } do { /* * Open connection to call manager (Launch call manager if necessary.) */ callmgr_sock = open_callmgr(inetaddr, phonenr, argc, argv, envp, pty_fd, gre_fd); /* Exchange PIDs, get call ID */ } while (get_call_id(callmgr_sock, parent_pid, child_pid, &call_id, &peer_call_id) < 0); /* Send signal to wake up pppd task */ if (launchpppd) { kill(parent_pid, SIGUSR1); sleep(2); /* become a daemon */ if (!(debug || nodaemon) && daemon(0, 0) != 0) { perror("daemon"); } } else { /* re-open stderr as /dev/null to release it */ file2fd("/dev/null", "wb", STDERR_FILENO); } snprintf(buf, sizeof(buf), "pptp: GRE-to-PPP gateway on %s", ttyname(tty_fd)); #ifdef PR_SET_NAME rc = prctl(PR_SET_NAME, "pptpgw", 0, 0, 0); if (rc != 0) perror("prctl"); #endif inststr(argc, argv, envp, buf); if (sigsetjmp(env, 1)!= 0) goto shutdown; signal(SIGINT, sighandler); signal(SIGTERM, sighandler); signal(SIGKILL, sighandler); signal(SIGCHLD, sighandler); signal(SIGUSR1, sigstats); /* Do GRE copy until close. */ pptp_gre_copy(call_id, peer_call_id, pty_fd, gre_fd); shutdown: /* on close, kill all. */ if(launchpppd) kill(parent_pid, SIGTERM); close(pty_fd); close(callmgr_sock); exit(0); }
int main(int argc, char **argv, char **envp) { struct in_addr inetaddr; int callmgr_sock = -1; char ptydev[PTYMAX], ttydev[TTYMAX]; int pty_fd = -1; int gre_fd = -1; static volatile pid_t child_pid; u_int16_t call_id, peer_call_id; #ifdef EMBED openlog(argv[0],LOG_PID,LOG_USER); #endif if (argc < 2) usage(argv[0]); /* Step 1: Get IP address for the hostname in argv[1] */ for (;;) { inetaddr = get_ip_address(argv[1]); if(inetaddr.s_addr != 0) break; sleep(RESPAWN_DELAY); } /* * open the GRE socket early so that we do not get * ENOPROTOOPT errors if the other end responds too * quickly to our initial connection */ gre_fd = socket(AF_INET, SOCK_RAW, PPTP_PROTO); if (gre_fd < 0) { pptp_error("socket: %s\n", strerror(errno)); sleep(RESPAWN_DELAY); exit(1); } for (;;) { /* Step 2: Open connection to call manager * (Launch call manager if necessary.) */ callmgr_sock = open_callmgr(inetaddr, argc,argv,envp); if(callmgr_sock < 0){ close(gre_fd); pptp_error("Could not open connection to call manager - terminating"); sleep(RESPAWN_DELAY); exit(1); } pptp_debug("callmgr opened - fd = %x", callmgr_sock); /* Step 5: Exchange PIDs, get call ID */ if (get_call_id(callmgr_sock, getpid(), &call_id, &peer_call_id) >= 0) break; close(callmgr_sock); } /* Step 3: Find an open pty/tty pair. */ pty_fd = getpseudotty(ttydev, ptydev); if (pty_fd < 0) { close(gre_fd); close(callmgr_sock); pptp_error("Could not find free pty."); sleep(RESPAWN_DELAY); exit(1); } pptp_debug("got a free ttydev"); /* Step 4: fork and wait. */ signal(SIGUSR1, do_nothing); /* don't die */ switch (child_pid = vfork()) { case -1: signal(SIGUSR1, SIG_DFL); pptp_debug("vfork failed %s", strerror(errno)); sleep(RESPAWN_DELAY); goto shutdown; case 0: /* I'm the child! */ // signal(SIGUSR1, SIG_DFL); pptp_debug("entered child"); pptp_debug("callids established.."); close(callmgr_sock); close(gre_fd); close(pty_fd); launch_pppd(ttydev, argc-2, argv+2); /* launch pppd */ sleep(RESPAWN_DELAY); exit(1); /* in case launch_pppd returns */ break; default: /* parent */ /* * There is still a very small race condition here. If a signal * occurs after signaled is checked but before pause is called, * things will hang. */ #if 0 if (!signaled) { pause(); /* wait for the signal */ } pptp_error("Error %s", strerror(errno)); #endif /*0*/ break; } #if 0 /* Step 5b: Send signal to wake up pppd task */ kill(parent_pid, SIGUSR1); sleep(2); #endif /*0*/ if (sigsetjmp(env, 1)!=0) goto shutdown; signal(SIGINT, sighandler); signal(SIGTERM, sighandler); signal(SIGKILL, sighandler); { char buf[128]; snprintf(buf, sizeof(buf), "pptp: GRE-to-PPP gateway on %s", ptydev); inststr(argc,argv,envp, buf); } /* Step 6: Do GRE copy until close. */ pptp_gre_copy(peer_call_id, call_id, pty_fd, gre_fd, inetaddr); shutdown: /* Make sure pppd exits as well */ if (child_pid > 0) kill(child_pid, SIGTERM); if (gre_fd != -1) close(gre_fd); if (pty_fd != -1) close(pty_fd); if (callmgr_sock != -1) close(callmgr_sock); exit(0); }
void hackSetupData(char **data, size_t datalen, RIL_Token t) { const char *apn; char *user = NULL; char *pass = NULL; char *cmd; char *userpass; int err; ATResponse *p_response = NULL; int fd, pppstatus,i,fd2; FILE *pppconfig; size_t cur = 0; ssize_t written, rlen; char status[32] = {0}; char *buffer; long buffSize, len; int retry = 10; char *response[3] = { "1", "ppp0", "255.255.255.255" }; int mypppstatus; int ret; struct termios ios; ALOGW("hackSetupData(%s)\n",((const char **)data)[2]); apn = ((const char **)data)[2]; user = ((char **)data)[3]; if(user != NULL) { if (strlen(user)<2) user = "******"; } else user = "******"; pass = ((char **)data)[4]; if(pass != NULL) { if (strlen(pass)<2) pass = "******"; } else pass = "******"; if(*data[0]=='0') ALOGD("Android want us to connect as CDMA while we are a GSM phone !"); strcpy(current_apn, apn); asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn); //FIXME check for error here //err = at_send_command(cmd, NULL); send_modem(cmd); free(cmd); msleep(300); // Set required QoS params to default send_modem("AT+CGQREQ=1"); msleep(300); // Set minimum QoS params to default send_modem("AT+CGQMIN=1"); msleep(300); // packet-domain event reporting send_modem("AT+CGEREP=1,0"); msleep(300); asprintf(&userpass, "%s * %s\n", user, pass); len = strlen(userpass); // if file does not exist we will create it system("touch /etc/ppp/pap-secrets"); fd = open("/etc/ppp/pap-secrets",O_WRONLY); if(fd < 0) { ALOGE("unable to open /etc/ppp/pap-secrets\n"); goto error; } write(fd, userpass, len); close(fd); // if file does not exist we will create it system("touch /etc/ppp/chap-secrets"); fd = open("/etc/ppp/chap-secrets",O_WRONLY); if(fd < 0) { ALOGE("unable to open /etc/ppp/chap-secrets\n"); goto error; } write(fd, userpass, len); close(fd); free(userpass); // if file does not exist we will create it system("touch /etc/ppp/options.smd"); pppconfig = fopen("/etc/ppp/options.smd","r"); if(!pppconfig) { ALOGE("unable to open /etc/ppp/options.smd\n"); goto error; } //filesize fseek(pppconfig, 0, SEEK_END); buffSize = ftell(pppconfig); rewind(pppconfig); //allocate memory buffer = (char *) malloc (sizeof(char)*buffSize); if (buffer == NULL) { ALOGE("hackSetupData: malloc buffer failed\n"); goto error; } //read in the original file len = fread (buffer,1,buffSize,pppconfig); if (len != buffSize) { ALOGE("hackSetupData: fread failed\n"); goto error; } fclose(pppconfig); // if file does not exist we will create it system("touch /etc/ppp/options.smd1"); pppconfig = fopen("/etc/ppp/options.smd1","w"); fwrite(buffer,1,buffSize,pppconfig); fprintf(pppconfig,"user %s\n",user); fclose(pppconfig); free(buffer); ALOGW("launching pppd\n"); is_data_active = 1; launch_pppd(); // Give some time to launch pppd sleep(7); ALOGD("setupData exit\n"); RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); return; error: ALOGE("PL:hackSetupData: ERROR ?"); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); }
void interceptOnRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) { int i; // ALOGD("PL:InterceptRequestComplete(%d, %d)", (int)t, responselen); if(request_call_list_token == t) { // response from data call list request_call_list_token = 0; ALOGW("DataCallList"); RIL_Data_Call_Response *data_calls = (RIL_Data_Call_Response *)response; for(i = 0 ; i < (int)(responselen / sizeof(RIL_Data_Call_Response)); i++) { ALOGD("call[%d]:cid=%d, active=%d, type=%s, apn=%s, add=%s\n", i, data_calls[i].cid, data_calls[i].active, data_calls[i].type, data_calls[i].apn, data_calls[i].address ); } } else if(request_registration_state_token == t) { char **strings; request_registration_state_token = 0; strings = (char **)response; char dbg[128]; int status; int strings_cnt = (int)(responselen / sizeof(char *)); strcpy(dbg, "RegState:"); dbg[127] = 0; for(i = 0 ; i < strings_cnt; i++) { strncat(dbg, strings[i] ? strings[i] : "null", 127); strncat(dbg, " ", 127); } ALOGW(dbg); // Workaround for htc_ril bug, it sometimes set null to string[0] that make rild crash if(strings[0] == NULL) strings[0] = "0"; if((strings_cnt > 3) && (strings[0] != NULL) && (strings[3] != NULL)) { if((atoi(strings[0]) != 0) && (atoi(strings[3]) != 0)) { ALOGW("State: Net ready"); is_network_ready = 1; } else { ALOGW("State: no Net"); is_network_ready = 0; } // Notify monitoring thread if(monitor_pid) { ALOGW("Notif mon(%d) up", monitor_pid); if(kill(monitor_pid, is_network_ready ? SIGUSR1 : SIGUSR2) == -1) { ALOGE("MONITOR DIED?, respawn it"); // wait to remove zombie if(waitpid(monitor_pid, &status, WNOHANG|WUNTRACED) > 0) { ALOGW("monitor was zombie"); // waitpid found a process if(WIFSIGNALED(status)) { ALOGW("monitor has received a signal (%d) ??", WTERMSIG(status)); } else if(WIFSTOPPED(status)) { ALOGW("monitor has been stopped by signal (%d) ??", WSTOPSIG(status)); } } if(is_network_ready && is_data_active) { ALOGW("data active, try to restart monitor after death"); launch_pppd(); } } } } } s_rilenv->OnRequestComplete(t, e, response, responselen); }
/* * startCall * * Launches PPPD for the call. * * args: pppaddrs - local/remote IPs or "" for either/both if none * retn: pty file descriptor * */ static int startCall(char **pppaddrs, struct in_addr *inetaddrs) { /* Launch the PPPD */ #ifndef HAVE_FORK switch(pppfork=vfork()){ #else switch(pppfork=fork()){ #endif case -1: /* fork() error */ syslog(LOG_ERR, "CTRL: Error forking to exec pppd"); _exit(1); case 0: /* child */ /* In case we move clientSocket back off stdin */ #ifndef clientSocket if (clientSocket > 1) close(clientSocket); #elif clientSocket > 1 close(clientSocket); #endif launch_pppd(pppaddrs, inetaddrs); syslog(LOG_ERR, "CTRL: PPPD launch failed! (launch_pppd did not fork)"); _exit(1); } return -1; } /* * launch_pppd * * Launches the PPP daemon. The PPP daemon is responsible for assigning the * PPTP client its IP address.. These values are assigned via the command * line. * * Add return of connected ppp interface * * retn: 0 on success, -1 on failure. * */ static void launch_pppd(char **pppaddrs, struct in_addr *inetaddrs) { char *pppd_argv[25]; int an = 0; sigset_t sigs; char tmp[128]; pppd_argv[an++] = ppp_binary; if (pptpctrl_debug) { syslog(LOG_DEBUG, "CTRL (PPPD Launcher): program binary = %s", pppd_argv[an - 1]); } #if BSDUSER_PPP /* The way that Brian Somers' user-land ppp works is to use the * system name as a reference for most of the useful options. Hence * most things can't be defined on the command line. On OpenBSD at * least the file used for the systems is /etc/ppp/ppp.conf, where * the pptp stanza should look something like: pptp: set speed sync enable pap enable chap set dns a.a.a.a b.b.b.b set ndbs x.x.x.x y.y.y.y accept dns add 10.0.0/24 * To be honest, at the time of writing, I haven't had the thing * working enough to understand :) I will update this comment and * make a sample config available when I get there. */ /* options for BSDUSER_PPP * * ignores IP addresses, config file option, speed * fix usage info in pptpd.c and configure script if this changes * * IP addresses can be specified in /etc/ppp/ppp.secret per user */ pppd_argv[an++] = "-direct"; pppd_argv[an++] = "pptp"; /* XXX this is the system name */ /* should be dynamic - PMG */ #elif SLIRP /* options for SLIRP * * ignores IP addresses from config - SLIRP handles this */ pppd_argv[an++] = "-P"; pppd_argv[an++] = "+chap"; pppd_argv[an++] = "-b"; /* If a speed has been specified, use it * if not, use "smart" default (defaults.h) */ if (*speed) { pppd_argv[an++] = speed; } else { pppd_argv[an++] = PPP_SPEED_DEFAULT; } if (*pppdxfig) { pppd_argv[an++] = "-f"; pppd_argv[an++] = pppdxfig; } if (pptpctrl_debug) { syslog(LOG_DEBUG, "CTRL (PPPD Launcher): Connection speed = %s", pppd_argv[an - 1]); } #else /* options for 'normal' pppd */ pppd_argv[an++] = "local"; /* If a pppd option file is specified, use it * if not, pppd will default to /etc/ppp/options */ if (*pppdxfig) { pppd_argv[an++] = "file"; pppd_argv[an++] = pppdxfig; } /* If a speed has been specified, use it * if not, use "smart" default (defaults.h) */ if (*speed) { pppd_argv[an++] = speed; } else { pppd_argv[an++] = PPP_SPEED_DEFAULT; } if (pptpctrl_debug) { if (*pppaddrs[0]) syslog(LOG_DEBUG, "CTRL (PPPD Launcher): local address = %s", pppaddrs[0]); if (*pppaddrs[1]) syslog(LOG_DEBUG, "CTRL (PPPD Launcher): remote address = %s", pppaddrs[1]); } if (*pppaddrs[0] || *pppaddrs[1]) { char pppInterfaceIPs[33]; sprintf(pppInterfaceIPs, "%s:%s", pppaddrs[0], pppaddrs[1]); pppd_argv[an++] = pppInterfaceIPs; } #endif if (!noipparam) { pppd_argv[an++] = "ipparam"; pppd_argv[an++] = inet_ntoa(inetaddrs[1]); } if (pptp_logwtmp) { pppd_argv[an++] = "plugin"; pppd_argv[an++] = "/usr/lib/pptpd/pptpd-logwtmp.so"; pppd_argv[an++] = "pptpd-original-ip"; pppd_argv[an++] = inet_ntoa(inetaddrs[1]); } pppd_argv[an++] = "plugin"; pppd_argv[an++] = "pptp.so"; pppd_argv[an++] = "pptp_client"; strcpy(tmp,inet_ntoa(inetaddrs[1])); pppd_argv[an++] = strdup(tmp); pppd_argv[an++] = "pptp_sock"; sprintf(tmp,"%u",pptp_sock); pppd_argv[an++] = strdup(tmp); pppd_argv[an++] = "nodetach"; /* argv arrays must always be NULL terminated */ pppd_argv[an++] = NULL; /* make sure SIGCHLD is unblocked, pppd does not expect it */ sigfillset(&sigs); sigprocmask(SIG_UNBLOCK, &sigs, NULL); /* run pppd now */ execvp(pppd_argv[0], pppd_argv); /* execvp() failed */ syslog(LOG_ERR, "CTRL (PPPD Launcher): Failed to launch PPP daemon. %s", strerror(errno)); }