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

📄 pptp_gre.c

📁 this is a linux pptp software
💻 C
📖 第 1 页 / 共 2 页
字号:
        /* check, then remove the 16-bit FCS checksum field */        if (pppfcs16 (PPPINITFCS16, copy, len) != PPPGOODFCS16)            warn("Bad Frame Check Sequence during PPP to GRE decapsulation");        len -= sizeof(u_int16_t);        /* so now we have a packet of length 'len' in 'copy' */        if ((status = cb (cl, copy, len)) < 0)            return status; /* error-check */        /* Great!  Let's do more! */        len = 0; escape = 0;    }    return 0;    /* No more data to process. */}/*** Make stripped packet into HDLC packet ************************************/int encaps_hdlc(int fd, void *pack, unsigned int len){    unsigned char *source = (unsigned char *)pack;    unsigned char dest[2 * PACKET_MAX + 2]; /* largest expansion possible */    unsigned int pos = 0, i;    u_int16_t fcs;    /* in synchronous mode there is little to do */    if ( syncppp )        return write(fd, source, len);    /* asynchronous mode */    /* Compute the FCS */    fcs = pppfcs16(PPPINITFCS16, source, len) ^ 0xFFFF;    /* start character */    dest[pos++] = HDLC_FLAG;    /* escape the payload */    for (i = 0; i < len + 2; i++) {        /* wacked out assignment to add FCS to end of source buffer */        unsigned char c =            (i < len)?source[i]:(i == len)?(fcs & 0xFF):((fcs >> 8) & 0xFF);        if (pos >= sizeof(dest)) break; /* truncate on overflow */        if ( (c < 0x20) || (c == HDLC_FLAG) || (c == HDLC_ESCAPE) ) {            dest[pos++] = HDLC_ESCAPE;            if (pos < sizeof(dest))                dest[pos++] = c ^ 0x20;        } else            dest[pos++] = c;    }    /* tack on the end-flag */    if (pos < sizeof(dest))        dest[pos++] = HDLC_FLAG;    /* now write this packet */    return write(fd, dest, pos);}/*** decaps_gre ***************************************************************/int decaps_gre (int fd, callback_t callback, int cl){    unsigned char buffer[PACKET_MAX + 64 /*ip header*/];    struct pptp_gre_header *header;    int status, ip_len = 0;    static int first = 1;    unsigned int headersize;    unsigned int payload_len;    u_int32_t seq;    if ((status = read (fd, buffer, sizeof(buffer))) <= 0) {        warn("short read (%d): %s", status, strerror(errno));        stats.rx_errors++;        return -1;    }    /* strip off IP header, if present */    if ((buffer[0] & 0xF0) == 0x40)         ip_len = (buffer[0] & 0xF) * 4;    header = (struct pptp_gre_header *)(buffer + ip_len);    /* verify packet (else discard) */    if (    /* version should be 1 */            ((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) ||            /* PPTP-GRE protocol for PPTP */            (ntoh16(header->protocol) != PPTP_GRE_PROTO)||            /* flag C should be clear   */            PPTP_GRE_IS_C(ntoh8(header->flags)) ||            /* flag R should be clear   */            PPTP_GRE_IS_R(ntoh8(header->flags)) ||            /* flag K should be set     */            (!PPTP_GRE_IS_K(ntoh8(header->flags))) ||            /* routing and recursion ctrl = 0  */            ((ntoh8(header->flags)&0xF) != 0)) {        /* if invalid, discard this packet */        warn("Discarding GRE: %X %X %X %X %X %X",                 ntoh8(header->ver)&0x7F, ntoh16(header->protocol),                 PPTP_GRE_IS_C(ntoh8(header->flags)),                PPTP_GRE_IS_R(ntoh8(header->flags)),                 PPTP_GRE_IS_K(ntoh8(header->flags)),                ntoh8(header->flags) & 0xF);        stats.rx_invalid++;        return 0;    }    /* silently discard packets not for this call */    if (ntoh16(header->call_id) != pptp_gre_call_id) return 0;    /* test if acknowledgement present */    if (PPTP_GRE_IS_A(ntoh8(header->ver))) {         u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags)))?            header->ack:header->seq; /* ack in different place if S = 0 */        ack = ntoh32( ack);        if (ack > ack_recv) ack_recv = ack;        /* also handle sequence number wrap-around  */        if (WRAPPED(ack,ack_recv)) ack_recv = ack;        if (ack_recv == stats.pt.seq) {            int rtt = time_now_usecs() - stats.pt.time;            stats.rtt = (stats.rtt + rtt) / 2;        }    }    /* test if payload present */    if (!PPTP_GRE_IS_S(ntoh8(header->flags)))        return 0; /* ack, but no payload */    headersize  = sizeof(*header);    payload_len = ntoh16(header->payload_len);    seq         = ntoh32(header->seq);    /* no ack present? */    if (!PPTP_GRE_IS_A(ntoh8(header->ver))) headersize -= sizeof(header->ack);    /* check for incomplete packet (length smaller than expected) */    if (status - headersize < payload_len) {        warn("discarding truncated packet (expected %d, got %d bytes)",                payload_len, status - headersize);        stats.rx_truncated++;        return 0;     }    /* check for expected sequence number */    if ( first || (seq == seq_recv + 1)) { /* wrap-around safe */	if ( log_level >= 2 )            log("accepting packet %d", seq);        stats.rx_accepted++;        first = 0;        seq_recv = seq;        return callback(cl, buffer + ip_len + headersize, payload_len);    /* out of order, check if the number is too low and discard the packet.      * (handle sequence number wrap-around, and try to do it right) */    } else if ( seq < seq_recv + 1 || WRAPPED(seq_recv, seq) ) {	if ( log_level >= 1 )            log("discarding duplicate or old packet %d (expecting %d)",                seq, seq_recv + 1);        stats.rx_underwin++;    /* sequence number too high, is it reasonably close? */    } else if ( seq < seq_recv + MISSING_WINDOW ||                WRAPPED(seq, seq_recv + MISSING_WINDOW) ) {	stats.rx_buffered++;        if ( log_level >= 1 )            log("%s packet %d (expecting %d, lost or reordered)",                disable_buffer ? "accepting" : "buffering",                seq, seq_recv+1);        if ( disable_buffer ) {            seq_recv = seq;            stats.rx_lost += seq - seq_recv - 1;            return callback(cl, buffer + ip_len + headersize, payload_len);        } else {            pqueue_add(seq, buffer + ip_len + headersize, payload_len);	}    /* no, packet must be discarded */    } else {	if ( log_level >= 1 )            warn("discarding bogus packet %d (expecting %d)", 		 seq, seq_recv + 1);        stats.rx_overwin++;    }    return 0;}/*** dequeue_gre **************************************************************/int dequeue_gre (callback_t callback, int cl){    pqueue_t *head;    int status;    /* process packets in the queue that either are expected or have      * timed out. */    head = pqueue_head();    while ( head != NULL &&            ( (head->seq == seq_recv + 1) || /* wrap-around safe */               (pqueue_expiry_time(head) <= 0)             )          ) {        /* if it is timed out... */        if (head->seq != seq_recv + 1 ) {  /* wrap-around safe */                      stats.rx_lost += head->seq - seq_recv - 1;	    if (log_level >= 2)                log("timeout waiting for %d packets", head->seq - seq_recv - 1);        }	if (log_level >= 2)            log("accepting %d from queue", head->seq);        seq_recv = head->seq;        status = callback(cl, head->packet, head->packlen);        pqueue_del(head);        if (status < 0)            return status;        head = pqueue_head();    }    return 0;}/*** encaps_gre ***************************************************************/int encaps_gre (int fd, void *pack, unsigned int len){    union {        struct pptp_gre_header header;        unsigned char buffer[PACKET_MAX + sizeof(struct pptp_gre_header)];    } u;    static u_int32_t seq = 1; /* first sequence number sent must be 1 */    unsigned int header_len;    int rc;    /* package this up in a GRE shell. */    u.header.flags       = hton8 (PPTP_GRE_FLAG_K);    u.header.ver         = hton8 (PPTP_GRE_VER);    u.header.protocol    = hton16(PPTP_GRE_PROTO);    u.header.payload_len = hton16(len);    u.header.call_id     = hton16(pptp_gre_peer_call_id);    /* special case ACK with no payload */    if (pack == NULL) {        if (ack_sent != seq_recv) {            u.header.ver |= hton8(PPTP_GRE_FLAG_A);            u.header.payload_len = hton16(0);            /* ack is in odd place because S == 0 */            u.header.seq = hton32(seq_recv);            ack_sent = seq_recv;            rc = write(fd, &u.header, sizeof(u.header) - sizeof(u.header.seq));            if (rc < 0) {                stats.tx_failed++;            } else if (rc < sizeof(u.header) - sizeof(u.header.seq)) {                stats.tx_short++;            } else {                stats.tx_acks++;            }            return rc;        } else return 0; /* we don't need to send ACK */    } /* explicit brace to avoid ambiguous `else' warning */    /* send packet with payload */    u.header.flags |= hton8(PPTP_GRE_FLAG_S);    u.header.seq    = hton32(seq);    if (ack_sent != seq_recv) { /* send ack with this message */        u.header.ver |= hton8(PPTP_GRE_FLAG_A);        u.header.ack  = hton32(seq_recv);        ack_sent = seq_recv;        header_len = sizeof(u.header);    } else { /* don't send ack */        header_len = sizeof(u.header) - sizeof(u.header.ack);    }    if (header_len + len >= sizeof(u.buffer)) {        stats.tx_oversize++;        return 0; /* drop this, it's too big */    }    /* copy payload into buffer */    memcpy(u.buffer + header_len, pack, len);    /* record and increment sequence numbers */    seq_sent = seq; seq++;    /* write this baby out to the net */    /* print_packet(2, u.buffer, header_len + len); */    rc = write(fd, u.buffer, header_len + len);    if (rc < 0) {        stats.tx_failed++;    } else if (rc < header_len + len) {        stats.tx_short++;    } else {        stats.tx_sent++;        stats.pt.seq  = seq_sent;        stats.pt.time = time_now_usecs();    }    return rc;}

⌨️ 快捷键说明

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