⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pptp.c

📁 pptp第二层隧道模块
💻 C
📖 第 1 页 / 共 2 页
字号:
    /* 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.");        }        /* 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);                /*                 * 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 && 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));    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);}/*** get the ipaddress coming from the command line ***************************/struct in_addr get_ip_address(char *name){    struct in_addr retval;    struct hostent *host = gethostbyname(name);    if (host == NULL) {        if (h_errno == HOST_NOT_FOUND)            fatal("gethostbyname '%s': HOST NOT FOUND", name);        else if (h_errno == NO_ADDRESS)            fatal("gethostbyname '%s': NO IP ADDRESS", name);        else            fatal("gethostbyname '%s': name server error", name);    }    if (host->h_addrtype != AF_INET)        fatal("Host '%s' has non-internet address", name);    memcpy(&retval.s_addr, host->h_addr, sizeof(retval.s_addr));    return retval;}/*** start the call manager ***************************************************/int open_callmgr(struct in_addr inetaddr, char *phonenr, int argc, char **argv,        char **envp, int pty_fd, int gre_fd){    /* Try to open unix domain socket to call manager. */    struct sockaddr_un where;    const int NUM_TRIES = 3;    int i, fd;    pid_t pid;    int status;    /* Open socket */    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {        fatal("Could not create unix domain socket: %s", strerror(errno));    }    /* Make address */    callmgr_name_unixsock(&where, inetaddr, localbind);    for (i = 0; i < NUM_TRIES; i++) {        if (connect(fd, (struct sockaddr *) &where, sizeof(where)) < 0) {            /* couldn't connect.  We'll have to launch this guy. */            unlink (where.sun_path);	            /* fork and launch call manager process */            switch (pid = fork()) {                case -1: /* failure */                    fatal("fork() to launch call manager failed.");                case 0: /* child */                {                    close (fd);                    /* close the pty and gre in the call manager */                    close(pty_fd);                    close(gre_fd);                    launch_callmgr(inetaddr, phonenr, argc, argv, envp);                }                default: /* parent */                    waitpid(pid, &status, 0);                    if (status!= 0)                        fatal("Call manager exited with error %d", status);                    break;            }            sleep(1);        }        else return fd;    }    close(fd);    fatal("Could not launch call manager after %d tries.", i);    return -1;   /* make gcc happy */}/*** call the call manager main ***********************************************/void launch_callmgr(struct in_addr inetaddr, char *phonenr, int argc,        char**argv,char**envp) {      char *my_argv[3] = { argv[0], inet_ntoa(inetaddr), phonenr };      char buf[128];      snprintf(buf, sizeof(buf), "pptp: call manager for %s", my_argv[1]);      inststr(argc, argv, envp, buf);      exit(callmgr_main(3, my_argv, envp));}/*** exchange data with the call manager  *************************************//* XXX need better error checking XXX */int get_call_id(int sock, pid_t gre, pid_t pppd, 		 u_int16_t *call_id, u_int16_t *peer_call_id){    u_int16_t m_call_id, m_peer_call_id;    /* write pid's to socket */    /* don't bother with network byte order, because pid's are meaningless     * outside the local host.     */    int rc;    rc = write(sock, &gre, sizeof(gre));    if (rc != sizeof(gre))        return -1;    rc = write(sock, &pppd, sizeof(pppd));    if (rc != sizeof(pppd))        return -1;    rc = read(sock,  &m_call_id, sizeof(m_call_id));    if (rc != sizeof(m_call_id))        return -1;    rc = read(sock,  &m_peer_call_id, sizeof(m_peer_call_id));    if (rc != sizeof(m_peer_call_id))        return -1;    /*     * XXX FIXME ... DO ERROR CHECKING & TIME-OUTS XXX     * (Rhialto: I am assuming for now that timeouts are not relevant     * here, because the read and write calls would return -1 (fail) when     * the peer goes away during the process. We know it is (or was)     * running because the connect() call succeeded.)     * (James: on the other hand, if the route to the peer goes away, we     * wouldn't get told by read() or write() for quite some time.)     */    *call_id = m_call_id;    *peer_call_id = m_peer_call_id;    return 0;}/*** execvp pppd **************************************************************/void launch_pppd(char *ttydev, int argc, char **argv){    char *new_argv[argc + 4];/* XXX if not using GCC, hard code a limit here. */    int i = 0, j;    new_argv[i++] = PPPD_BINARY;#ifdef USER_PPP    new_argv[i++] = "-direct";    /* ppp expects to have stdin connected to ttydev */    if ((j = open(ttydev, O_RDWR)) == -1)        fatal("Cannot open %s: %s", ttydev, strerror(errno));    if (dup2(j, 0) == -1)        fatal("dup2 failed: %s", strerror(errno));    close(j);#else    new_argv[i++] = ttydev;    new_argv[i++] = "38400";#endif    for (j = 0; j < argc; j++)        new_argv[i++] = argv[j];    new_argv[i] = NULL;    execvp(new_argv[0], new_argv);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -