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

📄 pptp_ctrl.c

📁 pptp第二层隧道模块
💻 C
📖 第 1 页 / 共 3 页
字号:
/* pptp_ctrl.c ... handle PPTP control connection. *                 C. Scott Ananian <cananian@alumni.princeton.edu> * * $Id: pptp_ctrl.c,v 1.31 2005/03/31 07:42:39 quozl Exp $ */#include <errno.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <stdlib.h>#include <assert.h>#include <signal.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include "pptp_msg.h"#include "pptp_ctrl.h"#include "pptp_options.h"#include "vector.h"#include "util.h"#include "pptp_quirks.h"/* BECAUSE OF SIGNAL LIMITATIONS, EACH PROCESS CAN ONLY MANAGE ONE * CONNECTION.  SO THIS 'PPTP_CONN' STRUCTURE IS A BIT MISLEADING. * WE'LL KEEP CONNECTION-SPECIFIC INFORMATION IN THERE ANYWAY (AS * OPPOSED TO USING GLOBAL VARIABLES), BUT BEWARE THAT THE ENTIRE * UNIX SIGNAL-HANDLING SEMANTICS WOULD HAVE TO CHANGE (OR THE * TIME-OUT CODE DRASTICALLY REWRITTEN) BEFORE YOU COULD DO A  * PPTP_CONN_OPEN MORE THAN ONCE PER PROCESS AND GET AWAY WITH IT. *//* This structure contains connection-specific information that the * signal handler needs to see.  Thus, it needs to be in a global * variable.  If you end up using pthreads or something (why not * just processes?), this would have to be placed in a thread-specific * data area, using pthread_get|set_specific, etc., so I've  * conveniently encapsulated it for you. * [linux threads will have to support thread-specific signals *  before this would work at all, which, as of this writing *  (linux-threads v0.6, linux kernel 2.1.72), it does not.] *//* Globals *//* control the number of times echo packets will be logged */static int nlogecho = 10;static struct thread_specific {    struct sigaction old_sigaction; /* evil signals */    PPTP_CONN * conn;} global;#define INITIAL_BUFSIZE 512 /* initial i/o buffer size. */struct PPTP_CONN {    int inet_sock;    /* Connection States */    enum {         CONN_IDLE, CONN_WAIT_CTL_REPLY, CONN_WAIT_STOP_REPLY, CONN_ESTABLISHED     } conn_state; /* on startup: CONN_IDLE */    /* Keep-alive states */    enum {         KA_NONE, KA_OUTSTANDING     } ka_state;  /* on startup: KA_NONE */    /* Keep-alive ID; monotonically increasing (watch wrap-around!) */    u_int32_t ka_id; /* on startup: 1 */    /* Other properties. */    u_int16_t version;    u_int16_t firmware_rev;    u_int8_t  hostname[64], vendor[64];    /* XXX these are only PNS properties, currently XXX */    /* Call assignment information. */    u_int16_t call_serial_number;    VECTOR *call;    void * closure;    pptp_conn_cb callback;    /******* IO buffers ******/    char * read_buffer, *write_buffer;    size_t read_alloc,   write_alloc;    size_t read_size,    write_size;};struct PPTP_CALL {    /* Call properties */    enum {        PPTP_CALL_PAC, PPTP_CALL_PNS    } call_type;    union {         enum pptp_pac_state {            PAC_IDLE, PAC_WAIT_REPLY, PAC_ESTABLISHED, PAC_WAIT_CS_ANS        } pac;        enum pptp_pns_state {            PNS_IDLE, PNS_WAIT_REPLY, PNS_ESTABLISHED, PNS_WAIT_DISCONNECT         } pns;    } state;    u_int16_t call_id, peer_call_id;    u_int16_t sernum;    u_int32_t speed;    /* For user data: */    pptp_call_cb callback;    void * closure;};/* PPTP error codes: ----------------------------------------------*//* (General Error Codes) */static const struct {    const char *name, *desc;} pptp_general_errors[] = {#define PPTP_GENERAL_ERROR_NONE                 0    { "(None)", "No general error" },#define PPTP_GENERAL_ERROR_NOT_CONNECTED        1    { "(Not-Connected)", "No control connection exists yet for this "        "PAC-PNS pair" },#define PPTP_GENERAL_ERROR_BAD_FORMAT           2    { "(Bad-Format)", "Length is wrong or Magic Cookie value is incorrect" },#define PPTP_GENERAL_ERROR_BAD_VALUE            3    { "(Bad-Value)", "One of the field values was out of range or "            "reserved field was non-zero" },#define PPTP_GENERAL_ERROR_NO_RESOURCE          4    { "(No-Resource)", "Insufficient resources to handle this command now" },#define PPTP_GENERAL_ERROR_BAD_CALLID           5    { "(Bad-Call ID)", "The Call ID is invalid in this context" },#define PPTP_GENERAL_ERROR_PAC_ERROR            6    { "(PAC-Error)", "A generic vendor-specific error occured in the PAC" }};#define  MAX_GENERAL_ERROR ( sizeof(pptp_general_errors) / \        sizeof(pptp_general_errors[0]) - 1)/* Outgoing Call Reply Result Codes */static const char *pptp_out_call_reply_result[] = {/* 0 */	"Unknown Result Code",/* 1 */	"Connected",/* 2 */	"General Error",/* 3 */	"No Carrier Detected",/* 4 */	"Busy Signal",/* 5 */	"No Dial Tone",/* 6 */	"Time Out",/* 7 */	"Not Accepted, Call is administratively prohibited" };#define MAX_OUT_CALL_REPLY_RESULT 7/* Call Disconnect Notify  Result Codes */static const char *pptp_call_disc_ntfy[] = {/* 0 */	"Unknown Result Code",/* 1 */	"Lost Carrier",/* 2 */	"General Error",/* 3 */	"Administrative Shutdown",/* 4 */	"(your) Request" };#define MAX_CALL_DISC_NTFY 4/* Call Disconnect Notify  Result Codes */static const char *pptp_start_ctrl_conn_rply[] = {/* 0 */	"Unknown Result Code",/* 1 */	"Successful Channel Establishment",/* 2 */	"General Error",/* 3 */	"Command Channel Already Exists",/* 4 */	"Requester is not Authorized" };#define MAX_START_CTRL_CONN_REPLY 4/* timing options */int idle_wait = PPTP_TIMEOUT;int max_echo_wait = PPTP_TIMEOUT;/* Local prototypes */static void pptp_reset_timer(void);static void pptp_handle_timer();/* Write/read as much as we can without blocking. */int pptp_write_some(PPTP_CONN * conn);int pptp_read_some(PPTP_CONN * conn);/* Make valid packets from read_buffer */int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size);/* Add packet to write_buffer */int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size);/* Dispatch packets (general) */int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size);/* Dispatch packets (control messages) */int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size);/* Set link info, for pptp servers that need it.   this is a noop, unless the user specified a quirk and   there's a set_link hook defined in the quirks table   for that quirk */void pptp_set_link(PPTP_CONN * conn, int peer_call_id);/*** log error information in control packets *********************************/static void ctrlp_error( int result, int error, int cause,        const char *result_text[], int max_result){    if( cause >= 0)        log("Result code is %d '%s'. Error code is %d, Cause code is %d",                result, result_text[result <= max_result ?  result : 0], error,                cause );    else        log("Reply result code is %d '%s'. Error code is %d",                result, result_text[result <= max_result ?  result : 0], error);    if ((error > 0) && (error <= MAX_GENERAL_ERROR)){        if( result != PPTP_RESULT_GENERAL_ERROR )            log("Result code is something else then \"general error\", "                    "so the following error is probably bogus.");        log("Error is '%s', Error message: '%s'",                pptp_general_errors[error].name,                pptp_general_errors[error].desc);    }}static const char *ctrl_msg_types[] = {         "invalid control message type",/*         (Control Connection Management) */         "Start-Control-Connection-Request",            /* 1 */         "Start-Control-Connection-Reply",              /* 2 */         "Stop-Control-Connection-Request",             /* 3 */         "Stop-Control-Connection-Reply",               /* 4 */         "Echo-Request",                                /* 5 */         "Echo-Reply",                                  /* 6 *//*         (Call Management) */         "Outgoing-Call-Request",                       /* 7 */         "Outgoing-Call-Reply",                         /* 8 */         "Incoming-Call-Request",                       /* 9 */         "Incoming-Call-Reply",                        /* 10 */         "Incoming-Call-Connected",                    /* 11 */         "Call-Clear-Request",                         /* 12 */         "Call-Disconnect-Notify",                     /* 13 *//*         (Error Reporting) */         "WAN-Error-Notify",                           /* 14 *//*         (PPP Session Control) */         "Set-Link-Info"                              /* 15 */};#define MAX_CTRLMSG_TYPE 15         /*** report a sent packet ****************************************************/static void ctrlp_rep( void * buffer, int size, int isbuff){    struct pptp_header *packet = buffer;    unsigned int type;    if(size < sizeof(struct pptp_header)) return;    type = ntoh16(packet->ctrl_type);    /* FIXME: do not report sending echo requests as long as they are     * sent in a signal handler. This may dead lock as the syslog call     * is not reentrant */    if( type ==  PPTP_ECHO_RQST ) return;    /* don't keep reporting sending of echo's */    if( (type == PPTP_ECHO_RQST || type == PPTP_ECHO_RPLY) && nlogecho <= 0 ) return;    log("%s control packet type is %d '%s'\n",isbuff ? "Buffered" : "Sent",             type, ctrl_msg_types[type <= MAX_CTRLMSG_TYPE ? type : 0]);}        /* Open new pptp_connection.  Returns NULL on failure. */PPTP_CONN * pptp_conn_open(int inet_sock, int isclient, pptp_conn_cb callback){    PPTP_CONN *conn;    /* Allocate structure */    if ((conn = malloc(sizeof(*conn))) == NULL) return NULL;    if ((conn->call = vector_create()) == NULL) { free(conn); return NULL; }    /* Initialize */    conn->inet_sock = inet_sock;    conn->conn_state = CONN_IDLE;    conn->ka_state  = KA_NONE;    conn->ka_id     = 1;    conn->call_serial_number = 0;    conn->callback  = callback;    /* Create I/O buffers */    conn->read_size = conn->write_size = 0;    conn->read_alloc = conn->write_alloc = INITIAL_BUFSIZE;    conn->read_buffer =        malloc(sizeof(*(conn->read_buffer)) * conn->read_alloc);    conn->write_buffer =        malloc(sizeof(*(conn->write_buffer)) * conn->write_alloc);    if (conn->read_buffer == NULL || conn->write_buffer == NULL) {        if (conn->read_buffer  != NULL) free(conn->read_buffer);        if (conn->write_buffer != NULL) free(conn->write_buffer);        vector_destroy(conn->call); free(conn); return NULL;    }    /* Make this socket non-blocking. */    fcntl(conn->inet_sock, F_SETFL, O_NONBLOCK);    /* Request connection from server, if this is a client */    if (isclient) {        struct pptp_start_ctrl_conn packet = {            PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RQST),            hton16(PPTP_VERSION), 0, 0,             hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP),            hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION),             PPTP_HOSTNAME, PPTP_VENDOR        };        /* fix this packet, if necessary */        int idx, rc;        idx = get_quirk_index();        if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {            if ((rc = pptp_fixups[idx].start_ctrl_conn(&packet)))                warn("calling the start_ctrl_conn hook failed (%d)", rc);        }        if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet)))            conn->conn_state = CONN_WAIT_CTL_REPLY;        else            return NULL; /* could not send initial start request. */    }    /* Set up interval/keep-alive timer */    /*   First, register handler for SIGALRM */    sigpipe_create();    sigpipe_assign(SIGALRM);    global.conn = conn;    /* Reset event timer */    pptp_reset_timer();    /* all done. */    return conn;}int pptp_conn_established(PPTP_CONN *conn) {  return (conn->conn_state == CONN_ESTABLISHED);}/* This currently *only* works for client call requests. * We need to do something else to allocate calls for incoming requests. */PPTP_CALL * pptp_call_open(PPTP_CONN * conn, pptp_call_cb callback,        char *phonenr){    PPTP_CALL * call;    int i;    int idx, rc;    /* Send off the call request */    struct pptp_out_call_rqst packet = {        PPTP_HEADER_CTRL(PPTP_OUT_CALL_RQST),        0,0, /*call_id, sernum */        hton32(PPTP_BPS_MIN), hton32(PPTP_BPS_MAX),        hton32(PPTP_BEARER_CAP), hton32(PPTP_FRAME_CAP),         hton16(PPTP_WINDOW), 0, 0, 0, {0}, {0}    };    assert(conn && conn->call);    assert(conn->conn_state == CONN_ESTABLISHED);    /* Assign call id */    if (!vector_scan(conn->call, 0, PPTP_MAX_CHANNELS - 1, &i))        /* no more calls available! */        return NULL;    /* allocate structure. */    if ((call = malloc(sizeof(*call))) == NULL) return NULL;    /* Initialize call structure */    call->call_type = PPTP_CALL_PNS;    call->state.pns = PNS_IDLE;    call->call_id   = (u_int16_t) i;    call->sernum    = conn->call_serial_number++;    call->callback  = callback;    call->closure   = NULL;    packet.call_id = htons(call->call_id);    packet.call_sernum = htons(call->sernum);    /* if we have a quirk, build a new packet to fit it */    idx = get_quirk_index();    if (idx != -1 && pptp_fixups[idx].out_call_rqst_hook) {        if ((rc = pptp_fixups[idx].out_call_rqst_hook(&packet)))            warn("calling the out_call_rqst hook failed (%d)", rc);    }

⌨️ 快捷键说明

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