📄 pptp.c
字号:
/* pptp.c ... client shell to launch call managers, data handlers, and * the pppd from the command line. * C. Scott Ananian <cananian@alumni.princeton.edu> * * $Id: pptp.c,v 1.42 2004/11/09 21:56:46 quozl Exp $ */#include <sys/types.h>#include <sys/socket.h>#if defined(__FreeBSD__)#include <libutil.h>#elif defined(__NetBSD__) || defined(__OpenBSD__)#include <util.h>#elif defined(__APPLE__)#include <util.h>#else#include <pty.h>#endif#ifdef USER_PPP#include <fcntl.h>#endif#include <netinet/in.h>#include <arpa/inet.h>#include <sys/un.h>#include <netdb.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <syslog.h>#include <unistd.h>#include <signal.h>#include <setjmp.h>#include <errno.h>#include <sys/wait.h>#include <sys/param.h>#if defined(__APPLE__)#include "getopt.h"#else#include <getopt.h>#endif#include <limits.h>#include "config.h"#include "pptp_callmgr.h"#include "pptp_gre.h"#include "version.h"#include "inststr.h"#include "util.h"#include "pptp_quirks.h"#include "pqueue.h"#include "pptp_options.h"#ifndef PPPD_BINARY#define PPPD_BINARY "pppd"#endifint syncppp = 0;int log_level = 1;int disable_buffer = 0;struct in_addr get_ip_address(char *name);int open_callmgr(struct in_addr inetaddr, char *phonenr, int argc,char **argv,char **envp, int pty_fd, int gre_fd);void launch_callmgr(struct in_addr inetaddr, char *phonenr, int argc,char **argv,char **envp);int get_call_id(int sock, pid_t gre, pid_t pppd, u_int16_t *call_id, u_int16_t *peer_call_id);void launch_pppd(char *ttydev, int argc, char **argv);/*** print usage and exit *****************************************************/void usage(char *progname){ fprintf(stderr, "%s\n" "Usage:\n" " %s <hostname> [<pptp options>] [[--] <pppd options>]\n" "\n" "Or using pppd's pty option: \n" " pppd pty \"%s <hostname> --nolaunchpppd <pptp options>\"\n" "\n" "Available pptp options:\n" " --phone <number> Pass <number> to remote host as phone number\n" " --nolaunchpppd Do not launch pppd, for use as a pppd pty\n" " --quirks <quirk> Work around a buggy PPTP implementation\n" " Currently recognised values are BEZEQ_ISRAEL only\n" " --debug Run in foreground (for debugging with gdb)\n" " --sync Enable Synchronous HDLC (pppd must use it too)\n" " --timeout <secs> Time to wait for reordered packets (0.01 to 10 secs)\n" " --nobuffer Disable packet buffering and reordering completely\n" " --idle-wait Time to wait before sending echo request\n" " --max-echo-wait Time to wait before giving up on lack of reply\n" " --logstring <name> Use <name> instead of 'anon' in syslog messages\n" " --localbind <addr> Bind to specified IP address instead of wildcard\n" " --loglevel <level> Sets the debugging level (0=low, 1=default, 2=high)\n", version, progname, progname); log("%s called with wrong arguments, program not started.", progname); exit(1);}struct in_addr localbind = { INADDR_NONE };static int signaled = 0;/*** do nothing signal handler ************************************************/void do_nothing(int sig){ /* do nothing signal handler. Better than SIG_IGN. */ signaled = sig;}sigjmp_buf env;/*** signal handler ***********************************************************/void sighandler(int sig){ siglongjmp(env, 1);}/*** report statistics signal handler (SIGUSR1) *******************************/void sigstats(int sig){ syslog(LOG_NOTICE, "GRE statistics:\n");#define LOG(name,value) syslog(LOG_NOTICE, name "\n", stats .value) LOG("rx accepted = %d", rx_accepted); LOG("rx lost = %d", rx_lost); LOG("rx under win = %d", rx_underwin); LOG("rx over win = %d", rx_overwin); LOG("rx buffered = %d", rx_buffered); LOG("rx OS errors = %d", rx_errors); LOG("rx truncated = %d", rx_truncated); LOG("rx invalid = %d", rx_invalid); LOG("rx acks = %d", rx_acks); LOG("tx sent = %d", tx_sent); LOG("tx failed = %d", tx_failed); LOG("tx short = %d", tx_short); LOG("tx acks = %d", tx_acks); LOG("tx oversize = %d", tx_oversize); LOG("round trip = %d usecs", rtt);#undef LOG}/*** main *********************************************************************//* 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; 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}, {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"); } break; case '?': /* unrecognised option */ /* fall through */ default: usage(argv[0]); } if (c == -1) break; /* no more options for pptp */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -