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

📄 control.c

📁 第二层隧道模块l2tp源码,开发环境为linux
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Layer Two Tunnelling Protocol Daemon * Copyright (C) 1998 Adtran, Inc. * Copyright (C) 2002 Jeff McAdams * * Mark Spencer * * This software is distributed under the terms * of the GPL, which you should have received * along with this source. * * Control Packet Handling * */#include <errno.h>#include <string.h>#include <stdio.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <stdlib.h>#include "l2tp.h"#ifdef USE_KERNEL#include <sys/ioctl.h>#endif_u16 ppp_crc16_table[256] = {    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78};int global_serno = 1;struct buffer *new_outgoing (struct tunnel *t){    /*     * Make a new outgoing control packet     */    struct buffer *tmp = new_buf (MAX_RECV_SIZE);    if (!tmp)        return NULL;    tmp->peer = t->peer;    tmp->start += sizeof (struct control_hdr);    tmp->len = 0;    tmp->retries = 0;    tmp->tunnel = t;    return tmp;}inline void recycle_outgoing (struct buffer *buf, struct sockaddr_in peer){    /*      * This should only be used for ZLB's!     */    buf->start = buf->rstart + sizeof (struct control_hdr);    buf->peer = peer;    buf->len = 0;    buf->retries = -1;    buf->tunnel = NULL;}void add_fcs (struct buffer *buf){    _u16 fcs = PPP_INITFCS;    unsigned char *c = buf->start;    int x;    for (x = 0; x < buf->len; x++)    {        fcs = PPP_FCS (fcs, *c);        c++;    }    fcs = fcs ^ 0xFFFF;    *c = fcs & 0xFF;    c++;    *c = (fcs >> 8) & 0xFF;    buf->len += 2;}void add_control_hdr (struct tunnel *t, struct call *c, struct buffer *buf){    struct control_hdr *h;    buf->start -= sizeof (struct control_hdr);    buf->len += sizeof (struct control_hdr);    h = (struct control_hdr *) buf->start;    h->ver = htons (TBIT | LBIT | FBIT | VER_L2TP);    h->length = htons ((_u16) buf->len);    h->tid = htons (t->tid);    h->cid = htons (c->cid);    h->Ns = htons (t->control_seq_num);    h->Nr = htons (t->control_rec_seq_num);    t->control_seq_num++;}void hello (void *tun){    struct buffer *buf;    struct tunnel *t;    struct timeval tv;    tv.tv_sec = HELLO_DELAY;    tv.tv_usec = 0;    t = (struct tunnel *) tun;    buf = new_outgoing (t);    add_message_type_avp (buf, Hello);    add_control_hdr (t, t->self, buf);    if (packet_dump)        do_packet_dump (buf);#ifdef DEBUG_HELLO    log (LOG_DEBUG, "%s: sending Hello on %d\n", __FUNCTION__, t->ourtid);#endif    control_xmit (buf);    /*     * Schedule another Hello in a little bit.     */#ifdef DEBUG_HELLO    log (LOG_DEBUG, "%s: scheduling another Hello on %d\n", __FUNCTION__,         t->ourtid);#endif    t->hello = schedule (tv, hello, (void *) t);}void control_zlb (struct buffer *buf, struct tunnel *t, struct call *c){    recycle_outgoing (buf, t->peer);    add_control_hdr (t, c, buf);    t->control_seq_num--;#ifdef DEBUG_ZLB    log (LOG_DEBUG, "%s: sending control ZLB on tunnel %d\n", __FUNCTION__,         t->tid);#endif    udp_xmit (buf);}int control_finish (struct tunnel *t, struct call *c){    /*     * After all AVP's have been handled, do anything else     * which needs to be done, like prepare response     * packets to go back.  This is essentially the     * implementation of the state machine of section 7.2.1     *     * If we set c->needclose, the call (or tunnel) will     * be closed upon return.     */    struct buffer *buf;    struct call *p, *z;    struct tunnel *y;    struct timeval tv;    struct ppp_opts *po;#ifdef USE_KERNEL    struct l2tp_call_opts co;#endif    char ip1[STRLEN];    char ip2[STRLEN];    char dummy_buf[128] = "/var/l2tp/"; /* jz: needed to read /etc/ppp/var.options - just kick it if you dont like */    if (c->msgtype < 0)    {        log (LOG_DEBUG, "%s: Whoa...  non-ZLB with no message type!\n",             __FUNCTION__);        return -EINVAL;    }    if (debug_state)        log (LOG_DEBUG,             "%s: message type is %s(%d).  Tunnel is %d, call is %d.\n",             __FUNCTION__, msgtypes[c->msgtype], c->msgtype, t->tid, c->cid);    switch (c->msgtype)    {    case 0:        /*         * We need to initiate a connection.         */        if (t->self == c)        {            if (t->lns)            {                t->ourrws = t->lns->tun_rws;                t->hbit = t->lns->hbit;            }            else if (t->lac)            {                t->ourrws = t->lac->tun_rws;                t->hbit = t->lac->hbit;            }            /* This is an attempt to bring up the tunnel */            t->state = SCCRQ;            buf = new_outgoing (t);            add_message_type_avp (buf, SCCRQ);            if (t->hbit)            {                mk_challenge (t->chal_them.vector, VECTOR_SIZE);                add_randvect_avp (buf, t->chal_them.vector, VECTOR_SIZE);            }            add_protocol_avp (buf);            add_frame_caps_avp (buf, t->ourfc);            add_bearer_caps_avp (buf, t->ourbc);            /* FIXME:  Tie breaker */            add_firmware_avp (buf);            add_hostname_avp (buf);            add_vendor_avp (buf);            add_tunnelid_avp (buf, t->ourtid);            if (t->ourrws >= 0)                add_avp_rws (buf, t->ourrws);            if ((t->lac && t->lac->challenge)                || (t->lns && t->lns->challenge))            {                mk_challenge (t->chal_them.challenge, MD_SIG_SIZE);                add_challenge_avp (buf, t->chal_them.challenge, MD_SIG_SIZE);                t->chal_them.state = STATE_CHALLENGED;                /* We generate the challenge and make a note that we plan to                   challenge the peer, but we can't predict the response yet                   because we don't know their hostname AVP */            }            add_control_hdr (t, c, buf);            c->cnu = 0;            if (packet_dump)                do_packet_dump (buf);            if (debug_state)                log (LOG_DEBUG, "%s: control_finish: sending SCCRQ\n",                     __FUNCTION__);            control_xmit (buf);        }        else        {            if (switch_io)            {                c->state = ICRQ;                if (c->lns)                {                    c->lbit = c->lns->lbit ? LBIT : 0;/*					c->ourrws = c->lns->call_rws;					if (c->ourrws > -1) c->ourfbit = FBIT; else c->ourfbit = 0; */                }                else if (c->lac)                {                    c->lbit = c->lac->lbit ? LBIT : 0;/*					c->ourrws = c->lac->call_rws;					if (c->ourrws > -1) c->ourfbit = FBIT; else c->ourfbit = 0; */                }                buf = new_outgoing (t);                add_message_type_avp (buf, ICRQ);                if (t->hbit)                {                    mk_challenge (t->chal_them.vector, VECTOR_SIZE);                    add_randvect_avp (buf, t->chal_them.vector, VECTOR_SIZE);                }#ifdef TEST_HIDDEN                add_callid_avp (buf, c->ourcid, t);#else                add_callid_avp (buf, c->ourcid);#endif                add_serno_avp (buf, global_serno);                c->serno = global_serno;                global_serno++;                add_bearer_avp (buf, 0);                add_control_hdr (t, c, buf);                c->cnu = 0;                if (packet_dump)                    do_packet_dump (buf);                if (debug_state)                    log (LOG_DEBUG, "%s: sending ICRQ\n", __FUNCTION__);                control_xmit (buf);            }            else            {                   /* jz: sending a OCRQ */                c->state = OCRQ;                if (c->lns)                {                    c->lbit = c->lns->lbit ? LBIT : 0;/*                                      c->ourrws = c->lns->call_rws;                                        if (c->ourrws > -1) c->ourfbit = FBIT; else c->ourfbit = 0; */                }                else if (c->lac)                {/*                                      c->ourrws = c->lac->call_rws;                                        if (c->ourrws > -1) c->ourfbit = FBIT; else c->ourfbit = 0; */                }                if (t->fc & SYNC_FRAMING)                    c->frame = SYNC_FRAMING;                else                    c->frame = ASYNC_FRAMING;                buf = new_outgoing (t);                add_message_type_avp (buf, OCRQ);#ifdef TEST_HIDDEN                add_callid_avp (buf, c->ourcid, t);#else                add_callid_avp (buf, c->ourcid);#endif                add_serno_avp (buf, global_serno);                c->serno = global_serno;                global_serno++;                add_minbps_avp (buf, DEFAULT_MIN_BPS);                add_maxbps_avp (buf, DEFAULT_MAX_BPS);                add_bearer_avp (buf, 0);                add_frame_avp (buf, c->frame);                add_number_avp (buf, c->dial_no);                add_control_hdr (t, c, buf);                c->cnu = 0;                if (packet_dump)                    do_packet_dump (buf);                control_xmit (buf);            }        }        break;    case SCCRQ:        /*         * We've received a request, now let's         * formulate a response.         */        if (t->tid <= 0)        {            if (DEBUG)                log (LOG_DEBUG,                     "%s: Peer did not specify assigned tunnel ID.  Closing.\n",                     __FUNCTION__);            set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID");            c->needclose = -1;            return -EINVAL;        }        if (!(t->lns = get_lns (t)))        {            if (DEBUG)                log (LOG_DEBUG,                     "%s: Denied connection to unauthorized peer %s\n",                     __FUNCTION__, IPADDY (t->peer.sin_addr));            set_error (c, VENDOR_ERROR, "No Authorization");            c->needclose = -1;            return -EINVAL;        }        t->ourrws = t->lns->tun_rws;        t->hbit = t->lns->hbit;        if (t->fc < 0)        {            if (DEBUG)                log (LOG_DEBUG,                     "%s: Peer did not specify framing capability.  Closing.\n",                     __FUNCTION__);            set_error (c, VENDOR_ERROR, "Specify framing capability");            c->needclose = -1;            return -EINVAL;        }        /* FIXME: Do we need to be sure they specified a version number?         *   Theoretically, yes, but we don't have anything in the code         *   to actually *do* anything with it, so...why check at this point?         * We shouldn't be requiring a bearer capabilities avp to be present in          * SCCRQ and SCCRP as they aren't required         if (t->bc < 0 ) {         if (DEBUG) log(LOG_DEBUG,         "%s: Peer did not specify bearer capability.  Closing.\n",__FUNCTION__);         set_error(c, VENDOR_ERROR, "Specify bearer capability");         c->needclose = -1;         return -EINVAL;         }  */        if (!strlen (t->hostname))        {            if (DEBUG)                log (LOG_DEBUG,                     "%s: Peer did not specify hostname.  Closing.\n",                     __FUNCTION__);            set_error (c, VENDOR_ERROR, "Specify your hostname");            c->needclose = -1;            return -EINVAL;        }        y = tunnels.head;        while (y)        {            if ((y->tid == t->tid) &&                (y->peer.sin_addr.s_addr == t->peer.sin_addr.s_addr) &&                (y != t))            {                /* This can happen if we get a duplicate                   StartCCN or if they don't get our ack packet */                /*                 * But it is legitimate for two different remote systems                 * to use the same tid                 */                log (LOG_DEBUG,                     "%s: Peer requested tunnel %d twice, ignoring second one.\n",                     __FUNCTION__, t->tid);                c->needclose = 0;                c->closing = -1;                return 0;            }            y = y->next;        }        t->state = SCCRP;        buf = new_outgoing (t);        add_message_type_avp (buf, SCCRP);        if (t->hbit)        {            mk_challenge (t->chal_them.vector, VECTOR_SIZE);            add_randvect_avp (buf, t->chal_them.vector, VECTOR_SIZE);        }        add_protocol_avp (buf);        add_frame_caps_avp (buf, t->ourfc);        add_bearer_caps_avp (buf, t->ourbc);        add_firmware_avp (buf);        add_hostname_avp (buf);        add_vendor_avp (buf);        add_tunnelid_avp (buf, t->ourtid);        if (t->ourrws >= 0)            add_avp_rws (buf, t->ourrws);        if (t->chal_us.state)        {            t->chal_us.ss = SCCRP;            handle_challenge (t, &t->chal_us);            add_chalresp_avp (buf, t->chal_us.response, MD_SIG_SIZE);        }        if (t->lns->challenge)        {            t->chal_them.challenge = malloc(MD_SIG_SIZE);            if (!(t->chal_them.challenge))            {                log (LOG_WARN, "%s: malloc failed\n", __FUNCTION__);                set_error (c, VENDOR_ERROR, "malloc failed");                toss (buf);                return -EINVAL;            }            mk_challenge (t->chal_them.challenge, MD_SIG_SIZE);            t->chal_them.ss = SCCCN;            if (handle_challenge (t, &t->chal_them))            {                /* We already know what to expect back */                log (LOG_WARN, "%s: No secret for '%s'\n", __FUNCTION__,

⌨️ 快捷键说明

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