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

📄 pptp_gre.c

📁 this is a linux pptp software
💻 C
📖 第 1 页 / 共 2 页
字号:
/* pptp_gre.c  -- encapsulate PPP in PPTP-GRE. *                Handle the IP Protocol 47 portion of PPTP. *                C. Scott Ananian <cananian@alumni.princeton.edu> * * $Id: pptp_gre.c,v 1.39 2005/07/11 03:23:48 quozl Exp $ */#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/time.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include "ppp_fcs.h"#include "pptp_msg.h"#include "pptp_gre.h"#include "util.h"#include "pqueue.h"#define PACKET_MAX 8196/* test for a 32 bit counter overflow */#define WRAPPED( curseq, lastseq) \    ((((curseq) & 0xffffff00) == 0) && \     (((lastseq) & 0xffffff00 ) == 0xffffff00))static u_int32_t ack_sent, ack_recv;static u_int32_t seq_sent, seq_recv;static u_int16_t pptp_gre_call_id, pptp_gre_peer_call_id;gre_stats_t stats;typedef int (*callback_t)(int cl, void *pack, unsigned int len);/* decaps_hdlc gets all the packets possible with ONE blocking read *//* returns <0 if read() call fails */int decaps_hdlc(int fd, callback_t callback, int cl);int encaps_hdlc(int fd, void *pack, unsigned int len);int decaps_gre (int fd, callback_t callback, int cl);int encaps_gre (int fd, void *pack, unsigned int len);int dequeue_gre(callback_t callback, int cl);#if 1#include <stdio.h>void print_packet(int fd, void *pack, unsigned int len){    unsigned char *b = (unsigned char *)pack;    unsigned int i,j;    FILE *out = fdopen(fd, "w");    fprintf(out,"-- begin packet (%u) --\n", len);    for (i = 0; i < len; i += 16) {        for (j = 0; j < 8; j++)            if (i + 2 * j + 1 < len)                fprintf(out, "%02x%02x ",                         (unsigned int) b[i + 2 * j],                        (unsigned int) b[i + 2 * j + 1]);            else if (i + 2 * j < len)                fprintf(out, "%02x ", (unsigned int) b[i + 2 * j]);        fprintf(out, "\n");    }    fprintf(out, "-- end packet --\n");    fflush(out);}#endif/*** time_now_usecs ***********************************************************/uint64_t time_now_usecs(){    struct timeval tv;    gettimeofday(&tv, NULL);    return (tv.tv_sec * 1000000) + tv.tv_usec;}/*** Open IP protocol socket **************************************************/int pptp_gre_bind(struct in_addr inetaddr){    struct sockaddr_in src_addr, loc_addr;    extern struct in_addr localbind;    int s = socket(AF_INET, SOCK_RAW, PPTP_PROTO);    if (s < 0) { warn("socket: %s", strerror(errno)); return -1; }    if (localbind.s_addr != INADDR_NONE) {        bzero(&loc_addr, sizeof(loc_addr));        loc_addr.sin_family = AF_INET;        loc_addr.sin_addr   = localbind;        if (bind(s, (struct sockaddr *) &loc_addr, sizeof(loc_addr)) != 0) {            warn("bind: %s", strerror(errno)); close(s); return -1;        }    }    src_addr.sin_family = AF_INET;    src_addr.sin_addr   = inetaddr;    src_addr.sin_port   = 0;    if (connect(s, (struct sockaddr *) &src_addr, sizeof(src_addr)) < 0) {        warn("connect: %s", strerror(errno)); close(s); return -1;    }    return s;}/*** pptp_gre_copy ************************************************************/void pptp_gre_copy(u_int16_t call_id, u_int16_t peer_call_id, 		   int pty_fd, int gre_fd){    int max_fd;    pptp_gre_call_id = call_id;    pptp_gre_peer_call_id = peer_call_id;    /* Pseudo-terminal already open. */    ack_sent = ack_recv = seq_sent = seq_recv = 0;    /* weird select semantics */    max_fd = gre_fd;    if (pty_fd > max_fd) max_fd = pty_fd;    /* Dispatch loop */    for (;;) { /* until error happens on gre_fd or pty_fd */        struct timeval tv = {0, 0};        struct timeval *tvp;        fd_set rfds;        int retval;        pqueue_t *head;        int block_usecs = -1; /* wait forever */        /* watch terminal and socket for input */        FD_ZERO(&rfds);        FD_SET(gre_fd, &rfds);        FD_SET(pty_fd, &rfds);        /*         * if there are multiple pending ACKs, then do a minimal timeout;         * else if there is a single pending ACK then timeout after 0,5 seconds;         * else block until data is available.         */        if (ack_sent != seq_recv) {            if (ack_sent + 1 == seq_recv)  /* u_int wrap-around safe */                block_usecs = 500000;            else                /* don't use zero, this will force a resceduling */                /* when calling select(), giving pppd a chance to */                /* run. */                block_usecs = 1;        }        /* otherwise block_usecs == -1, which means wait forever */        /*         * If there is a packet in the queue, then don't wait longer than         * the time remaining until it expires.         */        head = pqueue_head();        if (head != NULL) {            int expiry_time = pqueue_expiry_time(head);            if (block_usecs == -1 || expiry_time < block_usecs)                block_usecs = expiry_time;        }        if (block_usecs == -1) {            tvp = NULL;        } else {            tvp = &tv;            tv.tv_usec = block_usecs;            tv.tv_sec  = tv.tv_usec / 1000000;            tv.tv_usec %= 1000000;        }        retval = select(max_fd + 1, &rfds, NULL, NULL, tvp);        if (FD_ISSET(pty_fd, &rfds)) {            if (decaps_hdlc(pty_fd, encaps_gre,  gre_fd) < 0)                break;        } else if (retval == 0 && ack_sent != seq_recv) {            /* if outstanding ack */            /* send ack with no payload */            encaps_gre(gre_fd, NULL, 0);                 }        if (FD_ISSET(gre_fd, &rfds)) {            if (decaps_gre (gre_fd, encaps_hdlc, pty_fd) < 0)                break;        }        if (dequeue_gre (encaps_hdlc, pty_fd) < 0)            break;    }    /* Close up when done. */    close(gre_fd);    close(pty_fd);}#define HDLC_FLAG         0x7E#define HDLC_ESCAPE       0x7D#define HDLC_TRANSPARENCY 0x20/* ONE blocking read per call; dispatches all packets possible *//* returns 0 on success, or <0 on read failure                 */int decaps_hdlc(int fd, int (*cb)(int cl, void *pack, unsigned int len), int cl){    unsigned char buffer[PACKET_MAX];    unsigned int start = 0;    int end;    int status;    static unsigned int len = 0, escape = 0;    static unsigned char copy[PACKET_MAX];    static int checkedsync = 0;    /* start is start of packet.  end is end of buffer data */    /*  this is the only blocking read we will allow */    if ((end = read (fd, buffer, sizeof(buffer))) <= 0) {        int saved_errno = errno;        warn("short read (%d): %s", end, strerror(saved_errno));	switch (saved_errno) {	  case EMSGSIZE: {	    int optval, optlen = sizeof(optval);	    warn("transmitted GRE packet triggered an ICMP destination unreachable, fragmentation needed, or exceeds the MTU of the network interface");#define IP_MTU 14	    if(getsockopt(fd, IPPROTO_IP, IP_MTU, &optval, &optlen) < 0)	      warn("getsockopt: %s", strerror(errno));	    warn("getsockopt: IP_MTU: %d\n", optval);	    return 0;	  }	case EIO:    	    warn("pppd may have shutdown, see pppd log");	    break;	}        return -1;    }    /* warn if the sync options of ppp and pptp don't match */    if( !checkedsync) {        checkedsync = 1;        if( buffer[0] == HDLC_FLAG){            if( syncppp )                warn( "pptp --sync option is active, "                        "yet the ppp mode is asynchronous!\n");        }	else if( !syncppp )            warn( "The ppp mode is synchronous, "                    "yet no pptp --sync option is specified!\n");    }    /* in synchronous mode there are no hdlc control characters nor checksum     * bytes. Find end of packet with the length information in the PPP packet     */    if ( syncppp ){        while ( start + 8 < end) {            len = ntoh16(*(short int *)(buffer + start + 6)) + 4;            /* note: the buffer may contain an incomplete packet at the end             * this packet will be read again at the next read() */            if ( start + len <= end)                if ((status = cb (cl, buffer + start, len)) < 0)                    return status; /* error-check */            start += len;        }        return 0;    }    /* asynchronous mode */    while (start < end) {        /* Copy to 'copy' and un-escape as we go. */        while (buffer[start] != HDLC_FLAG) {            if ((escape == 0) && buffer[start] == HDLC_ESCAPE) {                escape = HDLC_TRANSPARENCY;            } else {                if (len < PACKET_MAX)                    copy [len++] = buffer[start] ^ escape;                escape = 0;            }            start++;            if (start >= end)                return 0; /* No more data, but the frame is not complete yet. */        }        /* found flag.  skip past it */        start++;        /* check for over-short packets and silently discard, as per RFC1662 */        if ((len < 4) || (escape != 0)) {            len = 0; escape = 0;            continue;        }

⌨️ 快捷键说明

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