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

📄 pptp_ctrl.c

📁 pptp第二层隧道模块
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* fill in the phone number if it was specified */    if (phonenr) {        strncpy(packet.phone_num, phonenr, sizeof(packet.phone_num));        packet.phone_len = strlen(phonenr);        if( packet.phone_len > sizeof(packet.phone_num))            packet.phone_len = sizeof(packet.phone_num);        packet.phone_len = hton16 (packet.phone_len);    }    if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) {        pptp_reset_timer();        call->state.pns = PNS_WAIT_REPLY;        /* and add it to the call vector */        vector_insert(conn->call, i, call);        return call;    } else { /* oops, unsuccessful. Deallocate. */        free(call);        return NULL;    }}/*** pptp_call_close **********************************************************/void pptp_call_close(PPTP_CONN * conn, PPTP_CALL * call){    struct pptp_call_clear_rqst rqst = {        PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_RQST), 0, 0    };    assert(conn && conn->call); assert(call);    assert(vector_contains(conn->call, call->call_id));    /* haven't thought about PAC yet */    assert(call->call_type == PPTP_CALL_PNS);    assert(call->state.pns != PNS_IDLE);    rqst.call_id = hton16(call->call_id);    /* don't check state against WAIT_DISCONNECT... allow multiple disconnect     * requests to be made.     */    pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));    pptp_reset_timer();    call->state.pns = PNS_WAIT_DISCONNECT;    /* call structure will be freed when we have confirmation of disconnect. */}/*** hard close ***************************************************************/void pptp_call_destroy(PPTP_CONN *conn, PPTP_CALL *call){    assert(conn && conn->call); assert(call);    assert(vector_contains(conn->call, call->call_id));    /* notify */    if (call->callback != NULL) call->callback(conn, call, CALL_CLOSE_DONE);    /* deallocate */    vector_remove(conn->call, call->call_id);    free(call);}/*** this is a soft close *****************************************************/void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason){    struct pptp_stop_ctrl_conn rqst = {        PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST),         hton8(close_reason), 0, 0    };    int i;    assert(conn && conn->call);    /* avoid repeated close attempts */    if (conn->conn_state == CONN_IDLE || conn->conn_state == CONN_WAIT_STOP_REPLY)         return;    /* close open calls, if any */    for (i = 0; i < vector_size(conn->call); i++)        pptp_call_close(conn, vector_get_Nth(conn->call, i));    /* now close connection */    log("Closing PPTP connection");    pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));    pptp_reset_timer(); /* wait 60 seconds for reply */    conn->conn_state = CONN_WAIT_STOP_REPLY;    return;}/*** this is a hard close *****************************************************/void pptp_conn_destroy(PPTP_CONN * conn){    int i;    assert(conn != NULL); assert(conn->call != NULL);    /* destroy all open calls */    for (i = 0; i < vector_size(conn->call); i++)        pptp_call_destroy(conn, vector_get_Nth(conn->call, i));    /* notify */    if (conn->callback != NULL) conn->callback(conn, CONN_CLOSE_DONE);    sigpipe_close();    close(conn->inet_sock);    /* deallocate */    vector_destroy(conn->call);    free(conn);}/*** Deal with messages, in a non-blocking manner  * Add file descriptors used by pptp to fd_set. */void pptp_fd_set(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set,                 int * max_fd){    assert(conn && conn->call);    /* Add fd to write_set if there are outstanding writes. */    if (conn->write_size > 0)        FD_SET(conn->inet_sock, write_set);    /* Always add fd to read_set. (always want something to read) */    FD_SET(conn->inet_sock, read_set);    if (*max_fd < conn->inet_sock) *max_fd = conn->inet_sock;    /* Add signal pipe file descriptor to set */    int sig_fd = sigpipe_fd();    FD_SET(sig_fd, read_set);    if (*max_fd < sig_fd) *max_fd = sig_fd;}/*** handle any pptp file descriptors set in fd_set, and clear them ***********/int pptp_dispatch(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set){    int r = 0;    assert(conn && conn->call);    /* Check for signals */    if (FD_ISSET(sigpipe_fd(), read_set)) {        if (sigpipe_read() == SIGALRM) pptp_handle_timer();	FD_CLR(sigpipe_fd(), read_set);    }    /* Check write_set could be set. */    if (FD_ISSET(conn->inet_sock, write_set)) {        FD_CLR(conn->inet_sock, write_set);        if (conn->write_size > 0)            r = pptp_write_some(conn);/* write as much as we can without blocking */    }    /* Check read_set */    if (r >= 0 && FD_ISSET(conn->inet_sock, read_set)) {        void *buffer; size_t size;        FD_CLR(conn->inet_sock, read_set);        r = pptp_read_some(conn); /* read as much as we can without blocking */	if (r < 0)	    return r;        /* make packets of the buffer, while we can. */        while (r >= 0 && pptp_make_packet(conn, &buffer, &size)) {            r = pptp_dispatch_packet(conn, buffer, size);            free(buffer);        }    }    /* That's all, folks.  Simple, eh? */    return r;}/*** Non-blocking write *******************************************************/int pptp_write_some(PPTP_CONN * conn) {    ssize_t retval;    assert(conn && conn->call);    retval = write(conn->inet_sock, conn->write_buffer, conn->write_size);    if (retval < 0) { /* error. */        if (errno == EAGAIN || errno == EINTR) {             return 0;        } else { /* a real error */            log("write error: %s", strerror(errno));	    return -1;        }    }    assert(retval <= conn->write_size);    conn->write_size -= retval;    memmove(conn->write_buffer, conn->write_buffer + retval, conn->write_size);    ctrlp_rep(conn->write_buffer, retval, 0);    return 0;}/*** Non-blocking read ********************************************************/int pptp_read_some(PPTP_CONN * conn){    ssize_t retval;    assert(conn && conn->call);    if (conn->read_size == conn->read_alloc) { /* need to alloc more memory */        char *new_buffer = realloc(conn->read_buffer,                 sizeof(*(conn->read_buffer)) * conn->read_alloc * 2);        if (new_buffer == NULL) {            log("Out of memory"); return -1;        }        conn->read_alloc *= 2;        conn->read_buffer = new_buffer;    }    retval = read(conn->inet_sock, conn->read_buffer + conn->read_size,            conn->read_alloc  - conn->read_size);    if (retval == 0) {        log("read returned zero, peer has closed");        return -1;    }    if (retval < 0) {        if (errno == EINTR || errno == EAGAIN)	    return 0;        else { /* a real error */            log("read error: %s", strerror(errno));            return -1;        }    }    conn->read_size += retval;    assert(conn->read_size <= conn->read_alloc);    return 0;}/*** Packet formation *********************************************************/int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size){    struct pptp_header *header;    size_t bad_bytes = 0;    assert(conn && conn->call); assert(buf != NULL); assert(size != NULL);    /* Give up unless there are at least sizeof(pptp_header) bytes */    while ((conn->read_size-bad_bytes) >= sizeof(struct pptp_header)) {        /* Throw out bytes until we have a valid header. */        header = (struct pptp_header *) (conn->read_buffer + bad_bytes);        if (ntoh32(header->magic) != PPTP_MAGIC) goto throwitout;        if (ntoh16(header->reserved0) != 0)            log("reserved0 field is not zero! (0x%x) Cisco feature? \n",                    ntoh16(header->reserved0));        if (ntoh16(header->length) < sizeof(struct pptp_header)) goto throwitout;        if (ntoh16(header->length) > PPTP_CTRL_SIZE_MAX) goto throwitout;        /* well.  I guess it's good. Let's see if we've got it all. */        if (ntoh16(header->length) > (conn->read_size-bad_bytes))            /* nope.  Let's wait until we've got it, then. */            goto flushbadbytes;        /* One last check: */        if ((ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL) &&                (ntoh16(header->length) !=                         PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))))            goto throwitout;        /* well, I guess we've got it. */        *size = ntoh16(header->length);        *buf = malloc(*size);        if (*buf == NULL) { log("Out of memory."); return 0; /* ack! */ }        memcpy(*buf, conn->read_buffer + bad_bytes, *size);        /* Delete this packet from the read_buffer. */        conn->read_size -= (bad_bytes + *size);        memmove(conn->read_buffer, conn->read_buffer + bad_bytes + *size,                 conn->read_size);        if (bad_bytes > 0)             log("%lu bad bytes thrown away.", (unsigned long) bad_bytes);        return 1;throwitout:        bad_bytes++;    }flushbadbytes:    /* no more packets.  Let's get rid of those bad bytes */    conn->read_size -= bad_bytes;    memmove(conn->read_buffer, conn->read_buffer + bad_bytes, conn->read_size);    if (bad_bytes > 0)         log("%lu bad bytes thrown away.", (unsigned long) bad_bytes);    return 0;}/*** pptp_send_ctrl_packet ****************************************************/int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size){    assert(conn && conn->call); assert(buffer);    if( conn->write_size > 0) pptp_write_some( conn);    if( conn->write_size == 0) {        ssize_t retval;        retval = write(conn->inet_sock, buffer, size);        if (retval < 0) { /* error. */            if (errno == EAGAIN || errno == EINTR) {                 /* ignore */;                retval = 0;            } else { /* a real error */                log("write error: %s", strerror(errno));                pptp_conn_destroy(conn); /* shut down fast. */                return 0;            }        }        ctrlp_rep( buffer, retval, 0);        size -= retval;        if( size <= 0) return 1;    }    /* Shove anything not written into the write buffer */    if (conn->write_size + size > conn->write_alloc) { /* need more memory */        char *new_buffer = realloc(conn->write_buffer,                 sizeof(*(conn->write_buffer)) * conn->write_alloc * 2);        if (new_buffer == NULL) {            log("Out of memory"); return 0;        }        conn->write_alloc *= 2;        conn->write_buffer = new_buffer;    }    memcpy(conn->write_buffer + conn->write_size, buffer, size);    conn->write_size += size;    ctrlp_rep( buffer,size,1);    return 1;}/*** Packet Dispatch **********************************************************/int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size){    int r = 0;    struct pptp_header *header = (struct pptp_header *)buffer;    assert(conn && conn->call); assert(buffer);    assert(ntoh32(header->magic) == PPTP_MAGIC);    assert(ntoh16(header->length) == size);    switch (ntoh16(header->pptp_type)) {        case PPTP_MESSAGE_CONTROL:            r = ctrlp_disp(conn, buffer, size);            break;        case PPTP_MESSAGE_MANAGE:            /* MANAGEMENT messages aren't even part of the spec right now. */            log("PPTP management message received, but not understood.");            break;        default:            log("Unknown PPTP control message type received: %u",                     (unsigned int) ntoh16(header->pptp_type));            break;    }    return r;}/*** log echo request/replies *************************************************/static void logecho( int type){    /* hack to stop flooding the log files (the most interesting part is right     * after the connection built-up) */    if( nlogecho > 0) {        log( "Echo Re%s received.", type == PPTP_ECHO_RQST ? "quest" :"ply");        if( --nlogecho == 0)            log("no more Echo Reply/Request packets will be reported.");    }}/*** pptp_dispatch_ctrl_packet ************************************************/int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size){    struct pptp_header *header = (struct pptp_header *)buffer;    u_int8_t close_reason = PPTP_STOP_NONE;    assert(conn && conn->call); assert(buffer);    assert(ntoh32(header->magic) == PPTP_MAGIC);    assert(ntoh16(header->length) == size);    assert(ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL);    if (size < PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))) {        log("Invalid packet received [type: %d; length: %d].",                (int) ntoh16(header->ctrl_type), (int) size);        return 0;    }    switch (ntoh16(header->ctrl_type)) {        /* ----------- STANDARD Start-Session MESSAGES ------------ */        case PPTP_START_CTRL_CONN_RQST:        {            struct pptp_start_ctrl_conn *packet =                 (struct pptp_start_ctrl_conn *) buffer;            struct pptp_start_ctrl_conn reply = {                PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY),                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 };            int idx, rc;            log("Received Start Control Connection Request");            /* fix this packet, if necessary */            idx = get_quirk_index();            if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {                if ((rc = pptp_fixups[idx].start_ctrl_conn(&reply)))                    warn("calling the start_ctrl_conn hook failed (%d)", rc);            }            if (conn->conn_state == CONN_IDLE) {                if (ntoh16(packet->version) < PPTP_VERSION) {                    /* Can't support this (earlier) PPTP_VERSION */                    reply.version = packet->version;                    /* protocol version not supported */

⌨️ 快捷键说明

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